diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index a28fdda..389f5e9e2 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -404,3 +404,6 @@
 
 # The Blink Rename
 1c4d759e44259650dfb2c426a7f997d2d0bc73dc
+
+# DEPS sorting.
+f5e7996a0cffea847bb2c14bd8c49a1d9ea3749e
diff --git a/AUTHORS b/AUTHORS
index 8d89773..cb4f1e2 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -904,3 +904,4 @@
 Canonical Limited <*@canonical.com>
 Seznam.cz, a.s. <*@firma.seznam.cz>
 LG Electronics, Inc. <*@lge.com>
+Vewd Software AS <*@vewd.com>
diff --git a/BUILD.gn b/BUILD.gn
index 4023a0c7..1200abe 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -12,6 +12,7 @@
 import("//build/config/features.gni")
 import("//build/config/sanitizers/sanitizers.gni")
 import("//build/config/ui.gni")
+import("//components/nacl/features.gni")
 import("//device/vr/features/features.gni")
 import("//extensions/features/features.gni")
 import("//media/media_options.gni")
@@ -719,7 +720,9 @@
 
   if (enable_vr) {
     deps += [ "//chrome/browser/vr:vr_common_unittests" ]
-
+    if (is_linux && use_ozone) {
+      deps += [ "//chrome/browser/vr/testapp:vr_testapp" ]
+    }
     if (is_android) {
       deps += [ "//tools/perf/contrib/vr_benchmarks:vr_perf_tests" ]
     }
diff --git a/DEPS b/DEPS
index a89ec90..20893cc2 100644
--- a/DEPS
+++ b/DEPS
@@ -45,11 +45,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': 'a78f1bc1d4055b82c8d31861f80cafdcc17f3d1f',
+  'skia_revision': '980379d47589f06719c4f3545c412789bf4d43f4',
   # 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': '7c5095aa211593f16b9ca02598c32239e2006923',
+  'v8_revision': 'b4df6351f719186aee39e19ab3420cd5159f87c4',
   # 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.
@@ -57,7 +57,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': '1f9d68437c9d3fd1bcb8fffff84fdd29d1857919',
+  'angle_revision': 'db3422764a9bdebb924552169b3df8d42c4b463f',
   # 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.
@@ -65,11 +65,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '6b164c337c647c0898a0e54cdb260f0ee91ae4a6',
+  'swiftshader_revision': 'bc6ce4f1f78fb714f59caecf9ed0c886b99f1c82',
   # 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': '8b1408e7053247def45659515cda19a64a7fccd5',
+  'pdfium_revision': '58418a24debb15019ec71eca193eff02c2a4846c',
   # 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.
@@ -77,7 +77,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
-  'boringssl_revision': '42e93b6cf5e0a5c958b6b59cf4842b3dc275561a',
+  'boringssl_revision': 'e9c7b1c8ae85e5625e9d24d9e20ccedeaaeb0d0a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling google-toolbox-for-mac
   # and whatever else without interference from each other.
@@ -101,7 +101,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': 'd08152f8a5da45712afa0b89eff8d1df0f05b2ad',
+  'catapult_revision': 'b6bab938e5ff202ddf6377196e0b23bf99247b5a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -130,77 +130,9 @@
 ]
 
 deps = {
-  'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@a10bd7dbe86ec3230cf7b42bb3a5b247ac778082',
-    'condition': 'checkout_src_internal',
-  },
-
-  'src/third_party/breakpad/breakpad':
-    Var('chromium_git') + '/breakpad/breakpad.git' + '@' + '1c6d1613966eab5d77531e85f3b60c40124b43f0',
-
   'src/buildtools':
     Var('chromium_git') + '/chromium/buildtools.git' + '@' +  Var('buildtools_revision'),
 
-  'src/third_party/freetype/src':
-    Var('chromium_git') + '/chromium/src/third_party/freetype2.git' + '@' + Var('freetype_revision'),
-
-  'src/third_party/glslang/src':
-    Var('chromium_git') + '/external/github.com/google/glslang.git' + '@' + '210c6bf4d8119dc5f8ac21da2d4c87184f7015e0',
-
-  'src/third_party/shaderc/src':
-    Var('chromium_git') + '/external/github.com/google/shaderc.git' + '@' + 'cd8793c34907073025af2622c28bcee64e9879a4',
-
-  'src/third_party/SPIRV-Tools/src':
-    Var('chromium_git') + '/external/github.com/KhronosGroup/SPIRV-Tools.git' + '@' + '9166854ac93ef81b026e943ccd230fed6c8b8d3c',
-
-  'src/third_party/angle':
-    Var('chromium_git') + '/angle/angle.git' + '@' +  Var('angle_revision'),
-
-  'src/third_party/colorama/src':
-    Var('chromium_git') + '/external/colorama.git' + '@' + '799604a1041e9b3bc5d2789ecbd7e8db2e18e6b8',
-
-  'src/third_party/crc32c/src':
-    Var('chromium_git') + '/external/github.com/google/crc32c.git' + '@' + '9bc7a0cada31f3224779b7ba7f56cc7382758e54',
-
-  'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'b2e961b1171d9f27278461a0a3286ab89161368c',
-
-  'src/third_party/googletest/src':
-    Var('chromium_git') + '/external/github.com/google/googletest.git' + '@' + '7f8fefabedf2965980585be8c2bff97458f28e0b',
-
-  'src/third_party/icu':
-    Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '08cb956852a5ccdba7f9c941728bb833529ba3c6',
-
-  'src/third_party/hunspell_dictionaries':
-    Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + 'dc6e7c25bf47cbfb466e0701fd2728b4a12e79d5',
-
-  'src/third_party/leveldatabase/src':
-    Var('chromium_git') + '/external/leveldb.git' + '@' + '09a3c8e7417547829b94bcdaa62cdf9e896f29a9',
-
-  'src/third_party/snappy/src':
-    Var('chromium_git') + '/external/github.com/google/snappy.git' + '@' + 'b02bfa754ebf27921d8da3bd2517eab445b84ff9',
-
-  'src/tools/gyp':
-    Var('chromium_git') + '/external/gyp.git' + '@' + 'd61a9397e668fa9843c4aa7da9e79460fe590bfb',
-
-  'src/tools/swarming_client':
-    Var('chromium_git') + '/infra/luci/client-py.git' + '@' +  Var('swarming_revision'),
-
-  'src/v8':
-    Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
-
-  'src/native_client':
-    Var('chromium_git') + '/native_client/src/native_client.git' + '@' + Var('nacl_revision'),
-
-  'src/third_party/sfntly/src':
-    Var('chromium_git') + '/external/github.com/googlei18n/sfntly.git' + '@' + Var('sfntly_revision'),
-
-  'src/third_party/skia':
-    Var('skia_git') + '/skia.git' + '@' +  Var('skia_revision'),
-
-  'src/tools/page_cycler/acid3':
-    Var('chromium_git') + '/chromium/deps/acid3.git' + '@' + '6be0a66a1ebd7ebc5abc1b2f405a945f6d871521',
-
   'src/chrome/test/data/perf/canvas_bench':
     Var('chromium_git') + '/chromium/canvas_bench.git' + '@' + 'a7b40ea5ae0239517d78845a5fc9b12976bfc732',
 
@@ -210,118 +142,269 @@
   'src/chrome/test/data/vr/webvr_info':
     Var('chromium_git') + '/external/github.com/toji/webvr.info.git' + '@' + '932fd58075e564727b5525681d6b9293b41a90f7',
 
-  'src/third_party/bidichecker':
-    Var('chromium_git') + '/external/bidichecker/lib.git' + '@' + '97f2aa645b74c28c57eca56992235c79850fa9e0',
-
-  'src/third_party/webgl/src':
-    Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '34842fa3c36988840c89f5bc6a68503175acf7d9',
-
-  'src/third_party/webdriver/pylib':
-    Var('chromium_git') + '/external/selenium/py.git' + '@' + '5fd78261a75fe08d27ca4835fb6c5ce4b42275bd',
-
-  'src/third_party/libvpx/source/libvpx':
-    Var('chromium_git') + '/webm/libvpx.git' + '@' +  '10bab1ec2966e0c22e80965b00b2a953a338880b',
-
-  'src/third_party/ffmpeg':
-    Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '1e201feaa3260336aa63545c9471b76e5aef2e0a',
-
-  'src/third_party/usrsctp/usrsctplib':
-    Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + 'f4819e1b177f7bfdd761c147f5a649b9f1a78c06',
-
-  'src/third_party/libsrtp':
-    Var('chromium_git') + '/chromium/deps/libsrtp.git' + '@' + '1d45b8e599dc2db6ea3ae22dbc94a8c504652423',
-
-  'src/third_party/yasm/source/patched-yasm':
-    Var('chromium_git') + '/chromium/deps/yasm/patched-yasm.git' + '@' + 'b98114e18d8b9b84586b10d24353ab8616d4c5fc',
-
-  'src/third_party/libjpeg_turbo':
-    Var('chromium_git') + '/chromium/deps/libjpeg_turbo.git' + '@' + 'a1750dbc79a8792dde3d3f7d7d8ac28ba01ac9dd',
-
-  'src/third_party/flac':
-    Var('chromium_git') + '/chromium/deps/flac.git' + '@' + '7d0f5b3a173ffe98db08057d1f52b7787569e0a6',
-
-  'src/third_party/flatbuffers/src':
-    Var('chromium_git') + '/external/github.com/google/flatbuffers.git' + '@' + '01c50d57a67a52ee3cddd81b54d4647e9123a290',
-
-  'src/third_party/pyftpdlib/src':
-    Var('chromium_git') + '/external/pyftpdlib.git' + '@' + '2be6d65e31c7ee6320d059f581f05ae8d89d7e45',
-
-  'src/third_party/scons-2.0.1':
-    Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067',
-
-  'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '433b11ede72a8047ad5b34d8ab522e2da07f99f8', # commit position 19922
-
-  'src/third_party/openmax_dl':
-    Var('webrtc_git') + '/deps/third_party/openmax.git' + '@' +  Var('openmax_dl_revision'),
-
-  'src/third_party/jsoncpp/source':
-    Var('chromium_git') + '/external/github.com/open-source-parsers/jsoncpp.git' + '@' + 'f572e8e42e22cfcf5ab0aea26574f408943edfa4', # from svn 248
-
-  'src/third_party/libyuv':
-    Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '5b1af9a33545895ea12c52bf007f17914de19173',  # from r1670
-
-  'src/third_party/smhasher/src':
-    Var('chromium_git') + '/external/smhasher.git' + '@' + 'e87738e57558e0ec472b2fc3a643b838e5b6e88f',
-
-  'src/third_party/libaddressinput/src':
-    Var('chromium_git') + '/external/libaddressinput.git' + '@' + '4d18a0d4be9add0dc479e7b939ed8d39f6ec0d73',
-
-  'src/third_party/libphonenumber/dist':
-    Var('chromium_git') + '/external/libphonenumber.git' + '@' + 'a4da30df63a097d67e3c429ead6790ad91d36cf4',
-
-  'src/third_party/pywebsocket/src':
-    Var('chromium_git') + '/external/github.com/google/pywebsocket.git' + '@' + '2d7b73c3acbd0f41dcab487ae5c97c6feae06ce2',
-
   'src/media/cdm/api':
     Var('chromium_git') + '/chromium/cdm.git' + '@' + '1f49c55d3151a4e1eec088befee5f578fea81f4b',
 
-  'src/third_party/mesa/src':
-    Var('chromium_git') + '/chromium/deps/mesa.git' + '@' + 'ef811c6bd4de74e13e7035ca882cc77f85793fef',
+  'src/native_client':
+    Var('chromium_git') + '/native_client/src/native_client.git' + '@' + Var('nacl_revision'),
+
+  'src/third_party/SPIRV-Tools/src':
+    Var('chromium_git') + '/external/github.com/KhronosGroup/SPIRV-Tools.git' + '@' + '9166854ac93ef81b026e943ccd230fed6c8b8d3c',
+
+  'src/third_party/android_protobuf/src': {
+      'url': Var('chromium_git') + '/external/android_protobuf.git' + '@' + '7fca48d8ce97f7ba3ab8eea5c472f1ad3711762f',
+      'condition': 'checkout_android',
+  },
+
+  'src/third_party/android_tools': {
+      'url': Var('chromium_git') + '/android_tools.git' + '@' + 'ca9dc7245b888c75307f0619e4a39fb46a82de66',
+      'condition': 'checkout_android',
+  },
+
+  'src/third_party/angle':
+    Var('chromium_git') + '/angle/angle.git' + '@' +  Var('angle_revision'),
+
+  'src/third_party/apache-portable-runtime/src': {
+      'url': Var('chromium_git') + '/external/apache-portable-runtime.git' + '@' + 'c76a8c4277e09a82eaa229e35246edea1ee0a6a1',
+      'condition': 'checkout_android',
+  },
+
+  'src/third_party/bidichecker':
+    Var('chromium_git') + '/external/bidichecker/lib.git' + '@' + '97f2aa645b74c28c57eca56992235c79850fa9e0',
+
+  'src/third_party/boringssl/src':
+    Var('boringssl_git') + '/boringssl.git' + '@' +  Var('boringssl_revision'),
+
+  'src/third_party/breakpad/breakpad':
+    Var('chromium_git') + '/breakpad/breakpad.git' + '@' + '1c6d1613966eab5d77531e85f3b60c40124b43f0',
+
+  'src/third_party/catapult':
+    Var('chromium_git') + '/catapult.git' + '@' + Var('catapult_revision'),
 
   'src/third_party/ced/src':
     Var('chromium_git') + '/external/github.com/google/compact_enc_det.git' + '@' + '94c367a1fe3a13207f4b22604fcfd1d9f9ddf6d9',
 
-  'src/third_party/swiftshader':
-    Var('swiftshader_git') + '/SwiftShader.git' + '@' +  Var('swiftshader_revision'),
-
   'src/third_party/cld_2/src':
     Var('chromium_git') + '/external/github.com/CLD2Owners/cld2.git' + '@' + '84b58a5d7690ebf05a91406f371ce00c3daf31c0',
 
   'src/third_party/cld_3/src':
     Var('chromium_git') + '/external/github.com/google/cld_3.git' + '@' + 'ae02d6b8a2af41e87c956c7c7d3f651a8b7b9e79',
 
-  'src/third_party/libwebm/source':
-    Var('chromium_git') + '/webm/libwebm.git' + '@' + '4956b2dec65352af32dc71bab553acb631c64177',
+  'src/third_party/colorama/src':
+    Var('chromium_git') + '/external/colorama.git' + '@' + '799604a1041e9b3bc5d2789ecbd7e8db2e18e6b8',
 
-  'src/third_party/pdfium':
-    Var('pdfium_git') + '/pdfium.git' + '@' +  Var('pdfium_revision'),
+  'src/third_party/crc32c/src':
+    Var('chromium_git') + '/external/github.com/google/crc32c.git' + '@' + '9bc7a0cada31f3224779b7ba7f56cc7382758e54',
 
-  'src/third_party/boringssl/src':
-    Var('boringssl_git') + '/boringssl.git' + '@' +  Var('boringssl_revision'),
+  'src/third_party/custom_tabs_client/src': {
+      'url': Var('chromium_git') + '/external/github.com/GoogleChrome/custom-tabs-client.git' + '@' + 'cff061038b852d647f7044d828a9df78aa135f38',
+      'condition': 'checkout_android',
+  },
+
+  'src/third_party/depot_tools':
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'b2e961b1171d9f27278461a0a3286ab89161368c',
 
   'src/third_party/dom_distiller_js/dist':
-    Var('chromium_git') + '/external/github.com/chromium/dom-distiller-dist.git' + '@' + '232c293a4d3ebcbc4320f642af017ee054b3be93',
+    Var('chromium_git') + '/chromium/dom-distiller/dist.git' + '@' + '232c293a4d3ebcbc4320f642af017ee054b3be93',
 
-  'src/third_party/catapult':
-    Var('chromium_git') + '/external/github.com/catapult-project/catapult.git' + '@' +
-    Var('catapult_revision'),
+  'src/third_party/elfutils/src': {
+      'url': Var('chromium_git') + '/external/elfutils.git' + '@' + '249673729a7e5dbd5de4f3760bdcaa3d23d154d7',
+      'condition': 'checkout_android',
+  },
 
-  'src/third_party/openh264/src':
-    Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + '0fd88df93c5dcaf858c57eb7892bd27763f0f0ac',
+  'src/third_party/errorprone/lib': {
+      'url': Var('chromium_git') + '/chromium/third_party/errorprone.git' + '@' + '0eea83b66343133b9c76b7d3288c30321818ebcf',
+      'condition': 'checkout_android',
+  },
 
-  'src/third_party/re2/src':
-    Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + 'ae9cb49a2e2ba95de4f0c6ec5a8afd039996d2c7',
+  'src/third_party/ffmpeg':
+    Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '1e201feaa3260336aa63545c9471b76e5aef2e0a',
 
-  # Used for building libFuzzers (only supports Linux).
+  'src/third_party/findbugs': {
+      'url': Var('chromium_git') + '/chromium/deps/findbugs.git' + '@' + '57f05238d3ac77ea0a194813d3065dd780c6e566',
+      'condition': 'checkout_android',
+  },
+
+  'src/third_party/flac':
+    Var('chromium_git') + '/chromium/deps/flac.git' + '@' + '7d0f5b3a173ffe98db08057d1f52b7787569e0a6',
+
+  'src/third_party/flatbuffers/src':
+    Var('chromium_git') + '/external/github.com/google/flatbuffers.git' + '@' + '01c50d57a67a52ee3cddd81b54d4647e9123a290',
+
+  'src/third_party/freetype/src':
+    Var('chromium_git') + '/chromium/src/third_party/freetype2.git' + '@' + Var('freetype_revision'),
+
+  'src/third_party/glslang/src':
+    Var('chromium_git') + '/external/github.com/google/glslang.git' + '@' + '210c6bf4d8119dc5f8ac21da2d4c87184f7015e0',
+
+  'src/third_party/googletest/src':
+    Var('chromium_git') + '/external/github.com/google/googletest.git' + '@' + '7f8fefabedf2965980585be8c2bff97458f28e0b',
+
+  'src/third_party/gvr-android-sdk/src': {
+      'url': Var('chromium_git') + '/external/github.com/googlevr/gvr-android-sdk.git' + '@' + 'ee5cb1c6138d0be57e82ddafc1b54d7d3e3e5560',
+      'condition': 'checkout_android',
+  },
+
+  'src/third_party/hunspell_dictionaries':
+    Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + 'dc6e7c25bf47cbfb466e0701fd2728b4a12e79d5',
+
+  'src/third_party/icu':
+    Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '08cb956852a5ccdba7f9c941728bb833529ba3c6',
+
+  'src/third_party/jsoncpp/source':
+    Var('chromium_git') + '/external/github.com/open-source-parsers/jsoncpp.git' + '@' + 'f572e8e42e22cfcf5ab0aea26574f408943edfa4', # from svn 248
+
+  'src/third_party/jsr-305/src': {
+      'url': Var('chromium_git') + '/external/jsr-305.git' + '@' + '642c508235471f7220af6d5df2d3210e3bfc0919',
+      'condition': 'checkout_android',
+  },
+
+  'src/third_party/junit/src': {
+      'url': Var('chromium_git') + '/external/junit.git' + '@' + '64155f8a9babcfcf4263cf4d08253a1556e75481',
+      'condition': 'checkout_android',
+  },
+
+  'src/third_party/leakcanary/src': {
+      'url': Var('chromium_git') + '/external/github.com/square/leakcanary.git' + '@' + '608ded739e036a3aa69db47ac43777dcee506f8e',
+      'condition': 'checkout_android',
+  },
+
+  'src/third_party/leveldatabase/src':
+    Var('chromium_git') + '/external/leveldb.git' + '@' + '09a3c8e7417547829b94bcdaa62cdf9e896f29a9',
+
   'src/third_party/libFuzzer/src':
     Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git' + '@' +  Var('libfuzzer_revision'),
 
+  'src/third_party/libaddressinput/src':
+    Var('chromium_git') + '/external/libaddressinput.git' + '@' + '4d18a0d4be9add0dc479e7b939ed8d39f6ec0d73',
+
+  'src/third_party/libjpeg_turbo':
+    Var('chromium_git') + '/chromium/deps/libjpeg_turbo.git' + '@' + 'a1750dbc79a8792dde3d3f7d7d8ac28ba01ac9dd',
+
+  'src/third_party/libphonenumber/dist':
+    Var('chromium_git') + '/external/libphonenumber.git' + '@' + 'a4da30df63a097d67e3c429ead6790ad91d36cf4',
+
   'src/third_party/libprotobuf-mutator/src':
     Var('chromium_git') + '/external/github.com/google/libprotobuf-mutator.git' + '@' +  Var('libprotobuf-mutator'),
 
+  'src/third_party/libsrtp':
+    Var('chromium_git') + '/chromium/deps/libsrtp.git' + '@' + '1d45b8e599dc2db6ea3ae22dbc94a8c504652423',
+
+  'src/third_party/libvpx/source/libvpx':
+    Var('chromium_git') + '/webm/libvpx.git' + '@' +  '10bab1ec2966e0c22e80965b00b2a953a338880b',
+
+  'src/third_party/libwebm/source':
+    Var('chromium_git') + '/webm/libwebm.git' + '@' + '4956b2dec65352af32dc71bab553acb631c64177',
+
+  'src/third_party/libyuv':
+    Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '5b1af9a33545895ea12c52bf007f17914de19173',  # from r1670
+
+  'src/third_party/mesa/src':
+    Var('chromium_git') + '/chromium/deps/mesa.git' + '@' + 'ef811c6bd4de74e13e7035ca882cc77f85793fef',
+
+  'src/third_party/mockito/src': {
+      'url': Var('chromium_git') + '/external/mockito/mockito.git' + '@' + 'de83ad4598ad4cf5ea53c69a8a8053780b04b850',
+      'condition': 'checkout_android',
+  },
+
+  'src/third_party/netty-tcnative/src': {
+      'url': Var('chromium_git') + '/external/netty-tcnative.git' + '@' + '5b46a8ef4a39c39c576fcdaaf718b585d75df463',
+      'condition': 'checkout_android',
+  },
+
+  'src/third_party/netty4/src': {
+      'url': Var('chromium_git') + '/external/netty4.git' + '@' + 'cc4420b13bb4eeea5b1cf4f93b2755644cd3b120',
+      'condition': 'checkout_android',
+  },
+
+  'src/third_party/openh264/src':
+    Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + 'a180c9d4d6f1a4830ca9eed9d159d54996bd63cb',
+
+  'src/third_party/openmax_dl':
+    Var('webrtc_git') + '/deps/third_party/openmax.git' + '@' +  Var('openmax_dl_revision'),
+
+  'src/third_party/pdfium':
+    Var('pdfium_git') + '/pdfium.git' + '@' +  Var('pdfium_revision'),
+
+  'src/third_party/pyftpdlib/src':
+    Var('chromium_git') + '/external/pyftpdlib.git' + '@' + '2be6d65e31c7ee6320d059f581f05ae8d89d7e45',
+
+  'src/third_party/pywebsocket/src':
+    Var('chromium_git') + '/external/github.com/google/pywebsocket.git' + '@' + '2d7b73c3acbd0f41dcab487ae5c97c6feae06ce2',
+
+  'src/third_party/re2/src':
+    Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + 'ae9cb49a2e2ba95de4f0c6ec5a8afd039996d2c7',
+
+  'src/third_party/requests/src': {
+      'url': Var('chromium_git') + '/external/github.com/kennethreitz/requests.git' + '@' + 'f172b30356d821d180fa4ecfa3e71c7274a32de4',
+      'condition': 'checkout_android',
+  },
+
+  'src/third_party/robolectric/robolectric': {
+      'url': Var('chromium_git') + '/external/robolectric.git' + '@' + 'b02c65cc6d7465f58f0de48a39914aa905692afa',
+      'condition': 'checkout_android',
+  },
+
+  'src/third_party/scons-2.0.1':
+    Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067',
+
+  'src/third_party/sfntly/src':
+    Var('chromium_git') + '/external/github.com/googlei18n/sfntly.git' + '@' + Var('sfntly_revision'),
+
+  'src/third_party/shaderc/src':
+    Var('chromium_git') + '/external/github.com/google/shaderc.git' + '@' + 'cd8793c34907073025af2622c28bcee64e9879a4',
+
+  'src/third_party/skia':
+    Var('skia_git') + '/skia.git' + '@' +  Var('skia_revision'),
+
+  'src/third_party/smhasher/src':
+    Var('chromium_git') + '/external/smhasher.git' + '@' + 'e87738e57558e0ec472b2fc3a643b838e5b6e88f',
+
+  'src/third_party/snappy/src':
+    Var('chromium_git') + '/external/github.com/google/snappy.git' + '@' + 'b02bfa754ebf27921d8da3bd2517eab445b84ff9',
+
+  'src/third_party/swiftshader':
+    Var('swiftshader_git') + '/SwiftShader.git' + '@' +  Var('swiftshader_revision'),
+
+  'src/third_party/ub-uiautomator/lib': {
+      'url': Var('chromium_git') + '/chromium/third_party/ub-uiautomator.git' + '@' + '00270549ce3161ae72ceb24712618ea28b4f9434',
+      'condition': 'checkout_android',
+  },
+
+  'src/third_party/usrsctp/usrsctplib':
+    Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + 'f4819e1b177f7bfdd761c147f5a649b9f1a78c06',
+
   'src/third_party/visualmetrics/src':
     Var('chromium_git') + '/external/github.com/WPO-Foundation/visualmetrics.git' + '@' +  '1edde9d2fe203229c895b648fdec355917200ad6',
+
+  'src/third_party/webdriver/pylib':
+    Var('chromium_git') + '/external/selenium/py.git' + '@' + '5fd78261a75fe08d27ca4835fb6c5ce4b42275bd',
+
+  'src/third_party/webgl/src':
+    Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '34842fa3c36988840c89f5bc6a68503175acf7d9',
+
+  'src/third_party/webrtc':
+    Var('webrtc_git') + '/src.git' + '@' + 'bbceb76f540159e2dba0701ac03c514f01624130', # commit position 20032
+
+  'src/third_party/yasm/source/patched-yasm':
+    Var('chromium_git') + '/chromium/deps/yasm/patched-yasm.git' + '@' + 'b98114e18d8b9b84586b10d24353ab8616d4c5fc',
+
+  'src/tools/gyp':
+    Var('chromium_git') + '/external/gyp.git' + '@' + 'd61a9397e668fa9843c4aa7da9e79460fe590bfb',
+
+  'src/tools/page_cycler/acid3':
+    Var('chromium_git') + '/chromium/deps/acid3.git' + '@' + '6be0a66a1ebd7ebc5abc1b2f405a945f6d871521',
+
+  'src/tools/swarming_client':
+    Var('chromium_git') + '/infra/luci/client-py.git' + '@' +  Var('swarming_revision'),
+
+  'src/v8':
+    Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
+
+  'src-internal': {
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@a10bd7dbe86ec3230cf7b42bb3a5b247ac778082',
+    'condition': 'checkout_src_internal',
+  },
 }
 
 
@@ -467,59 +550,9 @@
       Var('chromium_git') + '/aosp/platform/system/core/libsync.git' + '@' + 'aa6cda6f638bd57d3a024f0d201f723a5c3bb875',
   },
   'android': {
-    'src/third_party/android_protobuf/src':
-      Var('chromium_git') + '/external/android_protobuf.git' + '@' + '7fca48d8ce97f7ba3ab8eea5c472f1ad3711762f',
-
-    'src/third_party/android_tools':
-      Var('chromium_git') + '/android_tools.git' + '@' + 'ca9dc7245b888c75307f0619e4a39fb46a82de66',
-
-    'src/third_party/apache-portable-runtime/src':
-      Var('chromium_git') + '/external/apache-portable-runtime.git' + '@' + 'c76a8c4277e09a82eaa229e35246edea1ee0a6a1',
-
-    'src/third_party/errorprone/lib':
-      Var('chromium_git') + '/chromium/third_party/errorprone.git' + '@' + '0eea83b66343133b9c76b7d3288c30321818ebcf',
-
-    'src/third_party/findbugs':
-      Var('chromium_git') + '/chromium/deps/findbugs.git' + '@' + '57f05238d3ac77ea0a194813d3065dd780c6e566',
-
-    'src/third_party/elfutils/src':
-      Var('chromium_git') + '/external/elfutils.git' + '@' + '249673729a7e5dbd5de4f3760bdcaa3d23d154d7',
-
-    'src/third_party/jsr-305/src':
-      Var('chromium_git') + '/external/jsr-305.git' + '@' + '642c508235471f7220af6d5df2d3210e3bfc0919',
-
-    'src/third_party/junit/src':
-      Var('chromium_git') + '/external/junit.git' + '@' + '64155f8a9babcfcf4263cf4d08253a1556e75481',
-
-    'src/third_party/mockito/src':
-      Var('chromium_git') + '/external/mockito/mockito.git' + '@' + 'de83ad4598ad4cf5ea53c69a8a8053780b04b850',
-
-    'src/third_party/netty-tcnative/src':
-      Var('chromium_git') + '/external/netty-tcnative.git' + '@' + '5b46a8ef4a39c39c576fcdaaf718b585d75df463',
-
-    'src/third_party/netty4/src':
-      Var('chromium_git') + '/external/netty4.git' + '@' + 'cc4420b13bb4eeea5b1cf4f93b2755644cd3b120',
-
-    'src/third_party/robolectric/robolectric':
-      Var('chromium_git') + '/external/robolectric.git' + '@' + 'b02c65cc6d7465f58f0de48a39914aa905692afa',
-
-    'src/third_party/ub-uiautomator/lib':
-      Var('chromium_git') + '/chromium/third_party/ub-uiautomator.git' + '@' + '00270549ce3161ae72ceb24712618ea28b4f9434',
-
-    'src/third_party/leakcanary/src':
-      Var('chromium_git') + '/external/github.com/square/leakcanary.git' + '@' + '608ded739e036a3aa69db47ac43777dcee506f8e',
-
+    # TODO(phajdan.jr): move all lss entries together to deps behind proper condition.
     'src/third_party/lss':
       Var('chromium_git') + '/linux-syscall-support.git' + '@' + Var('lss_revision'),
-
-    'src/third_party/requests/src':
-      Var('chromium_git') + '/external/github.com/kennethreitz/requests.git' + '@' + 'f172b30356d821d180fa4ecfa3e71c7274a32de4',
-
-    'src/third_party/custom_tabs_client/src':
-      Var('chromium_git') + '/external/github.com/GoogleChrome/custom-tabs-client.git' + '@' + 'cff061038b852d647f7044d828a9df78aa135f38',
-
-    'src/third_party/gvr-android-sdk/src':
-      Var('chromium_git') + '/external/github.com/googlevr/gvr-android-sdk.git' + '@' + 'ee5cb1c6138d0be57e82ddafc1b54d7d3e3e5560',
   },
 }
 
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index fa5fef8a..70ad7be 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -316,7 +316,7 @@
       (),
     ),
     (
-      'BrowserThread::FILE',
+      r'/(WebThread|BrowserThread)::(FILE|FILE_USER_BLOCKING|DB|CACHE)',
       (
         'The non-UI/IO BrowserThreads are deprecated, please migrate this',
         'code to TaskScheduler. See https://goo.gl/mDSxKl for details.',
diff --git a/PRESUBMIT_test_mocks.py b/PRESUBMIT_test_mocks.py
index c6aa84a..3927f26 100644
--- a/PRESUBMIT_test_mocks.py
+++ b/PRESUBMIT_test_mocks.py
@@ -9,6 +9,47 @@
 import subprocess
 import sys
 
+# TODO(dcheng): It's kind of horrible that this is copy and pasted from
+# presubmit_canned_checks.py, but it's far easier than any of the alternatives.
+def _ReportErrorFileAndLine(filename, line_num, dummy_line):
+  """Default error formatter for _FindNewViolationsOfRule."""
+  return '%s:%s' % (filename, line_num)
+
+
+class MockCannedChecks(object):
+  def _FindNewViolationsOfRule(self, callable_rule, input_api,
+                               source_file_filter=None,
+                               error_formatter=_ReportErrorFileAndLine):
+    """Find all newly introduced violations of a per-line rule (a callable).
+
+    Arguments:
+      callable_rule: a callable taking a file extension and line of input and
+        returning True if the rule is satisfied and False if there was a
+        problem.
+      input_api: object to enumerate the affected files.
+      source_file_filter: a filter to be passed to the input api.
+      error_formatter: a callable taking (filename, line_number, line) and
+        returning a formatted error string.
+
+    Returns:
+      A list of the newly-introduced violations reported by the rule.
+    """
+    errors = []
+    for f in input_api.AffectedFiles(include_deletes=False,
+                                     file_filter=source_file_filter):
+      # For speed, we do two passes, checking first the full file.  Shelling out
+      # to the SCM to determine the changed region can be quite expensive on
+      # Win32.  Assuming that most files will be kept problem-free, we can
+      # skip the SCM operations most of the time.
+      extension = str(f.LocalPath()).rsplit('.', 1)[-1]
+      if all(callable_rule(extension, line) for line in f.NewContents()):
+        continue  # No violation found in full text: can skip considering diff.
+
+      for line_num, line in f.ChangedContents():
+        if not callable_rule(extension, line):
+          errors.append(error_formatter(f.LocalPath(), line_num, line))
+
+    return errors
 
 class MockInputApi(object):
   """Mock class for the InputApi class.
@@ -18,6 +59,7 @@
   """
 
   def __init__(self):
+    self.canned_checks = MockCannedChecks()
     self.fnmatch = fnmatch
     self.json = json
     self.re = re
diff --git a/android_webview/OWNERS b/android_webview/OWNERS
index cc77c50e..925cbe6 100644
--- a/android_webview/OWNERS
+++ b/android_webview/OWNERS
@@ -1,6 +1,5 @@
 boliu@chromium.org
 michaelbai@chromium.org
-sgurun@chromium.org
 tobiasjs@chromium.org
 torne@chromium.org
 
diff --git a/android_webview/browser/aw_contents.cc b/android_webview/browser/aw_contents.cc
index 5776088..3381f09 100644
--- a/android_webview/browser/aw_contents.cc
+++ b/android_webview/browser/aw_contents.cc
@@ -224,9 +224,10 @@
   browser_view_renderer_.RegisterWithWebContents(web_contents_.get());
 
   CompositorID compositor_id;
-  if (web_contents_->GetRenderProcessHost() &&
-      web_contents_->GetRenderViewHost()) {
-    compositor_id.process_id = web_contents_->GetRenderProcessHost()->GetID();
+  if (web_contents_->GetRenderViewHost() &&
+      web_contents_->GetRenderViewHost()->GetProcess()) {
+    compositor_id.process_id =
+        web_contents_->GetRenderViewHost()->GetProcess()->GetID();
     compositor_id.routing_id =
         web_contents_->GetRenderViewHost()->GetRoutingID();
   }
@@ -1212,7 +1213,9 @@
 jint AwContents::GetEffectivePriority(
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& obj) {
-  switch (web_contents_->GetRenderProcessHost()->ComputeEffectiveImportance()) {
+  switch (web_contents_->GetMainFrame()
+              ->GetProcess()
+              ->ComputeEffectiveImportance()) {
     case content::ChildProcessImportance::NORMAL:
       return static_cast<jint>(RendererPriority::WAIVED);
     case content::ChildProcessImportance::MODERATE:
@@ -1284,7 +1287,7 @@
     JNIEnv* env,
     const JavaParamRef<jobject>& obj) {
   content::ChildProcessSecurityPolicy::GetInstance()->GrantScheme(
-      web_contents_->GetRenderProcessHost()->GetID(), url::kFileScheme);
+      web_contents_->GetMainFrame()->GetProcess()->GetID(), url::kFileScheme);
 }
 
 void AwContents::ResumeLoadingCreatedPopupWebContents(
@@ -1331,9 +1334,10 @@
   CompositorID compositor_id;
   if (!web_contents_)
     return;
-  if (web_contents_->GetRenderProcessHost() &&
-      web_contents_->GetRenderViewHost()) {
-    compositor_id.process_id = web_contents_->GetRenderProcessHost()->GetID();
+  if (web_contents_->GetRenderViewHost() &&
+      web_contents_->GetRenderViewHost()->GetProcess()) {
+    compositor_id.process_id =
+        web_contents_->GetRenderViewHost()->GetProcess()->GetID();
     compositor_id.routing_id =
         web_contents_->GetRenderViewHost()->GetRoutingID();
   } else {
diff --git a/android_webview/browser/net/aw_cookie_store_wrapper.cc b/android_webview/browser/net/aw_cookie_store_wrapper.cc
index 6eca03e..79d91b8e 100644
--- a/android_webview/browser/net/aw_cookie_store_wrapper.cc
+++ b/android_webview/browser/net/aw_cookie_store_wrapper.cc
@@ -20,6 +20,21 @@
   GetCookieStoreTaskRunner()->PostTask(FROM_HERE, std::move(task));
 }
 
+class AwCookieChangedSubscription
+    : public net::CookieStore::CookieChangedSubscription {
+ public:
+  explicit AwCookieChangedSubscription(
+      std::unique_ptr<net::CookieStore::CookieChangedCallbackList::Subscription>
+          subscription)
+      : subscription_(std::move(subscription)) {}
+
+ private:
+  std::unique_ptr<net::CookieStore::CookieChangedCallbackList::Subscription>
+      subscription_;
+
+  DISALLOW_COPY_AND_ASSIGN(AwCookieChangedSubscription);
+};
+
 // Wraps a subscription to cookie change notifications for the global
 // CookieStore for a consumer that lives on another thread. Handles passing
 // messages between thread, and destroys itself when the consumer unsubscribes.
@@ -38,7 +53,8 @@
 
     nested_subscription_ =
         new NestedSubscription(url, name, weak_factory_.GetWeakPtr());
-    return callback_list_.Add(callback);
+    return std::make_unique<AwCookieChangedSubscription>(
+        callback_list_.Add(callback));
   }
 
  private:
diff --git a/android_webview/browser/state_serializer.cc b/android_webview/browser/state_serializer.cc
index 49223a4..1f2a64b 100644
--- a/android_webview/browser/state_serializer.cc
+++ b/android_webview/browser/state_serializer.cc
@@ -11,6 +11,7 @@
 #include "content/public/browser/child_process_security_policy.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/restore_type.h"
 #include "content/public/browser/web_contents.h"
@@ -106,9 +107,10 @@
 
   if (controller.GetLastCommittedEntry()) {
     // Set up the file access rights for the selected navigation entry.
-    // TODO(joth): This is duplicated from chrome/.../session_restore.cc and
-    // should be shared e.g. in  NavigationController. http://crbug.com/68222
-    const int id = web_contents->GetRenderProcessHost()->GetID();
+    // TODO(joth): https://crbug.com/767519: This is duplicated from
+    // chrome/.../session_restore.cc and should be shared e.g. in
+    // NavigationController.
+    const int id = web_contents->GetMainFrame()->GetProcess()->GetID();
     const content::PageState& page_state =
         controller.GetLastCommittedEntry()->GetPageState();
     const std::vector<base::FilePath>& file_paths =
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java
index b486e4a..2cde933 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java
@@ -1636,32 +1636,14 @@
 
     @Override
     public void onInitializeAccessibilityNodeInfo(final AccessibilityNodeInfo info) {
-        mFactory.startYourEngines(false);
-        if (checkNeedsPost()) {
-            mFactory.runVoidTaskOnUiThreadBlocking(new Runnable() {
-                @Override
-                public void run() {
-                    onInitializeAccessibilityNodeInfo(info);
-                }
-            });
-            return;
-        }
-        mAwContents.onInitializeAccessibilityNodeInfo(info);
+        // Intentional no-op. Chromium accessibility implementation currently does not need this
+        // calls.
     }
 
     @Override
     public void onInitializeAccessibilityEvent(final AccessibilityEvent event) {
-        mFactory.startYourEngines(false);
-        if (checkNeedsPost()) {
-            mFactory.runVoidTaskOnUiThreadBlocking(new Runnable() {
-                @Override
-                public void run() {
-                    onInitializeAccessibilityEvent(event);
-                }
-            });
-            return;
-        }
-        mAwContents.onInitializeAccessibilityEvent(event);
+        // Intentional no-op. Chromium accessibility implementation currently does not need this
+        // calls.
     }
 
     @Override
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 9ef980e..2879af5 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -37,8 +37,6 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewStructure;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeProvider;
 import android.view.animation.AnimationUtils;
 import android.view.autofill.AutofillValue;
@@ -2623,22 +2621,7 @@
      * @return The AccessibilityNodeProvider, if available, or null otherwise.
      */
     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
-        return isDestroyedOrNoOperation(WARN) ? null
-                : mContentViewCore.getAccessibilityNodeProvider();
-    }
-
-    /**
-     * @see android.webkit.WebView#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
-     */
-    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
-        // TODO(boliu): remove this method.
-    }
-
-    /**
-     * @see android.webkit.WebView#onInitializeAccessibilityEvent(AccessibilityEvent)
-     */
-    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
-     // TODO(boliu): remove this method.
+        return mAwViewMethods.getAccessibilityNodeProvider();
     }
 
     public boolean supportsAccessibilityAction(int action) {
@@ -2650,8 +2633,7 @@
      * @see android.webkit.WebView#performAccessibilityAction(int, Bundle)
      */
     public boolean performAccessibilityAction(int action, Bundle arguments) {
-        return isDestroyedOrNoOperation(WARN) ? false
-                : mContentViewCore.performAccessibilityAction(action, arguments);
+        return mAwViewMethods.performAccessibilityAction(action, arguments);
     }
 
     /**
@@ -3469,6 +3451,19 @@
             if (isDestroyedOrNoOperation(NO_WARN)) return;
             nativeOnComputeScroll(mNativeAwContents, AnimationUtils.currentAnimationTimeMillis());
         }
+
+        @Override
+        public AccessibilityNodeProvider getAccessibilityNodeProvider() {
+            return isDestroyedOrNoOperation(WARN) ? null
+                                                  : mContentViewCore.getAccessibilityNodeProvider();
+        }
+
+        @Override
+        public boolean performAccessibilityAction(final int action, final Bundle arguments) {
+            return isDestroyedOrNoOperation(WARN)
+                    ? false
+                    : mContentViewCore.performAccessibilityAction(action, arguments);
+        }
     }
 
     // Return true if the GeolocationPermissionAPI should be used.
diff --git a/android_webview/java/src/org/chromium/android_webview/AwViewMethods.java b/android_webview/java/src/org/chromium/android_webview/AwViewMethods.java
index 5b13ca0..c9599c1 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwViewMethods.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwViewMethods.java
@@ -8,10 +8,12 @@
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Rect;
+import android.os.Bundle;
 import android.view.DragEvent;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.accessibility.AccessibilityNodeProvider;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 
@@ -159,4 +161,14 @@
      * @see android.view.View#computeScroll
      */
     void computeScroll();
+
+    /**
+     * @see android.view.View#getAccessibilityNodeProvider
+     */
+    AccessibilityNodeProvider getAccessibilityNodeProvider();
+
+    /**
+     * @see android.view.View#performAccessibilityAction
+     */
+    public boolean performAccessibilityAction(final int action, final Bundle arguments);
 }
diff --git a/android_webview/java/src/org/chromium/android_webview/FullScreenView.java b/android_webview/java/src/org/chromium/android_webview/FullScreenView.java
index f37819b..45afd9ce 100644
--- a/android_webview/java/src/org/chromium/android_webview/FullScreenView.java
+++ b/android_webview/java/src/org/chromium/android_webview/FullScreenView.java
@@ -10,9 +10,11 @@
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Rect;
+import android.os.Bundle;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.accessibility.AccessibilityNodeProvider;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.widget.FrameLayout;
@@ -191,6 +193,16 @@
         mAwViewMethods.computeScroll();
     }
 
+    @Override
+    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
+        return mAwViewMethods.getAccessibilityNodeProvider();
+    }
+
+    @Override
+    public boolean performAccessibilityAction(final int action, final Bundle arguments) {
+        return mAwViewMethods.performAccessibilityAction(action, arguments);
+    }
+
     // AwContents.InternalAccessDelegate implementation --------------------------------------
     private class InternalAccessAdapter implements AwContents.InternalAccessDelegate {
 
diff --git a/android_webview/java/src/org/chromium/android_webview/NullAwViewMethods.java b/android_webview/java/src/org/chromium/android_webview/NullAwViewMethods.java
index adf98a93..8888b90a 100644
--- a/android_webview/java/src/org/chromium/android_webview/NullAwViewMethods.java
+++ b/android_webview/java/src/org/chromium/android_webview/NullAwViewMethods.java
@@ -8,10 +8,12 @@
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Rect;
+import android.os.Bundle;
 import android.view.DragEvent;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.accessibility.AccessibilityNodeProvider;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 
@@ -173,4 +175,14 @@
     public void computeScroll() {
         // Intentional no-op.
     }
+
+    @Override
+    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
+        return null;
+    }
+
+    @Override
+    public boolean performAccessibilityAction(final int action, final Bundle arguments) {
+        return 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 90c2e45..9d6741e 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
@@ -397,7 +397,7 @@
         private CallbackHelper mVirtualValueChanged = new CallbackHelper();
         private AwContents mAwContents;
         private TestViewStructure mTestViewStructure;
-        private SparseArray<AutofillValue> mAutofillValues;
+        private ArrayList<Pair<Integer, AutofillValue>> mChangedValues;
 
         public AwAutofillManagerHelper(Context context) {
             super(context);
@@ -413,11 +413,8 @@
             mVirtualViewEntered.waitForCallback(count);
         }
 
-        public SparseArray<AutofillValue> waitForNotifyVirtualValueChanged(int times)
-                throws Throwable {
-            int count = mVirtualValueChanged.getCallCount();
-            mVirtualValueChanged.waitForCallback(count, times);
-            return mAutofillValues;
+        public CallbackHelper getVirtualValueChangedCallbackHelper() {
+            return mVirtualValueChanged;
         }
 
         public void setAwContents(AwContents awContents) {
@@ -430,7 +427,6 @@
         }
 
         public void invokeAutofill(SparseArray<AutofillValue> values) {
-            mAutofillValues = new SparseArray<AutofillValue>();
             mAwContents.autofill(values);
         }
 
@@ -440,9 +436,16 @@
 
         @Override
         public void notifyVirtualValueChanged(View parent, int childId, AutofillValue value) {
-            if (mAutofillValues != null) mAutofillValues.append(childId, value);
+            if (mChangedValues == null) {
+                mChangedValues = new ArrayList<Pair<Integer, AutofillValue>>();
+            }
+            mChangedValues.add(new Pair<Integer, AutofillValue>(childId, value));
             mVirtualValueChanged.notifyCalled();
         }
+
+        public ArrayList<Pair<Integer, AutofillValue>> getChangedValues() {
+            return mChangedValues;
+        }
     }
 
     @Rule
@@ -491,8 +494,11 @@
                     mContentsClient.getOnPageFinishedHelper(), url);
             mActivityTestRule.executeJavaScriptAndWaitForResult(mTestContainerView.getAwContents(),
                     mContentsClient, "document.getElementById('text1').select();");
+            CallbackHelper callbackHelper = mHelper.getVirtualValueChangedCallbackHelper();
+            int count = callbackHelper.getCallCount();
             dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_A);
             mHelper.waitForNotifyVirtualViewEnteredCalled();
+            callbackHelper.waitForCallback(count);
             mHelper.invokeOnProvideAutoFillVirtualStructure();
             TestViewStructure viewStructure = mHelper.getTestViewStructure();
             assertNotNull(viewStructure);
@@ -545,8 +551,9 @@
             values.append(child0.getId(), AutofillValue.forText("example@example.com"));
             values.append(child1.getId(), AutofillValue.forToggle(true));
             values.append(child2.getId(), AutofillValue.forList(1));
+            count = callbackHelper.getCallCount();
             mHelper.invokeAutofill(values);
-            mHelper.waitForNotifyVirtualValueChanged(totalControls);
+            callbackHelper.waitForCallback(count, totalControls);
 
             // Verify form filled by Javascript
             String value0 = mActivityTestRule.executeJavaScriptAndWaitForResult(
@@ -566,6 +573,88 @@
         }
     }
 
+    @Test
+    @SmallTest
+    @Feature({"AndroidWebView"})
+    public void testNotifyVirtualValueChanged() throws Throwable {
+        TestWebServer webServer = TestWebServer.start();
+        mActivityTestRule.enableJavaScriptOnUiThread(mTestContainerView.getAwContents());
+        final String data = "<html><head></head><body><form action='a.html' name='formname'>"
+                + "<input type='text' id='text1' name='username'"
+                + " placeholder='placeholder@placeholder.com' autocomplete='username name'>"
+                + "</form></body></html>";
+        final String file = "/login.html";
+        try {
+            final String url = webServer.setResponse(file, data, null);
+            mActivityTestRule.loadUrlSync(mTestContainerView.getAwContents(),
+                    mContentsClient.getOnPageFinishedHelper(), url);
+            mActivityTestRule.executeJavaScriptAndWaitForResult(mTestContainerView.getAwContents(),
+                    mContentsClient, "document.getElementById('text1').select();");
+            CallbackHelper callbackHelper = mHelper.getVirtualValueChangedCallbackHelper();
+            int count = callbackHelper.getCallCount();
+            dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_A);
+            callbackHelper.waitForCallback(count);
+            ArrayList<Pair<Integer, AutofillValue>> values = mHelper.getChangedValues();
+            // Check if NotifyVirtualValueChanged() called and value is 'a'.
+            assertEquals(1, values.size());
+            assertEquals("a", values.get(0).second.getTextValue());
+            count = callbackHelper.getCallCount();
+            dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_B);
+            // Check if NotifyVirtualValueChanged() called 2 times, first value is 'a',
+            // second value is 'ab', and both time has the same id.
+            callbackHelper.waitForCallback(count);
+            values = mHelper.getChangedValues();
+            assertEquals(2, values.size());
+            assertEquals("a", values.get(0).second.getTextValue());
+            assertEquals("ab", values.get(1).second.getTextValue());
+            assertEquals(values.get(0).first, values.get(1).first);
+        } finally {
+            webServer.shutdown();
+        }
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"AndroidWebView"})
+    public void testJavascriptNotTriggerNotifyVirtualValueChanged() throws Throwable {
+        TestWebServer webServer = TestWebServer.start();
+        mActivityTestRule.enableJavaScriptOnUiThread(mTestContainerView.getAwContents());
+        final String data = "<html><head></head><body><form action='a.html' name='formname'>"
+                + "<input type='text' id='text1' name='username'"
+                + " placeholder='placeholder@placeholder.com' autocomplete='username name'>"
+                + "</form></body></html>";
+        final String file = "/login.html";
+        try {
+            final String url = webServer.setResponse(file, data, null);
+            mActivityTestRule.loadUrlSync(mTestContainerView.getAwContents(),
+                    mContentsClient.getOnPageFinishedHelper(), url);
+            mActivityTestRule.executeJavaScriptAndWaitForResult(mTestContainerView.getAwContents(),
+                    mContentsClient, "document.getElementById('text1').select();");
+            CallbackHelper callbackHelper = mHelper.getVirtualValueChangedCallbackHelper();
+            int count = callbackHelper.getCallCount();
+            dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_A);
+            callbackHelper.waitForCallback(count);
+            ArrayList<Pair<Integer, AutofillValue>> values = mHelper.getChangedValues();
+            // Check if NotifyVirtualValueChanged() called and value is 'a'.
+            assertEquals(1, values.size());
+            assertEquals("a", values.get(0).second.getTextValue());
+            count = callbackHelper.getCallCount();
+            mActivityTestRule.executeJavaScriptAndWaitForResult(mTestContainerView.getAwContents(),
+                    mContentsClient, "document.getElementById('text1').value='c';");
+            dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_B);
+            // Check if NotifyVirtualValueChanged() called one more time and value is 'cb', this
+            // means javascript change didn't trigger the NotifyVirtualValueChanged().
+            callbackHelper.waitForCallback(count);
+            values = mHelper.getChangedValues();
+            assertEquals(2, values.size());
+            assertEquals("a", values.get(0).second.getTextValue());
+            assertEquals("cb", values.get(1).second.getTextValue());
+            assertEquals(values.get(0).first, values.get(1).first);
+        } finally {
+            webServer.shutdown();
+        }
+    }
+
     private void dispatchDownAndUpKeyEvents(final int code) throws Throwable {
         dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, code));
         dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, code));
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java
index 3398c442..43110d29 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java
@@ -21,7 +21,6 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.android_webview.test.util.JavascriptEventObserver;
-import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.RetryOnFailure;
@@ -43,7 +42,7 @@
  * very common use case.
  */
 @RunWith(AwJUnit4ClassRunner.class)
-@DisableIf.Build(sdk_is_greater_than = 22, message = "crbug.com/615483,615184")
+@RetryOnFailure // crbug.com/615483
 public class AwContentsClientFullScreenTest {
     @Rule
     public AwActivityTestRule mActivityTestRule = new AwActivityTestRule();
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java
index f824a9e..daea671a 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java
@@ -407,18 +407,42 @@
 
     private void assertTargetPageHasLoaded(int pageColor) throws Exception {
         mActivityTestRule.waitForVisualStateCallback(mAwContents);
-        Assert.assertEquals("Target page should be visible", pageColor,
-                GraphicsTestUtils.getPixelColorAtCenterOfView(mAwContents, mContainerView));
+        Assert.assertEquals("Target page should be visible", colorToString(pageColor),
+                colorToString(GraphicsTestUtils.getPixelColorAtCenterOfView(
+                        mAwContents, mContainerView)));
+    }
+
+    private void assertGreenPageShowing() throws Exception {
+        Assert.assertEquals("Original page should be showing",
+                colorToString(GREEN_PAGE_BACKGROUND_COLOR),
+                colorToString(GraphicsTestUtils.getPixelColorAtCenterOfView(
+                        mAwContents, mContainerView)));
     }
 
     private void assertGreenPageNotShowing() throws Exception {
-        assertNotEquals("Original page should not be showing", GREEN_PAGE_BACKGROUND_COLOR,
-                GraphicsTestUtils.getPixelColorAtCenterOfView(mAwContents, mContainerView));
+        assertNotEquals("Original page should not be showing",
+                colorToString(GREEN_PAGE_BACKGROUND_COLOR),
+                colorToString(GraphicsTestUtils.getPixelColorAtCenterOfView(
+                        mAwContents, mContainerView)));
     }
 
     private void assertTargetPageNotShowing(int pageColor) throws Exception {
-        assertNotEquals("Target page should not be showing", pageColor,
-                GraphicsTestUtils.getPixelColorAtCenterOfView(mAwContents, mContainerView));
+        assertNotEquals("Target page should not be showing", colorToString(pageColor),
+                colorToString(GraphicsTestUtils.getPixelColorAtCenterOfView(
+                        mAwContents, mContainerView)));
+    }
+
+    /**
+     * Converts a color from the confusing integer representation to a more readable string
+     * respresentation. There is a 1:1 mapping between integer and string representations, so it's
+     * valid to compare strings directly. The string representation is better for assert output.
+     *
+     * @param color integer representation of the color
+     * @return a String representation of the color in RGBA format
+     */
+    private String colorToString(int color) {
+        return "(" + Color.red(color) + "," + Color.green(color) + "," + Color.blue(color) + ","
+                + Color.alpha(color) + ")";
     }
 
     @Test
@@ -784,8 +808,7 @@
         Assert.assertEquals("Network error is for the malicious page", responseUrl,
                 errorHelper.getRequest().url);
 
-        Assert.assertEquals("Original page should be showing", GREEN_PAGE_BACKGROUND_COLOR,
-                GraphicsTestUtils.getPixelColorAtCenterOfView(mAwContents, mContainerView));
+        assertGreenPageShowing();
 
         // Check onSafeBrowsingHit arguments
         Assert.assertEquals(responseUrl, mContentsClient.getLastRequest().url);
@@ -835,9 +858,11 @@
         mContentsClient.getOnPageFinishedHelper().waitForCallback(pageFinishedCount);
 
         // Wait for the onSafeBrowsingHit to call BACK_TO_SAFETY and navigate back
-        mActivityTestRule.pollUiThread(() -> GREEN_PAGE_BACKGROUND_COLOR
-                == GraphicsTestUtils.getPixelColorAtCenterOfView(
-                mAwContents, mContainerView));
+        // clang-format off
+        mActivityTestRule.pollUiThread(() -> colorToString(GREEN_PAGE_BACKGROUND_COLOR).equals(
+                colorToString(GraphicsTestUtils.getPixelColorAtCenterOfView(mAwContents,
+                        mContainerView))));
+        // clang-format on
 
         // Check onSafeBrowsingHit arguments
         Assert.assertFalse(mContentsClient.getLastRequest().isMainFrame);
diff --git a/android_webview/tools/system_webview_shell/apk/src/org/chromium/webview_shell/WebViewBrowserActivity.java b/android_webview/tools/system_webview_shell/apk/src/org/chromium/webview_shell/WebViewBrowserActivity.java
index 224b5aa..3880f5d 100644
--- a/android_webview/tools/system_webview_shell/apk/src/org/chromium/webview_shell/WebViewBrowserActivity.java
+++ b/android_webview/tools/system_webview_shell/apk/src/org/chromium/webview_shell/WebViewBrowserActivity.java
@@ -22,7 +22,6 @@
 import android.os.Bundle;
 import android.provider.Browser;
 import android.util.SparseArray;
-
 import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.MenuItem;
@@ -32,14 +31,12 @@
 import android.view.ViewGroup.LayoutParams;
 import android.view.WindowManager;
 import android.view.inputmethod.InputMethodManager;
-
 import android.webkit.GeolocationPermissions;
 import android.webkit.PermissionRequest;
 import android.webkit.WebChromeClient;
 import android.webkit.WebSettings;
 import android.webkit.WebView;
 import android.webkit.WebViewClient;
-
 import android.widget.EditText;
 import android.widget.FrameLayout;
 import android.widget.PopupMenu;
@@ -50,7 +47,6 @@
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
-
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -475,6 +471,11 @@
         settings.setGeolocationEnabled(true);
         settings.setDatabaseEnabled(true);
         settings.setDomStorageEnabled(true);
+
+        // Default layout behavior for chrome on android.
+        settings.setUseWideViewPort(true);
+        settings.setLoadWithOverviewMode(true);
+        settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING);
     }
 
     private void about() {
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc
index 062c0cf0..73ffed6 100644
--- a/ash/accelerators/accelerator_controller.cc
+++ b/ash/accelerators/accelerator_controller.cc
@@ -51,11 +51,13 @@
 #include "ash/wm/wm_event.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
+#include "base/optional.h"
 #include "base/strings/string_split.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chromeos/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power_manager_client.h"
+#include "components/user_manager/user_type.h"
 #include "ui/app_list/app_list_constants.h"
 #include "ui/app_list/presenter/app_list.h"
 #include "ui/base/accelerators/accelerator.h"
@@ -261,7 +263,12 @@
 }
 
 bool CanHandleNewIncognitoWindow() {
-  return Shell::Get()->shell_delegate()->IsIncognitoAllowed();
+  // Guest mode does not use incognito windows. The browser may have other
+  // restrictions on incognito mode (e.g. enterprise policy) but those are rare.
+  // For non-guest mode, consume the key and defer the decision to the browser.
+  base::Optional<user_manager::UserType> user_type =
+      Shell::Get()->session_controller()->GetUserType();
+  return user_type && *user_type != user_manager::USER_TYPE_GUEST;
 }
 
 void HandleNewIncognitoWindow() {
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc
index 007f286..a9aaf181 100644
--- a/ash/accelerators/accelerator_controller_unittest.cc
+++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -14,6 +14,7 @@
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/public/interfaces/ime_info.mojom.h"
 #include "ash/session/session_controller.h"
+#include "ash/session/test_session_controller_client.h"
 #include "ash/shell.h"
 #include "ash/shell_port.h"
 #include "ash/system/brightness_control_delegate.h"
@@ -1374,4 +1375,18 @@
   RemoveAllNotifications();
 }
 
+using AcceleratorControllerGuestModeTest = NoSessionAshTestBase;
+
+TEST_F(AcceleratorControllerGuestModeTest, IncognitoWindowDisabled) {
+  // Simulate a guest mode login.
+  TestSessionControllerClient* session = GetSessionControllerClient();
+  session->Reset();
+  session->AddUserSession("user1@test.com", user_manager::USER_TYPE_GUEST);
+  session->SetSessionState(session_manager::SessionState::ACTIVE);
+
+  // New incognito window is disabled.
+  EXPECT_FALSE(Shell::Get()->accelerator_controller()->PerformActionIfEnabled(
+      NEW_INCOGNITO_WINDOW));
+}
+
 }  // namespace ash
diff --git a/ash/app_list/app_list_presenter_delegate_unittest.cc b/ash/app_list/app_list_presenter_delegate_unittest.cc
index bd612b9..0f57e12 100644
--- a/ash/app_list/app_list_presenter_delegate_unittest.cc
+++ b/ash/app_list/app_list_presenter_delegate_unittest.cc
@@ -866,47 +866,6 @@
   EXPECT_FALSE(app_list_presenter_impl()->IsVisible());
 }
 
-// Tests that the app list transitions on mousewheel and gesture scroll events.
-TEST_P(FullscreenAppListPresenterDelegateTest,
-       MouseWheelAndGestureScrollTransition) {
-  const bool test_mouse_event = GetParam();
-  app_list_presenter_impl()->ShowAndRunLoop(GetPrimaryDisplayId());
-  app_list::AppListView* view = app_list_presenter_impl()->GetView();
-  ui::test::EventGenerator& generator = GetEventGenerator();
-  EXPECT_EQ(view->app_list_state(), app_list::AppListView::PEEKING);
-
-  // Move mouse to over the searchbox, mousewheel scroll up.
-  generator.MoveMouseTo(GetPointInsideSearchbox());
-  if (test_mouse_event) {
-    generator.MoveMouseWheel(0, -30);
-  } else {
-    generator.ScrollSequence(GetPointInsideSearchbox(),
-                             base::TimeDelta::FromMilliseconds(5), 0, -300, 2,
-                             2);
-  }
-  EXPECT_EQ(view->app_list_state(), app_list::AppListView::FULLSCREEN_ALL_APPS);
-
-  // Swipe down slowly, the app list should return to peeking mode.
-  gfx::Point start(0, 0);
-  gfx::Point end(0, 500);
-  generator.GestureScrollSequence(
-      start, end,
-      generator.CalculateScrollDurationForFlingVelocity(start, end, 1, 100),
-      100);
-  EXPECT_EQ(view->app_list_state(), app_list::AppListView::PEEKING);
-
-  // Move mouse away from the searchbox, mousewheel scroll up.
-  generator.MoveMouseTo(GetPointOutsideSearchbox());
-  if (test_mouse_event) {
-    generator.MoveMouseWheel(0, -30);
-  } else {
-    generator.ScrollSequence(GetPointOutsideSearchbox(),
-                             base::TimeDelta::FromMilliseconds(5), 0, -300, 2,
-                             2);
-  }
-  EXPECT_EQ(view->app_list_state(), app_list::AppListView::FULLSCREEN_ALL_APPS);
-}
-
 // Tests that the search box is set active with a whitespace query and that the
 // app list state doesn't transition with a whitespace query.
 TEST_F(FullscreenAppListPresenterDelegateTest, WhitespaceQuery) {
diff --git a/ash/autoclick/mus/manifest.json b/ash/autoclick/mus/manifest.json
index ec2a7397..d55725a4 100644
--- a/ash/autoclick/mus/manifest.json
+++ b/ash/autoclick/mus/manifest.json
@@ -1,6 +1,7 @@
 {
   "name": "accessibility_autoclick",
   "display_name": "Autoclick",
+  "sandbox_type": "none",
   "interface_provider_specs": {
     "service_manager:connector": {
       "provides": {
diff --git a/ash/display/display_manager_unittest.cc b/ash/display/display_manager_unittest.cc
index 6676a755..1450d25 100644
--- a/ash/display/display_manager_unittest.cc
+++ b/ash/display/display_manager_unittest.cc
@@ -1137,29 +1137,33 @@
   const display::ManagedDisplayInfo display_info1 = GetDisplayInfoAt(0);
   const display::ManagedDisplayInfo display_info2 = GetDisplayInfoAt(1);
 
-  EXPECT_FALSE(display_info2.has_touch_calibration_data());
+  constexpr uint32_t touch_device_identifier_2 = 2345;
 
-  display::TouchCalibrationData::CalibrationPointPairQuad point_pair_quad = {
-      {std::make_pair(gfx::Point(50, 50), gfx::Point(43, 51)),
-       std::make_pair(gfx::Point(950, 50), gfx::Point(975, 45)),
-       std::make_pair(gfx::Point(50, 550), gfx::Point(48, 534)),
-       std::make_pair(gfx::Point(950, 550), gfx::Point(967, 574))}};
-  gfx::Size bounds_at_calibration(display_info2.size_in_pixel());
+  EXPECT_FALSE(display_info2.touch_calibration_data_map().size());
+
+  const display::TouchCalibrationData::CalibrationPointPairQuad
+      point_pair_quad = {
+          {std::make_pair(gfx::Point(50, 50), gfx::Point(43, 51)),
+           std::make_pair(gfx::Point(950, 50), gfx::Point(975, 45)),
+           std::make_pair(gfx::Point(50, 550), gfx::Point(48, 534)),
+           std::make_pair(gfx::Point(950, 550), gfx::Point(967, 574))}};
+  const gfx::Size bounds_at_calibration(display_info2.size_in_pixel());
   const display::TouchCalibrationData touch_data(point_pair_quad,
                                                  bounds_at_calibration);
 
   // Set the touch calibration data for the secondary display.
   display_manager()->SetTouchCalibrationData(
-      display_info2.id(), point_pair_quad, bounds_at_calibration);
+      display_info2.id(), point_pair_quad, bounds_at_calibration,
+      touch_device_identifier_2);
 
-  display::ManagedDisplayInfo updated_display_info2 = GetDisplayInfoAt(1);
-  EXPECT_TRUE(updated_display_info2.has_touch_calibration_data());
-  EXPECT_EQ(touch_data, updated_display_info2.GetTouchCalibrationData());
+  EXPECT_TRUE(GetDisplayInfoAt(1).touch_calibration_data_map().size());
+  EXPECT_EQ(touch_data, GetDisplayInfoAt(1).GetTouchCalibrationData(
+                            touch_device_identifier_2));
 
   // Clearing touch calibration data from the secondary display.
-  display_manager()->ClearTouchCalibrationData(display_info2.id());
-  updated_display_info2 = GetDisplayInfoAt(1);
-  EXPECT_FALSE(updated_display_info2.has_touch_calibration_data());
+  display_manager()->ClearTouchCalibrationData(GetDisplayInfoAt(1).id(),
+                                               touch_device_identifier_2);
+  EXPECT_FALSE(GetDisplayInfoAt(1).touch_calibration_data_map().size());
 
   // Make sure that SetTouchCalibrationData() is idempotent.
   display::TouchCalibrationData::CalibrationPointPairQuad point_pair_quad_2 =
@@ -1169,22 +1173,18 @@
   display::TouchCalibrationData touch_data_2(point_pair_quad_2,
                                              bounds_at_calibration);
   display_manager()->SetTouchCalibrationData(
-      display_info2.id(), point_pair_quad_2, bounds_at_calibration);
+      display_info2.id(), point_pair_quad_2, bounds_at_calibration,
+      touch_device_identifier_2);
 
-  updated_display_info2 = GetDisplayInfoAt(1);
-  EXPECT_TRUE(updated_display_info2.has_touch_calibration_data());
-  EXPECT_EQ(touch_data_2, updated_display_info2.GetTouchCalibrationData());
-
-  display_manager()->SetTouchCalibrationData(
-      display_info2.id(), point_pair_quad, bounds_at_calibration);
-  EXPECT_TRUE(updated_display_info2.has_touch_calibration_data());
-  EXPECT_EQ(touch_data_2, updated_display_info2.GetTouchCalibrationData());
+  EXPECT_TRUE(GetDisplayInfoAt(1).touch_calibration_data_map().size());
+  EXPECT_EQ(touch_data_2, GetDisplayInfoAt(1).GetTouchCalibrationData(
+                              touch_device_identifier_2));
 
   // Recreate a new 2nd display. It won't apply the touhc calibration data
   // because the new display has a different ID.
   UpdateDisplay("0+0-500x500");
   UpdateDisplay("0+0-500x500,0+501-400x400");
-  EXPECT_FALSE(GetDisplayInfoAt(1).has_touch_calibration_data());
+  EXPECT_FALSE(GetDisplayInfoAt(1).touch_calibration_data_map().size());
 
   // Recreate the displays with the same ID.  It should apply the touch
   // calibration associated data.
@@ -1193,10 +1193,23 @@
   display_info_list.push_back(display_info1);
   display_info_list.push_back(display_info2);
   display_manager()->OnNativeDisplaysChanged(display_info_list);
-  updated_display_info2 = GetDisplayInfoAt(1);
 
-  EXPECT_FALSE(updated_display_info2.has_touch_calibration_data());
-  EXPECT_EQ(touch_data, updated_display_info2.GetTouchCalibrationData());
+  // Make sure multiple touch devices works.
+  display_manager()->SetTouchCalibrationData(
+      display_info2.id(), point_pair_quad, bounds_at_calibration,
+      touch_device_identifier_2);
+
+  EXPECT_TRUE(GetDisplayInfoAt(1).touch_calibration_data_map().size());
+  EXPECT_EQ(touch_data, GetDisplayInfoAt(1).GetTouchCalibrationData(
+                            touch_device_identifier_2));
+
+  uint32_t touch_device_identifier_2_2 = 2456;
+  display_manager()->SetTouchCalibrationData(
+      display_info2.id(), point_pair_quad_2, bounds_at_calibration,
+      touch_device_identifier_2_2);
+  EXPECT_EQ(GetDisplayInfoAt(1).touch_calibration_data_map().size(), 2UL);
+  EXPECT_EQ(touch_data_2, GetDisplayInfoAt(1).GetTouchCalibrationData(
+                              touch_device_identifier_2_2));
 }
 
 TEST_F(DisplayManagerTest, TestDeviceScaleOnlyChange) {
@@ -1994,7 +2007,7 @@
   const gfx::Insets dummy_overscan_insets;
   display_manager()->RegisterDisplayProperty(
       display_id, display::Display::ROTATE_0, 1.0f, &dummy_overscan_insets,
-      gfx::Size(), 1.0f, nullptr);
+      gfx::Size(), 1.0f, nullptr /* touch_calibration_data_map */);
 
   // Setup the display modes with UI-scale.
   display::ManagedDisplayInfo native_display_info =
@@ -2858,9 +2871,9 @@
 
 TEST_F(DisplayManagerTest, CheckInitializationOfRotationProperty) {
   int64_t id = display_manager()->GetDisplayAt(0).id();
-  display_manager()->RegisterDisplayProperty(id, display::Display::ROTATE_90,
-                                             1.0f, nullptr, gfx::Size(), 1.0f,
-                                             nullptr);
+  display_manager()->RegisterDisplayProperty(
+      id, display::Display::ROTATE_90, 1.0f, nullptr, gfx::Size(), 1.0f,
+      nullptr /* touch_calibration_data_map */);
 
   const display::ManagedDisplayInfo& info =
       display_manager()->GetDisplayInfo(id);
diff --git a/ash/display/touch_calibrator_controller.cc b/ash/display/touch_calibrator_controller.cc
index 2671bc30..9f3810a1 100644
--- a/ash/display/touch_calibrator_controller.cc
+++ b/ash/display/touch_calibrator_controller.cc
@@ -10,6 +10,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "ui/display/screen.h"
+#include "ui/events/devices/device_data_manager.h"
 #include "ui/events/event.h"
 #include "ui/events/event_constants.h"
 
@@ -25,36 +26,47 @@
 
 TouchCalibratorController::~TouchCalibratorController() {
   touch_calibrator_views_.clear();
-  StopCalibration();
+  StopCalibrationAndResetParams();
 }
 
 void TouchCalibratorController::OnDisplayConfigurationChanged() {
   touch_calibrator_views_.clear();
-  StopCalibration();
+  StopCalibrationAndResetParams();
 }
 
 void TouchCalibratorController::StartCalibration(
     const display::Display& target_display,
-    const TouchCalibratorController::TouchCalibrationCallback& callback) {
-  is_calibrating_ = true;
-  callback_ = callback;
+    bool is_custom_calibration,
+    TouchCalibrationCallback opt_callback) {
+  state_ = is_custom_calibration ? CalibrationState::kCustomCalibration
+                                 : CalibrationState::kNativeCalibration;
 
-  Shell::Get()->window_tree_host_manager()->AddObserver(this);
+  if (opt_callback)
+    opt_callback_ = std::move(opt_callback);
+
   target_display_ = target_display;
 
   // Clear all touch calibrator views used in any previous calibration.
   touch_calibrator_views_.clear();
 
-  // Reset the calibration data.
-  touch_point_quad_.fill(std::make_pair(gfx::Point(0, 0), gfx::Point(0, 0)));
+  // Set the touch device id as invalid so it can be set during calibration.
+  touch_device_id_ = ui::InputDevice::kInvalidId;
 
-  std::vector<display::Display> displays =
-      display::Screen::GetScreen()->GetAllDisplays();
+  // If this is a native touch calibration, then initialize the UX for it.
+  if (state_ == CalibrationState::kNativeCalibration) {
+    Shell::Get()->window_tree_host_manager()->AddObserver(this);
 
-  for (const display::Display& display : displays) {
-    bool is_primary_view = display.id() == target_display_.id();
-    touch_calibrator_views_[display.id()] =
-        base::MakeUnique<TouchCalibratorView>(display, is_primary_view);
+    // Reset the calibration data.
+    touch_point_quad_.fill(std::make_pair(gfx::Point(0, 0), gfx::Point(0, 0)));
+
+    std::vector<display::Display> displays =
+        display::Screen::GetScreen()->GetAllDisplays();
+
+    for (const display::Display& display : displays) {
+      bool is_primary_view = display.id() == target_display_.id();
+      touch_calibrator_views_[display.id()] =
+          base::MakeUnique<TouchCalibratorView>(display, is_primary_view);
+    }
   }
 
   Shell::Get()->touch_transformer_controller()->SetForCalibration(true);
@@ -63,11 +75,9 @@
   Shell::Get()->AddPreTargetHandler(this);
 }
 
-void TouchCalibratorController::StopCalibration() {
-  if (!is_calibrating_)
+void TouchCalibratorController::StopCalibrationAndResetParams() {
+  if (!IsCalibrating())
     return;
-  is_calibrating_ = false;
-
   Shell::Get()->window_tree_host_manager()->RemoveObserver(this);
 
   Shell::Get()->touch_transformer_controller()->SetForCalibration(false);
@@ -76,30 +86,83 @@
   Shell::Get()->RemovePreTargetHandler(this);
 
   // Transition all touch calibrator views to their final state for a graceful
-  // exit.
-  for (const auto& it : touch_calibrator_views_)
-    it.second->SkipToFinalState();
-
-  if (callback_) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
-                                                  base::Bind(callback_, false));
-    callback_.Reset();
+  // exit if this is touch calibration with native UX.
+  if (state_ == CalibrationState::kNativeCalibration) {
+    for (const auto& it : touch_calibrator_views_)
+      it.second->SkipToFinalState();
   }
+
+  state_ = CalibrationState::kInactive;
+
+  if (opt_callback_) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindOnce(std::move(opt_callback_), false /* failure */));
+    opt_callback_.Reset();
+  }
+}
+
+void TouchCalibratorController::CompleteCalibration(
+    const CalibrationPointPairQuad& pairs,
+    const gfx::Size& display_size) {
+  bool did_find_touch_device = false;
+  uint32_t touch_device_identifier =
+      display::TouchCalibrationData::GetFallbackTouchDeviceIdentifier();
+
+  const std::vector<ui::TouchscreenDevice>& device_list =
+      ui::DeviceDataManager::GetInstance()->GetTouchscreenDevices();
+  for (const auto& device : device_list) {
+    if (device.id == touch_device_id_) {
+      touch_device_identifier =
+          display::TouchCalibrationData::GenerateTouchDeviceIdentifier(
+              device.name, device.vendor_id, device.product_id);
+      did_find_touch_device = true;
+      break;
+    }
+  }
+
+  if (!did_find_touch_device) {
+    VLOG(1) << "No touch device with id: " << touch_device_id_ << " found to "
+            << "complete touch calibration for display with id: "
+            << target_display_.id() << ". Storing it as a fallback";
+  } else if (touch_device_identifier ==
+             display::TouchCalibrationData::
+                 GetFallbackTouchDeviceIdentifier()) {
+    LOG(ERROR)
+        << "Hash collision in generating touch device identifier for "
+        << " device. Hash Generated: " << touch_device_identifier
+        << " || Fallback touch device identifier: "
+        << display::TouchCalibrationData::GetFallbackTouchDeviceIdentifier();
+  }
+
+  if (opt_callback_) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindOnce(std::move(opt_callback_), true /* success */));
+    opt_callback_.Reset();
+  }
+  StopCalibrationAndResetParams();
+  Shell::Get()->display_manager()->SetTouchCalibrationData(
+      target_display_.id(), pairs, display_size, touch_device_identifier);
+}
+
+bool TouchCalibratorController::IsCalibrating() const {
+  return state_ != CalibrationState::kInactive;
 }
 
 // ui::EventHandler:
 void TouchCalibratorController::OnKeyEvent(ui::KeyEvent* key) {
-  if (!is_calibrating_)
+  if (state_ != CalibrationState::kNativeCalibration)
     return;
   // Detect ESC key press.
   if (key->type() == ui::ET_KEY_PRESSED && key->key_code() == ui::VKEY_ESCAPE)
-    StopCalibration();
+    StopCalibrationAndResetParams();
 
   key->StopPropagation();
 }
 
 void TouchCalibratorController::OnTouchEvent(ui::TouchEvent* touch) {
-  if (!is_calibrating_)
+  if (!IsCalibrating())
     return;
   if (touch->type() != ui::ET_TOUCH_RELEASED)
     return;
@@ -107,6 +170,14 @@
     return;
   last_touch_timestamp_ = base::Time::Now();
 
+  if (touch_device_id_ == ui::InputDevice::kInvalidId)
+    touch_device_id_ = touch->source_device_id();
+
+  // If this is a custom touch calibration, then everything else is managed
+  // by the application responsible for the custom calibration UX.
+  if (state_ == CalibrationState::kCustomCalibration)
+    return;
+
   TouchCalibratorView* target_screen_calibration_view =
       touch_calibrator_views_[target_display_.id()].get();
 
@@ -114,15 +185,8 @@
   // calibration.
   if (target_screen_calibration_view->state() ==
       TouchCalibratorView::CALIBRATION_COMPLETE) {
-    if (callback_) {
-      base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE, base::Bind(callback_, true));
-      callback_.Reset();
-    }
-    StopCalibration();
-    Shell::Get()->display_manager()->SetTouchCalibrationData(
-        target_display_.id(), touch_point_quad_,
-        target_screen_calibration_view->size());
+    CompleteCalibration(touch_point_quad_,
+                        target_screen_calibration_view->size());
     return;
   }
 
diff --git a/ash/display/touch_calibrator_controller.h b/ash/display/touch_calibrator_controller.h
index 9d731693..e5bf7d0 100644
--- a/ash/display/touch_calibrator_controller.h
+++ b/ash/display/touch_calibrator_controller.h
@@ -12,6 +12,7 @@
 #include "base/time/time.h"
 #include "ui/display/display.h"
 #include "ui/display/manager/managed_display_info.h"
+#include "ui/events/devices/touchscreen_device.h"
 #include "ui/events/event_handler.h"
 
 namespace ui {
@@ -23,17 +24,20 @@
 
 class TouchCalibratorView;
 
-// TouchCalibratorController is responsible for collecting the touch calibration
-// associated data from the user. It instantiates TouchCalibratorView classes to
-// present an interface the user can interact with for calibration.
-// Touch calibration is restricted to calibrate only one display at a time.
+// TouchCalibratorController is responsible for managing the touch calibration
+// process. In case of native touch calibration it is also responsible for
+// collecting the touch calibration associated data from the user. It
+// instantiates TouchCalibratorView classes to present the native UX interface
+// the user can interact with for calibration.
+// This controller ensures that only one instance of calibration is running at
+// any given time.
 class ASH_EXPORT TouchCalibratorController
     : public ui::EventHandler,
       public WindowTreeHostManager::Observer {
  public:
   using CalibrationPointPairQuad =
       display::TouchCalibrationData::CalibrationPointPairQuad;
-  using TouchCalibrationCallback = base::Callback<void(bool)>;
+  using TouchCalibrationCallback = base::OnceCallback<void(bool)>;
 
   static const base::TimeDelta kTouchIntervalThreshold;
 
@@ -48,19 +52,48 @@
   void OnDisplayConfigurationChanged() override;
 
   // Starts the calibration process for the given |target_display|.
+  // |opt_callback| is an optional callback that if provided is executed
+  // with the success or failure of the calibration as a boolean argument.
   void StartCalibration(const display::Display& target_display,
-                        const TouchCalibrationCallback& callback);
+                        bool is_custom_calibration,
+                        TouchCalibrationCallback opt_callback);
 
-  // Stops any ongoing calibration process.
-  void StopCalibration();
+  // Stops any ongoing calibration process. This is a hard stop which does not
+  // save any calibration data. Call CompleteCalibration() if you wish to save
+  // calibration data.
+  void StopCalibrationAndResetParams();
 
-  bool is_calibrating() { return is_calibrating_; }
+  // Completes the touch calibration by storing the calibration data for the
+  // display.
+  void CompleteCalibration(const CalibrationPointPairQuad& pairs,
+                           const gfx::Size& display_size);
+
+  // Returns true if any type of touch calibration is active.
+  bool IsCalibrating() const;
 
  private:
   friend class TouchCalibratorControllerTest;
   FRIEND_TEST_ALL_PREFIXES(TouchCalibratorControllerTest, StartCalibration);
   FRIEND_TEST_ALL_PREFIXES(TouchCalibratorControllerTest, KeyEventIntercept);
   FRIEND_TEST_ALL_PREFIXES(TouchCalibratorControllerTest, TouchThreshold);
+  FRIEND_TEST_ALL_PREFIXES(TouchCalibratorControllerTest, TouchDeviceIdIsSet);
+  FRIEND_TEST_ALL_PREFIXES(TouchCalibratorControllerTest, CustomCalibration);
+  FRIEND_TEST_ALL_PREFIXES(TouchCalibratorControllerTest,
+                           CustomCalibrationInvalidTouchId);
+
+  enum class CalibrationState {
+    // Indicates that the touch calibration is currently active with the built
+    // in native UX.
+    kNativeCalibration = 0,
+
+    // Indicates that the touch calibration is currently active with a custom
+    // UX via the extensions API.
+    kCustomCalibration,
+
+    // Indicates that touch calibration is currently inactive.
+    kInactive
+  };
+  CalibrationState state_ = CalibrationState::kInactive;
 
   // A map for TouchCalibrator view with the key as display id of the display
   // it is present in.
@@ -75,15 +108,16 @@
   // was received.
   base::Time last_touch_timestamp_;
 
-  // Is true if a touch calibration is already underprocess.
-  bool is_calibrating_ = false;
+  // This is populated during calibration, based on the source id of the device
+  // the events are originating from.
+  int touch_device_id_ = ui::InputDevice::kInvalidId;
 
   // An array of Calibration point pairs. This stores all the 4 display and
   // touch input point pairs that will be used for calibration.
   CalibrationPointPairQuad touch_point_quad_;
 
   // A callback to be called when touch calibration completes.
-  TouchCalibrationCallback callback_;
+  TouchCalibrationCallback opt_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(TouchCalibratorController);
 };
diff --git a/ash/display/touch_calibrator_controller_unittest.cc b/ash/display/touch_calibrator_controller_unittest.cc
index 29da72dd..b3c0b38 100644
--- a/ash/display/touch_calibrator_controller_unittest.cc
+++ b/ash/display/touch_calibrator_controller_unittest.cc
@@ -13,7 +13,9 @@
 #include "ui/display/display.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/events/base_event_utils.h"
+#include "ui/events/devices/device_data_manager.h"
 #include "ui/events/event_handler.h"
+#include "ui/events/test/device_data_manager_test_api.h"
 #include "ui/events/test/event_generator.h"
 #include "ui/events/test/events_test_utils.h"
 
@@ -41,13 +43,16 @@
 
   void StartCalibrationChecks(TouchCalibratorController* ctrl,
                               const Display& target_display) {
-    EXPECT_FALSE(ctrl->is_calibrating());
+    EXPECT_FALSE(ctrl->IsCalibrating());
     EXPECT_FALSE(!!ctrl->touch_calibrator_views_.size());
 
     TouchCalibratorController::TouchCalibrationCallback empty_callback;
 
-    ctrl->StartCalibration(target_display, empty_callback);
-    EXPECT_TRUE(ctrl->is_calibrating());
+    ctrl->StartCalibration(target_display, false /* is_custom_calibration */,
+                           std::move(empty_callback));
+    EXPECT_TRUE(ctrl->IsCalibrating());
+    EXPECT_EQ(ctrl->state_,
+              TouchCalibratorController::CalibrationState::kNativeCalibration);
 
     // There should be a touch calibrator view associated with each of the
     // active displays.
@@ -66,6 +71,53 @@
               TouchCalibratorView::DISPLAY_POINT_1);
   }
 
+  // Generates a touch press and release event in the |display| with source
+  // device id as |touch_device_id|.
+  void GenerateTouchEvent(const Display& display, int touch_device_id) {
+    gfx::Vector2d offset(display_manager()
+                             ->GetDisplayInfo(display.id())
+                             .bounds_in_native()
+                             .OffsetFromOrigin());
+    ui::test::EventGenerator& eg = GetEventGenerator();
+    ui::TouchEvent press_touch_event(
+        ui::ET_TOUCH_PRESSED, gfx::Point(20, 20) + offset,
+        ui::EventTimeForNow(),
+        ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 12, 1.0f,
+                           1.0f, 0.0f),
+        0, 0.0f);
+    ui::TouchEvent release_touch_event(
+        ui::ET_TOUCH_RELEASED, gfx::Point(20, 20) + offset,
+        ui::EventTimeForNow(),
+        ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 12, 1.0f,
+                           1.0f, 0.0f),
+        0, 0.0f);
+
+    press_touch_event.set_source_device_id(touch_device_id);
+    release_touch_event.set_source_device_id(touch_device_id);
+
+    eg.Dispatch(&press_touch_event);
+    eg.Dispatch(&release_touch_event);
+  }
+
+  ui::TouchscreenDevice InitTouchDevice(int64_t display_id) {
+    ui::DeviceDataManager::CreateInstance();
+    ui::TouchscreenDevice touchdevice(
+        12, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL,
+        std::string("test touch device"), gfx::Size(1000, 1000), 1);
+
+    ui::test::DeviceDataManagerTestAPI devices_test_api;
+    devices_test_api.SetTouchscreenDevices({touchdevice});
+
+    std::vector<ui::TouchDeviceTransform> transforms;
+    ui::TouchDeviceTransform touch_device_transform;
+    touch_device_transform.display_id = display_id;
+    touch_device_transform.device_id = touchdevice.id;
+    transforms.push_back(touch_device_transform);
+
+    ui::DeviceDataManager::GetInstance()->ConfigureTouchDevices(transforms);
+    return touchdevice;
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(TouchCalibratorControllerTest);
 };
@@ -86,9 +138,9 @@
   StartCalibrationChecks(&touch_calibrator_controller, touch_display);
 
   ui::test::EventGenerator& eg = GetEventGenerator();
-  EXPECT_TRUE(touch_calibrator_controller.is_calibrating());
+  EXPECT_TRUE(touch_calibrator_controller.IsCalibrating());
   eg.PressKey(ui::VKEY_ESCAPE, ui::EF_NONE);
-  EXPECT_FALSE(touch_calibrator_controller.is_calibrating());
+  EXPECT_FALSE(touch_calibrator_controller.IsCalibrating());
 }
 
 TEST_F(TouchCalibratorControllerTest, TouchThreshold) {
@@ -119,4 +171,113 @@
             touch_calibrator_controller.last_touch_timestamp_);
 }
 
+TEST_F(TouchCalibratorControllerTest, TouchDeviceIdIsSet) {
+  const Display& touch_display = InitDisplays();
+  ui::TouchscreenDevice touchdevice = InitTouchDevice(touch_display.id());
+
+  TouchCalibratorController touch_calibrator_controller;
+  StartCalibrationChecks(&touch_calibrator_controller, touch_display);
+
+  base::Time current_timestamp = base::Time::Now();
+  touch_calibrator_controller.last_touch_timestamp_ =
+      current_timestamp - (TouchCalibratorController::kTouchIntervalThreshold);
+
+  EXPECT_EQ(touch_calibrator_controller.touch_device_id_,
+            ui::InputDevice::kInvalidId);
+  GenerateTouchEvent(touch_display, touchdevice.id);
+  EXPECT_EQ(touch_calibrator_controller.touch_device_id_, touchdevice.id);
+}
+
+TEST_F(TouchCalibratorControllerTest, CustomCalibration) {
+  const Display& touch_display = InitDisplays();
+  ui::TouchscreenDevice touchdevice = InitTouchDevice(touch_display.id());
+
+  TouchCalibratorController touch_calibrator_controller;
+  EXPECT_FALSE(touch_calibrator_controller.IsCalibrating());
+  EXPECT_FALSE(!!touch_calibrator_controller.touch_calibrator_views_.size());
+
+  touch_calibrator_controller.StartCalibration(
+      touch_display, true /* is_custom_calibbration */,
+      TouchCalibratorController::TouchCalibrationCallback());
+
+  EXPECT_TRUE(touch_calibrator_controller.IsCalibrating());
+  EXPECT_EQ(touch_calibrator_controller.state_,
+            TouchCalibratorController::CalibrationState::kCustomCalibration);
+
+  // Native touch calibration UX should not initialize during custom calibration
+  EXPECT_EQ(touch_calibrator_controller.touch_calibrator_views_.size(), 0UL);
+  EXPECT_EQ(touch_calibrator_controller.touch_device_id_,
+            ui::InputDevice::kInvalidId);
+
+  base::Time current_timestamp = base::Time::Now();
+  touch_calibrator_controller.last_touch_timestamp_ =
+      current_timestamp - (TouchCalibratorController::kTouchIntervalThreshold);
+
+  GenerateTouchEvent(touch_display, touchdevice.id);
+  EXPECT_EQ(touch_calibrator_controller.touch_device_id_, touchdevice.id);
+
+  display::TouchCalibrationData::CalibrationPointPairQuad points = {
+      {std::make_pair(gfx::Point(10, 10), gfx::Point(11, 12)),
+       std::make_pair(gfx::Point(190, 10), gfx::Point(195, 8)),
+       std::make_pair(gfx::Point(10, 90), gfx::Point(12, 94)),
+       std::make_pair(gfx::Point(190, 90), gfx::Point(189, 88))}};
+  gfx::Size size(200, 100);
+  display::TouchCalibrationData calibration_data(points, size);
+
+  touch_calibrator_controller.CompleteCalibration(points, size);
+
+  const display::ManagedDisplayInfo& info =
+      display_manager()->GetDisplayInfo(touch_display.id());
+
+  uint32_t touch_device_identifier =
+      display::TouchCalibrationData::GenerateTouchDeviceIdentifier(
+          touchdevice.name, touchdevice.vendor_id, touchdevice.product_id);
+  EXPECT_TRUE(info.HasTouchCalibrationData(touch_device_identifier));
+  EXPECT_EQ(calibration_data,
+            info.GetTouchCalibrationData(touch_device_identifier));
+}
+
+TEST_F(TouchCalibratorControllerTest, CustomCalibrationInvalidTouchId) {
+  const Display& touch_display = InitDisplays();
+
+  TouchCalibratorController touch_calibrator_controller;
+  EXPECT_FALSE(touch_calibrator_controller.IsCalibrating());
+  EXPECT_FALSE(!!touch_calibrator_controller.touch_calibrator_views_.size());
+
+  touch_calibrator_controller.StartCalibration(
+      touch_display, true /* is_custom_calibbration */,
+      TouchCalibratorController::TouchCalibrationCallback());
+
+  EXPECT_TRUE(touch_calibrator_controller.IsCalibrating());
+  EXPECT_EQ(touch_calibrator_controller.state_,
+            TouchCalibratorController::CalibrationState::kCustomCalibration);
+
+  // Native touch calibration UX should not initialize during custom calibration
+  EXPECT_EQ(touch_calibrator_controller.touch_calibrator_views_.size(), 0UL);
+  EXPECT_EQ(touch_calibrator_controller.touch_device_id_,
+            ui::InputDevice::kInvalidId);
+
+  base::Time current_timestamp = base::Time::Now();
+  touch_calibrator_controller.last_touch_timestamp_ =
+      current_timestamp - (TouchCalibratorController::kTouchIntervalThreshold);
+
+  display::TouchCalibrationData::CalibrationPointPairQuad points = {
+      {std::make_pair(gfx::Point(10, 10), gfx::Point(11, 12)),
+       std::make_pair(gfx::Point(190, 10), gfx::Point(195, 8)),
+       std::make_pair(gfx::Point(10, 90), gfx::Point(12, 94)),
+       std::make_pair(gfx::Point(190, 90), gfx::Point(189, 88))}};
+  gfx::Size size(200, 100);
+  display::TouchCalibrationData calibration_data(points, size);
+
+  touch_calibrator_controller.CompleteCalibration(points, size);
+
+  const display::ManagedDisplayInfo& info =
+      display_manager()->GetDisplayInfo(touch_display.id());
+
+  uint32_t random_touch_device_identifier = 123456;
+  EXPECT_TRUE(info.HasTouchCalibrationData(random_touch_device_identifier));
+  EXPECT_EQ(calibration_data,
+            info.GetTouchCalibrationData(random_touch_device_identifier));
+}
+
 }  // namespace ash
diff --git a/ash/highlighter/highlighter_controller.cc b/ash/highlighter/highlighter_controller.cc
index 803d820e..b6b2ffc3 100644
--- a/ash/highlighter/highlighter_controller.cc
+++ b/ash/highlighter/highlighter_controller.cc
@@ -131,6 +131,7 @@
 
   aura::Window* current_window =
       highlighter_view_->GetWidget()->GetNativeWindow()->GetRootWindow();
+  const gfx::Rect bounds = current_window->bounds();
 
   const FastInkPoints& points = highlighter_view_->points();
   gfx::RectF box = points.GetBoundingBoxF();
@@ -145,8 +146,7 @@
     box = AdjustHorizontalStroke(box, HighlighterView::kPenTipSize);
   } else if (gesture_type == HighlighterGestureType::kClosedShape) {
     const float fraction =
-        box.width() * box.height() /
-        (current_window->bounds().width() * current_window->bounds().height());
+        box.width() * box.height() / (bounds.width() * bounds.height());
     UMA_HISTOGRAM_PERCENTAGE("Ash.Shelf.Palette.Assistant.CircledPercentage",
                              static_cast<int>(fraction * 100));
   }
@@ -157,17 +157,30 @@
                  base::Unretained(this)));
 
   if (gesture_type != HighlighterGestureType::kNotRecognized) {
-    if (observer_) {
-      observer_->HandleSelection(gfx::ToEnclosingRect(
-          gfx::ScaleRect(box, GetScreenshotScale(current_window))));
+    // |box| is not guaranteed to be inside the screen bounds, clip it.
+    // Not converting |box| to gfx::Rect here to avoid accumulating rounding
+    // errors, instead converting |bounds| to gfx::RectF.
+    box.Intersect(
+        gfx::RectF(bounds.x(), bounds.y(), bounds.width(), bounds.height()));
+    if (box.IsEmpty()) {
+      if (observer_)
+        observer_->HandleFailedSelection();
+    } else {
+      if (observer_) {
+        observer_->HandleSelection(gfx::ToEnclosingRect(
+            gfx::ScaleRect(box, GetScreenshotScale(current_window))));
+      }
+
+      result_view_ = base::MakeUnique<HighlighterResultView>(current_window);
+      result_view_->Animate(
+          box, gesture_type,
+          base::Bind(&HighlighterController::DestroyResultView,
+                     base::Unretained(this)));
+
+      recognized_gesture_counter_++;
     }
-
-    result_view_ = base::MakeUnique<HighlighterResultView>(current_window);
-    result_view_->Animate(box, gesture_type,
-                          base::Bind(&HighlighterController::DestroyResultView,
-                                     base::Unretained(this)));
-
-    recognized_gesture_counter_++;
+  } else if (observer_) {
+    observer_->HandleFailedSelection();
   }
 
   gesture_counter_++;
diff --git a/ash/highlighter/highlighter_controller_test_api.cc b/ash/highlighter/highlighter_controller_test_api.cc
index 485d776..3c863df 100644
--- a/ash/highlighter/highlighter_controller_test_api.cc
+++ b/ash/highlighter/highlighter_controller_test_api.cc
@@ -29,6 +29,8 @@
 }
 
 void HighlighterControllerTestApi::SimulateInterruptedStrokeTimeout() {
+  if (!instance_->interrupted_stroke_timer_)
+    return;
   instance_->interrupted_stroke_timer_->Stop();
   instance_->RecognizeGesture();
 }
@@ -61,6 +63,17 @@
 void HighlighterControllerTestApi::HandleSelection(const gfx::Rect& rect) {
   handle_selection_called_ = true;
   selection_ = rect;
+  // This is mimicking the logic implemented PaletteDelegateChromeOS,
+  // which should eventually move to HighlighterController (crbug/761120).
+  CallMetalayerDone();
+}
+
+void HighlighterControllerTestApi::HandleFailedSelection() {
+  handle_failed_selection_called_ = true;
+  // This is mimicking the logic implemented PaletteDelegateChromeOS,
+  // which should eventually move to HighlighterController (crbug/761120).
+  if (via_button_)
+    CallMetalayerDone();
 }
 
 }  // namespace ash
diff --git a/ash/highlighter/highlighter_controller_test_api.h b/ash/highlighter/highlighter_controller_test_api.h
index 734ef7eb1..8af31d7d 100644
--- a/ash/highlighter/highlighter_controller_test_api.h
+++ b/ash/highlighter/highlighter_controller_test_api.h
@@ -6,6 +6,7 @@
 #define ASH_HIGHLIGHTER_HIGHLIGHTER_CONTROLLER_TEST_API_H_
 
 #include "ash/highlighter/highlighter_selection_observer.h"
+#include "base/callback.h"
 #include "base/macros.h"
 #include "ui/gfx/geometry/rect.h"
 
@@ -22,6 +23,14 @@
   explicit HighlighterControllerTestApi(HighlighterController* instance);
   ~HighlighterControllerTestApi() override;
 
+  void SetMetalayerDone(base::OnceClosure done) {
+    metalayer_done_ = std::move(done);
+  }
+  void CallMetalayerDone() {
+    if (!metalayer_done_.is_null())
+      std::move(metalayer_done_).Run();
+  }
+  void SetViaButton(bool via_button) { via_button_ = via_button; }
   void SetEnabled(bool enabled);
   void DestroyPointerView();
   void SimulateInterruptedStrokeTimeout();
@@ -32,19 +41,30 @@
   const FastInkPoints& points() const;
   const FastInkPoints& predicted_points() const;
 
-  void ResetSelection() { handle_selection_called_ = false; }
+  void ResetSelection() {
+    handle_selection_called_ = false;
+    handle_failed_selection_called_ = false;
+  }
   bool handle_selection_called() const { return handle_selection_called_; }
+  bool handle_failed_selection_called() const {
+    return handle_failed_selection_called_;
+  }
   const gfx::Rect& selection() const { return selection_; }
 
  private:
   // HighlighterSelectionObserver:
   void HandleSelection(const gfx::Rect& rect) override;
+  void HandleFailedSelection() override;
 
   HighlighterController* instance_;
 
   bool handle_selection_called_ = false;
+  bool handle_failed_selection_called_ = false;
   gfx::Rect selection_;
 
+  base::OnceClosure metalayer_done_;
+  bool via_button_ = false;
+
   DISALLOW_COPY_AND_ASSIGN(HighlighterControllerTestApi);
 };
 
diff --git a/ash/highlighter/highlighter_controller_unittest.cc b/ash/highlighter/highlighter_controller_unittest.cc
index b3f4c84a..052f71a9 100644
--- a/ash/highlighter/highlighter_controller_unittest.cc
+++ b/ash/highlighter/highlighter_controller_unittest.cc
@@ -168,6 +168,7 @@
   GetEventGenerator().MoveTouch(gfx::Point(200, 200));
   GetEventGenerator().ReleaseTouch();
   EXPECT_FALSE(controller_test_api_->handle_selection_called());
+  EXPECT_TRUE(controller_test_api_->handle_failed_selection_called());
 
   // An almost horizontal stroke is recognized
   controller_test_api_->ResetSelection();
@@ -176,6 +177,7 @@
   GetEventGenerator().MoveTouch(gfx::Point(300, 102));
   GetEventGenerator().ReleaseTouch();
   EXPECT_TRUE(controller_test_api_->handle_selection_called());
+  EXPECT_FALSE(controller_test_api_->handle_failed_selection_called());
 
   // Horizontal stroke selection rectangle should:
   //   have the same horizontal center line as the stroke bounding box,
@@ -192,6 +194,7 @@
   GetEventGenerator().MoveTouch(gfx::Point(100, 100));
   GetEventGenerator().ReleaseTouch();
   EXPECT_FALSE(controller_test_api_->handle_selection_called());
+  EXPECT_TRUE(controller_test_api_->handle_failed_selection_called());
 
   // An almost closed G-like shape is recognized
   controller_test_api_->ResetSelection();
@@ -203,6 +206,7 @@
   GetEventGenerator().MoveTouch(gfx::Point(200, 20));
   GetEventGenerator().ReleaseTouch();
   EXPECT_TRUE(controller_test_api_->handle_selection_called());
+  EXPECT_FALSE(controller_test_api_->handle_failed_selection_called());
   EXPECT_EQ("0,0 200x100", controller_test_api_->selection().ToString());
 
   // A closed diamond shape is recognized
@@ -215,6 +219,7 @@
   GetEventGenerator().MoveTouch(gfx::Point(100, 50));
   GetEventGenerator().ReleaseTouch();
   EXPECT_TRUE(controller_test_api_->handle_selection_called());
+  EXPECT_FALSE(controller_test_api_->handle_failed_selection_called());
   EXPECT_EQ("0,50 200x200", controller_test_api_->selection().ToString());
 }
 
@@ -246,6 +251,7 @@
       controller_test_api_->ResetSelection();
       TraceRect(original_rect);
       EXPECT_TRUE(controller_test_api_->handle_selection_called());
+      EXPECT_FALSE(controller_test_api_->handle_failed_selection_called());
 
       const gfx::Rect selection = controller_test_api_->selection();
       EXPECT_TRUE(inflated.Contains(selection));
@@ -266,6 +272,7 @@
   controller_test_api_->ResetSelection();
   TraceRect(trace);
   EXPECT_TRUE(controller_test_api_->handle_selection_called());
+  EXPECT_FALSE(controller_test_api_->handle_failed_selection_called());
   EXPECT_EQ("200,100 400x300", controller_test_api_->selection().ToString());
 
   // Rotate to 90 degrees
@@ -273,6 +280,7 @@
   controller_test_api_->ResetSelection();
   TraceRect(trace);
   EXPECT_TRUE(controller_test_api_->handle_selection_called());
+  EXPECT_FALSE(controller_test_api_->handle_failed_selection_called());
   EXPECT_EQ("100,900 300x400", controller_test_api_->selection().ToString());
 
   // Rotate to 180 degrees
@@ -280,6 +288,7 @@
   controller_test_api_->ResetSelection();
   TraceRect(trace);
   EXPECT_TRUE(controller_test_api_->handle_selection_called());
+  EXPECT_FALSE(controller_test_api_->handle_failed_selection_called());
   EXPECT_EQ("900,600 400x300", controller_test_api_->selection().ToString());
 
   // Rotate to 270 degrees
@@ -287,6 +296,7 @@
   controller_test_api_->ResetSelection();
   TraceRect(trace);
   EXPECT_TRUE(controller_test_api_->handle_selection_called());
+  EXPECT_FALSE(controller_test_api_->handle_failed_selection_called());
   EXPECT_EQ("600,200 300x400", controller_test_api_->selection().ToString());
 }
 
@@ -307,6 +317,7 @@
   GetEventGenerator().ReleaseTouch();
   EXPECT_TRUE(controller_test_api_->IsWaitingToResumeStroke());
   EXPECT_FALSE(controller_test_api_->handle_selection_called());
+  EXPECT_FALSE(controller_test_api_->handle_failed_selection_called());
   EXPECT_FALSE(controller_test_api_->IsFadingAway());
 
   GetEventGenerator().MoveTouch(gfx::Point(0, 200));
@@ -315,6 +326,7 @@
   GetEventGenerator().ReleaseTouch();
   EXPECT_FALSE(controller_test_api_->IsWaitingToResumeStroke());
   EXPECT_TRUE(controller_test_api_->handle_selection_called());
+  EXPECT_FALSE(controller_test_api_->handle_failed_selection_called());
   EXPECT_EQ("0,100 300x100", controller_test_api_->selection().ToString());
 
   // Repeat the same gesture, but simulate a timeout after the gap. This should
@@ -326,12 +338,94 @@
   GetEventGenerator().ReleaseTouch();
   EXPECT_TRUE(controller_test_api_->IsWaitingToResumeStroke());
   EXPECT_FALSE(controller_test_api_->handle_selection_called());
+  EXPECT_FALSE(controller_test_api_->handle_failed_selection_called());
   EXPECT_FALSE(controller_test_api_->IsFadingAway());
 
   controller_test_api_->SimulateInterruptedStrokeTimeout();
   EXPECT_FALSE(controller_test_api_->IsWaitingToResumeStroke());
   EXPECT_TRUE(controller_test_api_->handle_selection_called());
+  EXPECT_FALSE(controller_test_api_->handle_failed_selection_called());
   EXPECT_TRUE(controller_test_api_->IsFadingAway());
 }
 
+// Test that the selection is never crossing the screen bounds.
+TEST_F(HighlighterControllerTest, SelectionInsideScreen) {
+  controller_test_api_->SetEnabled(true);
+  GetEventGenerator().EnterPenPointerMode();
+
+  constexpr float display_scales[] = {1.f, 1.5f, 2.0f};
+
+  for (size_t i = 0; i < sizeof(display_scales) / sizeof(float); ++i) {
+    std::string display_spec =
+        base::StringPrintf("1000x1000*%.2f", display_scales[i]);
+    SCOPED_TRACE(display_spec);
+    UpdateDisplay(display_spec);
+
+    const gfx::Rect screen(0, 0, 1000, 1000);
+
+    // Rectangle completely offscreen.
+    controller_test_api_->ResetSelection();
+    TraceRect(gfx::Rect(-100, -100, 10, 10));
+    controller_test_api_->SimulateInterruptedStrokeTimeout();
+    EXPECT_TRUE(controller_test_api_->handle_failed_selection_called());
+
+    // Rectangle crossing the left edge.
+    controller_test_api_->ResetSelection();
+    TraceRect(gfx::Rect(-100, 100, 200, 200));
+    controller_test_api_->SimulateInterruptedStrokeTimeout();
+    EXPECT_TRUE(controller_test_api_->handle_selection_called());
+    EXPECT_TRUE(screen.Contains(controller_test_api_->selection()));
+
+    // Rectangle crossing the top edge.
+    controller_test_api_->ResetSelection();
+    TraceRect(gfx::Rect(100, -100, 200, 200));
+    controller_test_api_->SimulateInterruptedStrokeTimeout();
+    EXPECT_TRUE(controller_test_api_->handle_selection_called());
+    EXPECT_TRUE(screen.Contains(controller_test_api_->selection()));
+
+    // Rectangle crossing the right edge.
+    controller_test_api_->ResetSelection();
+    TraceRect(gfx::Rect(900, 100, 200, 200));
+    controller_test_api_->SimulateInterruptedStrokeTimeout();
+    EXPECT_TRUE(controller_test_api_->handle_selection_called());
+    EXPECT_TRUE(screen.Contains(controller_test_api_->selection()));
+
+    // Rectangle crossing the bottom edge.
+    controller_test_api_->ResetSelection();
+    TraceRect(gfx::Rect(100, 900, 200, 200));
+    controller_test_api_->SimulateInterruptedStrokeTimeout();
+    EXPECT_TRUE(controller_test_api_->handle_selection_called());
+    EXPECT_TRUE(screen.Contains(controller_test_api_->selection()));
+
+    // Horizontal stroke completely offscreen.
+    controller_test_api_->ResetSelection();
+    GetEventGenerator().MoveTouch(gfx::Point(0, -100));
+    GetEventGenerator().PressTouch();
+    GetEventGenerator().MoveTouch(gfx::Point(1000, -100));
+    GetEventGenerator().ReleaseTouch();
+    controller_test_api_->SimulateInterruptedStrokeTimeout();
+    EXPECT_TRUE(controller_test_api_->handle_failed_selection_called());
+
+    // Horizontal stroke along the top edge of the screen.
+    controller_test_api_->ResetSelection();
+    GetEventGenerator().MoveTouch(gfx::Point(0, 0));
+    GetEventGenerator().PressTouch();
+    GetEventGenerator().MoveTouch(gfx::Point(1000, 0));
+    GetEventGenerator().ReleaseTouch();
+    controller_test_api_->SimulateInterruptedStrokeTimeout();
+    EXPECT_TRUE(controller_test_api_->handle_selection_called());
+    EXPECT_TRUE(screen.Contains(controller_test_api_->selection()));
+
+    // Horizontal stroke along the bottom edge of the screen.
+    controller_test_api_->ResetSelection();
+    GetEventGenerator().MoveTouch(gfx::Point(0, 999));
+    GetEventGenerator().PressTouch();
+    GetEventGenerator().MoveTouch(gfx::Point(1000, 999));
+    GetEventGenerator().ReleaseTouch();
+    controller_test_api_->SimulateInterruptedStrokeTimeout();
+    EXPECT_TRUE(controller_test_api_->handle_selection_called());
+    EXPECT_TRUE(screen.Contains(controller_test_api_->selection()));
+  }
+}
+
 }  // namespace ash
diff --git a/ash/highlighter/highlighter_selection_observer.h b/ash/highlighter/highlighter_selection_observer.h
index 871f4b3..67f12032c 100644
--- a/ash/highlighter/highlighter_selection_observer.h
+++ b/ash/highlighter/highlighter_selection_observer.h
@@ -16,7 +16,10 @@
  public:
   virtual ~HighlighterSelectionObserver() {}
 
+  // |rect| is the selected rectangle in screen pixes, clipped to screen bounds
+  // if necessary.
   virtual void HandleSelection(const gfx::Rect& rect) = 0;
+  virtual void HandleFailedSelection() = 0;
 };
 
 }  // namespace ash
diff --git a/ash/login/ui/login_password_view.cc b/ash/login/ui/login_password_view.cc
index 7dbc91e4..28c3579f 100644
--- a/ash/login/ui/login_password_view.cc
+++ b/ash/login/ui/login_password_view.cc
@@ -46,6 +46,9 @@
 // Distance between the last password dot and the submit arrow/button.
 constexpr int kDistanceBetweenPasswordAndSubmitDp = 0;
 
+// The character used for displaying obscured password text.
+constexpr base::char16 kPasswordReplacementChar = 0x2219;
+
 constexpr const char kLoginPasswordViewName[] = "LoginPasswordView";
 
 class NonAccessibleSeparator : public views::Separator {
@@ -104,6 +107,7 @@
   textfield_->set_placeholder_text(base::ASCIIToUTF16("Password (FIXME)"));
   textfield_->SetBorder(nullptr);
   textfield_->SetBackgroundColor(SK_ColorTRANSPARENT);
+  textfield_->SetPasswordReplacementChar(kPasswordReplacementChar);
 
   textfield_sizer->AddChildView(textfield_);
   row->AddChildView(textfield_sizer);
diff --git a/ash/message_center/notifier_settings_view.cc b/ash/message_center/notifier_settings_view.cc
index cde9164..87df763 100644
--- a/ash/message_center/notifier_settings_view.cc
+++ b/ash/message_center/notifier_settings_view.cc
@@ -18,7 +18,6 @@
 #include "skia/ext/image_operations.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/base/models/combobox_model.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/events/event_utils.h"
 #include "ui/events/keycodes/keyboard_codes.h"
@@ -27,12 +26,12 @@
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/image/image.h"
 #include "ui/message_center/public/cpp/message_center_constants.h"
+#include "ui/message_center/vector_icons.h"
 #include "ui/resources/grit/ui_resources.h"
 #include "ui/views/background.h"
 #include "ui/views/border.h"
 #include "ui/views/controls/button/checkbox.h"
 #include "ui/views/controls/button/label_button_border.h"
-#include "ui/views/controls/combobox/combobox.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/controls/link.h"
@@ -201,40 +200,6 @@
   SchedulePaint();
 }
 
-// NotifierGroupComboboxModel --------------------------------------------------
-
-class NotifierGroupComboboxModel : public ui::ComboboxModel {
- public:
-  explicit NotifierGroupComboboxModel(
-      NotifierSettingsProvider* notifier_settings_provider);
-  ~NotifierGroupComboboxModel() override;
-
-  // ui::ComboboxModel:
-  int GetItemCount() const override;
-  base::string16 GetItemAt(int index) override;
-
- private:
-  NotifierSettingsProvider* notifier_settings_provider_;
-
-  DISALLOW_COPY_AND_ASSIGN(NotifierGroupComboboxModel);
-};
-
-NotifierGroupComboboxModel::NotifierGroupComboboxModel(
-    NotifierSettingsProvider* notifier_settings_provider)
-    : notifier_settings_provider_(notifier_settings_provider) {}
-
-NotifierGroupComboboxModel::~NotifierGroupComboboxModel() {}
-
-int NotifierGroupComboboxModel::GetItemCount() const {
-  return notifier_settings_provider_->GetNotifierGroupCount();
-}
-
-base::string16 NotifierGroupComboboxModel::GetItemAt(int index) {
-  const NotifierGroup& group =
-      notifier_settings_provider_->GetNotifierGroupAt(index);
-  return group.login_info.empty() ? group.name : group.login_info;
-}
-
 }  // namespace
 
 // NotifierSettingsView::NotifierButton ---------------------------------------
@@ -255,10 +220,6 @@
   DCHECK(provider_);
   DCHECK(notifier_);
 
-  // Since there may never be an icon (but that could change at a later time),
-  // we own the icon view here.
-  icon_view_->set_owned_by_client();
-
   checkbox_->SetChecked(notifier_->enabled);
   checkbox_->set_listener(this);
   checkbox_->SetFocusBehavior(FocusBehavior::NEVER);
@@ -300,15 +261,15 @@
 
 void NotifierSettingsView::NotifierButton::UpdateIconImage(
     const gfx::Image& icon) {
-  bool has_icon_view = false;
-
   notifier_->icon = icon;
-  if (!icon.IsEmpty()) {
+  if (icon.IsEmpty()) {
+    icon_view_->SetImage(gfx::CreateVectorIcon(
+        message_center::kProductIcon, kEntryIconSize, gfx::kChromeIconGrey));
+  } else {
     icon_view_->SetImage(icon.ToImageSkia());
     icon_view_->SetImageSize(gfx::Size(kEntryIconSize, kEntryIconSize));
-    has_icon_view = true;
   }
-  GridChanged(ShouldHaveLearnMoreButton(), has_icon_view);
+  GridChanged(ShouldHaveLearnMoreButton());
 }
 
 void NotifierSettingsView::NotifierButton::SetChecked(bool checked) {
@@ -366,8 +327,7 @@
   return provider_->NotifierHasAdvancedSettings(notifier_->notifier_id);
 }
 
-void NotifierSettingsView::NotifierButton::GridChanged(bool has_learn_more,
-                                                       bool has_icon_view) {
+void NotifierSettingsView::NotifierButton::GridChanged(bool has_learn_more) {
   using views::ColumnSet;
   using views::GridLayout;
 
@@ -379,12 +339,10 @@
                 kComputedCheckboxSize, 0);
   cs->AddPaddingColumn(0, kInternalHorizontalSpacing);
 
-  if (has_icon_view) {
-    // Add a column for the icon.
-    cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, GridLayout::FIXED,
-                  kEntryIconSize, 0);
-    cs->AddPaddingColumn(0, kInternalHorizontalSpacing);
-  }
+  // Add a column for the icon.
+  cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, GridLayout::FIXED,
+                kEntryIconSize, 0);
+  cs->AddPaddingColumn(0, kInternalHorizontalSpacing);
 
   // Add a column for the name.
   cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
@@ -402,8 +360,7 @@
 
   layout->StartRow(0, 0);
   layout->AddView(checkbox_);
-  if (has_icon_view)
-    layout->AddView(icon_view_.get());
+  layout->AddView(icon_view_);
   layout->AddView(name_view_);
   if (has_learn_more)
     layout->AddView(learn_more_);
@@ -416,7 +373,6 @@
 NotifierSettingsView::NotifierSettingsView(NotifierSettingsProvider* provider)
     : title_arrow_(nullptr),
       title_label_(nullptr),
-      notifier_group_combobox_(nullptr),
       scroller_(nullptr),
       provider_(provider) {
   // |provider_| may be null in tests.
@@ -505,32 +461,6 @@
   top_label->SetMultiLine(true);
 
   contents_title_view->AddChildView(top_label);
-
-  // TODO(estade): remove this; there's only ever one notifier group in ash.
-  bool need_account_switcher =
-      provider_ && provider_->GetNotifierGroupCount() > 1;
-  if (need_account_switcher) {
-    const NotifierGroup& active_group = provider_->GetActiveNotifierGroup();
-    base::string16 notifier_group_text = active_group.login_info.empty()
-                                             ? active_group.name
-                                             : active_group.login_info;
-    notifier_group_model_.reset(new NotifierGroupComboboxModel(provider_));
-    notifier_group_combobox_ = new views::Combobox(notifier_group_model_.get());
-    notifier_group_combobox_->set_listener(this);
-
-    // Move the combobox over enough to align with the checkboxes.
-    views::View* combobox_spacer = new views::View();
-    combobox_spacer->SetLayoutManager(new views::FillLayout());
-    int padding = views::LabelButtonAssetBorder::GetDefaultInsetsForStyle(
-                      views::LabelButton::STYLE_TEXTBUTTON)
-                      .left() -
-                  notifier_group_combobox_->border()->GetInsets().left();
-    combobox_spacer->SetBorder(views::CreateEmptyBorder(0, padding, 0, 0));
-    combobox_spacer->AddChildView(notifier_group_combobox_);
-
-    contents_title_view->AddChildView(combobox_spacer);
-  }
-
   contents_view->AddChildView(contents_title_view);
 
   size_t notifier_count = notifiers.size();
@@ -625,10 +555,4 @@
                                   (*iter)->checked());
 }
 
-void NotifierSettingsView::OnPerformAction(views::Combobox* combobox) {
-  provider_->SwitchToNotifierGroup(combobox->selected_index());
-  MessageCenterView* center_view = static_cast<MessageCenterView*>(parent());
-  center_view->OnSettingsChanged();
-}
-
 }  // namespace ash
diff --git a/ash/message_center/notifier_settings_view.h b/ash/message_center/notifier_settings_view.h
index d3a067b6..fe9531a 100644
--- a/ash/message_center/notifier_settings_view.h
+++ b/ash/message_center/notifier_settings_view.h
@@ -14,16 +14,10 @@
 #include "ui/message_center/notifier_settings.h"
 #include "ui/views/controls/button/checkbox.h"
 #include "ui/views/controls/button/image_button.h"
-#include "ui/views/controls/combobox/combobox_listener.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/view.h"
 
-namespace ui {
-class ComboboxModel;
-}
-
 namespace views {
-class Combobox;
 class Label;
 }  // namespace views
 
@@ -34,8 +28,7 @@
 class ASH_EXPORT NotifierSettingsView
     : public message_center::NotifierSettingsObserver,
       public views::View,
-      public views::ButtonListener,
-      public views::ComboboxListener {
+      public views::ButtonListener {
  public:
   explicit NotifierSettingsView(
       message_center::NotifierSettingsProvider* provider);
@@ -81,13 +74,11 @@
     bool ShouldHaveLearnMoreButton() const;
     // Helper function to reset the layout when the view has substantially
     // changed.
-    void GridChanged(bool has_learn_more, bool has_icon_view);
+    void GridChanged(bool has_learn_more);
 
     message_center::NotifierSettingsProvider* provider_;  // Weak.
     std::unique_ptr<message_center::Notifier> notifier_;
-    // |icon_view_| is owned by us because sometimes we don't leave it
-    // in the view hierarchy.
-    std::unique_ptr<views::ImageView> icon_view_;
+    views::ImageView* icon_view_;
     views::Label* name_view_;
     views::Checkbox* checkbox_;
     views::ImageButton* learn_more_;
@@ -109,19 +100,14 @@
   // Overridden from views::ButtonListener:
   void ButtonPressed(views::Button* sender, const ui::Event& event) override;
 
-  // Overridden from views::ComboboxListener:
-  void OnPerformAction(views::Combobox* combobox) override;
-
   // Callback for views::MenuModelAdapter.
   void OnMenuClosed();
 
   views::ImageButton* title_arrow_;
   views::Label* title_label_;
-  views::Combobox* notifier_group_combobox_;
   views::ScrollView* scroller_;
   message_center::NotifierSettingsProvider* provider_;
   std::set<NotifierButton*> buttons_;
-  std::unique_ptr<ui::ComboboxModel> notifier_group_model_;
 
   DISALLOW_COPY_AND_ASSIGN(NotifierSettingsView);
 };
diff --git a/ash/mus/manifest.json b/ash/mus/manifest.json
index b154e4b8..5570cb4e 100644
--- a/ash/mus/manifest.json
+++ b/ash/mus/manifest.json
@@ -1,6 +1,7 @@
 {
   "name": "ash",
   "display_name": "Ash Window Manager and Shell",
+  "sandbox_type": "none",
   "interface_provider_specs": {
     "service_manager:connector": {
       "provides": {
diff --git a/ash/mus/shell_delegate_mus.cc b/ash/mus/shell_delegate_mus.cc
index 40cd4a6..a8c873b0 100644
--- a/ash/mus/shell_delegate_mus.cc
+++ b/ash/mus/shell_delegate_mus.cc
@@ -29,11 +29,6 @@
   return connector_;
 }
 
-bool ShellDelegateMus::IsIncognitoAllowed() const {
-  NOTIMPLEMENTED();
-  return false;
-}
-
 bool ShellDelegateMus::IsRunningInForcedAppMode() const {
   NOTIMPLEMENTED();
   return false;
diff --git a/ash/mus/shell_delegate_mus.h b/ash/mus/shell_delegate_mus.h
index 6f70387..0470ca6 100644
--- a/ash/mus/shell_delegate_mus.h
+++ b/ash/mus/shell_delegate_mus.h
@@ -23,7 +23,6 @@
 
   // ShellDelegate:
   service_manager::Connector* GetShellConnector() const override;
-  bool IsIncognitoAllowed() const override;
   bool IsRunningInForcedAppMode() const override;
   bool CanShowWindowForUser(aura::Window* window) const override;
   bool IsForceMaximizeOnFirstRun() const override;
diff --git a/ash/palette_delegate.h b/ash/palette_delegate.h
index 9401eb2..518e88c5 100644
--- a/ash/palette_delegate.h
+++ b/ash/palette_delegate.h
@@ -56,8 +56,9 @@
   virtual void CancelPartialScreenshot() = 0;
 
   // Shows the metalayer. |done| is called when the metalayer session has
-  // finished.
-  virtual void ShowMetalayer(base::OnceClosure done) = 0;
+  // finished. |via_button| is true if metalayer is invoked via a hardware
+  // stylus button.
+  virtual void ShowMetalayer(base::OnceClosure done, bool via_button) = 0;
 
   // Hides the metalayer.
   virtual void HideMetalayer() = 0;
diff --git a/ash/shelf/shelf_controller.cc b/ash/shelf/shelf_controller.cc
index b5ff7b5..caa86482 100644
--- a/ash/shelf/shelf_controller.cc
+++ b/ash/shelf/shelf_controller.cc
@@ -201,9 +201,11 @@
   DCHECK_GT(index, 0) << " Items can not precede the AppList";
   DCHECK_LT(index, model_.item_count()) << " Index out of bounds";
   index = std::min(std::max(index, 1), model_.item_count() - 1);
-  DCHECK_NE(current_index, index) << " The item is already at the given index";
-  if (current_index == index)
+  if (current_index == index) {
+    DVLOG(1) << "The item is already at the given index (" << index << "). "
+             << "This happens when syncing a ShelfModel weight reordering.";
     return;
+  }
   base::AutoReset<bool> reset(&applying_remote_shelf_model_changes_, true);
   model_.Move(current_index, index);
 }
diff --git a/ash/shelf/shelf_controller.h b/ash/shelf/shelf_controller.h
index ef91ba1..f1bf744 100644
--- a/ash/shelf/shelf_controller.h
+++ b/ash/shelf/shelf_controller.h
@@ -39,6 +39,10 @@
 
   ShelfModel* model() { return &model_; }
 
+  bool should_synchronize_shelf_models() const {
+    return should_synchronize_shelf_models_;
+  }
+
   // mojom::ShelfController:
   void AddObserver(mojom::ShelfObserverAssociatedPtrInfo observer) override;
   void AddShelfItem(int32_t index, const ShelfItem& item) override;
diff --git a/ash/shelf/shelf_controller_unittest.cc b/ash/shelf/shelf_controller_unittest.cc
index b4bc2743..794f7fe5 100644
--- a/ash/shelf/shelf_controller_unittest.cc
+++ b/ash/shelf/shelf_controller_unittest.cc
@@ -65,11 +65,11 @@
   EXPECT_TRUE(model->GetShelfItemDelegate(ShelfID(kAppListId)));
 }
 
-TEST_F(ShelfControllerTest, ShelfModelChangesInClassicAsh) {
-  if (Shell::GetAshConfig() == Config::MASH)
+TEST_F(ShelfControllerTest, ShelfModelChangesWithoutSync) {
+  ShelfController* controller = Shell::Get()->shelf_controller();
+  if (controller->should_synchronize_shelf_models())
     return;
 
-  ShelfController* controller = Shell::Get()->shelf_controller();
   TestShelfObserver observer;
   mojom::ShelfObserverAssociatedPtr observer_ptr;
   mojo::AssociatedBinding<mojom::ShelfObserver> binding(
@@ -77,12 +77,12 @@
   controller->AddObserver(observer_ptr.PassInterface());
 
   // The ShelfModel should be initialized with a single item for the AppList.
-  // In classic ash, the observer should not be notified of ShelfModel changes.
+  // Without syncing, the observer should not be notified of ShelfModel changes.
   EXPECT_EQ(1, controller->model()->item_count());
   EXPECT_EQ(0u, observer.added_count());
   EXPECT_EQ(0u, observer.removed_count());
 
-  // Add a ShelfModel item; |observer| should not be notified in classic ash.
+  // Add a ShelfModel item; |observer| should not be notified without sync.
   ShelfItem item;
   item.type = TYPE_PINNED_APP;
   item.id = ShelfID("foo");
@@ -92,7 +92,7 @@
   EXPECT_EQ(0u, observer.added_count());
   EXPECT_EQ(0u, observer.removed_count());
 
-  // Remove a ShelfModel item; |observer| should not be notified in classic ash.
+  // Remove a ShelfModel item; |observer| should not be notified without sync.
   controller->model()->RemoveItemAt(index);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1, controller->model()->item_count());
@@ -100,11 +100,11 @@
   EXPECT_EQ(0u, observer.removed_count());
 }
 
-TEST_F(ShelfControllerTest, ShelfModelChangesInMash) {
-  if (Shell::GetAshConfig() != Config::MASH)
+TEST_F(ShelfControllerTest, ShelfModelChangesWithSync) {
+  ShelfController* controller = Shell::Get()->shelf_controller();
+  if (!controller->should_synchronize_shelf_models())
     return;
 
-  ShelfController* controller = Shell::Get()->shelf_controller();
   TestShelfObserver observer;
   mojom::ShelfObserverAssociatedPtr observer_ptr;
   mojo::AssociatedBinding<mojom::ShelfObserver> binding(
@@ -113,12 +113,12 @@
   base::RunLoop().RunUntilIdle();
 
   // The ShelfModel should be initialized with a single item for the AppList.
-  // In mash, the observer is immediately notified of existing shelf items.
+  // When syncing, the observer is immediately notified of existing shelf items.
   EXPECT_EQ(1, controller->model()->item_count());
   EXPECT_EQ(1u, observer.added_count());
   EXPECT_EQ(0u, observer.removed_count());
 
-  // Add a ShelfModel item; |observer| should be notified in mash.
+  // Add a ShelfModel item; |observer| should be notified when syncing.
   ShelfItem item;
   item.type = TYPE_PINNED_APP;
   item.id = ShelfID("foo");
@@ -128,7 +128,7 @@
   EXPECT_EQ(2u, observer.added_count());
   EXPECT_EQ(0u, observer.removed_count());
 
-  // Remove a ShelfModel item; |observer| should be notified in mash.
+  // Remove a ShelfModel item; |observer| should be notified when syncing.
   controller->model()->RemoveItemAt(index);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1, controller->model()->item_count());
diff --git a/ash/shell/shell_delegate_impl.cc b/ash/shell/shell_delegate_impl.cc
index f419078..5b8b374 100644
--- a/ash/shell/shell_delegate_impl.cc
+++ b/ash/shell/shell_delegate_impl.cc
@@ -50,7 +50,7 @@
       done.Run();
   }
   void CancelPartialScreenshot() override {}
-  void ShowMetalayer(base::OnceClosure done) override {}
+  void ShowMetalayer(base::OnceClosure done, bool via_button) override {}
   void HideMetalayer() override {}
 
  private:
@@ -67,10 +67,6 @@
   return nullptr;
 }
 
-bool ShellDelegateImpl::IsIncognitoAllowed() const {
-  return true;
-}
-
 bool ShellDelegateImpl::IsRunningInForcedAppMode() const {
   return false;
 }
diff --git a/ash/shell/shell_delegate_impl.h b/ash/shell/shell_delegate_impl.h
index f58723b..6e1b3cfc 100644
--- a/ash/shell/shell_delegate_impl.h
+++ b/ash/shell/shell_delegate_impl.h
@@ -25,7 +25,6 @@
 
   // ShellDelegate:
   ::service_manager::Connector* GetShellConnector() const override;
-  bool IsIncognitoAllowed() const override;
   bool IsRunningInForcedAppMode() const override;
   bool CanShowWindowForUser(aura::Window* window) const override;
   bool IsForceMaximizeOnFirstRun() const override;
diff --git a/ash/shell_delegate.h b/ash/shell_delegate.h
index ca27763..4fa5109 100644
--- a/ash/shell_delegate.h
+++ b/ash/shell_delegate.h
@@ -51,10 +51,6 @@
   // Returns the connector for the mojo service manager. Returns null in tests.
   virtual service_manager::Connector* GetShellConnector() const = 0;
 
-  // Returns true if incognito mode is allowed for the user.
-  // Incognito windows are restricted for supervised users.
-  virtual bool IsIncognitoAllowed() const = 0;
-
   // Returns true if we're running in forced app mode.
   virtual bool IsRunningInForcedAppMode() const = 0;
 
diff --git a/ash/system/palette/palette_tray_unittest.cc b/ash/system/palette/palette_tray_unittest.cc
index 2075bb3..81b1d2d 100644
--- a/ash/system/palette/palette_tray_unittest.cc
+++ b/ash/system/palette/palette_tray_unittest.cc
@@ -291,11 +291,10 @@
                            expected_on_press);
   }
 
-  void DestroyPointerView() { highlighter_test_api_->DestroyPointerView(); }
+  std::unique_ptr<HighlighterControllerTestApi> highlighter_test_api_;
 
  private:
   std::unique_ptr<HighlighterController> highlighter_controller_;
-  std::unique_ptr<HighlighterControllerTestApi> highlighter_test_api_;
 
   // Owned by |ui|.
   base::SimpleTestTickClock* simulated_clock_ = nullptr;
@@ -334,13 +333,33 @@
   EXPECT_FALSE(highlighter_showing());
 
   // Press/drag over a regular (non-palette) location. This should activate the
-  // highlighter.
+  // highlighter. Note that a diagonal stroke does not create a valid selection.
+  highlighter_test_api_->ResetSelection();
   DragAndAssertMetalayer("tool enabled", origin, ui::EF_NONE,
-                         true /* enables metalayer */,
+                         true /* metalayer stays enabled after the press */,
                          true /* highlighter shown on press */);
+  // When metalayer is entered normally (not via stylus button), a failed
+  // selection should not exit the mode.
+  // NOTE that this is not testing the real logic in PaletteDelegateChromeOS,
+  // but the logic in HighlighterControllerTestApi (which is mimicking
+  // PaletteDelegateChromeOS). Once PaletteDelegateChromeOS is refactored
+  // (crbug/761120) the assertions below become more useful.
+  EXPECT_TRUE(highlighter_test_api_->handle_failed_selection_called());
+  EXPECT_TRUE(metalayer_enabled());
+
+  // A successfull selection should exit the metalayer mode.
+  SCOPED_TRACE("horizontal stroke");
+  highlighter_test_api_->ResetSelection();
+  generator.MoveTouch(gfx::Point(100, 100));
+  generator.PressTouch();
+  EXPECT_TRUE(metalayer_enabled());
+  generator.MoveTouch(gfx::Point(300, 100));
+  generator.ReleaseTouch();
+  EXPECT_TRUE(highlighter_test_api_->handle_selection_called());
+  EXPECT_FALSE(metalayer_enabled());
 
   SCOPED_TRACE("drag over palette");
-  DestroyPointerView();
+  highlighter_test_api_->DestroyPointerView();
   // Press/drag over the palette button. This should not activate the
   // highlighter, but should disable the palette tool instead.
   gfx::Point palette_point = palette_tray_->GetBoundsInScreen().CenterPoint();
@@ -439,6 +458,8 @@
   WaitDragAndAssertMetalayer("with button", origin, ui::EF_LEFT_MOUSE_BUTTON,
                              true /* enables metalayer */,
                              false /* no highlighter on press */);
+  // Metalayer mode entered via the stylus button should not be sticky.
+  EXPECT_FALSE(metalayer_enabled());
 
   // Repeat the previous step without a pause, make sure that the palette tool
   // is not toggled, and the highlighter is enabled immediately.
@@ -452,7 +473,7 @@
       true /* enables metalayer */, true /* highlighter shown on press */);
 
   // The barrel button should not work on the lock screen.
-  DestroyPointerView();
+  highlighter_test_api_->DestroyPointerView();
   GetSessionControllerClient()->RequestLockScreen();
   EXPECT_FALSE(test_api_->GetPaletteToolManager()->IsToolActive(
       PaletteToolId::METALAYER));
@@ -472,7 +493,7 @@
   EXPECT_FALSE(test_api_->GetPaletteToolManager()->IsToolActive(
       PaletteToolId::METALAYER));
 
-  DestroyPointerView();
+  highlighter_test_api_->DestroyPointerView();
   EXPECT_FALSE(highlighter_showing());
   DragAndAssertMetalayer("disabled", origin, ui::EF_LEFT_MOUSE_BUTTON,
                          false /* no metalayer */,
diff --git a/ash/system/palette/test_palette_delegate.cc b/ash/system/palette/test_palette_delegate.cc
index aeceaca..732d4941 100644
--- a/ash/system/palette/test_palette_delegate.cc
+++ b/ash/system/palette/test_palette_delegate.cc
@@ -47,11 +47,14 @@
 
 void TestPaletteDelegate::CancelPartialScreenshot() {}
 
-void TestPaletteDelegate::ShowMetalayer(base::OnceClosure done) {
-  metalayer_done_ = std::move(done);
+void TestPaletteDelegate::ShowMetalayer(base::OnceClosure done,
+                                        bool via_button) {
   ++show_metalayer_count_;
-  if (highlighter_test_api_)
+  if (highlighter_test_api_) {
+    highlighter_test_api_->SetMetalayerDone(std::move(done));
+    highlighter_test_api_->SetViaButton(via_button);
     highlighter_test_api_->SetEnabled(true);
+  }
 }
 
 void TestPaletteDelegate::HideMetalayer() {
diff --git a/ash/system/palette/test_palette_delegate.h b/ash/system/palette/test_palette_delegate.h
index c46f0af..7d63ca1 100644
--- a/ash/system/palette/test_palette_delegate.h
+++ b/ash/system/palette/test_palette_delegate.h
@@ -46,8 +46,6 @@
 
   int hide_metalayer_count() const { return hide_metalayer_count_; }
 
-  void CallMetalayerDone() { std::move(metalayer_done_).Run(); }
-
   void set_highlighter_test_api(HighlighterControllerTestApi* api) {
     highlighter_test_api_ = api;
   }
@@ -63,7 +61,7 @@
   void TakeScreenshot() override;
   void TakePartialScreenshot(const base::Closure& done) override;
   void CancelPartialScreenshot() override;
-  void ShowMetalayer(base::OnceClosure done) override;
+  void ShowMetalayer(base::OnceClosure done, bool via_button) override;
   void HideMetalayer() override;
 
   int create_note_count_ = 0;
@@ -76,7 +74,6 @@
   bool should_show_palette_ = false;
   int show_metalayer_count_ = 0;
   int hide_metalayer_count_ = 0;
-  base::OnceClosure metalayer_done_;
 
   HighlighterControllerTestApi* highlighter_test_api_ = nullptr;
 
diff --git a/ash/system/palette/tools/metalayer_mode.cc b/ash/system/palette/tools/metalayer_mode.cc
index c25287d..edbd31a 100644
--- a/ash/system/palette/tools/metalayer_mode.cc
+++ b/ash/system/palette/tools/metalayer_mode.cc
@@ -56,8 +56,10 @@
 void MetalayerMode::OnEnable() {
   CommonPaletteTool::OnEnable();
 
-  Shell::Get()->palette_delegate()->ShowMetalayer(base::BindOnce(
-      &MetalayerMode::OnMetalayerSessionComplete, weak_factory_.GetWeakPtr()));
+  Shell::Get()->palette_delegate()->ShowMetalayer(
+      base::BindOnce(&MetalayerMode::OnMetalayerSessionComplete,
+                     weak_factory_.GetWeakPtr()),
+      activated_via_button_);
   delegate()->HidePalette();
 }
 
@@ -65,6 +67,7 @@
   CommonPaletteTool::OnDisable();
 
   Shell::Get()->palette_delegate()->HideMetalayer();
+  activated_via_button_ = false;
 }
 
 const gfx::VectorIcon& MetalayerMode::GetActiveTrayIcon() const {
@@ -130,6 +133,7 @@
     delegate()->RecordPaletteOptionsUsage(
         PaletteToolIdToPaletteTrayOptions(GetToolId()),
         PaletteInvocationMethod::SHORTCUT);
+    activated_via_button_ = true;
     delegate()->EnableTool(GetToolId());
   }
   event->StopPropagation();
diff --git a/ash/system/palette/tools/metalayer_mode.h b/ash/system/palette/tools/metalayer_mode.h
index 2e080b0..d43dd8f 100644
--- a/ash/system/palette/tools/metalayer_mode.h
+++ b/ash/system/palette/tools/metalayer_mode.h
@@ -85,6 +85,9 @@
 
   base::TimeTicks previous_stroke_end_;
 
+  // True when the mode is activated via the stylus barrel button.
+  bool activated_via_button_ = false;
+
   base::WeakPtrFactory<MetalayerMode> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(MetalayerMode);
diff --git a/ash/system/palette/tools/metalayer_unittest.cc b/ash/system/palette/tools/metalayer_unittest.cc
index a5b89d7..0f9d736 100644
--- a/ash/system/palette/tools/metalayer_unittest.cc
+++ b/ash/system/palette/tools/metalayer_unittest.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "ash/highlighter/highlighter_controller.h"
+#include "ash/highlighter/highlighter_controller_test_api.h"
 #include "ash/shell.h"
 #include "ash/shell_test_api.h"
 #include "ash/system/palette/mock_palette_tool_delegate.h"
@@ -34,11 +36,19 @@
 
     palette_tool_delegate_ = base::MakeUnique<MockPaletteToolDelegate>();
     tool_ = base::MakeUnique<MetalayerMode>(palette_tool_delegate_.get());
+    highlighter_controller_ = base::MakeUnique<HighlighterController>();
+    highlighter_test_api_ = base::MakeUnique<HighlighterControllerTestApi>(
+        highlighter_controller_.get());
+    test_palette_delegate()->set_highlighter_test_api(
+        highlighter_test_api_.get());
   }
 
   void TearDown() override {
     // This needs to be called first to remove the event handler before the
     // shell instance gets torn down.
+    test_palette_delegate()->set_highlighter_test_api(nullptr);
+    highlighter_test_api_.reset();
+    highlighter_controller_.reset();
     tool_.reset();
     AshTestBase::TearDown();
   }
@@ -48,6 +58,8 @@
   }
 
  protected:
+  std::unique_ptr<HighlighterController> highlighter_controller_;
+  std::unique_ptr<HighlighterControllerTestApi> highlighter_test_api_;
   std::unique_ptr<MockPaletteToolDelegate> palette_tool_delegate_;
   std::unique_ptr<PaletteTool> tool_;
 
@@ -162,7 +174,7 @@
   // Calling the associated callback |metalayer_done| will disable the tool.
   EXPECT_CALL(*palette_tool_delegate_.get(),
               DisableTool(PaletteToolId::METALAYER));
-  test_palette_delegate()->CallMetalayerDone();
+  highlighter_test_api_->CallMetalayerDone();
 }
 
 }  // namespace ash
diff --git a/ash/test_shell_delegate.cc b/ash/test_shell_delegate.cc
index 8ce8acc..cbeabaa9f 100644
--- a/ash/test_shell_delegate.cc
+++ b/ash/test_shell_delegate.cc
@@ -23,10 +23,6 @@
   return nullptr;
 }
 
-bool TestShellDelegate::IsIncognitoAllowed() const {
-  return true;
-}
-
 bool TestShellDelegate::IsRunningInForcedAppMode() const {
   return false;
 }
diff --git a/ash/test_shell_delegate.h b/ash/test_shell_delegate.h
index 2a93c929..5404d130 100644
--- a/ash/test_shell_delegate.h
+++ b/ash/test_shell_delegate.h
@@ -19,7 +19,6 @@
 
   // Overridden from ShellDelegate:
   ::service_manager::Connector* GetShellConnector() const override;
-  bool IsIncognitoAllowed() const override;
   bool IsRunningInForcedAppMode() const override;
   bool CanShowWindowForUser(aura::Window* window) const override;
   bool IsForceMaximizeOnFirstRun() const override;
diff --git a/ash/touch_hud/mus/manifest.json b/ash/touch_hud/mus/manifest.json
index 1c7e9854..ab4a19d 100644
--- a/ash/touch_hud/mus/manifest.json
+++ b/ash/touch_hud/mus/manifest.json
@@ -1,6 +1,7 @@
 {
   "name": "touch_hud",
   "display_name": "Touch Hud",
+  "sandbox_type": "none",
   "interface_provider_specs": {
     "service_manager:connector": {
       "provides": { "mash:launchable": [ "mash::mojom::Launchable" ] },
diff --git a/ash/wm/overview/window_selector.cc b/ash/wm/overview/window_selector.cc
index 880a284..b581116e 100644
--- a/ash/wm/overview/window_selector.cc
+++ b/ash/wm/overview/window_selector.cc
@@ -564,6 +564,7 @@
     return false;
 
   switch (key_event.key_code()) {
+    case ui::VKEY_BROWSER_BACK:
     case ui::VKEY_ESCAPE:
       CancelSelection();
       break;
diff --git a/ash/wm/overview/window_selector_unittest.cc b/ash/wm/overview/window_selector_unittest.cc
index 2c9f3a89..037962b5 100644
--- a/ash/wm/overview/window_selector_unittest.cc
+++ b/ash/wm/overview/window_selector_unittest.cc
@@ -1467,6 +1467,22 @@
   }
 }
 
+// Verifies hitting the escape and back keys exit overview mode.
+TEST_F(WindowSelectorTest, ExitOverviewWithKey) {
+  std::unique_ptr<aura::Window> window1(CreateTestWindow());
+  std::unique_ptr<aura::Window> window2(CreateTestWindow());
+
+  ToggleOverview();
+  ASSERT_TRUE(window_selector_controller()->IsSelecting());
+  SendKey(ui::VKEY_ESCAPE);
+  EXPECT_FALSE(window_selector_controller()->IsSelecting());
+
+  ToggleOverview();
+  ASSERT_TRUE(window_selector_controller()->IsSelecting());
+  SendKey(ui::VKEY_BROWSER_BACK);
+  EXPECT_FALSE(window_selector_controller()->IsSelecting());
+}
+
 // Tests basic selection across multiple monitors.
 TEST_F(WindowSelectorTest, BasicMultiMonitorArrowKeyNavigation) {
   UpdateDisplay("400x400,400x400");
diff --git a/ash/wm/workspace/workspace_layout_manager.cc b/ash/wm/workspace/workspace_layout_manager.cc
index d2db092a8..cc234d3 100644
--- a/ash/wm/workspace/workspace_layout_manager.cc
+++ b/ash/wm/workspace/workspace_layout_manager.cc
@@ -250,16 +250,21 @@
 //////////////////////////////////////////////////////////////////////////////
 // WorkspaceLayoutManager, wm::ActivationChangeObserver implementation:
 
-void WorkspaceLayoutManager::OnWindowActivated(ActivationReason reason,
-                                               aura::Window* gained_active,
-                                               aura::Window* lost_active) {
+void WorkspaceLayoutManager::OnWindowActivating(ActivationReason reason,
+                                                aura::Window* gaining_active,
+                                                aura::Window* losing_active) {
   wm::WindowState* window_state =
-      gained_active ? wm::GetWindowState(gained_active) : nullptr;
+      gaining_active ? wm::GetWindowState(gaining_active) : nullptr;
   if (window_state && window_state->IsMinimized() &&
-      !gained_active->IsVisible()) {
+      !gaining_active->IsVisible()) {
     window_state->Unminimize();
     DCHECK(!window_state->IsMinimized());
   }
+}
+
+void WorkspaceLayoutManager::OnWindowActivated(ActivationReason reason,
+                                               aura::Window* gained_active,
+                                               aura::Window* lost_active) {
   UpdateFullscreenState();
   UpdateShelfVisibility();
 }
diff --git a/ash/wm/workspace/workspace_layout_manager.h b/ash/wm/workspace/workspace_layout_manager.h
index e68c2ae9..69f0eba 100644
--- a/ash/wm/workspace/workspace_layout_manager.h
+++ b/ash/wm/workspace/workspace_layout_manager.h
@@ -75,6 +75,9 @@
                              const gfx::Rect& new_bounds) override;
 
   // wm::ActivationChangeObserver overrides:
+  void OnWindowActivating(ActivationReason reason,
+                          aura::Window* gaining_active,
+                          aura::Window* losing_active) override;
   void OnWindowActivated(
       ::wm::ActivationChangeObserver::ActivationReason reason,
       aura::Window* gained_active,
diff --git a/ash/wm/workspace/workspace_layout_manager_unittest.cc b/ash/wm/workspace/workspace_layout_manager_unittest.cc
index 8c64e141..7010937 100644
--- a/ash/wm/workspace/workspace_layout_manager_unittest.cc
+++ b/ash/wm/workspace/workspace_layout_manager_unittest.cc
@@ -658,6 +658,17 @@
   EXPECT_EQ(bounds, window->bounds());
 }
 
+// Tests that activation of a minimized window unminimizes the window.
+TEST_F(WorkspaceLayoutManagerSoloTest, UnminimizeWithActivation) {
+  std::unique_ptr<aura::Window> window = CreateTestWindow();
+  wm::GetWindowState(window.get())->Minimize();
+  EXPECT_TRUE(wm::GetWindowState(window.get())->IsMinimized());
+  EXPECT_FALSE(wm::GetWindowState(window.get())->IsActive());
+  wm::GetWindowState(window.get())->Activate();
+  EXPECT_FALSE(wm::GetWindowState(window.get())->IsMinimized());
+  EXPECT_TRUE(wm::GetWindowState(window.get())->IsActive());
+}
+
 // A aura::WindowObserver which sets the focus when the window becomes visible.
 class FocusDuringUnminimizeWindowObserver : public aura::WindowObserver {
  public:
@@ -1668,15 +1679,24 @@
   SplitViewController* split_view_controller =
       Shell::Get()->split_view_controller();
 
+  // Windows in tablet mode are created with immersive mode on. In mash,
+  // immersive mode creates a new widget to render the title area. This will
+  // cause some differences in the test in mash configuration and non-mash
+  // configuration.
+  const bool is_mash = Shell::GetAshConfig() == Config::MASH;
+
   const gfx::Rect bounds(0, 0, 400, 400);
   std::unique_ptr<aura::Window> window1(CreateTestWindow(bounds));
   window1->Show();
 
+  // In mash, with one window, there is a extra child, the title area renderer
+  // of |window1|.
+  size_t expected_size = is_mash ? 3U : 2U;
   // Test that backdrop window is visible and is the second child in the
   // container. Its bounds should be the same as the container bounds.
-  ASSERT_EQ(2U, default_container()->children().size());
-  EXPECT_TRUE(default_container()->children()[0]->IsVisible());
-  EXPECT_TRUE(default_container()->children()[1]->IsVisible());
+  ASSERT_EQ(expected_size, default_container()->children().size());
+  for (auto* child : default_container()->children())
+    EXPECT_TRUE(child->IsVisible());
   EXPECT_EQ(window1.get(), default_container()->children()[1]);
   EXPECT_EQ(default_container()->bounds(),
             default_container()->children()[0]->bounds());
@@ -1685,9 +1705,9 @@
   // and is the second child in the container. Its bounds should still be the
   // same as the container bounds.
   split_view_controller->SnapWindow(window1.get(), SplitViewController::LEFT);
-  ASSERT_EQ(2U, default_container()->children().size());
-  EXPECT_TRUE(default_container()->children()[0]->IsVisible());
-  EXPECT_TRUE(default_container()->children()[1]->IsVisible());
+  ASSERT_EQ(expected_size, default_container()->children().size());
+  for (auto* child : default_container()->children())
+    EXPECT_TRUE(child->IsVisible());
   EXPECT_EQ(window1.get(), default_container()->children()[1]);
   EXPECT_EQ(default_container()->bounds(),
             default_container()->children()[0]->bounds());
@@ -1698,25 +1718,32 @@
   std::unique_ptr<aura::Window> window2(CreateTestWindow(bounds));
   split_view_controller->SnapWindow(window2.get(), SplitViewController::RIGHT);
 
-  ASSERT_EQ(3U, default_container()->children().size());
-  EXPECT_TRUE(default_container()->children()[0]->IsVisible());
-  EXPECT_TRUE(default_container()->children()[1]->IsVisible());
-  EXPECT_TRUE(default_container()->children()[2]->IsVisible());
+  // In mash, with two windows, there are two extra children, the title area
+  // renderer of |window1| and |window2|.
+  expected_size = is_mash ? 5U : 3U;
+  const int expected_second_window_index = is_mash ? 3 : 2;
+
+  ASSERT_EQ(expected_size, default_container()->children().size());
+  for (auto* child : default_container()->children())
+    EXPECT_TRUE(child->IsVisible());
   EXPECT_EQ(window1.get(), default_container()->children()[1]);
-  EXPECT_EQ(window2.get(), default_container()->children()[2]);
+  EXPECT_EQ(window2.get(),
+            default_container()->children()[expected_second_window_index]);
   EXPECT_EQ(default_container()->bounds(),
             default_container()->children()[0]->bounds());
 
   // Test activation change correctly updates the backdrop.
   wm::ActivateWindow(window1.get());
-  EXPECT_EQ(window1.get(), default_container()->children()[2]);
+  EXPECT_EQ(window1.get(),
+            default_container()->children()[expected_second_window_index]);
   EXPECT_EQ(window2.get(), default_container()->children()[1]);
   EXPECT_EQ(default_container()->bounds(),
             default_container()->children()[0]->bounds());
 
   wm::ActivateWindow(window2.get());
   EXPECT_EQ(window1.get(), default_container()->children()[1]);
-  EXPECT_EQ(window2.get(), default_container()->children()[2]);
+  EXPECT_EQ(window2.get(),
+            default_container()->children()[expected_second_window_index]);
   EXPECT_EQ(default_container()->bounds(),
             default_container()->children()[0]->bounds());
 }
diff --git a/base/BUILD.gn b/base/BUILD.gn
index e01eaf1..f666ab3 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -924,8 +924,6 @@
     "trace_event/common/trace_event_common.h",
     "trace_event/event_name_filter.cc",
     "trace_event/event_name_filter.h",
-    "trace_event/freed_object_tracker.cc",
-    "trace_event/freed_object_tracker.h",
     "trace_event/heap_profiler.h",
     "trace_event/heap_profiler_allocation_context.cc",
     "trace_event/heap_profiler_allocation_context.h",
@@ -1581,6 +1579,7 @@
       "process/process_posix.cc",
       "sync_socket.h",
       "sync_socket_posix.cc",
+      "synchronization/waitable_event_watcher.h",
     ]
     sources += [
       "base_paths_mac.h",
@@ -1621,7 +1620,6 @@
       "process/memory_stubs.cc",
       "strings/sys_string_conversions_mac.mm",
       "synchronization/waitable_event_mac.cc",
-      "synchronization/waitable_event_watcher_mac.cc",
       "threading/platform_thread_mac.mm",
       "time/time_conversion_posix.cc",
       "time/time_mac.cc",
@@ -2199,7 +2197,6 @@
     "tools_sanity_unittest.cc",
     "trace_event/blame_context_unittest.cc",
     "trace_event/event_name_filter_unittest.cc",
-    "trace_event/freed_object_tracker_unittest.cc",
     "trace_event/heap_profiler_allocation_context_tracker_unittest.cc",
     "trace_event/heap_profiler_allocation_register_unittest.cc",
     "trace_event/heap_profiler_heap_dump_writer_unittest.cc",
@@ -2309,6 +2306,7 @@
       "process/process_unittest.cc",
       "process/process_util_unittest.cc",
       "sync_socket_unittest.cc",
+      "synchronization/waitable_event_watcher_unittest.cc",
     ]
 
     # Pull in specific Mac files for iOS (which have been filtered out by file
diff --git a/base/containers/circular_deque.h b/base/containers/circular_deque.h
index a2750ea..9883316 100644
--- a/base/containers/circular_deque.h
+++ b/base/containers/circular_deque.h
@@ -799,7 +799,7 @@
       buffer_.DestructRange(&buffer_[0], &buffer_[last.index_]);
     }
 
-    if (last.index_ == begin_) {
+    if (first.index_ == begin_) {
       // This deletion is from the beginning. Nothing needs to be copied, only
       // begin_ needs to be updated.
       begin_ = last.index_;
diff --git a/base/logging.h b/base/logging.h
index 66c1e8a8..a2cdaa1 100644
--- a/base/logging.h
+++ b/base/logging.h
@@ -823,8 +823,9 @@
 
 #else  // DCHECK_IS_ON()
 
-// This is a dummy value, since the DCHECK implementation is a no-op.
-const LogSeverity LOG_DCHECK = LOG_INFO;
+// There may be users of LOG_DCHECK that are enabled independently
+// of DCHECK_IS_ON(), so default to FATAL logging for those.
+const LogSeverity LOG_DCHECK = LOG_FATAL;
 
 #endif  // DCHECK_IS_ON()
 
diff --git a/base/logging_unittest.cc b/base/logging_unittest.cc
index 7418ec4..93808ef 100644
--- a/base/logging_unittest.cc
+++ b/base/logging_unittest.cc
@@ -401,7 +401,28 @@
 }
 void DcheckEmptyFunction2() {}
 
+#if DCHECK_IS_ON() && defined(SYZYASAN)
+class ScopedDcheckSeverity {
+ public:
+  ScopedDcheckSeverity(LogSeverity new_severity) : old_severity_(LOG_DCHECK) {
+    LOG_DCHECK = new_severity;
+  }
+
+  ~ScopedDcheckSeverity() { LOG_DCHECK = old_severity_; }
+
+ private:
+  LogSeverity old_severity_;
+};
+#endif  // DCHECK_IS_ON() && defined(SYZYASAN)
+
 TEST_F(LoggingTest, 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.
+  ScopedDcheckSeverity dcheck_severity(LOG_FATAL);
+#endif  // DCHECK_IS_ON() && defined(SYZYASAN)
+
 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
   // Release build.
   EXPECT_FALSE(DCHECK_IS_ON());
@@ -418,13 +439,16 @@
   EXPECT_TRUE(DLOG_IS_ON(DCHECK));
 #endif
 
+  // DCHECKs are fatal iff they're compiled in DCHECK_IS_ON() and the DCHECK
+  // log level is set to fatal.
+  const bool dchecks_are_fatal = DCHECK_IS_ON() && LOG_DCHECK == LOG_FATAL;
   EXPECT_EQ(0, g_log_sink_call_count);
   DCHECK(false);
-  EXPECT_EQ(LOG_DCHECK == LOG_FATAL ? 1 : 0, g_log_sink_call_count);
+  EXPECT_EQ(dchecks_are_fatal ? 1 : 0, g_log_sink_call_count);
   DPCHECK(false);
-  EXPECT_EQ(LOG_DCHECK == LOG_FATAL ? 2 : 0, g_log_sink_call_count);
+  EXPECT_EQ(dchecks_are_fatal ? 2 : 0, g_log_sink_call_count);
   DCHECK_EQ(0, 1);
-  EXPECT_EQ(LOG_DCHECK == LOG_FATAL ? 3 : 0, g_log_sink_call_count);
+  EXPECT_EQ(dchecks_are_fatal ? 3 : 0, g_log_sink_call_count);
 
   // Test DCHECK on std::nullptr_t
   g_log_sink_call_count = 0;
@@ -441,7 +465,7 @@
   DCHECK_EQ(Animal::DOG, Animal::DOG);
   EXPECT_EQ(0, g_log_sink_call_count);
   DCHECK_EQ(Animal::DOG, Animal::CAT);
-  EXPECT_EQ(LOG_DCHECK == LOG_FATAL ? 1 : 0, g_log_sink_call_count);
+  EXPECT_EQ(dchecks_are_fatal ? 1 : 0, g_log_sink_call_count);
 
   // Test DCHECK on functions and function pointers.
   g_log_sink_call_count = 0;
@@ -464,9 +488,9 @@
   DCHECK_EQ(mp2, &MemberFunctions::MemberFunction2);
   EXPECT_EQ(0, g_log_sink_call_count);
   DCHECK_EQ(fp1, fp2);
-  EXPECT_EQ(LOG_DCHECK == LOG_FATAL ? 1 : 0, g_log_sink_call_count);
+  EXPECT_EQ(dchecks_are_fatal ? 1 : 0, g_log_sink_call_count);
   DCHECK_EQ(mp2, &MemberFunctions::MemberFunction1);
-  EXPECT_EQ(LOG_DCHECK == LOG_FATAL ? 2 : 0, g_log_sink_call_count);
+  EXPECT_EQ(dchecks_are_fatal ? 2 : 0, g_log_sink_call_count);
 }
 
 TEST_F(LoggingTest, DcheckReleaseBehavior) {
diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc
index 0ca42ad..7d091315 100644
--- a/base/metrics/histogram.cc
+++ b/base/metrics/histogram.cc
@@ -35,11 +35,6 @@
 #include "base/values.h"
 #include "build/build_config.h"
 
-#if !defined(OS_NACL)  // crbug/744734
-#include "base/trace_event/freed_object_tracker.h"
-#include "base/trace_event/heap_profiler_allocation_context.h"
-#endif
-
 namespace base {
 
 namespace {
@@ -591,45 +586,6 @@
   std::string debug_string = base::StringPrintf(
       "%s/%" PRIu32 "#%d", histogram_name().c_str(), bad_fields, identifier);
 #if !defined(OS_NACL)
-  // Bad dummy field: look up the previous object at "this" address.
-  // Bad name string: look up the previous object at its "data" address.
-  base::trace_event::AllocationRegister::Allocation allocation;
-  if (((bad_fields & (1 << kDummyField)) != 0 &&
-       base::trace_event::FreedObjectTracker::GetInstance()->Get(
-           this, &allocation)) ||
-      ((bad_fields & (1 << kHistogramNameField)) != 0 &&
-       base::trace_event::FreedObjectTracker::GetInstance()->Get(
-           histogram_name().data(), &allocation))) {
-    debug_string.reserve(10000);
-    if (allocation.context.type_name) {
-      debug_string += " (";
-      debug_string += allocation.context.type_name;
-      debug_string += ")";
-    }
-    for (int i = allocation.context.backtrace.frame_count - 1; i >= 0; --i) {
-      base::trace_event::StackFrame& frame =
-          allocation.context.backtrace.frames[i];
-      switch (frame.type) {
-        case base::trace_event::StackFrame::Type::TRACE_EVENT_NAME:
-          debug_string += " EV=\"";
-          debug_string += static_cast<const char*>(frame.value);
-          debug_string += "\"";
-          break;
-        case base::trace_event::StackFrame::Type::THREAD_NAME:
-          debug_string += " T=\"";
-          debug_string += static_cast<const char*>(frame.value);
-          debug_string += "\"";
-          break;
-        case base::trace_event::StackFrame::Type::PROGRAM_COUNTER:
-          debug_string += " PC:";
-          debug_string += StringPrintf(
-              "%08" PRIXPTR, reinterpret_cast<uintptr_t>(frame.value));
-          break;
-      }
-    }
-  } else {
-    debug_string += " [no previous allocation]";
-  }
   base::debug::ScopedCrashKey crash_key("bad_histogram", debug_string);
 #endif
   CHECK(false) << debug_string;
diff --git a/base/test/android/OWNERS b/base/test/android/OWNERS
index f25aa90..2b0078b2 100644
--- a/base/test/android/OWNERS
+++ b/base/test/android/OWNERS
@@ -1,5 +1,4 @@
 jbudorick@chromium.org
-nyquist@chromium.org
-yfriedman@chromium.org
+file://base/android/OWNERS
 
 # COMPONENT: Test>Android
diff --git a/base/trace_event/freed_object_tracker.cc b/base/trace_event/freed_object_tracker.cc
deleted file mode 100644
index 4c797757..0000000
--- a/base/trace_event/freed_object_tracker.cc
+++ /dev/null
@@ -1,174 +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 "base/trace_event/freed_object_tracker.h"
-
-#include "base/allocator/allocator_shim.h"
-#include "base/allocator/features.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/trace_event/heap_profiler_allocation_context.h"
-#include "base/trace_event/heap_profiler_allocation_context_tracker.h"
-#include "build/build_config.h"
-
-namespace base {
-namespace trace_event {
-
-namespace {
-#if BUILDFLAG(USE_ALLOCATOR_SHIM)
-
-using base::allocator::AllocatorDispatch;
-
-void* HookAlloc(const AllocatorDispatch* self, size_t size, void* context) {
-  const AllocatorDispatch* const next = self->next;
-  return next->alloc_function(next, size, context);
-}
-
-void* HookZeroInitAlloc(const AllocatorDispatch* self,
-                        size_t n,
-                        size_t size,
-                        void* context) {
-  const AllocatorDispatch* const next = self->next;
-  return next->alloc_zero_initialized_function(next, n, size, context);
-}
-
-void* HookAllocAligned(const AllocatorDispatch* self,
-                       size_t alignment,
-                       size_t size,
-                       void* context) {
-  const AllocatorDispatch* const next = self->next;
-  return next->alloc_aligned_function(next, alignment, size, context);
-}
-
-void* HookRealloc(const AllocatorDispatch* self,
-                  void* address,
-                  size_t size,
-                  void* context) {
-  const AllocatorDispatch* const next = self->next;
-  void* new_addr = next->realloc_function(next, address, size, context);
-  if (size == 0 || new_addr != address)
-    FreedObjectTracker::GetInstance()->RemoveAllocation(address);
-  return new_addr;
-}
-
-void HookFree(const AllocatorDispatch* self, void* address, void* context) {
-  if (address)
-    FreedObjectTracker::GetInstance()->RemoveAllocation(address);
-  const AllocatorDispatch* const next = self->next;
-  next->free_function(next, address, context);
-}
-
-size_t HookGetSizeEstimate(const AllocatorDispatch* self,
-                           void* address,
-                           void* context) {
-  const AllocatorDispatch* const next = self->next;
-  return next->get_size_estimate_function(next, address, context);
-}
-
-unsigned HookBatchMalloc(const AllocatorDispatch* self,
-                         size_t size,
-                         void** results,
-                         unsigned num_requested,
-                         void* context) {
-  const AllocatorDispatch* const next = self->next;
-  return next->batch_malloc_function(next, size, results, num_requested,
-                                     context);
-}
-
-void HookBatchFree(const AllocatorDispatch* self,
-                   void** to_be_freed,
-                   unsigned num_to_be_freed,
-                   void* context) {
-  for (unsigned i = 0; i < num_to_be_freed; ++i) {
-    FreedObjectTracker::GetInstance()->RemoveAllocation(to_be_freed[i]);
-  }
-  const AllocatorDispatch* const next = self->next;
-  next->batch_free_function(next, to_be_freed, num_to_be_freed, context);
-}
-
-void HookFreeDefiniteSize(const AllocatorDispatch* self,
-                          void* address,
-                          size_t size,
-                          void* context) {
-  if (address)
-    FreedObjectTracker::GetInstance()->RemoveAllocation(address);
-  const AllocatorDispatch* const next = self->next;
-  next->free_definite_size_function(next, address, size, context);
-}
-
-AllocatorDispatch g_allocator_hooks = {
-    &HookAlloc,            /* alloc_function */
-    &HookZeroInitAlloc,    /* alloc_zero_initialized_function */
-    &HookAllocAligned,     /* alloc_aligned_function */
-    &HookRealloc,          /* realloc_function */
-    &HookFree,             /* free_function */
-    &HookGetSizeEstimate,  /* get_size_estimate_function */
-    &HookBatchMalloc,      /* batch_malloc_function */
-    &HookBatchFree,        /* batch_free_function */
-    &HookFreeDefiniteSize, /* free_definite_size_function */
-    nullptr,               /* next */
-};
-
-#endif  // BUILDFLAG(USE_ALLOCATOR_SHIM)
-}  // namespace
-
-LazyInstance<FreedObjectTracker>::Leaky g_freed_object_tracker;
-
-// static
-FreedObjectTracker* FreedObjectTracker::GetInstance() {
-  return g_freed_object_tracker.Pointer();
-}
-
-FreedObjectTracker::FreedObjectTracker() {}
-
-FreedObjectTracker::~FreedObjectTracker() {}
-
-void FreedObjectTracker::Enable() {
-#if BUILDFLAG(USE_ALLOCATOR_SHIM)
-  allocation_register_.SetEnabled();
-  allocator::InsertAllocatorDispatch(&g_allocator_hooks);
-
-#if !DCHECK_IS_ON()
-  // This causes a NOTREACHED exception in OnThreadExitInternal trying to call
-  // a destructor but it works fine when DCHECK isn't enabled.
-  base::trace_event::AllocationContextTracker::SetCaptureMode(
-      base::trace_event::AllocationContextTracker::CaptureMode::NATIVE_STACK);
-#endif
-#endif
-}
-
-void FreedObjectTracker::DisableForTesting() {
-#if BUILDFLAG(USE_ALLOCATOR_SHIM)
-  allocation_register_.SetDisabled();
-  allocator::RemoveAllocatorDispatchForTesting(&g_allocator_hooks);
-#endif
-}
-
-bool FreedObjectTracker::Get(
-    const void* address,
-    AllocationRegister::Allocation* out_allocation) const {
-  if (!allocation_register_.is_enabled())
-    return false;
-
-  return allocation_register_.Get(address, out_allocation);
-}
-
-void FreedObjectTracker::RemoveAllocation(void* address) {
-  if (!allocation_register_.is_enabled())
-    return;
-
-  auto* tracker = AllocationContextTracker::GetInstanceForCurrentThread();
-  if (!tracker)
-    return;
-
-  AllocationContext context;
-  if (!tracker->GetContextSnapshot(&context))
-    return;
-
-  // Original size is unknown. 0 won't be recorded.
-  allocation_register_.Insert(address, 1, context);
-}
-
-}  // namespace trace_event
-}  // namespace base
diff --git a/base/trace_event/freed_object_tracker.h b/base/trace_event/freed_object_tracker.h
deleted file mode 100644
index e300fc1..0000000
--- a/base/trace_event/freed_object_tracker.h
+++ /dev/null
@@ -1,55 +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 BASE_METRICS_FREED_OBJECT_TRACKER_H_
-#define BASE_METRICS_FREED_OBJECT_TRACKER_H_
-
-#include "base/macros.h"
-#include "base/trace_event/heap_profiler_allocation_register.h"
-#include "base/trace_event/sharded_allocation_register.h"
-
-namespace base {
-
-template <typename T>
-struct LazyInstanceTraitsBase;
-
-namespace trace_event {
-
-// Records what objects were freed so use-after-free knows where to look. This
-// only tracks the last object freed from a given memory location so could be
-// incorrect if too much time passes between being freed and being accessed.
-// This is most accurate with BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS) set
-// by 64-bit builds or "enable_profiling=true".
-class BASE_EXPORT FreedObjectTracker {
- public:
-  static FreedObjectTracker* GetInstance();
-
-  void Enable();
-  void DisableForTesting();
-
-  // Gets information about an allocation. The |address| has to be an exact
-  // match for the original allocation; no searching is done for a larger
-  // allocation that encompasses that address. Returns false if no match
-  // is found.
-  bool Get(const void* address,
-           AllocationRegister::Allocation* out_allocation) const;
-
-  // This is public because it's called from the anonymous namespace.
-  void RemoveAllocation(void* address);
-
- private:
-  friend struct base::LazyInstanceTraitsBase<FreedObjectTracker>;
-
-  FreedObjectTracker();
-  ~FreedObjectTracker();
-
-  ShardedAllocationRegister allocation_register_;
-
-  DISALLOW_COPY_AND_ASSIGN(FreedObjectTracker);
-};
-
-}  // namespace trace_event
-}  // namespace base
-
-#endif  // BASE_METRICS_FREED_OBJECT_TRACKER_H_
diff --git a/base/trace_event/freed_object_tracker_unittest.cc b/base/trace_event/freed_object_tracker_unittest.cc
deleted file mode 100644
index 5e685ce..0000000
--- a/base/trace_event/freed_object_tracker_unittest.cc
+++ /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.
-
-#include "base/trace_event/freed_object_tracker.h"
-
-#include <memory>
-
-#include "base/allocator/allocator_shim.h"
-#include "base/allocator/features.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace trace_event {
-
-class FreedObjectTrackerTest : public testing::Test {
- public:
-  FreedObjectTrackerTest() {}
-  ~FreedObjectTrackerTest() override {}
-
-  // A 24-byte class for testing.
-  struct Size24 {
-    char bytes[24];
-  };
-
-  void SetUp() override {
-#if defined(OS_MACOSX) && BUILDFLAG(USE_ALLOCATOR_SHIM)
-    allocator::InitializeAllocatorShim();
-#endif
-    FreedObjectTracker::GetInstance()->Enable();
-  }
-
-  void TearDown() override {
-    FreedObjectTracker::GetInstance()->DisableForTesting();
-  }
-};
-
-#if BUILDFLAG(USE_ALLOCATOR_SHIM)
-#define MAYBE_Get Get
-#else
-#define MAYBE_Get DISABLED_Get
-#endif
-TEST_F(FreedObjectTrackerTest, MAYBE_Get) {
-  FreedObjectTracker* tracker = FreedObjectTracker::GetInstance();
-  AllocationRegister::Allocation allocation;
-
-  std::unique_ptr<Size24> obj = std::make_unique<Size24>();
-  Size24* objptr = obj.get();
-  ASSERT_FALSE(tracker->Get(objptr, &allocation));
-
-  obj.reset();
-  ASSERT_TRUE(tracker->Get(objptr, &allocation));
-  EXPECT_EQ(objptr, allocation.address);
-  EXPECT_LT(0U, allocation.context.backtrace.frame_count);
-}
-
-}  // namespace trace_event
-}  // namespace base
diff --git a/base/win/windows_version.cc b/base/win/windows_version.cc
index 8489fe8..3cf8611c 100644
--- a/base/win/windows_version.cc
+++ b/base/win/windows_version.cc
@@ -14,8 +14,8 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/win/registry.h"
 
-#if !defined(__clang__) && _MSC_FULL_VER < 190024213
-#error VS 2015 Update 3 with Cumulative Servicing Release or higher is required
+#if !defined(__clang__) && _MSC_FULL_VER < 191125507

+#error VS 2017 Update 3.2 or higher is required
 #endif
 
 #if !defined(NTDDI_WIN10_RS2)
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn
index 390506f2..c513afe 100644
--- a/build/config/BUILD.gn
+++ b/build/config/BUILD.gn
@@ -300,10 +300,7 @@
     # Currently only turn on linker CFI for executables.
     configs += [ "//build/config/win:cfi_linker" ]
   } else if (is_mac) {
-    configs += [
-      "//build/config/mac:mac_dynamic_flags",
-      "//build/config/mac:mac_executable_flags",
-    ]
+    configs += [ "//build/config/mac:mac_dynamic_flags" ]
   } else if (is_ios) {
     configs += [
       "//build/config/ios:ios_dynamic_flags",
diff --git a/build/config/features.gni b/build/config/features.gni
index 21b3bbc..d014d0e 100644
--- a/build/config/features.gni
+++ b/build/config/features.gni
@@ -21,16 +21,6 @@
 }
 
 declare_args() {
-  # Enables Native Client support.
-  # Temporarily disable nacl on arm64 linux to get rid of compilation errors.
-  # TODO(mcgrathr): When mipsel-nacl-clang is available, drop the exclusion.
-  enable_nacl = !is_ios && !is_android && !is_fuchsia && !is_chromecast &&
-                current_cpu != "mipsel" && current_cpu != "mips64el" &&
-                !(is_linux && target_cpu == "arm64")
-
-  # Non-SFI is not yet supported on mipsel
-  enable_nacl_nonsfi = current_cpu != "mipsel" && current_cpu != "mips64el"
-
   # Enables proprietary codecs and demuxers; e.g. H264, AAC, MP3, and MP4.
   # We always build Google Chrome and Chromecast with proprietary codecs.
   #
diff --git a/build/config/mac/BUILD.gn b/build/config/mac/BUILD.gn
index 45740bb..45bd90c 100644
--- a/build/config/mac/BUILD.gn
+++ b/build/config/mac/BUILD.gn
@@ -82,12 +82,6 @@
   }
 }
 
-# On Mac, this is used only for executables.
-config("mac_executable_flags") {
-  # Remove this when targeting >=10.7 since it is the default in that config.
-  ldflags = [ "-Wl,-pie" ]  # Position independent.
-}
-
 # The ldflags referenced below are handled by
 # //build/toolchain/mac/linker_driver.py.
 # Remove this config if a target wishes to change the arguments passed to the
diff --git a/build/config/nacl/config.gni b/build/config/nacl/config.gni
index ad8936ed9..77e15fc 100644
--- a/build/config/nacl/config.gni
+++ b/build/config/nacl/config.gni
@@ -2,8 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/features.gni")
-
 declare_args() {
   # Native Client supports both Newlib and Glibc C libraries where Newlib
   # is assumed to be the default one; use this to determine whether Glibc
@@ -14,39 +12,44 @@
 is_nacl_irt = false
 is_nacl_nonsfi = false
 
-if (enable_nacl) {
-  nacl_toolchain_dir = "//native_client/toolchain/${host_os}_x86"
+nacl_toolchain_dir = "//native_client/toolchain/${host_os}_x86"
 
-  if (is_nacl_glibc) {
-    if (current_cpu == "x86" || current_cpu == "x64") {
-      nacl_toolchain_package = "nacl_x86_glibc"
-    } else if (current_cpu == "arm") {
-      nacl_toolchain_package = "nacl_arm_glibc"
-    }
-  } else {
-    nacl_toolchain_package = "pnacl_newlib"
-  }
-
-  if (current_cpu == "pnacl") {
-    _nacl_tuple = "pnacl"
-  } else if (current_cpu == "x86" || current_cpu == "x64") {
-    _nacl_tuple = "x86_64-nacl"
+if (is_nacl_glibc) {
+  if (current_cpu == "x86" || current_cpu == "x64") {
+    nacl_toolchain_package = "nacl_x86_glibc"
   } else if (current_cpu == "arm") {
-    _nacl_tuple = "arm-nacl"
-  } else if (current_cpu == "mipsel") {
-    _nacl_tuple = "mipsel-nacl"
+    nacl_toolchain_package = "nacl_arm_glibc"
   }
-
-  nacl_toolchain_bindir = "${nacl_toolchain_dir}/${nacl_toolchain_package}/bin"
-  nacl_toolchain_tooldir =
-      "${nacl_toolchain_dir}/${nacl_toolchain_package}/${_nacl_tuple}"
-  nacl_toolprefix = "${nacl_toolchain_bindir}/${_nacl_tuple}-"
-
-  nacl_irt_toolchain = "//build/toolchain/nacl:irt_" + target_cpu
-  is_nacl_irt = current_toolchain == nacl_irt_toolchain
-
-  # Non-SFI mode is a lightweight sandbox used by Chrome OS for running ARC
-  # applications.
-  nacl_nonsfi_toolchain = "//build/toolchain/nacl:newlib_pnacl_nonsfi"
-  is_nacl_nonsfi = current_toolchain == nacl_nonsfi_toolchain
+} else {
+  nacl_toolchain_package = "pnacl_newlib"
 }
+
+if (current_cpu == "pnacl") {
+  _nacl_tuple = "pnacl"
+} else if (current_cpu == "x86" || current_cpu == "x64") {
+  _nacl_tuple = "x86_64-nacl"
+} else if (current_cpu == "arm") {
+  _nacl_tuple = "arm-nacl"
+} else if (current_cpu == "mipsel") {
+  _nacl_tuple = "mipsel-nacl"
+} else {
+  # In order to allow this file to be included unconditionally
+  # from build files that can't depend on //components/nacl/features.gni
+  # we provide a dummy value that should be harmless if nacl isn't needed.
+  # If nacl *is* needed this will result in a real error, indicating that
+  # people need to set the toolchain path correctly.
+  _nacl_tuple = "unknown"
+}
+
+nacl_toolchain_bindir = "${nacl_toolchain_dir}/${nacl_toolchain_package}/bin"
+nacl_toolchain_tooldir =
+    "${nacl_toolchain_dir}/${nacl_toolchain_package}/${_nacl_tuple}"
+nacl_toolprefix = "${nacl_toolchain_bindir}/${_nacl_tuple}-"
+
+nacl_irt_toolchain = "//build/toolchain/nacl:irt_" + target_cpu
+is_nacl_irt = current_toolchain == nacl_irt_toolchain
+
+# Non-SFI mode is a lightweight sandbox used by Chrome OS for running ARC
+# applications.
+nacl_nonsfi_toolchain = "//build/toolchain/nacl:newlib_pnacl_nonsfi"
+is_nacl_nonsfi = current_toolchain == nacl_nonsfi_toolchain
diff --git a/build/config/nacl/rules.gni b/build/config/nacl/rules.gni
index 1c1a912..9bb4ede 100644
--- a/build/config/nacl/rules.gni
+++ b/build/config/nacl/rules.gni
@@ -2,7 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/features.gni")
 import("//build/config/nacl/config.gni")
 
 # Generate a nmf file
diff --git a/build/install-build-deps.sh b/build/install-build-deps.sh
index 961aebaf..f2ab2668 100755
--- a/build/install-build-deps.sh
+++ b/build/install-build-deps.sh
@@ -165,6 +165,7 @@
   libcap-dev
   libcups2-dev
   libcurl4-gnutls-dev
+  libdconf-dev
   libdrm-dev
   libelf-dev
   libffi-dev
@@ -232,6 +233,7 @@
   libcairo2
   libcap2
   libcups2
+  libdconf1
   libexpat1
   libffi6
   libfontconfig1
@@ -377,6 +379,7 @@
   libasound2:i386
   libcap2:i386
   libelf-dev:i386
+  libdconf1:i386
   libfontconfig1:i386
   libgconf-2-4:i386
   libglib2.0-0:i386
diff --git a/build/run_swarming_xcode_install.py b/build/run_swarming_xcode_install.py
index 4b1448c..a731c1b 100755
--- a/build/run_swarming_xcode_install.py
+++ b/build/run_swarming_xcode_install.py
@@ -31,8 +31,11 @@
   parser.add_argument('--isolate-server', required=True, type=str)
   parser.add_argument('--batches', type=int, default=25,
                       help="Run xcode install in batches of size |batches|.")
+  parser.add_argument('--dimension', nargs=2, action='append')
   args = parser.parse_args()
 
+  args.dimension = args.dimension or []
+
   script_dir = os.path.dirname(os.path.abspath(__file__))
   tmp_dir = tempfile.mkdtemp(prefix='swarming_xcode')
   try:
@@ -54,12 +57,16 @@
     # swarming for iOS is fleshed out, likely removing xcode_version 9 and
     # adding different dimensions.
     luci_tools = os.path.join(luci_client, 'tools')
+    dimensions = [['pool', 'Chrome'], ['xcode_version', '9.0']] + args.dimension
+    dim_args = []
+    for d in dimensions:
+      dim_args += ['--dimension'] + d
     cmd = [
       sys.executable, os.path.join(luci_tools, 'run_on_bots.py'),
       '--swarming', args.swarming_server, '--isolate-server',
-      args.isolate_server, '--priority', '20', '--dimension', 'pool',
-      'Chrome', '--dimension', 'xcode_version', '9.0', '--batches',
-      args.batches, '--name', 'run_swarming_xcode_install', '--', isolate_hash,
+      args.isolate_server, '--priority', '20', '--batches', str(args.batches),
+      '--tags', 'name:run_swarming_xcode_install',
+    ] + dim_args + ['--name', 'run_swarming_xcode_install', '--', isolate_hash,
       'python', 'swarming_xcode_install.py',
     ]
     subprocess.check_call(cmd)
diff --git a/build/toolchain/win/midl.py b/build/toolchain/win/midl.py
index c8134fb..e344b16 100644
--- a/build/toolchain/win/midl.py
+++ b/build/toolchain/win/midl.py
@@ -113,6 +113,8 @@
       return popen.returncode
     if is_chromoting:
       return 0
+    # Skip checking of results until crbug.com/756607 is fixed.
+    return 0
 
     for f in os.listdir(tmp_dir):
       ZapTimestamp(os.path.join(tmp_dir, f))
diff --git a/build/vs_toolchain.py b/build/vs_toolchain.py
index e546426..a1e77ea 100755
--- a/build/vs_toolchain.py
+++ b/build/vs_toolchain.py
@@ -153,6 +153,7 @@
     # 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'):
       if path and os.path.exists(path):
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index 4f69bb4..447d732 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -297,7 +297,6 @@
     "trees/layer_tree_settings.h",
     "trees/managed_memory_policy.cc",
     "trees/managed_memory_policy.h",
-    "trees/mutable_properties.h",
     "trees/mutator_host.h",
     "trees/mutator_host_client.h",
     "trees/occlusion.cc",
diff --git a/cc/benchmarks/rasterize_and_record_benchmark_impl.cc b/cc/benchmarks/rasterize_and_record_benchmark_impl.cc
index e28e367..2fb28ba 100644
--- a/cc/benchmarks/rasterize_and_record_benchmark_impl.cc
+++ b/cc/benchmarks/rasterize_and_record_benchmark_impl.cc
@@ -58,9 +58,16 @@
                                                     content_rect.height()));
       SkCanvas canvas(bitmap);
 
-      PlaybackImageProvider image_provider(false, PaintImageIdFlatSet(), {},
-                                           image_decode_cache,
-                                           gfx::ColorSpace(), {});
+      // Pass an empty settings to make sure that the decode cache is used to
+      // replace all images.
+      base::Optional<PlaybackImageProvider::Settings> image_settings;
+      image_settings.emplace();
+      image_settings->images_to_skip = {};
+      image_settings->at_raster_images = {};
+      image_settings->image_to_current_frame_index = {};
+
+      PlaybackImageProvider image_provider(
+          image_decode_cache, gfx::ColorSpace(), std::move(image_settings));
       RasterSource::PlaybackSettings settings;
       settings.image_provider = &image_provider;
 
diff --git a/cc/blink/web_layer_impl.cc b/cc/blink/web_layer_impl.cc
index b4ced27d..539ec57 100644
--- a/cc/blink/web_layer_impl.cc
+++ b/cc/blink/web_layer_impl.cc
@@ -487,14 +487,6 @@
   return layer_->element_id();
 }
 
-void WebLayerImpl::SetCompositorMutableProperties(uint32_t properties) {
-  layer_->SetMutableProperties(properties);
-}
-
-uint32_t WebLayerImpl::CompositorMutableProperties() const {
-  return layer_->mutable_properties();
-}
-
 void WebLayerImpl::SetScrollParent(blink::WebLayer* parent) {
   cc::Layer* scroll_parent = nullptr;
   if (parent)
diff --git a/cc/blink/web_layer_impl.h b/cc/blink/web_layer_impl.h
index a40883f..099c815 100644
--- a/cc/blink/web_layer_impl.h
+++ b/cc/blink/web_layer_impl.h
@@ -128,8 +128,6 @@
   cc::Layer* CcLayer() override;
   void SetElementId(const cc::ElementId&) override;
   cc::ElementId GetElementId() const override;
-  void SetCompositorMutableProperties(uint32_t properties) override;
-  uint32_t CompositorMutableProperties() const override;
   void SetHasWillChangeTransformHint(bool has_will_change) override;
   void ShowScrollbars() override;
   void SetScrollBoundaryBehavior(
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc
index c04aabc..629de45 100644
--- a/cc/layers/layer.cc
+++ b/cc/layers/layer.cc
@@ -25,7 +25,6 @@
 #include "cc/trees/effect_node.h"
 #include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_impl.h"
-#include "cc/trees/mutable_properties.h"
 #include "cc/trees/mutator_host.h"
 #include "cc/trees/scroll_node.h"
 #include "cc/trees/transform_node.h"
@@ -61,7 +60,6 @@
           MainThreadScrollingReason::kNotScrollingOnMain),
       is_resized_by_browser_controls(false),
       is_container_for_fixed_position_layers(false),
-      mutable_properties(MutableProperty::kNone),
       scroll_parent(nullptr),
       clip_parent(nullptr),
       has_will_change_transform_hint(false),
@@ -1202,7 +1200,6 @@
 
   if (scrollable())
     layer->SetScrollable(inputs_.scroll_container_bounds);
-  layer->SetMutableProperties(inputs_.mutable_properties);
 
   // The property trees must be safe to access because they will be used below
   // to call |SetScrollOffsetClobberActiveValue|.
@@ -1439,16 +1436,6 @@
   SetNeedsCommit();
 }
 
-void Layer::SetMutableProperties(uint32_t properties) {
-  DCHECK(IsPropertyChangeAllowed());
-  if (inputs_.mutable_properties == properties)
-    return;
-  TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
-               "Layer::SetMutableProperties", "properties", properties);
-  inputs_.mutable_properties = properties;
-  SetNeedsCommit();
-}
-
 bool Layer::has_copy_requests_in_target_subtree() {
   return layer_tree_host_->property_trees()
       ->effect_tree.Node(effect_tree_index())
diff --git a/cc/layers/layer.h b/cc/layers/layer.h
index 98a9062..b3a9cb4 100644
--- a/cc/layers/layer.h
+++ b/cc/layers/layer.h
@@ -415,9 +415,6 @@
   void SetElementId(ElementId id);
   ElementId element_id() const { return inputs_.element_id; }
 
-  void SetMutableProperties(uint32_t properties);
-  uint32_t mutable_properties() const { return inputs_.mutable_properties; }
-
   bool HasTickingAnimationForTesting() const;
 
   void SetHasWillChangeTransformHint(bool has_will_change);
@@ -612,8 +609,6 @@
 
     ElementId element_id;
 
-    uint32_t mutable_properties;
-
     Layer* scroll_parent;
     Layer* clip_parent;
 
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 7a203ead..8b95e3d 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -30,7 +30,6 @@
 #include "cc/trees/layer_tree_host_common.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "cc/trees/layer_tree_settings.h"
-#include "cc/trees/mutable_properties.h"
 #include "cc/trees/mutator_host.h"
 #include "cc/trees/proxy.h"
 #include "cc/trees/scroll_node.h"
@@ -73,7 +72,6 @@
       clip_tree_index_(ClipTree::kInvalidNodeId),
       scroll_tree_index_(ScrollTree::kInvalidNodeId),
       current_draw_mode_(DRAW_MODE_NONE),
-      mutable_properties_(MutableProperty::kNone),
       debug_info_(nullptr),
       has_will_change_transform_hint_(false),
       trilinear_filtering_(false),
@@ -216,19 +214,19 @@
 
 void LayerImpl::AppendDebugBorderQuad(
     viz::RenderPass* render_pass,
-    const gfx::Size& bounds,
+    const gfx::Rect& quad_rect,
     const viz::SharedQuadState* shared_quad_state,
     AppendQuadsData* append_quads_data) const {
   SkColor color;
   float width;
   GetDebugBorderProperties(&color, &width);
-  AppendDebugBorderQuad(render_pass, bounds, shared_quad_state,
+  AppendDebugBorderQuad(render_pass, quad_rect, shared_quad_state,
                         append_quads_data, color, width);
 }
 
 void LayerImpl::AppendDebugBorderQuad(
     viz::RenderPass* render_pass,
-    const gfx::Size& bounds,
+    const gfx::Rect& quad_rect,
     const viz::SharedQuadState* shared_quad_state,
     AppendQuadsData* append_quads_data,
     SkColor color,
@@ -236,7 +234,6 @@
   if (!ShowDebugBorders(DebugBorderType::LAYER))
     return;
 
-  gfx::Rect quad_rect(bounds);
   gfx::Rect visible_quad_rect(quad_rect);
   auto* debug_border_quad =
       render_pass->CreateAndAppendDrawQuad<viz::DebugBorderDrawQuad>();
@@ -347,7 +344,6 @@
   layer->SetBounds(bounds_);
   if (scrollable_)
     layer->SetScrollable(scroll_container_bounds_);
-  layer->SetMutableProperties(mutable_properties_);
 
   // If the main thread commits multiple times before the impl thread actually
   // draws, then damage tracking will become incorrect if we simply clobber the
@@ -652,18 +648,6 @@
   SetNeedsPushProperties();
 }
 
-void LayerImpl::SetMutableProperties(uint32_t properties) {
-  if (mutable_properties_ == properties)
-    return;
-
-  TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
-               "LayerImpl::SetMutableProperties", "properties", properties);
-
-  mutable_properties_ = properties;
-  // If this layer is already in the element map, update its properties.
-  layer_tree_impl_->AddToElementMap(this);
-}
-
 void LayerImpl::SetPosition(const gfx::PointF& position) {
   position_ = position;
 }
@@ -751,9 +735,6 @@
   if (element_id_)
     element_id_.AddToTracedValue(state);
 
-  if (mutable_properties_ != MutableProperty::kNone)
-    state->SetInteger("mutable_properties", mutable_properties_);
-
   MathUtil::AddToTracedValue("scroll_offset", CurrentScrollOffset(), state);
 
   if (!ScreenSpaceTransform().IsIdentity())
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h
index 5ec9501..9c90521 100644
--- a/cc/layers/layer_impl.h
+++ b/cc/layers/layer_impl.h
@@ -193,9 +193,6 @@
   void SetElementId(ElementId element_id);
   ElementId element_id() const { return element_id_; }
 
-  void SetMutableProperties(uint32_t properties);
-  uint32_t mutable_properties() const { return mutable_properties_; }
-
   void SetPosition(const gfx::PointF& position);
   gfx::PointF position() const { return position_; }
 
@@ -451,11 +448,11 @@
   virtual void GetDebugBorderProperties(SkColor* color, float* width) const;
 
   void AppendDebugBorderQuad(viz::RenderPass* render_pass,
-                             const gfx::Size& bounds,
+                             const gfx::Rect& quad_rect,
                              const viz::SharedQuadState* shared_quad_state,
                              AppendQuadsData* append_quads_data) const;
   void AppendDebugBorderQuad(viz::RenderPass* render_pass,
-                             const gfx::Size& bounds,
+                             const gfx::Rect& quad_rect,
                              const viz::SharedQuadState* shared_quad_state,
                              AppendQuadsData* append_quads_data,
                              SkColor color,
@@ -539,7 +536,6 @@
   TransformTree& GetTransformTree() const;
 
   ElementId element_id_;
-  uint32_t mutable_properties_;
   // Rect indicating what was repainted/updated during update.
   // Note that plugin layers bypass this and leave it empty.
   // This is in the layer's space.
diff --git a/cc/layers/layer_impl_unittest.cc b/cc/layers/layer_impl_unittest.cc
index c8ac16a..3274f2c 100644
--- a/cc/layers/layer_impl_unittest.cc
+++ b/cc/layers/layer_impl_unittest.cc
@@ -15,7 +15,6 @@
 #include "cc/test/geometry_test_utils.h"
 #include "cc/test/test_task_graph_runner.h"
 #include "cc/trees/layer_tree_impl.h"
-#include "cc/trees/mutable_properties.h"
 #include "cc/trees/single_thread_proxy.h"
 #include "cc/trees/tree_synchronizer.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -191,9 +190,6 @@
   // but does cause the layer to need to push properties.
   EXECUTE_AND_VERIFY_NEEDS_PUSH_PROPERTIES_AND_SUBTREE_DID_NOT_CHANGE(
       root->SetElementId(ElementId(2)));
-  EXECUTE_AND_VERIFY_NEEDS_PUSH_PROPERTIES_AND_SUBTREE_DID_NOT_CHANGE(
-      root->SetMutableProperties(MutableProperty::kOpacity);
-      root->SetNeedsPushProperties());
 
   // After setting all these properties already, setting to the exact same
   // values again should not cause any change.
@@ -392,8 +388,6 @@
       layer->SetBackgroundColor(arbitrary_color));
   VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(layer->SetBounds(arbitrary_size));
   VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(layer->SetElementId(ElementId(2)));
-  VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(
-      layer->SetMutableProperties(MutableProperty::kTransform));
 }
 
 TEST(LayerImplTest, SafeOpaqueBackgroundColor) {
diff --git a/cc/layers/layer_unittest.cc b/cc/layers/layer_unittest.cc
index 6bdc718..6b241132 100644
--- a/cc/layers/layer_unittest.cc
+++ b/cc/layers/layer_unittest.cc
@@ -26,7 +26,6 @@
 #include "cc/test/stub_layer_tree_host_single_thread_client.h"
 #include "cc/test/test_task_graph_runner.h"
 #include "cc/trees/layer_tree_host.h"
-#include "cc/trees/mutable_properties.h"
 #include "cc/trees/single_thread_proxy.h"
 #include "cc/trees/transform_node.h"
 #include "components/viz/common/frame_sinks/copy_output_request.h"
@@ -924,8 +923,6 @@
   EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetForceRenderSurfaceForTesting(true));
   EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetHideLayerAndSubtree(true));
   EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetElementId(ElementId(2)));
-  EXPECT_SET_NEEDS_COMMIT(
-      1, test_layer->SetMutableProperties(MutableProperty::kTransform));
 
   EXPECT_SET_NEEDS_FULL_TREE_SYNC(1, test_layer->SetMaskLayer(
       dummy_layer1.get()));
@@ -1418,7 +1415,7 @@
   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
 }
 
-TEST_F(LayerTest, ElementIdAndMutablePropertiesArePushed) {
+TEST_F(LayerTest, ElementIdIsPushed) {
   scoped_refptr<Layer> test_layer = Layer::Create();
   std::unique_ptr<LayerImpl> impl_layer =
       LayerImpl::Create(host_impl_.active_tree(), 1);
@@ -1426,18 +1423,15 @@
   EXPECT_SET_NEEDS_FULL_TREE_SYNC(1,
                                   layer_tree_host_->SetRootLayer(test_layer));
 
-  EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(2);
+  EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
 
   test_layer->SetElementId(ElementId(2));
-  test_layer->SetMutableProperties(MutableProperty::kTransform);
 
   EXPECT_FALSE(impl_layer->element_id());
-  EXPECT_EQ(MutableProperty::kNone, impl_layer->mutable_properties());
 
   test_layer->PushPropertiesTo(impl_layer.get());
 
   EXPECT_EQ(ElementId(2), impl_layer->element_id());
-  EXPECT_EQ(MutableProperty::kTransform, impl_layer->mutable_properties());
 }
 
 TEST_F(LayerTest, SetLayerTreeHostNotUsingLayerListsManagesElementId) {
diff --git a/cc/layers/nine_patch_layer_impl.cc b/cc/layers/nine_patch_layer_impl.cc
index eb3cdd1..15822176 100644
--- a/cc/layers/nine_patch_layer_impl.cc
+++ b/cc/layers/nine_patch_layer_impl.cc
@@ -64,7 +64,7 @@
                         contents_opaque()
                   : false;
   PopulateSharedQuadState(shared_quad_state, are_contents_opaque);
-  AppendDebugBorderQuad(render_pass, bounds(), shared_quad_state,
+  AppendDebugBorderQuad(render_pass, gfx::Rect(bounds()), shared_quad_state,
                         append_quads_data);
 
   if (!is_resource)
diff --git a/cc/layers/painted_overlay_scrollbar_layer_impl.cc b/cc/layers/painted_overlay_scrollbar_layer_impl.cc
index 0f6c9e6..f445def 100644
--- a/cc/layers/painted_overlay_scrollbar_layer_impl.cc
+++ b/cc/layers/painted_overlay_scrollbar_layer_impl.cc
@@ -81,7 +81,7 @@
                 contents_opaque()
           : false;
   PopulateSharedQuadState(shared_quad_state, are_contents_opaque);
-  AppendDebugBorderQuad(render_pass, bounds(), shared_quad_state,
+  AppendDebugBorderQuad(render_pass, gfx::Rect(bounds()), shared_quad_state,
                         append_quads_data);
 
   if (!is_resource)
diff --git a/cc/layers/painted_scrollbar_layer_impl.cc b/cc/layers/painted_scrollbar_layer_impl.cc
index 89d9fca..edcd3332 100644
--- a/cc/layers/painted_scrollbar_layer_impl.cc
+++ b/cc/layers/painted_scrollbar_layer_impl.cc
@@ -97,7 +97,7 @@
   PopulateScaledSharedQuadState(shared_quad_state, internal_contents_scale_,
                                 internal_contents_scale_, contents_opaque());
 
-  AppendDebugBorderQuad(render_pass, internal_content_bounds_,
+  AppendDebugBorderQuad(render_pass, gfx::Rect(internal_content_bounds_),
                         shared_quad_state, append_quads_data);
 
   gfx::Rect thumb_quad_rect = ComputeThumbQuadRect();
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index e640106..9c9cceb 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -213,8 +213,8 @@
   if (raster_source_->IsSolidColor()) {
     PopulateSharedQuadState(shared_quad_state, contents_opaque());
 
-    AppendDebugBorderQuad(
-        render_pass, bounds(), shared_quad_state, append_quads_data);
+    AppendDebugBorderQuad(render_pass, gfx::Rect(bounds()), shared_quad_state,
+                          append_quads_data);
 
     SolidColorLayerImpl::AppendSolidQuads(
         render_pass, draw_properties().occlusion_in_content_space,
@@ -237,10 +237,10 @@
   }
 
   if (current_draw_mode_ == DRAW_MODE_RESOURCELESS_SOFTWARE) {
+    DCHECK(shared_quad_state->quad_layer_rect.origin() == gfx::Point(0, 0));
     AppendDebugBorderQuad(
-        render_pass, shared_quad_state->quad_layer_rect.size(),
-        shared_quad_state, append_quads_data,
-        DebugColors::DirectPictureBorderColor(),
+        render_pass, shared_quad_state->quad_layer_rect, shared_quad_state,
+        append_quads_data, DebugColors::DirectPictureBorderColor(),
         DebugColors::DirectPictureBorderWidth(device_scale_factor));
 
     gfx::Rect geometry_rect = shared_quad_state->visible_quad_layer_rect;
@@ -272,8 +272,23 @@
     return;
   }
 
-  AppendDebugBorderQuad(render_pass, shared_quad_state->quad_layer_rect.size(),
-                        shared_quad_state, append_quads_data);
+  // If we're doing a regular AppendQuads (ie, not solid color or resourceless
+  // software draw, and if the visible rect is scrolled far enough away, then we
+  // may run into a floating point precision in AA calculations in the renderer.
+  // See crbug.com/765297. In order to avoid this, we shift the quads up from
+  // where they logically reside and adjust the shared_quad_state's transform
+  // instead. We only do this in a scale/translate matrices to ensure the math
+  // is correct.
+  gfx::Vector2d quad_offset;
+  if (shared_quad_state->quad_to_target_transform.IsScaleOrTranslation()) {
+    const auto& visible_rect = shared_quad_state->visible_quad_layer_rect;
+    quad_offset = gfx::Vector2d(-visible_rect.x(), -visible_rect.y());
+  }
+
+  gfx::Rect debug_border_rect(shared_quad_state->quad_layer_rect);
+  debug_border_rect.Offset(quad_offset);
+  AppendDebugBorderQuad(render_pass, debug_border_rect, shared_quad_state,
+                        append_quads_data);
 
   if (ShowDebugBorders(DebugBorderType::LAYER)) {
     for (PictureLayerTilingSet::CoverageIterator iter(
@@ -314,6 +329,7 @@
       auto* debug_border_quad =
           render_pass->CreateAndAppendDrawQuad<viz::DebugBorderDrawQuad>();
       gfx::Rect geometry_rect = iter.geometry_rect();
+      geometry_rect.Offset(quad_offset);
       gfx::Rect visible_geometry_rect = geometry_rect;
       debug_border_quad->SetNew(shared_quad_state,
                                 geometry_rect,
@@ -345,6 +361,12 @@
     gfx::Rect geometry_rect = iter.geometry_rect();
     gfx::Rect visible_geometry_rect =
         scaled_occlusion.GetUnoccludedContentRect(geometry_rect);
+
+    gfx::Rect offset_geometry_rect = geometry_rect;
+    offset_geometry_rect.Offset(quad_offset);
+    gfx::Rect offset_visible_geometry_rect = visible_geometry_rect;
+    offset_visible_geometry_rect.Offset(quad_offset);
+
     bool needs_blending = !contents_opaque();
     if (visible_geometry_rect.IsEmpty())
       continue;
@@ -357,6 +379,7 @@
     bool has_draw_quad = false;
     if (*iter && iter->draw_info().IsReadyToDraw()) {
       const TileDrawInfo& draw_info = iter->draw_info();
+
       switch (draw_info.mode()) {
         case TileDrawInfo::RESOURCE_MODE: {
           gfx::RectF texture_rect = iter.texture_rect();
@@ -375,8 +398,9 @@
 
           auto* quad =
               render_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
-          quad->SetNew(shared_quad_state, geometry_rect, visible_geometry_rect,
-                       needs_blending, draw_info.resource_id(), texture_rect,
+          quad->SetNew(shared_quad_state, offset_geometry_rect,
+                       offset_visible_geometry_rect, needs_blending,
+                       draw_info.resource_id(), texture_rect,
                        draw_info.resource_size(), draw_info.contents_swizzled(),
                        nearest_neighbor_);
           ValidateQuadResources(quad);
@@ -391,8 +415,9 @@
               alpha >= std::numeric_limits<float>::epsilon()) {
             auto* quad =
                 render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>();
-            quad->SetNew(shared_quad_state, geometry_rect,
-                         visible_geometry_rect, draw_info.solid_color(), false);
+            quad->SetNew(shared_quad_state, offset_geometry_rect,
+                         offset_visible_geometry_rect, draw_info.solid_color(),
+                         false);
             ValidateQuadResources(quad);
           }
           has_draw_quad = true;
@@ -412,8 +437,8 @@
       }
       auto* quad =
           render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>();
-      quad->SetNew(shared_quad_state, geometry_rect, visible_geometry_rect,
-                   color, false);
+      quad->SetNew(shared_quad_state, offset_geometry_rect,
+                   offset_visible_geometry_rect, color, false);
       ValidateQuadResources(quad);
 
       if (geometry_rect.Intersects(scaled_viewport_for_tile_priority)) {
@@ -454,6 +479,12 @@
     }
   }
 
+  // Adjust shared_quad_state with the quad_offset, since we've adjusted each
+  // quad we've appended by it.
+  shared_quad_state->quad_to_target_transform.Translate(-quad_offset);
+  shared_quad_state->quad_layer_rect.Offset(quad_offset);
+  shared_quad_state->visible_quad_layer_rect.Offset(quad_offset);
+
   if (missing_tile_count) {
     TRACE_EVENT_INSTANT2("cc",
                          "PictureLayerImpl::AppendQuads checkerboard",
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index 465463d..6b1e9fa 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -43,6 +43,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 #include "ui/gfx/geometry/size_conversions.h"
+#include "ui/gfx/test/gfx_util.h"
 
 namespace cc {
 namespace {
@@ -1595,6 +1596,161 @@
   EXPECT_EQ(0U, render_pass->quad_list.size());
 }
 
+TEST_F(PictureLayerImplTest, FarScrolledQuadsShifted) {
+  std::unique_ptr<viz::RenderPass> render_pass = viz::RenderPass::Create();
+
+  gfx::Size layer_bounds(1000, 10000);
+  scoped_refptr<FakeRasterSource> active_raster_source =
+      FakeRasterSource::CreateFilled(layer_bounds);
+  SetupPendingTree(active_raster_source);
+  ActivateTree();
+
+  active_layer()->SetContentsOpaque(true);
+  active_layer()->draw_properties().visible_layer_rect =
+      gfx::Rect(0, 5000, 1000, 1000);
+  active_layer()->UpdateTiles();
+
+  auto* high_res_tiling = active_layer()->HighResTiling();
+  ASSERT_TRUE(high_res_tiling);
+  const std::vector<Tile*>& tiles = high_res_tiling->AllTilesForTesting();
+  ASSERT_GT(tiles.size(), 0u);
+
+  host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting(tiles);
+
+  AppendQuadsData data;
+  active_layer()->WillDraw(DRAW_MODE_HARDWARE, nullptr);
+  active_layer()->AppendQuads(render_pass.get(), &data);
+  active_layer()->DidDraw(nullptr);
+
+  EXPECT_EQ(20u, render_pass->quad_list.size());
+  int last_y = -1;
+  int last_height = -1;
+  int min_y = std::numeric_limits<int>::max();
+  float min_transformed_y = std::numeric_limits<float>::max();
+  float max_transformed_y = -1;
+  for (auto* draw_quad : render_pass->quad_list) {
+    if (last_y == -1) {
+      last_y = draw_quad->rect.y();
+      min_y = last_y;
+      last_height = draw_quad->rect.height();
+    }
+
+    if (last_y != draw_quad->rect.y()) {
+      EXPECT_EQ(last_y + last_height, draw_quad->rect.y());
+      last_y = draw_quad->rect.y();
+      min_y = std::min(min_y, last_y);
+      last_height = draw_quad->rect.height();
+    }
+    EXPECT_LT(last_y, 5000);
+    EXPECT_EQ(draw_quad->material, viz::DrawQuad::TILED_CONTENT);
+
+    auto transform = [draw_quad](const gfx::Rect& rect) {
+      gfx::RectF result(rect);
+      draw_quad->shared_quad_state->quad_to_target_transform.TransformRect(
+          &result);
+      return result;
+    };
+
+    gfx::RectF transformed_rect = transform(draw_quad->rect);
+    EXPECT_GT(transformed_rect.y(), 0);
+    if (min_transformed_y < 0 || transformed_rect.y() < min_transformed_y)
+      min_transformed_y = transformed_rect.y();
+    if (transformed_rect.bottom() > max_transformed_y)
+      max_transformed_y = transformed_rect.bottom();
+
+    gfx::RectF transformed_quad_layer_rect =
+        transform(draw_quad->shared_quad_state->quad_layer_rect);
+    EXPECT_RECTF_EQ(transformed_quad_layer_rect,
+                    gfx::RectF(0.f, 0.f, 1000.f, 10000.f));
+
+    gfx::RectF transformed_visible_quad_layer_rect =
+        transform(draw_quad->shared_quad_state->visible_quad_layer_rect);
+    EXPECT_RECTF_EQ(transformed_visible_quad_layer_rect,
+                    gfx::RectF(0.f, 5000.f, 1000.f, 1000.f));
+  }
+  EXPECT_EQ(min_y, 0);
+  EXPECT_FLOAT_EQ(min_transformed_y, 5000.f);
+  EXPECT_FLOAT_EQ(max_transformed_y, 6000.f);
+}
+
+TEST_F(PictureLayerImplTest, FarScrolledSolidColorQuadsShifted) {
+  std::unique_ptr<viz::RenderPass> render_pass = viz::RenderPass::Create();
+
+  gfx::Size layer_bounds(1000, 10000);
+  scoped_refptr<FakeRasterSource> active_raster_source =
+      FakeRasterSource::CreateFilled(layer_bounds);
+  SetupPendingTree(active_raster_source);
+  ActivateTree();
+
+  active_layer()->SetContentsOpaque(true);
+  active_layer()->draw_properties().visible_layer_rect =
+      gfx::Rect(0, 9000, 1000, 1000);
+  active_layer()->UpdateTiles();
+
+  auto* high_res_tiling = active_layer()->HighResTiling();
+  ASSERT_TRUE(high_res_tiling);
+  const std::vector<Tile*>& tiles = high_res_tiling->AllTilesForTesting();
+  ASSERT_GT(tiles.size(), 0u);
+
+  for (auto* tile : tiles)
+    tile->draw_info().SetSolidColorForTesting(SK_ColorBLUE);
+
+  AppendQuadsData data;
+  active_layer()->WillDraw(DRAW_MODE_HARDWARE, nullptr);
+  active_layer()->AppendQuads(render_pass.get(), &data);
+  active_layer()->DidDraw(nullptr);
+
+  EXPECT_EQ(20u, render_pass->quad_list.size());
+  int last_y = -1;
+  int last_height = -1;
+  int min_y = std::numeric_limits<int>::max();
+  float min_transformed_y = std::numeric_limits<float>::max();
+  float max_transformed_y = -1;
+  for (auto* draw_quad : render_pass->quad_list) {
+    if (last_y == -1) {
+      last_y = draw_quad->rect.y();
+      min_y = last_y;
+      last_height = draw_quad->rect.height();
+    }
+
+    if (last_y != draw_quad->rect.y()) {
+      EXPECT_EQ(last_y + last_height, draw_quad->rect.y());
+      last_y = draw_quad->rect.y();
+      min_y = std::min(min_y, last_y);
+      last_height = draw_quad->rect.height();
+    }
+    EXPECT_LT(last_y, 5000);
+    EXPECT_EQ(draw_quad->material, viz::DrawQuad::SOLID_COLOR);
+
+    auto transform = [draw_quad](const gfx::Rect& rect) {
+      gfx::RectF result(rect);
+      draw_quad->shared_quad_state->quad_to_target_transform.TransformRect(
+          &result);
+      return result;
+    };
+
+    gfx::RectF transformed_rect = transform(draw_quad->rect);
+    EXPECT_GT(transformed_rect.y(), 0);
+    if (transformed_rect.y() < min_transformed_y)
+      min_transformed_y = transformed_rect.y();
+    if (transformed_rect.bottom() > max_transformed_y)
+      max_transformed_y = transformed_rect.bottom();
+
+    gfx::RectF transformed_quad_layer_rect =
+        transform(draw_quad->shared_quad_state->quad_layer_rect);
+    EXPECT_RECTF_EQ(transformed_quad_layer_rect,
+                    gfx::RectF(0.f, 0.f, 1000.f, 10000.f));
+
+    gfx::RectF transformed_visible_quad_layer_rect =
+        transform(draw_quad->shared_quad_state->visible_quad_layer_rect);
+    EXPECT_RECTF_EQ(transformed_visible_quad_layer_rect,
+                    gfx::RectF(0.f, 9000.f, 1000.f, 1000.f));
+  }
+  EXPECT_EQ(min_y, 0);
+  EXPECT_FLOAT_EQ(min_transformed_y, 9000.f);
+  EXPECT_FLOAT_EQ(max_transformed_y, 10000.f);
+}
+
 TEST_F(PictureLayerImplTest, SolidColorLayerHasVisibleFullCoverage) {
   std::unique_ptr<viz::RenderPass> render_pass = viz::RenderPass::Create();
 
diff --git a/cc/layers/render_surface_impl.cc b/cc/layers/render_surface_impl.cc
index 83f5cb36..b40cd3a 100644
--- a/cc/layers/render_surface_impl.cc
+++ b/cc/layers/render_surface_impl.cc
@@ -129,6 +129,10 @@
   return OwningEffectNode()->mask_layer_id != Layer::INVALID_ID;
 }
 
+bool RenderSurfaceImpl::HasMaskingContributingSurface() const {
+  return OwningEffectNode()->has_masking_child;
+}
+
 const FilterOperations& RenderSurfaceImpl::Filters() const {
   return OwningEffectNode()->filters;
 }
diff --git a/cc/layers/render_surface_impl.h b/cc/layers/render_surface_impl.h
index 6082e3c..00b05df 100644
--- a/cc/layers/render_surface_impl.h
+++ b/cc/layers/render_surface_impl.h
@@ -146,6 +146,7 @@
 
   LayerImpl* MaskLayer();
   bool HasMask() const;
+  bool HasMaskingContributingSurface() const;
 
   const FilterOperations& Filters() const;
   const FilterOperations& BackgroundFilters() const;
diff --git a/cc/layers/solid_color_layer_impl.cc b/cc/layers/solid_color_layer_impl.cc
index 0611556..89e1444e 100644
--- a/cc/layers/solid_color_layer_impl.cc
+++ b/cc/layers/solid_color_layer_impl.cc
@@ -73,7 +73,7 @@
       render_pass->CreateAndAppendSharedQuadState();
   PopulateSharedQuadState(shared_quad_state, contents_opaque());
 
-  AppendDebugBorderQuad(render_pass, bounds(), shared_quad_state,
+  AppendDebugBorderQuad(render_pass, gfx::Rect(bounds()), shared_quad_state,
                         append_quads_data);
 
   // TODO(hendrikw): We need to pass the visible content rect rather than
diff --git a/cc/layers/solid_color_scrollbar_layer_impl.cc b/cc/layers/solid_color_scrollbar_layer_impl.cc
index ed23ea2..2ab831c 100644
--- a/cc/layers/solid_color_scrollbar_layer_impl.cc
+++ b/cc/layers/solid_color_scrollbar_layer_impl.cc
@@ -98,7 +98,7 @@
       render_pass->CreateAndAppendSharedQuadState();
   PopulateSharedQuadState(shared_quad_state, contents_opaque());
 
-  AppendDebugBorderQuad(render_pass, bounds(), shared_quad_state,
+  AppendDebugBorderQuad(render_pass, gfx::Rect(bounds()), shared_quad_state,
                         append_quads_data);
 
   gfx::Rect thumb_quad_rect(ComputeThumbQuadRect());
diff --git a/cc/layers/texture_layer_impl.cc b/cc/layers/texture_layer_impl.cc
index 9b99126e..c5aa818 100644
--- a/cc/layers/texture_layer_impl.cc
+++ b/cc/layers/texture_layer_impl.cc
@@ -155,7 +155,7 @@
       render_pass->CreateAndAppendSharedQuadState();
   PopulateSharedQuadState(shared_quad_state, are_contents_opaque);
 
-  AppendDebugBorderQuad(render_pass, bounds(), shared_quad_state,
+  AppendDebugBorderQuad(render_pass, gfx::Rect(bounds()), shared_quad_state,
                         append_quads_data);
 
   gfx::Rect quad_rect(bounds());
diff --git a/cc/layers/ui_resource_layer_impl.cc b/cc/layers/ui_resource_layer_impl.cc
index 0667102c..79d5556 100644
--- a/cc/layers/ui_resource_layer_impl.cc
+++ b/cc/layers/ui_resource_layer_impl.cc
@@ -107,7 +107,7 @@
                   contents_opaque())
                : false;
   PopulateSharedQuadState(shared_quad_state, are_contents_opaque);
-  AppendDebugBorderQuad(render_pass, bounds(), shared_quad_state,
+  AppendDebugBorderQuad(render_pass, gfx::Rect(bounds()), shared_quad_state,
                         append_quads_data);
 
   if (!resource)
diff --git a/cc/layers/video_layer_impl.cc b/cc/layers/video_layer_impl.cc
index 5aebdd9..09c2d861 100644
--- a/cc/layers/video_layer_impl.cc
+++ b/cc/layers/video_layer_impl.cc
@@ -169,13 +169,14 @@
 
   viz::SharedQuadState* shared_quad_state =
       render_pass->CreateAndAppendSharedQuadState();
-  shared_quad_state->SetAll(transform, gfx::Rect(rotated_size),
-                            visible_layer_rect(), clip_rect(), is_clipped(),
-                            contents_opaque(), draw_opacity(),
-                            SkBlendMode::kSrcOver, GetSortingContextId());
+  gfx::Rect rotated_size_rect(rotated_size);
+  shared_quad_state->SetAll(transform, rotated_size_rect, visible_layer_rect(),
+                            clip_rect(), is_clipped(), contents_opaque(),
+                            draw_opacity(), SkBlendMode::kSrcOver,
+                            GetSortingContextId());
 
-  AppendDebugBorderQuad(
-      render_pass, rotated_size, shared_quad_state, append_quads_data);
+  AppendDebugBorderQuad(render_pass, rotated_size_rect, shared_quad_state,
+                        append_quads_data);
 
   gfx::Rect quad_rect(rotated_size);
   gfx::Rect visible_rect = frame_->visible_rect();
diff --git a/cc/paint/paint_image.cc b/cc/paint/paint_image.cc
index c0a255c..567af56 100644
--- a/cc/paint/paint_image.cc
+++ b/cc/paint/paint_image.cc
@@ -99,6 +99,12 @@
   return result;
 }
 
+PaintImage PaintImage::MakeStatic() const {
+  PaintImage result(*this);
+  result.repetition_count_ = kAnimationNone;
+  return result;
+}
+
 SkISize PaintImage::GetSupportedDecodeSize(
     const SkISize& requested_size) const {
   // TODO(vmpstr): If this image is using subset_rect, then we don't support
diff --git a/cc/paint/paint_image.h b/cc/paint/paint_image.h
index 7720344f..26ce684 100644
--- a/cc/paint/paint_image.h
+++ b/cc/paint/paint_image.h
@@ -89,6 +89,10 @@
   // subset must be non-empty and lie within the image bounds.
   PaintImage MakeSubset(const gfx::Rect& subset) const;
 
+  // Makes a new PaintImage representing a static frame of the original image,
+  // which should not be animated by the compositor.
+  PaintImage MakeStatic() const;
+
   bool operator==(const PaintImage& other) const;
 
   // Returns the smallest size that is at least as big as the requested_size
diff --git a/cc/paint/solid_color_analyzer.cc b/cc/paint/solid_color_analyzer.cc
index fe341d2e..79b3a43 100644
--- a/cc/paint/solid_color_analyzer.cc
+++ b/cc/paint/solid_color_analyzer.cc
@@ -45,9 +45,13 @@
          flags.getStyle() == PaintFlags::kFill_Style;
 }
 
-// Returns true if the specified drawn_rect will cover the entire canvas, and
-// that the canvas is not clipped (i.e. it covers ALL of the canvas).
-bool IsFullQuad(const SkCanvas& canvas, const SkRect& drawn_rect) {
+// Returns true if the specified |drawn_shape| will cover the entire canvas
+// and that the canvas is not clipped (i.e. it covers ALL of the canvas).
+template <typename T>
+bool IsFullQuad(const SkCanvas& canvas, const T& drawn_shape) {
+  if (!canvas.isClipRect())
+    return false;
+
   SkIRect clip_irect;
   if (!canvas.getDeviceClipBounds(&clip_irect))
     return false;
@@ -62,11 +66,13 @@
   if (!matrix.rectStaysRect())
     return false;
 
-  SkRect device_rect;
-  matrix.mapRect(&device_rect, drawn_rect);
-  SkRect clip_rect;
-  clip_rect.set(clip_irect);
-  return device_rect.contains(clip_rect);
+  SkMatrix inverse;
+  if (!matrix.invert(&inverse))
+    return false;
+
+  SkRect clip_rect = SkRect::Make(clip_irect);
+  inverse.mapRect(&clip_rect, clip_rect);
+  return drawn_shape.contains(clip_rect);
 }
 
 void CheckIfSolidColor(const SkCanvas& canvas,
@@ -97,18 +103,19 @@
   }
 }
 
-void CheckIfSolidRect(const SkCanvas& canvas,
-                      const SkRect& rect,
-                      const PaintFlags& flags,
-                      bool* is_solid_color,
-                      bool* is_transparent,
-                      SkColor* color) {
+template <typename T>
+void CheckIfSolidShape(const SkCanvas& canvas,
+                       const T& shape,
+                       const PaintFlags& flags,
+                       bool* is_solid_color,
+                       bool* is_transparent,
+                       SkColor* color) {
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
-               "SolidColorAnalyzer::HandleDrawRect");
+               "SolidColorAnalyzer::CheckIfSolidShape");
   if (flags.nothingToDraw())
     return;
 
-  bool does_cover_canvas = IsFullQuad(canvas, rect);
+  bool does_cover_canvas = IsFullQuad(canvas, shape);
   SkBlendMode blendmode = flags.getBlendMode();
   if (does_cover_canvas && ActsLikeClear(blendmode, flags.getAlpha()))
     *is_transparent = true;
@@ -123,6 +130,13 @@
   }
 }
 
+bool CheckIfRRectClipCoversCanvas(const SkCanvas& canvas,
+                                  const SkRRect& rrect) {
+  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
+               "SolidColorAnalyzer::CheckIfRRectClipCoversCanvas");
+  return IsFullQuad(canvas, rrect);
+}
+
 }  // namespace
 
 base::Optional<SkColor> SolidColorAnalyzer::DetermineIfSolidColor(
@@ -160,7 +174,7 @@
   stack.emplace_back(PaintOpBuffer::CompositeIterator(buffer, offsets),
                      canvas.getTotalMatrix(), canvas.getSaveCount());
 
-  int num_ops = 0;
+  int num_draw_ops = 0;
   while (!stack.empty()) {
     auto& frame = stack.back();
     if (!frame.iter) {
@@ -191,7 +205,15 @@
       case PaintOpType::DrawOval:
       case PaintOpType::DrawPath:
         return base::nullopt;
-      case PaintOpType::DrawRRect:
+      // TODO(vmpstr): Add more tests on exceeding max_ops_to_analyze.
+      case PaintOpType::DrawRRect: {
+        if (++num_draw_ops > max_ops_to_analyze)
+          return base::nullopt;
+        const DrawRRectOp* rrect_op = static_cast<const DrawRRectOp*>(op);
+        CheckIfSolidShape(canvas, rrect_op->rrect, rrect_op->flags, &is_solid,
+                          &is_transparent, &color);
+        break;
+      }
       case PaintOpType::DrawTextBlob:
       // Anything that has to do a save layer is probably not solid. As it will
       // likely need more than one draw op.
@@ -202,18 +224,27 @@
       // cover the canvas.
       // TODO(vmpstr): We could investigate handling these.
       case PaintOpType::ClipPath:
-      case PaintOpType::ClipRRect:
         return base::nullopt;
+      case PaintOpType::ClipRRect: {
+        const ClipRRectOp* rrect_op = static_cast<const ClipRRectOp*>(op);
+        bool does_cover_canvas =
+            CheckIfRRectClipCoversCanvas(canvas, rrect_op->rrect);
+        // If the clip covers the full canvas, we can treat it as if there's no
+        // clip at all and continue, otherwise this is no longer a solid color.
+        if (!does_cover_canvas)
+          return base::nullopt;
+        break;
+      }
       case PaintOpType::DrawRect: {
-        if (++num_ops > max_ops_to_analyze)
+        if (++num_draw_ops > max_ops_to_analyze)
           return base::nullopt;
         const DrawRectOp* rect_op = static_cast<const DrawRectOp*>(op);
-        CheckIfSolidRect(canvas, rect_op->rect, rect_op->flags, &is_solid,
-                         &is_transparent, &color);
+        CheckIfSolidShape(canvas, rect_op->rect, rect_op->flags, &is_solid,
+                          &is_transparent, &color);
         break;
       }
       case PaintOpType::DrawColor: {
-        if (++num_ops > max_ops_to_analyze)
+        if (++num_draw_ops > max_ops_to_analyze)
           return base::nullopt;
         const DrawColorOp* color_op = static_cast<const DrawColorOp*>(op);
         CheckIfSolidColor(canvas, color_op->color, color_op->mode, &is_solid,
diff --git a/cc/paint/solid_color_analyzer_unittest.cc b/cc/paint/solid_color_analyzer_unittest.cc
index a944cc6f..c73cbe9 100644
--- a/cc/paint/solid_color_analyzer_unittest.cc
+++ b/cc/paint/solid_color_analyzer_unittest.cc
@@ -29,6 +29,11 @@
     buffer_ = nullptr;
   }
 
+  void Reset() {
+    TearDown();
+    SetUp();
+  }
+
   void Initialize(const gfx::Rect& rect = gfx::Rect(0, 0, 100, 100)) {
     canvas_.emplace(display_item_list_.get(), gfx::RectToSkRect(rect));
     rect_ = rect;
@@ -127,6 +132,21 @@
   EXPECT_EQ(color, GetColor());
 }
 
+// TODO(vmpstr): Generalize the DrawRect test cases so that we can test both
+// Rect and RRect.
+TEST_F(SolidColorAnalyzerTest, DrawRRect) {
+  SkRect rect = SkRect::MakeWH(200, 200);
+  SkRRect rrect;
+  rrect.setRectXY(rect, 5, 5);
+  gfx::Rect canvas_rect(5, 5, 190, 190);
+  Initialize(canvas_rect);
+  PaintFlags flags;
+  SkColor color = SkColorSetARGB(255, 11, 22, 33);
+  flags.setColor(color);
+  canvas()->drawRRect(rrect, flags);
+  EXPECT_EQ(color, GetColor());
+}
+
 TEST_F(SolidColorAnalyzerTest, DrawRectClipped) {
   Initialize();
   PaintFlags flags;
@@ -278,5 +298,85 @@
   EXPECT_FALSE(IsSolidColor());
 }
 
+TEST_F(SolidColorAnalyzerTest, ClipRRectCoversCanvas) {
+  SkVector radii[4] = {
+      SkVector::Make(10.0, 15.0), SkVector::Make(20.0, 25.0),
+      SkVector::Make(30.0, 35.0), SkVector::Make(40.0, 45.0),
+  };
+
+  SkVector radii_scale[4] = {
+      SkVector::Make(100.0, 150.0), SkVector::Make(200.0, 250.0),
+      SkVector::Make(300.0, 350.0), SkVector::Make(400.0, 450.0),
+  };
+
+  int rr_size = 600;
+  int canvas_size = 255;
+  gfx::Rect canvas_rect(canvas_size, canvas_size);
+  PaintFlags flags;
+  flags.setColor(SK_ColorWHITE);
+
+  struct {
+    SkVector offset;
+    SkVector offset_scale;
+    bool expected;
+  } cases[] = {
+      // Not within bounding box of |rr|.
+      {SkVector::Make(100, 100), SkVector::Make(100, 100), false},
+
+      // Intersects UL corner.
+      {SkVector::Make(0, 0), SkVector::Make(0, 0), false},
+
+      // Between UL and UR.
+      {SkVector::Make(-50, 0), SkVector::Make(-50, -15), true},
+
+      // Intersects UR corner.
+      {SkVector::Make(canvas_size - rr_size, 0),
+       SkVector::Make(canvas_size - rr_size, 0), false},
+
+      // Between UR and LR.
+      {SkVector::Make(canvas_size - rr_size, -50), SkVector::Make(-305, -80),
+       true},
+
+      // Intersects LR corner.
+      {SkVector::Make(canvas_size - rr_size, canvas_size - rr_size),
+       SkVector::Make(canvas_size - rr_size, canvas_size - rr_size), false},
+
+      // Between LL and LR
+      {SkVector::Make(-50, canvas_size - rr_size), SkVector::Make(-205, -310),
+       true},
+
+      // Intersects LL corner
+      {SkVector::Make(0, canvas_size - rr_size),
+       SkVector::Make(0, canvas_size - rr_size), false},
+
+      // Between UL and LL
+      {SkVector::Make(0, -50), SkVector::Make(-15, -60), true},
+
+      // In center
+      {SkVector::Make(-100, -100), SkVector::Make(-100, -100), true},
+  };
+
+  for (int case_scale = 0; case_scale < 2; ++case_scale) {
+    bool scaled = case_scale > 0;
+    for (size_t i = 0; i < arraysize(cases); ++i) {
+      Reset();
+      Initialize(canvas_rect);
+
+      SkRect bounding_rect = SkRect::MakeXYWH(
+          scaled ? cases[i].offset_scale.x() : cases[i].offset.x(),
+          scaled ? cases[i].offset_scale.y() : cases[i].offset.y(), rr_size,
+          rr_size);
+
+      SkRRect rr;
+      rr.setRectRadii(bounding_rect, scaled ? radii_scale : radii);
+
+      canvas()->clipRRect(rr, SkClipOp::kIntersect, false);
+      canvas()->drawRect(RectToSkRect(canvas_rect), flags);
+      EXPECT_EQ(cases[i].expected, IsSolidColor())
+          << "Case " << i << ", " << scaled << " failed.";
+    }
+  }
+}
+
 }  // namespace
 }  // namespace cc
diff --git a/cc/raster/playback_image_provider.cc b/cc/raster/playback_image_provider.cc
index 86bc53b..f2a6682 100644
--- a/cc/raster/playback_image_provider.cc
+++ b/cc/raster/playback_image_provider.cc
@@ -18,18 +18,12 @@
 }  // namespace
 
 PlaybackImageProvider::PlaybackImageProvider(
-    bool skip_all_images,
-    PaintImageIdFlatSet images_to_skip,
-    std::vector<DrawImage> at_raster_images,
     ImageDecodeCache* cache,
     const gfx::ColorSpace& target_color_space,
-    base::flat_map<PaintImage::Id, size_t> image_to_current_frame_index)
-    : skip_all_images_(skip_all_images),
-      images_to_skip_(std::move(images_to_skip)),
-      at_raster_images_(std::move(at_raster_images)),
-      cache_(cache),
+    base::Optional<Settings> settings)
+    : cache_(cache),
       target_color_space_(target_color_space),
-      image_to_current_frame_index_(std::move(image_to_current_frame_index)) {
+      settings_(std::move(settings)) {
   DCHECK(cache_);
 }
 
@@ -47,7 +41,11 @@
   DCHECK(decoded_at_raster_.empty());
   DCHECK(!in_raster_);
   in_raster_ = true;
-  for (auto& draw_image : at_raster_images_)
+
+  if (!settings_.has_value())
+    return;
+
+  for (auto& draw_image : settings_->at_raster_images)
     decoded_at_raster_.push_back(GetDecodedDrawImage(draw_image));
 }
 
@@ -61,14 +59,14 @@
 PlaybackImageProvider::GetDecodedDrawImage(const DrawImage& draw_image) {
   DCHECK(in_raster_);
 
-  // Return an empty decoded images if we are skipping all images during this
+  // Return an empty decoded image if we are skipping all images during this
   // raster.
-  if (skip_all_images_)
+  if (!settings_.has_value())
     return ScopedDecodedDrawImage();
 
   const PaintImage& paint_image = draw_image.paint_image();
 
-  if (images_to_skip_.count(paint_image.stable_id()) != 0) {
+  if (settings_->images_to_skip.count(paint_image.stable_id()) != 0) {
     DCHECK(paint_image.GetSkImage()->isLazyGenerated());
     return ScopedDecodedDrawImage();
   }
@@ -79,8 +77,9 @@
                          SkSize::Make(1.f, 1.f), draw_image.filter_quality()));
   }
 
-  const auto& it = image_to_current_frame_index_.find(paint_image.stable_id());
-  size_t frame_index = it == image_to_current_frame_index_.end()
+  const auto& it =
+      settings_->image_to_current_frame_index.find(paint_image.stable_id());
+  size_t frame_index = it == settings_->image_to_current_frame_index.end()
                            ? paint_image.frame_index()
                            : it->second;
 
@@ -92,4 +91,8 @@
       base::BindOnce(&UnrefImageFromCache, std::move(adjusted_image), cache_));
 }
 
+PlaybackImageProvider::Settings::Settings() = default;
+PlaybackImageProvider::Settings::Settings(const Settings& other) = default;
+PlaybackImageProvider::Settings::~Settings() = default;
+
 }  // namespace cc
diff --git a/cc/raster/playback_image_provider.h b/cc/raster/playback_image_provider.h
index ddd2633c..bae8c25 100644
--- a/cc/raster/playback_image_provider.h
+++ b/cc/raster/playback_image_provider.h
@@ -15,20 +15,31 @@
 class ImageDecodeCache;
 
 // PlaybackImageProvider is used to replace lazy generated PaintImages with
-// decoded images for raster from the ImageDecodeCache. The following settings
-// can be used to modify rasterization of these images:
-// 1) skip_all_images: Ensures that no images are decoded or rasterized.
-// 2) images_to_skip: Used to selectively skip images during raster. This should
-//    only be used for lazy generated images.
+// decoded images for raster from the ImageDecodeCache.
 class CC_EXPORT PlaybackImageProvider : public ImageProvider {
  public:
-  PlaybackImageProvider(
-      bool skip_all_images,
-      PaintImageIdFlatSet images_to_skip,
-      std::vector<DrawImage> at_raster_images,
-      ImageDecodeCache* cache,
-      const gfx::ColorSpace& taget_color_space,
-      base::flat_map<PaintImage::Id, size_t> image_to_current_frame_index);
+  struct CC_EXPORT Settings {
+    Settings();
+    Settings(const Settings& other);
+    ~Settings();
+
+    // The set of image ids to skip during raster.
+    PaintImageIdFlatSet images_to_skip;
+
+    // The set of images which must be decoded by the provider before beginning
+    // raster. The images are decoded and locked by the provider in BeginRaster
+    // and unlocked in EndRaster.
+    std::vector<DrawImage> at_raster_images;
+
+    // The frame index to use for the given image id. If no index is provided,
+    // the frame index provided in the PaintImage will be used.
+    base::flat_map<PaintImage::Id, size_t> image_to_current_frame_index;
+  };
+
+  // If no settings are provided, all images are skipped during rasterization.
+  PlaybackImageProvider(ImageDecodeCache* cache,
+                        const gfx::ColorSpace& target_color_space,
+                        base::Optional<Settings> settings);
   ~PlaybackImageProvider() override;
 
   void BeginRaster() override;
@@ -42,14 +53,12 @@
       const DrawImage& draw_image) override;
 
  private:
-  bool skip_all_images_;
-  bool in_raster_ = false;
-  PaintImageIdFlatSet images_to_skip_;
-  std::vector<DrawImage> at_raster_images_;
-  std::vector<ImageProvider::ScopedDecodedDrawImage> decoded_at_raster_;
   ImageDecodeCache* cache_;
   gfx::ColorSpace target_color_space_;
-  base::flat_map<PaintImage::Id, size_t> image_to_current_frame_index_;
+  base::Optional<Settings> settings_;
+
+  bool in_raster_ = false;
+  std::vector<ImageProvider::ScopedDecodedDrawImage> decoded_at_raster_;
 
   DISALLOW_COPY_AND_ASSIGN(PlaybackImageProvider);
 };
diff --git a/cc/raster/playback_image_provider_unittest.cc b/cc/raster/playback_image_provider_unittest.cc
index 153b484..2365eb3 100644
--- a/cc/raster/playback_image_provider_unittest.cc
+++ b/cc/raster/playback_image_provider_unittest.cc
@@ -55,7 +55,7 @@
 
 TEST(PlaybackImageProviderTest, SkipsAllImages) {
   MockDecodeCache cache;
-  PlaybackImageProvider provider(true, {}, {}, &cache, gfx::ColorSpace(), {});
+  PlaybackImageProvider provider(&cache, gfx::ColorSpace(), base::nullopt);
   provider.BeginRaster();
 
   SkIRect rect = SkIRect::MakeWH(10, 10);
@@ -79,8 +79,12 @@
 TEST(PlaybackImageProviderTest, SkipsSomeImages) {
   MockDecodeCache cache;
   PaintImage skip_image = CreateDiscardablePaintImage(gfx::Size(10, 10));
-  PlaybackImageProvider provider(false, {skip_image.stable_id()}, {}, &cache,
-                                 gfx::ColorSpace(), {});
+
+  base::Optional<PlaybackImageProvider::Settings> settings;
+  settings.emplace();
+  settings->images_to_skip = {skip_image.stable_id()};
+
+  PlaybackImageProvider provider(&cache, gfx::ColorSpace(), settings);
   provider.BeginRaster();
 
   SkIRect rect = SkIRect::MakeWH(10, 10);
@@ -93,7 +97,10 @@
 
 TEST(PlaybackImageProviderTest, RefAndUnrefDecode) {
   MockDecodeCache cache;
-  PlaybackImageProvider provider(false, {}, {}, &cache, gfx::ColorSpace(), {});
+
+  base::Optional<PlaybackImageProvider::Settings> settings;
+  settings.emplace();
+  PlaybackImageProvider provider(&cache, gfx::ColorSpace(), settings);
   provider.BeginRaster();
 
   {
@@ -122,8 +129,11 @@
   auto draw_image2 = CreateDiscardableDrawImage(
       size, nullptr, rect, kMedium_SkFilterQuality, matrix);
 
-  PlaybackImageProvider provider(false, {}, {draw_image1, draw_image2}, &cache,
-                                 gfx::ColorSpace(), {});
+  base::Optional<PlaybackImageProvider::Settings> settings;
+  settings.emplace();
+  settings->at_raster_images = {draw_image1, draw_image2};
+
+  PlaybackImageProvider provider(&cache, gfx::ColorSpace(), settings);
 
   EXPECT_EQ(cache.refed_image_count(), 0);
   provider.BeginRaster();
@@ -144,8 +154,11 @@
 
   base::flat_map<PaintImage::Id, size_t> image_to_frame;
   image_to_frame[image.stable_id()] = 1u;
-  PlaybackImageProvider provider(false, {}, {}, &cache, gfx::ColorSpace(),
-                                 image_to_frame);
+  base::Optional<PlaybackImageProvider::Settings> settings;
+  settings.emplace();
+  settings->image_to_current_frame_index = image_to_frame;
+
+  PlaybackImageProvider provider(&cache, gfx::ColorSpace(), settings);
   provider.BeginRaster();
 
   SkIRect rect = SkIRect::MakeWH(10, 10);
diff --git a/cc/test/layer_tree_pixel_test.h b/cc/test/layer_tree_pixel_test.h
index d54a8545..20cf30e 100644
--- a/cc/test/layer_tree_pixel_test.h
+++ b/cc/test/layer_tree_pixel_test.h
@@ -97,6 +97,7 @@
   static const SkColor kCSSOrange = 0xffffa500;
   static const SkColor kCSSBrown = 0xffa52a2a;
   static const SkColor kCSSGreen = 0xff008000;
+  static const SkColor kCSSBlack = 0xff000000;
 
   gl::DisableNullDrawGLBindings enable_pixel_output_;
   std::unique_ptr<PixelComparator> pixel_comparator_;
diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc
index 2bc4f83..2b2f416d 100644
--- a/cc/tiles/tile_manager.cc
+++ b/cc/tiles/tile_manager.cc
@@ -1186,10 +1186,17 @@
   const bool has_at_raster_images = !at_raster_images.empty();
   if (skip_images || has_checker_images || has_sync_decoded_images ||
       has_at_raster_images) {
-    image_provider.emplace(skip_images, std::move(images_to_skip),
-                           std::move(at_raster_images),
-                           image_controller_.cache(), color_space,
-                           std::move(image_id_to_current_frame_index));
+    base::Optional<PlaybackImageProvider::Settings> settings;
+    if (!skip_images) {
+      settings.emplace();
+      settings->images_to_skip = std::move(images_to_skip);
+      settings->at_raster_images = std::move(at_raster_images);
+      settings->image_to_current_frame_index =
+          std::move(image_id_to_current_frame_index);
+    }
+
+    image_provider.emplace(image_controller_.cache(), color_space,
+                           std::move(settings));
   }
 
   return base::MakeRefCounted<RasterTaskImpl>(
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc
index e458ba70..a794bd3 100644
--- a/cc/trees/draw_property_utils.cc
+++ b/cc/trees/draw_property_utils.cc
@@ -1009,6 +1009,7 @@
                                    property_trees->transform_tree);
   mask_layer->draw_properties().visible_layer_rect =
       gfx::Rect(mask_layer->bounds());
+  mask_layer->draw_properties().opacity = 1;
 }
 
 void ComputeSurfaceDrawProperties(PropertyTrees* property_trees,
diff --git a/cc/trees/effect_node.cc b/cc/trees/effect_node.cc
index f411d05..3a0669e 100644
--- a/cc/trees/effect_node.cc
+++ b/cc/trees/effect_node.cc
@@ -28,6 +28,7 @@
       has_potential_opacity_animation(false),
       is_currently_animating_filter(false),
       is_currently_animating_opacity(false),
+      has_masking_child(false),
       effect_changed(false),
       subtree_has_copy_request(false),
       transform_id(0),
@@ -63,6 +64,7 @@
          is_currently_animating_filter == other.is_currently_animating_filter &&
          is_currently_animating_opacity ==
              other.is_currently_animating_opacity &&
+         has_masking_child == other.has_masking_child &&
          effect_changed == other.effect_changed &&
          subtree_has_copy_request == other.subtree_has_copy_request &&
          transform_id == other.transform_id && clip_id == other.clip_id &&
diff --git a/cc/trees/effect_node.h b/cc/trees/effect_node.h
index 954b4b1..ecf3c90 100644
--- a/cc/trees/effect_node.h
+++ b/cc/trees/effect_node.h
@@ -68,6 +68,8 @@
   bool is_currently_animating_filter : 1;
   // Whether this node has a currently running opacity animation.
   bool is_currently_animating_opacity : 1;
+  // Whether this node has a child node with kDstIn blend mode.
+  bool has_masking_child : 1;
   // Whether this node's effect has been changed since the last
   // frame. Needed in order to compute damage rect.
   bool effect_changed : 1;
diff --git a/cc/trees/layer_tree_host_pixeltest_masks.cc b/cc/trees/layer_tree_host_pixeltest_masks.cc
index 8000f95..d095173 100644
--- a/cc/trees/layer_tree_host_pixeltest_masks.cc
+++ b/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -17,6 +17,7 @@
 #include "cc/test/layer_tree_pixel_resource_test.h"
 #include "cc/test/pixel_comparator.h"
 #include "cc/test/solid_color_content_layer_client.h"
+#include "components/viz/test/test_layer_tree_frame_sink.h"
 #include "third_party/skia/include/core/SkImage.h"
 
 #if !defined(OS_ANDROID)
@@ -380,6 +381,343 @@
                            FILE_PATH_LITERAL("mask_of_layer_with_blend.png")));
 }
 
+class StaticPictureLayer : private ContentLayerClient, public PictureLayer {
+ public:
+  static scoped_refptr<StaticPictureLayer> Create(
+      scoped_refptr<DisplayItemList> display_list) {
+    return base::WrapRefCounted(
+        new StaticPictureLayer(std::move(display_list)));
+  }
+
+  gfx::Rect PaintableRegion() override { return gfx::Rect(bounds()); }
+  scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
+      PaintingControlSetting) override {
+    return display_list_;
+  }
+  bool FillsBoundsCompletely() const override { return false; }
+  size_t GetApproximateUnsharedMemoryUsage() const override { return 0; }
+
+ protected:
+  explicit StaticPictureLayer(scoped_refptr<DisplayItemList> display_list)
+      : PictureLayer(this), display_list_(std::move(display_list)) {}
+  ~StaticPictureLayer() override {}
+
+ private:
+  scoped_refptr<DisplayItemList> display_list_;
+};
+
+class LayerTreeHostMaskAsBlendingPixelTest
+    : public LayerTreeHostPixelResourceTest,
+      public ::testing::WithParamInterface<int> {
+ public:
+  LayerTreeHostMaskAsBlendingPixelTest()
+      : LayerTreeHostPixelResourceTest(
+            GetParam() ? GL_ZERO_COPY_RECT_DRAW : SOFTWARE,
+            Layer::LayerMaskType::SINGLE_TEXTURE_MASK),
+        use_antialiasing_(GetParam() == 2 || GetParam() == 4),
+        force_shaders_(GetParam() == 3 || GetParam() == 4) {
+    float percentage_pixels_small_error = 0.f;
+    float percentage_pixels_error = 0.f;
+    float average_error_allowed_in_bad_pixels = 0.f;
+    int large_error_allowed = 0;
+    int small_error_allowed = 0;
+    if (use_antialiasing_) {
+      percentage_pixels_small_error = 0.9f;
+      percentage_pixels_error = 6.7f;
+      average_error_allowed_in_bad_pixels = 3.5f;
+      large_error_allowed = 15;
+      small_error_allowed = 1;
+    } else if (test_type_ != PIXEL_TEST_SOFTWARE) {
+      percentage_pixels_small_error = 0.9f;
+      percentage_pixels_error = 6.5f;
+      average_error_allowed_in_bad_pixels = 3.5f;
+      large_error_allowed = 15;
+      small_error_allowed = 1;
+    }
+
+    pixel_comparator_.reset(new FuzzyPixelComparator(
+        false,  // discard_alpha
+        percentage_pixels_error, percentage_pixels_small_error,
+        average_error_allowed_in_bad_pixels, large_error_allowed,
+        small_error_allowed));
+  }
+
+  static scoped_refptr<Layer> CreateCheckerboardLayer(const gfx::Size& bounds) {
+    constexpr int kGridSize = 8;
+    static const SkColor color_even = SkColorSetRGB(153, 153, 153);
+    static const SkColor color_odd = SkColorSetRGB(102, 102, 102);
+
+    auto display_list = base::MakeRefCounted<DisplayItemList>();
+    display_list->StartPaint();
+    display_list->push<DrawColorOp>(color_even, SkBlendMode::kSrc);
+    PaintFlags flags;
+    flags.setColor(color_odd);
+    for (int j = 0; j < (bounds.height() + kGridSize - 1) / kGridSize; j++) {
+      for (int i = 0; i < (bounds.width() + kGridSize - 1) / kGridSize; i++) {
+        bool is_odd_grid = (i ^ j) & 1;
+        if (!is_odd_grid)
+          continue;
+        display_list->push<DrawRectOp>(
+            SkRect::MakeXYWH(i * kGridSize, j * kGridSize, kGridSize,
+                             kGridSize),
+            flags);
+      }
+    }
+    display_list->EndPaintOfUnpaired(gfx::Rect(bounds));
+    display_list->Finalize();
+
+    scoped_refptr<Layer> layer =
+        StaticPictureLayer::Create(std::move(display_list));
+    layer->SetIsDrawable(true);
+    layer->SetBounds(bounds);
+    return layer;
+  }
+
+  static scoped_refptr<Layer> CreateTestPatternLayer(const gfx::Size& bounds,
+                                                     int grid_size) {
+    // Creates a layer consists of solid grids. The grids are in a mix of
+    // different transparency and colors (1 transparent, 3 semi-transparent,
+    // and 3 opaque).
+    static SkColor test_colors[7] = {
+        SkColorSetARGB(128, 255, 0, 0), SkColorSetARGB(255, 0, 0, 255),
+        SkColorSetARGB(128, 0, 255, 0), SkColorSetARGB(128, 0, 0, 255),
+        SkColorSetARGB(255, 0, 255, 0), SkColorSetARGB(0, 0, 0, 0),
+        SkColorSetARGB(255, 255, 0, 0)};
+
+    auto display_list = base::MakeRefCounted<DisplayItemList>();
+    display_list->StartPaint();
+    for (int j = 0; j < (bounds.height() + grid_size - 1) / grid_size; j++) {
+      for (int i = 0; i < (bounds.width() + grid_size - 1) / grid_size; i++) {
+        PaintFlags flags;
+        flags.setColor(test_colors[(i + j * 3) % arraysize(test_colors)]);
+        display_list->push<DrawRectOp>(
+            SkRect::MakeXYWH(i * grid_size, j * grid_size, grid_size,
+                             grid_size),
+            flags);
+      }
+    }
+    display_list->EndPaintOfUnpaired(gfx::Rect(bounds));
+    display_list->Finalize();
+
+    scoped_refptr<Layer> layer =
+        StaticPictureLayer::Create(std::move(display_list));
+    layer->SetIsDrawable(true);
+    layer->SetBounds(bounds);
+    return layer;
+  }
+
+ protected:
+  std::unique_ptr<viz::TestLayerTreeFrameSink> CreateLayerTreeFrameSink(
+      const viz::RendererSettings& renderer_settings,
+      double refresh_rate,
+      scoped_refptr<viz::ContextProvider> compositor_context_provider,
+      scoped_refptr<viz::ContextProvider> worker_context_provider) override {
+    viz::RendererSettings modified_renderer_settings = renderer_settings;
+    modified_renderer_settings.force_antialiasing = use_antialiasing_;
+    modified_renderer_settings.force_blending_with_shaders = force_shaders_;
+    return LayerTreeHostPixelResourceTest::CreateLayerTreeFrameSink(
+        modified_renderer_settings, refresh_rate,
+        std::move(compositor_context_provider),
+        std::move(worker_context_provider));
+  }
+
+  bool use_antialiasing_;
+  bool force_shaders_;
+};
+
+INSTANTIATE_TEST_CASE_P(All,
+                        LayerTreeHostMaskAsBlendingPixelTest,
+                        ::testing::Range(0, 5));
+// Instantiate 5 test modes of the following:
+// 0: SOFTWARE (golden sample)
+// 1: GL
+// 2: GL + AA
+// 3: GL + Forced Shaders
+// 4: GL + Forced Shaders + AA
+
+TEST_P(LayerTreeHostMaskAsBlendingPixelTest, PixelAlignedNoop) {
+  // This test verifies the degenerate case of a no-op mask doesn't affect
+  // the contents in any way.
+  scoped_refptr<Layer> root = CreateCheckerboardLayer(gfx::Size(400, 300));
+
+  scoped_refptr<Layer> mask_isolation = Layer::Create();
+  mask_isolation->SetPosition(gfx::PointF(20, 20));
+  mask_isolation->SetBounds(gfx::Size(350, 250));
+  mask_isolation->SetMasksToBounds(true);
+  mask_isolation->SetIsRootForIsolatedGroup(true);
+  root->AddChild(mask_isolation);
+
+  scoped_refptr<Layer> content =
+      CreateTestPatternLayer(gfx::Size(400, 300), 25);
+  content->SetPosition(gfx::PointF(-40, -40));
+  mask_isolation->AddChild(content);
+
+  scoped_refptr<Layer> mask_layer =
+      CreateSolidColorLayer(gfx::Rect(350, 250), kCSSBlack);
+  mask_layer->SetBlendMode(SkBlendMode::kDstIn);
+  mask_isolation->AddChild(mask_layer);
+
+  RunPixelResourceTest(
+      root, base::FilePath(FILE_PATH_LITERAL("mask_as_blending_noop.png")));
+}
+
+TEST_P(LayerTreeHostMaskAsBlendingPixelTest, PixelAlignedClippedCircle) {
+  // This test verifies a simple pixel aligned mask applies correctly.
+  scoped_refptr<Layer> root = CreateCheckerboardLayer(gfx::Size(400, 300));
+
+  scoped_refptr<Layer> mask_isolation = Layer::Create();
+  mask_isolation->SetPosition(gfx::PointF(20, 20));
+  mask_isolation->SetBounds(gfx::Size(350, 250));
+  mask_isolation->SetMasksToBounds(true);
+  mask_isolation->SetIsRootForIsolatedGroup(true);
+  root->AddChild(mask_isolation);
+
+  scoped_refptr<Layer> content =
+      CreateTestPatternLayer(gfx::Size(400, 300), 25);
+  content->SetPosition(gfx::PointF(-40, -40));
+  mask_isolation->AddChild(content);
+
+  auto display_list = base::MakeRefCounted<DisplayItemList>();
+  display_list->StartPaint();
+  PaintFlags flags;
+  flags.setColor(kCSSBlack);
+  flags.setAntiAlias(true);
+  display_list->push<DrawOvalOp>(SkRect::MakeXYWH(-5, -55, 360, 360), flags);
+  display_list->EndPaintOfUnpaired(gfx::Rect(-5, -55, 360, 360));
+  display_list->Finalize();
+  scoped_refptr<Layer> mask_layer =
+      StaticPictureLayer::Create(std::move(display_list));
+  mask_layer->SetIsDrawable(true);
+  mask_layer->SetBounds(gfx::Size(350, 250));
+  mask_layer->SetBlendMode(SkBlendMode::kDstIn);
+  mask_isolation->AddChild(mask_layer);
+
+  RunPixelResourceTest(
+      root, base::FilePath(FILE_PATH_LITERAL("mask_as_blending_circle.png")));
+}
+
+TEST_P(LayerTreeHostMaskAsBlendingPixelTest,
+       PixelAlignedClippedCircleUnderflow) {
+  // This test verifies a simple pixel aligned mask applies correctly when
+  // the content is smaller than the mask.
+  scoped_refptr<Layer> root = CreateCheckerboardLayer(gfx::Size(400, 300));
+
+  scoped_refptr<Layer> mask_isolation = Layer::Create();
+  mask_isolation->SetPosition(gfx::PointF(20, 20));
+  mask_isolation->SetBounds(gfx::Size(350, 250));
+  mask_isolation->SetMasksToBounds(true);
+  mask_isolation->SetIsRootForIsolatedGroup(true);
+  root->AddChild(mask_isolation);
+
+  scoped_refptr<Layer> content =
+      CreateTestPatternLayer(gfx::Size(330, 230), 25);
+  content->SetPosition(gfx::PointF(10, 10));
+  mask_isolation->AddChild(content);
+
+  auto display_list = base::MakeRefCounted<DisplayItemList>();
+  display_list->StartPaint();
+  PaintFlags flags;
+  flags.setColor(kCSSBlack);
+  flags.setAntiAlias(true);
+  display_list->push<DrawOvalOp>(SkRect::MakeXYWH(-5, -55, 360, 360), flags);
+  display_list->EndPaintOfUnpaired(gfx::Rect(-5, -55, 360, 360));
+  display_list->Finalize();
+  scoped_refptr<Layer> mask_layer =
+      StaticPictureLayer::Create(std::move(display_list));
+  mask_layer->SetIsDrawable(true);
+  mask_layer->SetBounds(gfx::Size(350, 250));
+  mask_layer->SetBlendMode(SkBlendMode::kDstIn);
+  mask_isolation->AddChild(mask_layer);
+
+  RunPixelResourceTest(root, base::FilePath(FILE_PATH_LITERAL(
+                                 "mask_as_blending_circle_underflow.png")));
+}
+
+TEST_P(LayerTreeHostMaskAsBlendingPixelTest, RotatedClippedCircle) {
+  // This test verifies a simple pixel aligned mask that is not pixel aligned
+  // to its target surface is rendered correctly.
+  scoped_refptr<Layer> root = CreateCheckerboardLayer(gfx::Size(400, 300));
+
+  scoped_refptr<Layer> mask_isolation = Layer::Create();
+  mask_isolation->SetPosition(gfx::PointF(20, 20));
+  {
+    gfx::Transform rotate;
+    rotate.Rotate(5.f);
+    mask_isolation->SetTransform(rotate);
+  }
+  mask_isolation->SetBounds(gfx::Size(350, 250));
+  mask_isolation->SetMasksToBounds(true);
+  mask_isolation->SetIsRootForIsolatedGroup(true);
+  root->AddChild(mask_isolation);
+
+  scoped_refptr<Layer> content =
+      CreateTestPatternLayer(gfx::Size(400, 300), 25);
+  content->SetPosition(gfx::PointF(-40, -40));
+  mask_isolation->AddChild(content);
+
+  auto display_list = base::MakeRefCounted<DisplayItemList>();
+  display_list->StartPaint();
+  PaintFlags flags;
+  flags.setColor(kCSSBlack);
+  flags.setAntiAlias(true);
+  display_list->push<DrawOvalOp>(SkRect::MakeXYWH(-5, -55, 360, 360), flags);
+  display_list->EndPaintOfUnpaired(gfx::Rect(-5, -55, 360, 360));
+  display_list->Finalize();
+  scoped_refptr<Layer> mask_layer =
+      StaticPictureLayer::Create(std::move(display_list));
+  mask_layer->SetIsDrawable(true);
+  mask_layer->SetBounds(gfx::Size(350, 250));
+  mask_layer->SetBlendMode(SkBlendMode::kDstIn);
+  mask_isolation->AddChild(mask_layer);
+
+  RunPixelResourceTest(
+      root,
+      base::FilePath(FILE_PATH_LITERAL("mask_as_blending_rotated_circle.png")));
+}
+
+TEST_P(LayerTreeHostMaskAsBlendingPixelTest, RotatedClippedCircleUnderflow) {
+  // This test verifies a simple pixel aligned mask that is not pixel aligned
+  // to its target surface, and has the content smaller than the mask, is
+  // rendered correctly.
+  scoped_refptr<Layer> root = CreateCheckerboardLayer(gfx::Size(400, 300));
+
+  scoped_refptr<Layer> mask_isolation = Layer::Create();
+  mask_isolation->SetPosition(gfx::PointF(20, 20));
+  {
+    gfx::Transform rotate;
+    rotate.Rotate(5.f);
+    mask_isolation->SetTransform(rotate);
+  }
+  mask_isolation->SetBounds(gfx::Size(350, 250));
+  mask_isolation->SetMasksToBounds(true);
+  mask_isolation->SetIsRootForIsolatedGroup(true);
+  root->AddChild(mask_isolation);
+
+  scoped_refptr<Layer> content =
+      CreateTestPatternLayer(gfx::Size(330, 230), 25);
+  content->SetPosition(gfx::PointF(10, 10));
+  mask_isolation->AddChild(content);
+
+  auto display_list = base::MakeRefCounted<DisplayItemList>();
+  display_list->StartPaint();
+  PaintFlags flags;
+  flags.setColor(kCSSBlack);
+  flags.setAntiAlias(true);
+  display_list->push<DrawOvalOp>(SkRect::MakeXYWH(-5, -55, 360, 360), flags);
+  display_list->EndPaintOfUnpaired(gfx::Rect(-5, -55, 360, 360));
+  display_list->Finalize();
+  scoped_refptr<Layer> mask_layer =
+      StaticPictureLayer::Create(std::move(display_list));
+  mask_layer->SetIsDrawable(true);
+  mask_layer->SetBounds(gfx::Size(350, 250));
+  mask_layer->SetBlendMode(SkBlendMode::kDstIn);
+  mask_isolation->AddChild(mask_layer);
+
+  RunPixelResourceTest(root,
+                       base::FilePath(FILE_PATH_LITERAL(
+                           "mask_as_blending_rotated_circle_underflow.png")));
+}
+
 }  // namespace
 }  // namespace cc
 
diff --git a/cc/trees/layer_tree_impl_unittest.cc b/cc/trees/layer_tree_impl_unittest.cc
index fef1cac..40c039d 100644
--- a/cc/trees/layer_tree_impl_unittest.cc
+++ b/cc/trees/layer_tree_impl_unittest.cc
@@ -14,7 +14,6 @@
 #include "cc/trees/draw_property_utils.h"
 #include "cc/trees/layer_tree_host_common.h"
 #include "cc/trees/layer_tree_host_impl.h"
-#include "cc/trees/mutable_properties.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -1996,52 +1995,6 @@
   EXPECT_TRUE(output.start.visible());
 }
 
-TEST_F(LayerTreeImplTest, NodesiesForProxies) {
-  LayerImpl* root = root_layer();
-  root->SetDrawsContent(true);
-  root->SetBounds(gfx::Size(100, 100));
-
-  uint32_t properties[] = {
-      MutableProperty::kOpacity, MutableProperty::kScrollLeft,
-      MutableProperty::kScrollTop, MutableProperty::kTransform,
-  };
-
-  for (size_t i = 0; i < arraysize(properties); ++i) {
-    int sub_layer_id = i + 2;
-    std::unique_ptr<LayerImpl> sub_layer =
-        LayerImpl::Create(host_impl().active_tree(), sub_layer_id);
-    sub_layer->SetBounds(gfx::Size(50, 50));
-    sub_layer->SetDrawsContent(true);
-    sub_layer->SetMutableProperties(properties[i]);
-    root->test_properties()->AddChild(std::move(sub_layer));
-  }
-
-  host_impl().active_tree()->BuildPropertyTreesForTesting();
-
-  for (size_t i = 0; i < arraysize(properties); ++i) {
-    LayerImpl* layer = host_impl().active_tree()->LayerById(i + 2);
-    switch (properties[i]) {
-      case MutableProperty::kOpacity:
-        DCHECK_EQ(root->transform_tree_index(), layer->transform_tree_index());
-        DCHECK_NE(root->effect_tree_index(), layer->effect_tree_index());
-        break;
-      case MutableProperty::kScrollLeft:
-      case MutableProperty::kScrollTop:
-      case MutableProperty::kTransform:
-        DCHECK_EQ(root->effect_tree_index(), layer->effect_tree_index());
-        DCHECK_NE(root->transform_tree_index(), layer->transform_tree_index());
-        for (size_t j = 0; j < arraysize(properties); ++j) {
-          if (j == i)
-            continue;
-          LayerImpl* other = host_impl().active_tree()->LayerById(j + 2);
-          DCHECK_NE(other->transform_tree_index(),
-                    layer->transform_tree_index());
-        }
-        break;
-    }
-  }
-}
-
 TEST_F(LayerTreeImplTest, SelectionBoundsForScaledLayers) {
   LayerImpl* root = root_layer();
   root->SetDrawsContent(true);
diff --git a/cc/trees/mutable_properties.h b/cc/trees/mutable_properties.h
deleted file mode 100644
index ef68c5a..0000000
--- a/cc/trees/mutable_properties.h
+++ /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.
-
-#ifndef CC_TREES_MUTABLE_PROPERTIES_H_
-#define CC_TREES_MUTABLE_PROPERTIES_H_
-
-#include <stdint.h>
-
-namespace cc {
-
-struct MutableProperty {
-  enum : uint32_t { kNone = 0 };
-  enum : uint32_t { kOpacity = 1 << 0 };
-  enum : uint32_t { kScrollLeft = 1 << 1 };
-  enum : uint32_t { kScrollTop = 1 << 2 };
-  enum : uint32_t { kTransform = 1 << 3 };
-  enum : uint32_t { kTransformRelated = kTransform | kScrollLeft | kScrollTop };
-
-  enum : int { kNumProperties = 4 };
-};
-
-}  // namespace cc
-
-#endif  // CC_TREES_MUTABLE_PROPERTIES_H_
diff --git a/cc/trees/occlusion_tracker.cc b/cc/trees/occlusion_tracker.cc
index f4c3c6b7..9cf7f167 100644
--- a/cc/trees/occlusion_tracker.cc
+++ b/cc/trees/occlusion_tracker.cc
@@ -198,6 +198,7 @@
   // If the occlusion within the surface can not be applied to things outside of
   // the surface's subtree, then clear the occlusion here so it won't be used.
   if (finished_target_surface->HasMask() ||
+      finished_target_surface->HasMaskingContributingSurface() ||
       finished_target_surface->draw_opacity() < 1 ||
       !finished_target_surface->UsesDefaultBlendMode() ||
       target_is_only_for_copy_request_or_force_render_surface ||
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc
index f44dbd2..b6a8513 100644
--- a/cc/trees/property_tree.cc
+++ b/cc/trees/property_tree.cc
@@ -812,6 +812,15 @@
           .is_showing_backface;
 }
 
+void EffectTree::UpdateHasMaskingChild(EffectNode* node,
+                                       EffectNode* parent_node) {
+  // Reset to false when a node is first met. We'll set the bit later
+  // when we actually encounter a masking child.
+  node->has_masking_child = false;
+  if (node->blend_mode == SkBlendMode::kDstIn)
+    parent_node->has_masking_child = true;
+}
+
 void EffectTree::UpdateSurfaceContentsScale(EffectNode* effect_node) {
   if (!effect_node->has_render_surface) {
     effect_node->surface_contents_scale = gfx::Vector2dF(1.0f, 1.0f);
@@ -886,6 +895,7 @@
   UpdateIsDrawn(node, parent_node);
   UpdateEffectChanged(node, parent_node);
   UpdateBackfaceVisibility(node, parent_node);
+  UpdateHasMaskingChild(node, parent_node);
   UpdateSurfaceContentsScale(node);
 }
 
diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h
index 22ac11c4..d89b0d6 100644
--- a/cc/trees/property_tree.h
+++ b/cc/trees/property_tree.h
@@ -368,6 +368,7 @@
   void UpdateOpacities(EffectNode* node, EffectNode* parent_node);
   void UpdateIsDrawn(EffectNode* node, EffectNode* parent_node);
   void UpdateBackfaceVisibility(EffectNode* node, EffectNode* parent_node);
+  void UpdateHasMaskingChild(EffectNode* node, EffectNode* parent_node);
 
   // Stores copy requests, keyed by node id.
   std::unordered_multimap<int, std::unique_ptr<viz::CopyOutputRequest>>
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc
index abd08c8..497ece19 100644
--- a/cc/trees/property_tree_builder.cc
+++ b/cc/trees/property_tree_builder.cc
@@ -18,7 +18,6 @@
 #include "cc/trees/effect_node.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "cc/trees/layer_tree_settings.h"
-#include "cc/trees/mutable_properties.h"
 #include "cc/trees/mutator_host.h"
 #include "cc/trees/scroll_node.h"
 #include "cc/trees/transform_node.h"
@@ -410,9 +409,6 @@
   const bool has_any_transform_animation =
       HasAnyAnimationTargetingProperty(layer, TargetProperty::TRANSFORM);
 
-  const bool has_proxied_transform_related_property =
-      !!(layer->mutable_properties() & MutableProperty::kTransformRelated);
-
   const bool has_surface = created_render_surface;
 
   const bool is_at_boundary_of_3d_rendering_context =
@@ -422,8 +418,7 @@
   bool requires_node = is_root || is_snapped || has_significant_transform ||
                        has_any_transform_animation || has_surface || is_fixed ||
                        is_page_scale_layer || is_overscroll_elasticity_layer ||
-                       has_proxied_transform_related_property || is_sticky ||
-                       is_at_boundary_of_3d_rendering_context;
+                       is_sticky || is_at_boundary_of_3d_rendering_context;
 
   int parent_index = TransformTree::kRootNodeId;
   int source_index = TransformTree::kRootNodeId;
@@ -920,8 +915,6 @@
       HasPotentialOpacityAnimation(layer);
   const bool has_potential_filter_animation =
       HasPotentiallyRunningFilterAnimation(layer);
-  const bool has_proxied_opacity =
-      !!(layer->mutable_properties() & MutableProperty::kOpacity);
 
   data_for_children->animation_axis_aligned_since_render_target &=
       AnimationsPreserveAxisAlignment(layer);
@@ -940,10 +933,9 @@
   bool has_non_axis_aligned_clip =
       not_axis_aligned_since_last_clip && LayerClipsSubtree(layer);
 
-  bool requires_node = is_root || has_transparency ||
-                       has_potential_opacity_animation || has_proxied_opacity ||
-                       has_non_axis_aligned_clip ||
-                       should_create_render_surface;
+  bool requires_node =
+      is_root || has_transparency || has_potential_opacity_animation ||
+      has_non_axis_aligned_clip || should_create_render_surface;
 
   int parent_id = data_from_ancestor.effect_tree_parent;
 
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
index e8387e1d..23ce0d2 100644
--- a/chrome/BUILD.gn
+++ b/chrome/BUILD.gn
@@ -15,6 +15,7 @@
 import("//chrome/chrome_paks.gni")
 import("//chrome/common/features.gni")
 import("//chrome/process_version_rc_template.gni")
+import("//components/nacl/features.gni")
 import("//extensions/features/features.gni")
 import("//media/media_options.gni")
 import("//ppapi/features/features.gni")
diff --git a/chrome/VERSION b/chrome/VERSION
index c3cd7de..32888cb 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=63
 MINOR=0
-BUILD=3226
+BUILD=3229
 PATCH=0
diff --git a/chrome/android/java/res/drawable-hdpi/ic_new_releases_black_18dp.png b/chrome/android/java/res/drawable-hdpi/ic_new_releases_black_18dp.png
new file mode 100644
index 0000000..c922f84
--- /dev/null
+++ b/chrome/android/java/res/drawable-hdpi/ic_new_releases_black_18dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/ic_new_releases_black_18dp.png b/chrome/android/java/res/drawable-mdpi/ic_new_releases_black_18dp.png
new file mode 100644
index 0000000..b021a6b
--- /dev/null
+++ b/chrome/android/java/res/drawable-mdpi/ic_new_releases_black_18dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/ic_new_releases_black_18dp.png b/chrome/android/java/res/drawable-xhdpi/ic_new_releases_black_18dp.png
new file mode 100644
index 0000000..db0b316
--- /dev/null
+++ b/chrome/android/java/res/drawable-xhdpi/ic_new_releases_black_18dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/ic_new_releases_black_18dp.png b/chrome/android/java/res/drawable-xxhdpi/ic_new_releases_black_18dp.png
new file mode 100644
index 0000000..76af60a
--- /dev/null
+++ b/chrome/android/java/res/drawable-xxhdpi/ic_new_releases_black_18dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/ic_new_releases_black_18dp.png b/chrome/android/java/res/drawable-xxxhdpi/ic_new_releases_black_18dp.png
new file mode 100644
index 0000000..56c24d8
--- /dev/null
+++ b/chrome/android/java/res/drawable-xxxhdpi/ic_new_releases_black_18dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable/chrome_home_promo_static.xml b/chrome/android/java/res/drawable/chrome_home_promo_static.xml
new file mode 100644
index 0000000..af9b2517
--- /dev/null
+++ b/chrome/android/java/res/drawable/chrome_home_promo_static.xml
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:tools="http://schemas.android.com/tools"
+        tools:targetApi="21"
+        android:width="252dp"
+        android:height="216dp"
+        android:viewportWidth="252.0"
+        android:viewportHeight="216.0">
+    <path
+        android:pathData="M131.35,100.06l-9.06,-9.06l-2.29,2.29l9.06,9.06l-9.06,9.06l2.29,2.29l9.06,-9.06l2.29,-2.29z"
+        android:strokeColor="#00000000"
+        android:fillColor="#404549"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M93.6,0C101.55,0 108,6.45 108,14.4L108,191.6C108,199.55 101.55,206 93.6,206L14.4,206C6.45,206 0,199.55 0,191.6L0,14.4C0,6.45 6.45,0 14.4,0L93.6,0Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#E8EAED"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M10.4,22L97.6,22C98.93,22 100,23.07 100,24.4L100,156L8,156L8,24.4C8,23.07 9.07,22 10.4,22Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#C0E09E"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M43.69,67.36C62.53,50.55 81.22,42.39 100,42.88L100,112.71C99.64,112.71 80.87,97.6 43.69,67.36Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#55A326"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M100,110.21L100,156L8,156L8,60C70.95,60.16 100,108.88 100,110.21Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#007C6A"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M26,114.58C26,111.54 27.44,111.24 30.32,113.68C33.03,115.69 36.26,119.01 40.02,123.66L69.42,123.66C73.2,118.98 76.35,115.66 78.87,113.68C81.62,111.17 83,111.47 83,114.58L83,156.03L26,156.03L26,114.58Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#F6F5ED"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M51,150l7,0l-3.5,3z"
+        android:strokeColor="#00000000"
+        android:fillColor="#DA7D92"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M39,143.1a2.53,3.1 0,1 0,5.05 0a2.53,3.1 0,1 0,-5.05 0z"
+        android:strokeColor="#00000000"
+        android:fillColor="#404549"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M64.82,143.1a2.53,3.1 0,1 0,5.05 0a2.53,3.1 0,1 0,-5.05 0z"
+        android:strokeColor="#00000000"
+        android:fillColor="#404549"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M28.35,156C28.76,155.53 29,154.8 29,153.85C29,150.07 25.42,147 21,147C16.58,147 13,150.07 13,153.85C13,154.83 13.23,155.53 13.66,156L28.35,156Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#D6D4CC"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M94.35,156C94.76,155.53 95,154.8 95,153.85C95,150.07 91.42,147 87,147C82.58,147 79,150.07 79,153.85C79,154.83 79.23,155.53 79.66,156L94.35,156Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#D6D4CC"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M8,156h92v25h-92z"
+        android:strokeColor="#00000000"
+        android:fillColor="#FFFFFF"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M18.57,163C15.49,163 13,165.69 13,169C13,172.31 15.49,175 18.57,175L89.43,175C92.51,175 95,172.31 95,169C95,165.69 92.51,163 89.43,163L18.57,163Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#E8EAED"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M54,159C62.28,159 69,165.6 69,173.75L69,216L39,216L39,173.75C39,165.6 45.72,159 54,159Z"
+        android:fillAlpha="0.5"
+        android:strokeColor="#00000000"
+        android:fillColor="#00B7FF"
+        android:strokeWidth="1"
+        android:strokeAlpha="0.5"/>
+    <path
+        android:pathData="M48,172l6,-7l6,7z"
+        android:strokeColor="#00000000"
+        android:fillColor="#FFFFFF"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M237.6,0C245.55,0 252,6.45 252,14.4L252,191.6C252,199.55 245.55,206 237.6,206L158.4,206C150.45,206 144,199.55 144,191.6L144,14.4C144,6.45 150.45,0 158.4,0L237.6,0Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#E8EAED"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M154.4,22L241.6,22C242.93,22 244,23.07 244,24.4L244,91L152,91L152,24.4C152,23.07 153.07,22 154.4,22Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#C0E09E"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M187.69,67.36C206.53,50.55 225.22,42.39 244,42.88L244,112.71C243.64,112.71 224.87,97.6 187.69,67.36Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#55A326"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M152,91L152,60C188.81,60.1 214.03,76.88 228.63,91L152,91Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#007C6A"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M152,91h92v91h-92z"
+        android:strokeColor="#00000000"
+        android:fillColor="#FFFFFF"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M162.57,98C159.49,98 157,100.69 157,104C157,107.31 159.49,110 162.57,110L233.43,110C236.51,110 239,107.31 239,104C239,100.69 236.51,98 233.43,98L162.57,98Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#E8EAED"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M168,124m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
+        android:strokeColor="#00000000"
+        android:fillColor="#38266E"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M198,124m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
+        android:strokeColor="#00000000"
+        android:fillColor="#FED7B4"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M228,124m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
+        android:strokeColor="#00000000"
+        android:fillColor="#FC757D"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M168,147m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
+        android:strokeColor="#00000000"
+        android:fillColor="#93E4E2"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M198,147m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
+        android:strokeColor="#00000000"
+        android:fillColor="#55A326"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M228,147m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
+        android:strokeColor="#00000000"
+        android:fillColor="#FCE55F"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M204.33,166.83l-4.79,-0.41l-1.87,-4.41l-1.87,4.42l-4.79,0.41l3.64,3.15l-1.09,4.69l4.12,-2.49l4.12,2.49l-1.09,-4.69z"
+        android:strokeColor="#00000000"
+        android:fillColor="#404549"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M173.49,168.92l-3.28,0l0,-4.92l-4.92,0l0,4.92l-3.28,0l5.74,5.74z"
+        android:strokeColor="#00000000"
+        android:fillColor="#404549"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M228.24,164C225.35,164 223,166.35 223,169.25C223,172.15 225.35,174.5 228.24,174.5C231.15,174.5 233.5,172.15 233.5,169.25C233.5,166.35 231.15,164 228.24,164Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#404549"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M228.79,167l-0.79,0l0,3.15l2.76,1.65l0.39,-0.65l-2.36,-1.4z"
+        android:strokeColor="#00000000"
+        android:fillColor="#FFFFFF"
+        android:strokeWidth="1"/>
+</vector>
diff --git a/chrome/android/java/res/layout/chrome_home_promo_toggle.xml b/chrome/android/java/res/layout/chrome_home_promo_toggle.xml
new file mode 100644
index 0000000..b3d538d
--- /dev/null
+++ b/chrome/android/java/res/layout/chrome_home_promo_toggle.xml
@@ -0,0 +1,35 @@
+<?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. -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingTop="@dimen/promo_dialog_padding"
+    android:orientation="horizontal"
+    android:gravity="center_vertical" >
+
+    <TextView
+        android:id="@+id/chrome_home_promo_state_text"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingEnd="4dp"
+        android:textStyle="bold"
+        style="@style/PromoDialogNormalText" />
+
+    <TextView
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:text="@string/chrome_home_promo_dialog_change_later"
+        style="@style/PromoDialogNormalText" />
+
+    <Switch
+        android:id="@+id/chrome_home_toggle"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:gravity="end" />
+
+</LinearLayout>
diff --git a/chrome/android/java/res/layout/content_suggestions_action_card_modern.xml b/chrome/android/java/res/layout/content_suggestions_action_card_modern.xml
index 9277569..e7c0e41 100644
--- a/chrome/android/java/res/layout/content_suggestions_action_card_modern.xml
+++ b/chrome/android/java/res/layout/content_suggestions_action_card_modern.xml
@@ -7,7 +7,7 @@
     android:padding="8dp">
 
     <Button
-        style="@style/SuggestionCardActionModern"
+        style="@style/SuggestionCardAction"
         android:id="@+id/action_button"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
diff --git a/chrome/android/java/res/layout/content_suggestions_card_modern.xml b/chrome/android/java/res/layout/content_suggestions_card_modern.xml
index d7d8fe20..69c1bbbf 100644
--- a/chrome/android/java/res/layout/content_suggestions_card_modern.xml
+++ b/chrome/android/java/res/layout/content_suggestions_card_modern.xml
@@ -41,7 +41,7 @@
                     "@dimen/content_suggestions_card_modern_offline_badge_overlay_margin_start"
             android:layout_marginTop=
                     "@dimen/content_suggestions_card_modern_offline_badge_overlay_margin_top"
-            android:contentDescription="@null"
+            android:contentDescription="@string/accessibility_ntp_offline_badge"
             android:visibility="gone"
             app:srcCompat="@drawable/ic_offline_pin_white"
             tools:src="@drawable/ic_offline_pin_white"/>
@@ -65,21 +65,12 @@
                 android:layout_weight="1"
                 tools:text="Article headline" />
 
-            <org.chromium.ui.widget.TextViewWithLeading
-                style="@style/SuggestionCardBodyModern"
-                android:id="@+id/article_snippet"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="8dp"
-                android:maxLines="2"
-                tools:text="Article snippet" />
-
             <LinearLayout
                 tools:ignore="UseCompoundDrawables"
                 android:id="@+id/publisher_bar"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/snippets_publisher_margin_top_with_article_snippet"
+                android:layout_marginTop="@dimen/snippets_publisher_margin_top"
                 android:orientation="horizontal">
 
                 <!-- The following attributes:
diff --git a/chrome/android/java/res/layout/content_suggestions_status_card_modern.xml b/chrome/android/java/res/layout/content_suggestions_status_card_modern.xml
index da345a59..1394671 100644
--- a/chrome/android/java/res/layout/content_suggestions_status_card_modern.xml
+++ b/chrome/android/java/res/layout/content_suggestions_status_card_modern.xml
@@ -30,10 +30,11 @@
         tools:text="Status card body can be over multiple lines and quite wide" />
 
     <Button
-        style="@style/SuggestionCardActionModern"
+        style="@style/SuggestionCardAction"
         android:id="@+id/status_action_button"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:layout_marginTop="16dp"
         tools:text="Action" />
 
 </LinearLayout>
diff --git a/chrome/android/java/res/layout/contextual_suggestions_card.xml b/chrome/android/java/res/layout/contextual_suggestions_card.xml
index 431aaf3..23d2190 100644
--- a/chrome/android/java/res/layout/contextual_suggestions_card.xml
+++ b/chrome/android/java/res/layout/contextual_suggestions_card.xml
@@ -55,23 +55,12 @@
             android:textAppearance="@style/BlackTitle1"
             chrome:leading="22sp" />
 
-        <org.chromium.ui.widget.TextViewWithLeading
-            android:id="@+id/article_snippet"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="8dp"
-            android:maxLines="2"
-            android:ellipsize="end"
-            android:textSize="14sp"
-            android:textColor="@color/snippets_text_color"
-            chrome:leading="20sp" />
-
         <LinearLayout
             tools:ignore="UseCompoundDrawables"
             android:id="@+id/publisher_bar"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginTop="@dimen/snippets_publisher_margin_top_with_article_snippet"
+            android:layout_marginTop="@dimen/snippets_publisher_margin_top"
             android:orientation="horizontal">
 
             <!-- The following attributes:
diff --git a/chrome/android/java/res/layout/new_tab_page_action_card.xml b/chrome/android/java/res/layout/new_tab_page_action_card.xml
index 16e5ef6..db04dba3 100644
--- a/chrome/android/java/res/layout/new_tab_page_action_card.xml
+++ b/chrome/android/java/res/layout/new_tab_page_action_card.xml
@@ -14,25 +14,17 @@
     android:padding="8dp"
     android:background="@drawable/card_single">
 
-    <!-- Using some standard metrics (minWidth, paddings) to override the
-         special ones used in ButtonCompatBorderless -->
     <Button
+        style="@style/SuggestionCardAction"
         android:id="@+id/action_button"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:gravity="center_vertical"
-        android:minWidth="0dp"
-        android:paddingEnd="16dp"
-        android:paddingStart="16dp"
-        android:text="@string/more"
-        android:textAllCaps="true"
-        android:textColor="@color/light_active_color"
-        style="@style/ButtonCompatBorderless" />
+        android:layout_gravity="center_vertical"
+        android:text="@string/more" />
 
     <org.chromium.chrome.browser.ntp.cards.ProgressIndicatorView
         android:id="@+id/progress_indicator"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_gravity="center_vertical"
-        />
+        android:layout_gravity="center_vertical" />
 </FrameLayout>
diff --git a/chrome/android/java/res/layout/new_tab_page_layout.xml b/chrome/android/java/res/layout/new_tab_page_layout.xml
index 41c8927..743143dd 100644
--- a/chrome/android/java/res/layout/new_tab_page_layout.xml
+++ b/chrome/android/java/res/layout/new_tab_page_layout.xml
@@ -96,6 +96,23 @@
             android:src="@drawable/btn_mic" />
     </LinearLayout>
 
+    <!-- Chrome Home promo -->
+    <FrameLayout
+        android:id="@+id/chrome_home_promo_container"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="8dp"
+        android:visibility="gone">
+        <org.chromium.ui.widget.TextViewWithClickableSpans
+            android:id="@+id/chrome_home_promo_text"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:drawableStart="@drawable/ic_new_releases_black_18dp"
+            android:drawablePadding="8dp"
+            android:padding="8dp"
+            android:textAppearance="@style/BlackHint2" />
+    </FrameLayout>
+
     <!-- Middle spacer -->
     <View
         android:id="@+id/ntp_middle_spacer"
diff --git a/chrome/android/java/res/layout/new_tab_page_snippets_card.xml b/chrome/android/java/res/layout/new_tab_page_snippets_card.xml
index f30b6ecc..f370715 100644
--- a/chrome/android/java/res/layout/new_tab_page_snippets_card.xml
+++ b/chrome/android/java/res/layout/new_tab_page_snippets_card.xml
@@ -24,28 +24,14 @@
         android:textAppearance="@style/BlackTitle1"
         chrome:leading="24sp" />
 
-    <org.chromium.ui.widget.TextViewWithLeading
-        android:id="@+id/article_snippet"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_alignParentStart="true"
-        android:layout_below="@+id/article_headline"
-        android:layout_toStartOf="@+id/article_thumbnail"
-        android:layout_marginTop="8dp"
-        android:maxLines="2"
-        android:ellipsize="end"
-        android:textSize="14sp"
-        android:textColor="@color/snippets_text_color"
-        chrome:leading="20sp" />
-
     <LinearLayout
         tools:ignore="UseCompoundDrawables"
         android:id="@+id/publisher_bar"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginTop="@dimen/snippets_publisher_margin_top_with_article_snippet"
+        android:layout_marginTop="@dimen/snippets_publisher_margin_top"
         android:layout_alignParentStart="true"
-        android:layout_below="@+id/article_snippet"
+        android:layout_below="@+id/article_headline"
         android:orientation="horizontal">
 
         <!-- The following attributes:
diff --git a/chrome/android/java/res/layout/new_tab_page_snippets_card_large_thumbnail.xml b/chrome/android/java/res/layout/new_tab_page_snippets_card_large_thumbnail.xml
index d1d5310c..8d93a67 100644
--- a/chrome/android/java/res/layout/new_tab_page_snippets_card_large_thumbnail.xml
+++ b/chrome/android/java/res/layout/new_tab_page_snippets_card_large_thumbnail.xml
@@ -33,23 +33,12 @@
             android:textAppearance="@style/BlackTitle1"
             chrome:leading="22sp" />
 
-        <org.chromium.ui.widget.TextViewWithLeading
-            android:id="@+id/article_snippet"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="8dp"
-            android:maxLines="2"
-            android:ellipsize="end"
-            android:textSize="14sp"
-            android:textColor="@color/snippets_text_color"
-            chrome:leading="20sp" />
-
         <LinearLayout
             tools:ignore="UseCompoundDrawables"
             android:id="@+id/publisher_bar"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginTop="@dimen/snippets_publisher_margin_top_with_article_snippet"
+            android:layout_marginTop="@dimen/snippets_publisher_margin_top"
             android:orientation="horizontal">
 
             <!-- The following attributes:
diff --git a/chrome/android/java/res/layout/new_tab_page_status_card.xml b/chrome/android/java/res/layout/new_tab_page_status_card.xml
index e2b02a3..94d1c5e 100644
--- a/chrome/android/java/res/layout/new_tab_page_status_card.xml
+++ b/chrome/android/java/res/layout/new_tab_page_status_card.xml
@@ -30,18 +30,11 @@
         android:textColor="@color/snippets_text_color"
         chrome:leading="20dp" />
 
-    <!-- Negative marginEnd to balance the parent's padding. Buttons are
-         supposed to have 8dp margin while we have a 16dp margin at the parent
-         level. -->
     <Button
-      android:id="@+id/status_action_button"
-      style="@style/ButtonCompatBorderless"
-      android:layout_marginTop="16dp"
-      android:layout_marginEnd="-8dp"
-      android:layout_width="wrap_content"
-      android:layout_height="wrap_content"
-      android:textAllCaps="true"
-      android:textColor="@color/light_active_color"
-      android:textSize="15sp" />
+        style="@style/SuggestionCardAction"
+        android:id="@+id/status_action_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="16dp" />
 
 </LinearLayout>
diff --git a/chrome/android/java/res/layout/personalized_signin_promo_view_body.xml b/chrome/android/java/res/layout/personalized_signin_promo_view_body.xml
new file mode 100644
index 0000000..72615900
--- /dev/null
+++ b/chrome/android/java/res/layout/personalized_signin_promo_view_body.xml
@@ -0,0 +1,46 @@
+<?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:tools="http://schemas.android.com/tools"
+       tools:showIn="@layout/personalized_signin_promo_view_settings">
+
+    <TextView
+        android:id="@+id/signin_promo_description"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="12dp"
+        android:layout_marginEnd="24dp"
+        android:layout_marginStart="24dp"
+        android:gravity="center"
+        android:textAppearance="@style/BlackTitle2"
+        tools:text="@string/signin_promo_description_settings"/>
+
+    <org.chromium.ui.widget.ButtonCompat
+        android:id="@+id/signin_promo_signin_button"
+        style="@style/SigninButtonCompat"
+        android:layout_width="match_parent"
+        android:layout_height="36dp"
+        android:layout_marginBottom="6dp"
+        android:layout_marginEnd="24dp"
+        android:layout_marginStart="24dp"
+        android:layout_marginTop="6dp"
+        android:ellipsize="end"
+        android:maxLines="1"
+        android:text="@string/signin_promo_continue_as"/>
+
+    <Button
+        android:id="@+id/signin_promo_choose_account_button"
+        style="@style/SigninButtonBorderlessRegular"
+        android:layout_width="match_parent"
+        android:layout_height="36dp"
+        android:layout_marginBottom="6dp"
+        android:layout_marginEnd="24dp"
+        android:layout_marginStart="24dp"
+        android:layout_marginTop="6dp"
+        android:ellipsize="end"
+        android:maxLines="1"
+        android:text="@string/signin_promo_choose_account"/>
+</merge>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/personalized_signin_promo_view_bookmarks.xml b/chrome/android/java/res/layout/personalized_signin_promo_view_bookmarks.xml
index a8277645b..fff45fe 100644
--- a/chrome/android/java/res/layout/personalized_signin_promo_view_bookmarks.xml
+++ b/chrome/android/java/res/layout/personalized_signin_promo_view_bookmarks.xml
@@ -15,6 +15,16 @@
     android:paddingBottom="12dp"
     android:paddingTop="14dp">
 
-    <include layout="@layout/personalized_signin_promo_view_impl"/>
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="12dp"
+        android:layout_marginEnd="12dp"
+        android:layout_marginStart="12dp">
+
+        <include layout="@layout/personalized_signin_promo_view_header"/>
+    </FrameLayout>
+
+    <include layout="@layout/personalized_signin_promo_view_body"/>
 
 </org.chromium.chrome.browser.signin.PersonalizedSigninPromoView>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/personalized_signin_promo_view_header.xml b/chrome/android/java/res/layout/personalized_signin_promo_view_header.xml
new file mode 100644
index 0000000..36bcaeb
--- /dev/null
+++ b/chrome/android/java/res/layout/personalized_signin_promo_view_header.xml
@@ -0,0 +1,28 @@
+<?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:tools="http://schemas.android.com/tools"
+       tools:showIn="@layout/personalized_signin_promo_view_settings">
+
+    <ImageView
+        android:id="@+id/signin_promo_image"
+        android:layout_width="@dimen/signin_promo_account_image_size"
+        android:layout_height="@dimen/signin_promo_account_image_size"
+        android:layout_gravity="center"
+        android:contentDescription="@null"
+        android:scaleType="fitCenter"/>
+
+    <ImageButton
+        android:id="@+id/signin_promo_close_button"
+        android:layout_width="24dp"
+        android:layout_height="24dp"
+        android:layout_gravity="top|end"
+        android:background="?attr/selectableItemBackground"
+        android:contentDescription="@string/close"
+        android:scaleType="fitCenter"
+        android:src="@drawable/btn_close"
+        android:visibility="gone"/>
+</merge>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/personalized_signin_promo_view_impl.xml b/chrome/android/java/res/layout/personalized_signin_promo_view_impl.xml
deleted file mode 100644
index 3eb06179..0000000
--- a/chrome/android/java/res/layout/personalized_signin_promo_view_impl.xml
+++ /dev/null
@@ -1,73 +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:tools="http://schemas.android.com/tools"
-       tools:showIn="@layout/personalized_signin_promo_view_settings">
-
-    <FrameLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="12dp"
-        android:layout_marginEnd="12dp"
-        android:layout_marginStart="12dp">
-
-        <ImageView
-            android:id="@+id/signin_promo_image"
-            android:layout_width="@dimen/signin_promo_account_image_size"
-            android:layout_height="@dimen/signin_promo_account_image_size"
-            android:layout_gravity="center"
-            android:contentDescription="@null"
-            android:scaleType="fitCenter"/>
-
-        <ImageButton
-            android:id="@+id/signin_promo_close_button"
-            android:layout_width="24dp"
-            android:layout_height="24dp"
-            android:layout_gravity="top|end"
-            android:background="?attr/selectableItemBackground"
-            android:contentDescription="@string/close"
-            android:scaleType="fitCenter"
-            android:src="@drawable/btn_close"
-            android:visibility="gone"/>
-    </FrameLayout>
-
-    <TextView
-        android:id="@+id/signin_promo_description"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="12dp"
-        android:layout_marginEnd="24dp"
-        android:layout_marginStart="24dp"
-        android:gravity="center"
-        android:textAppearance="@style/BlackTitle2"
-        tools:text="@string/signin_promo_description_settings"/>
-
-    <org.chromium.ui.widget.ButtonCompat
-        android:id="@+id/signin_promo_signin_button"
-        style="@style/SigninButtonCompat"
-        android:layout_width="match_parent"
-        android:layout_height="36dp"
-        android:layout_marginBottom="6dp"
-        android:layout_marginEnd="24dp"
-        android:layout_marginStart="24dp"
-        android:layout_marginTop="6dp"
-        android:ellipsize="end"
-        android:maxLines="1"
-        android:text="@string/signin_promo_continue_as"/>
-
-    <Button
-        android:id="@+id/signin_promo_choose_account_button"
-        style="@style/SigninButtonBorderlessRegular"
-        android:layout_width="match_parent"
-        android:layout_height="36dp"
-        android:layout_marginBottom="6dp"
-        android:layout_marginEnd="24dp"
-        android:layout_marginStart="24dp"
-        android:layout_marginTop="6dp"
-        android:ellipsize="end"
-        android:maxLines="1"
-        android:text="@string/signin_promo_choose_account"/>
-</merge>
diff --git a/chrome/android/java/res/layout/personalized_signin_promo_view_modern_content_suggestions.xml b/chrome/android/java/res/layout/personalized_signin_promo_view_modern_content_suggestions.xml
index 28a4b0be..dd11dae6 100644
--- a/chrome/android/java/res/layout/personalized_signin_promo_view_modern_content_suggestions.xml
+++ b/chrome/android/java/res/layout/personalized_signin_promo_view_modern_content_suggestions.xml
@@ -16,6 +16,16 @@
     android:paddingStart="16dp"
     android:paddingTop="12dp">
 
-    <include layout="@layout/personalized_signin_promo_view_impl"/>
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="12dp"
+        android:layout_marginEnd="12dp"
+        android:layout_marginStart="12dp">
+
+        <include layout="@layout/personalized_signin_promo_view_header"/>
+    </FrameLayout>
+
+    <include layout="@layout/personalized_signin_promo_view_body"/>
 
 </org.chromium.chrome.browser.signin.PersonalizedSigninPromoView>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/personalized_signin_promo_view_ntp_content_suggestions.xml b/chrome/android/java/res/layout/personalized_signin_promo_view_ntp_content_suggestions.xml
index 9d90dcdb..c87807261 100644
--- a/chrome/android/java/res/layout/personalized_signin_promo_view_ntp_content_suggestions.xml
+++ b/chrome/android/java/res/layout/personalized_signin_promo_view_ntp_content_suggestions.xml
@@ -15,6 +15,16 @@
     android:paddingStart="16dp"
     android:paddingTop="12dp">
 
-    <include layout="@layout/personalized_signin_promo_view_impl"/>
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="12dp"
+        android:layout_marginEnd="12dp"
+        android:layout_marginStart="12dp">
+
+        <include layout="@layout/personalized_signin_promo_view_header"/>
+    </FrameLayout>
+
+    <include layout="@layout/personalized_signin_promo_view_body"/>
 
 </org.chromium.chrome.browser.signin.PersonalizedSigninPromoView>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/personalized_signin_promo_view_recent_tabs.xml b/chrome/android/java/res/layout/personalized_signin_promo_view_recent_tabs.xml
index 38010aa..a74d80a 100644
--- a/chrome/android/java/res/layout/personalized_signin_promo_view_recent_tabs.xml
+++ b/chrome/android/java/res/layout/personalized_signin_promo_view_recent_tabs.xml
@@ -16,6 +16,16 @@
     android:paddingStart="16dp"
     android:paddingTop="28dp">
 
-    <include layout="@layout/personalized_signin_promo_view_impl"/>
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="12dp"
+        android:layout_marginEnd="12dp"
+        android:layout_marginStart="12dp">
+
+        <include layout="@layout/personalized_signin_promo_view_header"/>
+    </FrameLayout>
+
+    <include layout="@layout/personalized_signin_promo_view_body"/>
 
 </org.chromium.chrome.browser.signin.PersonalizedSigninPromoView>
diff --git a/chrome/android/java/res/layout/personalized_signin_promo_view_settings.xml b/chrome/android/java/res/layout/personalized_signin_promo_view_settings.xml
index bec2a0b..626ba8d 100644
--- a/chrome/android/java/res/layout/personalized_signin_promo_view_settings.xml
+++ b/chrome/android/java/res/layout/personalized_signin_promo_view_settings.xml
@@ -14,6 +14,16 @@
     android:paddingBottom="12dp"
     android:paddingTop="12dp">
 
-    <include layout="@layout/personalized_signin_promo_view_impl"/>
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="12dp"
+        android:layout_marginEnd="12dp"
+        android:layout_marginStart="12dp">
+
+        <include layout="@layout/personalized_signin_promo_view_header"/>
+    </FrameLayout>
+
+    <include layout="@layout/personalized_signin_promo_view_body"/>
 
 </org.chromium.chrome.browser.signin.PersonalizedSigninPromoView>
diff --git a/chrome/android/java/res/layout/promo_dialog_layout.xml b/chrome/android/java/res/layout/promo_dialog_layout.xml
index 8efde5cb7..a9653c7 100644
--- a/chrome/android/java/res/layout/promo_dialog_layout.xml
+++ b/chrome/android/java/res/layout/promo_dialog_layout.xml
@@ -68,9 +68,7 @@
                             android:id="@+id/subheader"
                             android:layout_width="wrap_content"
                             android:layout_height="wrap_content"
-                            android:lineSpacingMultiplier="1.3"
-                            android:textColor="#646464"
-                            android:textSize="@dimen/promo_dialog_normal_text_size" />
+                            style="@style/PromoDialogNormalText" />
                 </org.chromium.chrome.browser.widget.BoundedLinearLayout>
             </LinearLayout>
 
diff --git a/chrome/android/java/res/values-v17/styles.xml b/chrome/android/java/res/values-v17/styles.xml
index 4917a24d..d5628a6 100644
--- a/chrome/android/java/res/values-v17/styles.xml
+++ b/chrome/android/java/res/values-v17/styles.xml
@@ -340,6 +340,9 @@
         <item name="android:windowIsTranslucent">true</item>
         <item name="android:windowNoTitle">true</item>
     </style>
+    <style name="PromoDialogNormalText" parent="@style/BlackDisabledText2">
+        <item name="android:lineSpacingMultiplier">1.3</item>
+    </style>
 
     <!-- Cast and media playback notifications -->
     <style
@@ -746,9 +749,10 @@
         <item name="android:ellipsize">end</item>
         <item name="leading">16sp</item>
     </style>
-    <style name="SuggestionCardActionModern" parent="ButtonCompatBorderless">
+    <style name="SuggestionCardAction" parent="ButtonCompatBorderless">
         <item name="android:textAppearance">@style/BlueButtonText2</item>
-        <item name="android:layout_marginTop">16dp</item>
+        <item name="android:paddingStart">16dp</item>
+        <item name="android:paddingEnd">16dp</item>
 
         <!-- Negative marginEnd to balance the padding from the parent (SuggestionCardModern).
              Buttons are supposed to have 8dp margin while we have a 16dp margin at the parent
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml
index a638091..c915479 100644
--- a/chrome/android/java/res/values/dimens.xml
+++ b/chrome/android/java/res/values/dimens.xml
@@ -143,7 +143,6 @@
     <dimen name="promo_dialog_max_content_width">320dp</dimen>
     <dimen name="promo_dialog_min_scrollable_height">100dp</dimen>
     <dimen name="promo_dialog_title_text_size">23sp</dimen>
-    <dimen name="promo_dialog_normal_text_size">14sp</dimen>
 
     <!-- Data Saver -->
     <dimen name="data_usage_chart_height">252dp</dimen>
@@ -351,8 +350,7 @@
     <dimen name="snippets_peeking_card_bounce_distance">10dp</dimen>
     <dimen name="snippets_card_gap">0.5dp</dimen>
     <dimen name="snippets_article_header_height">40dp</dimen>
-    <dimen name="snippets_publisher_margin_top_with_article_snippet">16dp</dimen>
-    <dimen name="snippets_publisher_margin_top_without_article_snippet">8dp</dimen>
+    <dimen name="snippets_publisher_margin_top">8dp</dimen>
     <!-- This is in sp because we want the icon to scale with the TextView it sits alongside. -->
     <dimen name="snippets_offline_icon_size">18sp</dimen>
     <dimen name="ntp_suggestions_footer_padding_top">40dp</dimen>
@@ -493,8 +491,6 @@
     <!-- Bottom sheet dimensions -->
     <dimen name="bottom_sheet_help_bubble_inset">10dp</dimen>
     <dimen name="bottom_nav_height">40dp</dimen>
-    <dimen name="bottom_nav_space_from_toolbar">96dp</dimen>
-    <!-- The following two dimensions override defaults in Android's BottomNavigationView -->
 
     <!-- Chrome Home dimensions -->
     <dimen name="chrome_home_empty_view_top_padding">72dp</dimen>
@@ -508,6 +504,8 @@
     <dimen name="text_bubble_arrow_width">20dp</dimen>
     <dimen name="text_bubble_arrow_height">10dp</dimen>
     <dimen name="text_bubble_menu_anchor_y_inset">14dp</dimen>
+    <dimen name="iph_pulse_baseline_radius">16dp</dimen>
+    <dimen name="iph_pulse_chrome_home_baseline_radius">16dp</dimen>
 
     <!--  Miscellaneous dimensions -->
     <dimen name="action_bar_shadow_height">10dp</dimen>
diff --git a/chrome/android/java/res/xml/privacy_preferences.xml b/chrome/android/java/res/xml/privacy_preferences.xml
index e5c7907..527d33f9 100644
--- a/chrome/android/java/res/xml/privacy_preferences.xml
+++ b/chrome/android/java/res/xml/privacy_preferences.xml
@@ -29,6 +29,7 @@
     <org.chromium.chrome.browser.preferences.ChromeBaseCheckBoxPreference
         android:key="network_predictions"
         android:title="@string/network_predictions_title"
+        android:summary="@string/network_predictions_summary"
         android:persistent="false" />
     <Preference
         android:key="usage_and_crash_reports"
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 0176788..12c42b7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -397,10 +397,7 @@
             mBottomSheetContentController =
                     (BottomSheetContentController) ((ViewStub) findViewById(R.id.bottom_nav_stub))
                             .inflate();
-            int controlContainerHeight =
-                    ((ControlContainer) findViewById(R.id.control_container)).getView().getHeight();
-            mBottomSheetContentController.init(
-                    mBottomSheet, controlContainerHeight, mTabModelSelector, this);
+            mBottomSheetContentController.init(mBottomSheet, mTabModelSelector, this);
         }
         ((BottomContainer) findViewById(R.id.bottom_container)).initialize(mFullscreenManager);
     }
@@ -1373,6 +1370,7 @@
     protected void showAppMenuForKeyboardEvent() {
         if (getAppMenuHandler() == null) return;
 
+        TextBubble.dismissBubbles();
         boolean hasPermanentMenuKey = ViewConfiguration.get(this).hasPermanentMenuKey();
         getAppMenuHandler().showAppMenu(
                 hasPermanentMenuKey ? null : getToolbarManager().getMenuButton(), false);
@@ -1796,7 +1794,7 @@
     public final void onBackPressed() {
         if (mNativeInitialized) RecordUserAction.record("SystemBack");
 
-        TextBubble.onBackPressed();
+        TextBubble.dismissBubbles();
         if (VrShellDelegate.onBackPressed()) return;
         if (mCompositorViewHolder != null) {
             LayoutManager layoutManager = mCompositorViewHolder.getLayoutManager();
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 2dc5e3f..b7564604 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -161,6 +161,7 @@
     public static final String CHROME_HOME_DESTROY_SUGGESTIONS = "ChromeHomeDestroySuggestions";
     public static final String CHROME_HOME_DOODLE = "ChromeHomeDoodle";
     public static final String CHROME_HOME_EXPAND_BUTTON = "ChromeHomeExpandButton";
+    public static final String CHROME_HOME_PROMO = "ChromeHomePromo";
     public static final String CONTENT_SUGGESTIONS_FAVICONS_FROM_NEW_SERVER =
             "ContentSuggestionsFaviconsFromNewServer";
     public static final String CONTENT_SUGGESTIONS_NOTIFICATIONS =
@@ -170,7 +171,6 @@
     public static final String CONTENT_SUGGESTIONS_SCROLL_TO_LOAD =
             "ContentSuggestionsScrollToLoad";
     public static final String CONTENT_SUGGESTIONS_SETTINGS = "ContentSuggestionsSettings";
-    public static final String CONTENT_SUGGESTIONS_SHOW_SUMMARY = "ContentSuggestionsShowSummary";
     public static final String CONTENT_SUGGESTIONS_THUMBNAIL_DOMINANT_COLOR =
             "ContentSuggestionsThumbnailDominantColor";
     public static final String CONTENT_SUGGESTIONS_VIDEO_OVERLAY = "ContentSuggestionsVideoOverlay";
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 0714e098..50bb824 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -20,7 +20,6 @@
 import android.os.SystemClock;
 import android.support.annotation.IntDef;
 import android.support.annotation.Nullable;
-import android.support.annotation.StringRes;
 import android.text.TextUtils;
 import android.util.Pair;
 import android.view.KeyEvent;
@@ -121,6 +120,7 @@
 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.ChromeHomePromoDialog;
 import org.chromium.chrome.browser.widget.emptybackground.EmptyBackgroundViewWrapper;
 import org.chromium.chrome.browser.widget.textbubble.ViewAnchoredTextBubble;
 import org.chromium.components.feature_engagement.EventConstants;
@@ -484,9 +484,15 @@
                 TabModel currentModel = mTabModelSelectorImpl.getCurrentModel();
                 if (!SigninPromoUtil.launchSigninPromoIfNeeded(this)) {
                     if (!DataReductionPromoScreen.launchDataReductionPromo(
-                                this, currentModel.isIncognito())
-                            && getBottomSheet() != null) {
-                        getBottomSheet().showHelpBubbleIfNecessary();
+                                this, currentModel.isIncognito())) {
+                        // TODO(mdjones): Refine this triggering logic when promo is complete:
+                        // crbug.com/767738
+                        if (ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_HOME_PROMO)) {
+                            ChromeHomePromoDialog chDialog = new ChromeHomePromoDialog(this);
+                            chDialog.show();
+                        } else if (getBottomSheet() != null) {
+                            getBottomSheet().showHelpBubbleIfNecessary();
+                        }
                     }
                 }
             } else {
@@ -763,10 +769,8 @@
 
             final Tracker tracker =
                     TrackerFactory.getTrackerForProfile(Profile.getLastUsedProfile());
-            tracker.addOnInitializedCallback((Callback<Boolean>) success
-                    -> maybeShowDownloadHomeTextBubble(tracker,
-                            FeatureConstants.DOWNLOAD_HOME_FEATURE, R.string.iph_download_home_text,
-                            R.string.iph_download_home_accessibility_text));
+            tracker.addOnInitializedCallback(
+                    (Callback<Boolean>) success -> maybeShowDownloadHomeTextBubble(tracker));
 
             mScreenshotMonitor = ScreenshotMonitor.create(ChromeTabbedActivity.this);
 
@@ -776,8 +780,7 @@
         }
     }
 
-    private void maybeShowDownloadHomeTextBubble(final Tracker tracker, String featureName,
-            @StringRes int stringId, @StringRes int accessibilityStringId) {
+    private void maybeShowDownloadHomeTextBubble(final Tracker tracker) {
         // Don't show the IPH, if bottom sheet is already open.
         if (FeatureUtilities.isChromeHomeEnabled()
                 && (getBottomSheet() == null
@@ -785,13 +788,23 @@
             return;
         }
 
-        if (!tracker.shouldTriggerHelpUI(featureName)) return;
+        if (!tracker.shouldTriggerHelpUI(FeatureConstants.DOWNLOAD_HOME_FEATURE)) return;
 
-        ViewAnchoredTextBubble textBubble = new ViewAnchoredTextBubble(this,
-                getToolbarAnchorViewForDownloadHomeTextBubble(), stringId, accessibilityStringId);
+        int accessibilityStringId = R.string.iph_download_home_accessibility_text;
+        if (FeatureUtilities.isChromeHomeEnabled()) {
+            accessibilityStringId = R.string.iph_download_home_accessibility_text_chrome_home;
+            if (FeatureUtilities.isChromeHomeExpandButtonEnabled()) {
+                accessibilityStringId =
+                        R.string.iph_download_home_accessibility_text_chrome_home_expand;
+            }
+        }
+
+        ViewAnchoredTextBubble textBubble =
+                new ViewAnchoredTextBubble(this, getToolbarAnchorViewForDownloadHomeTextBubble(),
+                        R.string.iph_download_home_text, accessibilityStringId);
         textBubble.setDismissOnTouchInteraction(true);
         textBubble.addOnDismissListener(() -> mHandler.postDelayed(() -> {
-            tracker.dismissed(featureName);
+            tracker.dismissed(FeatureConstants.DOWNLOAD_HOME_FEATURE);
             turnOffHighlightForDownloadHomeTextBubble();
         }, ViewHighlighter.IPH_MIN_DELAY_BETWEEN_TWO_HIGHLIGHTS));
 
@@ -2241,10 +2254,8 @@
         ThreadUtils.postOnUiThread(new Runnable() {
             @Override
             public void run() {
-                maybeShowDownloadHomeTextBubble(tracker,
-                        FeatureConstants.DOWNLOAD_PAGE_SCREENSHOT_FEATURE,
-                        R.string.iph_download_page_for_offline_usage_text,
-                        R.string.iph_download_page_for_offline_usage_accessibility_text);
+                getToolbarManager().showDownloadPageTextBubble(
+                        getActivityTab(), FeatureConstants.DOWNLOAD_PAGE_SCREENSHOT_FEATURE);
             }
         });
     }
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 0a03fdb7..0403fa82 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
@@ -27,7 +27,7 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.blink_public.web.WebReferrerPolicy;
-import org.chromium.chrome.browser.customtabs.CustomTabActivity;
+import org.chromium.chrome.browser.browserservices.BrowserSessionContentUtils;
 import org.chromium.chrome.browser.externalauth.ExternalAuthUtils;
 import org.chromium.chrome.browser.externalnav.ExternalNavigationDelegateImpl;
 import org.chromium.chrome.browser.externalnav.IntentWithGesturesHandler;
@@ -446,7 +446,8 @@
         } else if (isValidReferrerHeader(referrerExtra)) {
             return referrerExtra.toString();
         } else if (IntentHandler.isIntentChromeOrFirstParty(intent)
-                || CustomTabActivity.canActiveContentHandlerUseReferrer(intent, referrerExtra)) {
+                || BrowserSessionContentUtils.canActiveContentHandlerUseReferrer(
+                           intent, referrerExtra)) {
             return referrerExtra.toString();
         }
         return null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/LauncherShortcutActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/LauncherShortcutActivity.java
index 2905a933..6f84f4f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/LauncherShortcutActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/LauncherShortcutActivity.java
@@ -74,10 +74,13 @@
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N_MR1) return;
 
         SharedPreferences preferences = ContextUtils.getAppSharedPreferences();
-        if (!preferences.getBoolean(INCOGNITO_SHORTCUT_ADDED_PREF, false)
-                && PrefServiceBridge.getInstance().isIncognitoModeEnabled()) {
+        if (PrefServiceBridge.getInstance().isIncognitoModeEnabled()) {
             boolean success = LauncherShortcutActivity.addIncognitoLauncherShortcut(context);
-            preferences.edit().putBoolean(INCOGNITO_SHORTCUT_ADDED_PREF, success).apply();
+
+            // Save a shared preference indicating the incognito shortcut has been added.
+            if (success) {
+                preferences.edit().putBoolean(INCOGNITO_SHORTCUT_ADDED_PREF, true).apply();
+            }
         } else if (preferences.getBoolean(INCOGNITO_SHORTCUT_ADDED_PREF, false)
                 && !PrefServiceBridge.getInstance().isIncognitoModeEnabled()) {
             LauncherShortcutActivity.removeIncognitoLauncherShortcut(context);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserSessionContentHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserSessionContentHandler.java
new file mode 100644
index 0000000..fb6553d
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserSessionContentHandler.java
@@ -0,0 +1,59 @@
+// 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.
+
+package org.chromium.chrome.browser.browserservices;
+
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.support.customtabs.CustomTabsSessionToken;
+import android.widget.RemoteViews;
+
+import org.chromium.content_public.browser.LoadUrlParams;
+
+/**
+ * Interface to handle browser services calls whenever the session id matched.
+ * TODO(yusufo): Add a way to handle mayLaunchUrl as well.
+ */
+public interface BrowserSessionContentHandler {
+    /**
+     * Loads a new url inside the {@link BrowserSessionContentHandler}, and tracks
+     * its load time.
+     *
+     * @param params The params to use while loading the url.
+     * @param timestamp The intent arrival timestamp, as returned by
+     *                  {@link SystemClock#elapsedRealtime()}.
+     */
+    void loadUrlAndTrackFromTimestamp(LoadUrlParams params, long timestamp);
+
+    /**
+     * @return The session this {@link BrowserSessionContentHandler} is associated with.
+     */
+    CustomTabsSessionToken getSession();
+
+    /**
+     * Check whether an intent is valid or should be ignored within this content handler.
+     * @param intent The intent to check.
+     * @return Whether the intent should be ignored.
+     */
+    boolean shouldIgnoreIntent(Intent intent);
+
+    /**
+     * Finds the action button with the given id, and updates it with the new content.
+     * @return Whether the action button has been updated.
+     */
+    boolean updateCustomButton(int id, Bitmap bitmap, String description);
+
+    /**
+     * Updates the {@link RemoteViews} shown on the secondary toolbar.
+     * @return Whether this update is successful.
+     */
+    boolean updateRemoteViews(
+            RemoteViews remoteViews, int[] clickableIDs, PendingIntent pendingIntent);
+
+    /**
+     * @return The current url being displayed to the user.
+     */
+    String getCurrentUrl();
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserSessionContentUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserSessionContentUtils.java
new file mode 100644
index 0000000..31a275d
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserSessionContentUtils.java
@@ -0,0 +1,145 @@
+// 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.browserservices;
+
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.IBinder;
+import android.support.customtabs.CustomTabsService;
+import android.support.customtabs.CustomTabsSessionToken;
+import android.text.TextUtils;
+import android.widget.RemoteViews;
+
+import org.chromium.base.Log;
+import org.chromium.base.ThreadUtils;
+import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.IntentHandler;
+import org.chromium.chrome.browser.UrlConstants;
+import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
+import org.chromium.content_public.browser.LoadUrlParams;
+
+/**
+ * Utilies for managing the active {@link BrowserSessionContentHandler}. This is an interface owned
+ * by the currently focused {@link ChromeActivity} has a linkage to a third party client app through
+ * a session.
+ */
+public class BrowserSessionContentUtils {
+    private static final String TAG = "BrowserSession_Utils";
+    private static BrowserSessionContentHandler sActiveContentHandler;
+
+    /**
+     * Sets the currently active {@link BrowserSessionContentHandler} in focus.
+     * @param contentHandler {@link BrowserSessionContentHandler} to set.
+     */
+    public static void setActiveContentHandler(BrowserSessionContentHandler contentHandler) {
+        sActiveContentHandler = contentHandler;
+    }
+
+    /**
+     * Called when a Browser Services intent is handled.
+     *
+     * Used to check whether an incoming intent can be handled by the current
+     * {@link BrowserSessionContentHandler}, and to perform action on new Intent.
+     *
+     * @return Whether the active {@link BrowserSessionContentHandler} has handled the intent.
+     */
+    public static boolean handleInActiveContentIfNeeded(Intent intent) {
+        CustomTabsSessionToken session = CustomTabsSessionToken.getSessionTokenFromIntent(intent);
+
+        String url = IntentHandler.getUrlFromIntent(intent);
+        if (TextUtils.isEmpty(url)) return false;
+        CustomTabsConnection.getInstance().onHandledIntent(session, url, intent);
+
+        if (sActiveContentHandler == null) return false;
+        if (session == null || !session.equals(sActiveContentHandler.getSession())) return false;
+        if (sActiveContentHandler.shouldIgnoreIntent(intent)) {
+            Log.w(TAG, "Incoming intent to Custom Tab was ignored.");
+            return false;
+        }
+        sActiveContentHandler.loadUrlAndTrackFromTimestamp(
+                new LoadUrlParams(url), IntentHandler.getTimestampFromIntent(intent));
+        return true;
+    }
+
+    /**
+     * @return Whether the given session is the currently active session.
+     */
+    public static boolean isActiveSession(CustomTabsSessionToken session) {
+        if (sActiveContentHandler == null) return false;
+        if (session == null || sActiveContentHandler.getSession() == null) return false;
+        return sActiveContentHandler.getSession().equals(session);
+    }
+
+    /**
+     * Checks whether the given referrer can be used as valid within the Activity launched by the
+     * given intent. For this to be true, the intent should be for a {@link CustomTabsSessionToken}
+     * that is the currently in focus custom tab and also the related client should have a verified
+     * relationship with the referrer origin. This can only be true for https:// origins.
+     *
+     * @param intent The intent that was used to launch the Activity in question.
+     * @param referrer The referrer url that is to be used.
+     * @return Whether the given referrer is a valid first party url to the client that launched
+     *         the activity.
+     */
+    public static boolean canActiveContentHandlerUseReferrer(Intent intent, Uri referrer) {
+        if (sActiveContentHandler == null) return false;
+        CustomTabsSessionToken session = CustomTabsSessionToken.getSessionTokenFromIntent(intent);
+        if (session == null || !session.equals(sActiveContentHandler.getSession())) return false;
+        String packageName =
+                CustomTabsConnection.getInstance().getClientPackageNameForSession(session);
+        if (TextUtils.isEmpty(packageName)) return false;
+        boolean valid = OriginVerifier.isValidOrigin(
+                packageName, referrer, CustomTabsService.RELATION_USE_AS_ORIGIN);
+
+        // OriginVerifier should only be allowing https schemes.
+        assert valid == UrlConstants.HTTPS_SCHEME.equals(referrer.getScheme());
+
+        return valid;
+    }
+
+    /**
+     * @return The url for the page displayed using the current {@link
+     * BrowserSessionContentHandler}.
+     */
+    public static String getCurrentUrlForActiveBrowserSession() {
+        if (sActiveContentHandler == null) return null;
+        return sActiveContentHandler.getCurrentUrl();
+    }
+
+    /**
+     * Checks whether the active {@link BrowserSessionContentHandler} belongs to the given session,
+     * and if true, update toolbar's custom button.
+     * @param session     The {@link IBinder} that the calling client represents.
+     * @param bitmap      The new icon for action button.
+     * @param description The new content description for the action button.
+     * @return Whether the update is successful.
+     */
+    public static boolean updateCustomButton(
+            CustomTabsSessionToken session, int id, Bitmap bitmap, String description) {
+        ThreadUtils.assertOnUiThread();
+        // Do nothing if there is no activity or the activity does not belong to this session.
+        if (sActiveContentHandler == null || !sActiveContentHandler.getSession().equals(session)) {
+            return false;
+        }
+        return sActiveContentHandler.updateCustomButton(id, bitmap, description);
+    }
+
+    /**
+     * Checks whether the active {@link BrowserSessionContentHandler} belongs to the given session,
+     * and if true, updates {@link RemoteViews} on the secondary toolbar.
+     * @return Whether the update is successful.
+     */
+    public static boolean updateRemoteViews(CustomTabsSessionToken session, RemoteViews remoteViews,
+            int[] clickableIDs, PendingIntent pendingIntent) {
+        ThreadUtils.assertOnUiThread();
+        // Do nothing if there is no activity or the activity does not belong to this session.
+        if (sActiveContentHandler == null || !sActiveContentHandler.getSession().equals(session)) {
+            return false;
+        }
+        return sActiveContentHandler.updateRemoteViews(remoteViews, clickableIDs, pendingIntent);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserSessionDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserSessionDataProvider.java
new file mode 100644
index 0000000..0951c1c
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserSessionDataProvider.java
@@ -0,0 +1,111 @@
+// 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.browserservices;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.customtabs.CustomTabsIntent;
+import android.support.customtabs.CustomTabsSessionToken;
+
+import org.chromium.chrome.browser.IntentHandler;
+import org.chromium.chrome.browser.util.IntentUtils;
+
+/**
+ * A model class that parses intent from third-party apps for data related with various browser
+ * services related Intent types.
+ */
+public class BrowserSessionDataProvider {
+    private static final String TAG = "BrowserSessionData";
+
+    /**
+     * Extra used to keep the caller alive. Its value is an Intent.
+     */
+    public static final String EXTRA_KEEP_ALIVE = "android.support.customtabs.extra.KEEP_ALIVE";
+
+    private static final String ANIMATION_BUNDLE_PREFIX =
+            Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? "android:activity." : "android:";
+    private static final String BUNDLE_PACKAGE_NAME = ANIMATION_BUNDLE_PREFIX + "packageName";
+    private static final String BUNDLE_ENTER_ANIMATION_RESOURCE =
+            ANIMATION_BUNDLE_PREFIX + "animEnterRes";
+    private static final String BUNDLE_EXIT_ANIMATION_RESOURCE =
+            ANIMATION_BUNDLE_PREFIX + "animExitRes";
+
+    private final CustomTabsSessionToken mSession;
+    private final boolean mIsTrustedIntent;
+    private final Intent mKeepAliveServiceIntent;
+    private Bundle mAnimationBundle;
+
+    /**
+     * Constructs a {@link BrowserSessionDataProvider}.
+     */
+    public BrowserSessionDataProvider(Intent intent) {
+        if (intent == null) assert false;
+        mSession = CustomTabsSessionToken.getSessionTokenFromIntent(intent);
+        mIsTrustedIntent = IntentHandler.isIntentChromeOrFirstParty(intent);
+
+        mAnimationBundle = IntentUtils.safeGetBundleExtra(
+                intent, CustomTabsIntent.EXTRA_EXIT_ANIMATION_BUNDLE);
+
+        mKeepAliveServiceIntent = IntentUtils.safeGetParcelableExtra(intent, EXTRA_KEEP_ALIVE);
+    }
+
+    /**
+     * @return The session specified in the intent, or null.
+     */
+    public CustomTabsSessionToken getSession() {
+        return mSession;
+    }
+
+    /**
+     * @return The keep alive service intent specified in the intent, or null.
+     */
+    public Intent getKeepAliveServiceIntent() {
+        return mKeepAliveServiceIntent;
+    }
+
+    /**
+     * @return Whether chrome should animate when it finishes. We show animations only if the client
+     *         app has supplied the correct animation resources via intent extra.
+     */
+    public boolean shouldAnimateOnFinish() {
+        return mAnimationBundle != null && getClientPackageName() != null;
+    }
+
+    /**
+     * @return The package name of the client app. This is used for a workaround in order to
+     *         retrieve the client's animation resources.
+     */
+    public String getClientPackageName() {
+        if (mAnimationBundle == null) return null;
+        return mAnimationBundle.getString(BUNDLE_PACKAGE_NAME);
+    }
+
+    /**
+     * @return The resource id for enter animation, which is used in
+     *         {@link Activity#overridePendingTransition(int, int)}.
+     */
+    public int getAnimationEnterRes() {
+        return shouldAnimateOnFinish() ? mAnimationBundle.getInt(BUNDLE_ENTER_ANIMATION_RESOURCE)
+                                       : 0;
+    }
+
+    /**
+     * @return The resource id for exit animation, which is used in
+     *         {@link Activity#overridePendingTransition(int, int)}.
+     */
+    public int getAnimationExitRes() {
+        return shouldAnimateOnFinish() ? mAnimationBundle.getInt(BUNDLE_EXIT_ANIMATION_RESOURCE)
+                                       : 0;
+    }
+
+    /**
+     * Checks whether or not the Intent is from Chrome or other trusted first party.
+     */
+    public boolean isTrustedIntent() {
+        return mIsTrustedIntent;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/OWNERS
new file mode 100644
index 0000000..29c5e2ee
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/OWNERS
@@ -0,0 +1,2 @@
+lizeb@chromium.org
+yusufo@chromium.org
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/OriginVerifier.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/OriginVerifier.java
new file mode 100644
index 0000000..251717c
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/OriginVerifier.java
@@ -0,0 +1,284 @@
+// 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.browserservices;
+
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.support.annotation.NonNull;
+import android.support.customtabs.CustomTabsService;
+import android.support.customtabs.CustomTabsService.Relation;
+import android.support.v4.util.Pair;
+import android.text.TextUtils;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.base.Log;
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.VisibleForTesting;
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.library_loader.LibraryProcessType;
+import org.chromium.chrome.browser.IntentHandler;
+import org.chromium.chrome.browser.UrlConstants;
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.content.browser.BrowserStartupController;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Used to verify postMessage origin for a designated package name.
+ *
+ * Uses Digital Asset Links to confirm that the given origin is associated with the package name as
+ * a postMessage origin. It caches any origin that has been verified during the current application
+ * lifecycle and reuses that without making any new network requests.
+ *
+ * The lifecycle of this object is governed by the owner. The owner has to call
+ * {@link OriginVerifier#cleanUp()} for proper cleanup of dependencies.
+ */
+@JNINamespace("customtabs")
+public class OriginVerifier {
+    private static final String TAG = "OriginVerifier";
+    private static final char[] HEX_CHAR_LOOKUP = "0123456789ABCDEF".toCharArray();
+    private static final String USE_AS_ORIGIN = "delegate_permission/common.use_as_origin";
+    private static final String HANDLE_ALL_URLS = "delegate_permission/common.handle_all_urls";
+
+    private static Map<Pair<String, Integer>, Set<Uri>> sPackageToCachedOrigins;
+    private final OriginVerificationListener mListener;
+    private final String mPackageName;
+    private final String mSignatureFingerprint;
+    private final @Relation int mRelation;
+    private long mNativeOriginVerifier = 0;
+    private Uri mOrigin;
+
+    /** Small helper class to post a result of origin verification. */
+    private class VerifiedCallback implements Runnable {
+        private final boolean mResult;
+
+        public VerifiedCallback(boolean result) {
+            this.mResult = result;
+        }
+
+        @Override
+        public void run() {
+            originVerified(mResult);
+        }
+    }
+
+    static Uri getPostMessageOriginFromVerifiedOrigin(String packageName, Uri verifiedOrigin) {
+        return Uri.parse(IntentHandler.ANDROID_APP_REFERRER_SCHEME + "://"
+                + verifiedOrigin.getHost() + "/" + packageName);
+    }
+
+    /** Clears all known relations. */
+    @VisibleForTesting
+    public static void reset() {
+        ThreadUtils.assertOnUiThread();
+        if (sPackageToCachedOrigins != null) sPackageToCachedOrigins.clear();
+    }
+
+    /**
+     * Mark an origin as verified for a package.
+     * @param packageName The package name to prepopulate for.
+     * @param origin The origin to add as verified.
+     * @param relation The Digital Asset Links relation verified.
+     */
+    public static void addVerifiedOriginForPackage(
+            String packageName, Uri origin, @Relation int relation) {
+        ThreadUtils.assertOnUiThread();
+        if (sPackageToCachedOrigins == null) sPackageToCachedOrigins = new HashMap<>();
+        Set<Uri> cachedOrigins =
+                sPackageToCachedOrigins.get(new Pair<String, Integer>(packageName, relation));
+        if (cachedOrigins == null) {
+            cachedOrigins = new HashSet<Uri>();
+            sPackageToCachedOrigins.put(
+                    new Pair<String, Integer>(packageName, relation), cachedOrigins);
+        }
+        cachedOrigins.add(origin);
+    }
+
+    /**
+     * Returns whether an origin is first-party relative to a given package name.
+     *
+     * This only returns data from previously cached relations, and does not
+     * trigger an asynchronous validation.
+     *
+     * @param packageName The package name
+     * @param origin The origin to verify
+     * @param relation The Digital Asset Links relation to verify for.
+     */
+    public static boolean isValidOrigin(String packageName, Uri origin, @Relation int relation) {
+        ThreadUtils.assertOnUiThread();
+        if (sPackageToCachedOrigins == null) return false;
+        Set<Uri> cachedOrigins =
+                sPackageToCachedOrigins.get(new Pair<String, Integer>(packageName, relation));
+        if (cachedOrigins == null) return false;
+        return cachedOrigins.contains(origin);
+    }
+
+    /**
+     * Callback interface for getting verification results.
+     */
+    public interface OriginVerificationListener {
+        /**
+         * To be posted on the handler thread after the verification finishes.
+         * @param packageName The package name for the origin verification query for this result.
+         * @param origin The origin that was declared on the query for this result.
+         * @param verified Whether the given origin was verified to correspond to the given package.
+         */
+        void onOriginVerified(String packageName, Uri origin, boolean verified);
+    }
+
+    /**
+     * Main constructor.
+     * Use {@link OriginVerifier#start(Uri)}
+     * @param listener The listener who will get the verification result.
+     * @param packageName The package for the Android application for verification.
+     * @param relation Digital Asset Links {@link Relation} to use during verification.
+     */
+    public OriginVerifier(
+            OriginVerificationListener listener, String packageName, @Relation int relation) {
+        mListener = listener;
+        mPackageName = packageName;
+        mSignatureFingerprint = getCertificateSHA256FingerprintForPackage(mPackageName);
+        mRelation = relation;
+    }
+
+    /**
+     * Verify the claimed origin for the cached package name asynchronously. This will end up
+     * making a network request for non-cached origins with a URLFetcher using the last used
+     * profile as context.
+     * @param origin The postMessage origin the application is claiming to have. Can't be null.
+     */
+    public void start(@NonNull Uri origin) {
+        ThreadUtils.assertOnUiThread();
+        mOrigin = origin;
+        String scheme = mOrigin.getScheme();
+        if (TextUtils.isEmpty(scheme)
+                || !UrlConstants.HTTPS_SCHEME.equals(scheme.toLowerCase(Locale.US))) {
+            ThreadUtils.runOnUiThread(new VerifiedCallback(false));
+            return;
+        }
+
+        // If this origin is cached as verified already, use that.
+        if (isValidOrigin(mPackageName, origin, mRelation)) {
+            ThreadUtils.runOnUiThread(new VerifiedCallback(true));
+            return;
+        }
+        if (mNativeOriginVerifier != 0) cleanUp();
+        if (!BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER)
+                        .isStartupSuccessfullyCompleted()) {
+            // Early return for testing without native.
+            return;
+        }
+        mNativeOriginVerifier = nativeInit(Profile.getLastUsedProfile().getOriginalProfile());
+        assert mNativeOriginVerifier != 0;
+        String relationship = null;
+        switch (mRelation) {
+            case CustomTabsService.RELATION_USE_AS_ORIGIN:
+                relationship = USE_AS_ORIGIN;
+                break;
+            case CustomTabsService.RELATION_HANDLE_ALL_URLS:
+                relationship = HANDLE_ALL_URLS;
+                break;
+            default:
+                assert false;
+                break;
+        }
+        boolean success = nativeVerifyOrigin(mNativeOriginVerifier, mPackageName,
+                mSignatureFingerprint, mOrigin.toString(), relationship);
+        if (!success) ThreadUtils.runOnUiThread(new VerifiedCallback(false));
+    }
+
+    /**
+     * Cleanup native dependencies on this object.
+     */
+    void cleanUp() {
+        if (mNativeOriginVerifier == 0) return;
+        nativeDestroy(mNativeOriginVerifier);
+        mNativeOriginVerifier = 0;
+    }
+
+    private static PackageInfo getPackageInfo(String packageName) {
+        PackageManager pm = ContextUtils.getApplicationContext().getPackageManager();
+
+        PackageInfo packageInfo = null;
+        try {
+            packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
+        } catch (PackageManager.NameNotFoundException e) {
+            // Will return null if there is no package found.
+        }
+        return packageInfo;
+    }
+
+    /**
+     * Computes the SHA256 certificate for the given package name. The app with the given package
+     * name has to be installed on device. The output will be a 30 long HEX string with : between
+     * each value.
+     * @param packageName The package name to query the signature for.
+     * @return The SHA256 certificate for the package name.
+     */
+    static String getCertificateSHA256FingerprintForPackage(String packageName) {
+        PackageInfo packageInfo = getPackageInfo(packageName);
+        if (packageInfo == null) return null;
+
+        InputStream input = new ByteArrayInputStream(packageInfo.signatures[0].toByteArray());
+        X509Certificate certificate = null;
+        String hexString = null;
+        try {
+            certificate =
+                    (X509Certificate) CertificateFactory.getInstance("X509").generateCertificate(
+                            input);
+            hexString = byteArrayToHexString(
+                    MessageDigest.getInstance("SHA256").digest(certificate.getEncoded()));
+        } catch (CertificateEncodingException e) {
+            Log.w(TAG, "Certificate type X509 encoding failed");
+        } catch (CertificateException | NoSuchAlgorithmException e) {
+            // This shouldn't happen.
+        }
+        return hexString;
+    }
+
+    /**
+     * Converts a byte array to hex string with : inserted between each element.
+     * @param byteArray The array to be converted.
+     * @return A string with two letters representing each byte and : in between.
+     */
+    static String byteArrayToHexString(byte[] byteArray) {
+        StringBuilder hexString = new StringBuilder(byteArray.length * 3 - 1);
+        for (int i = 0; i < byteArray.length; ++i) {
+            hexString.append(HEX_CHAR_LOOKUP[(byteArray[i] & 0xf0) >>> 4]);
+            hexString.append(HEX_CHAR_LOOKUP[byteArray[i] & 0xf]);
+            if (i < (byteArray.length - 1)) hexString.append(':');
+        }
+        return hexString.toString();
+    }
+
+    @CalledByNative
+    private void originVerified(boolean originVerified) {
+        if (originVerified) {
+            addVerifiedOriginForPackage(mPackageName, mOrigin, mRelation);
+            mOrigin = getPostMessageOriginFromVerifiedOrigin(mPackageName, mOrigin);
+        }
+        mListener.onOriginVerified(mPackageName, mOrigin, originVerified);
+        cleanUp();
+    }
+
+    private native long nativeInit(Profile profile);
+    private native boolean nativeVerifyOrigin(long nativeOriginVerifier, String packageName,
+            String signatureFingerprint, String origin, String relationship);
+    private native void nativeDestroy(long nativeOriginVerifier);
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java
new file mode 100644
index 0000000..0d9febd
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java
@@ -0,0 +1,235 @@
+// 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.
+
+package org.chromium.chrome.browser.browserservices;
+
+import android.content.Context;
+import android.net.Uri;
+import android.support.annotation.NonNull;
+import android.support.customtabs.CustomTabsService;
+import android.support.customtabs.CustomTabsService.Relation;
+import android.support.customtabs.CustomTabsSessionToken;
+import android.support.customtabs.PostMessageServiceConnection;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.VisibleForTesting;
+import org.chromium.chrome.browser.browserservices.OriginVerifier.OriginVerificationListener;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.content.browser.AppWebMessagePort;
+import org.chromium.content_public.browser.MessagePort;
+import org.chromium.content_public.browser.MessagePort.MessageCallback;
+import org.chromium.content_public.browser.WebContents;
+import org.chromium.content_public.browser.WebContentsObserver;
+
+/**
+ * A class that handles postMessage communications with a designated {@link CustomTabsSessionToken}.
+ */
+public class PostMessageHandler
+        extends PostMessageServiceConnection implements OriginVerificationListener {
+    private final MessageCallback mMessageCallback;
+    private OriginVerifier mOriginVerifier;
+    private WebContents mWebContents;
+    private boolean mMessageChannelCreated;
+    private boolean mBoundToService;
+    private AppWebMessagePort[] mChannel;
+    private Uri mOrigin;
+    private String mPackageName;
+    private @Relation int mRelation;
+
+    /**
+     * Basic constructor. Everytime the given {@link CustomTabsSessionToken} is associated with a
+     * new {@link WebContents},
+     * {@link PostMessageHandler#reset(WebContents)} should be called to
+     * reset all internal state.
+     * @param session The {@link CustomTabsSessionToken} to establish the postMessage communication
+     *                with.
+     */
+    public PostMessageHandler(CustomTabsSessionToken session) {
+        super(session);
+        mMessageCallback = new MessageCallback() {
+            @Override
+            public void onMessage(String message, MessagePort[] sentPorts) {
+                if (mBoundToService) postMessage(message, null);
+            }
+        };
+    }
+
+    /**
+     * Sets the package name unique to the session.
+     * @param packageName The package name for the client app for the owning session.
+     */
+    public void setPackageName(@NonNull String packageName) {
+        mPackageName = packageName;
+    }
+
+    /**
+     * Resets the internal state of the handler, linking the associated
+     * {@link CustomTabsSessionToken} with a new {@link WebContents} and the {@link Tab} that
+     * contains it.
+     * @param webContents The new {@link WebContents} that the session got associated with. If this
+     *                    is null, the handler disconnects and unbinds from service.
+     */
+    public void reset(final WebContents webContents) {
+        if (webContents == null || webContents.isDestroyed()) {
+            disconnectChannel();
+            unbindFromContext(ContextUtils.getApplicationContext());
+            return;
+        }
+        // Can't reset with the same web contents twice.
+        if (webContents.equals(mWebContents)) return;
+        mWebContents = webContents;
+        if (mOrigin == null) return;
+        new WebContentsObserver(webContents) {
+            private boolean mNavigatedOnce;
+
+            @Override
+            public void didFinishNavigation(String url, boolean isInMainFrame, boolean isErrorPage,
+                    boolean hasCommitted, boolean isSameDocument, boolean isFragmentNavigation,
+                    Integer pageTransition, int errorCode, String errorDescription,
+                    int httpStatusCode) {
+                if (mNavigatedOnce && hasCommitted && isInMainFrame && !isSameDocument
+                        && mChannel != null) {
+                    webContents.removeObserver(this);
+                    disconnectChannel();
+                    unbindFromContext(ContextUtils.getApplicationContext());
+                    return;
+                }
+                mNavigatedOnce = true;
+            }
+
+            @Override
+            public void renderProcessGone(boolean wasOomProtected) {
+                disconnectChannel();
+                unbindFromContext(ContextUtils.getApplicationContext());
+            }
+
+            @Override
+            public void documentLoadedInFrame(long frameId, boolean isMainFrame) {
+                if (!isMainFrame || mChannel != null) return;
+                initializeWithWebContents(webContents);
+            }
+        };
+    }
+
+    /**
+     * See
+     * {@link PostMessageServiceConnection#bindSessionToPostMessageService(Context, String)}.
+     * Attempts to bind with the package name set during initialization.
+     */
+    public boolean bindSessionToPostMessageService() {
+        return super.bindSessionToPostMessageService(
+                ContextUtils.getApplicationContext(), mPackageName);
+    }
+
+    private void initializeWithWebContents(final WebContents webContents) {
+        mChannel = (AppWebMessagePort[]) webContents.createMessageChannel();
+        mChannel[0].setMessageCallback(mMessageCallback, null);
+
+        webContents.postMessageToFrame(
+                null, "", mOrigin.toString(), "", new AppWebMessagePort[] {mChannel[1]});
+
+        mMessageChannelCreated = true;
+        if (mBoundToService) notifyMessageChannelReady(null);
+    }
+
+    private void disconnectChannel() {
+        if (mChannel == null) return;
+        mChannel[0].close();
+        mChannel = null;
+        mWebContents = null;
+    }
+
+    /**
+     * Sets the postMessage origin for this session to the given {@link Uri}.
+     * @param origin The origin value to be set.
+     */
+    public void initializeWithOrigin(Uri origin) {
+        mOrigin = origin;
+        if (mWebContents != null && !mWebContents.isDestroyed()) {
+            initializeWithWebContents(mWebContents);
+        }
+    }
+
+    /**
+     * Asynchronously verify the postMessage origin for the given package name and initialize with
+     * it if the result is a success. Can be called multiple times. If so, the previous requests
+     * will be overridden.
+     * @param origin The origin to verify for.
+     */
+    public void verifyAndInitializeWithOrigin(final Uri origin, @Relation int relation) {
+        mRelation = relation;
+        mOriginVerifier = new OriginVerifier(this, mPackageName, mRelation);
+        ThreadUtils.postOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mOriginVerifier.start(origin);
+            }
+        });
+    }
+
+    /**
+     * Relay a postMessage request through the current channel assigned to this session.
+     * @param message The message to be sent.
+     * @return The result of the postMessage request. Returning true means the request was accepted,
+     *         not necessarily that the postMessage was successful.
+     */
+    public int postMessageFromClientApp(final String message) {
+        if (mChannel == null || !mChannel[0].isReady() || mChannel[0].isClosed()) {
+            return CustomTabsService.RESULT_FAILURE_MESSAGING_ERROR;
+        }
+        if (mWebContents == null || mWebContents.isDestroyed()) {
+            return CustomTabsService.RESULT_FAILURE_MESSAGING_ERROR;
+        }
+        ThreadUtils.postOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // It is still possible that the page has navigated while this task is in the queue.
+                // If that happens fail gracefully.
+                if (mChannel == null || mChannel[0].isClosed()) return;
+                mChannel[0].postMessage(message, null);
+            }
+        });
+        return CustomTabsService.RESULT_SUCCESS;
+    }
+
+    @Override
+    public void unbindFromContext(Context context) {
+        if (mBoundToService) super.unbindFromContext(context);
+    }
+
+    @Override
+    public void onPostMessageServiceConnected() {
+        mBoundToService = true;
+        if (mMessageChannelCreated) notifyMessageChannelReady(null);
+    }
+
+    @Override
+    public void onPostMessageServiceDisconnected() {
+        mBoundToService = false;
+    }
+
+    @Override
+    public void onOriginVerified(String packageName, Uri origin, boolean result) {
+        if (!result) return;
+        initializeWithOrigin(origin);
+    }
+
+    /**
+     * @return The origin that has been declared for this handler.
+     */
+    @VisibleForTesting
+    public Uri getOriginForTesting() {
+        return mOrigin;
+    }
+
+    /**
+     * Cleans up any dependencies that this handler might have.
+     * @param context Context to use for unbinding if necessary.
+     */
+    public void cleanup(Context context) {
+        if (mBoundToService) super.unbindFromContext(context);
+        if (mOriginVerifier != null) mOriginVerifier.cleanUp();
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java
index e052ae4..7e6d867 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java
@@ -9,6 +9,7 @@
 import android.content.Context;
 import android.view.animation.Interpolator;
 
+import org.chromium.chrome.browser.compositor.animation.CompositorAnimationHandler;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.PanelState;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason;
 import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation;
@@ -75,6 +76,13 @@
     // ============================================================================================
 
     /**
+     * @return The handler responsible for running compositor animations.
+     */
+    public CompositorAnimationHandler getAnimationHandler() {
+        return mUpdateHost.getAnimationHandler();
+    }
+
+    /**
      * Animates the Overlay Panel to its maximized state.
      *
      * @param reason The reason for the change of panel state.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBase.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBase.java
index fad120a..ca64030 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBase.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBase.java
@@ -159,6 +159,13 @@
     // ============================================================================================
 
     /**
+     * @return An Android {@link Context}.
+     */
+    public Context getContext() {
+        return mContext;
+    }
+
+    /**
      * Animates the Overlay Panel to its closed state.
      * @param reason The reason for the change of panel state.
      * @param animate If the panel should animate closed.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java
index 2e6394ff..7e807fa 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java
@@ -16,6 +16,7 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.SuppressFBWarnings;
 import org.chromium.chrome.browser.compositor.LayerTitleCache;
+import org.chromium.chrome.browser.compositor.animation.CompositorAnimationHandler;
 import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.Animatable;
 import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.Animation;
 import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
@@ -135,6 +136,13 @@
     }
 
     /**
+     * @return The handler responsible for running compositor animations.
+     */
+    public CompositorAnimationHandler getAnimationHandler() {
+        return mUpdateHost.getAnimationHandler();
+    }
+
+    /**
      * Adds a {@link SceneOverlay} that can potentially be shown on top of this {@link Layout}.  The
      * {@link SceneOverlay}s added to this {@link Layout} will be cascaded in the order they are
      * added.  The {@link SceneOverlay} added first will become the content of the
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java
index 48bb843c..8ecc2238 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java
@@ -149,6 +149,11 @@
         setNextLayout(null);
     }
 
+    @Override
+    public CompositorAnimationHandler getAnimationHandler() {
+        return mAnimationHandler;
+    }
+
     /**
      * @return The actual current time of the app in ms.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutUpdateHost.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutUpdateHost.java
index 17d2da7..447eee5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutUpdateHost.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutUpdateHost.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.compositor.layouts;
 
+import org.chromium.chrome.browser.compositor.animation.CompositorAnimationHandler;
 import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
 import org.chromium.chrome.browser.tab.Tab;
 
@@ -79,4 +80,10 @@
      *           {@link org.chromium.chrome.browser.tabmodel.TabModel}.
      */
     void releaseTabLayout(int id);
+
+    /**
+     * Get the handler responsible for running the compositor's animations.
+     * @return The {@link CompositorAnimationHandler}.
+     */
+    CompositorAnimationHandler getAnimationHandler();
 }
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 c21d773..466c7dc 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
@@ -425,7 +425,7 @@
         if (basePageWebContents != null) {
             mDidExpandSelection = true;
             basePageWebContents.adjustSelectionByCharacterOffset(
-                    selectionStartAdjust, selectionEndAdjust);
+                    selectionStartAdjust, selectionEndAdjust, /* show_selection_menu = */ false);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java
index 8e9f6655..6cc4a1e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java
@@ -24,6 +24,8 @@
 import org.chromium.base.annotations.SuppressFBWarnings;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.browser.IntentHandler;
+import org.chromium.chrome.browser.browserservices.OriginVerifier;
+import org.chromium.chrome.browser.browserservices.PostMessageHandler;
 import org.chromium.chrome.browser.util.UrlUtilities;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.common.Referrer;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomButtonParams.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomButtonParams.java
index 9b4a58d..8f71f3dd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomButtonParams.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomButtonParams.java
@@ -39,7 +39,7 @@
 /**
  * Container for all parameters related to creating a customizable button.
  */
-class CustomButtonParams {
+public class CustomButtonParams {
     private static final String TAG = "CustomTabs";
 
     private final PendingIntent mPendingIntent;
@@ -70,7 +70,7 @@
     /**
      * @return Whether this button should be shown on the toolbar.
      */
-    boolean showOnToolbar() {
+    public boolean showOnToolbar() {
         return mIsOnToolbar;
     }
 
@@ -78,7 +78,7 @@
      * @return The id associated with this button. The custom button on the toolbar always uses
      *         {@link CustomTabsIntent#TOOLBAR_ACTION_BUTTON_ID} as id.
      */
-    int getId() {
+    public int getId() {
         return mId;
     }
 
@@ -101,9 +101,9 @@
     }
 
     /**
-    * @return The {@link PendingIntent} that will be sent when user clicks the customized button.
-    */
-    PendingIntent getPendingIntent() {
+     * @return The {@link PendingIntent} that will be sent when user clicks the customized button.
+     */
+    public PendingIntent getPendingIntent() {
         return mPendingIntent;
     }
 
@@ -117,8 +117,8 @@
     ImageButton buildBottomBarButton(Context context, ViewGroup parent, OnClickListener listener) {
         if (mIsOnToolbar) return null;
 
-        ImageButton button = (ImageButton) LayoutInflater.from(context)
-                .inflate(R.layout.custom_tabs_bottombar_item, parent, false);
+        ImageButton button = (ImageButton) LayoutInflater.from(context).inflate(
+                R.layout.custom_tabs_bottombar_item, parent, false);
         button.setId(mId);
         button.setImageBitmap(mIcon);
         button.setContentDescription(mDescription);
@@ -139,8 +139,7 @@
                 Toast toast = Toast.makeText(
                         view.getContext(), view.getContentDescription(), Toast.LENGTH_SHORT);
                 toast.setGravity(Gravity.BOTTOM | Gravity.END,
-                        screenWidth - screenPos[0] - width / 2,
-                        screenHeight - screenPos[1]);
+                        screenWidth - screenPos[0] - width / 2, screenHeight - screenPos[1]);
                 toast.show();
                 return true;
             }
@@ -153,16 +152,16 @@
      * @param intent The intent sent by the client.
      * @return A list of parsed {@link CustomButtonParams}. Return an empty list if input is invalid
      */
-    static List<CustomButtonParams> fromIntent(Context context, Intent intent) {
+    public static List<CustomButtonParams> fromIntent(Context context, Intent intent) {
         List<CustomButtonParams> paramsList = new ArrayList<>(1);
         if (intent == null) return paramsList;
 
-        Bundle singleBundle = IntentUtils.safeGetBundleExtra(intent,
-                CustomTabsIntent.EXTRA_ACTION_BUTTON_BUNDLE);
-        ArrayList<Bundle> bundleList = IntentUtils.getParcelableArrayListExtra(intent,
-                CustomTabsIntent.EXTRA_TOOLBAR_ITEMS);
-        boolean tinted = IntentUtils.safeGetBooleanExtra(intent,
-                CustomTabsIntent.EXTRA_TINT_ACTION_BUTTON, false);
+        Bundle singleBundle =
+                IntentUtils.safeGetBundleExtra(intent, CustomTabsIntent.EXTRA_ACTION_BUTTON_BUNDLE);
+        ArrayList<Bundle> bundleList = IntentUtils.getParcelableArrayListExtra(
+                intent, CustomTabsIntent.EXTRA_TOOLBAR_ITEMS);
+        boolean tinted = IntentUtils.safeGetBooleanExtra(
+                intent, CustomTabsIntent.EXTRA_TINT_ACTION_BUTTON, false);
         if (singleBundle != null) {
             CustomButtonParams singleParams = fromBundle(context, singleBundle, tinted, false);
             if (singleParams != null) paramsList.add(singleParams);
@@ -190,13 +189,13 @@
      * @param fromList Whether the bundle is contained in a list or it is the single bundle that
      *                 directly comes from the intent.
      */
-    private static CustomButtonParams fromBundle(Context context, Bundle bundle, boolean tinted,
-            boolean fromList) {
+    private static CustomButtonParams fromBundle(
+            Context context, Bundle bundle, boolean tinted, boolean fromList) {
         if (bundle == null) return null;
 
         if (fromList && !bundle.containsKey(CustomTabsIntent.KEY_ID)) return null;
-        int id = IntentUtils.safeGetInt(bundle, CustomTabsIntent.KEY_ID,
-                CustomTabsIntent.TOOLBAR_ACTION_BUTTON_ID);
+        int id = IntentUtils.safeGetInt(
+                bundle, CustomTabsIntent.KEY_ID, CustomTabsIntent.TOOLBAR_ACTION_BUTTON_ID);
 
         Bitmap bitmap = parseBitmapFromBundle(bundle);
         if (bitmap == null) {
@@ -215,13 +214,14 @@
         boolean onToolbar = id == CustomTabsIntent.TOOLBAR_ACTION_BUTTON_ID;
         if (onToolbar && !doesIconFitToolbar(context, bitmap)) {
             onToolbar = false;
-            Log.w(TAG, "Button's icon not suitable for toolbar, putting it to bottom bar instead."
-                    + "See: https://developer.android.com/reference/android/support/customtabs/"
-                    + "CustomTabsIntent.html#KEY_ICON");
+            Log.w(TAG,
+                    "Button's icon not suitable for toolbar, putting it to bottom bar instead."
+                            + "See: https://developer.android.com/reference/android/support/customtabs/"
+                            + "CustomTabsIntent.html#KEY_ICON");
         }
 
-        PendingIntent pendingIntent = IntentUtils.safeGetParcelable(bundle,
-                CustomTabsIntent.KEY_PENDING_INTENT);
+        PendingIntent pendingIntent =
+                IntentUtils.safeGetParcelable(bundle, CustomTabsIntent.KEY_PENDING_INTENT);
         // PendingIntent is a must for buttons on the toolbar, but it's optional for bottom bar.
         if (onToolbar && pendingIntent == null) {
             Log.w(TAG, "Invalid action button on toolbar: pending intent not present in bundle!");
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
index 753ec72..160e8a0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -18,12 +18,10 @@
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.IBinder;
 import android.os.StrictMode;
 import android.provider.Browser;
 import android.support.customtabs.CustomTabsCallback;
 import android.support.customtabs.CustomTabsIntent;
-import android.support.customtabs.CustomTabsService;
 import android.support.customtabs.CustomTabsSessionToken;
 import android.support.v4.app.ActivityOptionsCompat;
 import android.text.TextUtils;
@@ -38,7 +36,6 @@
 
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.ContextUtils;
-import org.chromium.base.Log;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.metrics.RecordHistogram;
@@ -53,6 +50,8 @@
 import org.chromium.chrome.browser.WarmupManager;
 import org.chromium.chrome.browser.WebContentsFactory;
 import org.chromium.chrome.browser.appmenu.AppMenuPropertiesDelegate;
+import org.chromium.chrome.browser.browserservices.BrowserSessionContentHandler;
+import org.chromium.chrome.browser.browserservices.BrowserSessionContentUtils;
 import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
 import org.chromium.chrome.browser.datausage.DataUseTabUIManager;
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
@@ -92,7 +91,6 @@
  * The activity for custom tabs. It will be launched on top of a client's task.
  */
 public class CustomTabActivity extends ChromeActivity {
-
     private static final String TAG = "CustomTabActivity";
     private static final String LAST_URL_PREF = "pref_last_custom_tab_url";
 
@@ -110,11 +108,9 @@
     private static final int CONNECTION_STATUS_CONNECTED_KEEP_ALIVE = 3;
     private static final int CONNECTION_STATUS_MAX = 4;
 
-    private static CustomTabContentHandler sActiveContentHandler;
-
     private CustomTabIntentDataProvider mIntentDataProvider;
     private CustomTabsSessionToken mSession;
-    private CustomTabContentHandler mCustomTabContentHandler;
+    private BrowserSessionContentHandler mBrowserSessionContentHandler;
     private Tab mMainTab;
     private CustomTabBottomBarDelegate mBottomBarDelegate;
     private CustomTabTabPersistencePolicy mTabPersistencePolicy;
@@ -254,118 +250,6 @@
         }
     };
 
-    /**
-     * Sets the currently active {@link CustomTabContentHandler} in focus.
-     * @param contentHandler {@link CustomTabContentHandler} to set.
-     */
-    public static void setActiveContentHandler(CustomTabContentHandler contentHandler) {
-        sActiveContentHandler = contentHandler;
-    }
-
-    /**
-     * Called when a CustomTabs intent is handled.
-     *
-     * Used to check whether an incoming intent can be handled by the current
-     * {@link CustomTabContentHandler}, and to perform action on new Intent.
-     *
-     * @return Whether the active {@link CustomTabContentHandler} has handled the intent.
-     */
-    public static boolean handleInActiveContentIfNeeded(Intent intent) {
-        CustomTabsSessionToken session = CustomTabsSessionToken.getSessionTokenFromIntent(intent);
-
-        String url = IntentHandler.getUrlFromIntent(intent);
-        if (TextUtils.isEmpty(url)) return false;
-        CustomTabsConnection.getInstance().onHandledIntent(session, url, intent);
-
-        if (sActiveContentHandler == null) return false;
-        if (session == null || !session.equals(sActiveContentHandler.getSession())) return false;
-        if (sActiveContentHandler.shouldIgnoreIntent(intent)) {
-            Log.w(TAG, "Incoming intent to Custom Tab was ignored.");
-            return false;
-        }
-        sActiveContentHandler.loadUrlAndTrackFromTimestamp(new LoadUrlParams(url),
-                IntentHandler.getTimestampFromIntent(intent));
-        return true;
-    }
-
-    /**
-     * @return Whether the given session is the currently active session.
-     */
-    public static boolean isActiveSession(CustomTabsSessionToken session) {
-        if (sActiveContentHandler == null) return false;
-        if (session == null || sActiveContentHandler.getSession() == null) return false;
-        return sActiveContentHandler.getSession().equals(session);
-    }
-
-    /**
-     * Checks whether the given referrer can be used as valid within the Activity launched by the
-     * given intent. For this to be true, the intent should be for a {@link CustomTabsSessionToken}
-     * that is the currently in focus custom tab and also the related client should have a verified
-     * relationship with the referrer origin. This can only be true for https:// origins.
-     *
-     * @param intent The intent that was used to launch the Activity in question.
-     * @param referrer The referrer url that is to be used.
-     * @return Whether the given referrer is a valid first party url to the client that launched
-     *         the activity.
-     */
-    public static boolean canActiveContentHandlerUseReferrer(Intent intent, Uri referrer) {
-        if (sActiveContentHandler == null) return false;
-        CustomTabsSessionToken session = CustomTabsSessionToken.getSessionTokenFromIntent(intent);
-        if (session == null || !session.equals(sActiveContentHandler.getSession())) return false;
-        String packageName =
-                CustomTabsConnection.getInstance().getClientPackageNameForSession(session);
-        if (TextUtils.isEmpty(packageName)) return false;
-        boolean valid = OriginVerifier.isValidOrigin(
-                packageName, referrer, CustomTabsService.RELATION_USE_AS_ORIGIN);
-
-        // OriginVerifier should only be allowing https schemes.
-        assert valid == UrlConstants.HTTPS_SCHEME.equals(referrer.getScheme());
-
-        return valid;
-    }
-
-    /**
-     * @return The url for the page displayed using the current {@link CustomTabContentHandler}.
-     */
-    public static String getCurrentUrlForActiveCustomTabSession() {
-        if (sActiveContentHandler == null) return null;
-        return sActiveContentHandler.getCurrentUrl();
-    }
-
-    /**
-     * Checks whether the active {@link CustomTabContentHandler} belongs to the given session, and
-     * if true, update toolbar's custom button.
-     * @param session     The {@link IBinder} that the calling client represents.
-     * @param bitmap      The new icon for action button.
-     * @param description The new content description for the action button.
-     * @return Whether the update is successful.
-     */
-    static boolean updateCustomButton(
-            CustomTabsSessionToken session, int id, Bitmap bitmap, String description) {
-        ThreadUtils.assertOnUiThread();
-        // Do nothing if there is no activity or the activity does not belong to this session.
-        if (sActiveContentHandler == null || !sActiveContentHandler.getSession().equals(session)) {
-            return false;
-        }
-        return sActiveContentHandler.updateCustomButton(id, bitmap, description);
-    }
-
-    /**
-     * Checks whether the active {@link CustomTabContentHandler} belongs to the given session, and
-     * if true, updates {@link RemoteViews} on the secondary toolbar.
-     * @return Whether the update is successful.
-     */
-    static boolean updateRemoteViews(
-            CustomTabsSessionToken session, RemoteViews remoteViews, int[] clickableIDs,
-            PendingIntent pendingIntent) {
-        ThreadUtils.assertOnUiThread();
-        // Do nothing if there is no activity or the activity does not belong to this session.
-        if (sActiveContentHandler == null || !sActiveContentHandler.getSession().equals(session)) {
-            return false;
-        }
-        return sActiveContentHandler.updateRemoteViews(remoteViews, clickableIDs, pendingIntent);
-    }
-
     @Override
     protected Drawable getBackgroundDrawable() {
         int initialBackgroundColor = mIntentDataProvider.getInitialBackgroundColor();
@@ -551,7 +435,7 @@
                     }
                 });
 
-        mCustomTabContentHandler = new CustomTabContentHandler() {
+        mBrowserSessionContentHandler = new BrowserSessionContentHandler() {
             @Override
             public void loadUrlAndTrackFromTimestamp(LoadUrlParams params, long timestamp) {
                 if (!TextUtils.isEmpty(params.getUrl())) {
@@ -758,7 +642,7 @@
     @Override
     public void onStartWithNative() {
         super.onStartWithNative();
-        setActiveContentHandler(mCustomTabContentHandler);
+        BrowserSessionContentUtils.setActiveContentHandler(mBrowserSessionContentHandler);
         if (mHasCreatedTabEarly && !mMainTab.isLoading()) postDeferredStartupIfNeeded();
     }
 
@@ -804,7 +688,7 @@
     @Override
     public void onStopWithNative() {
         super.onStopWithNative();
-        setActiveContentHandler(null);
+        BrowserSessionContentUtils.setActiveContentHandler(null);
         if (mIsClosing) {
             getTabModelSelector().closeAllTabs(true);
             mTabPersistencePolicy.deleteMetadataStateFileAsync();
@@ -1296,7 +1180,8 @@
         // Custom Tabs can be used to open Chrome help pages before the ToS has been accepted.
         if (IntentHandler.isIntentChromeOrFirstParty(intent)
                 && IntentUtils.safeGetIntExtra(intent, CustomTabIntentDataProvider.EXTRA_UI_TYPE,
-                           CUSTOM_TABS_UI_TYPE_DEFAULT) == CUSTOM_TABS_UI_TYPE_INFO_PAGE) {
+                           CUSTOM_TABS_UI_TYPE_DEFAULT)
+                        == CUSTOM_TABS_UI_TYPE_INFO_PAGE) {
             return false;
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabContentHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabContentHandler.java
deleted file mode 100644
index 8a082179..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabContentHandler.java
+++ /dev/null
@@ -1,59 +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.
-
-package org.chromium.chrome.browser.customtabs;
-
-import android.app.PendingIntent;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.support.customtabs.CustomTabsSessionToken;
-import android.widget.RemoteViews;
-
-import org.chromium.content_public.browser.LoadUrlParams;
-
-/**
- * Interface to handle custom tab calls whenever the session id matched.
- * TODO(yusufo): Add a way to handle mayLaunchUrl as well.
- */
-public interface CustomTabContentHandler {
-    /**
-     * Loads a new url inside the {@link CustomTabContentHandler}, and tracks
-     * its load time.
-     *
-     * @param params The params to use while loading the url.
-     * @param timestamp The intent arrival timestamp, as returned by
-     *                  {@link SystemClock#elapsedRealtime()}.
-     */
-    void loadUrlAndTrackFromTimestamp(LoadUrlParams params, long timestamp);
-
-    /**
-     * @return The session this {@link CustomTabContentHandler} is associated with.
-     */
-    CustomTabsSessionToken getSession();
-
-    /**
-     * Check whether an intent is valid or should be ignored within this content handler.
-     * @param intent The intent to check.
-     * @return Whether the intent should be ignored.
-     */
-    boolean shouldIgnoreIntent(Intent intent);
-
-    /**
-     * Finds the action button with the given id, and updates it with the new content.
-     * @return Whether the action button has been updated.
-     */
-    boolean updateCustomButton(int id, Bitmap bitmap, String description);
-
-    /**
-     * Updates the {@link RemoteViews} shown on the secondary toolbar.
-     * @return Whether this update is successful.
-     */
-    boolean updateRemoteViews(RemoteViews remoteViews, int[] clickableIDs,
-            PendingIntent pendingIntent);
-
-    /**
-     * @return The current url being displayed to the user.
-     */
-    String getCurrentUrl();
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
index 3f4026e..093008a3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.browser.customtabs;
 
-import android.app.Activity;
 import android.app.PendingIntent;
 import android.app.PendingIntent.CanceledException;
 import android.content.Context;
@@ -14,11 +13,9 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
-import android.os.Build;
 import android.os.Bundle;
 import android.support.annotation.IntDef;
 import android.support.customtabs.CustomTabsIntent;
-import android.support.customtabs.CustomTabsSessionToken;
 import android.text.TextUtils;
 import android.util.Pair;
 import android.view.View;
@@ -32,6 +29,7 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeVersionInfo;
 import org.chromium.chrome.browser.IntentHandler;
+import org.chromium.chrome.browser.browserservices.BrowserSessionDataProvider;
 import org.chromium.chrome.browser.util.IntentUtils;
 import org.chromium.chrome.browser.widget.TintedDrawable;
 
@@ -41,10 +39,9 @@
 import java.util.List;
 
 /**
- * A model class that parses intent from third-party apps and provides results to
- * {@link CustomTabActivity}.
+ * A model class that parses the incoming intent for Custom Tabs specific customization data.
  */
-public class CustomTabIntentDataProvider {
+public class CustomTabIntentDataProvider extends BrowserSessionDataProvider {
     private static final String TAG = "CustomTabIntentData";
 
     // The type of UI for Custom Tab to use.
@@ -63,11 +60,6 @@
     public static final int CUSTOM_TABS_UI_TYPE_MINIMAL_UI_WEBAPP = 5;
 
     /**
-     * Extra used to keep the caller alive. Its value is an Intent.
-     */
-    public static final String EXTRA_KEEP_ALIVE = "android.support.customtabs.extra.KEEP_ALIVE";
-
-    /**
      * Herb: Extra that indicates whether or not the Custom Tab is being launched by an Intent fired
      * by Chrome itself.
      */
@@ -98,27 +90,18 @@
     public static final String EXTRA_DISABLE_DOWNLOAD_BUTTON =
             "org.chromium.chrome.browser.customtabs.EXTRA_DISABLE_DOWNLOAD_BUTTON";
 
-    //TODO(yusufo): Move this to CustomTabsIntent.
+    // TODO(yusufo): Move this to CustomTabsIntent.
     /** Signals custom tabs to favor sending initial urls to external handler apps if possible. */
     public static final String EXTRA_SEND_TO_EXTERNAL_DEFAULT_HANDLER =
             "android.support.customtabs.extra.SEND_TO_EXTERNAL_HANDLER";
 
     private static final int MAX_CUSTOM_MENU_ITEMS = 5;
-    private static final String ANIMATION_BUNDLE_PREFIX =
-            Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? "android:activity." : "android:";
-    private static final String BUNDLE_PACKAGE_NAME = ANIMATION_BUNDLE_PREFIX + "packageName";
-    private static final String BUNDLE_ENTER_ANIMATION_RESOURCE =
-            ANIMATION_BUNDLE_PREFIX + "animEnterRes";
-    private static final String BUNDLE_EXIT_ANIMATION_RESOURCE =
-            ANIMATION_BUNDLE_PREFIX + "animExitRes";
+
     private static final String FIRST_PARTY_PITFALL_MSG =
             "The intent contains a non-default UI type, but it is not from a first-party app. "
             + "To make locally-built Chrome a first-party app, sign with release-test "
             + "signing keys and run on userdebug devices. See use_signing_keys GN arg.";
 
-    private final CustomTabsSessionToken mSession;
-    private final boolean mIsTrustedIntent;
-    private final Intent mKeepAliveServiceIntent;
     private final int mUiType;
     private final int mTitleVisibilityState;
     private final String mMediaViewerUrl;
@@ -133,7 +116,6 @@
     private List<CustomButtonParams> mCustomButtonParams;
     private Drawable mCloseButtonIcon;
     private List<Pair<String, PendingIntent>> mMenuEntries = new ArrayList<>();
-    private Bundle mAnimationBundle;
     private boolean mShowShareItem;
     private CustomButtonParams mToolbarButton;
     private List<CustomButtonParams> mBottombarButtons = new ArrayList<>(2);
@@ -168,9 +150,8 @@
      * Constructs a {@link CustomTabIntentDataProvider}.
      */
     public CustomTabIntentDataProvider(Intent intent, Context context) {
+        super(intent);
         if (intent == null) assert false;
-        mSession = CustomTabsSessionToken.getSessionTokenFromIntent(intent);
-        mIsTrustedIntent = IntentHandler.isIntentChromeOrFirstParty(intent);
 
         retrieveCustomButtons(intent, context);
         retrieveToolbarColor(intent, context);
@@ -179,18 +160,17 @@
 
         mEnableUrlBarHiding = IntentUtils.safeGetBooleanExtra(
                 intent, CustomTabsIntent.EXTRA_ENABLE_URLBAR_HIDING, true);
-        mKeepAliveServiceIntent = IntentUtils.safeGetParcelableExtra(intent, EXTRA_KEEP_ALIVE);
 
-        Bitmap bitmap = IntentUtils.safeGetParcelableExtra(intent,
-                CustomTabsIntent.EXTRA_CLOSE_BUTTON_ICON);
+        Bitmap bitmap = IntentUtils.safeGetParcelableExtra(
+                intent, CustomTabsIntent.EXTRA_CLOSE_BUTTON_ICON);
         if (bitmap != null && !checkCloseButtonSize(context, bitmap)) {
             IntentUtils.safeRemoveExtra(intent, CustomTabsIntent.EXTRA_CLOSE_BUTTON_ICON);
             bitmap.recycle();
             bitmap = null;
         }
         if (bitmap == null) {
-            mCloseButtonIcon = TintedDrawable.constructTintedDrawable(context.getResources(),
-                    R.drawable.btn_close);
+            mCloseButtonIcon = TintedDrawable.constructTintedDrawable(
+                    context.getResources(), R.drawable.btn_close);
         } else {
             mCloseButtonIcon = new BitmapDrawable(context.getResources(), bitmap);
         }
@@ -214,29 +194,27 @@
 
         final int requestedUiType =
                 IntentUtils.safeGetIntExtra(intent, EXTRA_UI_TYPE, CUSTOM_TABS_UI_TYPE_DEFAULT);
-        mUiType = verifiedUiType(requestedUiType, context);
+        mUiType = verifiedUiType(requestedUiType);
 
-        mAnimationBundle = IntentUtils.safeGetBundleExtra(
-                intent, CustomTabsIntent.EXTRA_EXIT_ANIMATION_BUNDLE);
-        mTitleVisibilityState = IntentUtils.safeGetIntExtra(intent,
-                CustomTabsIntent.EXTRA_TITLE_VISIBILITY_STATE, CustomTabsIntent.NO_TITLE);
-        mShowShareItem = IntentUtils.safeGetBooleanExtra(intent,
-                CustomTabsIntent.EXTRA_DEFAULT_SHARE_MENU_ITEM, false);
-        mRemoteViews = IntentUtils.safeGetParcelableExtra(intent,
-                CustomTabsIntent.EXTRA_REMOTEVIEWS);
-        mClickableViewIds = IntentUtils.safeGetIntArrayExtra(intent,
-                CustomTabsIntent.EXTRA_REMOTEVIEWS_VIEW_IDS);
-        mRemoteViewsPendingIntent = IntentUtils.safeGetParcelableExtra(intent,
-                CustomTabsIntent.EXTRA_REMOTEVIEWS_PENDINGINTENT);
+        mTitleVisibilityState = IntentUtils.safeGetIntExtra(
+                intent, CustomTabsIntent.EXTRA_TITLE_VISIBILITY_STATE, CustomTabsIntent.NO_TITLE);
+        mShowShareItem = IntentUtils.safeGetBooleanExtra(
+                intent, CustomTabsIntent.EXTRA_DEFAULT_SHARE_MENU_ITEM, false);
+        mRemoteViews =
+                IntentUtils.safeGetParcelableExtra(intent, CustomTabsIntent.EXTRA_REMOTEVIEWS);
+        mClickableViewIds = IntentUtils.safeGetIntArrayExtra(
+                intent, CustomTabsIntent.EXTRA_REMOTEVIEWS_VIEW_IDS);
+        mRemoteViewsPendingIntent = IntentUtils.safeGetParcelableExtra(
+                intent, CustomTabsIntent.EXTRA_REMOTEVIEWS_PENDINGINTENT);
         mMediaViewerUrl = isMediaViewer()
                 ? IntentUtils.safeGetStringExtra(intent, EXTRA_MEDIA_VIEWER_URL)
                 : null;
-        mEnableEmbeddedMediaExperience = mIsTrustedIntent
+        mEnableEmbeddedMediaExperience = isTrustedIntent()
                 && IntentUtils.safeGetBooleanExtra(
                            intent, EXTRA_ENABLE_EMBEDDED_MEDIA_EXPERIENCE, false);
         mDisableStar = IntentUtils.safeGetBooleanExtra(intent, EXTRA_DISABLE_STAR_BUTTON, false);
-        mDisableDownload = IntentUtils.safeGetBooleanExtra(intent, EXTRA_DISABLE_DOWNLOAD_BUTTON,
-                false);
+        mDisableDownload =
+                IntentUtils.safeGetBooleanExtra(intent, EXTRA_DISABLE_DOWNLOAD_BUTTON, false);
     }
 
     /**
@@ -244,8 +222,8 @@
      * @param requestedUiType requested UI type in the intent, unqualified
      * @return verified UI type
      */
-    private int verifiedUiType(int requestedUiType, Context context) {
-        if (!mIsTrustedIntent) {
+    private int verifiedUiType(int requestedUiType) {
+        if (!isTrustedIntent()) {
             if (ChromeVersionInfo.isLocalBuild()) Log.w(TAG, FIRST_PARTY_PITFALL_MSG);
             return CUSTOM_TABS_UI_TYPE_DEFAULT;
         }
@@ -280,10 +258,10 @@
      * Processes the color passed from the client app and updates {@link #mToolbarColor}.
      */
     private void retrieveToolbarColor(Intent intent, Context context) {
-        int defaultColor = ApiCompatibilityUtils.getColor(context.getResources(),
-                R.color.default_primary_color);
-        int color = IntentUtils.safeGetIntExtra(intent, CustomTabsIntent.EXTRA_TOOLBAR_COLOR,
-                defaultColor);
+        int defaultColor = ApiCompatibilityUtils.getColor(
+                context.getResources(), R.color.default_primary_color);
+        int color = IntentUtils.safeGetIntExtra(
+                intent, CustomTabsIntent.EXTRA_TOOLBAR_COLOR, defaultColor);
         mToolbarColor = removeTransparencyFromColor(color);
     }
 
@@ -292,8 +270,8 @@
      */
     private void retrieveBottomBarColor(Intent intent) {
         int defaultColor = mToolbarColor;
-        int color = IntentUtils.safeGetIntExtra(intent,
-                CustomTabsIntent.EXTRA_SECONDARY_TOOLBAR_COLOR, defaultColor);
+        int color = IntentUtils.safeGetIntExtra(
+                intent, CustomTabsIntent.EXTRA_SECONDARY_TOOLBAR_COLOR, defaultColor);
         mBottomBarColor = removeTransparencyFromColor(color);
     }
 
@@ -303,8 +281,8 @@
      */
     private int retrieveInitialBackgroundColor(Intent intent) {
         int defaultColor = Color.TRANSPARENT;
-        int color = IntentUtils.safeGetIntExtra(
-                intent, EXTRA_INITIAL_BACKGROUND_COLOR, defaultColor);
+        int color =
+                IntentUtils.safeGetIntExtra(intent, EXTRA_INITIAL_BACKGROUND_COLOR, defaultColor);
         return color == Color.TRANSPARENT ? color : removeTransparencyFromColor(color);
     }
 
@@ -316,20 +294,6 @@
     }
 
     /**
-     * @return The session specified in the intent, or null.
-     */
-    public CustomTabsSessionToken getSession() {
-        return mSession;
-    }
-
-    /**
-     * @return The keep alive service intent specified in the intent, or null.
-     */
-    public Intent getKeepAliveServiceIntent() {
-        return mKeepAliveServiceIntent;
-    }
-
-    /**
      * @return Whether url bar hiding should be enabled in the custom tab. Default is false.
      */
     public boolean shouldEnableUrlBarHiding() {
@@ -478,41 +442,6 @@
     }
 
     /**
-     * @return Whether chrome should animate when it finishes. We show animations only if the client
-     *         app has supplied the correct animation resources via intent extra.
-     */
-    public boolean shouldAnimateOnFinish() {
-        return mAnimationBundle != null && getClientPackageName() != null;
-    }
-
-    /**
-     * @return The package name of the client app. This is used for a workaround in order to
-     *         retrieve the client's animation resources.
-     */
-    public String getClientPackageName() {
-        if (mAnimationBundle == null) return null;
-        return mAnimationBundle.getString(BUNDLE_PACKAGE_NAME);
-    }
-
-    /**
-     * @return The resource id for enter animation, which is used in
-     *         {@link Activity#overridePendingTransition(int, int)}.
-     */
-    public int getAnimationEnterRes() {
-        return shouldAnimateOnFinish() ? mAnimationBundle.getInt(BUNDLE_ENTER_ANIMATION_RESOURCE)
-                : 0;
-    }
-
-    /**
-     * @return The resource id for exit animation, which is used in
-     *         {@link Activity#overridePendingTransition(int, int)}.
-     */
-    public int getAnimationExitRes() {
-        return shouldAnimateOnFinish() ? mAnimationBundle.getInt(BUNDLE_EXIT_ANIMATION_RESOURCE)
-                : 0;
-    }
-
-    /**
      * Sends the pending intent for the custom button on toolbar with the given url as data.
      * @param context The context to use for sending the {@link PendingIntent}.
      * @param url The url to attach as additional data to the {@link PendingIntent}.
@@ -521,8 +450,8 @@
         Intent addedIntent = new Intent();
         addedIntent.setData(Uri.parse(url));
         try {
-            getCustomButtonOnToolbar().getPendingIntent().send(context, 0, addedIntent, mOnFinished,
-                    null);
+            getCustomButtonOnToolbar().getPendingIntent().send(
+                    context, 0, addedIntent, mOnFinished, null);
         } catch (CanceledException e) {
             Log.e(TAG, "CanceledException while sending pending intent in custom tab");
         }
@@ -551,13 +480,6 @@
     }
 
     /**
-     * Checks whether or not the Intent is from Chrome or other trusted first party.
-     */
-    boolean isTrustedIntent() {
-        return mIsTrustedIntent;
-    }
-
-    /**
      * @return See {@link #EXTRA_UI_TYPE}.
      */
     boolean isMediaViewer() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
index 45e7c4b..19aad3e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
@@ -48,6 +48,8 @@
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.WarmupManager;
+import org.chromium.chrome.browser.browserservices.BrowserSessionContentUtils;
+import org.chromium.chrome.browser.browserservices.PostMessageHandler;
 import org.chromium.chrome.browser.device.DeviceClassManager;
 import org.chromium.chrome.browser.init.ChainedTasks;
 import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
@@ -607,8 +609,8 @@
                     result &= ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() {
                         @Override
                         public Boolean call() throws Exception {
-                            return CustomTabActivity.updateCustomButton(session, id,
-                                    bitmap, description);
+                            return BrowserSessionContentUtils.updateCustomButton(
+                                    session, id, bitmap, description);
                         }
                     });
                 } catch (ExecutionException e) {
@@ -627,8 +629,8 @@
                 result &= ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() {
                     @Override
                     public Boolean call() throws Exception {
-                        return CustomTabActivity.updateRemoteViews(session,
-                                remoteViews, clickableIDs, pendingIntent);
+                        return BrowserSessionContentUtils.updateRemoteViews(
+                                session, remoteViews, clickableIDs, pendingIntent);
                     }
                 });
             } catch (ExecutionException e) {
@@ -650,7 +652,7 @@
     private boolean requestPostMessageChannelInternal(final CustomTabsSessionToken session,
             final Uri postMessageOrigin) {
         if (!mWarmupHasBeenCalled.get()) return false;
-        if (!isCallerForegroundOrSelf() && !CustomTabActivity.isActiveSession(session)) {
+        if (!isCallerForegroundOrSelf() && !BrowserSessionContentUtils.isActiveSession(session)) {
             return false;
         }
         if (!mClientManager.bindToPostMessageServiceForSession(session)) return false;
@@ -695,7 +697,7 @@
     public int postMessage(CustomTabsSessionToken session, String message, Bundle extras) {
         int result;
         if (!mWarmupHasBeenCalled.get()) result = CustomTabsService.RESULT_FAILURE_DISALLOWED;
-        if (!isCallerForegroundOrSelf() && !CustomTabActivity.isActiveSession(session)) {
+        if (!isCallerForegroundOrSelf() && !BrowserSessionContentUtils.isActiveSession(session)) {
             result = CustomTabsService.RESULT_FAILURE_DISALLOWED;
         }
         // If called before a validatePostMessageOrigin, the post message origin will be invalid and
@@ -853,7 +855,7 @@
      * @param url URL extracted from the intent.
      * @param intent incoming intent.
      */
-    void onHandledIntent(CustomTabsSessionToken session, String url, Intent intent) {
+    public void onHandledIntent(CustomTabsSessionToken session, String url, Intent intent) {
         if (mLogRequests) {
             Log.w(TAG, "onHandledIntent, URL = " + url);
             Bundle extras = intent.getExtras();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/OriginVerifier.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/OriginVerifier.java
deleted file mode 100644
index 5d390ab..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/OriginVerifier.java
+++ /dev/null
@@ -1,284 +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.customtabs;
-
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.net.Uri;
-import android.support.annotation.NonNull;
-import android.support.customtabs.CustomTabsService;
-import android.support.customtabs.CustomTabsService.Relation;
-import android.support.v4.util.Pair;
-import android.text.TextUtils;
-
-import org.chromium.base.ContextUtils;
-import org.chromium.base.Log;
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.VisibleForTesting;
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-import org.chromium.base.library_loader.LibraryProcessType;
-import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.UrlConstants;
-import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.content.browser.BrowserStartupController;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Used to verify postMessage origin for a designated package name.
- *
- * Uses Digital Asset Links to confirm that the given origin is associated with the package name as
- * a postMessage origin. It caches any origin that has been verified during the current application
- * lifecycle and reuses that without making any new network requests.
- *
- * The lifecycle of this object is governed by the owner. The owner has to call
- * {@link OriginVerifier#cleanUp()} for proper cleanup of dependencies.
- */
-@JNINamespace("customtabs")
-class OriginVerifier {
-    private static final String TAG = "OriginVerifier";
-    private static final char[] HEX_CHAR_LOOKUP = "0123456789ABCDEF".toCharArray();
-    private static final String USE_AS_ORIGIN = "delegate_permission/common.use_as_origin";
-    private static final String HANDLE_ALL_URLS = "delegate_permission/common.handle_all_urls";
-
-    private static Map<Pair<String, Integer>, Set<Uri>> sPackageToCachedOrigins;
-    private final OriginVerificationListener mListener;
-    private final String mPackageName;
-    private final String mSignatureFingerprint;
-    private final @Relation int mRelation;
-    private long mNativeOriginVerifier = 0;
-    private Uri mOrigin;
-
-    /** Small helper class to post a result of origin verification. */
-    private class VerifiedCallback implements Runnable {
-        private final boolean mResult;
-
-        public VerifiedCallback(boolean result) {
-            this.mResult = result;
-        }
-
-        @Override
-        public void run() {
-            originVerified(mResult);
-        }
-    }
-
-    static Uri getPostMessageOriginFromVerifiedOrigin(String packageName, Uri verifiedOrigin) {
-        return Uri.parse(IntentHandler.ANDROID_APP_REFERRER_SCHEME + "://"
-                + verifiedOrigin.getHost() + "/" + packageName);
-    }
-
-    /** Clears all known relations. */
-    @VisibleForTesting
-    static void reset() {
-        ThreadUtils.assertOnUiThread();
-        if (sPackageToCachedOrigins != null) sPackageToCachedOrigins.clear();
-    }
-
-    /**
-     * Mark an origin as verified for a package.
-     * @param packageName The package name to prepopulate for.
-     * @param origin The origin to add as verified.
-     * @param relation The Digital Asset Links relation verified.
-     */
-    static void addVerifiedOriginForPackage(
-            String packageName, Uri origin, @Relation int relation) {
-        ThreadUtils.assertOnUiThread();
-        if (sPackageToCachedOrigins == null) sPackageToCachedOrigins = new HashMap<>();
-        Set<Uri> cachedOrigins =
-                sPackageToCachedOrigins.get(new Pair<String, Integer>(packageName, relation));
-        if (cachedOrigins == null) {
-            cachedOrigins = new HashSet<Uri>();
-            sPackageToCachedOrigins.put(
-                    new Pair<String, Integer>(packageName, relation), cachedOrigins);
-        }
-        cachedOrigins.add(origin);
-    }
-
-    /**
-     * Returns whether an origin is first-party relative to a given package name.
-     *
-     * This only returns data from previously cached relations, and does not
-     * trigger an asynchronous validation.
-     *
-     * @param packageName The package name
-     * @param origin The origin to verify
-     * @param relation The Digital Asset Links relation to verify for.
-     */
-    static boolean isValidOrigin(String packageName, Uri origin, @Relation int relation) {
-        ThreadUtils.assertOnUiThread();
-        if (sPackageToCachedOrigins == null) return false;
-        Set<Uri> cachedOrigins =
-                sPackageToCachedOrigins.get(new Pair<String, Integer>(packageName, relation));
-        if (cachedOrigins == null) return false;
-        return cachedOrigins.contains(origin);
-    }
-
-    /**
-     * Callback interface for getting verification results.
-     */
-    public interface OriginVerificationListener {
-        /**
-         * To be posted on the handler thread after the verification finishes.
-         * @param packageName The package name for the origin verification query for this result.
-         * @param origin The origin that was declared on the query for this result.
-         * @param verified Whether the given origin was verified to correspond to the given package.
-         */
-        void onOriginVerified(String packageName, Uri origin, boolean verified);
-    }
-
-    /**
-     * Main constructor.
-     * Use {@link OriginVerifier#start(Uri)}
-     * @param listener The listener who will get the verification result.
-     * @param packageName The package for the Android application for verification.
-     * @param relation Digital Asset Links {@link Relation} to use during verification.
-     */
-    public OriginVerifier(
-            OriginVerificationListener listener, String packageName, @Relation int relation) {
-        mListener = listener;
-        mPackageName = packageName;
-        mSignatureFingerprint = getCertificateSHA256FingerprintForPackage(mPackageName);
-        mRelation = relation;
-    }
-
-    /**
-     * Verify the claimed origin for the cached package name asynchronously. This will end up
-     * making a network request for non-cached origins with a URLFetcher using the last used
-     * profile as context.
-     * @param origin The postMessage origin the application is claiming to have. Can't be null.
-     */
-    public void start(@NonNull Uri origin) {
-        ThreadUtils.assertOnUiThread();
-        mOrigin = origin;
-        String scheme = mOrigin.getScheme();
-        if (TextUtils.isEmpty(scheme)
-                || !UrlConstants.HTTPS_SCHEME.equals(scheme.toLowerCase(Locale.US))) {
-            ThreadUtils.runOnUiThread(new VerifiedCallback(false));
-            return;
-        }
-
-        // If this origin is cached as verified already, use that.
-        if (isValidOrigin(mPackageName, origin, mRelation)) {
-            ThreadUtils.runOnUiThread(new VerifiedCallback(true));
-            return;
-        }
-        if (mNativeOriginVerifier != 0) cleanUp();
-        if (!BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER)
-                        .isStartupSuccessfullyCompleted()) {
-            // Early return for testing without native.
-            return;
-        }
-        mNativeOriginVerifier = nativeInit(Profile.getLastUsedProfile().getOriginalProfile());
-        assert mNativeOriginVerifier != 0;
-        String relationship = null;
-        switch (mRelation) {
-            case CustomTabsService.RELATION_USE_AS_ORIGIN:
-                relationship = USE_AS_ORIGIN;
-                break;
-            case CustomTabsService.RELATION_HANDLE_ALL_URLS:
-                relationship = HANDLE_ALL_URLS;
-                break;
-            default:
-                assert false;
-                break;
-        }
-        boolean success = nativeVerifyOrigin(mNativeOriginVerifier, mPackageName,
-                mSignatureFingerprint, mOrigin.toString(), relationship);
-        if (!success) ThreadUtils.runOnUiThread(new VerifiedCallback(false));
-    }
-
-    /**
-     * Cleanup native dependencies on this object.
-     */
-    void cleanUp() {
-        if (mNativeOriginVerifier == 0) return;
-        nativeDestroy(mNativeOriginVerifier);
-        mNativeOriginVerifier = 0;
-    }
-
-    private static PackageInfo getPackageInfo(String packageName) {
-        PackageManager pm = ContextUtils.getApplicationContext().getPackageManager();
-
-        PackageInfo packageInfo = null;
-        try {
-            packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
-        } catch (PackageManager.NameNotFoundException e) {
-            // Will return null if there is no package found.
-        }
-        return packageInfo;
-    }
-
-    /**
-     * Computes the SHA256 certificate for the given package name. The app with the given package
-     * name has to be installed on device. The output will be a 30 long HEX string with : between
-     * each value.
-     * @param packageName The package name to query the signature for.
-     * @return The SHA256 certificate for the package name.
-     */
-    static String getCertificateSHA256FingerprintForPackage(String packageName) {
-        PackageInfo packageInfo = getPackageInfo(packageName);
-        if (packageInfo == null) return null;
-
-        InputStream input = new ByteArrayInputStream(packageInfo.signatures[0].toByteArray());
-        X509Certificate certificate = null;
-        String hexString = null;
-        try {
-            certificate =
-                    (X509Certificate) CertificateFactory.getInstance("X509").generateCertificate(
-                            input);
-            hexString = byteArrayToHexString(
-                    MessageDigest.getInstance("SHA256").digest(certificate.getEncoded()));
-        } catch (CertificateEncodingException e) {
-            Log.w(TAG, "Certificate type X509 encoding failed");
-        } catch (CertificateException | NoSuchAlgorithmException e) {
-            // This shouldn't happen.
-        }
-        return hexString;
-    }
-
-    /**
-     * Converts a byte array to hex string with : inserted between each element.
-     * @param byteArray The array to be converted.
-     * @return A string with two letters representing each byte and : in between.
-     */
-    static String byteArrayToHexString(byte[] byteArray) {
-        StringBuilder hexString = new StringBuilder(byteArray.length * 3 - 1);
-        for (int i = 0; i < byteArray.length; ++i) {
-            hexString.append(HEX_CHAR_LOOKUP[(byteArray[i] & 0xf0) >>> 4]);
-            hexString.append(HEX_CHAR_LOOKUP[byteArray[i] & 0xf]);
-            if (i < (byteArray.length - 1)) hexString.append(':');
-        }
-        return hexString.toString();
-    }
-
-    @CalledByNative
-    private void originVerified(boolean originVerified) {
-        if (originVerified) {
-            addVerifiedOriginForPackage(mPackageName, mOrigin, mRelation);
-            mOrigin = getPostMessageOriginFromVerifiedOrigin(mPackageName, mOrigin);
-        }
-        mListener.onOriginVerified(mPackageName, mOrigin, originVerified);
-        cleanUp();
-    }
-
-    private native long nativeInit(Profile profile);
-    private native boolean nativeVerifyOrigin(long nativeOriginVerifier, String packageName,
-            String signatureFingerprint, String origin, String relationship);
-    private native void nativeDestroy(long nativeOriginVerifier);
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PostMessageHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PostMessageHandler.java
deleted file mode 100644
index 5333b4e5..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PostMessageHandler.java
+++ /dev/null
@@ -1,235 +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.
-
-package org.chromium.chrome.browser.customtabs;
-
-import android.content.Context;
-import android.net.Uri;
-import android.support.annotation.NonNull;
-import android.support.customtabs.CustomTabsService;
-import android.support.customtabs.CustomTabsService.Relation;
-import android.support.customtabs.CustomTabsSessionToken;
-import android.support.customtabs.PostMessageServiceConnection;
-
-import org.chromium.base.ContextUtils;
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.VisibleForTesting;
-import org.chromium.chrome.browser.customtabs.OriginVerifier.OriginVerificationListener;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.content.browser.AppWebMessagePort;
-import org.chromium.content_public.browser.MessagePort;
-import org.chromium.content_public.browser.MessagePort.MessageCallback;
-import org.chromium.content_public.browser.WebContents;
-import org.chromium.content_public.browser.WebContentsObserver;
-
-/**
- * A class that handles postMessage communications with a designated {@link CustomTabsSessionToken}.
- */
-public class PostMessageHandler
-        extends PostMessageServiceConnection implements OriginVerificationListener {
-    private final MessageCallback mMessageCallback;
-    private OriginVerifier mOriginVerifier;
-    private WebContents mWebContents;
-    private boolean mMessageChannelCreated;
-    private boolean mBoundToService;
-    private AppWebMessagePort[] mChannel;
-    private Uri mOrigin;
-    private String mPackageName;
-    private @Relation int mRelation;
-
-    /**
-     * Basic constructor. Everytime the given {@link CustomTabsSessionToken} is associated with a
-     * new {@link WebContents},
-     * {@link PostMessageHandler#reset(WebContents)} should be called to
-     * reset all internal state.
-     * @param session The {@link CustomTabsSessionToken} to establish the postMessage communication
-     *                with.
-     */
-    public PostMessageHandler(CustomTabsSessionToken session) {
-        super(session);
-        mMessageCallback = new MessageCallback() {
-            @Override
-            public void onMessage(String message, MessagePort[] sentPorts) {
-                if (mBoundToService) postMessage(message, null);
-            }
-        };
-    }
-
-    /**
-     * Sets the package name unique to the session.
-     * @param packageName The package name for the client app for the owning session.
-     */
-    void setPackageName(@NonNull String packageName) {
-        mPackageName = packageName;
-    }
-
-    /**
-     * Resets the internal state of the handler, linking the associated
-     * {@link CustomTabsSessionToken} with a new {@link WebContents} and the {@link Tab} that
-     * contains it.
-     * @param webContents The new {@link WebContents} that the session got associated with. If this
-     *                    is null, the handler disconnects and unbinds from service.
-     */
-    public void reset(final WebContents webContents) {
-        if (webContents == null || webContents.isDestroyed()) {
-            disconnectChannel();
-            unbindFromContext(ContextUtils.getApplicationContext());
-            return;
-        }
-        // Can't reset with the same web contents twice.
-        if (webContents.equals(mWebContents)) return;
-        mWebContents = webContents;
-        if (mOrigin == null) return;
-        new WebContentsObserver(webContents) {
-            private boolean mNavigatedOnce;
-
-            @Override
-            public void didFinishNavigation(String url, boolean isInMainFrame, boolean isErrorPage,
-                    boolean hasCommitted, boolean isSameDocument, boolean isFragmentNavigation,
-                    Integer pageTransition, int errorCode, String errorDescription,
-                    int httpStatusCode) {
-                if (mNavigatedOnce && hasCommitted && isInMainFrame && !isSameDocument
-                        && mChannel != null) {
-                    webContents.removeObserver(this);
-                    disconnectChannel();
-                    unbindFromContext(ContextUtils.getApplicationContext());
-                    return;
-                }
-                mNavigatedOnce = true;
-            }
-
-            @Override
-            public void renderProcessGone(boolean wasOomProtected) {
-                disconnectChannel();
-                unbindFromContext(ContextUtils.getApplicationContext());
-            }
-
-            @Override
-            public void documentLoadedInFrame(long frameId, boolean isMainFrame) {
-                if (!isMainFrame || mChannel != null) return;
-                initializeWithWebContents(webContents);
-            }
-        };
-    }
-
-    /**
-     * See
-     * {@link PostMessageServiceConnection#bindSessionToPostMessageService(Context, String)}.
-     * Attempts to bind with the package name set during initialization.
-     */
-    public boolean bindSessionToPostMessageService() {
-        return super.bindSessionToPostMessageService(
-                ContextUtils.getApplicationContext(), mPackageName);
-    }
-
-    private void initializeWithWebContents(final WebContents webContents) {
-        mChannel = (AppWebMessagePort[]) webContents.createMessageChannel();
-        mChannel[0].setMessageCallback(mMessageCallback, null);
-
-        webContents.postMessageToFrame(
-                null, "", mOrigin.toString(), "", new AppWebMessagePort[] {mChannel[1]});
-
-        mMessageChannelCreated = true;
-        if (mBoundToService) notifyMessageChannelReady(null);
-    }
-
-    private void disconnectChannel() {
-        if (mChannel == null) return;
-        mChannel[0].close();
-        mChannel = null;
-        mWebContents = null;
-    }
-
-    /**
-     * Sets the postMessage origin for this session to the given {@link Uri}.
-     * @param origin The origin value to be set.
-     */
-    public void initializeWithOrigin(Uri origin) {
-        mOrigin = origin;
-        if (mWebContents != null && !mWebContents.isDestroyed()) {
-            initializeWithWebContents(mWebContents);
-        }
-    }
-
-    /**
-     * Asynchronously verify the postMessage origin for the given package name and initialize with
-     * it if the result is a success. Can be called multiple times. If so, the previous requests
-     * will be overridden.
-     * @param origin The origin to verify for.
-     */
-    public void verifyAndInitializeWithOrigin(final Uri origin, @Relation int relation) {
-        mRelation = relation;
-        mOriginVerifier = new OriginVerifier(this, mPackageName, mRelation);
-        ThreadUtils.postOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mOriginVerifier.start(origin);
-            }
-        });
-    }
-
-    /**
-     * Relay a postMessage request through the current channel assigned to this session.
-     * @param message The message to be sent.
-     * @return The result of the postMessage request. Returning true means the request was accepted,
-     *         not necessarily that the postMessage was successful.
-     */
-    public int postMessageFromClientApp(final String message) {
-        if (mChannel == null || !mChannel[0].isReady() || mChannel[0].isClosed()) {
-            return CustomTabsService.RESULT_FAILURE_MESSAGING_ERROR;
-        }
-        if (mWebContents == null || mWebContents.isDestroyed()) {
-            return CustomTabsService.RESULT_FAILURE_MESSAGING_ERROR;
-        }
-        ThreadUtils.postOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                // It is still possible that the page has navigated while this task is in the queue.
-                // If that happens fail gracefully.
-                if (mChannel == null || mChannel[0].isClosed()) return;
-                mChannel[0].postMessage(message, null);
-            }
-        });
-        return CustomTabsService.RESULT_SUCCESS;
-    }
-
-    @Override
-    public void unbindFromContext(Context context) {
-        if (mBoundToService) super.unbindFromContext(context);
-    }
-
-    @Override
-    public void onPostMessageServiceConnected() {
-        mBoundToService = true;
-        if (mMessageChannelCreated) notifyMessageChannelReady(null);
-    }
-
-    @Override
-    public void onPostMessageServiceDisconnected() {
-        mBoundToService = false;
-    }
-
-    @Override
-    public void onOriginVerified(String packageName, Uri origin, boolean result) {
-        if (!result) return;
-        initializeWithOrigin(origin);
-    }
-
-    /**
-     * @return The origin that has been declared for this handler.
-     */
-    @VisibleForTesting
-    Uri getOriginForTesting() {
-        return mOrigin;
-    }
-
-    /**
-     * Cleans up any dependencies that this handler might have.
-     * @param context Context to use for unbinding if necessary.
-     */
-    void cleanup(Context context) {
-        if (mBoundToService) super.unbindFromContext(context);
-        if (mOriginVerifier != null) mOriginVerifier.cleanUp();
-    }
-}
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 721b95b..337d9c5 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
@@ -34,6 +34,7 @@
 import org.chromium.chrome.browser.ShortcutHelper;
 import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.WarmupManager;
+import org.chromium.chrome.browser.browserservices.BrowserSessionContentUtils;
 import org.chromium.chrome.browser.customtabs.CustomTabActivity;
 import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
 import org.chromium.chrome.browser.customtabs.SeparateTaskCustomTabActivity;
@@ -386,7 +387,7 @@
      * in the same task.
      */
     private void launchCustomTabActivity() {
-        boolean handled = CustomTabActivity.handleInActiveContentIfNeeded(getIntent());
+        boolean handled = BrowserSessionContentUtils.handleInActiveContentIfNeeded(getIntent());
         if (handled) return;
 
         maybePrefetchDnsInBackground();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java
index 8b4cdef..bea8f66e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java
@@ -18,6 +18,7 @@
 import org.chromium.chrome.browser.preferences.website.WebsitePermissionsFetcher;
 import org.chromium.webapk.lib.common.WebApkConstants;
 
+import java.io.File;
 import java.util.Collection;
 import java.util.concurrent.TimeUnit;
 
@@ -97,6 +98,13 @@
         RecordHistogram.recordEnumeratedHistogram("WebApk.OpenFromMenu", type, WEBAPK_OPEN_MAX);
     }
 
+    /** Records whether a WebAPK has permission to display notifications. */
+    public static void recordNotificationPermissionStatus(boolean permissionEnabled) {
+        int status = permissionEnabled ? 1 : 0;
+        RecordHistogram.recordEnumeratedHistogram(
+                "WebApk.Notification.Permission.Status", status, 2);
+    }
+
     /**
      * Records whether installing a WebAPK from Google Play succeeded. If not, records the reason
      * that the install failed.
@@ -202,6 +210,41 @@
         }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     }
 
+    public static void logCacheSizeInUMA() {
+        new AsyncTask<Void, Void, Integer>() {
+            private long getDirectorySizeInByte(File dir) {
+                if (dir == null) return 0;
+                if (!dir.isDirectory()) return dir.length();
+
+                long sizeInByte = 0;
+                try {
+                    File[] files = dir.listFiles();
+                    if (files == null) return 0;
+
+                    for (File file : files) {
+                        sizeInByte += getDirectorySizeInByte(file);
+                    }
+                } catch (SecurityException e) {
+                    return 0;
+                }
+                return sizeInByte;
+            }
+
+            @Override
+            protected Integer doInBackground(Void... params) {
+                long cacheSizeInByte =
+                        getDirectorySizeInByte(ContextUtils.getApplicationContext().getCacheDir());
+                return Math.min(2000, (int) (cacheSizeInByte / 1024L / 1024L / 10L * 10L));
+            }
+
+            @Override
+            protected void onPostExecute(Integer cacheSizeInMb) {
+                RecordHistogram.recordSparseSlowlyHistogram(
+                        "WebApk.Install.ChromeCacheSize.Fail", cacheSizeInMb);
+            }
+        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+    }
+
     public static void logUnimportantStorageSizeInUMA() {
         WebsitePermissionsFetcher fetcher =
                 new WebsitePermissionsFetcher(new UnimportantStorageSizeCalculator());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
index 54c5bfc2..dfdab0e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -18,6 +18,7 @@
 import android.support.v7.widget.RecyclerView.ViewHolder;
 import android.text.Editable;
 import android.text.TextWatcher;
+import android.text.method.LinkMovementMethod;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 import android.view.View;
@@ -56,8 +57,11 @@
 import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.MathUtils;
 import org.chromium.chrome.browser.util.ViewUtils;
+import org.chromium.chrome.browser.widget.bottomsheet.ChromeHomePromoDialog;
 import org.chromium.chrome.browser.widget.displaystyle.UiConfig;
 import org.chromium.ui.base.DeviceFormFactor;
+import org.chromium.ui.text.NoUnderlineClickableSpan;
+import org.chromium.ui.text.SpanApplier;
 
 /**
  * The native new tab page, represented by some basic data such as title and url, and an Android
@@ -284,6 +288,7 @@
 
         initializeSearchBoxTextView();
         initializeVoiceSearchButton();
+        initializeChromeHomePromo();
         initializeLayoutChangeListeners();
         setSearchProviderInfo(searchProviderHasLogo, searchProviderIsGoogle);
         mSearchProviderLogoView.showSearchProviderInitialView();
@@ -409,6 +414,25 @@
         TraceEvent.end(TAG + ".initializeVoiceSearchButton()");
     }
 
+    private void initializeChromeHomePromo() {
+        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_HOME_PROMO)) return;
+
+        NoUnderlineClickableSpan link = new NoUnderlineClickableSpan() {
+            @Override
+            public void onClick(View view) {
+                new ChromeHomePromoDialog(mActivity).show();
+            }
+        };
+
+        TextView textView = mNewTabPageLayout.findViewById(R.id.chrome_home_promo_text);
+        textView.setText(
+                SpanApplier.applySpans(getResources().getString(R.string.ntp_chrome_home_promo),
+                        new SpanApplier.SpanInfo("<link>", "</link>", link)));
+        textView.setMovementMethod(LinkMovementMethod.getInstance());
+        mNewTabPageLayout.findViewById(R.id.chrome_home_promo_container)
+                .setVisibility(View.VISIBLE);
+    }
+
     private void initializeLayoutChangeListeners() {
         TraceEvent.begin(TAG + ".initializeLayoutChangeListeners()");
         mNewTabPageLayout.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@@ -642,8 +666,13 @@
         for (int i = 0; i < childCount; i++) {
             View child = mNewTabPageLayout.getChildAt(i);
             if (child == mSiteSectionViewHolder.itemView) break;
+
             // Don't change the visibility of a ViewStub as that will automagically inflate it.
             if (child instanceof ViewStub) continue;
+
+            // Skip the Chrome Home promo.
+            if (child.getId() == R.id.chrome_home_promo_container) continue;
+
             if (child == mSearchProviderLogoView) {
                 child.setVisibility(logoVisibility);
             } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java
index c40fe3b..81d349d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java
@@ -418,9 +418,10 @@
         return suggestionIds;
     }
 
-    private void updatePlaceholderVisibility() {
-        if (!FeatureUtilities.isChromeHomeEnabled()) return;
+    private boolean updatePlaceholderVisibility() {
+        if (!FeatureUtilities.isChromeHomeEnabled()) return false;
         mPlaceholder.setVisible(isLoading() && !hasSuggestions());
+        return mPlaceholder.isVisible();
     }
 
     /**
@@ -575,7 +576,9 @@
 
         boolean isLoading = SnippetsBridge.isCategoryLoading(status);
         mMoreButton.updateState(isLoading ? ActionItem.State.LOADING : ActionItem.State.BUTTON);
-        updatePlaceholderVisibility();
+        if (updatePlaceholderVisibility()) {
+            mPlaceholder.trackVisibilityDuration();
+        }
     }
 
     /** Clears the suggestions and related data, resetting the state of the section. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticle.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticle.java
index 04989e4..7b5e748 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticle.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticle.java
@@ -28,9 +28,6 @@
     /** The canonical publisher name (e.g., New York Times). */
     public final String mPublisher;
 
-    /** The snippet preview text. */
-    public final String mPreviewText;
-
     /** The URL of this article. This may be an AMP url. */
     public final String mUrl;
 
@@ -89,13 +86,12 @@
      * Creates a SnippetArticleListItem object that will hold the data.
      */
     public SnippetArticle(int category, String idWithinCategory, String title, String publisher,
-            String previewText, String url, long publishTimestamp, float score, long fetchTimestamp,
+            String url, long publishTimestamp, float score, long fetchTimestamp,
             boolean isVideoSuggestion, @ColorInt Integer thumbnailDominantColor) {
         mCategory = category;
         mIdWithinCategory = idWithinCategory;
         mTitle = title;
         mPublisher = publisher;
-        mPreviewText = previewText;
         mUrl = url;
         mPublishTimestampMilliseconds = publishTimestamp;
         mScore = score;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java
index 144c5dbd..096ebc905 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java
@@ -5,7 +5,6 @@
 package org.chromium.chrome.browser.ntp.snippets;
 
 import android.support.annotation.LayoutRes;
-import android.text.TextUtils;
 
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
@@ -21,9 +20,7 @@
 import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
 import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.widget.displaystyle.DisplayStyleObserverAdapter;
-import org.chromium.chrome.browser.widget.displaystyle.HorizontalDisplayStyle;
 import org.chromium.chrome.browser.widget.displaystyle.UiConfig;
-import org.chromium.chrome.browser.widget.displaystyle.VerticalDisplayStyle;
 import org.chromium.ui.mojom.WindowOpenDisposition;
 
 /**
@@ -139,18 +136,14 @@
      * Updates the layout taking into account screen dimensions and the type of snippet displayed.
      */
     private void updateLayout() {
-        final int horizontalStyle = mUiConfig.getCurrentDisplayStyle().horizontal;
-        final int verticalStyle = mUiConfig.getCurrentDisplayStyle().vertical;
         final int layout = mCategoryInfo.getCardLayout();
 
         boolean showHeadline = shouldShowHeadline();
-        boolean showDescription = shouldShowDescription(horizontalStyle, verticalStyle, layout);
         boolean showThumbnail = shouldShowThumbnail(layout);
         boolean showThumbnailVideoOverlay = shouldShowThumbnailVideoOverlay(showThumbnail);
 
-        mSuggestionsBinder.updateFieldsVisibility(showHeadline, showDescription, showThumbnail,
-                showThumbnailVideoOverlay,
-                getHeaderMaxLines(horizontalStyle, verticalStyle, layout));
+        mSuggestionsBinder.updateFieldsVisibility(
+                showHeadline, showThumbnail, showThumbnailVideoOverlay);
     }
 
     /** If the title is empty (or contains only whitespace characters), we do not show it. */
@@ -158,21 +151,6 @@
         return !mArticle.mTitle.trim().isEmpty();
     }
 
-    private boolean shouldShowDescription(int horizontalStyle, int verticalStyle, int layout) {
-        // Minimal cards don't have a description.
-        if (layout == ContentSuggestionsCardLayout.MINIMAL_CARD) return false;
-
-        // When the screen is too small (narrow or flat) we don't show the description to have more
-        // space for the header.
-        if (horizontalStyle == HorizontalDisplayStyle.NARROW) return false;
-        if (verticalStyle == VerticalDisplayStyle.FLAT) return false;
-
-        // When article's description is empty, we do not want empty space.
-        if (mArticle != null && TextUtils.isEmpty(mArticle.mPreviewText)) return false;
-
-        return ChromeFeatureList.isEnabled(ChromeFeatureList.CONTENT_SUGGESTIONS_SHOW_SUMMARY);
-    }
-
     private boolean shouldShowThumbnail(int layout) {
         // Minimal cards don't have a thumbnail
         if (layout == ContentSuggestionsCardLayout.MINIMAL_CARD) return false;
@@ -186,14 +164,6 @@
         return ChromeFeatureList.isEnabled(ChromeFeatureList.CONTENT_SUGGESTIONS_VIDEO_OVERLAY);
     }
 
-    /**
-     * If no summary (no description) is shown, allow more lines for the header (title).
-     * @return The maximum number of header text lines.
-     */
-    private int getHeaderMaxLines(int horizontalStyle, int verticalStyle, int layout) {
-        return shouldShowDescription(horizontalStyle, verticalStyle, layout) ? 2 : 3;
-    }
-
     /** Updates the visibility of the card's offline badge by checking the bound article's info. */
     private void refreshOfflineBadgeVisibility() {
         boolean visible = mArticle.getOfflinePageOfflineId() != null || mArticle.isAssetDownload();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java
index fdb15de..b104a42 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java
@@ -20,8 +20,6 @@
  * Provides access to the snippets to display on the NTP using the C++ ContentSuggestionsService.
  */
 public class SnippetsBridge implements SuggestionsSource {
-    private static final String TAG = "SnippetsBridge";
-
     private long mNativeSnippetsBridge;
     private final ObserverList<Observer> mObserverList = new ObserverList<>();
 
@@ -202,14 +200,13 @@
 
     @CalledByNative
     private static SnippetArticle addSuggestion(List<SnippetArticle> suggestions, int category,
-            String id, String title, String publisher, String previewText, String url,
-            long timestamp, float score, long fetchTime, boolean isVideoSuggestion,
-            int thumbnailDominantColor) {
+            String id, String title, String publisher, String url, long timestamp, float score,
+            long fetchTime, boolean isVideoSuggestion, int thumbnailDominantColor) {
         int position = suggestions.size();
         // thumbnailDominantColor equal to 0 encodes absence of the value. 0 is not a valid color,
         // because the passed color cannot be fully transparent.
-        suggestions.add(new SnippetArticle(category, id, title, publisher, previewText, url,
-                timestamp, score, fetchTime, isVideoSuggestion,
+        suggestions.add(new SnippetArticle(category, id, title, publisher, url, timestamp, score,
+                fetchTime, isVideoSuggestion,
                 thumbnailDominantColor == 0 ? null : thumbnailDominantColor));
         return suggestions.get(position);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java
index 1e83735..274617c9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java
@@ -5,8 +5,12 @@
 package org.chromium.chrome.browser.partnerbookmarks;
 
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.os.AsyncTask;
-import android.util.Log;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.base.Log;
+import org.chromium.base.metrics.RecordHistogram;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -17,7 +21,9 @@
  * Reads bookmarks from the partner content provider (if any).
 */
 public class PartnerBookmarksReader {
-    private static final String TAG = "PartnerBookmarksReader";
+    private static final String TAG = "PartnerBMReader";
+
+    static final String LAST_EMPTY_READ_PREFS_NAME = "PartnerBookmarksReader.last_empty_read";
 
     private static boolean sInitialized;
     private static boolean sForceDisableEditing;
@@ -122,10 +128,25 @@
     private class ReadBookmarksTask extends AsyncTask<Void, Void, Void> {
         private final Object mRootSync = new Object();
 
+        private void handleZeroBookmark() {
+            SharedPreferences.Editor editor = ContextUtils.getAppSharedPreferences().edit();
+            editor.putLong(LAST_EMPTY_READ_PREFS_NAME, System.currentTimeMillis());
+            editor.apply();
+
+            Log.w(TAG,
+                    "Obtained zero partner bookmarks. "
+                            + "Will skip reading partner bookmarks for a while.");
+        }
+
         @Override
         protected Void doInBackground(Void... params) {
             BookmarkIterator bookmarkIterator = getAvailableBookmarks();
-            if (bookmarkIterator == null) return null;
+            RecordHistogram.recordBooleanHistogram(
+                    "PartnerBookmark.Null", bookmarkIterator == null);
+            if (bookmarkIterator == null) {
+                handleZeroBookmark();
+                return null;
+            }
 
             // Get a snapshot of the bookmarks.
             LinkedHashMap<Long, Bookmark> idMap = new LinkedHashMap<Long, Bookmark>();
@@ -157,6 +178,17 @@
                 urlSet.add(bookmark.mUrl);
             }
             bookmarkIterator.close();
+            int count = urlSet.size();
+            RecordHistogram.recordCount100Histogram("PartnerBookmark.Count", count);
+
+            if (count == 0) {
+                handleZeroBookmark();
+            } else {
+                SharedPreferences pref = ContextUtils.getAppSharedPreferences();
+                if (pref.contains(LAST_EMPTY_READ_PREFS_NAME)) {
+                    pref.edit().remove(LAST_EMPTY_READ_PREFS_NAME).apply();
+                }
+            }
 
             // Recreate the folder hierarchy and read it.
             recreateFolderHierarchy(idMap);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java
index b47ed2c..39ca8f1f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java
@@ -5,8 +5,15 @@
 package org.chromium.chrome.browser.partnerbookmarks;
 
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.content.pm.ApplicationInfo;
 
+import org.chromium.base.ContextUtils;
+import org.chromium.base.Log;
+import org.chromium.base.metrics.RecordHistogram;
+
+import java.util.concurrent.TimeUnit;
+
 /**
  * The Java counterpart for the C++ partner bookmarks shim.
  * Responsible for:
@@ -16,7 +23,10 @@
  * - reporting that all partner bookmarks were read to the C++ side.
  */
 public class PartnerBookmarksShim {
+    private static final String TAG = "PartnerBookmarksShim";
+
     private static boolean sIsReadingAttempted;
+    private static final long BAN_DURATION_MS = TimeUnit.DAYS.toMillis(7);
 
     /**
      * Checks if we need to fetch the Partner bookmarks and kicks the reading off. If reading was
@@ -27,10 +37,26 @@
         sIsReadingAttempted = true;
 
         PartnerBookmarksReader reader = new PartnerBookmarksReader(context);
-        if ((context.getApplicationInfo().flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+
+        boolean skip = shouldSkipReading();
+        RecordHistogram.recordBooleanHistogram("PartnerBookmark.Skipped", skip);
+        if (skip) {
+            Log.i(TAG, "Skip reading partner bookmarks since recent result was empty.");
+        }
+
+        if ((context.getApplicationInfo().flags & ApplicationInfo.FLAG_SYSTEM) == 0 || skip) {
             reader.onBookmarksRead();
             return;
         }
         reader.readBookmarks();
     }
+
+    private static boolean shouldSkipReading() {
+        SharedPreferences pref = ContextUtils.getAppSharedPreferences();
+        long last = pref.getLong(PartnerBookmarksReader.LAST_EMPTY_READ_PREFS_NAME, 0);
+        long elapsed = System.currentTimeMillis() - last;
+        // Without checking elapsed >= 0, we might get stuck at an "always skip mode" if
+        // |LAST_EMPTY_READ_PREFS_NAME| is a bogus future time.
+        return 0 <= elapsed && elapsed < BAN_DURATION_MS;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java
index 4cbcb27..4ccda15 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java
@@ -45,6 +45,7 @@
             "contextual_search_current_week_number";
     private static final String HERB_FLAVOR_KEY = "herb_flavor";
     private static final String CHROME_HOME_ENABLED_KEY = "chrome_home_enabled";
+    private static final String CHROME_HOME_USER_ENABLED_KEY = "chrome_home_user_enabled";
 
     private static final String CHROME_DEFAULT_BROWSER = "applink.chrome_default_browser";
 
@@ -414,6 +415,29 @@
         return mSharedPreferences.getBoolean(CHROME_HOME_ENABLED_KEY, false);
     }
 
+    /**
+     * Set whether or not Chrome Home is enabled by the user.
+     * @param isEnabled If Chrome Home is enabled by the user.
+     */
+    public void setChromeHomeUserEnabled(boolean isEnabled) {
+        writeBoolean(CHROME_HOME_USER_ENABLED_KEY, isEnabled);
+    }
+
+    /**
+     * Get whether or not Chrome Home is enabled by the user.
+     * @return True if Chrome Home is enabled by the user.
+     */
+    public boolean isChromeHomeUserEnabled() {
+        return mSharedPreferences.getBoolean(CHROME_HOME_USER_ENABLED_KEY, false);
+    }
+
+    /**
+     * @return Whether or not the user has set their Chrome Home preference.
+     */
+    public boolean isChromeHomeUserPreferenceSet() {
+        return mSharedPreferences.contains(CHROME_HOME_USER_ENABLED_KEY);
+    }
+
     /** Marks that the content suggestions surface has been shown. */
     public void setSuggestionsSurfaceShown() {
         writeBoolean(CONTENT_SUGGESTIONS_SHOWN_KEY, true);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java
index b8e29b50..d73d02c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java
@@ -389,7 +389,8 @@
         getActivity().getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
 
         changeHowPasswordIsDisplayed(R.drawable.ic_visibility_off,
-                InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD,
+                InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
+                        | InputType.TYPE_TEXT_FLAG_MULTI_LINE,
                 R.string.password_entry_editor_hide_stored_password);
         RecordHistogram.recordEnumeratedHistogram(
                 "PasswordManager.Android.PasswordCredentialEntry.Password",
@@ -398,7 +399,8 @@
 
     private void hidePassword() {
         changeHowPasswordIsDisplayed(R.drawable.ic_visibility,
-                InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD,
+                InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD
+                        | InputType.TYPE_TEXT_FLAG_MULTI_LINE,
                 R.string.password_entry_editor_view_stored_password);
         RecordHistogram.recordEnumeratedHistogram(
                 "PasswordManager.Android.PasswordCredentialEntry.Password", PASSWORD_ACTION_HIDDEN,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninActivity.java
index d602e14..4ac2cf7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninActivity.java
@@ -63,22 +63,6 @@
 
     /**
      * A convenience method to create a AccountSigninActivity passing the access point as an
-     * intent.
-     * @param accessPoint {@link AccessPoint} for starting signin flow. Used in metrics.
-     * @param isFromPersonalizedPromo Whether the signin activity is started from a personalized
-     *         promo.
-     */
-    public static void startAccountSigninActivity(
-            Context context, @AccessPoint int accessPoint, boolean isFromPersonalizedPromo) {
-        Intent intent = new Intent(context, AccountSigninActivity.class);
-        intent.putExtra(INTENT_SIGNIN_ACCESS_POINT, accessPoint);
-        intent.putExtra(INTENT_SIGNIN_FLOW_TYPE, SIGNIN_FLOW_DEFAULT);
-        intent.putExtra(INTENT_IS_FROM_PERSONALIZED_PROMO, isFromPersonalizedPromo);
-        context.startActivity(intent);
-    }
-
-    /**
-     * A convenience method to create a AccountSigninActivity passing the access point as an
      * intent. Checks if the sign in flow can be started before showing the activity.
      * @param accessPoint {@link AccessPoint} for starting signin flow. Used in metrics.
      * @return {@code true} if sign in has been allowed.
@@ -91,12 +75,28 @@
             return false;
         }
 
-        startAccountSigninActivity(context, accessPoint, false);
+        context.startActivity(createIntentForDefaultSigninFlow(context, accessPoint, false));
         return true;
     }
 
     /**
-     * Starts AccountSigninActivity from signin confirmation page.
+     * Creates an {@link Intent} which can be used to start the default signin flow.
+     * @param accessPoint {@link AccessPoint} for starting signin flow. Used in metrics.
+     * @param isFromPersonalizedPromo Whether the signin activity is started from a personalized
+     *         promo.
+     */
+    public static Intent createIntentForDefaultSigninFlow(
+            Context context, @AccessPoint int accessPoint, boolean isFromPersonalizedPromo) {
+        Intent intent = new Intent(context, AccountSigninActivity.class);
+        intent.putExtra(INTENT_SIGNIN_ACCESS_POINT, accessPoint);
+        intent.putExtra(INTENT_SIGNIN_FLOW_TYPE, SIGNIN_FLOW_DEFAULT);
+        intent.putExtra(INTENT_IS_FROM_PERSONALIZED_PROMO, isFromPersonalizedPromo);
+        return intent;
+    }
+
+    /**
+     * Creates an {@link Intent} which can be used to start the signin flow from the confirmation
+     * screen.
      * @param accessPoint {@link AccessPoint} for starting signin flow. Used in metrics.
      * @param selectAccount Account for which signin confirmation page should be shown.
      * @param isDefaultAccount Whether {@param selectedAccount} is the default account on
@@ -104,30 +104,32 @@
      * @param isFromPersonalizedPromo Whether the signin activity is started from a personalized
      *         promo.
      */
-    public static void startFromConfirmationPage(Context context, @AccessPoint int accessPoint,
-            String selectAccount, boolean isDefaultAccount, boolean isFromPersonalizedPromo) {
+    public static Intent createIntentForConfirmationOnlySigninFlow(Context context,
+            @AccessPoint int accessPoint, String selectAccount, boolean isDefaultAccount,
+            boolean isFromPersonalizedPromo) {
         Intent intent = new Intent(context, AccountSigninActivity.class);
         intent.putExtra(INTENT_SIGNIN_ACCESS_POINT, accessPoint);
         intent.putExtra(INTENT_SIGNIN_FLOW_TYPE, SIGNIN_FLOW_CONFIRMATION_ONLY);
         intent.putExtra(INTENT_ACCOUNT_NAME, selectAccount);
         intent.putExtra(INTENT_IS_DEFAULT_ACCOUNT, isDefaultAccount);
         intent.putExtra(INTENT_IS_FROM_PERSONALIZED_PROMO, isFromPersonalizedPromo);
-        context.startActivity(intent);
+        return intent;
     }
 
     /**
-     * Starts AccountSigninActivity from "Add account" page.
+     * Creates an {@link Intent} which can be used to start the signin flow from the "Add Account"
+     * page.
      * @param accessPoint {@link AccessPoint} for starting signin flow. Used in metrics.
      * @param isFromPersonalizedPromo Whether the signin activity is started from a personalized
      *         promo.
      */
-    public static void startFromAddAccountPage(
+    public static Intent createIntentForAddAccountSigninFlow(
             Context context, @AccessPoint int accessPoint, boolean isFromPersonalizedPromo) {
         Intent intent = new Intent(context, AccountSigninActivity.class);
         intent.putExtra(INTENT_SIGNIN_ACCESS_POINT, accessPoint);
         intent.putExtra(INTENT_SIGNIN_FLOW_TYPE, SIGNIN_FLOW_ADD_NEW_ACCOUNT);
         intent.putExtra(INTENT_IS_FROM_PERSONALIZED_PROMO, isFromPersonalizedPromo);
-        context.startActivity(intent);
+        return intent;
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninAndSyncView.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninAndSyncView.java
index d7884af..9483580 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninAndSyncView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninAndSyncView.java
@@ -195,26 +195,18 @@
                 ? R.string.bookmark_sign_in_promo_description
                 : R.string.recent_tabs_sign_in_promo_description;
 
-        ButtonState positiveButton = new ButtonPresent(
-                R.string.sign_in_button,
-                new OnClickListener() {
-                    @Override
-                    public void onClick(View view) {
-                        AccountSigninActivity.startAccountSigninActivity(
-                                getContext(), mAccessPoint, false);
-                    }
-                });
+        ButtonState positiveButton = new ButtonPresent(R.string.sign_in_button, view -> {
+            Context context = getContext();
+            context.startActivity(AccountSigninActivity.createIntentForDefaultSigninFlow(
+                    context, mAccessPoint, false));
+        });
 
         ButtonState negativeButton;
         if (mAccessPoint == SigninAccessPoint.RECENT_TABS) {
             negativeButton = new ButtonAbsent();
         } else {
-            negativeButton = new ButtonPresent(R.string.no_thanks, new OnClickListener() {
-                @Override
-                public void onClick(View view) {
-                    mListener.onViewDismissed();
-                }
-            });
+            negativeButton =
+                    new ButtonPresent(R.string.no_thanks, view -> mListener.onViewDismissed());
         }
 
         return new ViewState(descId, positiveButton, negativeButton);
@@ -226,18 +218,13 @@
 
         int descId = R.string.recent_tabs_sync_promo_enable_android_sync;
 
-        ButtonState positiveButton = new ButtonPresent(
-                R.string.open_settings_button,
-                new OnClickListener() {
-                    @Override
-                    public void onClick(View v) {
-                        // TODO(crbug.com/557784): Like AccountManagementFragment, this would also
-                        // benefit from going directly to an account.
-                        Intent intent = new Intent(Settings.ACTION_SYNC_SETTINGS);
-                        intent.putExtra(Settings.EXTRA_ACCOUNT_TYPES, new String[] {"com.google"});
-                        getContext().startActivity(intent);
-                    }
-                });
+        ButtonState positiveButton = new ButtonPresent(R.string.open_settings_button, view -> {
+            // TODO(crbug.com/557784): Like AccountManagementFragment, this would also
+            // benefit from going directly to an account.
+            Intent intent = new Intent(Settings.ACTION_SYNC_SETTINGS);
+            intent.putExtra(Settings.EXTRA_ACCOUNT_TYPES, new String[] {"com.google"});
+            getContext().startActivity(intent);
+        });
 
         return new ViewState(descId, positiveButton, new ButtonAbsent());
     }
@@ -247,15 +234,9 @@
                 ? R.string.bookmarks_sync_promo_enable_sync
                 : R.string.recent_tabs_sync_promo_enable_chrome_sync;
 
-        ButtonState positiveButton = new ButtonPresent(
-                R.string.enable_sync_button,
-                new OnClickListener() {
-                    @Override
-                    public void onClick(View v) {
-                        PreferencesLauncher.launchSettingsPage(getContext(),
-                                SyncCustomizationFragment.class.getName());
-                    }
-                });
+        ButtonState positiveButton = new ButtonPresent(R.string.enable_sync_button,
+                view -> PreferencesLauncher.launchSettingsPage(
+                        getContext(), SyncCustomizationFragment.class.getName()));
 
         return new ViewState(descId, positiveButton, new ButtonAbsent());
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
index dfd91a1..29d03a1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
@@ -14,7 +14,6 @@
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.Callback;
-import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
 import org.chromium.base.ObserverList;
 import org.chromium.base.Promise;
@@ -25,7 +24,6 @@
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.browser.externalauth.ExternalAuthUtils;
 import org.chromium.chrome.browser.externalauth.UserRecoverableErrorHandler;
-import org.chromium.chrome.browser.sync.SyncController;
 import org.chromium.chrome.browser.sync.SyncUserDataWiper;
 import org.chromium.components.signin.AccountManagerFacade;
 import org.chromium.components.signin.ChromeSigninController;
@@ -341,11 +339,6 @@
      */
     public void signIn(
             Account account, @Nullable Activity activity, @Nullable SignInCallback callback) {
-        // TODO(https://crbug.com/761476): remove this as soon as race condition in Sync is fixed.
-        // SyncController has a race condition inside so it needs to be initialized before actually
-        // signin in.
-        SyncController.get(ContextUtils.getApplicationContext());
-
         if (account == null) {
             Log.w(TAG, "Ignoring sign-in request due to null account.");
             if (callback != null) callback.onSignInAborted();
@@ -463,6 +456,7 @@
         // sync tries to start without being signed in natively and crashes.
         ChromeSigninController.get().setSignedInAccountName(mSignInState.account.name);
         AndroidSyncSettings.updateAccount(mContext, mSignInState.account);
+        AndroidSyncSettings.enableChromeSync(mContext);
 
         if (mSignInState.callback != null) {
             mSignInState.callback.onSignInComplete();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoController.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoController.java
index 42b0927..59e4c0e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoController.java
@@ -14,6 +14,7 @@
 import android.view.ViewGroup;
 
 import org.chromium.base.ContextUtils;
+import org.chromium.base.VisibleForTesting;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
@@ -43,6 +44,7 @@
             "signin_promo_impressions_count_bookmarks";
     private static final String SIGNIN_PROMO_IMPRESSIONS_COUNT_SETTINGS =
             "signin_promo_impressions_count_settings";
+
     private static final int MAX_IMPRESSIONS_BOOKMARKS = 20;
     private static final int MAX_IMPRESSIONS_SETTINGS = 5;
 
@@ -224,7 +226,8 @@
         view.getSigninButton().setText(R.string.sign_in_to_chrome);
         view.getSigninButton().setOnClickListener(promoView -> {
             recordSigninButtonUsed();
-            AccountSigninActivity.startFromAddAccountPage(context, mAccessPoint, true);
+            context.startActivity(AccountSigninActivity.createIntentForAddAccountSigninFlow(
+                    context, mAccessPoint, true));
         });
 
         view.getChooseAccountButton().setVisibility(View.GONE);
@@ -240,8 +243,8 @@
         view.getSigninButton().setText(signinButtonText);
         view.getSigninButton().setOnClickListener(promoView -> {
             recordSigninButtonUsed();
-            AccountSigninActivity.startFromConfirmationPage(
-                    context, mAccessPoint, mProfileData.getAccountName(), true, true);
+            context.startActivity(AccountSigninActivity.createIntentForConfirmationOnlySigninFlow(
+                    context, mAccessPoint, mProfileData.getAccountName(), true, true));
         });
 
         String chooseAccountButtonText = context.getString(
@@ -249,7 +252,8 @@
         view.getChooseAccountButton().setText(chooseAccountButtonText);
         view.getChooseAccountButton().setOnClickListener(promoView -> {
             recordSigninButtonUsed();
-            AccountSigninActivity.startAccountSigninActivity(context, mAccessPoint, true);
+            context.startActivity(AccountSigninActivity.createIntentForDefaultSigninFlow(
+                    context, mAccessPoint, true));
         });
         view.getChooseAccountButton().setVisibility(View.VISIBLE);
     }
@@ -290,4 +294,9 @@
             preferences.edit().putInt(mImpressionCountName, numImpressions).apply();
         }
     }
+
+    @VisibleForTesting
+    public static int getMaxImpressionsBookmarksForTests() {
+        return MAX_IMPRESSIONS_BOOKMARKS;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ssl/CaptivePortalHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ssl/CaptivePortalHelper.java
index ea514052..f1afe24 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ssl/CaptivePortalHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ssl/CaptivePortalHelper.java
@@ -17,17 +17,21 @@
 /** Helper class for captive portal related methods on Android. */
 @JNINamespace("chrome::android")
 public class CaptivePortalHelper {
-    public static void addCaptivePortalCertificateForTesting(String spkiHash) {
-        nativeAddCaptivePortalCertificateForTesting(spkiHash);
+    public static void setCaptivePortalCertificateForTesting(String spkiHash) {
+        nativeSetCaptivePortalCertificateForTesting(spkiHash);
+    }
+
+    public static void setOSReportsCaptivePortalForTesting(boolean osReportsCaptivePortal) {
+        nativeSetOSReportsCaptivePortalForTesting(osReportsCaptivePortal);
     }
 
     @CalledByNative
     private static String getCaptivePortalServerUrl() {
-        // Since Android N MR2 it is possible that a captive portal was detected with a different
-        // URL than getCaptivePortalServerUrl(). By default, Android uses the URL from
-        // getCaptivePortalServerUrl() first, but there are also two additional fallback HTTP URLs
-        // to probe if the first HTTP probe does not find anything. Using the default URL is
-        // acceptable as the return value is only used by the captive portal interstitial.
+        // Since Android N MR2 it is possible that a captive portal was detected with a
+        // different URL than getCaptivePortalServerUrl(). By default, Android uses the URL from
+        // getCaptivePortalServerUrl() first, but there are also two additional fallback HTTP
+        // URLs to probe if the first HTTP probe does not find anything. Using the default URL
+        // is acceptable as the return value is only used by the captive portal interstitial.
         try {
             Context context = ContextUtils.getApplicationContext();
             ConnectivityManager connectivityManager =
@@ -43,5 +47,8 @@
 
     private CaptivePortalHelper() {}
 
-    private static native void nativeAddCaptivePortalCertificateForTesting(String spkiHash);
+    private static native void nativeSetCaptivePortalCertificateForTesting(String spkiHash);
+
+    private static native void nativeSetOSReportsCaptivePortalForTesting(
+            boolean osReportsCaptivePortal);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ContentSuggestionPlaceholder.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ContentSuggestionPlaceholder.java
index a25b19c..2410bda 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ContentSuggestionPlaceholder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ContentSuggestionPlaceholder.java
@@ -13,6 +13,7 @@
 import org.chromium.chrome.browser.ntp.cards.NewTabPageViewHolder;
 import org.chromium.chrome.browser.ntp.cards.NodeVisitor;
 import org.chromium.chrome.browser.ntp.cards.OptionalLeaf;
+import org.chromium.chrome.browser.suggestions.SuggestionsMetrics.DurationTracker;
 import org.chromium.chrome.browser.widget.displaystyle.UiConfig;
 
 /**
@@ -22,8 +23,20 @@
     /** Color used to fill highlighted empty UI elements of the placeholder. */
     private static final @ColorRes int HIGHLIGHT_COLOR = R.color.black_alpha_20;
 
+    private final DurationTracker mVisibilityDurationTracker =
+            SuggestionsMetrics.getPlaceholderVisibilityReporter();
+
     public void setVisible(boolean visible) {
         setVisibilityInternal(visible);
+        if (!visible) mVisibilityDurationTracker.endTracking();
+    }
+
+    /**
+     * Start tracking how long we show the placeholder. When it is hidden, it will report that
+     * duration through UMA.
+     */
+    public void trackVisibilityDuration() {
+        mVisibilityDurationTracker.startTracking();
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ContextualSuggestionsCardViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ContextualSuggestionsCardViewHolder.java
index 7370f4d3..1b6cda0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ContextualSuggestionsCardViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ContextualSuggestionsCardViewHolder.java
@@ -16,7 +16,6 @@
 import org.chromium.chrome.browser.ntp.cards.NewTabPageViewHolder;
 import org.chromium.chrome.browser.ntp.snippets.SnippetArticle;
 import org.chromium.chrome.browser.util.FeatureUtilities;
-import org.chromium.chrome.browser.widget.displaystyle.DisplayStyleObserver;
 import org.chromium.chrome.browser.widget.displaystyle.DisplayStyleObserverAdapter;
 import org.chromium.chrome.browser.widget.displaystyle.HorizontalDisplayStyle;
 import org.chromium.chrome.browser.widget.displaystyle.UiConfig;
@@ -51,15 +50,9 @@
                 (ViewGroup.MarginLayoutParams) itemView.getLayoutParams(), startMargin);
 
         mDisplayStyleObserver =
-                new DisplayStyleObserverAdapter(itemView, uiConfig, new DisplayStyleObserver() {
-                    @Override
-                    public void onDisplayStyleChanged(UiConfig.DisplayStyle newDisplayStyle) {
-                        updateCardWidth(newDisplayStyle);
-                    }
-                });
+                new DisplayStyleObserverAdapter(itemView, uiConfig, this::updateCardWidth);
         mSuggestionsBinder.updateFieldsVisibility(/* showHeadline = */ true,
-                /* showDescription = */ false, /* showThumbnail = */ true,
-                /* showThumbnailVideoOverlay = */ false, /* headerMaxLines = */ 3);
+                /* showThumbnail = */ true, /* showThumbnailVideoOverlay = */ false);
     }
 
     public void onBindViewHolder(SnippetArticle suggestion) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/MostVisitedSites.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/MostVisitedSites.java
index 31837eba..dd038ea 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/MostVisitedSites.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/MostVisitedSites.java
@@ -88,17 +88,20 @@
      * its visual type.
      * @param index The index of the tile that was impressed (0-based).
      * @param type The visual type of the item as defined in {@link TileVisualType}.
+     * @param titleSource The {@link TileTitleSource} where the item's title originated from.
      * @param source The {@link TileSource} that generated this item.
      * @param url The URL of the tile.
      */
-    void recordTileImpression(
-            int index, @TileVisualType int type, @TileSource int source, String url);
+    void recordTileImpression(int index, @TileVisualType int type, @TileTitleSource int titleSource,
+            @TileSource int source, String url);
 
     /**
      * Records the opening of a Most Visited Item.
      * @param index The index of the item that was opened.
      * @param type The visual type of the item as defined in {@link TileVisualType}.
+     * @param titleSource The {@link TileTitleSource} where the item's title originated from.
      * @param source The {@link TileSource} that generated this item.
      */
-    void recordOpenedMostVisitedItem(int index, @TileVisualType int type, @TileSource int source);
+    void recordOpenedMostVisitedItem(int index, @TileVisualType int type,
+            @TileTitleSource int titleSource, @TileSource int source);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/MostVisitedSitesBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/MostVisitedSitesBridge.java
index f3a7ce3..06a8735 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/MostVisitedSitesBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/MostVisitedSitesBridge.java
@@ -97,14 +97,17 @@
     }
 
     @Override
-    public void recordTileImpression(int index, int type, int source, String url) {
-        nativeRecordTileImpression(mNativeMostVisitedSitesBridge, index, type, source, url);
+    public void recordTileImpression(int index, @TileVisualType int type,
+            @TileTitleSource int titleSource, @TileSource int source, String url) {
+        nativeRecordTileImpression(
+                mNativeMostVisitedSitesBridge, index, type, titleSource, source, url);
     }
 
     @Override
-    public void recordOpenedMostVisitedItem(
-            int index, @TileVisualType int type, @TileSource int source) {
-        nativeRecordOpenedMostVisitedItem(mNativeMostVisitedSitesBridge, index, type, source);
+    public void recordOpenedMostVisitedItem(int index, @TileVisualType int type,
+            @TileTitleSource int titleSource, @TileSource int source) {
+        nativeRecordOpenedMostVisitedItem(
+                mNativeMostVisitedSitesBridge, index, type, titleSource, source);
     }
 
     @Override
@@ -123,11 +126,11 @@
      * {@link SiteSuggestion}s.
      */
     public static List<SiteSuggestion> buildSiteSuggestions(String[] titles, String[] urls,
-            int[] sections, String[] whitelistIconPaths, int[] sources) {
+            int[] sections, String[] whitelistIconPaths, int[] titleSources, int[] sources) {
         List<SiteSuggestion> siteSuggestions = new ArrayList<>(titles.length);
         for (int i = 0; i < titles.length; ++i) {
-            siteSuggestions.add(new SiteSuggestion(
-                    titles[i], urls[i], whitelistIconPaths[i], sources[i], sections[i]));
+            siteSuggestions.add(new SiteSuggestion(titles[i], urls[i], whitelistIconPaths[i],
+                    titleSources[i], sources[i], sections[i]));
         }
         return siteSuggestions;
     }
@@ -146,14 +149,14 @@
      */
     @CalledByNative
     private void onURLsAvailable(String[] titles, String[] urls, int[] sections,
-            String[] whitelistIconPaths, int[] sources) {
+            String[] whitelistIconPaths, int[] titleSources, int[] sources) {
         // Don't notify observer if we've already been destroyed.
         if (mNativeMostVisitedSitesBridge == 0) return;
 
         List<SiteSuggestion> suggestions = new ArrayList<>();
 
-        suggestions.addAll(
-                buildSiteSuggestions(titles, urls, sections, whitelistIconPaths, sources));
+        suggestions.addAll(buildSiteSuggestions(
+                titles, urls, sections, whitelistIconPaths, titleSources, sources));
 
         mWrappedObserver.onSiteSuggestionsAvailable(suggestions);
     }
@@ -190,8 +193,8 @@
             long nativeMostVisitedSitesBridge, String url, boolean addUrl);
     private native void nativeRecordPageImpression(
             long nativeMostVisitedSitesBridge, int tilesCount);
-    private native void nativeRecordTileImpression(
-            long nativeMostVisitedSitesBridge, int index, int type, int source, String url);
-    private native void nativeRecordOpenedMostVisitedItem(
-            long nativeMostVisitedSitesBridge, int index, int tileType, int source);
+    private native void nativeRecordTileImpression(long nativeMostVisitedSitesBridge, int index,
+            int type, int titleSource, int source, String url);
+    private native void nativeRecordOpenedMostVisitedItem(long nativeMostVisitedSitesBridge,
+            int index, int tileType, int titleSource, int source);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteSuggestion.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteSuggestion.java
index 7df4bd4..1fde3c17 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteSuggestion.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteSuggestion.java
@@ -17,6 +17,10 @@
     /** The path to the icon image file for whitelisted tile, empty string otherwise. */
     public final String whitelistIconPath;
 
+    /** The generated tile's title originated from this {@code TileTitleSource}. */
+    @TileTitleSource
+    public final int titleSource;
+
     /** the {@code TileSource} that generated the tile. */
     @TileSource
     public final int source;
@@ -25,12 +29,13 @@
     @TileSectionType
     public final int sectionType;
 
-    public SiteSuggestion(
-            String title, String url, String whitelistIconPath, int source, int sectionType) {
+    public SiteSuggestion(String title, String url, String whitelistIconPath, int titleSource,
+            int source, int sectionType) {
         this.title = title;
         this.url = url;
         this.whitelistIconPath = whitelistIconPath;
         this.source = source;
+        this.titleSource = titleSource;
         this.sectionType = sectionType;
     }
 
@@ -42,6 +47,8 @@
         SiteSuggestion that = (SiteSuggestion) o;
 
         if (source != that.source) return false;
+        if (titleSource != that.titleSource) return false;
+        if (sectionType != that.sectionType) return false;
         if (!title.equals(that.title)) return false;
         if (!url.equals(that.url)) return false;
         return whitelistIconPath.equals(that.whitelistIconPath);
@@ -53,6 +60,8 @@
         result = 31 * result + url.hashCode();
         result = 31 * result + whitelistIconPath.hashCode();
         result = 31 * result + source;
+        result = 31 * result + sectionType;
+        result = 31 * result + titleSource;
         return result;
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java
index d2883a1..d2f7f8f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java
@@ -46,6 +46,7 @@
 public class SuggestionsBinder {
     private static final String ARTICLE_AGE_FORMAT_STRING = " - %s";
     private static final int FADE_IN_ANIMATION_TIME_MS = 300;
+    private static final int MAX_HEADER_LINES = 3;
 
     private final ImageFetcher mImageFetcher;
     private final SuggestionsUiDelegate mUiDelegate;
@@ -54,7 +55,6 @@
     private final LinearLayout mTextLayout;
     private final TextView mHeadlineTextView;
     private final TextView mPublisherTextView;
-    private final TextView mSnippetTextView;
     private final TextView mAgeTextView;
     private final TintedImageView mThumbnailView;
     // TODO(dgn): Modern suggestions currently do not support the video overlay at all.
@@ -81,7 +81,6 @@
 
         mHeadlineTextView = mCardContainerView.findViewById(R.id.article_headline);
         mPublisherTextView = mCardContainerView.findViewById(R.id.article_publisher);
-        mSnippetTextView = mCardContainerView.findViewById(R.id.article_snippet);
         mAgeTextView = mCardContainerView.findViewById(R.id.article_age);
         mThumbnailVideoOverlay =
                 mCardContainerView.findViewById(R.id.article_thumbnail_video_overlay);
@@ -98,7 +97,6 @@
         mSuggestion = suggestion;
 
         mHeadlineTextView.setText(suggestion.mTitle);
-        mSnippetTextView.setText(suggestion.mPreviewText);
         mPublisherTextView.setText(getPublisherString(suggestion));
         mAgeTextView.setText(getArticleAge(suggestion));
 
@@ -106,11 +104,10 @@
         setThumbnail();
     }
 
-    public void updateFieldsVisibility(boolean showHeadline, boolean showDescription,
-            boolean showThumbnail, boolean showThumbnailVideoOverlay, int headerMaxLines) {
+    public void updateFieldsVisibility(
+            boolean showHeadline, boolean showThumbnail, boolean showThumbnailVideoOverlay) {
         mHeadlineTextView.setVisibility(showHeadline ? View.VISIBLE : View.GONE);
-        mHeadlineTextView.setMaxLines(headerMaxLines);
-        mSnippetTextView.setVisibility(showDescription ? View.VISIBLE : View.GONE);
+        mHeadlineTextView.setMaxLines(MAX_HEADER_LINES);
         mThumbnailView.setVisibility(showThumbnail ? View.VISIBLE : View.GONE);
         if (mThumbnailVideoOverlay != null) {
             mThumbnailVideoOverlay.setVisibility(
@@ -120,14 +117,11 @@
         ViewGroup.MarginLayoutParams publisherBarParams =
                 (ViewGroup.MarginLayoutParams) mPublisherBar.getLayoutParams();
 
-        if (showDescription) {
-            publisherBarParams.topMargin = mPublisherBar.getResources().getDimensionPixelSize(
-                    R.dimen.snippets_publisher_margin_top_with_article_snippet);
-        } else if (showHeadline) {
+        if (showHeadline) {
             // When we show a headline and not a description, we reduce the top margin of the
             // publisher bar.
             publisherBarParams.topMargin = mPublisherBar.getResources().getDimensionPixelSize(
-                    R.dimen.snippets_publisher_margin_top_without_article_snippet);
+                    R.dimen.snippets_publisher_margin_top);
         } else {
             // When there is no headline and no description, we remove the top margin of the
             // publisher bar.
@@ -154,18 +148,14 @@
         int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
         int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
         mPublisherTextView.measure(widthSpec, heightSpec);
-        final int publisherFaviconSizePx = mPublisherTextView.getMeasuredHeight();
+        int publisherFaviconSizePx = mPublisherTextView.getMeasuredHeight();
 
         // Set the favicon of the publisher.
         // We start initialising with the default favicon to reserve the space and prevent the text
         // from moving later.
         setDefaultFaviconOnView(publisherFaviconSizePx);
-        Callback<Bitmap> faviconCallback = new Callback<Bitmap>() {
-            @Override
-            public void onResult(Bitmap bitmap) {
-                setFaviconOnView(bitmap, publisherFaviconSizePx);
-            }
-        };
+        Callback<Bitmap> faviconCallback =
+                bitmap -> setFaviconOnView(bitmap, publisherFaviconSizePx);
 
         mImageFetcher.makeFaviconRequest(mSuggestion, publisherFaviconSizePx, faviconCallback);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsMetrics.java
index 7b2c98f..110730dad 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsMetrics.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsMetrics.java
@@ -90,15 +90,12 @@
     public static void recordVisit(Tab tab, SnippetArticle suggestion) {
         @CategoryInt
         final int category = suggestion.mCategory;
-        NavigationRecorder.record(tab, new Callback<NavigationRecorder.VisitData>() {
-            @Override
-            public void onResult(NavigationRecorder.VisitData visit) {
-                if (NewTabPage.isNTPUrl(visit.endUrl)) {
-                    RecordUserAction.record("MobileNTP.Snippets.VisitEndBackInNTP");
-                }
-                RecordUserAction.record("MobileNTP.Snippets.VisitEnd");
-                SuggestionsEventReporterBridge.onSuggestionTargetVisited(category, visit.duration);
+        NavigationRecorder.record(tab, visit -> {
+            if (NewTabPage.isNTPUrl(visit.endUrl)) {
+                RecordUserAction.record("MobileNTP.Snippets.VisitEndBackInNTP");
             }
+            RecordUserAction.record("MobileNTP.Snippets.VisitEnd");
+            SuggestionsEventReporterBridge.onSuggestionTargetVisited(category, visit.duration);
         });
     }
 
@@ -136,6 +133,18 @@
     }
 
     /**
+     * @return A {@link DurationTracker} to notify to report how long the placeholder is visible
+     * for.
+     */
+    public static DurationTracker getPlaceholderVisibilityReporter() {
+        return new DurationTracker((duration) -> {
+            RecordHistogram.recordTimesHistogram(
+                    "ContentSuggestions.FetchPendingPlaceholder.VisibleDuration", duration,
+                    TimeUnit.MILLISECONDS);
+        });
+    }
+
+    /**
      * Measures the amount of time it takes for date formatting in order to track StrictMode
      * violations.
      * See https://crbug.com/639877
@@ -165,4 +174,33 @@
             mFired = false;
         }
     }
+
+    /**
+     * Utility class to track the duration of an event. Call {@link #startTracking()} and
+     * {@link #endTracking()} to notify about the key moments. These methods are no-ops when called
+     * while tracking is not in the expected state.
+     */
+    public static class DurationTracker {
+        private long mTrackingStartTimeMs;
+        private final Callback<Long> mTrackingCompleteCallback;
+
+        private DurationTracker(Callback<Long> trackingCompleteCallback) {
+            mTrackingCompleteCallback = trackingCompleteCallback;
+        }
+
+        public void startTracking() {
+            if (isTracking()) return;
+            mTrackingStartTimeMs = System.currentTimeMillis();
+        }
+
+        public void endTracking() {
+            if (!isTracking()) return;
+            mTrackingCompleteCallback.onResult(System.currentTimeMillis() - mTrackingStartTimeMs);
+            mTrackingStartTimeMs = 0;
+        }
+
+        private boolean isTracking() {
+            return mTrackingStartTimeMs > 0;
+        }
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/Tile.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/Tile.java
index 8cd4945..77372563 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/Tile.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/Tile.java
@@ -80,6 +80,15 @@
     }
 
     /**
+     * @return The source of this tile's title. Used for metrics tracking. Valid values are listed
+     * in {@code TileTitleSource}.
+     */
+    @TileTitleSource
+    public int getTitleSource() {
+        return mSiteData.titleSource;
+    }
+
+    /**
      * @return The source of this tile. Used for metrics tracking. Valid values are listed in
      * {@code TileSource}.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGroupDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGroupDelegateImpl.java
index 347cf9f..1f5ee19 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGroupDelegateImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGroupDelegateImpl.java
@@ -79,8 +79,8 @@
         if (mIsDestroyed) return;
 
         for (Tile tile : tiles) {
-            mMostVisitedSites.recordTileImpression(
-                    tile.getIndex(), tile.getType(), tile.getSource(), tile.getUrl());
+            mMostVisitedSites.recordTileImpression(tile.getIndex(), tile.getType(),
+                    tile.getTitleSource(), tile.getSource(), tile.getUrl());
         }
 
         mMostVisitedSites.recordPageImpression(tiles.size());
@@ -134,6 +134,6 @@
         NewTabPageUma.recordExplicitUserNavigation(
                 tile.getUrl(), NewTabPageUma.RAPPOR_ACTION_VISITED_SUGGESTED_TILE);
         mMostVisitedSites.recordOpenedMostVisitedItem(
-                tile.getIndex(), tile.getType(), tile.getSource());
+                tile.getIndex(), tile.getType(), tile.getTitleSource(), tile.getSource());
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarPhone.java
index 94a00ec0..ba79120 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarPhone.java
@@ -334,7 +334,7 @@
 
     @Override
     public boolean isInTabSwitcherMode() {
-        return !mBottomSheet.isSheetOpen() && super.isInTabSwitcherMode();
+        return super.isInTabSwitcherMode() && (mBottomSheet == null || !mBottomSheet.isSheetOpen());
     }
 
     @Override
@@ -744,7 +744,7 @@
             mExpandButton.setTint(tint);
         }
 
-        if (mBottomSheet.isSheetOpen()) {
+        if (mBottomSheet != null && mBottomSheet.isSheetOpen()) {
             mShowMenuButtonWhenSheetOpen = mBottomSheet.isShowingNewTab();
             updateButtonsContainerVisibilityAndTranslation();
             updateMenuButtonClickableState();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
index 2e90c880..a2da490 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -497,39 +497,7 @@
                     return;
                 }
 
-                // TODO(shaktisahu): Find out if the download menu button is enabled (crbug/712438).
-                if (!(activity instanceof ChromeTabbedActivity) || DeviceFormFactor.isTablet()
-                        || activity.isInOverviewMode()
-                        || !DownloadUtils.isAllowedToDownloadPage(tab)) {
-                    return;
-                }
-
-                final Tracker tracker = TrackerFactory.getTrackerForProfile(tab.getProfile());
-
-                if (!tracker.shouldTriggerHelpUI(FeatureConstants.DOWNLOAD_PAGE_FEATURE)) return;
-
-                mTextBubble = new ViewAnchoredTextBubble(mToolbar.getContext(), getMenuButton(),
-                        R.string.iph_download_page_for_offline_usage_text,
-                        R.string.iph_download_page_for_offline_usage_accessibility_text);
-                mTextBubble.setDismissOnTouchInteraction(true);
-                mTextBubble.addOnDismissListener(new OnDismissListener() {
-                    @Override
-                    public void onDismiss() {
-                        mHandler.postDelayed(new Runnable() {
-                            @Override
-                            public void run() {
-                                tracker.dismissed(FeatureConstants.DOWNLOAD_PAGE_FEATURE);
-                                activity.getAppMenuHandler().setMenuHighlight(null);
-                            }
-                        }, ViewHighlighter.IPH_MIN_DELAY_BETWEEN_TWO_HIGHLIGHTS);
-                    }
-                });
-                activity.getAppMenuHandler().setMenuHighlight(R.id.offline_page_id);
-                int yInsetPx = mToolbar.getContext().getResources().getDimensionPixelOffset(
-                        R.dimen.text_bubble_menu_anchor_y_inset);
-                mTextBubble.setInsetPx(0, FeatureUtilities.isChromeHomeEnabled() ? yInsetPx : 0, 0,
-                        FeatureUtilities.isChromeHomeEnabled() ? 0 : yInsetPx);
-                mTextBubble.show();
+                showDownloadPageTextBubble(tab, FeatureConstants.DOWNLOAD_PAGE_FEATURE);
             }
 
             private void handleIPHForErrorPageShown(Tab tab) {
@@ -616,6 +584,47 @@
     }
 
     /**
+     * Show the download page in-product-help bubble. Also used by download page screenshot IPH.
+     * @param tab The current tab.
+     * @param featureName The associated feature name.
+     */
+    public void showDownloadPageTextBubble(final Tab tab, String featureName) {
+        // TODO(shaktisahu): Find out if the download menu button is enabled (crbug/712438).
+        ChromeActivity activity = tab.getActivity();
+        if (!(activity instanceof ChromeTabbedActivity) || DeviceFormFactor.isTablet()
+                || activity.isInOverviewMode() || !DownloadUtils.isAllowedToDownloadPage(tab)) {
+            return;
+        }
+
+        final Tracker tracker = TrackerFactory.getTrackerForProfile(tab.getProfile());
+
+        if (!tracker.shouldTriggerHelpUI(featureName)) return;
+
+        mTextBubble = new ViewAnchoredTextBubble(mToolbar.getContext(), getMenuButton(),
+                R.string.iph_download_page_for_offline_usage_text,
+                R.string.iph_download_page_for_offline_usage_accessibility_text);
+        mTextBubble.setDismissOnTouchInteraction(true);
+        mTextBubble.addOnDismissListener(new OnDismissListener() {
+            @Override
+            public void onDismiss() {
+                mHandler.postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        tracker.dismissed(featureName);
+                        activity.getAppMenuHandler().setMenuHighlight(null);
+                    }
+                }, ViewHighlighter.IPH_MIN_DELAY_BETWEEN_TWO_HIGHLIGHTS);
+            }
+        });
+        activity.getAppMenuHandler().setMenuHighlight(R.id.offline_page_id);
+        int yInsetPx = mToolbar.getContext().getResources().getDimensionPixelOffset(
+                R.dimen.text_bubble_menu_anchor_y_inset);
+        mTextBubble.setInsetPx(0, FeatureUtilities.isChromeHomeEnabled() ? yInsetPx : 0, 0,
+                FeatureUtilities.isChromeHomeEnabled() ? 0 : yInsetPx);
+        mTextBubble.show();
+    }
+
+    /**
      * Initialize the manager with the components that had native initialization dependencies.
      * <p>
      * Calling this must occur after the native library have completely loaded.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
index b317c20..4969c14 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
@@ -256,6 +256,16 @@
     }
 
     /**
+     * Update the user's setting for Chrome Home. This is a user-facing setting different from the
+     * one in chrome://flags. This setting will take prescience over the one in flags.
+     * @param enabled Whether or not the feature should be enabled.
+     */
+    public static void switchChromeHomeUserSetting(boolean enabled) {
+        ChromePreferenceManager.getInstance().setChromeHomeUserEnabled(enabled);
+        sChromeHomeEnabled = enabled;
+    }
+
+    /**
      * @return Whether or not chrome should attach the toolbar to the bottom of the screen.
      */
     @CalledByNative
@@ -263,17 +273,25 @@
         if (DeviceFormFactor.isTablet()) return false;
 
         if (sChromeHomeEnabled == null) {
+            boolean isUserPreferenceSet = false;
+            ChromePreferenceManager prefManager = ChromePreferenceManager.getInstance();
+
             // Allow disk access for preferences while Chrome Home is in experimentation.
             StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
             try {
-                sChromeHomeEnabled = ChromePreferenceManager.getInstance().isChromeHomeEnabled();
+                if (ChromePreferenceManager.getInstance().isChromeHomeUserPreferenceSet()) {
+                    isUserPreferenceSet = true;
+                    sChromeHomeEnabled = prefManager.isChromeHomeUserEnabled();
+                } else {
+                    sChromeHomeEnabled = prefManager.isChromeHomeEnabled();
+                }
             } finally {
                 StrictMode.setThreadPolicy(oldPolicy);
             }
 
             // If the browser has been initialized by this point, check the experiment as well to
             // avoid the restart logic in cacheChromeHomeEnabled.
-            if (ChromeFeatureList.isInitialized()) {
+            if (ChromeFeatureList.isInitialized() && !isUserPreferenceSet) {
                 boolean chromeHomeExperimentEnabled =
                         ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_HOME);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkServiceClient.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkServiceClient.java
index 219b3050..55fb41c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkServiceClient.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkServiceClient.java
@@ -14,6 +14,7 @@
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
+import org.chromium.chrome.browser.metrics.WebApkUma;
 import org.chromium.chrome.browser.notifications.NotificationBuilderBase;
 import org.chromium.webapk.lib.client.WebApkServiceConnectionManager;
 import org.chromium.webapk.lib.runtime_library.IWebApkApi;
@@ -84,7 +85,11 @@
                 } else {
                     notificationBuilder.setSmallIcon(smallIconId);
                 }
-                api.notifyNotification(platformTag, platformID, notificationBuilder.build());
+                boolean notificationPermissionEnabled = api.notificationPermissionEnabled();
+                if (notificationPermissionEnabled) {
+                    api.notifyNotification(platformTag, platformID, notificationBuilder.build());
+                }
+                WebApkUma.recordNotificationPermissionStatus(notificationPermissionEnabled);
             }
         };
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/PulseDrawable.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/PulseDrawable.java
index a99c778..6ac36aa 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/PulseDrawable.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/PulseDrawable.java
@@ -17,12 +17,12 @@
 import android.support.annotation.ColorInt;
 import android.support.v4.view.animation.FastOutSlowInInterpolator;
 import android.support.v4.view.animation.PathInterpolatorCompat;
-import android.util.TypedValue;
 import android.view.animation.Interpolator;
 
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.ContextUtils;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.MathUtils;
 
 /**
@@ -88,8 +88,10 @@
      * @return A new {@link PulseDrawable} instance.
      */
     public static PulseDrawable createCircle(Context context) {
-        final int startingPulseRadiusPx = Math.round(TypedValue.applyDimension(
-                TypedValue.COMPLEX_UNIT_DIP, 16.f, context.getResources().getDisplayMetrics()));
+        final int startingPulseRadiusPx =
+                context.getResources().getDimensionPixelSize(FeatureUtilities.isChromeHomeEnabled()
+                                ? R.dimen.iph_pulse_chrome_home_baseline_radius
+                                : R.dimen.iph_pulse_baseline_radius);
 
         PulseDrawable.Painter painter = new PulseDrawable.Painter() {
             @Override
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 c6e8047d..daf6f750 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
@@ -1504,7 +1504,7 @@
      * @param state The state to get the height from.
      * @return The height of the sheet at the provided state.
      */
-    private float getSheetHeightForState(@SheetState int state) {
+    public float getSheetHeightForState(@SheetState int state) {
         return mStateRatios[state] * mContainerHeight;
     }
 
@@ -1573,7 +1573,7 @@
         return prevState;
     }
 
-    private boolean isSmallScreen() {
+    public boolean isSmallScreen() {
         // A small screen is defined by there being less than 160dp between half and full states.
         float fullToHalfDiff = (getFullRatio() - getHalfRatio()) * mContainerHeight;
         return fullToHalfDiff < mMinHalfFullDistance;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetContentController.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetContentController.java
index 23322179..5dfa513 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetContentController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetContentController.java
@@ -7,7 +7,6 @@
 import android.app.Activity;
 import android.content.Context;
 import android.content.res.ColorStateList;
-import android.content.res.Resources;
 import android.support.annotation.IntDef;
 import android.support.annotation.Nullable;
 import android.util.AttributeSet;
@@ -89,9 +88,10 @@
         public void onSheetOffsetChanged(float heightFraction) {
             // If the omnibox is not focused, allow the navigation bar to set its Y translation.
             if (!mOmniboxHasFocus) {
-                float offsetY =
-                        (mBottomSheet.getMinOffset() - mBottomSheet.getSheetOffsetFromBottom())
-                        + mDistanceBelowToolbarPx;
+                float offsetY = mBottomSheet.getSheetHeightForState(mBottomSheet.isSmallScreen()
+                                                ? BottomSheet.SHEET_STATE_FULL
+                                                : BottomSheet.SHEET_STATE_HALF)
+                        - mBottomSheet.getSheetOffsetFromBottom();
                 setTranslationY(Math.max(offsetY, 0f));
 
                 if (mBottomSheet.getTargetSheetState() != BottomSheet.SHEET_STATE_PEEK
@@ -119,7 +119,7 @@
 
             if (mHighlightItemId != null) {
                 mHighlightedView = mActivity.findViewById(mHighlightItemId);
-                ViewHighlighter.turnOnHighlight(mHighlightedView, false);
+                ViewHighlighter.turnOnHighlight(mHighlightedView, true);
             }
         }
 
@@ -172,7 +172,6 @@
     private BottomSheet mBottomSheet;
     private TabModelSelector mTabModelSelector;
     private SnackbarManager mSnackbarManager;
-    private float mDistanceBelowToolbarPx;
     private int mSelectedItemId;
     private ChromeActivity mActivity;
     private boolean mShouldOpenSheetOnNextContentChange;
@@ -209,12 +208,11 @@
     /**
      * Initializes the {@link BottomSheetContentController}.
      * @param bottomSheet The {@link BottomSheet} associated with this bottom nav.
-     * @param controlContainerHeight The height of the control container in px.
      * @param tabModelSelector The {@link TabModelSelector} for the application.
      * @param activity The {@link ChromeActivity} that owns the BottomSheet.
      */
-    public void init(BottomSheet bottomSheet, int controlContainerHeight,
-            TabModelSelector tabModelSelector, ChromeActivity activity) {
+    public void init(
+            BottomSheet bottomSheet, TabModelSelector tabModelSelector, ChromeActivity activity) {
         mBottomSheet = bottomSheet;
         mBottomSheet.addObserver(mBottomSheetObserver);
         mActivity = activity;
@@ -236,10 +234,6 @@
         };
         mTabModelSelector.addObserver(mTabModelSelectorObserver);
 
-        Resources res = getContext().getResources();
-        mDistanceBelowToolbarPx = controlContainerHeight
-                + res.getDimensionPixelOffset(R.dimen.bottom_nav_space_from_toolbar);
-
         setOnNavigationItemSelectedListener(this);
         hideMenuLabels();
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/ChromeHomePromoDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/ChromeHomePromoDialog.java
new file mode 100644
index 0000000..3fd21f88
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/ChromeHomePromoDialog.java
@@ -0,0 +1,111 @@
+// 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.app.Activity;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.CompoundButton;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import org.chromium.base.ApplicationStatus;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
+import org.chromium.chrome.browser.util.FeatureUtilities;
+import org.chromium.chrome.browser.widget.PromoDialog;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * A promotion for Chrome Home (the bottom sheet). This dialog can optionally restart the current
+ * activity to bring a user in or out of the feature.
+ */
+public class ChromeHomePromoDialog extends PromoDialog {
+    /** Whether or not the switch in the promo is enabled or disabled. */
+    private boolean mSwitchStateShouldEnable;
+
+    /**
+     * Default constructor.
+     * @param activity The {@link Activity} showing the promo.
+     */
+    public ChromeHomePromoDialog(Activity activity) {
+        super(activity);
+    }
+
+    @Override
+    protected DialogParams getDialogParams() {
+        PromoDialog.DialogParams params = new PromoDialog.DialogParams();
+        params.headerStringResource = R.string.chrome_home_promo_dialog_title;
+        params.subheaderStringResource = R.string.chrome_home_promo_dialog_message;
+        params.primaryButtonStringResource = R.string.ok;
+        params.drawableResource = R.drawable.chrome_home_promo_static;
+
+        return params;
+    }
+
+    @Override
+    public void onClick(View view) {
+        if (mSwitchStateShouldEnable != FeatureUtilities.isChromeHomeEnabled()) {
+            FeatureUtilities.switchChromeHomeUserSetting(mSwitchStateShouldEnable);
+            restartChromeInstances();
+        }
+
+        // There is only one button for this dialog, so dismiss on any click.
+        dismiss();
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        final String onString = getContext().getString(R.string.text_on);
+        final String offString = getContext().getString(R.string.text_off);
+
+        View toggleLayout = getLayoutInflater().inflate(R.layout.chrome_home_promo_toggle, null);
+
+        final TextView toggleText =
+                (TextView) toggleLayout.findViewById(R.id.chrome_home_promo_state_text);
+        Switch toggle = (Switch) toggleLayout.findViewById(R.id.chrome_home_toggle);
+        toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+            @Override
+            public void onCheckedChanged(CompoundButton compoundButton, boolean enabled) {
+                mSwitchStateShouldEnable = enabled;
+                toggleText.setText(mSwitchStateShouldEnable ? onString : offString);
+            }
+        });
+
+        toggle.setChecked(FeatureUtilities.isChromeHomeEnabled());
+        toggleText.setText(FeatureUtilities.isChromeHomeEnabled() ? onString : offString);
+
+        addControl(toggleLayout);
+    }
+
+    /**
+     * Restart any open Chrome instances, including the activity this promo is running in.
+     */
+    private void restartChromeInstances() {
+        // If there can be multiple activities, restart them before restarting this one.
+        if (FeatureUtilities.isTabModelMergingEnabled()) {
+            Class<?> otherWindowActivityClass =
+                    MultiWindowUtils.getInstance().getOpenInOtherWindowActivity(getOwnerActivity());
+
+            for (WeakReference<Activity> activityRef : ApplicationStatus.getRunningActivities()) {
+                Activity activity = activityRef.get();
+                if (activity == null) continue;
+                if (activity.getClass().equals(otherWindowActivityClass)) {
+                    activity.recreate();
+                    break;
+                }
+            }
+        }
+
+        getOwnerActivity().recreate();
+    }
+
+    @Override
+    public void onDismiss(DialogInterface dialogInterface) {}
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/textbubble/TextBubble.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/textbubble/TextBubble.java
index 96d06af..3f5cfae 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/textbubble/TextBubble.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/textbubble/TextBubble.java
@@ -188,9 +188,9 @@
     }
 
     /**
-     * Dismisses the active bubbles if user has pressed the back button.
+     * Dismisses all the currently showing bubbles.
      */
-    public static void onBackPressed() {
+    public static void dismissBubbles() {
         Set<TextBubble> bubbles = new HashSet<>(sBubbles);
         for (TextBubble bubble : bubbles) {
             bubble.dismiss();
@@ -284,6 +284,12 @@
 
         mRootView.getWindowVisibleDisplayFrame(mCachedWindowRect);
 
+        // In multi-window, the coordinates of root view will be different than (0,0).
+        // So we translate the coordinates of |mCachedWindowRect| w.r.t. its window.
+        int[] rootCoordinates = new int[2];
+        mRootView.getLocationOnScreen(rootCoordinates);
+        mCachedWindowRect.offset(-rootCoordinates[0], -rootCoordinates[1]);
+
         // TODO(dtrainor): This follows the previous logic.  But we should look into if we want to
         // use the root view dimensions instead of the window dimensions here so the bubble can't
         // bleed onto the decorations.
@@ -320,7 +326,10 @@
         }
 
         mX = mAnchorRect.left + (mAnchorRect.width() - mWidth) / 2 + mMarginPx;
-        mX = MathUtils.clamp(mX, mMarginPx, mRootView.getWidth() - mWidth - mMarginPx);
+
+        // In landscape mode, root view includes the decorations in some devices. So we guard the
+        // window dimensions against |mCachedWindowRect.right| instead.
+        mX = MathUtils.clamp(mX, mMarginPx, mCachedWindowRect.right - mWidth - mMarginPx);
         int arrowXOffset = mAnchorRect.centerX() - mX;
 
         // Force the anchor to be in a reasonable spot w.r.t. the bubble (not over the corners).
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/textbubble/ViewAnchoredTextBubble.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/textbubble/ViewAnchoredTextBubble.java
index f4d162a..23dcaf8b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/textbubble/ViewAnchoredTextBubble.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/textbubble/ViewAnchoredTextBubble.java
@@ -23,7 +23,7 @@
 public class ViewAnchoredTextBubble extends TextBubble
         implements PositionObserver.Listener, ViewTreeObserver.OnGlobalLayoutListener,
                    View.OnAttachStateChangeListener, OnPreDrawListener, OnDismissListener {
-    private final int[] mCachedScreenCoordinates = new int[2];
+    private final int[] mCachedWindowCoordinates = new int[2];
     private final Rect mAnchorRect = new Rect();
     private final Rect mInsetRect = new Rect();
     private final View mAnchorView;
@@ -111,9 +111,9 @@
     }
 
     private void refreshAnchorBounds() {
-        mAnchorView.getLocationOnScreen(mCachedScreenCoordinates);
-        mAnchorRect.left = mCachedScreenCoordinates[0];
-        mAnchorRect.top = mCachedScreenCoordinates[1];
+        mAnchorView.getLocationInWindow(mCachedWindowCoordinates);
+        mAnchorRect.left = mCachedWindowCoordinates[0];
+        mAnchorRect.top = mCachedWindowCoordinates[1];
         mAnchorRect.right = mAnchorRect.left + mAnchorView.getWidth();
         mAnchorRect.bottom = mAnchorRect.top + mAnchorView.getHeight();
 
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index b6cc497..6829f0b 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -568,8 +568,11 @@
       <message name="IDS_NTP_SITES_EXPLORATION_CATEGORY_OTHER_TITLE" desc="In the Sites Explore UI, title of the Unknown category.">
         Other
       </message>
-      <message name="IDS_NETWORK_PREDICTIONS_TITLE" desc="Title for Prefetch page resources.">
-        Use a prediction service to load pages more quickly
+      <message name="IDS_NETWORK_PREDICTIONS_TITLE" desc="Title of a setting in Chrome settings. Followed by a body that describes what pages are downloaded. If setting is turned on, Chrome will download certain pages to the user’s phone automatically for offline reading. “Download” is a verb, imperative. ">
+        Automatically download pages
+      </message>
+      <message name="IDS_NETWORK_PREDICTIONS_SUMMARY" desc="Body text for the “Automatically download pages” setting in Chrome settings. Describes what happens if the setting is turned on. Load pages refers to how quickly website pages load. Offline reading refers to the ability to access the pages without a network connection.">
+        Load pages more quickly and save popular pages for offline reading
       </message>
       <message name="IDS_CONTEXTUAL_SEARCH_TITLE" desc="Name for the Contextual Search feature, which allows users to search for a term in a web page by tapping on it.">
         Touch to Search
@@ -2391,6 +2394,9 @@
       <message name="IDS_ACCESSIBILITY_NTP_OFFLINE_BADGE" desc="Content description for the badge that indicates offline availability of a most visited item or content suggestion on the new tab page.">
         Available offline
       </message>
+      <message name="IDS_NTP_CHROME_HOME_PROMO" desc="Text below the search box on the New Tab Page that encourages the user to try Chrome Home. Part of the text is a link to open the promo dialog.">
+        Be the first to <ph name="BEGIN_LINK">&lt;link&gt;</ph>try the new Chrome<ph name="END_LINK">&lt;/link&gt;</ph>
+      </message>
       <message name="IDS_NTP_LEARN_MORE_ABOUT_SUGGESTED_CONTENT" desc="Text in the footer of the New Tab Page. Part of the text is a link to a help center page where the user can learn more about suggested content.">
         <ph name="BEGIN_LINK">&lt;link&gt;</ph>Learn more<ph name="END_LINK">&lt;/link&gt;</ph> about suggested content
       </message>
@@ -3131,6 +3137,12 @@
       <message name="IDS_IPH_DOWNLOAD_HOME_ACCESSIBILITY_TEXT" desc="The in-product-help accessibility text to open download home after a restart.">
         Find your files and pages in Downloads from the More Options button
       </message>
+      <message name="IDS_IPH_DOWNLOAD_HOME_ACCESSIBILITY_TEXT_CHROME_HOME" desc="The in-product-help accessibility text to open download home after a restart in chrome home mode.">
+        Pull up the toolbar to find your files and pages in downloads
+      </message>
+      <message name="IDS_IPH_DOWNLOAD_HOME_ACCESSIBILITY_TEXT_CHROME_HOME_EXPAND" desc="The in-product-help accessibility text to open download home after a restart in chrome home mode with expand button enabled.">
+        Double tap the expand button to find your files and pages in downloads
+      </message>
       <message name="IDS_IPH_DATA_SAVER_PREVIEW_TEXT" desc="In-product help for when a data saver preview page and infobar are shown.">
           Chrome is using less data to show you this page
       </message>
@@ -3199,6 +3211,15 @@
       <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 Bookmarks, Downloads, 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. 'Bookmarks', 'Downloads', 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 bookmarks, downloads, and history?
       </message>
+      <message name="IDS_CHROME_HOME_PROMO_DIALOG_TITLE" desc="The title for the dialog promoting the Chrome Home feature.">
+        Try the new Chrome
+      </message>
+      <message name="IDS_CHROME_HOME_PROMO_DIALOG_MESSAGE" desc="The message for the dialog promoting the Chrome Home feature. The message emphasizes the fact that both appearance and functionality have been updated.">
+        One swipe access to your shortcuts and bookmarks with a fresh new look.
+      </message>
+      <message name="IDS_CHROME_HOME_PROMO_DIALOG_CHANGE_LATER" desc="The message beside the toggle that would enable or disable the Chrome Home feature. This string is used to indicate that the user may change the setting later.">
+        (You can change this later)
+      </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 f233773..3a6ed550 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -131,6 +131,11 @@
   "java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuItemDelegate.java",
   "java/src/org/chromium/chrome/browser/browseractions/BrowserActionsCustomContextMenuItem.java",
   "java/src/org/chromium/chrome/browser/browseractions/BrowserActionsService.java",
+  "java/src/org/chromium/chrome/browser/browserservices/BrowserSessionContentHandler.java",
+  "java/src/org/chromium/chrome/browser/browserservices/BrowserSessionContentUtils.java",
+  "java/src/org/chromium/chrome/browser/browserservices/BrowserSessionDataProvider.java",
+  "java/src/org/chromium/chrome/browser/browserservices/OriginVerifier.java",
+  "java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java",
   "java/src/org/chromium/chrome/browser/browsing_data/UrlFilters.java",
   "java/src/org/chromium/chrome/browser/childaccounts/ChildAccountFeedbackReporter.java",
   "java/src/org/chromium/chrome/browser/childaccounts/ChildAccountService.java",
@@ -286,7 +291,6 @@
   "java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java",
   "java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java",
   "java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java",
-  "java/src/org/chromium/chrome/browser/customtabs/CustomTabContentHandler.java",
   "java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java",
   "java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java",
   "java/src/org/chromium/chrome/browser/customtabs/CustomTabLayoutManager.java",
@@ -295,8 +299,6 @@
   "java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionService.java",
   "java/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicy.java",
   "java/src/org/chromium/chrome/browser/customtabs/LoadingPredictor.java",
-  "java/src/org/chromium/chrome/browser/customtabs/OriginVerifier.java",
-  "java/src/org/chromium/chrome/browser/customtabs/PostMessageHandler.java",
   "java/src/org/chromium/chrome/browser/customtabs/RequestThrottler.java",
   "java/src/org/chromium/chrome/browser/customtabs/SeparateTaskCustomTabActivity.java",
   "java/src/org/chromium/chrome/browser/customtabs/SeparateTaskCustomTabActivity0.java",
@@ -1311,6 +1313,7 @@
   "java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetMetrics.java",
   "java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetNewTabController.java",
   "java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetObserver.java",
+  "java/src/org/chromium/chrome/browser/widget/bottomsheet/ChromeHomePromoDialog.java",
   "java/src/org/chromium/chrome/browser/widget/bottomsheet/EmptyBottomSheetObserver.java",
   "java/src/org/chromium/chrome/browser/widget/bottomsheet/PlaceholderSheetContent.java",
   "java/src/org/chromium/chrome/browser/widget/displaystyle/MarginResizer.java",
@@ -1410,8 +1413,10 @@
   "javatests/src/org/chromium/chrome/browser/banners/InstallerDelegateTest.java",
   "javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java",
   "javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkModelTest.java",
+  "javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkPersonalizedSigninPromoTest.java",
   "javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java",
   "javatests/src/org/chromium/chrome/browser/browseractions/BrowserActionActivityTest.java",
+  "javatests/src/org/chromium/chrome/browser/browserservices/OriginVerifierTest.java",
   "javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java",
   "javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBaseTest.java",
   "javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelEventFilterTest.java",
@@ -1443,7 +1448,6 @@
   "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java",
   "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistenceIntegrationTest.java",
   "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicyTest.java",
-  "javatests/src/org/chromium/chrome/browser/customtabs/OriginVerifierTest.java",
   "javatests/src/org/chromium/chrome/browser/customtabs/RequestThrottlerTest.java",
   "javatests/src/org/chromium/chrome/browser/document/LauncherActivityTest.java",
   "javatests/src/org/chromium/chrome/browser/dom_distiller/DistillabilityServiceTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkPersonalizedSigninPromoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkPersonalizedSigninPromoTest.java
new file mode 100644
index 0000000..95bb310d
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkPersonalizedSigninPromoTest.java
@@ -0,0 +1,194 @@
+// 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.bookmarks;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.Espresso.pressBack;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import android.accounts.Account;
+import android.content.Intent;
+import android.support.test.filters.LargeTest;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.intent.IntentCallback;
+import android.support.test.runner.intent.IntentMonitorRegistry;
+
+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.R;
+import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.ChromeSwitches;
+import org.chromium.chrome.browser.signin.AccountSigninActivity;
+import org.chromium.chrome.browser.signin.SigninAccessPoint;
+import org.chromium.chrome.browser.signin.SigninPromoController;
+import org.chromium.chrome.test.ChromeActivityTestRule;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.components.signin.AccountManagerFacade;
+import org.chromium.components.signin.ProfileDataSource;
+import org.chromium.components.signin.test.util.AccountHolder;
+import org.chromium.components.signin.test.util.FakeAccountManagerDelegate;
+
+import java.io.Closeable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tests for the personalized signin promo on the Bookmarks page.
+ */
+@RunWith(ChromeJUnit4ClassRunner.class)
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
+        "enable-features=AndroidSigninPromos"})
+public class BookmarkPersonalizedSigninPromoTest {
+    private static final String TEST_ACCOUNT_NAME = "test@gmail.com";
+    private static final String TEST_FULL_NAME = "Test Account";
+
+    @Rule
+    public final ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
+            new ChromeActivityTestRule<>(ChromeActivity.class);
+
+    private final FakeAccountManagerDelegate mAccountManagerDelegate =
+            new FakeAccountManagerDelegate(FakeAccountManagerDelegate.ENABLE_PROFILE_DATA_SOURCE);
+
+    @Before
+    public void setUp() throws Exception {
+        mActivityTestRule.startMainActivityFromLauncher();
+        AccountManagerFacade.overrideAccountManagerFacadeForTests(mAccountManagerDelegate);
+    }
+
+    @Test
+    @MediumTest
+    public void testManualDismissPromo() throws Exception {
+        openBookmarkManager();
+        onView(withId(R.id.signin_promo_view_container)).check(matches(isDisplayed()));
+        onView(withId(R.id.signin_promo_close_button)).perform(click());
+        onView(withId(R.id.signin_promo_view_container)).check(doesNotExist());
+    }
+
+    @Test
+    @LargeTest
+    public void testAutoDismissPromo() throws Exception {
+        int impressionCap = SigninPromoController.getMaxImpressionsBookmarksForTests();
+        for (int impression = 0; impression < impressionCap; impression++) {
+            openBookmarkManager();
+            onView(withId(R.id.signin_promo_view_container)).check(matches(isDisplayed()));
+            pressBack();
+        }
+        openBookmarkManager();
+        onView(withId(R.id.signin_promo_view_container)).check(doesNotExist());
+    }
+
+    @Test
+    @MediumTest
+    public void testSigninButtonDefaultAccount() throws Exception {
+        addTestAccount();
+        openBookmarkManager();
+        onView(withId(R.id.signin_promo_view_container)).check(matches(isDisplayed()));
+
+        final List<Intent> startedIntents;
+        try (IntentCallbackHelper helper = new IntentCallbackHelper()) {
+            onView(withId(R.id.signin_promo_signin_button)).perform(click());
+            startedIntents = helper.getStartedIntents();
+        }
+
+        assertEquals("Choosing to sign in with the default account should fire an intent!", 1,
+                startedIntents.size());
+        Intent expectedIntent = AccountSigninActivity.createIntentForConfirmationOnlySigninFlow(
+                mActivityTestRule.getActivity(), SigninAccessPoint.BOOKMARK_MANAGER,
+                TEST_ACCOUNT_NAME, true, true);
+        assertTrue(expectedIntent.filterEquals(startedIntents.get(0)));
+    }
+
+    @Test
+    @MediumTest
+    public void testSigninButtonNotDefaultAccount() throws Exception {
+        addTestAccount();
+        openBookmarkManager();
+        onView(withId(R.id.signin_promo_view_container)).check(matches(isDisplayed()));
+
+        final List<Intent> startedIntents;
+        try (IntentCallbackHelper helper = new IntentCallbackHelper()) {
+            onView(withId(R.id.signin_promo_choose_account_button)).perform(click());
+            startedIntents = helper.getStartedIntents();
+        }
+
+        assertEquals("Choosing to sign in with another account should fire an intent!", 1,
+                startedIntents.size());
+        Intent expectedIntent = AccountSigninActivity.createIntentForDefaultSigninFlow(
+                mActivityTestRule.getActivity(), SigninAccessPoint.BOOKMARK_MANAGER, true);
+        assertTrue(expectedIntent.filterEquals(startedIntents.get(0)));
+    }
+
+    @Test
+    @MediumTest
+    public void testSigninButtonNewAccount() throws Exception {
+        openBookmarkManager();
+        onView(withId(R.id.signin_promo_view_container)).check(matches(isDisplayed()));
+
+        final List<Intent> startedIntents;
+        try (IntentCallbackHelper helper = new IntentCallbackHelper()) {
+            onView(withId(R.id.signin_promo_signin_button)).perform(click());
+            startedIntents = helper.getStartedIntents();
+        }
+
+        assertFalse(
+                "Adding a new account should fire at least one intent!", startedIntents.isEmpty());
+        Intent expectedIntent = AccountSigninActivity.createIntentForAddAccountSigninFlow(
+                mActivityTestRule.getActivity(), SigninAccessPoint.BOOKMARK_MANAGER, true);
+        // Comparing only the first intent as AccountSigninActivity will fire an intent after
+        // starting the flow to add an account.
+        assertTrue(expectedIntent.filterEquals(startedIntents.get(0)));
+    }
+
+    private void openBookmarkManager() throws InterruptedException {
+        onView(withId(R.id.menu_button)).perform(click());
+        onView(withText("Bookmarks")).perform(click());
+    }
+
+    private void addTestAccount() {
+        Account account = AccountManagerFacade.createAccountFromName(TEST_ACCOUNT_NAME);
+        AccountHolder.Builder accountHolder = AccountHolder.builder(account).alwaysAccept(true);
+        mAccountManagerDelegate.addAccountHolderExplicitly(accountHolder.build());
+        ProfileDataSource.ProfileData profileData =
+                new ProfileDataSource.ProfileData(TEST_ACCOUNT_NAME, null, TEST_FULL_NAME, null);
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> mAccountManagerDelegate.setProfileData(TEST_ACCOUNT_NAME, profileData));
+    }
+
+    private static class IntentCallbackHelper implements IntentCallback, Closeable {
+        private final List<Intent> mStartedIntents = new ArrayList<>();
+
+        public IntentCallbackHelper() {
+            IntentMonitorRegistry.getInstance().addIntentCallback(this);
+        }
+
+        @Override
+        public void onIntentSent(Intent intent) {
+            mStartedIntents.add(intent);
+        }
+
+        @Override
+        public void close() {
+            IntentMonitorRegistry.getInstance().removeIntentCallback(this);
+        }
+
+        public List<Intent> getStartedIntents() {
+            return mStartedIntents;
+        }
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/OriginVerifierTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/OriginVerifierTest.java
new file mode 100644
index 0000000..57ab729
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/OriginVerifierTest.java
@@ -0,0 +1,117 @@
+// 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.
+
+package org.chromium.chrome.browser.browserservices;
+
+import android.net.Uri;
+import android.support.customtabs.CustomTabsService;
+import android.support.test.filters.SmallTest;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.BaseJUnit4ClassRunner;
+import org.chromium.chrome.browser.browserservices.OriginVerifier.OriginVerificationListener;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+/** Tests for OriginVerifier. */
+@RunWith(BaseJUnit4ClassRunner.class)
+public class OriginVerifierTest {
+    private static final long TIMEOUT_MS = 1000;
+    private static final byte[] BYTE_ARRAY = new byte[] {(byte) 0xaa, (byte) 0xbb, (byte) 0xcc,
+            (byte) 0x10, (byte) 0x20, (byte) 0x30, (byte) 0x01, (byte) 0x02};
+    private static final String STRING_ARRAY = "AA:BB:CC:10:20:30:01:02";
+
+    private static final String PACKAGE_NAME = "org.chromium.chrome";
+    private static final String SHA_256_FINGERPRINT =
+            "32:A2:FC:74:D7:31:10:58:59:E5:A8:5D:F1:6D:95:F1:02:D8:5B"
+            + ":22:09:9B:80:64:C5:D8:91:5C:61:DA:D1:E0";
+    private static final Uri TEST_HTTPS_ORIGIN_1 = Uri.parse("https://www.example.com");
+    private static final Uri TEST_HTTPS_ORIGIN_2 = Uri.parse("https://www.android.com");
+    private static final Uri TEST_HTTP_ORIGIN = Uri.parse("http://www.android.com");
+
+    private class TestOriginVerificationListener implements OriginVerificationListener {
+        @Override
+        public void onOriginVerified(String packageName, Uri origin, boolean verified) {
+            mLastPackageName = packageName;
+            mLastOrigin = origin;
+            mLastVerified = verified;
+            mVerificationResultSemaphore.release();
+        }
+    }
+
+    private Semaphore mVerificationResultSemaphore;
+    private OriginVerifier mUseAsOriginVerifier;
+    private OriginVerifier mHandleAllUrlsVerifier;
+    private volatile String mLastPackageName;
+    private volatile Uri mLastOrigin;
+    private volatile boolean mLastVerified;
+
+    @Before
+    public void setUp() throws Exception {
+        mHandleAllUrlsVerifier = new OriginVerifier(new TestOriginVerificationListener(),
+                PACKAGE_NAME, CustomTabsService.RELATION_HANDLE_ALL_URLS);
+        mUseAsOriginVerifier = new OriginVerifier(new TestOriginVerificationListener(),
+                PACKAGE_NAME, CustomTabsService.RELATION_USE_AS_ORIGIN);
+        mVerificationResultSemaphore = new Semaphore(0);
+    }
+
+    @Test
+    @SmallTest
+    public void testSHA256CertificateChecks() {
+        Assert.assertEquals(OriginVerifier.byteArrayToHexString(BYTE_ARRAY), STRING_ARRAY);
+        Assert.assertEquals(OriginVerifier.getCertificateSHA256FingerprintForPackage(PACKAGE_NAME),
+                SHA_256_FINGERPRINT);
+    }
+
+    @Test
+    @SmallTest
+    public void testOnlyHttpsAllowed() throws InterruptedException {
+        ThreadUtils.postOnUiThread(() -> mHandleAllUrlsVerifier.start(Uri.parse("LOL")));
+        Assert.assertTrue(
+                mVerificationResultSemaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        Assert.assertFalse(mLastVerified);
+        ThreadUtils.postOnUiThread(() -> mHandleAllUrlsVerifier.start(TEST_HTTP_ORIGIN));
+        Assert.assertTrue(
+                mVerificationResultSemaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        Assert.assertFalse(mLastVerified);
+    }
+
+    @Test
+    @SmallTest
+    public void testMultipleRelationships() throws Exception {
+        ThreadUtils.postOnUiThread(
+                ()
+                        -> OriginVerifier.addVerifiedOriginForPackage(PACKAGE_NAME,
+                                TEST_HTTPS_ORIGIN_1, CustomTabsService.RELATION_USE_AS_ORIGIN));
+        ThreadUtils.postOnUiThread(() -> mUseAsOriginVerifier.start(TEST_HTTPS_ORIGIN_1));
+        Assert.assertTrue(
+                mVerificationResultSemaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        Assert.assertTrue(mLastVerified);
+        Assert.assertTrue(ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() {
+            @Override
+            public Boolean call() throws Exception {
+                return OriginVerifier.isValidOrigin(PACKAGE_NAME, TEST_HTTPS_ORIGIN_1,
+                        CustomTabsService.RELATION_USE_AS_ORIGIN);
+            }
+        }));
+        Assert.assertFalse(ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() {
+            @Override
+            public Boolean call() throws Exception {
+                return OriginVerifier.isValidOrigin(PACKAGE_NAME, TEST_HTTPS_ORIGIN_1,
+                        CustomTabsService.RELATION_HANDLE_ALL_URLS);
+            }
+        }));
+        Assert.assertEquals(mLastPackageName, PACKAGE_NAME);
+        Assert.assertEquals(mLastOrigin,
+                OriginVerifier.getPostMessageOriginFromVerifiedOrigin(
+                        PACKAGE_NAME, TEST_HTTPS_ORIGIN_1));
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/ClientManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/ClientManagerTest.java
index ec18fb7d..c446240 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/ClientManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/ClientManagerTest.java
@@ -25,6 +25,8 @@
 import org.chromium.base.test.util.MetricsUtils;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.IntentHandler;
+import org.chromium.chrome.browser.browserservices.OriginVerifier;
+import org.chromium.chrome.browser.browserservices.PostMessageHandler;
 import org.chromium.content.browser.test.NativeLibraryTestRule;
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
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 1040eea..f7d6171 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
@@ -76,6 +76,8 @@
 import org.chromium.chrome.browser.TabsOpenedFromExternalAppTest;
 import org.chromium.chrome.browser.WarmupManager;
 import org.chromium.chrome.browser.appmenu.AppMenuHandler;
+import org.chromium.chrome.browser.browserservices.BrowserSessionContentUtils;
+import org.chromium.chrome.browser.browserservices.OriginVerifier;
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 import org.chromium.chrome.browser.firstrun.FirstRunStatus;
 import org.chromium.chrome.browser.history.BrowsingHistoryBridge;
@@ -964,7 +966,7 @@
                 ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Boolean>() {
                     @Override
                     public Boolean call() throws Exception {
-                        return CustomTabActivity.handleInActiveContentIfNeeded(
+                        return BrowserSessionContentUtils.handleInActiveContentIfNeeded(
                                 CustomTabsTestUtils.createMinimalCustomTabIntent(
                                         context, mTestPage2));
                     }
@@ -980,7 +982,7 @@
                     @Override
                     public Boolean call() throws Exception {
                         intent.setData(Uri.parse(mTestPage2));
-                        return CustomTabActivity.handleInActiveContentIfNeeded(intent);
+                        return BrowserSessionContentUtils.handleInActiveContentIfNeeded(intent);
                     }
                 }));
         final Tab tab = getActivity().getActivityTab();
@@ -1071,7 +1073,7 @@
                 ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Boolean>() {
                     @Override
                     public Boolean call() throws Exception {
-                        return CustomTabActivity.handleInActiveContentIfNeeded(intent);
+                        return BrowserSessionContentUtils.handleInActiveContentIfNeeded(intent);
                     }
                 }));
         try {
@@ -1123,7 +1125,7 @@
                 ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Boolean>() {
                     @Override
                     public Boolean call() throws Exception {
-                        return CustomTabActivity.handleInActiveContentIfNeeded(intent);
+                        return BrowserSessionContentUtils.handleInActiveContentIfNeeded(intent);
                     }
                 }));
         try {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/OriginVerifierTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/OriginVerifierTest.java
deleted file mode 100644
index a980b1f..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/OriginVerifierTest.java
+++ /dev/null
@@ -1,117 +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.
-
-package org.chromium.chrome.browser.customtabs;
-
-import android.net.Uri;
-import android.support.customtabs.CustomTabsService;
-import android.support.test.filters.SmallTest;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.test.BaseJUnit4ClassRunner;
-import org.chromium.chrome.browser.customtabs.OriginVerifier.OriginVerificationListener;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-/** Tests for OriginVerifier. */
-@RunWith(BaseJUnit4ClassRunner.class)
-public class OriginVerifierTest {
-    private static final long TIMEOUT_MS = 1000;
-    private static final byte[] BYTE_ARRAY = new byte[] {(byte) 0xaa, (byte) 0xbb, (byte) 0xcc,
-            (byte) 0x10, (byte) 0x20, (byte) 0x30, (byte) 0x01, (byte) 0x02};
-    private static final String STRING_ARRAY = "AA:BB:CC:10:20:30:01:02";
-
-    private static final String PACKAGE_NAME = "org.chromium.chrome";
-    private static final String SHA_256_FINGERPRINT =
-            "32:A2:FC:74:D7:31:10:58:59:E5:A8:5D:F1:6D:95:F1:02:D8:5B"
-            + ":22:09:9B:80:64:C5:D8:91:5C:61:DA:D1:E0";
-    private static final Uri TEST_HTTPS_ORIGIN_1 = Uri.parse("https://www.example.com");
-    private static final Uri TEST_HTTPS_ORIGIN_2 = Uri.parse("https://www.android.com");
-    private static final Uri TEST_HTTP_ORIGIN = Uri.parse("http://www.android.com");
-
-    private class TestOriginVerificationListener implements OriginVerificationListener {
-        @Override
-        public void onOriginVerified(String packageName, Uri origin, boolean verified) {
-            mLastPackageName = packageName;
-            mLastOrigin = origin;
-            mLastVerified = verified;
-            mVerificationResultSemaphore.release();
-        }
-    }
-
-    private Semaphore mVerificationResultSemaphore;
-    private OriginVerifier mUseAsOriginVerifier;
-    private OriginVerifier mHandleAllUrlsVerifier;
-    private volatile String mLastPackageName;
-    private volatile Uri mLastOrigin;
-    private volatile boolean mLastVerified;
-
-    @Before
-    public void setUp() throws Exception {
-        mHandleAllUrlsVerifier = new OriginVerifier(new TestOriginVerificationListener(),
-                PACKAGE_NAME, CustomTabsService.RELATION_HANDLE_ALL_URLS);
-        mUseAsOriginVerifier = new OriginVerifier(new TestOriginVerificationListener(),
-                PACKAGE_NAME, CustomTabsService.RELATION_USE_AS_ORIGIN);
-        mVerificationResultSemaphore = new Semaphore(0);
-    }
-
-    @Test
-    @SmallTest
-    public void testSHA256CertificateChecks() {
-        Assert.assertEquals(OriginVerifier.byteArrayToHexString(BYTE_ARRAY), STRING_ARRAY);
-        Assert.assertEquals(OriginVerifier.getCertificateSHA256FingerprintForPackage(PACKAGE_NAME),
-                SHA_256_FINGERPRINT);
-    }
-
-    @Test
-    @SmallTest
-    public void testOnlyHttpsAllowed() throws InterruptedException {
-        ThreadUtils.postOnUiThread(() -> mHandleAllUrlsVerifier.start(Uri.parse("LOL")));
-        Assert.assertTrue(
-                mVerificationResultSemaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        Assert.assertFalse(mLastVerified);
-        ThreadUtils.postOnUiThread(() -> mHandleAllUrlsVerifier.start(TEST_HTTP_ORIGIN));
-        Assert.assertTrue(
-                mVerificationResultSemaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        Assert.assertFalse(mLastVerified);
-    }
-
-    @Test
-    @SmallTest
-    public void testMultipleRelationships() throws Exception {
-        ThreadUtils.postOnUiThread(
-                ()
-                        -> OriginVerifier.addVerifiedOriginForPackage(PACKAGE_NAME,
-                                TEST_HTTPS_ORIGIN_1, CustomTabsService.RELATION_USE_AS_ORIGIN));
-        ThreadUtils.postOnUiThread(() -> mUseAsOriginVerifier.start(TEST_HTTPS_ORIGIN_1));
-        Assert.assertTrue(
-                mVerificationResultSemaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        Assert.assertTrue(mLastVerified);
-        Assert.assertTrue(ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() {
-            @Override
-            public Boolean call() throws Exception {
-                return OriginVerifier.isValidOrigin(PACKAGE_NAME, TEST_HTTPS_ORIGIN_1,
-                        CustomTabsService.RELATION_USE_AS_ORIGIN);
-            }
-        }));
-        Assert.assertFalse(ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() {
-            @Override
-            public Boolean call() throws Exception {
-                return OriginVerifier.isValidOrigin(PACKAGE_NAME, TEST_HTTPS_ORIGIN_1,
-                        CustomTabsService.RELATION_HANDLE_ALL_URLS);
-            }
-        }));
-        Assert.assertEquals(mLastPackageName, PACKAGE_NAME);
-        Assert.assertEquals(mLastOrigin,
-                OriginVerifier.getPostMessageOriginFromVerifiedOrigin(
-                        PACKAGE_NAME, TEST_HTTPS_ORIGIN_1));
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageLoadTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageLoadTest.java
index f1eb2f6..ed62724 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageLoadTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageLoadTest.java
@@ -91,7 +91,8 @@
         }
 
         @Override
-        public void recordTileImpression(int index, int type, int source, String url) {
+        public void recordTileImpression(
+                int index, int type, int nameSource, int source, String url) {
             assertNotEquals(TileVisualType.NONE, type);
         }
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
index fff8bb1..e3ade50 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
@@ -37,6 +37,7 @@
 import org.chromium.chrome.browser.suggestions.SiteSuggestion;
 import org.chromium.chrome.browser.suggestions.TileSectionType;
 import org.chromium.chrome.browser.suggestions.TileSource;
+import org.chromium.chrome.browser.suggestions.TileTitleSource;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.test.ChromeActivityTestRule;
@@ -105,9 +106,10 @@
 
         mSiteSuggestions = new ArrayList<>();
         mSiteSuggestions.add(new SiteSuggestion("TOP_SITES", mTestServer.getURL(TEST_PAGE) + "#1",
-                "", TileSource.TOP_SITES, TileSectionType.PERSONALIZED));
+                "", TileTitleSource.TITLE_TAG, TileSource.TOP_SITES, TileSectionType.PERSONALIZED));
         mSiteSuggestions.add(new SiteSuggestion("WHITELIST", mTestServer.getURL(TEST_PAGE) + "#2",
-                "/test.png", TileSource.WHITELIST, TileSectionType.PERSONALIZED));
+                "/test.png", TileTitleSource.UNKNOWN, TileSource.WHITELIST,
+                TileSectionType.PERSONALIZED));
 
         mMostVisitedSites = new FakeMostVisitedSites();
         mMostVisitedSites.setTileSuggestions(mSiteSuggestions.get(0), mSiteSuggestions.get(1));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NtpUiCaptureTestData.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NtpUiCaptureTestData.java
index 30d6c1a..f9c2bc9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NtpUiCaptureTestData.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NtpUiCaptureTestData.java
@@ -84,60 +84,52 @@
     private static final SnippetArticle[] FAKE_ARTICLE_SUGGESTIONS = new SnippetArticle[] {
             new SnippetArticle(KnownCategories.ARTICLES, "suggestion0",
                     "James Roderick to step down as conductor for Laville orchestra",
-                    NEWS_PUBLISHER, "summary is not used", "http://example.com",
-                    getTimestamp(2017, Calendar.JUNE, 1), 0.0f, 0L, false,
-                    /* thumbnailDominantColor = */ null),
+                    NEWS_PUBLISHER, "http://example.com", getTimestamp(2017, Calendar.JUNE, 1),
+                    0.0f, 0L, false, /* thumbnailDominantColor = */ null),
             new SnippetArticle(KnownCategories.ARTICLES, "suggestion1", "Boy raises orphaned goat",
-                    MEME_PUBLISHER, "summary is not used", "http://example.com",
-                    getTimestamp(2017, Calendar.JANUARY, 30), 0.0f, 0L, false,
-                    /* thumbnailDominantColor = */ null),
+                    MEME_PUBLISHER, "http://example.com", getTimestamp(2017, Calendar.JANUARY, 30),
+                    0.0f, 0L, false, /* thumbnailDominantColor = */ null),
             new SnippetArticle(KnownCategories.ARTICLES, "suggestion2", "Top gigs this week",
-                    ENTERTAINMENT_PUBLISHER, "summary is not used", "http://example.com",
+                    ENTERTAINMENT_PUBLISHER, "http://example.com",
                     getTimestamp(2017, Calendar.JANUARY, 30), 0.0f, 0L, false,
                     /* thumbnailDominantColor = */ null),
             new SnippetArticle(KnownCategories.ARTICLES, "suggestion3", "No, you can’t sit here",
-                    MEME_PUBLISHER, "summary is not used", "http://example.com",
-                    getTimestamp(2017, Calendar.JANUARY, 30), 0.0f, 0L, false,
-                    /* thumbnailDominantColor = */ null),
+                    MEME_PUBLISHER, "http://example.com", getTimestamp(2017, Calendar.JANUARY, 30),
+                    0.0f, 0L, false, /* thumbnailDominantColor = */ null),
             new SnippetArticle(KnownCategories.ARTICLES, "suggestion4",
                     "Army training more difficult than expected", FACTS_PUBLISHER,
-                    "summary is not used", "http://example.com",
-                    getTimestamp(2017, Calendar.JANUARY, 30), 0.0f, 0L, false,
+                    "http://example.com", getTimestamp(2017, Calendar.JANUARY, 30), 0.0f, 0L, false,
                     /* thumbnailDominantColor = */ null),
             new SnippetArticle(KnownCategories.ARTICLES, "suggestion5",
                     "Classical music attracts smaller audiences", NEWS_PUBLISHER,
-                    "summary is not used", "http://example.com",
-                    getTimestamp(2017, Calendar.JANUARY, 30), 0.0f, 0L, false,
+                    "http://example.com", getTimestamp(2017, Calendar.JANUARY, 30), 0.0f, 0L, false,
                     /* thumbnailDominantColor = */ null),
             new SnippetArticle(KnownCategories.ARTICLES, "suggestion6",
                     "Report finds that freelancers are happier", ENTERTAINMENT_PUBLISHER,
-                    "summary is not used", "http://example.com",
-                    getTimestamp(2017, Calendar.JANUARY, 30), 0.0f, 0L, false,
+                    "http://example.com", getTimestamp(2017, Calendar.JANUARY, 30), 0.0f, 0L, false,
                     /* thumbnailDominantColor = */ null),
             new SnippetArticle(KnownCategories.ARTICLES, "suggestion7",
-                    "Dog denies eating the cookies", MEME_PUBLISHER, "summary is not used",
-                    "http://example.com", getTimestamp(2017, Calendar.JANUARY, 30), 0.0f, 0L, false,
+                    "Dog denies eating the cookies", MEME_PUBLISHER, "http://example.com",
+                    getTimestamp(2017, Calendar.JANUARY, 30), 0.0f, 0L, false,
                     /* thumbnailDominantColor = */ null),
             new SnippetArticle(KnownCategories.ARTICLES, "suggestion8",
                     "National train strike leads to massive delays for commuters", NEWS_PUBLISHER,
-                    "summary is not used", "http://example.com",
-                    getTimestamp(2017, Calendar.JANUARY, 30), 0.0f, 0L, false,
+                    "http://example.com", getTimestamp(2017, Calendar.JANUARY, 30), 0.0f, 0L, false,
                     /* thumbnailDominantColor = */ null),
     };
 
     private static final SnippetArticle[] FAKE_BOOKMARK_SUGGESTIONS = new SnippetArticle[] {
             new SnippetArticle(KnownCategories.BOOKMARKS, "bookmark0",
-                    "Light pollution worse than ever", FACTS_PUBLISHER, "summary is not used",
-                    "http://example.com", getTimestamp(2017, Calendar.MARCH, 10), 0.0f, 0L, false,
+                    "Light pollution worse than ever", FACTS_PUBLISHER, "http://example.com",
+                    getTimestamp(2017, Calendar.MARCH, 10), 0.0f, 0L, false,
                     /* thumbnailDominantColor = */ null),
             new SnippetArticle(KnownCategories.BOOKMARKS, "bookmark1",
                     "Emergency services suffering further budget cuts", NEWS_PUBLISHER,
-                    "summary is not used", "http://example.com",
-                    getTimestamp(2017, Calendar.FEBRUARY, 20), 0.0f, 0L, false,
-                    /* thumbnailDominantColor = */ null),
+                    "http://example.com", getTimestamp(2017, Calendar.FEBRUARY, 20), 0.0f, 0L,
+                    false, /* thumbnailDominantColor = */ null),
             new SnippetArticle(KnownCategories.BOOKMARKS, "bookmark2",
-                    "Local election yields surprise winner", FACTS_PUBLISHER, "summary is not used",
-                    "http://example.com", getTimestamp(2017, Calendar.MARCH, 30), 0.0f, 0L, false,
+                    "Local election yields surprise winner", FACTS_PUBLISHER, "http://example.com",
+                    getTimestamp(2017, Calendar.MARCH, 30), 0.0f, 0L, false,
                     /* thumbnailDominantColor = */ null),
     };
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerViewTest.java
index 6062adc..1c1012a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerViewTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerViewTest.java
@@ -422,10 +422,9 @@
         List<SnippetArticle> suggestions = new ArrayList<>();
         for (int i = 0; i < suggestionsCount; i++) {
             String url = mTestServer.getURL(TEST_PAGE) + "#" + i;
-            suggestions.add(
-                    new SnippetArticle(TEST_CATEGORY, "id" + i, "title" + i, "publisher" + i,
-                            "previewText" + i, url, FAKE_PUBLISH_TIMESTAMP + i, FAKE_SNIPPET_SCORE,
-                            FAKE_FETCH_TIMESTAMP, false, /* thumbnailDominantColor = */ null));
+            suggestions.add(new SnippetArticle(TEST_CATEGORY, "id" + i, "title" + i,
+                    "publisher" + i, url, FAKE_PUBLISH_TIMESTAMP + i, FAKE_SNIPPET_SCORE,
+                    FAKE_FETCH_TIMESTAMP, false, /* thumbnailDominantColor = */ null));
         }
         return suggestions;
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java
index 0d92059..b0b0515 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java
@@ -53,6 +53,7 @@
 import org.chromium.chrome.browser.signin.SigninAccessPoint;
 import org.chromium.chrome.browser.signin.SigninPromoController;
 import org.chromium.chrome.browser.snackbar.SnackbarManager;
+import org.chromium.chrome.browser.suggestions.ContentSuggestionPlaceholder;
 import org.chromium.chrome.browser.suggestions.ContentSuggestionsAdditionalAction;
 import org.chromium.chrome.browser.suggestions.DestructionObserver;
 import org.chromium.chrome.browser.suggestions.ImageFetcher;
@@ -98,8 +99,7 @@
             new ChromeActivityTestRule<>(ChromeActivity.class);
 
     @Rule
-    public RenderTestRule mRenderTestRule =
-            new RenderTestRule("chrome/test/data/android/render_tests");
+    public RenderTestRule mRenderTestRule = new RenderTestRule();
 
     @Rule
     public TestRule mDisableChromeAnimations = new DisableChromeAnimations();
@@ -193,7 +193,7 @@
                 /* show_if_empty = */ true, "No suggestions");
 
         SnippetArticle shortSnippet = new SnippetArticle(FULL_CATEGORY, "id1", "Snippet",
-                "Publisher", "Preview Text", "www.google.com",
+                "Publisher", "www.google.com",
                 mTimestamp, // Publish timestamp
                 10f, // Score
                 mTimestamp, // Fetch timestamp
@@ -210,7 +210,7 @@
         SnippetArticle longSnippet = new SnippetArticle(FULL_CATEGORY, "id2",
                 new String(new char[20]).replace("\0", "Snippet "),
                 new String(new char[20]).replace("\0", "Publisher "),
-                new String(new char[80]).replace("\0", "Preview Text "), "www.google.com",
+                "www.google.com",
                 mTimestamp, // Publish timestamp
                 20f, // Score
                 mTimestamp, // Fetch timestamp
@@ -225,7 +225,7 @@
 
         SnippetArticle minimalSnippet = new SnippetArticle(MINIMAL_CATEGORY, "id3",
                 new String(new char[20]).replace("\0", "Bookmark "), "Publisher",
-                "This should not be displayed", "www.google.com",
+                "www.google.com",
                 mTimestamp, // Publish timestamp
                 10f, // Score
                 mTimestamp, // Fetch timestamp
@@ -234,7 +234,7 @@
         renderSuggestion(minimalSnippet, minimalCategory, "minimal_snippet");
 
         SnippetArticle minimalSnippet2 = new SnippetArticle(MINIMAL_CATEGORY, "id4", "Bookmark",
-                "Publisher", "This should not be displayed", "www.google.com",
+                "Publisher", "www.google.com",
                 mTimestamp, // Publish timestamp
                 10f, // Score
                 mTimestamp, // Fetch timestamp
@@ -272,7 +272,7 @@
                 UrlUtils.getIsolatedTestFilePath("chrome/test/data/android/capybara.jpg");
         ThreadUtils.runOnUiThreadBlocking(() -> {
             SnippetArticle downloadSuggestion = new SnippetArticle(KnownCategories.DOWNLOADS, "id1",
-                    "test_image.jpg", "example.com", null, "http://example.com",
+                    "test_image.jpg", "example.com", "http://example.com",
                     mTimestamp, // Publish timestamp
                     10f, // Score
                     mTimestamp, // Fetch timestamp
@@ -325,8 +325,6 @@
     @Feature({"ArticleSnippets", "RenderTest"})
     public void testPersonalizedSigninPromosNoAccounts() throws IOException {
         ThreadUtils.runOnUiThreadBlocking(() -> {
-            mRecyclerView.init(mUiConfig, null);
-            mRecyclerView.setAdapter(null);
             createPersonalizedSigninPromo(null);
             mContentView.addView(mSigninPromo.itemView);
         });
@@ -338,14 +336,29 @@
     @Feature({"ArticleSnippets", "RenderTest"})
     public void testPersonalizedSigninPromosWithAccount() throws IOException {
         ThreadUtils.runOnUiThreadBlocking(() -> {
-            mRecyclerView.init(mUiConfig, null);
-            mRecyclerView.setAdapter(null);
             createPersonalizedSigninPromo(getTestProfileData());
             mContentView.addView(mSigninPromo.itemView);
         });
         mRenderTestRule.render(mSigninPromo.itemView, "hot_state_personalized_signin_promo");
     }
 
+    @Test
+    @MediumTest
+    @Feature({"ArticleSnippets", "RenderTest"})
+    public void testContentSuggestionPlaceholder() throws IOException {
+        // TODO(dgn): Try to use assume or notify the test runner in some way that we skipped it
+        // instead of making it always PASS here.
+        if (!mChromeHomeEnabled) return; // Placeholder is only valid on modern.
+
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            ContentSuggestionPlaceholder.ViewHolder viewHolder =
+                    new ContentSuggestionPlaceholder.ViewHolder(mRecyclerView, mUiConfig, null);
+            viewHolder.onBindViewHolder();
+            mContentView.addView(viewHolder.itemView);
+        });
+        mRenderTestRule.render(mContentView.getChildAt(0), "content_suggestion_placeholder");
+    }
+
     private void createPersonalizedSigninPromo(@Nullable DisplayableProfileData profileData) {
         SigninPromoController signinPromoController =
                 new SigninPromoController(SigninAccessPoint.NTP_CONTENT_SUGGESTIONS);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppUiSkipPreloadTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppUiSkipPreloadTest.java
index cd64626..9eb8ae9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppUiSkipPreloadTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppUiSkipPreloadTest.java
@@ -16,6 +16,7 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.test.ChromeActivityTestRule;
@@ -90,8 +91,9 @@
      * getInstruments.
      */
     @Test
-    @MediumTest
-    @Feature({"Payments"})
+    // @MediumTest
+    // @Feature({"Payments"})
+    @DisabledTest
     public void testPayViaDelayedSlowBobPay()
             throws InterruptedException, ExecutionException, TimeoutException {
         mPaymentRequestTestRule.installPaymentApp(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ssl/CaptivePortalTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ssl/CaptivePortalTest.java
index 1f53f36..a92772e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ssl/CaptivePortalTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ssl/CaptivePortalTest.java
@@ -58,6 +58,9 @@
         mServer = EmbeddedTestServer.createAndStartHTTPSServer(
                 InstrumentationRegistry.getInstrumentation().getContext(),
                 ServerCertificate.CERT_MISMATCHED_NAME);
+
+        CaptivePortalHelper.setOSReportsCaptivePortalForTesting(false);
+        CaptivePortalHelper.setCaptivePortalCertificateForTesting("sha256/test");
     }
 
     @After
@@ -74,18 +77,10 @@
         }));
     }
 
-    @Test
-    public void testCaptivePortalInterstitial() throws Exception {
-        // Add the SPKI of the root cert to captive portal certificate list.
-        byte[] rootCertSPKI = CertTestUtil.getPublicKeySha256(X509Util.createCertificateFromBytes(
-                CertTestUtil.pemToDer(mServer.getRootCertPemPath())));
-        Assert.assertTrue(rootCertSPKI != null);
-        CaptivePortalHelper.addCaptivePortalCertificateForTesting(
-                "sha256/" + Base64.encodeToString(rootCertSPKI, Base64.NO_WRAP));
-
-        // Navigate the tab to an interstitial with a name mismatch error. This should
-        // result in a captive portal interstitial since the certificate's SPKI hash
-        // is added to the captive portal certificate list.
+    /** Navigate the tab to an interstitial with a name mismatch error and check if this
+    /*  results in a captive portal interstitial.
+     */
+    private void navigateAndCheckCaptivePortalInterstitial() throws Exception {
         Tab tab = mActivityTestRule.getActivity().getActivityTab();
         ChromeTabUtils.loadUrlOnUiThread(
                 tab, mServer.getURL("/chrome/test/data/android/navigate/simple.html"));
@@ -102,4 +97,22 @@
 
         Assert.assertEquals(0, tab.getTitle().indexOf(CAPTIVE_PORTAL_INTERSTITIAL_TITLE_PREFIX));
     }
+
+    @Test
+    public void testCaptivePortalCertificateListFeature() throws Exception {
+        // Add the SPKI of the root cert to captive portal certificate list.
+        byte[] rootCertSPKI = CertTestUtil.getPublicKeySha256(X509Util.createCertificateFromBytes(
+                CertTestUtil.pemToDer(mServer.getRootCertPemPath())));
+        Assert.assertTrue(rootCertSPKI != null);
+        CaptivePortalHelper.setCaptivePortalCertificateForTesting(
+                "sha256/" + Base64.encodeToString(rootCertSPKI, Base64.NO_WRAP));
+
+        navigateAndCheckCaptivePortalInterstitial();
+    }
+
+    @Test
+    public void testOSReportsCaptivePortal() throws Exception {
+        CaptivePortalHelper.setOSReportsCaptivePortalForTesting(true);
+        navigateAndCheckCaptivePortalInterstitial();
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/ContextualSuggestionsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/ContextualSuggestionsTest.java
index 516c772..c4085af 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/ContextualSuggestionsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/ContextualSuggestionsTest.java
@@ -52,14 +52,12 @@
     private static final List<SnippetArticle> FAKE_CONTEXTUAL_SUGGESTIONS = Arrays.asList(
             new SnippetArticle(KnownCategories.CONTEXTUAL, "suggestion0",
                     "James Roderick to step down as conductor for Laville orchestra",
-                    "The Curious One", "summary is not used", "http://example.com", 0, 0.0f, 0L,
-                    false, null),
+                    "The Curious One", "http://example.com", 0, 0.0f, 0L, false, null),
             new SnippetArticle(KnownCategories.CONTEXTUAL, "suggestion1",
-                    "Boy raises orphaned goat", "Meme feed", "summary is not used",
-                    "http://example.com", 0, 0.0f, 0L, false, null),
+                    "Boy raises orphaned goat", "Meme feed", "http://example.com", 0, 0.0f, 0L,
+                    false, null),
             new SnippetArticle(KnownCategories.CONTEXTUAL, "suggestion2", "Top gigs this week",
-                    "Hello World", "summary is not used", "http://example.com", 0, 0.0f, 0L,
-                    false, null));
+                    "Hello World", "http://example.com", 0, 0.0f, 0L, false, null));
 
     @Rule
     public SuggestionsDependenciesRule mSuggestionsDeps = new SuggestionsDependenciesRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetCardsUiCaptureTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetCardsUiCaptureTest.java
index b6dd080..7371660 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetCardsUiCaptureTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetCardsUiCaptureTest.java
@@ -23,14 +23,19 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ntp.NtpUiCaptureTestData;
 import org.chromium.chrome.browser.ntp.cards.ItemViewType;
+import org.chromium.chrome.browser.ntp.snippets.CategoryStatus;
+import org.chromium.chrome.browser.ntp.snippets.KnownCategories;
 import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
 import org.chromium.chrome.browser.test.ScreenShooter;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.suggestions.FakeSuggestionsSource;
 import org.chromium.chrome.test.util.browser.suggestions.SuggestionsDependenciesRule;
+import org.chromium.chrome.test.util.browser.suggestions.SuggestionsDependenciesRule.TestFactory;
 import org.chromium.ui.test.util.UiRestriction;
 
+import java.util.Collections;
+
 /**
  * Tests for the appearance of the card suggestions in the home sheet.
  */
@@ -42,20 +47,21 @@
 
     @Rule
     public SuggestionsDependenciesRule setupSuggestions() {
-        SuggestionsDependenciesRule.TestFactory depsFactory = NtpUiCaptureTestData.createFactory();
         FakeSuggestionsSource suggestionsSource = new FakeSuggestionsSource();
         NtpUiCaptureTestData.registerArticleSamples(suggestionsSource);
-        depsFactory.suggestionsSource = suggestionsSource;
-        return new SuggestionsDependenciesRule(depsFactory);
+        mDepsFactory.suggestionsSource = suggestionsSource;
+        return new SuggestionsDependenciesRule(mDepsFactory);
     }
 
     @Rule
     public ScreenShooter mScreenShooter = new ScreenShooter();
 
+    private final TestFactory mDepsFactory = NtpUiCaptureTestData.createFactory();
+
     @Before
     public void setup() throws InterruptedException {
         ChromePreferenceManager.getInstance().setNewTabPageGenericSigninPromoDismissed(true);
-        mActivityRule.startMainActivityOnBlankPage();
+        mActivityRule.startMainActivityOnBottomSheet(BottomSheet.SHEET_STATE_PEEK);
     }
 
     @Test
@@ -87,4 +93,19 @@
         waitForWindowUpdates();
         mScreenShooter.shoot("ScrolledToFirstCard");
     }
+
+    @Test
+    @MediumTest
+    @Feature({"UiCatalogue"})
+    @ScreenShooter.Directory("HomeSheetCards")
+    public void testContentSuggestionPlaceholder() throws Exception {
+        FakeSuggestionsSource source = (FakeSuggestionsSource) mDepsFactory.suggestionsSource;
+        source.setSuggestionsForCategory(KnownCategories.ARTICLES, Collections.emptyList());
+        source.setStatusForCategory(KnownCategories.ARTICLES, CategoryStatus.AVAILABLE_LOADING);
+
+        mActivityRule.setSheetState(BottomSheet.SHEET_STATE_FULL, false);
+        waitForWindowUpdates();
+
+        mScreenShooter.shoot("ContentSuggestionsPlaceholder");
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/TileGridLayoutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/TileGridLayoutTest.java
index d015595..94466894 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/TileGridLayoutTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/TileGridLayoutTest.java
@@ -32,6 +32,7 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.Restriction;
+import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
@@ -43,6 +44,7 @@
 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.util.ViewUtils;
 import org.chromium.chrome.browser.widget.displaystyle.UiConfig;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -187,6 +189,7 @@
 
     @Test
     @MediumTest
+    @RetryOnFailure
     @Feature({"NewTabPage", "RenderTest"})
     @ChromeHome
     @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
@@ -202,6 +205,7 @@
 
     @Test
     @MediumTest
+    @RetryOnFailure
     @Feature({"NewTabPage", "RenderTest"})
     @ChromeHome(false)
     public void testTileGridAppearance_Two() throws IOException, InterruptedException {
@@ -233,8 +237,8 @@
     private NewTabPage setUpFakeDataToShowOnNtp(int homePagePosition) throws InterruptedException {
         List<SiteSuggestion> siteSuggestions = makeSuggestions(FAKE_MOST_VISITED_URLS.length);
         siteSuggestions.add(homePagePosition,
-                new SiteSuggestion("HOMEPAGE", HOME_PAGE_URL, "", TileSource.HOMEPAGE,
-                        TileSectionType.PERSONALIZED));
+                new SiteSuggestion("HOMEPAGE", HOME_PAGE_URL, "", TileTitleSource.TITLE_TAG,
+                        TileSource.HOMEPAGE, TileSectionType.PERSONALIZED));
 
         FakeMostVisitedSites mMostVisitedSites = new FakeMostVisitedSites();
         mMostVisitedSites.setTileSuggestions(siteSuggestions);
@@ -270,27 +274,24 @@
 
     /**
      * Checks whether the requested orientation matches the current one.
-     * @param activity Activity to check the orientation from. We pull its {@link Configuration}.
+     * @param activity Activity to check the orientation from. We pull its {@link Configuration} and
+     *         content {@link View}.
      * @param requestedOrientation The requested orientation, as used in
-     *         {@link ActivityInfo#screenOrientation}. Note: This value is different from the one we
-     *         check against from {@link Configuration#orientation}. The constants used to represent
-     *         the values are not the same.
+     *         {@link ActivityInfo#screenOrientation}.
      */
-    public boolean orientationMatchesRequest(Activity activity, int requestedOrientation) {
-        int currentOrientation = activity.getResources().getConfiguration().orientation;
+    private boolean orientationMatchesRequest(Activity activity, int requestedOrientation) {
+        // Note: Requests use a constant from ActivityInfo, not Configuration.ORIENTATION_*!
+        boolean expectLandscape = requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 
-        // 1 => 1
-        if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
-            return currentOrientation == Configuration.ORIENTATION_PORTRAIT;
-        }
+        // We check the orientation by looking at the dimensions of the content view. Looking at
+        // orientation from the configuration is not reliable as sometimes the activity gets the
+        // event that its configuration changed, but has not updated its layout yet.
+        Configuration configuration = activity.getResources().getConfiguration();
+        View contentView = activity.findViewById(android.R.id.content);
+        int smallestWidthPx = ViewUtils.dpToPx(activity, configuration.smallestScreenWidthDp);
+        boolean viewIsLandscape = contentView.getMeasuredWidth() > smallestWidthPx;
 
-        // 0 => 2
-        if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
-            return currentOrientation == Configuration.ORIENTATION_LANDSCAPE;
-        }
-
-        throw new IllegalArgumentException(
-                "unexpected orientation requested: " + requestedOrientation);
+        return expectLandscape == viewIsLandscape;
     }
 
     private TileGridLayout getTileGridLayout(NewTabPage ntp) {
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 e019af6..31ad4a3 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
@@ -5,6 +5,7 @@
 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.browser.vr_shell.VrTestFramework.POLL_TIMEOUT_SHORT_MS;
 import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_DEVICE_DAYDREAM;
@@ -31,6 +32,8 @@
 import org.chromium.chrome.browser.vr_shell.util.VrTransitionUtils;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.content.browser.test.util.Criteria;
+import org.chromium.content.browser.test.util.CriteriaHelper;
 import org.chromium.content.browser.test.util.DOMUtils;
 
 import java.util.concurrent.TimeoutException;
@@ -141,16 +144,27 @@
     @MediumTest
     public void testExitFullscreenAfterExitingVrFromCinemaMode()
             throws InterruptedException, TimeoutException {
-        mVrTestFramework.loadUrlAndAwaitInitialization(
-                VrTestFramework.getHtmlTestFile("test_navigation_2d_page"), PAGE_LOAD_TIMEOUT_S);
         VrTransitionUtils.forceEnterVr();
         VrTransitionUtils.waitForVrEntry(POLL_TIMEOUT_LONG_MS);
+        mVrTestFramework.loadUrlAndAwaitInitialization(
+                VrTestFramework.getHtmlTestFile("test_navigation_2d_page"), PAGE_LOAD_TIMEOUT_S);
         DOMUtils.clickNode(mVrTestFramework.getFirstTabCvc(), "fullscreen");
         mVrTestFramework.waitOnJavaScriptStep(mVrTestFramework.getFirstTabWebContents());
 
         Assert.assertTrue(DOMUtils.isFullscreen(mVrTestFramework.getFirstTabWebContents()));
         VrTransitionUtils.forceExitVr();
-        Assert.assertFalse(DOMUtils.isFullscreen(mVrTestFramework.getFirstTabWebContents()));
+        // The fullscreen exit from exiting VR isn't necessarily instantaneous, so give it
+        // a bit of time.
+        CriteriaHelper.pollInstrumentationThread(new Criteria() {
+            @Override
+            public boolean isSatisfied() {
+                try {
+                    return !DOMUtils.isFullscreen(mVrTestFramework.getFirstTabWebContents());
+                } catch (InterruptedException | TimeoutException e) {
+                    return false;
+                }
+            }
+        }, POLL_TIMEOUT_SHORT_MS, POLL_CHECK_INTERVAL_SHORT_MS);
     }
 
     /**
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/animation/CompositorAnimatorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/animation/CompositorAnimatorTest.java
index 266ea05..67ceb814 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/animation/CompositorAnimatorTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/animation/CompositorAnimatorTest.java
@@ -67,6 +67,11 @@
 
         @Override
         public void releaseTabLayout(int id) {}
+
+        @Override
+        public CompositorAnimationHandler getAnimationHandler() {
+            return null;
+        }
     }
 
     /** An animation update listener that counts calls to its methods. */
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
index 545afa47..04c4a25 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
@@ -391,8 +391,7 @@
 
         // Add another suggestion.
         suggestions.add(new SnippetArticle(TEST_CATEGORY, "https://site.com/url3", "title3", "pub3",
-                "txt3", "https://site.com/url3", 0, 0, 0, false,
-                /* thumbnailDominantColor = */ null));
+                "https://site.com/url3", 0, 0, 0, false, /* thumbnailDominantColor = */ null));
 
         // When the provider is removed, we should not be able to load suggestions. The UI should
         // stay the same though.
diff --git a/chrome/android/webapk/libs/runtime_library/BUILD.gn b/chrome/android/webapk/libs/runtime_library/BUILD.gn
index 4413aae..f6ad5e9 100644
--- a/chrome/android/webapk/libs/runtime_library/BUILD.gn
+++ b/chrome/android/webapk/libs/runtime_library/BUILD.gn
@@ -33,6 +33,9 @@
   java_files =
       [ "src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java" ]
   srcjar_deps = [ ":webapk_service_aidl" ]
+  deps = [
+    "//third_party/android_tools:android_support_v4_java",
+  ]
 }
 
 # The subset of runtime_library_from_assets_java needed for tests.
@@ -41,6 +44,7 @@
       [ "src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java" ]
   deps = [
     ":webapk_service_aidl_java",
+    "//third_party/android_tools:android_support_v4_java",
   ]
 }
 
diff --git a/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/IWebApkApi.aidl b/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/IWebApkApi.aidl
index 99ab9b5..f2afc82 100644
--- a/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/IWebApkApi.aidl
+++ b/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/IWebApkApi.aidl
@@ -13,6 +13,9 @@
     // Gets the id of the icon to represent WebAPK notifications in status bar.
     int getSmallIconId();
 
+    // Get if notification permission is enabled.
+    boolean notificationPermissionEnabled();
+
     // Display a notification.
     void notifyNotification(String platformTag, int platformID, in Notification notification);
 
diff --git a/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/OWNERS b/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/OWNERS
new file mode 100644
index 0000000..89442abe
--- /dev/null
+++ b/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/OWNERS
@@ -0,0 +1,2 @@
+per-file *.aidl=set noparent
+per-file *.aidl=file://ipc/SECURITY_OWNERS
\ No newline at end of file
diff --git a/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java b/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java
index 5fccbdc7..c556901 100644
--- a/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java
+++ b/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java
@@ -11,6 +11,7 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.RemoteException;
+import android.support.v4.app.NotificationManagerCompat;
 
 /**
  * Implements services offered by the WebAPK to Chrome.
@@ -72,6 +73,10 @@
         getNotificationManager().cancel(platformTag, platformID);
     }
 
+    public boolean notificationPermissionEnabled() {
+        return NotificationManagerCompat.from(mContext).areNotificationsEnabled();
+    }
+
     private NotificationManager getNotificationManager() {
         return (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
     }
diff --git a/chrome/android/webapk/libs/runtime_library_version.gni b/chrome/android/webapk/libs/runtime_library_version.gni
index 21a07fb..14f040de 100644
--- a/chrome/android/webapk/libs/runtime_library_version.gni
+++ b/chrome/android/webapk/libs/runtime_library_version.gni
@@ -5,4 +5,4 @@
 # Must be incremented whenever the runtime library is updated. The WebAPK
 # re-extracts the runtime library from the Chrome APK when
 # |runtime_library_version| is incremented.
-runtime_library_version = 1
+runtime_library_version = 2
diff --git a/chrome/app/BUILD.gn b/chrome/app/BUILD.gn
index abb33a3..3d1865e9 100644
--- a/chrome/app/BUILD.gn
+++ b/chrome/app/BUILD.gn
@@ -4,6 +4,7 @@
 
 import("//build/config/ui.gni")
 import("//chrome/common/features.gni")
+import("//components/nacl/features.gni")
 import("//ppapi/features/features.gni")
 import("//printing/features/features.gni")
 import("//services/catalog/public/tools/catalog.gni")
@@ -424,9 +425,15 @@
   source =
       "//chrome/browser/chrome_content_packaged_services_manifest_overlay.json"
   packaged_services = chrome_packaged_services
+  if (enable_package_mash_services) {
+    packaged_services += [ "//mash/quick_launch:manifest" ]
+  }
   if (is_chromeos) {
     packaged_services += [
+      "//ash/autoclick/mus:manifest",
       "//ash/mus:manifest",
+      "//ash/touch_hud/mus:manifest",
+      "//components/font_service:manifest",
       "//services/ui:manifest",
     ]
   }
diff --git a/chrome/app/chrome_main.cc b/chrome/app/chrome_main.cc
index e05f303..90b02a1 100644
--- a/chrome/app/chrome_main.cc
+++ b/chrome/app/chrome_main.cc
@@ -103,7 +103,8 @@
 #endif  // defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
 
 #if defined(OS_CHROMEOS) && BUILDFLAG(ENABLE_PACKAGE_MASH_SERVICES)
-  if (service_manager::ServiceManagerIsRemote()) {
+  if (service_manager::ServiceManagerIsRemote() ||
+      command_line->HasSwitch(switches::kMash)) {
     params.create_discardable_memory = false;
     params.env_mode = aura::Env::Mode::MUS;
   }
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc
index 06ba8f4..f492472 100644
--- a/chrome/app/chrome_main_delegate.cc
+++ b/chrome/app/chrome_main_delegate.cc
@@ -107,19 +107,13 @@
 #include "chromeos/chromeos_paths.h"
 #include "chromeos/chromeos_switches.h"
 #include "chromeos/hugepage_text/hugepage_text.h"
+#include "components/metrics/leak_detector/leak_detector.h"
 #endif
 
 #if BUILDFLAG(ENABLE_PACKAGE_MASH_SERVICES)
-#include "chrome/app/mash/chrome_mash_catalog.h"
-#include "chrome/app/mash/embedded_services.h"
 #include "mash/common/config.h"                                   // nogncheck
-#include "mash/quick_launch/public/interfaces/constants.mojom.h"  // nogncheck
 #include "services/ui/public/interfaces/constants.mojom.h"        // nogncheck
 
-#if defined(OS_CHROMEOS)
-#include "chrome/app/mash/chrome_mus_catalog.h"
-#endif
-
 #endif  // BUILDFLAG(ENABLE_PACKAGE_MASH_SERVICES)
 
 #if defined(OS_ANDROID)
@@ -151,10 +145,6 @@
 #include "components/crash/content/app/crashpad.h"
 #endif
 
-#if defined(OS_CHROMEOS)
-#include "components/metrics/leak_detector/leak_detector.h"
-#endif
-
 #if BUILDFLAG(ENABLE_NACL)
 #include "components/nacl/common/nacl_switches.h"
 #include "components/nacl/renderer/plugin/ppapi_entrypoints.h"
@@ -315,6 +305,11 @@
 // Returns true if this subprocess type needs the ResourceBundle initialized
 // and resources loaded.
 bool SubprocessNeedsResourceBundle(const std::string& process_type) {
+  if (process_type == switches::kUtilityProcess &&
+      base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kDisableServiceProcessResourceLoading)) {
+    return false;
+  }
   return
 #if defined(OS_POSIX) && !defined(OS_MACOSX)
       // The zygote process opens the resources for the renderers.
@@ -1135,53 +1130,9 @@
     // Don't mess with embedded service command lines.
     return service_manager::ProcessType::kDefault;
   }
-
-#if BUILDFLAG(ENABLE_PACKAGE_MASH_SERVICES)
-  if (command_line.HasSwitch(switches::kMash))
-    return service_manager::ProcessType::kServiceManager;
-#endif
-
   return service_manager::ProcessType::kDefault;
 }
 
-std::unique_ptr<base::Value> ChromeMainDelegate::CreateServiceCatalog() {
-  if (!g_service_catalog_factory.Get().is_null())
-    return g_service_catalog_factory.Get().Run();
-#if BUILDFLAG(ENABLE_PACKAGE_MASH_SERVICES)
-  const auto& command_line = *base::CommandLine::ForCurrentProcess();
-#if defined(OS_CHROMEOS)
-  if (command_line.HasSwitch(switches::kMus))
-    return CreateChromeMusCatalog();
-#endif  // defined(OS_CHROMEOS)
-  if (command_line.HasSwitch(switches::kMash))
-    return CreateChromeMashCatalog();
-#endif  // BUILDFLAG(ENABLE_PACKAGE_MASH_SERVICES)
-  return nullptr;
-}
-
-void ChromeMainDelegate::AdjustServiceProcessCommandLine(
-    const service_manager::Identity& identity,
-    base::CommandLine* command_line) {
-#if BUILDFLAG(ENABLE_PACKAGE_MASH_SERVICES)
-  // Add kMusConfig so that launched processes know what config they are
-  // running in.
-  const bool is_mash = command_line->HasSwitch(switches::kMash);
-  command_line->AppendSwitchASCII(switches::kMusConfig,
-                                  is_mash ? switches::kMash : switches::kMus);
-
-  if (identity.name() == content::mojom::kPackagedServicesServiceName) {
-    // Ensure the browser process doesn't inherit mash or mus flags, since these
-    // flags would cause the process to run as a Service Manager instead.
-    base::CommandLine::SwitchMap switches = command_line->GetSwitches();
-    switches.erase(switches::kMash);
-    switches.erase(switches::kMus);
-    *command_line = base::CommandLine(command_line->GetProgram());
-    for (const auto& sw : switches)
-      command_line->AppendSwitchNative(sw.first, sw.second);
-  }
-#endif
-}
-
 bool ChromeMainDelegate::ShouldTerminateServiceManagerOnInstanceQuit(
     const service_manager::Identity& identity,
     int* exit_code) {
@@ -1200,40 +1151,3 @@
 
   return false;
 }
-
-void ChromeMainDelegate::OnServiceManagerInitialized(
-    const base::Closure& quit_closure,
-    service_manager::BackgroundServiceManager* service_manager) {
-#if defined(OS_POSIX)
-  // Quit the main process in response to shutdown signals (like SIGTERM).
-  // These signals are used by Linux distributions to request clean shutdown.
-  // On Chrome OS the SIGTERM signal is sent by session_manager.
-  InstallShutdownSignalHandlers(quit_closure,
-                                base::ThreadTaskRunnerHandle::Get());
-#endif
-
-#if BUILDFLAG(ENABLE_PACKAGE_MASH_SERVICES)
-  // Start services that we know we want to launch on startup (UI service,
-  // window manager, quick launch app).
-  service_manager->StartService(
-      service_manager::Identity(ui::mojom::kServiceName));
-  service_manager->StartService(
-      service_manager::Identity(content::mojom::kPackagedServicesServiceName));
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kMash)) {
-    service_manager->StartService(
-        service_manager::Identity(mash::common::GetWindowManagerServiceName()));
-    service_manager->StartService(
-        service_manager::Identity(mash::quick_launch::mojom::kServiceName));
-  }
-#endif  // BUILDFLAG(ENABLE_PACKAGE_MASH_SERVICES)
-}
-
-std::unique_ptr<service_manager::Service>
-ChromeMainDelegate::CreateEmbeddedService(const std::string& service_name) {
-#if BUILDFLAG(ENABLE_PACKAGE_MASH_SERVICES)
-  auto mash_service = CreateEmbeddedMashService(service_name);
-  if (mash_service)
-    return mash_service;
-#endif  // BUILDFLAG(ENABLE_PACKAGE_MASH_SERVICES)
-  return nullptr;
-}
diff --git a/chrome/app/chrome_main_delegate.h b/chrome/app/chrome_main_delegate.h
index 01fc44af..2635707 100644
--- a/chrome/app/chrome_main_delegate.h
+++ b/chrome/app/chrome_main_delegate.h
@@ -56,18 +56,9 @@
 #endif
   bool ShouldEnableProfilerRecording() override;
   service_manager::ProcessType OverrideProcessType() override;
-  std::unique_ptr<base::Value> CreateServiceCatalog() override;
-  void AdjustServiceProcessCommandLine(
-      const service_manager::Identity& identity,
-      base::CommandLine* command_line) override;
   bool ShouldTerminateServiceManagerOnInstanceQuit(
       const service_manager::Identity& identity,
       int* exit_code) override;
-  void OnServiceManagerInitialized(
-      const base::Closure& quit_closure,
-      service_manager::BackgroundServiceManager* service_manager) override;
-  std::unique_ptr<service_manager::Service> CreateEmbeddedService(
-      const std::string& service_name) override;
 
   content::ContentBrowserClient* CreateContentBrowserClient() override;
   content::ContentGpuClient* CreateContentGpuClient() override;
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index d2faa0a..84ea4c1d 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -2447,14 +2447,8 @@
   <message name="IDS_OPTIONS_PHOTO_DISCARD_ACCESSIBLE_TEXT" desc="The accessible message to speak to announce that a photo was discarded.">
     Photo was discarded
   </message>
-  <message name="IDS_OPTIONS_CHANGE_PICTURE_FLIP_PHOTO" desc="The text on the button to flip the camera image horizontally.">
-    Flip camera image horizontally
-  </message>
-  <message name="IDS_OPTIONS_PHOTO_FLIP_ACCESSIBLE_TEXT" desc="The accessible message to speak to announce horizontal flip of camera image.">
-    Photo flipped
-  </message>
-  <message name="IDS_OPTIONS_PHOTO_FLIPBACK_ACCESSIBLE_TEXT" desc="The accessible message to speak to announce horizontal back-flip of camera image to not-flipped state.">
-    Photo flipped back
+  <message name="IDS_OPTIONS_CHANGE_PICTURE_SWITCH_MODE" desc="The text on the button to switch the mode of the camera between photo and video.">
+    Switch camera mode
   </message>
   <message name="IDS_IMAGE_SCREEN_PROFILE_PHOTO" desc="The title of the Google profile photo of the user on image selection screen. Please keep in sync with IDS_OPTIONS_CHANGE_PICTURE_PROFILE_PHOTO.">
     Google Profile photo
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 39919cc..1276886d 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -5592,6 +5592,12 @@
         <message name="IDS_PASSWORD_MANAGER_EXPORT_DIALOG_TITLE" desc="The title of the file selection dialog for exporting passwords">
           Export Passwords From Chrome
         </message>
+        <message name="IDS_PASSWORD_MANAGER_USERNAME_LABEL" desc="Label for the username field in a prompt to store new credential">
+          Username
+        </message>
+        <message name="IDS_PASSWORD_MANAGER_PASSWORD_LABEL" desc="Label for the password field in a prompt to store new credential">
+          Password
+        </message>
       </if>
       <if expr="is_android">
         <message name="IDS_PASSWORD_MANAGER_SAVE_BUTTON" desc="Mobile: Button text for the 'Save Password' infobar's 'Remember password' option">
@@ -7012,9 +7018,6 @@
       <message name="IDS_MEDIA_SCREEN_AND_AUDIO_CAPTURE_CONFIRMATION_TEXT" desc="Text for the prompt shown when screen and audio capturing is requrested by an app.">
         Do you want <ph name="APP_NAME">$1<ex>html5rocks.com</ex></ph> to share your screen and audio output?
       </message>
-      <message name="IDS_MEDIA_SYSTEM_AUDIO_CAPTURE_CONFIRMATION_TEXT" desc="Text for the prompt shown when system audio capturing is requrested by an app.">
-        Do you want <ph name="APP_NAME">$1<ex>html5rocks.com</ex></ph> to share your audio output?
-      </message>
       <message name="IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_TEXT" desc="label used in screen capture notification UI to show the screen sharing status when the stream is consumed by the same app initiating the window picker">
         <ph name="APP_NAME">$1<ex>html5rocks.com</ex></ph> is sharing your screen.
       </message>
@@ -7027,12 +7030,6 @@
       <message name="IDS_MEDIA_SCREEN_CAPTURE_WITH_AUDIO_NOTIFICATION_TEXT_DELEGATED" desc="label used in screen capture notification UI to show the screen sharing status when the stream is consumed by a tab instead of the app initiating the window picker">
         <ph name="APP_NAME">$1<ex>html5rocks.com</ex></ph> is sharing your screen and audio with <ph name="TAB_NAME">$2<ex>https://google.com</ex></ph>.
       </message>
-      <message name="IDS_MEDIA_SYSTEM_AUDIO_CAPTURE_NOTIFICATION_TEXT" desc="label used in screen capture notification UI to show the system audio sharing status when the stream is consumed by the same app initiating the window picker.">
-        <ph name="APP_NAME">$1<ex>html5rocks.com</ex></ph> is sharing your audio.
-      </message>
-      <message name="IDS_MEDIA_SYSTEM_AUDIO_CAPTURE_NOTIFICATION_TEXT_DELEGATED" desc="label used in screen capture notification UI to show the system audio sharing status when the stream is consumed by tab instead of the app initiating the window picker">
-        <ph name="APP_NAME">$1<ex>html5rocks.com</ex></ph> is sharing your audio with <ph name="TAB_NAME">$2<ex>https://google.com</ex></ph>.
-      </message>
       <message name="IDS_MEDIA_WINDOW_CAPTURE_NOTIFICATION_TEXT" desc="label used in screen capture notification UI to show the screen sharing status when the stream is consumed by the same app initiating the window picker">
         <ph name="APP_NAME">$1<ex>html5rocks.com</ex></ph> is sharing a window.
       </message>
diff --git a/chrome/app/mash/BUILD.gn b/chrome/app/mash/BUILD.gn
index 0e8a9e9..8c28123 100644
--- a/chrome/app/mash/BUILD.gn
+++ b/chrome/app/mash/BUILD.gn
@@ -4,22 +4,20 @@
 
 import("//build/config/nacl/config.gni")
 import("//chrome/common/features.gni")
+import("//components/nacl/features.gni")
 import("//services/catalog/public/tools/catalog.gni")
 import("//services/service_manager/public/service_manifest.gni")
 
 assert(enable_package_mash_services)
 
-source_set("embedded_services") {
-  sources = [
-    "embedded_services.cc",
-    "embedded_services.h",
-  ]
-
+# TODO(sky): clean this and catalog entries up.
+group("embedded_services") {
   deps = [
     ":chrome_mash_catalog",
     "//base:i18n",
     "//chrome/common:constants",
     "//components/tracing:startup_tracing",
+    "//content/public/browser",
     "//content/public/common",
     "//mash/catalog_viewer:lib",
     "//mash/catalog_viewer/public/interfaces:constants",
@@ -61,7 +59,10 @@
   }
 
   if (is_linux && !is_android) {
-    deps += [ "//components/font_service:lib" ]
+    deps += [
+      "//components/font_service:lib",
+      "//components/font_service/public/interfaces",
+    ]
   }
 }
 
diff --git a/chrome/app/mash/DEPS b/chrome/app/mash/DEPS
index bd124777..938bc79 100644
--- a/chrome/app/mash/DEPS
+++ b/chrome/app/mash/DEPS
@@ -9,6 +9,7 @@
   "+chrome/common/chrome_switches.h",
   "+components/font_service",
   "+components/tracing",
+  "+content/public",
   "+services/ui",
   "+mash",
   "+mojo/edk/embedder",
diff --git a/chrome/app/mash/embedded_services.cc b/chrome/app/mash/embedded_services.cc
deleted file mode 100644
index 88f5152a..0000000
--- a/chrome/app/mash/embedded_services.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/app/mash/embedded_services.h"
-
-#include "mash/catalog_viewer/catalog_viewer.h"
-#include "mash/catalog_viewer/public/interfaces/constants.mojom.h"
-#include "mash/common/config.h"
-#include "mash/quick_launch/public/interfaces/constants.mojom.h"
-#include "mash/quick_launch/quick_launch.h"
-#include "mash/session/public/interfaces/constants.mojom.h"
-#include "mash/session/session.h"
-#include "mash/task_viewer/public/interfaces/constants.mojom.h"
-#include "mash/task_viewer/task_viewer.h"
-#include "services/ui/ime/test_ime_driver/test_ime_application.h"
-#include "services/ui/public/interfaces/constants.mojom.h"
-#include "services/ui/service.h"
-
-#if defined(OS_CHROMEOS)
-#include "ash/autoclick/mus/autoclick_application.h"  // nogncheck
-#include "ash/mus/window_manager_application.h"       // nogncheck
-#include "ash/public/interfaces/constants.mojom.h"    // nogncheck
-#include "ash/touch_hud/mus/touch_hud_application.h"  // nogncheck
-#endif                                                // defined(OS_CHROMEOS)
-
-#if defined(OS_LINUX) && !defined(OS_ANDROID)
-#include "components/font_service/font_service_app.h"
-#endif  // defined(OS_LINUX) && !defined(OS_ANDROID)
-
-std::unique_ptr<service_manager::Service> CreateEmbeddedMashService(
-    const std::string& service_name) {
-#if defined(OS_CHROMEOS)
-  if (service_name == ash::mojom::kServiceName) {
-    const bool show_primary_host_on_connect = true;
-    return base::WrapUnique(
-        new ash::mus::WindowManagerApplication(show_primary_host_on_connect));
-  }
-  if (service_name == "accessibility_autoclick")
-    return base::MakeUnique<ash::autoclick::AutoclickApplication>();
-  if (service_name == "touch_hud")
-    return base::MakeUnique<ash::touch_hud::TouchHudApplication>();
-#endif  // defined(OS_CHROMEOS)
-  if (service_name == mash::catalog_viewer::mojom::kServiceName)
-    return base::MakeUnique<mash::catalog_viewer::CatalogViewer>();
-  if (service_name == mash::session::mojom::kServiceName)
-    return base::MakeUnique<mash::session::Session>();
-  if (service_name == ui::mojom::kServiceName)
-    return base::MakeUnique<ui::Service>();
-  if (service_name == mash::quick_launch::mojom::kServiceName)
-    return base::MakeUnique<mash::quick_launch::QuickLaunch>();
-  if (service_name == mash::task_viewer::mojom::kServiceName)
-    return base::MakeUnique<mash::task_viewer::TaskViewer>();
-  if (service_name == "test_ime_driver")
-    return base::MakeUnique<ui::test::TestIMEApplication>();
-#if defined(OS_LINUX) && !defined(OS_ANDROID)
-  if (service_name == "font_service")
-    return base::MakeUnique<font_service::FontServiceApp>();
-#endif  // defined(OS_LINUX) && !defined(OS_ANDROID)
-
-  return nullptr;
-}
diff --git a/chrome/app/mash/embedded_services.h b/chrome/app/mash/embedded_services.h
deleted file mode 100644
index 6eba944..0000000
--- a/chrome/app/mash/embedded_services.h
+++ /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.
-
-#ifndef CHROME_APP_MASH_EMBEDDED_SERVICES_H_
-#define CHROME_APP_MASH_EMBEDDED_SERVICES_H_
-
-#include <memory>
-
-#include "services/service_manager/public/cpp/service.h"
-
-// Starts one of Mash's embedded services.
-std::unique_ptr<service_manager::Service> CreateEmbeddedMashService(
-    const std::string& service_name);
-
-#endif  // CHROME_APP_MASH_EMBEDDED_SERVICES_H_
diff --git a/chrome/app/md_extensions_strings.grdp b/chrome/app/md_extensions_strings.grdp
index ecfbe0a..c269a55 100644
--- a/chrome/app/md_extensions_strings.grdp
+++ b/chrome/app/md_extensions_strings.grdp
@@ -166,4 +166,37 @@
   <message name="IDS_MD_EXTENSIONS_TYPE_A_SHORTCUT" desc="The prompt to the user to enter a keyboard shortcut in order to assign it to an extension.">
     Type a shortcut
   </message>
+<if expr="chromeos">
+  <!-- Extensions Kiosk apps -->
+  <message name="IDS_MD_EXTENSIONS_MANAGE_KIOSK_APP" desc="Label of the button to bring up kiosk management overlay on chrome extensions page.">
+    Manage kiosk applications
+  </message>
+  <message name="IDS_MD_EXTENSIONS_KIOSK_ADD_APP" desc="Label above the application id text input in the kiosk settings overlay.">
+    Add kiosk application
+  </message>
+  <message name="IDS_MD_EXTENSIONS_KIOSK_ADD_APP_HINT" desc="Placeholder hint in  the application id text input in the kiosk settings overlay.">
+    Enter application ID or webstore URL
+  </message>
+  <message name="IDS_MD_EXTENSIONS_KIOSK_ENABLE_AUTO_LAUNCH" desc="Text for a button that enables an application to auto launch on startup in the kiosk settings overlay.">
+    Set to auto-launch
+  </message>
+  <message name="IDS_MD_EXTENSIONS_KIOSK_DISABLE_AUTO_LAUNCH" desc="Text for a button that disables an application to auto launch on startup in the kiosk settings overlay.">
+    Disable auto-launch
+  </message>
+  <message name="IDS_MD_EXTENSIONS_KIOSK_AUTO_LAUNCH" desc="Text shows besides an application that is set to auto launch on start up in the kiosk settings overlay.">
+    (auto-launched)
+  </message>
+  <message name="IDS_MD_EXTENSIONS_KIOSK_INVALID_APP" desc="Text shows besides an application that is not valid in the kiosk settings overlay.">
+    Invalid application
+  </message>
+  <message name="IDS_MD_EXTENSIONS_KIOSK_DISABLE_BAILOUT_SHORTCUT_LABEL" desc="Label text for a checkbox to disable kiosk application launch bail out shortcut.">
+    Permanently keep this device in kiosk mode
+  </message>
+  <message name="IDS_MD_EXTENSIONS_KIOSK_DISABLE_BAILOUT_SHORTCUT_WARNING_TITLE" desc="Bold text of the warning dialog for disabling kiosk application launch bail out shortcut.">
+    Are you sure you want to permanently keep this device in kiosk mode?
+  </message>
+  <message name="IDS_MD_EXTENSIONS_KIOSK_DISABLE_BAILOUT_SHORTCUT_WARNING_BODY" desc="Warning text of disabling kiosk application launch bail out shortcut.">
+    The only way to undo this is to re-install <ph name="IDS_SHORT_PRODUCT_OS_NAME">$1<ex>Chrome OS</ex></ph>
+  </message>
+</if>
 </grit-part>
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index a293f61..56ca30e4 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -2435,6 +2435,9 @@
   <message name="IDS_SETTINGS_SITE_SETTINGS_BLOCK" desc="Label for add block sites in site settings.">
     Block
   </message>
+  <message name="IDS_SETTINGS_SITE_SETTINGS_BLOCK_SOUND" desc="Label for add muted sites in site settings.">
+    Muted
+  </message>
   <message name="IDS_SETTINGS_SITE_SETTINGS_SESSION_ONLY" desc="Label for sites in site settings allowing cookies for the current session only.">
     Clear on exit
   </message>
@@ -2852,14 +2855,14 @@
     <message name="IDS_SETTINGS_PHOTO_DISCARD_ACCESSIBLE_TEXT" desc="The accessible message to speak to announce that a photo was discarded.">
       Photo was discarded
     </message>
-    <message name="IDS_SETTINGS_CHANGE_PICTURE_FLIP_PHOTO" desc="The text on the button to flip the camera image horizontally.">
-      Flip camera image horizontally
+    <message name="IDS_SETTINGS_CHANGE_PICTURE_SWITCH_MODE" desc="The text on the button to switch the mode of the camera between photo and video.">
+    Switch camera mode
     </message>
-    <message name="IDS_SETTINGS_PHOTO_FLIP_ACCESSIBLE_TEXT" desc="The accessible message to speak to announce horizontal flip of camera image.">
-      Photo flipped
+    <message name="IDS_SETTINGS_PHOTO_MODE_ACCESSIBLE_TEXT" desc="The accessible message to speak to announce a switch to photo mode for camera.">
+      Photo mode entered
     </message>
-    <message name="IDS_SETTINGS_PHOTO_FLIPBACK_ACCESSIBLE_TEXT" desc="The accessible message to speak to announce horizontal back-flip of camera image to not-flipped state.">
-      Photo flipped back
+    <message name="IDS_SETTINGS_VIDEO_MODE_ACCESSIBLE_TEXT" desc="The accessible message to speak to announce a switch to video mode for camera.">
+      Video mode entered
     </message>
     <message name="IDS_SETTINGS_CHANGE_PICTURE_PREVIEW_ALT" desc="Alt text for the big preview of user image.">
       User image preview
diff --git a/chrome/app/theme/default_100_percent/cros/mirror_flip.png b/chrome/app/theme/default_100_percent/cros/mirror_flip.png
deleted file mode 100644
index 261b67d7..0000000
--- a/chrome/app/theme/default_100_percent/cros/mirror_flip.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/cros/mirror_flip.png b/chrome/app/theme/default_200_percent/cros/mirror_flip.png
deleted file mode 100644
index a8a93380..0000000
--- a/chrome/app/theme/default_200_percent/cros/mirror_flip.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index 4d27cfbb..c821c3b 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -243,7 +243,6 @@
       <structure type="chrome_scaled_image" name="IDR_MAXIMIZE_BUTTON_MASK" file="common/maximize_button_mask.png" />
       <structure type="chrome_scaled_image" name="IDR_MINIMIZE_BUTTON_MASK" file="common/minimize_button_mask.png" />
       <if expr="chromeos">
-        <structure type="chrome_scaled_image" name="IDR_MIRROR_FLIP" file="cros/mirror_flip.png" />
         <structure type="chrome_scaled_image" name="IDR_NETWORK_ADD_CONNECTION" file="cros/network_add_connection.png" />
       </if>
       <if expr="chromeos">
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 6418f22..4e8b60b6 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -9,6 +9,7 @@
 import("//build/split_static_library.gni")
 import("//chrome/common/features.gni")
 import("//components/feature_engagement/features.gni")
+import("//components/nacl/features.gni")
 import("//components/offline_pages/features/features.gni")
 import("//components/os_crypt/features.gni")
 import("//components/signin/features.gni")
@@ -101,6 +102,8 @@
     "background_fetch/background_fetch_delegate_factory.h",
     "background_fetch/background_fetch_delegate_impl.cc",
     "background_fetch/background_fetch_delegate_impl.h",
+    "background_fetch/background_fetch_download_client.cc",
+    "background_fetch/background_fetch_download_client.h",
     "background_sync/background_sync_controller_factory.cc",
     "background_sync/background_sync_controller_factory.h",
     "background_sync/background_sync_controller_impl.cc",
@@ -717,8 +720,6 @@
     "mod_pagespeed/mod_pagespeed_metrics.cc",
     "mod_pagespeed/mod_pagespeed_metrics.h",
     "native_window_notification_source.h",
-    "net/async_dns_field_trial.cc",
-    "net/async_dns_field_trial.h",
     "net/chrome_cookie_notification_details.h",
     "net/chrome_extensions_network_delegate.cc",
     "net/chrome_extensions_network_delegate.h",
@@ -3324,10 +3325,10 @@
       "metrics/tab_usage_recorder.h",
       "net/firefox_proxy_settings.cc",
       "net/firefox_proxy_settings.h",
-      "notifications/application_notifier_source.cc",
-      "notifications/application_notifier_source.h",
-      "notifications/arc_application_notifier_source_chromeos.cc",
-      "notifications/arc_application_notifier_source_chromeos.h",
+      "notifications/arc_application_notifier_controller_chromeos.cc",
+      "notifications/arc_application_notifier_controller_chromeos.h",
+      "notifications/extension_notifier_controller.cc",
+      "notifications/extension_notifier_controller.h",
       "notifications/message_center_notification_manager.cc",
       "notifications/message_center_notification_manager.h",
       "notifications/message_center_settings_controller.cc",
@@ -3337,13 +3338,13 @@
       "notifications/notification_system_observer.cc",
       "notifications/notification_system_observer.h",
       "notifications/notification_ui_manager_desktop.cc",
-      "notifications/notifier_source.h",
+      "notifications/notifier_controller.h",
       "notifications/profile_notification.cc",
       "notifications/profile_notification.h",
-      "notifications/system_component_notifier_source_chromeos.cc",
-      "notifications/system_component_notifier_source_chromeos.h",
-      "notifications/web_page_notifier_source.cc",
-      "notifications/web_page_notifier_source.h",
+      "notifications/system_component_notifier_controller_chromeos.cc",
+      "notifications/system_component_notifier_controller_chromeos.h",
+      "notifications/web_page_notifier_controller.cc",
+      "notifications/web_page_notifier_controller.h",
       "obsolete_system/obsolete_system.h",
       "obsolete_system/obsolete_system_linux.cc",
       "obsolete_system/obsolete_system_mac.cc",
@@ -3988,6 +3989,28 @@
       "password_manager/password_store_signin_notifier_impl.h",
     ]
   }
+
+  if (enable_package_mash_services) {
+    sources += [
+      "mash_service_registry.cc",
+      "mash_service_registry.h",
+    ]
+
+    deps += [
+      "//mash/quick_launch/public/interfaces:constants",
+      "//services/ui/public/interfaces",
+    ]
+
+    if (is_linux && !is_android) {
+      deps += [
+        "//components/font_service:lib",
+        "//components/font_service/public/interfaces",
+      ]
+    }
+    if (is_chromeos) {
+      deps += [ "//ash/public/cpp:ash_public_cpp" ]
+    }
+  }
 }
 
 if (is_android) {
@@ -4028,6 +4051,7 @@
       "../android/java/src/org/chromium/chrome/browser/autofill/PhoneNumberUtil.java",
       "../android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java",
       "../android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java",
+      "../android/java/src/org/chromium/chrome/browser/browserservices/OriginVerifier.java",
       "../android/java/src/org/chromium/chrome/browser/browsing_data/UrlFilterBridge.java",
       "../android/java/src/org/chromium/chrome/browser/childaccounts/ChildAccountFeedbackReporter.java",
       "../android/java/src/org/chromium/chrome/browser/childaccounts/ChildAccountService.java",
@@ -4053,7 +4077,6 @@
       "../android/java/src/org/chromium/chrome/browser/cookies/CookiesFetcher.java",
       "../android/java/src/org/chromium/chrome/browser/crash/MinidumpUploadService.java",
       "../android/java/src/org/chromium/chrome/browser/customtabs/LoadingPredictor.java",
-      "../android/java/src/org/chromium/chrome/browser/customtabs/OriginVerifier.java",
       "../android/java/src/org/chromium/chrome/browser/database/SQLiteCursor.java",
       "../android/java/src/org/chromium/chrome/browser/datausage/DataUseTabUIManager.java",
       "../android/java/src/org/chromium/chrome/browser/datausage/ExternalDataUseObserver.java",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index eb4ec28..5089027 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -94,6 +94,8 @@
   # Should be removed once the actual network service ships.
   "+content/public/network",
 
+  "+mash/quick_launch/public/interfaces",
+
   # Other libraries.
   "+libxml",
   "+third_party/google_toolbox_for_mac/src",
@@ -179,5 +181,8 @@
   "fullscreen_chromeos\.cc": [
     "+ash/root_window_controller.h",
     "+ash/shell.h",
+  ],
+  "mash_service_registry.cc": [
+    "+mash/quick_launch/quick_launch.h",
   ]
 }
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 334d6a79b..ddd41a0 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -84,6 +84,7 @@
 #include "components/translate/core/browser/translate_infobar_delegate.h"
 #include "components/translate/core/browser/translate_manager.h"
 #include "components/translate/core/browser/translate_prefs.h"
+#include "components/translate/core/browser/translate_ranker_impl.h"
 #include "components/version_info/version_info.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
@@ -1910,6 +1911,10 @@
     {"translate-lang-by-ulp", flag_descriptions::kTranslateLanguageByUlpName,
      flag_descriptions::kTranslateLanguageByUlpDescription, kOsAll,
      FEATURE_VALUE_TYPE(translate::kTranslateLanguageByULP)},
+    {"translate-ranker-enforcement",
+     flag_descriptions::kTranslateRankerEnforcementName,
+     flag_descriptions::kTranslateRankerEnforcementDescription, kOsAll,
+     FEATURE_VALUE_TYPE(translate::kTranslateRankerEnforcement)},
 #if BUILDFLAG(ENABLE_NATIVE_NOTIFICATIONS)
     {"enable-native-notifications",
      flag_descriptions::kNotificationsNativeFlagName,
@@ -1931,6 +1936,9 @@
     {"enable-chrome-home", flag_descriptions::kChromeHomeName,
      flag_descriptions::kChromeHomeDescription, kOsAndroid,
      FEATURE_VALUE_TYPE(chrome::android::kChromeHomeFeature)},
+    {"always-show-chrome-home-promo", flag_descriptions::kChromeHomePromoName,
+     flag_descriptions::kChromeHomePromoDescription, kOsAndroid,
+     FEATURE_VALUE_TYPE(chrome::android::kChromeHomePromo)},
     {"enable-chrome-home-doodle", flag_descriptions::kChromeHomeDoodleName,
      flag_descriptions::kChromeHomeDoodleDescription, kOsAndroid,
      FEATURE_VALUE_TYPE(chrome::android::kChromeHomeDoodle)},
@@ -2563,11 +2571,6 @@
      flag_descriptions::kEnableContentSuggestionsSettingsDescription,
      kOsAndroid,
      FEATURE_VALUE_TYPE(chrome::android::kContentSuggestionsSettings)},
-    {"enable-content-suggestions-show-summary",
-     flag_descriptions::kEnableContentSuggestionsShowSummaryName,
-     flag_descriptions::kEnableContentSuggestionsShowSummaryDescription,
-     kOsAndroid,
-     FEATURE_VALUE_TYPE(chrome::android::kContentSuggestionsShowSummary)},
     {"enable-favicons-from-web-manifest",
      flag_descriptions::kEnableFaviconsFromWebManifestName,
      flag_descriptions::kEnableFaviconsFromWebManifestDescription, kOsAndroid,
@@ -3180,12 +3183,6 @@
      flag_descriptions::kEnableOutOfProcessHeapProfilingDescription, kOsAll,
      MULTI_VALUE_TYPE(kEnableOutOfProcessHeapProfilingChoices)},
 
-#if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX)
-    {"show-cert-link", flag_descriptions::kShowCertLinkOnPageInfoName,
-     flag_descriptions::kShowCertLinkOnPageInfoDescription, kOsDesktop,
-     SINGLE_VALUE_TYPE(switches::kShowCertLink)},
-#endif
-
     {"omnibox-ui-elide-suggestion-url-after-host",
      flag_descriptions::kOmniboxUIElideSuggestionUrlAfterHostName,
      flag_descriptions::kOmniboxUIElideSuggestionUrlAfterHostDescription,
@@ -3519,6 +3516,12 @@
                                     kSpeculativePreconnectFeatureVariations,
                                     "SpeculativePreconnectValidation")},
 
+#if defined(OS_ANDROID)
+    {"enable-async-dns", flag_descriptions::kAsyncDnsName,
+     flag_descriptions::kAsyncDnsDescription, kOsAndroid,
+     FEATURE_VALUE_TYPE(features::kAsyncDns)},
+#endif  // defined(OS_ANDROID)
+
     // NOTE: Adding new command-line switches requires adding corresponding
     // entries to enum "LoginCustomFlags" in histograms/enums.xml. See note in
     // enums.xml and don't forget to run AboutFlagsHistogramTest unit test.
diff --git a/chrome/browser/android/banners/app_banner_manager_android.cc b/chrome/browser/android/banners/app_banner_manager_android.cc
index a4802bb..9938b09 100644
--- a/chrome/browser/android/banners/app_banner_manager_android.cc
+++ b/chrome/browser/android/banners/app_banner_manager_android.cc
@@ -174,6 +174,8 @@
     for (const auto& application : manifest_.related_applications) {
       std::string platform = base::UTF16ToUTF8(application.platform.string());
       std::string id = base::UTF16ToUTF8(application.id.string());
+      // TODO(crbug/770050): convert CanHandleNonWebApp() to return an
+      // InstallableStatusCode and pass it to StopWithCode here.
       if (CanHandleNonWebApp(platform, application.url, id))
         return;
     }
@@ -182,8 +184,7 @@
 
   if (can_install_webapk_) {
     if (!AreWebManifestUrlsWebApkCompatible(manifest_)) {
-      ReportStatus(web_contents(), URL_NOT_SUPPORTED_FOR_WEBAPK);
-      Stop();
+      StopWithCode(URL_NOT_SUPPORTED_FOR_WEBAPK);
       return;
     }
   }
@@ -206,8 +207,7 @@
 
 void AppBannerManagerAndroid::OnAppIconFetched(const SkBitmap& bitmap) {
   if (bitmap.drawsNothing()) {
-    ReportStatus(web_contents(), NO_ICON_AVAILABLE);
-    Stop();
+    StopWithCode(NO_ICON_AVAILABLE);
     return;
   }
 
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc
index f4680f4..9c7edea 100644
--- a/chrome/browser/android/chrome_feature_list.cc
+++ b/chrome/browser/android/chrome_feature_list.cc
@@ -61,11 +61,11 @@
     &kChromeHomeDestroySuggestions,
     &kChromeHomeDoodle,
     &kChromeHomeExpandButton,
+    &kChromeHomePromo,
     &kChromeHomeSwipeLogic,
     &kContentSuggestionsLargeThumbnail,
     &kContentSuggestionsScrollToLoad,
     &kContentSuggestionsSettings,
-    &kContentSuggestionsShowSummary,
     &kContentSuggestionsThumbnailDominantColor,
     &kContentSuggestionsVideoOverlay,
     &kContextualSearchSingleActions,
@@ -167,11 +167,14 @@
     "ChromeHomeDestroySuggestions", base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kChromeHomeDoodle{"ChromeHomeDoodle",
-                                      base::FEATURE_DISABLED_BY_DEFAULT};
+                                      base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kChromeHomeExpandButton{"ChromeHomeExpandButton",
                                             base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kChromeHomePromo{"ChromeHomePromo",
+                                     base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kChromeHomeSwipeLogic{"ChromeHomeSwipeLogic",
                                           base::FEATURE_DISABLED_BY_DEFAULT};
 
@@ -184,9 +187,6 @@
 const base::Feature kContentSuggestionsSettings{
     "ContentSuggestionsSettings", base::FEATURE_ENABLED_BY_DEFAULT};
 
-const base::Feature kContentSuggestionsShowSummary{
-    "ContentSuggestionsShowSummary", base::FEATURE_DISABLED_BY_DEFAULT};
-
 const base::Feature kContentSuggestionsThumbnailDominantColor{
     "ContentSuggestionsThumbnailDominantColor",
     base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/chrome/browser/android/chrome_feature_list.h b/chrome/browser/android/chrome_feature_list.h
index 8148983..4a1fdfa7 100644
--- a/chrome/browser/android/chrome_feature_list.h
+++ b/chrome/browser/android/chrome_feature_list.h
@@ -25,11 +25,11 @@
 extern const base::Feature kChromeHomeDestroySuggestions;
 extern const base::Feature kChromeHomeDoodle;
 extern const base::Feature kChromeHomeExpandButton;
+extern const base::Feature kChromeHomePromo;
 extern const base::Feature kChromeHomeSwipeLogic;
 extern const base::Feature kContentSuggestionsLargeThumbnail;
 extern const base::Feature kContentSuggestionsScrollToLoad;
 extern const base::Feature kContentSuggestionsSettings;
-extern const base::Feature kContentSuggestionsShowSummary;
 extern const base::Feature kContentSuggestionsThumbnailDominantColor;
 extern const base::Feature kContentSuggestionsVideoOverlay;
 extern const base::Feature kContextualSearchSingleActions;
diff --git a/chrome/browser/android/ntp/most_visited_sites_bridge.cc b/chrome/browser/android/ntp/most_visited_sites_bridge.cc
index e953e53d..32e3fe2 100644
--- a/chrome/browser/android/ntp/most_visited_sites_bridge.cc
+++ b/chrome/browser/android/ntp/most_visited_sites_bridge.cc
@@ -41,6 +41,7 @@
 using ntp_tiles::MostVisitedSites;
 using ntp_tiles::NTPTilesVector;
 using ntp_tiles::SectionType;
+using ntp_tiles::TileTitleSource;
 using ntp_tiles::TileSource;
 using ntp_tiles::TileVisualType;
 
@@ -160,6 +161,7 @@
   std::vector<base::string16> titles;
   std::vector<std::string> urls;
   std::vector<std::string> whitelist_icons;
+  std::vector<int> title_sources;
   std::vector<int> sources;
   std::vector<int> section_types;
   for (const auto& section : sections) {
@@ -170,13 +172,15 @@
       titles.emplace_back(tile.title);
       urls.emplace_back(tile.url.spec());
       whitelist_icons.emplace_back(tile.whitelist_icon_path.value());
+      title_sources.emplace_back(static_cast<int>(tile.title_source));
       sources.emplace_back(static_cast<int>(tile.source));
     }
   }
   Java_MostVisitedSitesBridge_onURLsAvailable(
       env, observer_, ToJavaArrayOfStrings(env, titles),
       ToJavaArrayOfStrings(env, urls), ToJavaIntArray(env, section_types),
-      ToJavaArrayOfStrings(env, whitelist_icons), ToJavaIntArray(env, sources));
+      ToJavaArrayOfStrings(env, whitelist_icons),
+      ToJavaIntArray(env, title_sources), ToJavaIntArray(env, sources));
 }
 
 void MostVisitedSitesBridge::JavaObserver::OnIconMadeAvailable(
@@ -246,13 +250,16 @@
     const JavaParamRef<jobject>& obj,
     jint jindex,
     jint jtype,
+    jint jtitle_source,
     jint jsource,
     const JavaParamRef<jstring>& jurl) {
   GURL url(ConvertJavaStringToUTF8(env, jurl));
+  TileTitleSource title_source = static_cast<TileTitleSource>(jtitle_source);
   TileSource source = static_cast<TileSource>(jsource);
   TileVisualType type = static_cast<TileVisualType>(jtype);
 
-  ntp_tiles::metrics::RecordTileImpression(jindex, source, type, url,
+  ntp_tiles::metrics::RecordTileImpression(jindex, title_source, source, type,
+                                           url,
                                            g_browser_process->rappor_service());
 }
 
@@ -261,9 +268,11 @@
     const JavaParamRef<jobject>& obj,
     jint index,
     jint tile_type,
+    jint title_source,
     jint source) {
-  ntp_tiles::metrics::RecordTileClick(index, static_cast<TileSource>(source),
-                                      static_cast<TileVisualType>(tile_type));
+  ntp_tiles::metrics::RecordTileClick(
+      index, static_cast<TileTitleSource>(title_source),
+      static_cast<TileSource>(source), static_cast<TileVisualType>(tile_type));
 }
 
 static jlong Init(JNIEnv* env,
diff --git a/chrome/browser/android/ntp/most_visited_sites_bridge.h b/chrome/browser/android/ntp/most_visited_sites_bridge.h
index 8458c79..ea677f5 100644
--- a/chrome/browser/android/ntp/most_visited_sites_bridge.h
+++ b/chrome/browser/android/ntp/most_visited_sites_bridge.h
@@ -49,6 +49,7 @@
                             const base::android::JavaParamRef<jobject>& obj,
                             jint jindex,
                             jint jtype,
+                            jint jtitle_source,
                             jint jsource,
                             const base::android::JavaParamRef<jstring>& jurl);
   void RecordOpenedMostVisitedItem(
@@ -56,6 +57,7 @@
       const base::android::JavaParamRef<jobject>& obj,
       jint index,
       jint tile_type,
+      jint title_source,
       jint source);
 
  private:
diff --git a/chrome/browser/android/ntp/ntp_snippets_bridge.cc b/chrome/browser/android/ntp/ntp_snippets_bridge.cc
index 31f7967..cdf313f 100644
--- a/chrome/browser/android/ntp/ntp_snippets_bridge.cc
+++ b/chrome/browser/android/ntp/ntp_snippets_bridge.cc
@@ -68,7 +68,6 @@
             ConvertUTF8ToJavaString(env, suggestion.id().id_within_category()),
             ConvertUTF16ToJavaString(env, suggestion.title()),
             ConvertUTF16ToJavaString(env, suggestion.publisher_name()),
-            ConvertUTF16ToJavaString(env, suggestion.snippet_text()),
             ConvertUTF8ToJavaString(env, suggestion.url().spec()),
             suggestion.publish_date().ToJavaTime(), suggestion.score(),
             suggestion.fetch_date().ToJavaTime(),
diff --git a/chrome/browser/android/tab_web_contents_delegate_android.cc b/chrome/browser/android/tab_web_contents_delegate_android.cc
index 822f65f..0bdc5d9 100644
--- a/chrome/browser/android/tab_web_contents_delegate_android.cc
+++ b/chrome/browser/android/tab_web_contents_delegate_android.cc
@@ -39,6 +39,7 @@
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
@@ -440,8 +441,8 @@
   InfoBarService* infobar_service =
       InfoBarService::FromWebContents(web_contents);
   DCHECK(!FindHungRendererInfoBar(infobar_service));
-  HungRendererInfoBarDelegate::Create(infobar_service,
-                                      web_contents->GetRenderProcessHost());
+  HungRendererInfoBarDelegate::Create(
+      infobar_service, web_contents->GetMainFrame()->GetProcess());
 }
 
 void OnRendererResponsive(JNIEnv* env,
diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.cc b/chrome/browser/android/vr_shell/vr_shell_gl.cc
index d604420..f7b0ad5 100644
--- a/chrome/browser/android/vr_shell/vr_shell_gl.cc
+++ b/chrome/browser/android/vr_shell/vr_shell_gl.cc
@@ -93,6 +93,8 @@
 
 static constexpr int kWebVrInitialFrameTimeoutSeconds = 5;
 
+static constexpr gfx::PointF kOutOfBoundsPoint = {-0.5f, -0.5f};
+
 // Provides the direction the head is looking towards as a 3x1 unit vector.
 gfx::Vector3dF GetForwardVector(const gfx::Transform& head_pose) {
   // Same as multiplying the inverse of the rotation component of the matrix by
@@ -180,7 +182,6 @@
                      bool reprojected_rendering,
                      bool daydream_support)
     : ui_(base::MakeUnique<vr::Ui>(ui_host_interface, this, ui_initial_state)),
-      ui_scene_manager_(ui_->ui()),
       surfaceless_rendering_(reprojected_rendering),
       daydream_support_(daydream_support),
       task_runner_(base::ThreadTaskRunnerHandle::Get()),
@@ -386,7 +387,7 @@
   TRACE_EVENT1("gpu", "VrShellGl::OnWebVRFrameAvailable", "frame", frame_index);
   pending_frames_.pop();
 
-  ui_scene_manager_->OnWebVrFrameAvailable();
+  ui_->OnWebVrFrameAvailable();
 
   DrawFrame(frame_index);
   if (web_vr_mode_) {
@@ -413,7 +414,7 @@
 }
 
 void VrShellGl::OnWebVrFrameTimedOut() {
-  ui_scene_manager_->OnWebVrTimedOut();
+  ui_->OnWebVrTimedOut();
 }
 
 void VrShellGl::GvrInit(gvr_context* gvr_api) {
@@ -621,8 +622,13 @@
 }
 
 void VrShellGl::OnContentLeave() {
+  // Note that we send an out of bounds mouse leave event. With blink feature
+  // UpdateHoverPostLayout turned on, a MouseMove event will dispatched post a
+  // Layout. Sending a mouse leave event at 0,0 will result continuous
+  // MouseMove events sent to the content if the content keeps relayout itself.
+  // See crbug.com/762573 for details.
   SendGestureToContent(
-      MakeMouseEvent(blink::WebInputEvent::kMouseLeave, gfx::PointF()));
+      MakeMouseEvent(blink::WebInputEvent::kMouseLeave, kOutOfBoundsPoint));
 }
 
 void VrShellGl::OnContentMove(const gfx::PointF& normalized_hit_point) {
@@ -717,15 +723,14 @@
         // Post a task, rather than calling the UI directly, so as not to modify
         // UI state in the midst of frame rendering.
         base::ThreadTaskRunnerHandle::Get()->PostTask(
-            FROM_HERE,
-            base::Bind(&vr::UiInterface::OnAppButtonGesturePerformed,
-                       base::Unretained(ui_scene_manager_), direction));
+            FROM_HERE, base::Bind(&vr::UiInterface::OnAppButtonGesturePerformed,
+                                  base::Unretained(ui_.get()), direction));
       }
     }
     if (direction == vr::UiInterface::NONE)
       base::ThreadTaskRunnerHandle::Get()->PostTask(
           FROM_HERE, base::Bind(&vr::UiInterface::OnAppButtonClicked,
-                                base::Unretained(ui_scene_manager_)));
+                                base::Unretained(ui_.get())));
   }
 }
 
@@ -842,8 +847,8 @@
   }
 
   // Update the render position of all UI elements (including desktop).
-  ui_scene_manager_->scene()->OnBeginFrame(
-      current_time, GetForwardVector(render_info_primary_.head_pose));
+  ui_->scene()->OnBeginFrame(current_time,
+                             GetForwardVector(render_info_primary_.head_pose));
 
   // WebVR handles controller input in OnVsync.
   if (!ShouldDrawWebVr())
@@ -852,15 +857,14 @@
   // Ensure that all elements are ready before drawing. Eg., elements may have
   // been dirtied due to animation on input processing and need to regenerate
   // textures.
-  ui_scene_manager_->scene()->PrepareToDraw();
+  ui_->scene()->PrepareToDraw();
 
   UpdateEyeInfos(render_info_primary_.head_pose, kViewportListPrimaryOffset,
                  render_info_primary_.surface_texture_size,
                  &render_info_primary_);
 
   // Measure projected content size and bubble up if delta exceeds threshold.
-  ui_scene_manager_->OnProjMatrixChanged(
-      render_info_primary_.left_eye_info.proj_matrix);
+  ui_->OnProjMatrixChanged(render_info_primary_.left_eye_info.proj_matrix);
 
   // At this point, we draw non-WebVR content that could, potentially, fill the
   // viewport.  NB: this is not just 2d browsing stuff, we may have a splash
@@ -870,8 +874,7 @@
 
   std::vector<const vr::UiElement*> overlay_elements;
   if (ShouldDrawWebVr()) {
-    overlay_elements =
-        ui_scene_manager_->scene()->GetVisibleWebVrOverlayForegroundElements();
+    overlay_elements = ui_->scene()->GetVisibleWebVrOverlayForegroundElements();
   }
 
   if (!overlay_elements.empty() && ShouldDrawWebVr()) {
@@ -1031,7 +1034,7 @@
 }
 
 bool VrShellGl::ShouldDrawWebVr() {
-  return web_vr_mode_ && ui_scene_manager_->ShouldRenderWebVr();
+  return web_vr_mode_ && ui_->ShouldRenderWebVr();
 }
 
 void VrShellGl::DrawWebVr() {
diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.h b/chrome/browser/android/vr_shell/vr_shell_gl.h
index da37485..ebc9832b 100644
--- a/chrome/browser/android/vr_shell/vr_shell_gl.h
+++ b/chrome/browser/android/vr_shell/vr_shell_gl.h
@@ -53,7 +53,6 @@
 class SlidingAverage;
 class Ui;
 class UiBrowserInterface;
-class UiInterface;
 struct UiInitialState;
 }  // namespace vr
 
@@ -236,7 +235,6 @@
   std::vector<gfx::Transform> webvr_head_pose_;
 
   std::unique_ptr<vr::Ui> ui_;
-  vr::UiInterface* ui_scene_manager_;
 
   bool web_vr_mode_;
   bool ready_to_draw_ = false;
diff --git a/chrome/browser/apps/guest_view/app_view_browsertest.cc b/chrome/browser/apps/guest_view/app_view_browsertest.cc
index 8aabb085..ecf0bcc 100644
--- a/chrome/browser/apps/guest_view/app_view_browsertest.cc
+++ b/chrome/browser/apps/guest_view/app_view_browsertest.cc
@@ -12,6 +12,7 @@
 #include "components/guest_view/browser/guest_view_manager_factory.h"
 #include "components/guest_view/browser/test_guest_view_manager.h"
 #include "content/public/browser/notification_service.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_process_host_observer.h"
 #include "content/public/common/content_features.h"
@@ -222,7 +223,8 @@
       extensions::AppWindowRegistry::Get(browser()->profile())
           ->GetCurrentAppWindowForApp(bad_app->id())
           ->web_contents()
-          ->GetRenderProcessHost();
+          ->GetMainFrame()
+          ->GetProcess();
 
   // Monitor |bad_app|'s RenderProcessHost for its exiting.
   RenderProcessHostObserverForExit exit_observer(bad_app_render_process_host);
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc
index ead3778..52a120c 100644
--- a/chrome/browser/apps/guest_view/web_view_browsertest.cc
+++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -55,6 +55,7 @@
 #include "content/public/browser/gpu_data_manager.h"
 #include "content/public/browser/interstitial_page.h"
 #include "content/public/browser/notification_service.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/render_widget_host_view.h"
@@ -680,8 +681,10 @@
     guest_observer.Wait();
     content::Source<content::NavigationController> source =
         guest_observer.source();
-    EXPECT_TRUE(source->GetWebContents()->GetRenderProcessHost()->
-        IsForGuestsOnly());
+    EXPECT_TRUE(source->GetWebContents()
+                    ->GetMainFrame()
+                    ->GetProcess()
+                    ->IsForGuestsOnly());
 
     content::WebContents* guest_web_contents = source->GetWebContents();
     return guest_web_contents;
@@ -718,7 +721,8 @@
     // Wait for interstitial page to be shown in guest.
     content::WebContents* guest_web_contents =
         GetGuestViewManager()->WaitForSingleGuestCreated();
-    ASSERT_TRUE(guest_web_contents->GetRenderProcessHost()->IsForGuestsOnly());
+    ASSERT_TRUE(
+        guest_web_contents->GetMainFrame()->GetProcess()->IsForGuestsOnly());
     content::WaitForInterstitialAttach(guest_web_contents);
   }
 
@@ -1666,8 +1670,10 @@
 
   content::Source<content::NavigationController> source =
       guest_observer.source();
-  EXPECT_TRUE(source->GetWebContents()->GetRenderProcessHost()->
-      IsForGuestsOnly());
+  EXPECT_TRUE(source->GetWebContents()
+                  ->GetMainFrame()
+                  ->GetProcess()
+                  ->IsForGuestsOnly());
 
   ASSERT_TRUE(guest_loaded_listener.WaitUntilSatisfied());
 
@@ -2612,19 +2618,19 @@
   // 1. Guest requests a download that its embedder denies.
   EXPECT_TRUE(content::ExecuteScript(guest_web_contents,
                                      "startDownload('download-link-1')"));
-  mock_delegate->WaitForCanDownload(false); // Expect to not allow.
+  mock_delegate->WaitForCanDownload(false);  // Expect to not allow.
   mock_delegate->Reset();
 
   // 2. Guest requests a download that its embedder allows.
   EXPECT_TRUE(content::ExecuteScript(guest_web_contents,
                                      "startDownload('download-link-2')"));
-  mock_delegate->WaitForCanDownload(true); // Expect to allow.
+  mock_delegate->WaitForCanDownload(true);  // Expect to allow.
   mock_delegate->Reset();
 
   // 3. Guest requests a download that its embedder ignores, this implies deny.
   EXPECT_TRUE(content::ExecuteScript(guest_web_contents,
                                      "startDownload('download-link-3')"));
-  mock_delegate->WaitForCanDownload(false); // Expect to not allow.
+  mock_delegate->WaitForCanDownload(false);  // Expect to not allow.
   completion_observer->WaitForFinished();
 }
 
@@ -3231,7 +3237,7 @@
   Profile* profile = browser()->profile();
   int rules_registry_id =
       extensions::WebViewGuest::GetOrGenerateRulesRegistryID(
-          guest->owner_web_contents()->GetRenderProcessHost()->GetID(),
+          guest->owner_web_contents()->GetMainFrame()->GetProcess()->GetID(),
           guest->view_instance_id());
 
   extensions::RulesRegistryService* registry_service =
@@ -3246,7 +3252,7 @@
 
   // Kill the embedder's render process, so the webview will go as well.
   base::Process process = base::Process::DeprecatedGetProcessFromHandle(
-        embedder_web_contents->GetRenderProcessHost()->GetHandle());
+      embedder_web_contents->GetMainFrame()->GetProcess()->GetHandle());
   process.Terminate(0, false);
   observer->WaitForEmbedderRenderProcessTerminate();
 
@@ -3268,7 +3274,7 @@
       extensions::RulesRegistryService::Get(profile);
   int rules_registry_id =
       extensions::WebViewGuest::GetOrGenerateRulesRegistryID(
-          guest->owner_web_contents()->GetRenderProcessHost()->GetID(),
+          guest->owner_web_contents()->GetMainFrame()->GetProcess()->GetID(),
           guest->view_instance_id());
 
   // Get an existing registered rule for the guest.
@@ -3655,9 +3661,9 @@
   }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(WebViewGuestScrollTest);
-
   base::test::ScopedFeatureList scoped_feature_list_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebViewGuestScrollTest);
 };
 
 class WebViewGuestScrollTouchTest : public WebViewGuestScrollTest {
@@ -3866,7 +3872,7 @@
     gfx::Point point(10, 10);
     FocusChangeWaiter focus_waiter(guest_contents, false);
     SendRoutedTouchTapSequence(embedder_contents, point);
-    SendRoutedGestureTapSequence(embedder_contents,point);
+    SendRoutedGestureTapSequence(embedder_contents, point);
     focus_waiter.WaitForFocusChange();
     EXPECT_FALSE(IsWebContentsBrowserPluginFocused(guest_contents));
   }
diff --git a/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc b/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc
index ffc216b..0b06733 100644
--- a/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc
+++ b/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc
@@ -309,8 +309,10 @@
     guest_observer.Wait();
     content::Source<content::NavigationController> source =
         guest_observer.source();
-    EXPECT_TRUE(source->GetWebContents()->GetRenderProcessHost()->
-        IsForGuestsOnly());
+    EXPECT_TRUE(source->GetWebContents()
+                    ->GetMainFrame()
+                    ->GetProcess()
+                    ->IsForGuestsOnly());
 
     guest_web_contents_ = source->GetWebContents();
     embedder_web_contents_ =
@@ -1545,7 +1547,7 @@
       guest_web_contents()->GetRenderWidgetHostView();
   ASSERT_TRUE(guest_rwhv);
   std::string selected_text = base::UTF16ToUTF8(guest_rwhv->GetSelectedText());
-  ASSERT_TRUE(selected_text.size() >= 10u);
+  ASSERT_GE(selected_text.size(), 10u);
   ASSERT_EQ("AAAAAAAAAA", selected_text.substr(0, 10));
 }
 
@@ -1564,7 +1566,7 @@
 
   auto guest_message_filter =
       browser_client.GetTextInputClientMessageFilterForProcess(
-          guest_web_contents()->GetRenderProcessHost());
+          guest_web_contents()->GetMainFrame()->GetProcess());
   ASSERT_TRUE(guest_message_filter);
 
   // Lookup some string through context menu.
diff --git a/chrome/browser/autofill/android/personal_data_manager_android.cc b/chrome/browser/autofill/android/personal_data_manager_android.cc
index 463d1cf..f0f7bab 100644
--- a/chrome/browser/autofill/android/personal_data_manager_android.cc
+++ b/chrome/browser/autofill/android/personal_data_manager_android.cc
@@ -282,7 +282,7 @@
 };
 
 class AndroidAddressNormalizerDelegate
-    : public ::payments::AddressNormalizer::Delegate,
+    : public AddressNormalizer::Delegate,
       public base::SupportsWeakPtr<AndroidAddressNormalizerDelegate> {
  public:
   AndroidAddressNormalizerDelegate(
diff --git a/chrome/browser/autofill/android/personal_data_manager_android.h b/chrome/browser/autofill/android/personal_data_manager_android.h
index 136d325a..ae14a646f 100644
--- a/chrome/browser/autofill/android/personal_data_manager_android.h
+++ b/chrome/browser/autofill/android/personal_data_manager_android.h
@@ -12,9 +12,9 @@
 #include "base/android/scoped_java_ref.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "components/autofill/core/browser/address_normalizer_impl.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/core/browser/personal_data_manager_observer.h"
-#include "components/payments/core/address_normalizer_impl.h"
 #include "components/payments/core/subkey_requester.h"
 #include "third_party/libaddressinput/chromium/chrome_address_validator.h"
 
@@ -384,7 +384,7 @@
   PersonalDataManager* personal_data_manager_;
 
   // The address validator used to normalize addresses.
-  payments::AddressNormalizerImpl address_normalizer_;
+  AddressNormalizerImpl address_normalizer_;
 
   // Used for subkey request.
   payments::SubKeyRequester subkey_requester_;
diff --git a/chrome/browser/background_fetch/background_fetch_delegate_factory.cc b/chrome/browser/background_fetch/background_fetch_delegate_factory.cc
index 137e4b40..befa63c 100644
--- a/chrome/browser/background_fetch/background_fetch_delegate_factory.cc
+++ b/chrome/browser/background_fetch/background_fetch_delegate_factory.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/background_fetch/background_fetch_delegate_factory.h"
 
 #include "chrome/browser/background_fetch/background_fetch_delegate_impl.h"
+#include "chrome/browser/download/download_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "content/public/browser/background_fetch_delegate.h"
@@ -24,7 +25,9 @@
 BackgroundFetchDelegateFactory::BackgroundFetchDelegateFactory()
     : BrowserContextKeyedServiceFactory(
           "BackgroundFetchService",
-          BrowserContextDependencyManager::GetInstance()) {}
+          BrowserContextDependencyManager::GetInstance()) {
+  DependsOn(DownloadServiceFactory::GetInstance());
+}
 
 BackgroundFetchDelegateFactory::~BackgroundFetchDelegateFactory() {}
 
diff --git a/chrome/browser/background_fetch/background_fetch_delegate_impl.cc b/chrome/browser/background_fetch/background_fetch_delegate_impl.cc
index cbce1de1..7714df3 100644
--- a/chrome/browser/background_fetch/background_fetch_delegate_impl.cc
+++ b/chrome/browser/background_fetch/background_fetch_delegate_impl.cc
@@ -6,87 +6,20 @@
 
 #include <utility>
 
-#include "build/build_config.h"
+#include "base/bind.h"
+#include "base/guid.h"
+#include "base/strings/string_util.h"
+#include "chrome/browser/download/download_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "components/download/public/download_params.h"
+#include "components/download/public/download_service.h"
 #include "content/public/browser/background_fetch_response.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/browser/download_item.h"
-#include "content/public/browser/download_manager.h"
-#include "content/public/browser/download_url_parameters.h"
-#include "content/public/browser/storage_partition.h"
-
-#if defined(OS_ANDROID)
-#include "base/android/path_utils.h"
-#include "base/files/file_path.h"
-#endif
-
-namespace {
-
-class DownloadItemObserver : public content::DownloadItem::Observer {
- public:
-  explicit DownloadItemObserver(
-      base::WeakPtr<content::BackgroundFetchDelegate::Client> client)
-      : client_(client) {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  }
-
-  void OnDownloadUpdated(content::DownloadItem* download_item) override {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-    if (!client_.get()) {
-      download_item->RemoveObserver(this);
-      delete this;
-      return;
-    }
-
-    switch (download_item->GetState()) {
-      case content::DownloadItem::DownloadState::COMPLETE:
-        client_->OnDownloadComplete(
-            download_item->GetGuid(),
-            std::make_unique<content::BackgroundFetchResult>(
-                download_item->GetEndTime(), download_item->GetTargetFilePath(),
-                download_item->GetReceivedBytes()));
-        download_item->RemoveObserver(this);
-        delete this;
-        // Cannot access this after deleting itself so return immediately.
-        return;
-      case content::DownloadItem::DownloadState::CANCELLED:
-        // TODO(delphick): Consider how we want to handle cancelled downloads.
-        break;
-      case content::DownloadItem::DownloadState::INTERRUPTED:
-        // TODO(delphick): Just update the notification that it is paused.
-        break;
-      case content::DownloadItem::DownloadState::IN_PROGRESS:
-        // TODO(delphick): If the download was previously paused, this should
-        // now unpause the notification.
-        break;
-      case content::DownloadItem::DownloadState::MAX_DOWNLOAD_STATE:
-        NOTREACHED();
-        break;
-    }
-  }
-
-  void OnDownloadDestroyed(content::DownloadItem* download_item) override {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-    download_item->RemoveObserver(this);
-    delete this;
-  }
-
- private:
-  base::WeakPtr<content::BackgroundFetchDelegate::Client> client_;
-};
-
-#if defined(OS_ANDROID)
-// Prefix for files stored in the Chromium-internal download directory to
-// indicate files that were fetched through Background Fetch.
-const char kBackgroundFetchFilePrefix[] = "BGFetch-";
-#endif  // defined(OS_ANDROID)
-
-}  // namespace
 
 BackgroundFetchDelegateImpl::BackgroundFetchDelegateImpl(Profile* profile)
-    : profile_(profile), weak_ptr_factory_(this) {}
+    : download_service_(
+          DownloadServiceFactory::GetInstance()->GetForBrowserContext(profile)),
+      weak_ptr_factory_(this) {}
 
 BackgroundFetchDelegateImpl::~BackgroundFetchDelegateImpl() {}
 
@@ -106,63 +39,112 @@
     const net::HttpRequestHeaders& headers) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  content::DownloadManager* download_manager =
-      content::BrowserContext::GetDownloadManager(profile_);
-  DCHECK(download_manager);
+  download::DownloadParams params;
+  params.guid = guid;
+  params.client = download::DownloadClient::BACKGROUND_FETCH;
+  params.request_params.method = method;
+  params.request_params.url = url;
+  params.request_params.request_headers = headers;
+  params.callback = base::Bind(&BackgroundFetchDelegateImpl::OnDownloadReceived,
+                               weak_ptr_factory_.GetWeakPtr());
+  params.traffic_annotation =
+      net::MutableNetworkTrafficAnnotationTag(traffic_annotation);
 
-  content::StoragePartition* storage_partition =
-      content::BrowserContext::GetStoragePartitionForSite(profile_, url);
-
-  std::unique_ptr<content::DownloadUrlParameters> download_parameters(
-      std::make_unique<content::DownloadUrlParameters>(
-          url, storage_partition->GetURLRequestContext(), traffic_annotation));
-
-  net::HttpRequestHeaders::Iterator iterator(headers);
-  while (iterator.GetNext())
-    download_parameters->add_request_header(iterator.name(), iterator.value());
-
-  // TODO(peter): Background Fetch responses should not end up in the user's
-  // download folder on any platform. Find an appropriate solution for desktop
-  // too. The Android internal directory is not scoped to a profile.
-
-  download_parameters->set_transient(true);
-
-#if defined(OS_ANDROID)
-  base::FilePath download_directory;
-  if (base::android::GetDownloadInternalDirectory(&download_directory)) {
-    download_parameters->set_file_path(download_directory.Append(
-        std::string(kBackgroundFetchFilePrefix) + guid));
-  }
-#endif  // defined(OS_ANDROID)
-
-  download_parameters->set_callback(
-      base::Bind(&BackgroundFetchDelegateImpl::DidStartRequest, GetWeakPtr()));
-  download_parameters->set_guid(guid);
-
-  download_manager->DownloadUrl(std::move(download_parameters));
+  download_service_->StartDownload(params);
 }
 
-base::WeakPtr<BackgroundFetchDelegateImpl>
-BackgroundFetchDelegateImpl::GetWeakPtr() {
-  return weak_ptr_factory_.GetWeakPtr();
-}
-
-void BackgroundFetchDelegateImpl::DidStartRequest(
-    content::DownloadItem* download_item,
-    content::DownloadInterruptReason interrupt_reason) {
+void BackgroundFetchDelegateImpl::OnDownloadStarted(
+    const std::string& guid,
+    std::unique_ptr<content::BackgroundFetchResponse> response) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  // TODO(peter): These two DCHECKs are assumptions our implementation
-  // currently makes, but are not fit for production. We need to handle such
-  // failures gracefully.
-  DCHECK_EQ(interrupt_reason, content::DOWNLOAD_INTERRUPT_REASON_NONE);
-  DCHECK(download_item);
+  if (client())
+    client()->OnDownloadStarted(guid, std::move(response));
+}
 
-  // Register for updates on the download's progress.
-  download_item->AddObserver(new DownloadItemObserver(client()));
+void BackgroundFetchDelegateImpl::OnDownloadUpdated(const std::string& guid,
+                                                    uint64_t bytes_downloaded) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  client()->OnDownloadStarted(
-      download_item->GetGuid(),
-      std::make_unique<content::BackgroundFetchResponse>(
-          download_item->GetUrlChain(), download_item->GetResponseHeaders()));
+  if (client())
+    client()->OnDownloadUpdated(guid, bytes_downloaded);
+}
+
+void BackgroundFetchDelegateImpl::OnDownloadFailed(
+    const std::string& guid,
+    download::Client::FailureReason reason) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  using FailureReason = content::BackgroundFetchDelegate::FailureReason;
+  FailureReason failure_reason;
+
+  switch (reason) {
+    case download::Client::FailureReason::NETWORK:
+      failure_reason = FailureReason::NETWORK;
+      break;
+    case download::Client::FailureReason::TIMEDOUT:
+      failure_reason = FailureReason::TIMEDOUT;
+      break;
+    case download::Client::FailureReason::UNKNOWN:
+      failure_reason = FailureReason::UNKNOWN;
+      break;
+
+    case download::Client::FailureReason::ABORTED:
+    case download::Client::FailureReason::CANCELLED:
+      // The client cancelled or aborted it so no need to notify it.
+      return;
+    default:
+      NOTREACHED();
+      return;
+  }
+
+  if (client())
+    client()->OnDownloadFailed(guid, failure_reason);
+}
+
+void BackgroundFetchDelegateImpl::OnDownloadSucceeded(
+    const std::string& guid,
+    const base::FilePath& path,
+    uint64_t size) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  if (client()) {
+    client()->OnDownloadComplete(
+        guid, std::make_unique<content::BackgroundFetchResult>(
+                  base::Time::Now(), path, size));
+  }
+}
+
+void BackgroundFetchDelegateImpl::OnDownloadReceived(
+    const std::string& guid,
+    download::DownloadParams::StartResult result) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  using StartResult = download::DownloadParams::StartResult;
+  switch (result) {
+    case StartResult::ACCEPTED:
+      // Nothing to do.
+      break;
+    case StartResult::BACKOFF:
+      // TODO(delphick): try again later?
+      // TODO(delphick): Due to a bug at the moment, this happens all the time
+      // because successful downloads are not removed, so don't NOTREACHED.
+      break;
+    case StartResult::UNEXPECTED_CLIENT:
+      // This really should never happen since we're supplying the
+      // DownloadClient.
+      NOTREACHED();
+    case StartResult::UNEXPECTED_GUID:
+      // TODO(delphick): try again with a different GUID.
+      NOTREACHED();
+    case StartResult::CLIENT_CANCELLED:
+      // TODO(delphick): do we need to do anything here, since we will have
+      // cancelled it?
+      break;
+    case StartResult::INTERNAL_ERROR:
+      // TODO(delphick): We need to handle this gracefully.
+      NOTREACHED();
+    case StartResult::COUNT:
+      NOTREACHED();
+  }
 }
diff --git a/chrome/browser/background_fetch/background_fetch_delegate_impl.h b/chrome/browser/background_fetch/background_fetch_delegate_impl.h
index f1d0957..3c78bd8 100644
--- a/chrome/browser/background_fetch/background_fetch_delegate_impl.h
+++ b/chrome/browser/background_fetch/background_fetch_delegate_impl.h
@@ -7,19 +7,19 @@
 
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "base/memory/weak_ptr.h"
+#include "components/download/public/download_params.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "content/public/browser/background_fetch_delegate.h"
-#include "content/public/browser/download_interrupt_reasons.h"
-
-namespace content {
-class DownloadItem;
-}  // namespace content
-
 class Profile;
 
-// Implementation of BackgroundFetchDelegate using the legacy DownloadManager.
+namespace download {
+class DownloadService;
+}  // namespace download
+
+// Implementation of BackgroundFetchDelegate using the DownloadService.
 class BackgroundFetchDelegateImpl : public content::BackgroundFetchDelegate,
                                     public KeyedService {
  public:
@@ -37,13 +37,29 @@
                    const net::NetworkTrafficAnnotationTag& traffic_annotation,
                    const net::HttpRequestHeaders& headers) override;
 
-  base::WeakPtr<BackgroundFetchDelegateImpl> GetWeakPtr();
+  void OnDownloadStarted(const std::string& guid,
+                         std::unique_ptr<content::BackgroundFetchResponse>);
+
+  void OnDownloadUpdated(const std::string& guid, uint64_t bytes_downloaded);
+
+  void OnDownloadFailed(const std::string& guid,
+                        download::Client::FailureReason reason);
+
+  void OnDownloadSucceeded(const std::string& guid,
+                           const base::FilePath& path,
+                           uint64_t size);
+
+  base::WeakPtr<BackgroundFetchDelegateImpl> GetWeakPtr() {
+    return weak_ptr_factory_.GetWeakPtr();
+  }
 
  private:
-  void DidStartRequest(content::DownloadItem* download_item,
-                       content::DownloadInterruptReason interrupt_reason);
+  void OnDownloadReceived(const std::string& guid,
+                          download::DownloadParams::StartResult result);
 
-  Profile* profile_;
+  // The BackgroundFetchDelegateImplFactory depends on the
+  // DownloadServiceFactory, so |download_service_| should outlive |this|.
+  download::DownloadService* download_service_;
 
   base::WeakPtrFactory<BackgroundFetchDelegateImpl> weak_ptr_factory_;
 
diff --git a/chrome/browser/background_fetch/background_fetch_download_client.cc b/chrome/browser/background_fetch/background_fetch_download_client.cc
new file mode 100644
index 0000000..b3e1216
--- /dev/null
+++ b/chrome/browser/background_fetch/background_fetch_download_client.cc
@@ -0,0 +1,76 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/background_fetch/background_fetch_download_client.h"
+
+#include <memory>
+#include <utility>
+
+#include "chrome/browser/background_fetch/background_fetch_delegate_impl.h"
+#include "chrome/browser/download/download_service_factory.h"
+#include "components/download/public/download_metadata.h"
+#include "content/public/browser/background_fetch_response.h"
+#include "content/public/browser/browser_context.h"
+#include "url/origin.h"
+
+BackgroundFetchDownloadClient::BackgroundFetchDownloadClient(
+    content::BrowserContext* context)
+    : browser_context_(context), delegate_(nullptr) {}
+
+BackgroundFetchDownloadClient::~BackgroundFetchDownloadClient() = default;
+
+void BackgroundFetchDownloadClient::OnServiceInitialized(
+    bool state_lost,
+    const std::vector<download::DownloadMetaData>& downloads) {
+  // TODO(delphick): Do something with outstanding downloads
+  delegate_ = static_cast<BackgroundFetchDelegateImpl*>(
+                  browser_context_->GetBackgroundFetchDelegate())
+                  ->GetWeakPtr();
+  DCHECK(delegate_);
+}
+
+void BackgroundFetchDownloadClient::OnServiceUnavailable() {}
+
+download::Client::ShouldDownload
+BackgroundFetchDownloadClient::OnDownloadStarted(
+    const std::string& guid,
+    const std::vector<GURL>& url_chain,
+    const scoped_refptr<const net::HttpResponseHeaders>& headers) {
+  if (delegate_) {
+    std::unique_ptr<content::BackgroundFetchResponse> response =
+        std::make_unique<content::BackgroundFetchResponse>(url_chain, headers);
+    delegate_->OnDownloadStarted(guid, std::move(response));
+  }
+
+  // TODO(delphick): validate the chain/headers before returning CONTINUE
+  return download::Client::ShouldDownload::CONTINUE;
+}
+
+void BackgroundFetchDownloadClient::OnDownloadUpdated(
+    const std::string& guid,
+    uint64_t bytes_downloaded) {
+  if (delegate_)
+    delegate_->OnDownloadUpdated(guid, bytes_downloaded);
+}
+
+void BackgroundFetchDownloadClient::OnDownloadFailed(
+    const std::string& guid,
+    download::Client::FailureReason reason) {
+  if (delegate_)
+    delegate_->OnDownloadFailed(guid, reason);
+}
+
+void BackgroundFetchDownloadClient::OnDownloadSucceeded(
+    const std::string& guid,
+    const download::CompletionInfo& info) {
+  if (delegate_)
+    delegate_->OnDownloadSucceeded(guid, info.path, info.bytes_downloaded);
+}
+
+bool BackgroundFetchDownloadClient::CanServiceRemoveDownloadedFile(
+    const std::string& guid,
+    bool force_delete) {
+  // TODO(delphick): Return false if the background fetch hasn't finished yet
+  return true;
+}
diff --git a/chrome/browser/background_fetch/background_fetch_download_client.h b/chrome/browser/background_fetch/background_fetch_download_client.h
new file mode 100644
index 0000000..16c3ab5
--- /dev/null
+++ b/chrome/browser/background_fetch/background_fetch_download_client.h
@@ -0,0 +1,53 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_DOWNLOAD_CLIENT_H_
+#define CHROME_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_DOWNLOAD_CLIENT_H_
+
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "components/download/public/client.h"
+
+class BackgroundFetchDelegateImpl;
+
+namespace content {
+class BrowserContext;
+}  // namespace content
+
+// A DownloadService client used by BackgroundFetch. Mostly this just forwards
+// calls to BackgroundFetchDelegateImpl.
+class BackgroundFetchDownloadClient : public download::Client {
+ public:
+  explicit BackgroundFetchDownloadClient(content::BrowserContext* context);
+  ~BackgroundFetchDownloadClient() override;
+
+ private:
+  // download::Client implementation
+  void OnServiceInitialized(
+      bool state_lost,
+      const std::vector<download::DownloadMetaData>& downloads) override;
+  void OnServiceUnavailable() override;
+  download::Client::ShouldDownload OnDownloadStarted(
+      const std::string& guid,
+      const std::vector<GURL>& url_chain,
+      const scoped_refptr<const net::HttpResponseHeaders>& headers) override;
+  void OnDownloadUpdated(const std::string& guid,
+                         uint64_t bytes_downloaded) override;
+  void OnDownloadFailed(const std::string& guid,
+                        download::Client::FailureReason reason) override;
+  void OnDownloadSucceeded(const std::string& guid,
+                           const download::CompletionInfo& info) override;
+  bool CanServiceRemoveDownloadedFile(const std::string& guid,
+                                      bool force_delete) override;
+
+  content::BrowserContext* browser_context_;
+  base::WeakPtr<BackgroundFetchDelegateImpl> delegate_;
+
+  DISALLOW_COPY_AND_ASSIGN(BackgroundFetchDownloadClient);
+};
+
+#endif  // CHROME_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_DOWNLOAD_CLIENT_H_
diff --git a/chrome/browser/background_sync/background_sync_permission_context_unittest.cc b/chrome/browser/background_sync/background_sync_permission_context_unittest.cc
index 6a12929..745f397 100644
--- a/chrome/browser/background_sync/background_sync_permission_context_unittest.cc
+++ b/chrome/browser/background_sync/background_sync_permission_context_unittest.cc
@@ -17,6 +17,7 @@
 #include "components/content_settings/core/common/content_settings.h"
 #include "components/content_settings/core/common/content_settings_pattern.h"
 #include "components/content_settings/core/common/content_settings_types.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/web_contents_tester.h"
@@ -37,7 +38,7 @@
     base::RunLoop run_loop;
 
     const PermissionRequestID id(
-        web_contents()->GetRenderProcessHost()->GetID(),
+        web_contents()->GetMainFrame()->GetProcess()->GetID(),
         web_contents()->GetMainFrame()->GetRoutingID(), -1 /* request_id */);
     permission_context->RequestPermission(
         web_contents(), id, url, false /* user_gesture */,
diff --git a/chrome/browser/banners/app_banner_infobar_delegate_desktop.cc b/chrome/browser/banners/app_banner_infobar_delegate_desktop.cc
index 1a86016..075c489 100644
--- a/chrome/browser/banners/app_banner_infobar_delegate_desktop.cc
+++ b/chrome/browser/banners/app_banner_infobar_delegate_desktop.cc
@@ -26,22 +26,25 @@
     content::WebContents* web_contents,
     base::WeakPtr<AppBannerManager> weak_manager,
     extensions::BookmarkAppHelper* bookmark_app_helper,
+    const GURL& manifest_url,
     const content::Manifest& manifest) {
   InfoBarService* infobar_service =
       InfoBarService::FromWebContents(web_contents);
   return infobar_service->AddInfoBar(infobar_service->CreateConfirmInfoBar(
       std::unique_ptr<ConfirmInfoBarDelegate>(
           new AppBannerInfoBarDelegateDesktop(weak_manager, bookmark_app_helper,
-                                              manifest))));
+                                              manifest_url, manifest))));
 }
 
 AppBannerInfoBarDelegateDesktop::AppBannerInfoBarDelegateDesktop(
     base::WeakPtr<AppBannerManager> weak_manager,
     extensions::BookmarkAppHelper* bookmark_app_helper,
+    const GURL& manifest_url,
     const content::Manifest& manifest)
     : ConfirmInfoBarDelegate(),
       weak_manager_(weak_manager),
       bookmark_app_helper_(bookmark_app_helper),
+      manifest_url_(manifest_url),
       manifest_(manifest),
       has_user_interaction_(false) {}
 
@@ -99,7 +102,7 @@
   bookmark_app_helper_->CreateFromAppBanner(
       base::Bind(&AppBannerManager::DidFinishCreatingBookmarkApp,
                  weak_manager_),
-      manifest_);
+      manifest_url_, manifest_);
   return true;
 }
 
diff --git a/chrome/browser/banners/app_banner_infobar_delegate_desktop.h b/chrome/browser/banners/app_banner_infobar_delegate_desktop.h
index 640d606..dc7d745 100644
--- a/chrome/browser/banners/app_banner_infobar_delegate_desktop.h
+++ b/chrome/browser/banners/app_banner_infobar_delegate_desktop.h
@@ -10,6 +10,7 @@
 #include "base/strings/string16.h"
 #include "components/infobars/core/confirm_infobar_delegate.h"
 #include "content/public/common/manifest.h"
+#include "url/gurl.h"
 
 namespace content {
 class WebContents;
@@ -34,12 +35,14 @@
       content::WebContents* web_contents,
       base::WeakPtr<AppBannerManager> weak_manager,
       extensions::BookmarkAppHelper* bookmark_app_helper,
+      const GURL& manifest_url,
       const content::Manifest& manifest);
 
  private:
   AppBannerInfoBarDelegateDesktop(
       base::WeakPtr<AppBannerManager> weak_manager,
       extensions::BookmarkAppHelper* bookmark_app_helper,
+      const GURL& manifest_url,
       const content::Manifest& manifest);
   ~AppBannerInfoBarDelegateDesktop() override;
 
@@ -55,6 +58,7 @@
 
   base::WeakPtr<AppBannerManager> weak_manager_;
   extensions::BookmarkAppHelper* bookmark_app_helper_;
+  GURL manifest_url_;
   content::Manifest manifest_;
   bool has_user_interaction_;
 
diff --git a/chrome/browser/banners/app_banner_manager.cc b/chrome/browser/banners/app_banner_manager.cc
index d426173..edabf8fe 100644
--- a/chrome/browser/banners/app_banner_manager.cc
+++ b/chrome/browser/banners/app_banner_manager.cc
@@ -87,8 +87,7 @@
   }
 
   if (code != NO_ERROR_DETECTED) {
-    ReportStatus(contents, code);
-    Stop();
+    StopWithCode(code);
     return;
   }
 
@@ -183,8 +182,7 @@
 void AppBannerManager::OnDidGetManifest(const InstallableData& data) {
   UpdateState(State::ACTIVE);
   if (data.error_code != NO_ERROR_DETECTED) {
-    ReportStatus(web_contents(), data.error_code);
-    Stop();
+    StopWithCode(data.error_code);
     return;
   }
 
@@ -229,8 +227,7 @@
     if (data.error_code == NO_MATCHING_SERVICE_WORKER)
       TrackDisplayEvent(DISPLAY_EVENT_LACKS_SERVICE_WORKER);
 
-    ReportStatus(web_contents(), data.error_code);
-    Stop();
+    StopWithCode(data.error_code);
     return;
   }
 
@@ -287,7 +284,6 @@
 }
 
 void AppBannerManager::Stop() {
-  // Record the status if we are currently waiting for data.
   InstallableStatusCode code = NO_ERROR_DETECTED;
   switch (state_) {
     case State::PENDING_PROMPT:
@@ -314,7 +310,10 @@
     case State::COMPLETE:
       break;
   }
+  StopWithCode(code);
+}
 
+void AppBannerManager::StopWithCode(InstallableStatusCode code) {
   if (code != NO_ERROR_DETECTED)
     ReportStatus(web_contents(), code);
 
@@ -516,8 +515,7 @@
       default:
         NOTREACHED();
     }
-    ReportStatus(contents, code);
-    Stop();
+    StopWithCode(code);
     return false;
   }
   return true;
@@ -585,12 +583,7 @@
 
 void AppBannerManager::DisplayAppBanner(bool user_gesture) {
   if (IsExperimentalAppBannersEnabled() && !user_gesture) {
-    ReportStatus(web_contents(), NO_GESTURE);
-
-    // The state is manually set to COMPLETE before calling Stop, because
-    // otherwise Stop will complain that the status has already been reported.
-    UpdateState(State::COMPLETE);
-    Stop();
+    StopWithCode(NO_GESTURE);
     return;
   }
 
diff --git a/chrome/browser/banners/app_banner_manager.h b/chrome/browser/banners/app_banner_manager.h
index d42e52ee..0465833 100644
--- a/chrome/browser/banners/app_banner_manager.h
+++ b/chrome/browser/banners/app_banner_manager.h
@@ -192,10 +192,12 @@
   // Resets all fetched data for the current page.
   virtual void ResetCurrentPageData();
 
+  void Stop();
+
   // Stops the banner pipeline, preventing any outstanding callbacks from
   // running and resetting the manager state. This method is virtual to allow
   // tests to intercept it and verify correct behaviour.
-  virtual void Stop();
+  virtual void StopWithCode(InstallableStatusCode code);
 
   // Sends a message to the renderer that the page has met the requirements to
   // show a banner. The page can respond to cancel the banner (and possibly
diff --git a/chrome/browser/banners/app_banner_manager_browsertest.cc b/chrome/browser/banners/app_banner_manager_browsertest.cc
index f8af1d9f..25b1824 100644
--- a/chrome/browser/banners/app_banner_manager_browsertest.cc
+++ b/chrome/browser/banners/app_banner_manager_browsertest.cc
@@ -82,12 +82,12 @@
   }
 
  protected:
-  // All calls to RequestAppBanner should terminate in one of Stop() (not
-  // showing banner), UpdateState(State::PENDING_ENGAGEMENT) (waiting for
+  // All calls to RequestAppBanner should terminate in one of StopWithCode()
+  // (not showing banner), UpdateState(State::PENDING_ENGAGEMENT) (waiting for
   // sufficient engagement), or ShowBannerUi(). Override these methods to
   // capture test status.
-  void Stop() override {
-    AppBannerManager::Stop();
+  void StopWithCode(InstallableStatusCode code) override {
+    AppBannerManager::StopWithCode(code);
     ASSERT_FALSE(will_show_.get());
     will_show_.reset(new bool(false));
     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure_);
diff --git a/chrome/browser/banners/app_banner_manager_desktop.cc b/chrome/browser/banners/app_banner_manager_desktop.cc
index 259f493..f63fb7d 100644
--- a/chrome/browser/banners/app_banner_manager_desktop.cc
+++ b/chrome/browser/banners/app_banner_manager_desktop.cc
@@ -86,7 +86,8 @@
   // the InfoBarService to show the banner. On desktop, an InfoBar class
   // is not required, and the delegate calls the InfoBarService.
   infobars::InfoBar* infobar = AppBannerInfoBarDelegateDesktop::Create(
-      contents, GetWeakPtr(), bookmark_app_helper_.get(), manifest_);
+      contents, GetWeakPtr(), bookmark_app_helper_.get(), manifest_url_,
+      manifest_);
   if (infobar) {
     RecordDidShowBanner("AppBanner.WebApp.Shown");
     TrackDisplayEvent(DISPLAY_EVENT_WEB_APP_BANNER_CREATED);
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 3978854..e1a26f2 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -190,8 +190,14 @@
         <include name="IDR_MD_EXTENSIONS_ERROR_PAGE_JS" file="resources\md_extensions\error_page.js" type="BINDATA" />
         <include name="IDR_MD_EXTENSIONS_KEYBOARD_SHORTCUTS_HTML" file="resources\md_extensions\keyboard_shortcuts.html" type="BINDATA" />
         <include name="IDR_MD_EXTENSIONS_KEYBOARD_SHORTCUTS_JS" file="resources\md_extensions\keyboard_shortcuts.js" type="BINDATA" />
-        <include name="IDR_MD_EXTENSIONS_MANAGER_HTML" file="resources\md_extensions\manager.html" type="BINDATA" />
-        <include name="IDR_MD_EXTENSIONS_MANAGER_JS" file="resources\md_extensions\manager.js" type="BINDATA" />
+      <if expr="chromeos">
+        <include name="IDR_MD_EXTENSIONS_KIOSK_BROWSER_PROXY_HTML" file="resources\md_extensions\kiosk_browser_proxy.html" type="BINDATA" />
+        <include name="IDR_MD_EXTENSIONS_KIOSK_BROWSER_PROXY_JS" file="resources\md_extensions\kiosk_browser_proxy.js" type="BINDATA" />
+        <include name="IDR_MD_EXTENSIONS_KIOSK_DIALOG_HTML" file="resources\md_extensions\kiosk_dialog.html" type="BINDATA" />
+        <include name="IDR_MD_EXTENSIONS_KIOSK_DIALOG_JS" file="resources\md_extensions\kiosk_dialog.js" type="BINDATA" />
+      </if>
+        <include name="IDR_MD_EXTENSIONS_MANAGER_HTML" file="resources\md_extensions\manager.html" type="BINDATA" flattenhtml="true" />
+        <include name="IDR_MD_EXTENSIONS_MANAGER_JS" file="resources\md_extensions\manager.js" type="BINDATA" flattenhtml="true" />
         <include name="IDR_MD_EXTENSIONS_ICONS_HTML" file="resources\md_extensions\icons.html" type="BINDATA" />
         <include name="IDR_MD_EXTENSIONS_ITEM_HTML" file="resources\md_extensions\item.html" type="BINDATA" />
         <include name="IDR_MD_EXTENSIONS_ITEM_JS" file="resources\md_extensions\item.js" type="BINDATA" />
@@ -215,8 +221,8 @@
         <include name="IDR_MD_EXTENSIONS_SHORTCUT_INPUT_JS" file="resources\md_extensions\shortcut_input.js" type="BINDATA" />
         <include name="IDR_MD_EXTENSIONS_SIDEBAR_HTML" file="resources\md_extensions\sidebar.html" type="BINDATA" />
         <include name="IDR_MD_EXTENSIONS_SIDEBAR_JS" file="resources\md_extensions\sidebar.js" type="BINDATA" />
-        <include name="IDR_MD_EXTENSIONS_TOOLBAR_HTML" file="resources\md_extensions\toolbar.html" type="BINDATA" />
-        <include name="IDR_MD_EXTENSIONS_TOOLBAR_JS" file="resources\md_extensions\toolbar.js" type="BINDATA" />
+        <include name="IDR_MD_EXTENSIONS_TOOLBAR_HTML" file="resources\md_extensions\toolbar.html" type="BINDATA" flattenhtml="true" />
+        <include name="IDR_MD_EXTENSIONS_TOOLBAR_JS" file="resources\md_extensions\toolbar.js" type="BINDATA" flattenhtml="true" />
         <include name="IDR_MD_EXTENSIONS_STRINGS_HTML" file="resources\md_extensions\strings.html" type="BINDATA" />
         <include name="IDR_MD_EXTENSIONS_VIEW_MANAGER_HTML" file="resources\md_extensions\view_manager.html" type="BINDATA" />
         <include name="IDR_MD_EXTENSIONS_VIEW_MANAGER_JS" file="resources\md_extensions\view_manager.js" type="BINDATA" />
diff --git a/chrome/browser/chrome_browser_field_trials.cc b/chrome/browser/chrome_browser_field_trials.cc
index ad15185..d1aca055 100644
--- a/chrome/browser/chrome_browser_field_trials.cc
+++ b/chrome/browser/chrome_browser_field_trials.cc
@@ -19,7 +19,6 @@
 #include "base/strings/string_util.h"
 #include "base/task_scheduler/post_task.h"
 #include "base/time/time.h"
-#include "base/trace_event/freed_object_tracker.h"
 #include "build/build_config.h"
 #include "chrome/browser/metrics/chrome_metrics_service_client.h"
 #include "chrome/browser/metrics/chrome_metrics_services_manager_client.h"
@@ -39,9 +38,6 @@
 
 namespace {
 
-const base::Feature kFreedObjectTrackerFeature{
-    "FreedObjectTracker", base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Creating a "spare" file for persistent metrics involves a lot of I/O and
 // isn't important so delay the operation for a while after startup.
 #if defined(OS_ANDROID)
@@ -242,9 +238,5 @@
   // Persistent histograms must be enabled as soon as possible.
   InstantiatePersistentHistograms();
 
-  // Enable use-after-free information gathering.
-  if (base::FeatureList::IsEnabled(kFreedObjectTrackerFeature))
-    base::trace_event::FreedObjectTracker::GetInstance()->Enable();
-
   tracing::SetupBackgroundTracingFieldTrial();
 }
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 0fbedef..1454229 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -244,6 +244,7 @@
 #elif defined(OS_MACOSX)
 #include "chrome/browser/chrome_browser_main_mac.h"
 #elif defined(OS_CHROMEOS)
+#include "ash/public/interfaces/constants.mojom.h"
 #include "chrome/browser/chromeos/arc/arc_util.h"
 #include "chrome/browser/chromeos/arc/fileapi/arc_content_file_system_backend_delegate.h"
 #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_backend_delegate.h"
@@ -365,6 +366,11 @@
 #include "chrome/browser/media/cast_transport_host_filter.h"
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
+#if BUILDFLAG(ENABLE_PACKAGE_MASH_SERVICES)
+#include "chrome/browser/mash_service_registry.h"
+#include "services/ui/public/interfaces/constants.mojom.h"
+#endif
+
 #if BUILDFLAG(ENABLE_PLUGINS)
 #include "chrome/browser/plugins/chrome_content_browser_client_plugins_part.h"
 #include "chrome/browser/plugins/flash_download_interception.h"
@@ -1282,6 +1288,13 @@
 #endif
 }
 
+bool ChromeContentBrowserClient::ShouldStayInParentProcessForNTP(
+    const GURL& url,
+    SiteInstance* parent_site_instance) {
+  return url.SchemeIs(chrome::kChromeSearchScheme) &&
+         IsNTPSiteInstance(parent_site_instance);
+}
+
 bool ChromeContentBrowserClient::IsSuitableHost(
     content::RenderProcessHost* process_host,
     const GURL& site_url) {
@@ -1819,6 +1832,36 @@
   }
 }
 
+void ChromeContentBrowserClient::AdjustUtilityServiceProcessCommandLine(
+    const service_manager::Identity& identity,
+    base::CommandLine* command_line) {
+#if BUILDFLAG(ENABLE_PACKAGE_MASH_SERVICES)
+  // Mash services do their own resource loading.
+  if (IsMashServiceName(identity.name()))
+    command_line->AppendSwitch(switches::kDisableServiceProcessResourceLoading);
+  bool copy_switches = false;
+  if (identity.name() == ui::mojom::kServiceName) {
+    command_line->AppendSwitch(switches::kMessageLoopTypeUi);
+    copy_switches = true;
+  }
+#if defined(OS_CHROMEOS)
+  if (identity.name() == ash::mojom::kServiceName)
+    copy_switches = true;
+#endif
+  // TODO(sky): move to a whitelist, but currently the set of flags is rather
+  // sprawling.
+  if (copy_switches) {
+    base::CommandLine::SwitchMap switches =
+        base::CommandLine::ForCurrentProcess()->GetSwitches();
+    switches.erase("single_process");
+    switches.erase(switches::kSingleProcess);
+    switches.erase("gtest_filter");
+    for (const auto& sw : switches)
+      command_line->AppendSwitchNative(sw.first, sw.second);
+  }
+#endif
+}
+
 std::string ChromeContentBrowserClient::GetApplicationLocale() {
   if (BrowserThread::CurrentlyOn(BrowserThread::IO))
     return g_io_thread_application_locale.Get();
@@ -3007,7 +3050,7 @@
 }
 
 void ChromeContentBrowserClient::RegisterOutOfProcessServices(
-      OutOfProcessServiceMap* services) {
+    OutOfProcessServiceMap* services) {
 #if BUILDFLAG(ENABLE_PRINTING)
   (*services)[printing::mojom::kServiceName] =
       base::ASCIIToUTF16("PDF Compositor Service");
@@ -3025,6 +3068,11 @@
   (*services)[chrome::mojom::kProfileImportServiceName] =
       l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_PROFILE_IMPORTER_NAME);
 #endif
+
+#if BUILDFLAG(ENABLE_PACKAGE_MASH_SERVICES)
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kMash))
+    RegisterOutOfProcessServicesForMash(services);
+#endif
 }
 
 std::unique_ptr<base::Value>
@@ -3419,8 +3467,9 @@
   return task_scheduler_util::GetBrowserTaskSchedulerInitParamsFromVariations();
 }
 
-base::FilePath ChromeContentBrowserClient::GetLoggingFileName() {
-  return logging::GetLogFileName();
+base::FilePath ChromeContentBrowserClient::GetLoggingFileName(
+    const base::CommandLine& command_line) {
+  return logging::GetLogFileName(command_line);
 }
 
 std::vector<std::unique_ptr<content::URLLoaderThrottle>>
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index dce1c50..dc08593c 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -117,6 +117,10 @@
   bool ShouldFrameShareParentSiteInstanceDespiteTopDocumentIsolation(
       const GURL& url,
       content::SiteInstance* parent_site_instance) override;
+  bool ShouldStayInParentProcessForNTP(
+      const GURL& url,
+      content::SiteInstance* parent_site_instance) override;
+
   bool IsSuitableHost(content::RenderProcessHost* process_host,
                       const GURL& site_url) override;
   bool MayReuseHost(content::RenderProcessHost* process_host) override;
@@ -137,6 +141,9 @@
   std::vector<url::Origin> GetOriginsRequiringDedicatedProcess() override;
   void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
                                       int child_process_id) override;
+  void AdjustUtilityServiceProcessCommandLine(
+      const service_manager::Identity& identity,
+      base::CommandLine* command_line) override;
   std::string GetApplicationLocale() override;
   std::string GetAcceptLangs(content::BrowserContext* context) override;
   const gfx::ImageSkia* GetDefaultFavicon() override;
@@ -336,7 +343,8 @@
 
   std::unique_ptr<base::TaskScheduler::InitParams> GetTaskSchedulerInitParams()
       override;
-  base::FilePath GetLoggingFileName() override;
+  base::FilePath GetLoggingFileName(
+      const base::CommandLine& command_line) override;
   std::vector<std::unique_ptr<content::URLLoaderThrottle>>
   CreateURLLoaderThrottles(
       const base::Callback<content::WebContents*()>& wc_getter) override;
diff --git a/chrome/browser/chrome_content_browser_client_unittest.cc b/chrome/browser/chrome_content_browser_client_unittest.cc
index 5b35a99..b0acc96 100644
--- a/chrome/browser/chrome_content_browser_client_unittest.cc
+++ b/chrome/browser/chrome_content_browser_client_unittest.cc
@@ -346,9 +346,20 @@
 class ChromeContentBrowserClientGetLoggingFileTest : public testing::Test {};
 
 TEST_F(ChromeContentBrowserClientGetLoggingFileTest, GetLoggingFile) {
+  base::CommandLine cmd_line(base::CommandLine::NO_PROGRAM);
   ChromeContentBrowserClient client;
   base::FilePath log_file_name;
-  EXPECT_FALSE(client.GetLoggingFileName().empty());
+  EXPECT_FALSE(client.GetLoggingFileName(cmd_line).empty());
+}
+
+TEST_F(ChromeContentBrowserClientGetLoggingFileTest,
+       GetLoggingFileFromCommandLine) {
+  base::CommandLine cmd_line(base::CommandLine::NO_PROGRAM);
+  cmd_line.AppendSwitchASCII(switches::kLogFile, "test_log.txt");
+  ChromeContentBrowserClient client;
+  base::FilePath log_file_name;
+  EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("test_log.txt")).value(),
+            client.GetLoggingFileName(cmd_line).value());
 }
 
 class TestChromeContentBrowserClient : public ChromeContentBrowserClient {
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index dee623b0..94ca4e4 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -830,12 +830,6 @@
     "login/demo_mode/demo_app_launcher.h",
     "login/demo_mode/demo_mode_detector.cc",
     "login/demo_mode/demo_mode_detector.h",
-    "login/easy_unlock/bootstrap_manager.cc",
-    "login/easy_unlock/bootstrap_manager.h",
-    "login/easy_unlock/bootstrap_user_context_initializer.cc",
-    "login/easy_unlock/bootstrap_user_context_initializer.h",
-    "login/easy_unlock/bootstrap_user_flow.cc",
-    "login/easy_unlock/bootstrap_user_flow.h",
     "login/easy_unlock/easy_unlock_challenge_wrapper.cc",
     "login/easy_unlock/easy_unlock_challenge_wrapper.h",
     "login/easy_unlock/easy_unlock_create_keys_operation.cc",
@@ -1847,6 +1841,8 @@
     "policy/fake_affiliated_invalidation_service_provider.h",
     "policy/heartbeat_scheduler_unittest.cc",
     "policy/network_configuration_updater_unittest.cc",
+    "policy/off_hours/off_hours_interval_unittest.cc",
+    "policy/off_hours/weekly_time_unittest.cc",
     "policy/pre_signin_policy_fetcher_unittest.cc",
     "policy/recommendation_restorer_unittest.cc",
     "policy/remote_commands/device_command_screenshot_job_unittest.cc",
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
index 5e5bafa..71a72f7 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -49,7 +49,6 @@
 #include "chrome/browser/chromeos/system/input_device_settings.h"
 #include "chrome/browser/extensions/api/braille_display_private/stub_braille_controller.h"
 #include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/prefs/incognito_mode_prefs.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/chrome_paths.h"
@@ -396,13 +395,6 @@
   NotifyAccessibilityStatusChanged(details);
 }
 
-bool AccessibilityManager::IsIncognitoAllowed() {
-  return profile_ != NULL &&
-         profile_->GetProfileType() != Profile::GUEST_PROFILE &&
-         IncognitoModePrefs::GetAvailability(profile_->GetPrefs()) !=
-             IncognitoModePrefs::DISABLED;
-}
-
 bool AccessibilityManager::IsLargeCursorEnabled() const {
   return profile_ && profile_->GetPrefs()->GetBoolean(
                          ash::prefs::kAccessibilityLargeCursorEnabled);
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.h b/chrome/browser/chromeos/accessibility/accessibility_manager.h
index da294e24..014881ca 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.h
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.h
@@ -136,9 +136,6 @@
   // Enables or disable Sticky Keys.
   void EnableStickyKeys(bool enabled);
 
-  // Returns true if Incognito mode is allowed, or false if not.
-  bool IsIncognitoAllowed();
-
   // Returns true if the Sticky Keys is enabled, or false if not.
   bool IsStickyKeysEnabled() const;
 
diff --git a/chrome/browser/chromeos/app_mode/kiosk_external_update_validator.cc b/chrome/browser/chromeos/app_mode/kiosk_external_update_validator.cc
index a37a37f..688699e 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_external_update_validator.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_external_update_validator.cc
@@ -70,7 +70,7 @@
   content::BrowserThread::PostTask(
       content::BrowserThread::UI, FROM_HERE,
       base::BindOnce(
-          &KioskExternalUpdateValidatorDelegate::OnExtenalUpdateUnpackSuccess,
+          &KioskExternalUpdateValidatorDelegate::OnExternalUpdateUnpackSuccess,
           delegate_, crx_file_.extension_id, extension->VersionString(),
           minimum_browser_version, temp_dir));
 }
diff --git a/chrome/browser/chromeos/app_mode/kiosk_external_update_validator.h b/chrome/browser/chromeos/app_mode/kiosk_external_update_validator.h
index 5946545..9d0b4c0 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_external_update_validator.h
+++ b/chrome/browser/chromeos/app_mode/kiosk_external_update_validator.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_CHROMEOS_APP_MODE_KIOSK_EXTERNAL_UPDATE_VALIDATOR_H_
 #define CHROME_BROWSER_CHROMEOS_APP_MODE_KIOSK_EXTERNAL_UPDATE_VALIDATOR_H_
 
+#include <memory>
 #include <string>
 
 #include "base/files/file_path.h"
@@ -23,7 +24,7 @@
 // WeakPtr.
 class KioskExternalUpdateValidatorDelegate {
  public:
-  virtual void OnExtenalUpdateUnpackSuccess(
+  virtual void OnExternalUpdateUnpackSuccess(
       const std::string& app_id,
       const std::string& version,
       const std::string& min_browser_version,
diff --git a/chrome/browser/chromeos/app_mode/kiosk_external_updater.cc b/chrome/browser/chromeos/app_mode/kiosk_external_updater.cc
index 6d05fbf..0163beda 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_external_updater.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_external_updater.cc
@@ -11,6 +11,7 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task_runner_util.h"
 #include "base/version.h"
 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
 #include "chrome/browser/chromeos/ui/kiosk_external_update_notification.h"
@@ -26,49 +27,38 @@
 
 namespace {
 
-const char kExternalUpdateManifest[] = "external_update.json";
-const char kExternalCrx[] = "external_crx";
-const char kExternalVersion[] = "external_version";
+constexpr base::FilePath::CharType kExternalUpdateManifest[] =
+    "external_update.json";
+constexpr char kExternalCrx[] = "external_crx";
+constexpr char kExternalVersion[] = "external_version";
 
-void ParseExternalUpdateManifest(
-    const base::FilePath& external_update_dir,
-    base::DictionaryValue* parsed_manifest,
-    KioskExternalUpdater::ExternalUpdateErrorCode* error_code) {
-  base::FilePath manifest =
-      external_update_dir.AppendASCII(kExternalUpdateManifest);
+std::pair<std::unique_ptr<base::DictionaryValue>,
+          KioskExternalUpdater::ExternalUpdateErrorCode>
+ParseExternalUpdateManifest(const base::FilePath& external_update_dir) {
+  base::FilePath manifest = external_update_dir.Append(kExternalUpdateManifest);
   if (!base::PathExists(manifest)) {
-    *error_code = KioskExternalUpdater::ERROR_NO_MANIFEST;
-    return;
+    return std::make_pair(nullptr, KioskExternalUpdater::ERROR_NO_MANIFEST);
   }
 
   JSONFileValueDeserializer deserializer(manifest);
-  std::string error_msg;
-  base::Value* extensions =
-      deserializer.Deserialize(NULL, &error_msg).release();
-  // TODO(Olli Raula) possible memory leak http://crbug.com/543015
+  std::unique_ptr<base::DictionaryValue> extensions =
+      base::DictionaryValue::From(deserializer.Deserialize(nullptr, nullptr));
   if (!extensions) {
-    *error_code = KioskExternalUpdater::ERROR_INVALID_MANIFEST;
-    return;
+    return std::make_pair(nullptr,
+                          KioskExternalUpdater::ERROR_INVALID_MANIFEST);
   }
 
-  base::DictionaryValue* dict_value = NULL;
-  if (!extensions->GetAsDictionary(&dict_value)) {
-    *error_code = KioskExternalUpdater::ERROR_INVALID_MANIFEST;
-    return;
-  }
-
-  parsed_manifest->Swap(dict_value);
-  *error_code = KioskExternalUpdater::ERROR_NONE;
+  return std::make_pair(std::move(extensions),
+                        KioskExternalUpdater::ERROR_NONE);
 }
 
 // Copies |external_crx_file| to |temp_crx_file|, and removes |temp_dir|
 // created for unpacking |external_crx_file|.
-void CopyExternalCrxAndDeleteTempDir(const base::FilePath& external_crx_file,
+bool CopyExternalCrxAndDeleteTempDir(const base::FilePath& external_crx_file,
                                      const base::FilePath& temp_crx_file,
-                                     const base::FilePath& temp_dir,
-                                     bool* success) {
+                                     const base::FilePath& temp_dir) {
   base::DeleteFile(temp_dir, true);
-  *success = base::CopyFile(external_crx_file, temp_crx_file);
+  return base::CopyFile(external_crx_file, temp_crx_file);
 }
 
 // Returns true if |version_1| < |version_2|, and
@@ -83,10 +73,7 @@
   int compare_result = v1.CompareTo(v2);
   if (compare_result < 0)
     return true;
-  else if (update_for_same_version && compare_result == 0)
-    return true;
-  else
-    return false;
+  return update_for_same_version && compare_result == 0;
 }
 
 }  // namespace
@@ -133,6 +120,7 @@
     MountError error_code,
     const disks::DiskMountManager::MountPointInfo& mount_info) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
   if (mount_info.mount_type != MOUNT_TYPE_DEVICE ||
       error_code != MOUNT_ERROR_NONE) {
     return;
@@ -147,30 +135,28 @@
       return;
     }
 
-    base::DictionaryValue* parsed_manifest = new base::DictionaryValue();
-    ExternalUpdateErrorCode* parsing_error = new ExternalUpdateErrorCode;
-    backend_task_runner_->PostTaskAndReply(
-        FROM_HERE,
+    base::PostTaskAndReplyWithResult(
+        backend_task_runner_.get(), FROM_HERE,
         base::BindOnce(&ParseExternalUpdateManifest,
-                       base::FilePath(mount_info.mount_path), parsed_manifest,
-                       parsing_error),
+                       base::FilePath(mount_info.mount_path)),
         base::BindOnce(&KioskExternalUpdater::ProcessParsedManifest,
-                       weak_factory_.GetWeakPtr(), base::Owned(parsing_error),
-                       base::FilePath(mount_info.mount_path),
-                       base::Owned(parsed_manifest)));
-  } else {  // unmounting a removable device.
-    if (external_update_path_.value().empty()) {
-      // Clear any previously displayed message.
-      DismissKioskUpdateNotification();
-    } else if (external_update_path_.value() == mount_info.mount_path) {
-      DismissKioskUpdateNotification();
-      if (IsExternalUpdatePending()) {
-        LOG(ERROR) << "External kiosk update is not completed when the usb "
-                      "stick is unmoutned.";
-      }
-      external_updates_.clear();
-      external_update_path_.clear();
+                       weak_factory_.GetWeakPtr(),
+                       base::FilePath(mount_info.mount_path)));
+    return;
+  }
+
+  // unmounting a removable device case.
+  if (external_update_path_.value().empty()) {
+    // Clear any previously displayed message.
+    DismissKioskUpdateNotification();
+  } else if (external_update_path_.value() == mount_info.mount_path) {
+    DismissKioskUpdateNotification();
+    if (IsExternalUpdatePending()) {
+      LOG(ERROR) << "External kiosk update is not completed when the usb "
+                 << "stick is unmoutned.";
     }
+    external_updates_.clear();
+    external_update_path_.clear();
   }
 }
 
@@ -185,7 +171,7 @@
     RenameError error_code,
     const std::string& device_path) {}
 
-void KioskExternalUpdater::OnExtenalUpdateUnpackSuccess(
+void KioskExternalUpdater::OnExternalUpdateUnpackSuccess(
     const std::string& app_id,
     const std::string& version,
     const std::string& min_browser_version,
@@ -210,14 +196,13 @@
       external_updates_[app_id].external_crx.path;
   base::FilePath temp_crx_path =
       crx_unpack_dir_.Append(external_crx_path.BaseName());
-  bool* success = new bool;
-  backend_task_runner_->PostTaskAndReply(
-      FROM_HERE,
+  base::PostTaskAndReplyWithResult(
+      backend_task_runner_.get(), FROM_HERE,
       base::BindOnce(&CopyExternalCrxAndDeleteTempDir, external_crx_path,
-                     temp_crx_path, temp_dir, success),
+                     temp_crx_path, temp_dir),
       base::BindOnce(&KioskExternalUpdater::PutValidatedExtension,
-                     weak_factory_.GetWeakPtr(), base::Owned(success), app_id,
-                     temp_crx_path, version));
+                     weak_factory_.GetWeakPtr(), app_id, temp_crx_path,
+                     version));
 }
 
 void KioskExternalUpdater::OnExternalUpdateUnpackFailure(
@@ -234,15 +219,17 @@
 }
 
 void KioskExternalUpdater::ProcessParsedManifest(
-    ExternalUpdateErrorCode* parsing_error,
     const base::FilePath& external_update_dir,
-    base::DictionaryValue* parsed_manifest) {
+    const ParseManifestResult& result) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  if (*parsing_error == ERROR_NO_MANIFEST) {
+  const std::unique_ptr<base::DictionaryValue>& parsed_manifest = result.first;
+  ExternalUpdateErrorCode parsing_error = result.second;
+  if (parsing_error == ERROR_NO_MANIFEST) {
     KioskAppManager::Get()->OnKioskAppExternalUpdateComplete(false);
     return;
-  } else if (*parsing_error == ERROR_INVALID_MANIFEST) {
+  }
+  if (parsing_error == ERROR_INVALID_MANIFEST) {
     NotifyKioskUpdateProgress(
         ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
             IDS_KIOSK_EXTERNAL_UPDATE_INVALID_MANIFEST));
@@ -266,7 +253,7 @@
       continue;
     }
 
-    const base::DictionaryValue* extension = NULL;
+    const base::DictionaryValue* extension = nullptr;
     if (!it.value().GetAsDictionary(&extension)) {
       LOG(ERROR) << "Found bad entry in manifest type " << it.value().GetType();
       continue;
@@ -326,39 +313,30 @@
 }
 
 void KioskExternalUpdater::ValidateExternalUpdates() {
-  for (ExternalUpdateMap::iterator it = external_updates_.begin();
-       it != external_updates_.end();
-       ++it) {
-    if (it->second.update_status == PENDING) {
-      scoped_refptr<KioskExternalUpdateValidator> crx_validator =
-          new KioskExternalUpdateValidator(backend_task_runner_,
-                                           it->second.external_crx,
-                                           crx_unpack_dir_,
-                                           weak_factory_.GetWeakPtr());
+  for (const auto& it : external_updates_) {
+    const ExternalUpdate& update = it.second;
+    if (update.update_status == PENDING) {
+      auto crx_validator = base::MakeRefCounted<KioskExternalUpdateValidator>(
+          backend_task_runner_, update.external_crx, crx_unpack_dir_,
+          weak_factory_.GetWeakPtr());
       crx_validator->Start();
       break;
     }
   }
 }
 
-bool KioskExternalUpdater::IsExternalUpdatePending() {
-  for (ExternalUpdateMap::iterator it = external_updates_.begin();
-       it != external_updates_.end();
-       ++it) {
-    if (it->second.update_status == PENDING) {
+bool KioskExternalUpdater::IsExternalUpdatePending() const {
+  for (const auto& it : external_updates_) {
+    if (it.second.update_status == PENDING)
       return true;
-    }
   }
   return false;
 }
 
-bool KioskExternalUpdater::IsAllExternalUpdatesSucceeded() {
-  for (ExternalUpdateMap::iterator it = external_updates_.begin();
-       it != external_updates_.end();
-       ++it) {
-    if (it->second.update_status != SUCCESS) {
+bool KioskExternalUpdater::IsAllExternalUpdatesSucceeded() const {
+  for (const auto& it : external_updates_) {
+    if (it.second.update_status != SUCCESS)
       return false;
-    }
   }
   return true;
 }
@@ -384,28 +362,28 @@
   }
 
   // Check minimum browser version.
-  if (!min_browser_version.empty()) {
-    if (!ShouldUpdateForHigherVersion(min_browser_version,
-                                      version_info::GetVersionNumber(), true)) {
-      external_updates_[app_id].error = l10n_util::GetStringFUTF16(
-          IDS_KIOSK_EXTERNAL_UPDATE_REQUIRE_HIGHER_BROWSER_VERSION,
-          base::UTF8ToUTF16(min_browser_version));
-      return false;
-    }
+  if (!min_browser_version.empty() &&
+      !ShouldUpdateForHigherVersion(min_browser_version,
+                                    version_info::GetVersionNumber(), true)) {
+    external_updates_[app_id].error = l10n_util::GetStringFUTF16(
+        IDS_KIOSK_EXTERNAL_UPDATE_REQUIRE_HIGHER_BROWSER_VERSION,
+        base::UTF8ToUTF16(min_browser_version));
+    return false;
   }
 
   return true;
 }
 
-void KioskExternalUpdater::PutValidatedExtension(bool* crx_copied,
-                                                 const std::string& app_id,
+void KioskExternalUpdater::PutValidatedExtension(const std::string& app_id,
                                                  const base::FilePath& crx_file,
-                                                 const std::string& version) {
+                                                 const std::string& version,
+                                                 bool crx_copied) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
   if (CheckExternalUpdateInterrupted())
     return;
 
-  if (!*crx_copied) {
+  if (!crx_copied) {
     LOG(ERROR) << "Cannot copy external crx file to " << crx_file.value();
     external_updates_[app_id].update_status = FAILED;
     external_updates_[app_id].error = l10n_util::GetStringFUTF16(
@@ -415,10 +393,8 @@
     return;
   }
 
-  chromeos::KioskAppManager::Get()->PutValidatedExternalExtension(
-      app_id,
-      crx_file,
-      version,
+  KioskAppManager::Get()->PutValidatedExternalExtension(
+      app_id, crx_file, version,
       base::Bind(&KioskExternalUpdater::OnPutValidatedExtension,
                  weak_factory_.GetWeakPtr()));
 }
@@ -426,6 +402,7 @@
 void KioskExternalUpdater::OnPutValidatedExtension(const std::string& app_id,
                                                    bool success) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
   if (CheckExternalUpdateInterrupted())
     return;
 
@@ -461,11 +438,10 @@
 
 void KioskExternalUpdater::NotifyKioskAppUpdateAvailable() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  for (ExternalUpdateMap::iterator it = external_updates_.begin();
-       it != external_updates_.end();
-       ++it) {
-    if (it->second.update_status == SUCCESS) {
-      KioskAppManager::Get()->OnKioskAppCacheUpdated(it->first);
+
+  for (const auto& it : external_updates_) {
+    if (it.second.update_status == SUCCESS) {
+      KioskAppManager::Get()->OnKioskAppCacheUpdated(it.first);
     }
   }
 }
@@ -473,7 +449,7 @@
 void KioskExternalUpdater::NotifyKioskUpdateProgress(
     const base::string16& message) {
   if (!notification_)
-    notification_.reset(new KioskExternalUpdateNotification(message));
+    notification_ = std::make_unique<KioskExternalUpdateNotification>(message);
   else
     notification_->ShowMessage(message);
 }
@@ -484,49 +460,47 @@
   }
 }
 
-base::string16 KioskExternalUpdater::GetUpdateReportMessage() {
+base::string16 KioskExternalUpdater::GetUpdateReportMessage() const {
   DCHECK(!IsExternalUpdatePending());
   int updated = 0;
   int failed = 0;
   base::string16 updated_apps;
   base::string16 failed_apps;
-  for (ExternalUpdateMap::iterator it = external_updates_.begin();
-       it != external_updates_.end();
-       ++it) {
-    base::string16 app_name = base::UTF8ToUTF16(it->second.app_name);
-    if (it->second.update_status == SUCCESS) {
+  for (const auto& it : external_updates_) {
+    const ExternalUpdate& update = it.second;
+    base::string16 app_name = base::UTF8ToUTF16(update.app_name);
+    if (update.update_status == SUCCESS) {
       ++updated;
       if (updated_apps.empty())
         updated_apps = app_name;
       else
-        updated_apps = updated_apps + base::ASCIIToUTF16(", ") + app_name;
+        updated_apps += base::ASCIIToUTF16(", ") + app_name;
     } else {  // FAILED
       ++failed;
       if (failed_apps.empty()) {
-        failed_apps = app_name + base::ASCIIToUTF16(": ") + it->second.error;
+        failed_apps = app_name + base::ASCIIToUTF16(": ") + update.error;
       } else {
-        failed_apps = failed_apps + base::ASCIIToUTF16("\n") + app_name +
-                      base::ASCIIToUTF16(": ") + it->second.error;
+        failed_apps += base::ASCIIToUTF16("\n") + app_name +
+                       base::ASCIIToUTF16(": ") + update.error;
       }
     }
   }
 
-  base::string16 message;
-  message = ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
-      IDS_KIOSK_EXTERNAL_UPDATE_COMPLETE);
-  base::string16 success_app_msg;
+  base::string16 message =
+      ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
+          IDS_KIOSK_EXTERNAL_UPDATE_COMPLETE);
   if (updated) {
-    success_app_msg = l10n_util::GetStringFUTF16(
+    base::string16 success_app_msg = l10n_util::GetStringFUTF16(
         IDS_KIOSK_EXTERNAL_UPDATE_SUCCESSFUL_UPDATED_APPS, updated_apps);
-    message = message + base::ASCIIToUTF16("\n") + success_app_msg;
+    message += base::ASCIIToUTF16("\n") + success_app_msg;
   }
 
-  base::string16 failed_app_msg;
   if (failed) {
-    failed_app_msg = ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
-                         IDS_KIOSK_EXTERNAL_UPDATE_FAILED_UPDATED_APPS) +
-                     base::ASCIIToUTF16("\n") + failed_apps;
-    message = message + base::ASCIIToUTF16("\n") + failed_app_msg;
+    base::string16 failed_app_msg =
+        ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
+            IDS_KIOSK_EXTERNAL_UPDATE_FAILED_UPDATED_APPS) +
+        base::ASCIIToUTF16("\n") + failed_apps;
+    message += base::ASCIIToUTF16("\n") + failed_app_msg;
   }
   return message;
 }
diff --git a/chrome/browser/chromeos/app_mode/kiosk_external_updater.h b/chrome/browser/chromeos/app_mode/kiosk_external_updater.h
index 9da95233..e52a6ec 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_external_updater.h
+++ b/chrome/browser/chromeos/app_mode/kiosk_external_updater.h
@@ -5,13 +5,14 @@
 #ifndef CHROME_BROWSER_CHROMEOS_APP_MODE_KIOSK_EXTERNAL_UPDATER_H_
 #define CHROME_BROWSER_CHROMEOS_APP_MODE_KIOSK_EXTERNAL_UPDATER_H_
 
+#include <map>
 #include <memory>
 #include <string>
+#include <utility>
 
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
 #include "base/sequenced_task_runner.h"
 #include "chrome/browser/chromeos/app_mode/kiosk_external_update_validator.h"
 #include "chromeos/disks/disk_mount_manager.h"
@@ -72,17 +73,18 @@
                      const std::string& device_path) override;
 
   // KioskExternalUpdateValidatorDelegate overrides:
-  void OnExtenalUpdateUnpackSuccess(const std::string& app_id,
-                                    const std::string& version,
-                                    const std::string& min_browser_version,
-                                    const base::FilePath& temp_dir) override;
+  void OnExternalUpdateUnpackSuccess(const std::string& app_id,
+                                     const std::string& version,
+                                     const std::string& min_browser_version,
+                                     const base::FilePath& temp_dir) override;
   void OnExternalUpdateUnpackFailure(const std::string& app_id) override;
 
-  // Processes the parsed external update manifest, check |parsing_error| for
-  // any manifest parsing error.
-  void ProcessParsedManifest(ExternalUpdateErrorCode* parsing_error,
-                             const base::FilePath& external_update_dir,
-                             base::DictionaryValue* parsed_manifest);
+  // Processes the parsed external update manifest, check the
+  // ExternalUpdateErrorCode in |result| for any manifest parsing error.
+  using ParseManifestResult = std::pair<std::unique_ptr<base::DictionaryValue>,
+                                        ExternalUpdateErrorCode>;
+  void ProcessParsedManifest(const base::FilePath& external_update_dir,
+                             const ParseManifestResult& result);
 
   // Returns true if |external_update_| is interrupted before the updating
   // completes.
@@ -92,11 +94,11 @@
   void ValidateExternalUpdates();
 
   // Returns true if there are any external updates pending.
-  bool IsExternalUpdatePending();
+  bool IsExternalUpdatePending() const;
 
   // Returns true if all external updates specified in the manifest are
   // completed successfully.
-  bool IsAllExternalUpdatesSucceeded();
+  bool IsAllExternalUpdatesSucceeded() const;
 
   // Returns true if the app with |app_id| should be updated to
   // |external_extension|.
@@ -105,11 +107,11 @@
                               const std::string& min_browser_version);
 
   // Installs the validated extension into cache.
-  // |*crx_copied| indicates whether the |crx_file| is copied successfully.
-  void PutValidatedExtension(bool* crx_copied,
-                             const std::string& app_id,
+  // |crx_copied| indicates whether the |crx_file| is copied successfully.
+  void PutValidatedExtension(const std::string& app_id,
                              const base::FilePath& crx_file,
-                             const std::string& version);
+                             const std::string& version,
+                             bool crx_copied);
 
   // Called upon completion of installing the validated external extension into
   // the local cache. |success| is true if the operation succeeded.
@@ -129,7 +131,7 @@
   void DismissKioskUpdateNotification();
 
   // Return a detailed message for kiosk updating status.
-  base::string16 GetUpdateReportMessage();
+  base::string16 GetUpdateReportMessage() const;
 
   // Task runner for executing file I/O tasks.
   const scoped_refptr<base::SequencedTaskRunner> backend_task_runner_;
@@ -144,8 +146,9 @@
   base::FilePath external_update_path_;
 
   // map of app_id: ExternalUpdate
-  typedef std::map<std::string, ExternalUpdate> ExternalUpdateMap;
+  using ExternalUpdateMap = std::map<std::string, ExternalUpdate>;
   ExternalUpdateMap external_updates_;
+
   std::unique_ptr<KioskExternalUpdateNotification> notification_;
 
   base::WeakPtrFactory<KioskExternalUpdater> weak_factory_;
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 b89db17e..ecf0afe 100644
--- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
+++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
@@ -60,22 +60,6 @@
   return ui::AX_EVENT_CHILDREN_CHANGED;
 }
 
-const gfx::Rect GetBounds(arc::mojom::AccessibilityNodeInfoData* node) {
-  exo::WMHelper* wm_helper = exo::WMHelper::GetInstance();
-  if (!wm_helper)
-    return gfx::Rect();
-
-  aura::Window* focused_window = wm_helper->GetFocusedWindow();
-  gfx::Rect bounds_in_screen = node->bounds_in_screen;
-  if (focused_window) {
-    aura::Window* toplevel_window = focused_window->GetToplevelWindow();
-    return gfx::ScaleToEnclosingRect(
-        bounds_in_screen,
-        1.0f / toplevel_window->layer()->device_scale_factor());
-  }
-  return bounds_in_screen;
-}
-
 bool GetBooleanProperty(arc::mojom::AccessibilityNodeInfoData* node,
                         arc::mojom::AccessibilityBooleanProperty prop) {
   if (!node->boolean_properties)
@@ -513,10 +497,20 @@
     out_data->AddBoolAttribute(ui::AX_ATTR_SCROLLABLE, true);
   }
 
-  const gfx::Rect bounds_in_screen = GetBounds(node);
-  out_data->location.SetRect(bounds_in_screen.x(), bounds_in_screen.y(),
-                             bounds_in_screen.width(),
-                             bounds_in_screen.height());
+  exo::WMHelper* wm_helper = exo::WMHelper::GetInstance();
+
+  // To get bounds of a node which can be passed to AXNodeData.location,
+  // - Root node must exist.
+  // - Window where this tree is attached to need to be focused.
+  if (root_id_ != -1 && wm_helper) {
+    aura::Window* focused_window = wm_helper->GetFocusedWindow();
+    if (focused_window) {
+      const gfx::Rect bounds_in_screen = GetBounds(node, focused_window);
+      out_data->location.SetRect(bounds_in_screen.x(), bounds_in_screen.y(),
+                                 bounds_in_screen.width(),
+                                 bounds_in_screen.height());
+    }
+  }
 
   if (out_data->role == ui::AX_ROLE_TEXT_FIELD && !text.empty())
     out_data->AddStringAttribute(ui::AX_ATTR_VALUE, text);
@@ -550,6 +544,35 @@
   }
 }
 
+const gfx::Rect AXTreeSourceArc::GetBounds(
+    mojom::AccessibilityNodeInfoData* node,
+    aura::Window* focused_window) const {
+  DCHECK(focused_window);
+  DCHECK(root_id_ != -1);
+
+  gfx::Rect node_bounds = node->bounds_in_screen;
+
+  if (node->id == root_id_) {
+    // Top level window returns its bounds in dip.
+    aura::Window* toplevel_window = focused_window->GetToplevelWindow();
+    float scale = toplevel_window->layer()->device_scale_factor();
+
+    // Bounds of root node is relative to its container, i.e. focused window.
+    node_bounds.Offset(
+        static_cast<int>(-1.0f * scale *
+                         static_cast<float>(toplevel_window->bounds().x())),
+        static_cast<int>(-1.0f * scale *
+                         static_cast<float>(toplevel_window->bounds().y())));
+
+    return node_bounds;
+  }
+
+  // Bounds of non-root node is relative to its tree's root.
+  gfx::Rect root_bounds = GetFromId(root_id_)->bounds_in_screen;
+  node_bounds.Offset(-1 * root_bounds.x(), -1 * root_bounds.y());
+  return node_bounds;
+}
+
 void AXTreeSourceArc::PerformAction(const ui::AXActionData& data) {
   delegate_->OnAction(data);
 }
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h
index 41ffdd7c..740aa89a 100644
--- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h
+++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h
@@ -75,6 +75,14 @@
   void SerializeNode(mojom::AccessibilityNodeInfoData* node,
                      ui::AXNodeData* out_data) const override;
 
+  // Returns bounds of a node which can be passed to AXNodeData.location. Bounds
+  // are returned in the following coordinates depending on whether it's root or
+  // not.
+  // - Root node is relative to its container, i.e. focused window.
+  // - Non-root node is relative to the root node of this tree.
+  const gfx::Rect GetBounds(mojom::AccessibilityNodeInfoData* node,
+                            aura::Window* focused_window) const;
+
   // AXHostDelegate overrides.
   void PerformAction(const ui::AXActionData& data) override;
 
diff --git a/chrome/browser/chromeos/arc/arc_util.cc b/chrome/browser/chromeos/arc/arc_util.cc
index 5e182e37..85b9f4c 100644
--- a/chrome/browser/chromeos/arc/arc_util.cc
+++ b/chrome/browser/chromeos/arc/arc_util.cc
@@ -6,6 +6,7 @@
 
 #include <linux/magic.h>
 #include <sys/statfs.h>
+#include <map>
 #include <set>
 
 #include "base/callback.h"
@@ -41,6 +42,11 @@
 base::LazyInstance<std::set<base::FilePath>>::DestructorAtExit
     g_profile_declined_set = LAZY_INSTANCE_INITIALIZER;
 
+// The cached value of migration allowed for profile. It is necessary to use
+// the same value during a user session.
+base::LazyInstance<std::map<base::FilePath, bool>>::DestructorAtExit
+    g_is_arc_migration_allowed = LAZY_INSTANCE_INITIALIZER;
+
 // Let IsAllowedForProfile() return "false" for any profile.
 bool g_disallow_for_testing = false;
 
@@ -110,6 +116,37 @@
   return inserted;
 }
 
+bool IsArcMigrationAllowedInternal(const Profile* profile) {
+  int migration_strategy =
+      profile->GetPrefs()->GetInteger(prefs::kEcryptfsMigrationStrategy);
+  // |kAskForEcryptfsArcUsers| value is received only if the device is in EDU
+  // and admin left the migration policy unset. Note that when enabling ARC on
+  // the admin console, it is mandatory for the administrator to also choose a
+  // migration policy.
+  // In this default case, only a group of devices that had ARC M enabled are
+  // allowed to migrate, provided that ARC is enabled by policy.
+  // TODO(pmarko): Remove the special kAskForEcryptfsArcUsers handling when we
+  // assess that it's not necessary anymore: crbug.com/761348.
+  if (migration_strategy ==
+      static_cast<int>(
+          arc::policy_util::EcryptfsMigrationAction::kAskForEcryptfsArcUsers)) {
+    // Note that ARC enablement is controlled by policy for managed users (as
+    // it's marked 'default_for_enterprise_users': False in
+    // policy_templates.json).
+    DCHECK(profile->GetPrefs()->IsManagedPreference(prefs::kArcEnabled));
+    // We can't reuse IsArcPlayStoreEnabledForProfile here because this would
+    // lead to a circular dependency: It ends up calling this function for some
+    // cases.
+    return profile->GetPrefs()->GetBoolean(prefs::kArcEnabled) &&
+           base::CommandLine::ForCurrentProcess()->HasSwitch(
+               chromeos::switches::kArcTransitionMigrationRequired);
+  }
+
+  return migration_strategy !=
+         static_cast<int>(
+             arc::policy_util::EcryptfsMigrationAction::kDisallowMigration);
+}
+
 }  // namespace
 
 bool IsArcAllowedForProfile(const Profile* profile) {
@@ -192,34 +229,16 @@
     return true;
   }
 
-  int migration_strategy =
-      profile->GetPrefs()->GetInteger(prefs::kEcryptfsMigrationStrategy);
-  // |kAskForEcryptfsArcUsers| value is received only if the device is in EDU
-  // and admin left the migration policy unset. Note that when enabling ARC on
-  // the admin console, it is mandatory for the administrator to also choose a
-  // migration policy.
-  // In this default case, only a group of devices that had ARC M enabled are
-  // allowed to migrate, provided that ARC is enabled by policy.
-  // TODO(pmarko): Remove the special kAskForEcryptfsArcUsers handling when we
-  // assess that it's not necessary anymore: crbug.com/761348.
-  if (migration_strategy ==
-      static_cast<int>(
-          arc::policy_util::EcryptfsMigrationAction::kAskForEcryptfsArcUsers)) {
-    // Note that ARC enablement is controlled by policy for managed users (as
-    // it's marked 'default_for_enterprise_users': False in
-    // policy_templates.json).
-    DCHECK(profile->GetPrefs()->IsManagedPreference(prefs::kArcEnabled));
-    // We can't reuse IsArcPlayStoreEnabledForProfile here because this would
-    // lead to a circular dependency: It ends up calling this function for some
-    // cases.
-    return profile->GetPrefs()->GetBoolean(prefs::kArcEnabled) &&
-           base::CommandLine::ForCurrentProcess()->HasSwitch(
-               chromeos::switches::kArcTransitionMigrationRequired);
+  // Use the profile path as unique identifier for profile.
+  const base::FilePath path = profile->GetPath();
+  auto iter = g_is_arc_migration_allowed.Get().find(path);
+  if (iter == g_is_arc_migration_allowed.Get().end()) {
+    iter = g_is_arc_migration_allowed.Get()
+               .emplace(path, IsArcMigrationAllowedInternal(profile))
+               .first;
   }
 
-  return migration_strategy !=
-         static_cast<int>(
-             arc::policy_util::EcryptfsMigrationAction::kDisallowMigration);
+  return iter->second;
 }
 
 bool IsArcBlockedDueToIncompatibleFileSystem(const Profile* profile) {
diff --git a/chrome/browser/chromeos/arc/arc_util_unittest.cc b/chrome/browser/chromeos/arc/arc_util_unittest.cc
index e826282e..df1d5e9 100644
--- a/chrome/browser/chromeos/arc/arc_util_unittest.cc
+++ b/chrome/browser/chromeos/arc/arc_util_unittest.cc
@@ -112,7 +112,7 @@
 class FakeUserManagerWithLocalState : public chromeos::FakeChromeUserManager {
  public:
   FakeUserManagerWithLocalState()
-      : test_local_state_(base::MakeUnique<TestingPrefServiceSimple>()) {
+      : test_local_state_(std::make_unique<TestingPrefServiceSimple>()) {
     RegisterPrefs(test_local_state_->registry());
   }
 
@@ -134,13 +134,13 @@
   ~ChromeArcUtilTest() override = default;
 
   void SetUp() override {
-    command_line_ = base::MakeUnique<base::test::ScopedCommandLine>();
+    command_line_ = std::make_unique<base::test::ScopedCommandLine>();
 
     user_manager_enabler_ =
-        base::MakeUnique<chromeos::ScopedUserManagerEnabler>(
+        std::make_unique<chromeos::ScopedUserManagerEnabler>(
             new FakeUserManagerWithLocalState());
     chromeos::WallpaperManager::Initialize();
-    profile_ = base::MakeUnique<TestingProfile>();
+    profile_ = std::make_unique<TestingProfile>();
     profile_->set_profile_name(kTestProfileName);
   }
 
@@ -437,7 +437,7 @@
   // 1) Set managed preference to true, then try to set the value to false
   // via SetArcPlayStoreEnabledForProfile().
   profile()->GetTestingPrefService()->SetManagedPref(
-      prefs::kArcEnabled, base::MakeUnique<base::Value>(true));
+      prefs::kArcEnabled, std::make_unique<base::Value>(true));
   EXPECT_TRUE(IsArcPlayStoreEnabledPreferenceManagedForProfile(profile()));
   EXPECT_TRUE(IsArcPlayStoreEnabledForProfile(profile()));
   SetArcPlayStoreEnabledForProfile(profile(), false);
@@ -451,7 +451,7 @@
   // 2) Set managed preference to false, then try to set the value to true
   // via SetArcPlayStoreEnabledForProfile().
   profile()->GetTestingPrefService()->SetManagedPref(
-      prefs::kArcEnabled, base::MakeUnique<base::Value>(false));
+      prefs::kArcEnabled, std::make_unique<base::Value>(false));
   EXPECT_TRUE(IsArcPlayStoreEnabledPreferenceManagedForProfile(profile()));
   EXPECT_FALSE(IsArcPlayStoreEnabledForProfile(profile()));
   SetArcPlayStoreEnabledForProfile(profile(), true);
@@ -486,7 +486,7 @@
   // Backup-restore pref is managed, while location-service is not, and the
   // function returns false.
   profile()->GetTestingPrefService()->SetManagedPref(
-      prefs::kArcBackupRestoreEnabled, base::MakeUnique<base::Value>(false));
+      prefs::kArcBackupRestoreEnabled, std::make_unique<base::Value>(false));
   EXPECT_FALSE(AreArcAllOptInPreferencesIgnorableForProfile(profile()));
 
   // Location-service pref is managed, while backup-restore is not, and the
@@ -494,12 +494,12 @@
   profile()->GetTestingPrefService()->RemoveManagedPref(
       prefs::kArcBackupRestoreEnabled);
   profile()->GetTestingPrefService()->SetManagedPref(
-      prefs::kArcLocationServiceEnabled, base::MakeUnique<base::Value>(false));
+      prefs::kArcLocationServiceEnabled, std::make_unique<base::Value>(false));
   EXPECT_FALSE(AreArcAllOptInPreferencesIgnorableForProfile(profile()));
 
   // Both OptIn prefs are set to managed values, and the function returns true.
   profile()->GetTestingPrefService()->SetManagedPref(
-      prefs::kArcBackupRestoreEnabled, base::MakeUnique<base::Value>(false));
+      prefs::kArcBackupRestoreEnabled, std::make_unique<base::Value>(false));
   EXPECT_TRUE(AreArcAllOptInPreferencesIgnorableForProfile(profile()));
 }
 
@@ -526,11 +526,11 @@
 
   void SetUp() override {
     user_manager_enabler_ =
-        base::MakeUnique<chromeos::ScopedUserManagerEnabler>(
+        std::make_unique<chromeos::ScopedUserManagerEnabler>(
             new FakeUserManagerWithLocalState());
     // Used by FakeChromeUserManager.
     chromeos::WallpaperManager::Initialize();
-    profile_ = base::MakeUnique<TestingProfile>();
+    profile_ = std::make_unique<TestingProfile>();
     profile_->set_profile_name(kTestProfileName);
   }
 
@@ -570,7 +570,7 @@
                     AccountId::AdFromUserEmailObjGuid(
                         profile()->GetProfileUserName(), kTestGaiaId));
   profile()->GetTestingPrefService()->SetManagedPref(
-      prefs::kEcryptfsMigrationStrategy, base::MakeUnique<base::Value>(0));
+      prefs::kEcryptfsMigrationStrategy, std::make_unique<base::Value>(0));
   EXPECT_FALSE(IsArcMigrationAllowedByPolicyForProfile(profile()));
 }
 
@@ -579,7 +579,7 @@
                     AccountId::AdFromUserEmailObjGuid(
                         profile()->GetProfileUserName(), kTestGaiaId));
   profile()->GetTestingPrefService()->SetManagedPref(
-      prefs::kEcryptfsMigrationStrategy, base::MakeUnique<base::Value>(1));
+      prefs::kEcryptfsMigrationStrategy, std::make_unique<base::Value>(1));
   EXPECT_TRUE(IsArcMigrationAllowedByPolicyForProfile(profile()));
 }
 
@@ -588,7 +588,7 @@
                     AccountId::AdFromUserEmailObjGuid(
                         profile()->GetProfileUserName(), kTestGaiaId));
   profile()->GetTestingPrefService()->SetManagedPref(
-      prefs::kEcryptfsMigrationStrategy, base::MakeUnique<base::Value>(2));
+      prefs::kEcryptfsMigrationStrategy, std::make_unique<base::Value>(2));
   EXPECT_TRUE(IsArcMigrationAllowedByPolicyForProfile(profile()));
 }
 
@@ -597,7 +597,7 @@
                     AccountId::AdFromUserEmailObjGuid(
                         profile()->GetProfileUserName(), kTestGaiaId));
   profile()->GetTestingPrefService()->SetManagedPref(
-      prefs::kEcryptfsMigrationStrategy, base::MakeUnique<base::Value>(3));
+      prefs::kEcryptfsMigrationStrategy, std::make_unique<base::Value>(3));
   EXPECT_TRUE(IsArcMigrationAllowedByPolicyForProfile(profile()));
 }
 
@@ -606,7 +606,35 @@
                     AccountId::AdFromUserEmailObjGuid(
                         profile()->GetProfileUserName(), kTestGaiaId));
   profile()->GetTestingPrefService()->SetManagedPref(
-      prefs::kEcryptfsMigrationStrategy, base::MakeUnique<base::Value>(4));
+      prefs::kEcryptfsMigrationStrategy, std::make_unique<base::Value>(4));
+  EXPECT_TRUE(IsArcMigrationAllowedByPolicyForProfile(profile()));
+}
+
+TEST_F(ArcMigrationTest, IsMigrationAllowedCachedValueForbidden) {
+  ScopedLogIn login(GetFakeUserManager(),
+                    AccountId::AdFromUserEmailObjGuid(
+                        profile()->GetProfileUserName(), kTestGaiaId));
+  profile()->GetTestingPrefService()->SetManagedPref(
+      prefs::kEcryptfsMigrationStrategy, std::make_unique<base::Value>(0));
+  EXPECT_FALSE(IsArcMigrationAllowedByPolicyForProfile(profile()));
+  profile()->GetTestingPrefService()->SetManagedPref(
+      prefs::kEcryptfsMigrationStrategy, std::make_unique<base::Value>(1));
+
+  // The value of IsArcMigrationAllowedByPolicyForProfile() should be cached.
+  // So, even if the policy is set after the first call, the returned value
+  // should not be changed.
+  EXPECT_FALSE(IsArcMigrationAllowedByPolicyForProfile(profile()));
+}
+
+TEST_F(ArcMigrationTest, IsMigrationAllowedCachedValueAllowed) {
+  ScopedLogIn login(GetFakeUserManager(),
+                    AccountId::AdFromUserEmailObjGuid(
+                        profile()->GetProfileUserName(), kTestGaiaId));
+  profile()->GetTestingPrefService()->SetManagedPref(
+      prefs::kEcryptfsMigrationStrategy, std::make_unique<base::Value>(1));
+  EXPECT_TRUE(IsArcMigrationAllowedByPolicyForProfile(profile()));
+  profile()->GetTestingPrefService()->SetManagedPref(
+      prefs::kEcryptfsMigrationStrategy, std::make_unique<base::Value>(0));
   EXPECT_TRUE(IsArcMigrationAllowedByPolicyForProfile(profile()));
 }
 
@@ -639,9 +667,9 @@
         chromeos::switches::kArcTransitionMigrationRequired);
   }
   profile()->GetTestingPrefService()->SetManagedPref(
-      prefs::kEcryptfsMigrationStrategy, base::MakeUnique<base::Value>(5));
+      prefs::kEcryptfsMigrationStrategy, std::make_unique<base::Value>(5));
   profile()->GetTestingPrefService()->SetManagedPref(
-      prefs::kArcEnabled, base::MakeUnique<base::Value>(param.arc_enabled));
+      prefs::kArcEnabled, std::make_unique<base::Value>(param.arc_enabled));
   EXPECT_EQ(param.expect_migration_allowed,
             IsArcMigrationAllowedByPolicyForProfile(profile()));
 }
diff --git a/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.cc b/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.cc
index a398e97..de874b7f 100644
--- a/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.cc
+++ b/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.cc
@@ -820,7 +820,7 @@
     }
   }
 
-  OnPoweredOn(std::move(callback));
+  OnPoweredOn(std::move(callback), false /* save_user_pref */);
 }
 
 void ArcBluetoothBridge::DisableAdapter(DisableAdapterCallback callback) {
@@ -835,7 +835,7 @@
     }
   }
 
-  OnPoweredOff(std::move(callback));
+  OnPoweredOff(std::move(callback), false /* save_user_pref */);
 }
 
 void ArcBluetoothBridge::GetAdapterProperty(mojom::BluetoothPropertyType type) {
@@ -1039,18 +1039,22 @@
 }
 
 void ArcBluetoothBridge::OnPoweredOn(
-    ArcBluetoothBridge::AdapterStateCallback callback) const {
-  // Saves the power state to user preference.
-  SetPrimaryUserBluetoothPowerSetting(true);
+    ArcBluetoothBridge::AdapterStateCallback callback,
+    bool save_user_pref) const {
+  // Saves the power state to user preference only if Android initiated it.
+  if (save_user_pref)
+    SetPrimaryUserBluetoothPowerSetting(true);
 
   std::move(callback).Run(mojom::BluetoothAdapterState::ON);
   SendCachedPairedDevices();
 }
 
 void ArcBluetoothBridge::OnPoweredOff(
-    ArcBluetoothBridge::AdapterStateCallback callback) const {
-  // Saves the power state to user preference.
-  SetPrimaryUserBluetoothPowerSetting(false);
+    ArcBluetoothBridge::AdapterStateCallback callback,
+    bool save_user_pref) const {
+  // Saves the power state to user preference only if Android initiated it.
+  if (save_user_pref)
+    SetPrimaryUserBluetoothPowerSetting(false);
 
   std::move(callback).Run(mojom::BluetoothAdapterState::OFF);
 }
@@ -2191,7 +2195,8 @@
       turn_on,
       base::Bind(turn_on ? &ArcBluetoothBridge::OnPoweredOn
                          : &ArcBluetoothBridge::OnPoweredOff,
-                 weak_factory_.GetWeakPtr(), repeating_callback),
+                 weak_factory_.GetWeakPtr(), repeating_callback,
+                 true /* save_user_pref */),
       base::Bind(&ArcBluetoothBridge::OnPoweredError,
                  weak_factory_.GetWeakPtr(), repeating_callback));
 }
diff --git a/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.h b/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.h
index 175585ca..5ccae585 100644
--- a/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.h
+++ b/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.h
@@ -312,8 +312,8 @@
   enum class AdapterPowerState { TURN_OFF, TURN_ON };
 
   // Chrome observer callbacks
-  void OnPoweredOn(AdapterStateCallback callback) const;
-  void OnPoweredOff(AdapterStateCallback callback) const;
+  void OnPoweredOn(AdapterStateCallback callback, bool save_user_pref) const;
+  void OnPoweredOff(AdapterStateCallback callback, bool save_user_pref) const;
   void OnPoweredError(AdapterStateCallback callback) const;
   void OnDiscoveryStarted(
       std::unique_ptr<device::BluetoothDiscoverySession> session);
diff --git a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service.cc b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service.cc
index 28f0bef..10efb1b 100644
--- a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service.cc
+++ b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service.cc
@@ -289,6 +289,8 @@
     return;
   }
 
+  VLOG(1) << "Retrieving voice interaction context";
+
   content::WebContents* web_contents =
       browser->tab_strip_model()->GetActiveWebContents();
   // Do not process incognito tab.
diff --git a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.cc b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.cc
index b53361b..74a19bb 100644
--- a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.cc
+++ b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.cc
@@ -11,7 +11,7 @@
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/shell.h"
 #include "base/bind.h"
-#include "base/callback.h"
+#include "base/callback_helpers.h"
 #include "base/command_line.h"
 #include "base/containers/flat_set.h"
 #include "base/logging.h"
@@ -152,6 +152,9 @@
       std::move(callback));
 }
 
+template <typename T>
+void DoNothing(T value) {}
+
 // Singleton factory for ArcVoiceInteractionFrameworkService.
 class ArcVoiceInteractionFrameworkServiceFactory
     : public internal::ArcBrowserContextKeyedServiceFactoryBase<
@@ -199,7 +202,10 @@
 ArcVoiceInteractionFrameworkService::ArcVoiceInteractionFrameworkService(
     content::BrowserContext* context,
     ArcBridgeService* bridge_service)
-    : context_(context), arc_bridge_service_(bridge_service), binding_(this) {
+    : context_(context),
+      arc_bridge_service_(bridge_service),
+      binding_(this),
+      weak_ptr_factory_(this) {
   arc_bridge_service_->voice_interaction_framework()->AddObserver(this);
   ArcSessionManager::Get()->AddObserver(this);
   session_manager::SessionManager::Get()->AddObserver(this);
@@ -314,7 +320,8 @@
         value_prop_accepted &&
         (!prefs->GetUserPrefValue(prefs::kVoiceInteractionEnabled) ||
          prefs->GetBoolean(prefs::kVoiceInteractionEnabled));
-    SetVoiceInteractionEnabled(enable_voice_interaction);
+    SetVoiceInteractionEnabled(enable_voice_interaction,
+                               base::BindOnce(&DoNothing<bool>));
 
     SetVoiceInteractionContextEnabled(
         (enable_voice_interaction &&
@@ -356,7 +363,7 @@
   // TODO(xiaohuic): remove deprecated prefs::kVoiceInteractionPrefSynced.
   prefs->SetBoolean(prefs::kVoiceInteractionPrefSynced, false);
   SetVoiceInteractionSetupCompletedInternal(false);
-  SetVoiceInteractionEnabled(false);
+  SetVoiceInteractionEnabled(false, base::BindOnce(&DoNothing<bool>));
   SetVoiceInteractionContextEnabled(false);
 }
 
@@ -393,21 +400,27 @@
 void ArcVoiceInteractionFrameworkService::StartVoiceInteractionSetupWizard() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  arc::mojom::VoiceInteractionFrameworkInstance* framework_instance =
-      ARC_GET_INSTANCE_FOR_METHOD(
-          arc_bridge_service_->voice_interaction_framework(),
-          StartVoiceInteractionSetupWizard);
-
-  if (!framework_instance)
-    return;
-
-  if (should_start_runtime_flow_) {
-    VLOG(1) << "Starting runtime setup flow.";
-    framework_instance->StartVoiceInteractionSession(IsHomescreenActive());
-    return;
-  }
-
-  framework_instance->StartVoiceInteractionSetupWizard();
+  // This screen is shown after the Just-A-Sec screen, which blocks until
+  // application sync'd is received. At that point, framework service should
+  // already be initialized. Here we get a method that is defined in version 1
+  // to ensure the connection is established.
+  // TODO(muyuanli): This is a hack for backward compatibility and should be
+  // removed once Android side is checked in and stablized, then we should
+  // DCHECK the |setting_applied| parameter in the lambda. See
+  // crbug.com/768935.
+  DCHECK(ARC_GET_INSTANCE_FOR_METHOD(
+      arc_bridge_service_->voice_interaction_framework(),
+      StartVoiceInteractionSession));
+  SetVoiceInteractionEnabled(
+      true, base::BindOnce(
+                [](base::OnceClosure next, bool setting_applied) {
+                  if (!setting_applied)
+                    DVLOG(1) << "Not synchronizing settings: version mismatch";
+                  std::move(next).Run();
+                },
+                base::BindOnce(&ArcVoiceInteractionFrameworkService::
+                                   StartVoiceInteractionSetupWizardActivity,
+                               weak_ptr_factory_.GetWeakPtr())));
 }
 
 void ArcVoiceInteractionFrameworkService::ShowVoiceInteractionSettings() {
@@ -434,19 +447,28 @@
 }
 
 void ArcVoiceInteractionFrameworkService::SetVoiceInteractionEnabled(
-    bool enable) {
+    bool enable,
+    VoiceInteractionSettingCompleteCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   ash::Shell::Get()->NotifyVoiceInteractionEnabled(enable);
 
   PrefService* prefs = Profile::FromBrowserContext(context_)->GetPrefs();
 
-  // We assume voice interaction is always enabled on in ARC, but we guard
-  // all possible entry points on CrOS side with this flag. In this case,
-  // we only need to set CrOS side flag.
   prefs->SetBoolean(prefs::kVoiceInteractionEnabled, enable);
   if (!enable)
     prefs->SetBoolean(prefs::kVoiceInteractionContextEnabled, false);
+
+  mojom::VoiceInteractionFrameworkInstance* framework_instance =
+      ARC_GET_INSTANCE_FOR_METHOD(
+          arc_bridge_service_->voice_interaction_framework(),
+          SetVoiceInteractionEnabled);
+  if (!framework_instance) {
+    std::move(callback).Run(false);
+    return;
+  }
+  framework_instance->SetVoiceInteractionEnabled(
+      enable, base::BindOnce(std::move(callback), true));
 }
 
 void ArcVoiceInteractionFrameworkService::SetVoiceInteractionContextEnabled(
@@ -471,7 +493,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   SetVoiceInteractionSetupCompletedInternal(true);
-  SetVoiceInteractionEnabled(true);
+  SetVoiceInteractionEnabled(true, base::BindOnce(&DoNothing<bool>));
   SetVoiceInteractionContextEnabled(true);
 }
 
@@ -603,4 +625,25 @@
   return !ash::Shell::Get()->activation_client()->GetActiveWindow();
 }
 
+void ArcVoiceInteractionFrameworkService::
+    StartVoiceInteractionSetupWizardActivity() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  arc::mojom::VoiceInteractionFrameworkInstance* framework_instance =
+      ARC_GET_INSTANCE_FOR_METHOD(
+          arc_bridge_service_->voice_interaction_framework(),
+          StartVoiceInteractionSetupWizard);
+
+  if (!framework_instance)
+    return;
+
+  if (should_start_runtime_flow_) {
+    should_start_runtime_flow_ = false;
+    VLOG(1) << "Starting runtime setup flow.";
+    framework_instance->StartVoiceInteractionSession(IsHomescreenActive());
+    return;
+  }
+  framework_instance->StartVoiceInteractionSetupWizard();
+}
+
 }  // namespace arc
diff --git a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.h b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.h
index 93790aac..c9828ed 100644
--- a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.h
+++ b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.h
@@ -7,7 +7,9 @@
 
 #include <memory>
 
+#include "base/callback_forward.h"
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
 #include "chrome/browser/chromeos/arc/arc_session_manager.h"
 #include "chromeos/audio/cras_audio_handler.h"
@@ -93,10 +95,13 @@
   // seesion if it is already running.
   void ToggleSessionFromUserInteraction();
 
-  // Turn on / off voice interaction in ARC.
-  // TODO(muyuanli): We should also check on Chrome side once CrOS side settings
-  // are ready (tracked separately at crbug.com/727873).
-  void SetVoiceInteractionEnabled(bool enable);
+  using VoiceInteractionSettingCompleteCallback =
+      base::OnceCallback<void(bool)>;
+  // Turn on / off voice interaction in ARC. |callback| will be called with
+  // |true| if setting is applied to Android side.
+  void SetVoiceInteractionEnabled(
+      bool enable,
+      VoiceInteractionSettingCompleteCallback callback);
 
   // Turn on / off voice interaction context (screenshot and structural data)
   // in ARC.
@@ -130,6 +135,8 @@
 
   bool IsHomescreenActive();
 
+  void StartVoiceInteractionSetupWizardActivity();
+
   content::BrowserContext* context_;
   ArcBridgeService* const arc_bridge_service_;  // Owned by ArcServiceManager
   mojo::Binding<mojom::VoiceInteractionFrameworkHost> binding_;
@@ -159,6 +166,8 @@
   // something malicious is going on.
   int32_t context_request_remaining_count_ = 0;
 
+  base::WeakPtrFactory<ArcVoiceInteractionFrameworkService> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(ArcVoiceInteractionFrameworkService);
 };
 
diff --git a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service_unittest.cc b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service_unittest.cc
index bff9f983..696c6fa99 100644
--- a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service_unittest.cc
+++ b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
+#include "base/bind.h"
 #include "base/files/scoped_temp_dir.h"
 #include "chrome/browser/chromeos/arc/arc_session_manager.h"
 #include "chrome/test/base/testing_profile.h"
@@ -106,7 +107,8 @@
 
 TEST_F(ArcVoiceInteractionFrameworkServiceTest, StartSessionWithoutFlag) {
   // Remove the voice interaction enabled flag.
-  framework_service()->SetVoiceInteractionEnabled(false);
+  framework_service()->SetVoiceInteractionEnabled(false,
+                                                  base::BindOnce([](bool) {}));
 
   framework_service()->StartSessionFromUserInteraction(gfx::Rect());
   // The signal should not be sent when voice interaction disabled.
diff --git a/chrome/browser/chromeos/display/display_preferences.cc b/chrome/browser/chromeos/display/display_preferences.cc
index 161ed1a..abaeb4b 100644
--- a/chrome/browser/chromeos/display/display_preferences.cc
+++ b/chrome/browser/chromeos/display/display_preferences.cc
@@ -39,6 +39,7 @@
 const char kInsetsBottomKey[] = "insets_bottom";
 const char kInsetsRightKey[] = "insets_right";
 
+const char kTouchCalibrationMap[] = "touch_calibration_map";
 const char kTouchCalibrationWidth[] = "touch_calibration_width";
 const char kTouchCalibrationHeight[] = "touch_calibration_height";
 const char kTouchCalibrationPointPairs[] = "touch_calibration_point_pairs";
@@ -122,6 +123,29 @@
   return true;
 }
 
+bool ValueToTouchDataMap(
+    const base::DictionaryValue& value,
+    std::map<uint32_t, display::TouchCalibrationData>* touch_calibration_map) {
+  const base::DictionaryValue* map_dictionary;
+
+  if (!value.GetDictionary(kTouchCalibrationMap, &map_dictionary))
+    return false;
+
+  for (const auto& data_pair : *map_dictionary) {
+    uint32_t touch_device_identifier;
+    if (!base::StringToUint(data_pair.first, &touch_device_identifier))
+      return false;
+    const base::DictionaryValue* data_dict;
+    if (!data_pair.second->GetAsDictionary(&data_dict))
+      return false;
+    display::TouchCalibrationData data;
+    if (!ValueToTouchData(*data_dict, &data))
+      return false;
+    touch_calibration_map->emplace(touch_device_identifier, data);
+  }
+  return true;
+}
+
 // Stores the touch calibration data into the dictionary.
 void TouchDataToValue(
     const display::TouchCalibrationData& touch_calibration_data,
@@ -151,6 +175,25 @@
                     touch_calibration_data.bounds.height());
 }
 
+// Stores the entire touch calibration data map to the dictionary.
+void TouchDataMapToValue(
+    const std::map<uint32_t, display::TouchCalibrationData>& touch_data_map,
+    base::DictionaryValue* value) {
+  std::unique_ptr<base::DictionaryValue> touch_data_map_dictionary =
+      std::make_unique<base::DictionaryValue>();
+
+  for (const auto& pair : touch_data_map) {
+    std::unique_ptr<base::DictionaryValue> touch_data_dictionary =
+        std::make_unique<base::DictionaryValue>();
+    TouchDataToValue(pair.second, touch_data_dictionary.get());
+
+    touch_data_map_dictionary->SetDictionary(base::UintToString(pair.first),
+                                             std::move(touch_data_dictionary));
+  }
+  value->SetDictionary(kTouchCalibrationMap,
+                       std::move(touch_data_map_dictionary));
+}
+
 display::DisplayManager* GetDisplayManager() {
   return ash::Shell::Get()->display_manager();
 }
@@ -237,14 +280,39 @@
     if (ValueToInsets(*dict_value, &insets))
       insets_to_set = &insets;
 
+    // Retrive any legacy touch calibration data.
     display::TouchCalibrationData calibration_data;
     display::TouchCalibrationData* calibration_data_to_set = nullptr;
     if (ValueToTouchData(*dict_value, &calibration_data))
       calibration_data_to_set = &calibration_data;
 
+    std::map<uint32_t, display::TouchCalibrationData> calibration_data_map;
+    std::map<uint32_t, display::TouchCalibrationData>*
+        calibration_data_map_to_set = nullptr;
+    if (ValueToTouchDataMap(*dict_value, &calibration_data_map))
+      calibration_data_map_to_set = &calibration_data_map;
+
+    // Migrate legacy touch calibration data to updated model. Use it as a
+    // fallback mechanism.
+    if (calibration_data_to_set) {
+      const uint32_t fallback_identifier =
+          display::TouchCalibrationData::GetFallbackTouchDeviceIdentifier();
+      // Store the legacy cailbration data in the calibration data map if we
+      // have a non-null calibration data map with no previous fallback
+      // calibration data stored in it.
+      if (calibration_data_map_to_set &&
+          calibration_data_map_to_set->count(fallback_identifier) == 0) {
+        (*calibration_data_map_to_set)[fallback_identifier] =
+            *calibration_data_to_set;
+      } else {
+        calibration_data_map[fallback_identifier] = *calibration_data_to_set;
+        calibration_data_map_to_set = &calibration_data_map;
+      }
+    }
+
     GetDisplayManager()->RegisterDisplayProperty(
         id, rotation, ui_scale, insets_to_set, resolution_in_pixels,
-        device_scale_factor, calibration_data_to_set);
+        device_scale_factor, calibration_data_map_to_set);
   }
 }
 
@@ -341,8 +409,12 @@
     }
     if (!info.overscan_insets_in_dip().IsEmpty())
       InsetsToValue(info.overscan_insets_in_dip(), property_value.get());
-    if (info.has_touch_calibration_data())
-      TouchDataToValue(info.GetTouchCalibrationData(), property_value.get());
+
+    if (info.touch_calibration_data_map().size()) {
+      TouchDataMapToValue(info.touch_calibration_data_map(),
+                          property_value.get());
+    }
+
     pref_data->Set(base::Int64ToString(id), std::move(property_value));
   }
 }
diff --git a/chrome/browser/chromeos/display/display_preferences_unittest.cc b/chrome/browser/chromeos/display/display_preferences_unittest.cc
index c0d6ee7..a846394 100644
--- a/chrome/browser/chromeos/display/display_preferences_unittest.cc
+++ b/chrome/browser/chromeos/display/display_preferences_unittest.cc
@@ -50,6 +50,7 @@
 const char kOffsetKey[] = "offset";
 const char kPlacementDisplayIdKey[] = "placement.display_id";
 const char kPlacementParentDisplayIdKey[] = "placement.parent_display_id";
+const char kTouchCalibrationMap[] = "touch_calibration_map";
 const char kTouchCalibrationWidth[] = "touch_calibration_width";
 const char kTouchCalibrationHeight[] = "touch_calibration_height";
 const char kTouchCalibrationPointPairs[] = "touch_calibration_point_pairs";
@@ -288,13 +289,26 @@
                    .SetDisplayUIScale(id2, 1.25f));
 
   // Set touch calibration data for display |id2|.
-  display::TouchCalibrationData::CalibrationPointPairQuad point_pair_quad = {
+  constexpr uint32_t touch_device_identifier_1 = 1234;
+  display::TouchCalibrationData::CalibrationPointPairQuad point_pair_quad_1 = {
       {std::make_pair(gfx::Point(10, 10), gfx::Point(11, 12)),
        std::make_pair(gfx::Point(190, 10), gfx::Point(195, 8)),
        std::make_pair(gfx::Point(10, 90), gfx::Point(12, 94)),
        std::make_pair(gfx::Point(190, 90), gfx::Point(189, 88))}};
-  gfx::Size touch_size(200, 150);
-  display_manager()->SetTouchCalibrationData(id2, point_pair_quad, touch_size);
+  gfx::Size touch_size_1(200, 150);
+
+  constexpr uint32_t touch_device_identifier_2 = 2345;
+  display::TouchCalibrationData::CalibrationPointPairQuad point_pair_quad_2 = {
+      {std::make_pair(gfx::Point(10, 10), gfx::Point(11, 12)),
+       std::make_pair(gfx::Point(190, 10), gfx::Point(195, 8)),
+       std::make_pair(gfx::Point(10, 90), gfx::Point(12, 94)),
+       std::make_pair(gfx::Point(190, 90), gfx::Point(189, 88))}};
+  gfx::Size touch_size_2(150, 150);
+
+  display_manager()->SetTouchCalibrationData(
+      id2, point_pair_quad_1, touch_size_1, touch_device_identifier_1);
+  display_manager()->SetTouchCalibrationData(
+      id2, point_pair_quad_2, touch_size_2, touch_device_identifier_2);
 
   const base::DictionaryValue* displays =
       local_state()->GetDictionary(prefs::kSecondaryDisplays);
@@ -344,9 +358,9 @@
   EXPECT_EQ(13, right);
 
   std::string touch_str;
-  EXPECT_FALSE(property->GetString(kTouchCalibrationPointPairs, &touch_str));
-  EXPECT_FALSE(property->GetInteger(kTouchCalibrationWidth, &width));
-  EXPECT_FALSE(property->GetInteger(kTouchCalibrationHeight, &height));
+  const base::DictionaryValue* map_dictionary;
+  const base::DictionaryValue* data_dict;
+  EXPECT_FALSE(property->GetDictionary(kTouchCalibrationMap, &map_dictionary));
 
   EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id2), &property));
   EXPECT_TRUE(property->GetInteger("rotation", &rotation));
@@ -361,22 +375,48 @@
 
   display::TouchCalibrationData::CalibrationPointPairQuad stored_pair_quad;
 
-  EXPECT_TRUE(property->GetString(kTouchCalibrationPointPairs, &touch_str));
+  EXPECT_TRUE(property->GetDictionary(kTouchCalibrationMap, &map_dictionary));
+  EXPECT_TRUE(map_dictionary->GetDictionary(
+      base::UintToString(touch_device_identifier_1), &data_dict));
+  EXPECT_TRUE(data_dict->GetString(kTouchCalibrationPointPairs, &touch_str));
   EXPECT_TRUE(ParseTouchCalibrationStringForTest(touch_str, &stored_pair_quad));
 
-  for (std::size_t row = 0; row < point_pair_quad.size(); row++) {
-    EXPECT_EQ(point_pair_quad[row].first.x(), stored_pair_quad[row].first.x());
-    EXPECT_EQ(point_pair_quad[row].first.y(), stored_pair_quad[row].first.y());
-    EXPECT_EQ(point_pair_quad[row].second.x(),
+  for (std::size_t row = 0; row < point_pair_quad_1.size(); row++) {
+    EXPECT_EQ(point_pair_quad_1[row].first.x(),
+              stored_pair_quad[row].first.x());
+    EXPECT_EQ(point_pair_quad_1[row].first.y(),
+              stored_pair_quad[row].first.y());
+    EXPECT_EQ(point_pair_quad_1[row].second.x(),
               stored_pair_quad[row].second.x());
-    EXPECT_EQ(point_pair_quad[row].second.y(),
+    EXPECT_EQ(point_pair_quad_1[row].second.y(),
               stored_pair_quad[row].second.y());
   }
   width = height = 0;
-  EXPECT_TRUE(property->GetInteger(kTouchCalibrationWidth, &width));
-  EXPECT_TRUE(property->GetInteger(kTouchCalibrationHeight, &height));
-  EXPECT_EQ(width, touch_size.width());
-  EXPECT_EQ(height, touch_size.height());
+  EXPECT_TRUE(data_dict->GetInteger(kTouchCalibrationWidth, &width));
+  EXPECT_TRUE(data_dict->GetInteger(kTouchCalibrationHeight, &height));
+  EXPECT_EQ(width, touch_size_1.width());
+  EXPECT_EQ(height, touch_size_1.height());
+
+  EXPECT_TRUE(map_dictionary->GetDictionary(
+      base::UintToString(touch_device_identifier_2), &data_dict));
+  EXPECT_TRUE(data_dict->GetString(kTouchCalibrationPointPairs, &touch_str));
+  EXPECT_TRUE(ParseTouchCalibrationStringForTest(touch_str, &stored_pair_quad));
+
+  for (std::size_t row = 0; row < point_pair_quad_2.size(); row++) {
+    EXPECT_EQ(point_pair_quad_2[row].first.x(),
+              stored_pair_quad[row].first.x());
+    EXPECT_EQ(point_pair_quad_2[row].first.y(),
+              stored_pair_quad[row].first.y());
+    EXPECT_EQ(point_pair_quad_2[row].second.x(),
+              stored_pair_quad[row].second.x());
+    EXPECT_EQ(point_pair_quad_2[row].second.y(),
+              stored_pair_quad[row].second.y());
+  }
+  width = height = 0;
+  EXPECT_TRUE(data_dict->GetInteger(kTouchCalibrationWidth, &width));
+  EXPECT_TRUE(data_dict->GetInteger(kTouchCalibrationHeight, &height));
+  EXPECT_EQ(width, touch_size_2.width());
+  EXPECT_EQ(height, touch_size_2.height());
 
   // Resolution is saved only when the resolution is set
   // by DisplayManager::SetDisplayMode
@@ -478,7 +518,7 @@
   // Set new display's selected resolution.
   display_manager()->RegisterDisplayProperty(
       id2 + 1, display::Display::ROTATE_0, 1.0f, nullptr, gfx::Size(500, 400),
-      1.0f, nullptr);
+      1.0f, nullptr /* touch_calibration_data_map */);
 
   UpdateDisplay("200x200*2, 600x500#600x500|500x400");
 
@@ -504,7 +544,7 @@
   // Set yet another new display's selected resolution.
   display_manager()->RegisterDisplayProperty(
       id2 + 1, display::Display::ROTATE_0, 1.0f, nullptr, gfx::Size(500, 400),
-      1.0f, nullptr);
+      1.0f, nullptr /* touch_calibration_data_map */);
   // Disconnect 2nd display first to generate new id for external display.
   UpdateDisplay("200x200*2");
   UpdateDisplay("200x200*2, 500x400#600x500|500x400%60.0f");
diff --git a/chrome/browser/chromeos/file_manager/app_id.h b/chrome/browser/chromeos/file_manager/app_id.h
index aca6fe3..f62b474b 100644
--- a/chrome/browser/chromeos/file_manager/app_id.h
+++ b/chrome/browser/chromeos/file_manager/app_id.h
@@ -22,6 +22,9 @@
 // The audio player's app ID.
 const char kAudioPlayerAppId[] = "cjbfomnbifhcdnihkgipgfcihmgjfhbf";
 
+// The text editor's app ID.
+const char kTextEditorAppId[] = "mmfbcljfglbokpmkimbfghdkjmjhdgbg";
+
 // The image loader extension's ID.
 const char kImageLoaderExtensionId[] = "pmfjbimdmchhbnneeidfognadeopoehp";
 
diff --git a/chrome/browser/chromeos/file_manager/file_tasks.cc b/chrome/browser/chromeos/file_manager/file_tasks.cc
index 4faef6f3..cc2670ca 100644
--- a/chrome/browser/chromeos/file_manager/file_tasks.cc
+++ b/chrome/browser/chromeos/file_manager/file_tasks.cc
@@ -128,9 +128,7 @@
     return false;
 
   const char* const kBuiltInApps[] = {
-    kFileManagerAppId,
-    kVideoPlayerAppId,
-    kGalleryAppId,
+      kFileManagerAppId, kVideoPlayerAppId, kGalleryAppId, kTextEditorAppId,
   };
 
   for (size_t i = 0; i < arraysize(kBuiltInApps); ++i) {
diff --git a/chrome/browser/chromeos/file_manager/file_tasks_unittest.cc b/chrome/browser/chromeos/file_manager/file_tasks_unittest.cc
index a0f9239..40ef157 100644
--- a/chrome/browser/chromeos/file_manager/file_tasks_unittest.cc
+++ b/chrome/browser/chromeos/file_manager/file_tasks_unittest.cc
@@ -335,6 +335,30 @@
   EXPECT_TRUE(tasks[0].is_default());
 }
 
+// Test that Text.app is chosen as default even if nothing is set in the
+// preferences.
+TEST(FileManagerFileTasksTest, ChooseAndSetDefaultTask_FallbackTextApp) {
+  TestingPrefServiceSimple pref_service;
+  RegisterDefaultTaskPreferences(&pref_service);
+
+  // The text editor app was found for "foo.txt".
+  TaskDescriptor files_app_task(kTextEditorAppId, TASK_TYPE_FILE_HANDLER,
+                                "Text");
+  std::vector<FullTaskDescriptor> tasks;
+  tasks.push_back(FullTaskDescriptor(
+      files_app_task, "Text", Verb::VERB_OPEN_WITH,
+      GURL("chrome://extension-icon/mmfbcljfglbokpmkimbfghdkjmjhdgbg/16/1"),
+      false /* is_default */, false /* is_generic_file_handler */));
+  std::vector<extensions::EntryInfo> entries;
+  entries.push_back(extensions::EntryInfo(
+      base::FilePath::FromUTF8Unsafe("foo.txt"), "text/plain", false));
+
+  // The text editor app should be chosen as default, as it's a fallback file
+  // browser handler.
+  ChooseAndSetDefaultTask(pref_service, entries, &tasks);
+  EXPECT_TRUE(tasks[0].is_default());
+}
+
 // Test IsGoodMatchFileHandler which returns whether a file handle info matches
 // with files as good match or not.
 TEST(FileManagerFileTasksTest, IsGoodMatchFileHandler) {
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 4e3aae19..a249b91 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc
+++ b/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc
@@ -33,6 +33,7 @@
 #include "ui/events/event.h"
 #include "ui/events/keycodes/dom/dom_code.h"
 #include "ui/events/keycodes/dom/keycode_converter.h"
+#include "ui/keyboard/keyboard_util.h"
 
 namespace chromeos {
 namespace input_method {
@@ -1074,13 +1075,12 @@
       ui::IMEBridge::Get()->GetCurrentEngineHandler();
   ASSERT_TRUE(engine_handler);
 
-  extensions::VirtualKeyboardAPI* virtual_keyboard_api =
-      extensions::BrowserContextKeyedAPIFactory<
-          extensions::VirtualKeyboardAPI>::Get(profile());
-  ASSERT_TRUE(virtual_keyboard_api);
-  ASSERT_TRUE(virtual_keyboard_api->delegate());
-  virtual_keyboard_api->delegate()->SetKeyboardRestricted(true);
-
+  keyboard::KeyboardConfig keyboard_config = keyboard::GetKeyboardConfig();
+  // Turn off these features, which are on by default.
+  keyboard_config.auto_correct = false;
+  keyboard_config.auto_complete = false;
+  keyboard_config.spell_check = false;
+  keyboard::UpdateKeyboardConfig(keyboard_config);
   extensions::ExtensionHost* host =
       extensions::ProcessManager::Get(profile())->GetBackgroundHostForExtension(
           extension_->id());
diff --git a/chrome/browser/chromeos/login/easy_unlock/bootstrap_browsertest.cc b/chrome/browser/chromeos/login/easy_unlock/bootstrap_browsertest.cc
deleted file mode 100644
index 5210658..0000000
--- a/chrome/browser/chromeos/login/easy_unlock/bootstrap_browsertest.cc
+++ /dev/null
@@ -1,169 +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 <string>
-
-#include "base/command_line.h"
-#include "base/macros.h"
-#include "base/path_service.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/chromeos/login/easy_unlock/bootstrap_user_context_initializer.h"
-#include "chrome/browser/chromeos/login/session/user_session_manager.h"
-#include "chrome/browser/chromeos/login/session/user_session_manager_test_api.h"
-#include "chrome/browser/chromeos/login/test/oobe_base_test.h"
-#include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
-#include "chrome/browser/chromeos/login/wizard_controller.h"
-#include "chrome/browser/signin/easy_unlock_service_factory.h"
-#include "chrome/common/chrome_paths.h"
-#include "chromeos/chromeos_switches.h"
-#include "components/proximity_auth/switches.h"
-#include "components/user_manager/user_manager.h"
-#include "content/public/test/browser_test_utils.h"
-#include "content/public/test/test_utils.h"
-#include "google_apis/gaia/gaia_constants.h"
-#include "google_apis/gaia/gaia_urls.h"
-#include "net/test/embedded_test_server/embedded_test_server.h"
-
-namespace chromeos {
-
-namespace {
-
-const char kFakeGaiaId[] = "123456";
-const char kFakeUser[] = "test_user@consumer.example.com";
-const char kFakeSid[] = "fake-sid";
-const char kFakeLsid[] = "fake-lsid";
-const char kFakeRefreshToken[] = "fake-refresh-token";
-const char kFakeUserInfoToken[] = "fake-user-info-token";
-
-class ScopedCompleteCallbackForTesting {
- public:
-  explicit ScopedCompleteCallbackForTesting(
-      const BootstrapUserContextInitializer::CompleteCallback& callback);
-  ~ScopedCompleteCallbackForTesting();
-
- private:
-  BootstrapUserContextInitializer::CompleteCallback callback_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedCompleteCallbackForTesting);
-};
-
-ScopedCompleteCallbackForTesting::ScopedCompleteCallbackForTesting(
-    const BootstrapUserContextInitializer::CompleteCallback& callback)
-    : callback_(callback) {
-  BootstrapUserContextInitializer::SetCompleteCallbackForTesting(&callback_);
-}
-
-ScopedCompleteCallbackForTesting::~ScopedCompleteCallbackForTesting() {
-  BootstrapUserContextInitializer::SetCompleteCallbackForTesting(NULL);
-}
-
-}  // namespace
-
-class BootstrapTest : public OobeBaseTest {
- public:
-  BootstrapTest() {}
-
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    OobeBaseTest::SetUpCommandLine(command_line);
-
-    base::CommandLine::ForCurrentProcess()->AppendSwitch(
-        proximity_auth::switches::kForceLoadEasyUnlockAppInTests);
-
-    base::CommandLine::ForCurrentProcess()->AppendSwitch(
-        proximity_auth::switches::kDisableBluetoothLowEnergyDiscovery);
-
-    const GURL& server_url = embedded_test_server()->base_url();
-    GURL::Replacements replace_host;
-    replace_host.SetHostStr("eafe");
-    GURL eafe_url = server_url.ReplaceComponents(replace_host);
-
-    command_line->AppendSwitchASCII(switches::kEafeUrl, eafe_url.spec());
-    command_line->AppendSwitchASCII(switches::kEafePath,
-                                    "login/easy_unlock/auth_code_login.html");
-  }
-
-  void SetUpOnMainThread() override {
-    OobeBaseTest::SetUpOnMainThread();
-
-    GaiaUrls* gaia_urls = GaiaUrls::GetInstance();
-
-    fake_gaia_->SetFakeMergeSessionParams(kFakeUser, kFakeSid, kFakeLsid);
-    fake_gaia_->MapEmailToGaiaId(kFakeUser, kFakeGaiaId);
-
-    FakeGaia::AccessTokenInfo userinfo_token_info;
-    userinfo_token_info.token = kFakeUserInfoToken;
-    userinfo_token_info.scopes.insert(GaiaConstants::kGoogleUserInfoEmail);
-    userinfo_token_info.scopes.insert(GaiaConstants::kGoogleUserInfoProfile);
-    userinfo_token_info.audience = gaia_urls->oauth2_chrome_client_id();
-    userinfo_token_info.email = kFakeUser;
-    fake_gaia_->IssueOAuthToken(kFakeRefreshToken, userinfo_token_info);
-  }
-
-  void SetExpectedCredentials(const UserContext& user_context) {
-    test::UserSessionManagerTestApi session_manager_test_api(
-        UserSessionManager::GetInstance());
-    session_manager_test_api.InjectStubUserContext(user_context);
-  }
-
-  bool JsExecute(const std::string& script) {
-    return content::ExecuteScript(GetLoginUI()->GetWebContents(), script);
-  }
-
-  void SetTestEasyUnlockAppPath(const std::string& relative_path) {
-    base::FilePath test_data_dir;
-    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir));
-    EasyUnlockServiceFactory::GetInstance()->set_app_path_for_testing(
-        test_data_dir.AppendASCII(relative_path));
-  }
-
-  void StartSignInScreen() {
-    WizardController::SkipPostLoginScreensForTesting();
-    WizardController* wizard_controller =
-        WizardController::default_controller();
-    ASSERT_TRUE(wizard_controller);
-    wizard_controller->SkipToLoginForTesting(LoginScreenContext());
-    OobeScreenWaiter(OobeScreen::SCREEN_GAIA_SIGNIN).Wait();
-  }
-
-  void OnBootstrapInitialized(bool success, const UserContext& user_context) {
-    EXPECT_TRUE(success);
-    SetExpectedCredentials(user_context);
-  }
-
-  void EafeLogin() {
-    StartSignInScreen();
-    JsExecute("cr.ui.Oobe.handleAccelerator('toggle_easy_bootstrap');");
-  }
-};
-
-IN_PROC_BROWSER_TEST_F(BootstrapTest, Basic) {
-  ScopedCompleteCallbackForTesting scoped_bootstrap_initialized(base::Bind(
-      &BootstrapTest::OnBootstrapInitialized, base::Unretained(this)));
-
-  SetTestEasyUnlockAppPath("login/easy_unlock/auto_pair_success");
-
-  EafeLogin();
-
-  content::WindowedNotificationObserver(
-      chrome::NOTIFICATION_SESSION_STARTED,
-      content::NotificationService::AllSources()).Wait();
-}
-
-IN_PROC_BROWSER_TEST_F(BootstrapTest, PRE_CleanUpFailedUser) {
-  ScopedCompleteCallbackForTesting scoped_bootstrap_initialized(base::Bind(
-      &BootstrapTest::OnBootstrapInitialized, base::Unretained(this)));
-
-  SetTestEasyUnlockAppPath("login/easy_unlock/auto_pair_failure");
-
-  EafeLogin();
-
-  // Failed bootstrap should attempt exit and get out of this loop.
-  content::RunMessageLoop();
-}
-
-IN_PROC_BROWSER_TEST_F(BootstrapTest, CleanUpFailedUser) {
-  EXPECT_FALSE(user_manager::UserManager::Get()->IsKnownUser(
-      AccountId::FromUserEmail(kFakeUser)));
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/easy_unlock/bootstrap_manager.cc b/chrome/browser/chromeos/login/easy_unlock/bootstrap_manager.cc
deleted file mode 100644
index d7d9c09..0000000
--- a/chrome/browser/chromeos/login/easy_unlock/bootstrap_manager.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/chromeos/login/easy_unlock/bootstrap_manager.h"
-
-#include <stddef.h>
-
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chromeos/login/users/chrome_user_manager_impl.h"
-#include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/pref_service.h"
-#include "components/prefs/scoped_user_pref_update.h"
-#include "components/signin/core/account_id/account_id.h"
-#include "components/user_manager/known_user.h"
-
-namespace chromeos {
-
-namespace {
-
-// A pref list of users who have not finished Easy bootstrapping.
-const char kPendingEasyBootstrapUsers[] = "PendingEasyBootstrapUsers";
-
-}  // namespace
-
-// static
-void BootstrapManager::RegisterPrefs(PrefRegistrySimple* registry) {
-  registry->RegisterListPref(kPendingEasyBootstrapUsers);
-}
-
-BootstrapManager::BootstrapManager(Delegate* delegate)
-    : delegate_(delegate) {
-}
-
-BootstrapManager::~BootstrapManager() {
-}
-
-void BootstrapManager::AddPendingBootstrap(const AccountId& account_id) {
-  DCHECK(account_id.is_valid());
-  PrefService* local_state = g_browser_process->local_state();
-
-  ListPrefUpdate update(local_state, kPendingEasyBootstrapUsers);
-  update->AppendString(account_id.GetUserEmail());
-}
-
-void BootstrapManager::FinishPendingBootstrap(const AccountId& account_id) {
-  PrefService* local_state = g_browser_process->local_state();
-
-  ListPrefUpdate update(local_state, kPendingEasyBootstrapUsers);
-  for (size_t i = 0; i < update->GetSize(); ++i) {
-    std::string current_user_email;
-    if (update->GetString(i, &current_user_email) &&
-        account_id.GetUserEmail() == current_user_email) {
-      update->Remove(i, NULL);
-      break;
-    }
-  }
-}
-
-void BootstrapManager::RemoveAllPendingBootstrap() {
-  PrefService* local_state = g_browser_process->local_state();
-
-  const base::ListValue* users =
-      local_state->GetList(kPendingEasyBootstrapUsers);
-  for (size_t i = 0; i < users->GetSize(); ++i) {
-    std::string current_user_email;
-    if (users->GetString(i, &current_user_email)) {
-      delegate_->RemovePendingBootstrapUser(
-          user_manager::known_user::GetAccountId(current_user_email,
-                                                 std::string() /* id */,
-                                                 AccountType::UNKNOWN));
-    }
-  }
-
-  local_state->ClearPref(kPendingEasyBootstrapUsers);
-  local_state->CommitPendingWrite();
-}
-
-bool BootstrapManager::HasPendingBootstrap(const AccountId& account_id) const {
-  PrefService* local_state = g_browser_process->local_state();
-
-  const base::ListValue* users =
-      local_state->GetList(kPendingEasyBootstrapUsers);
-  for (size_t i = 0; i < users->GetSize(); ++i) {
-    std::string current_user;
-    if (users->GetString(i, &current_user) &&
-        account_id.GetUserEmail() == current_user)
-      return true;
-  }
-  return false;
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/easy_unlock/bootstrap_manager.h b/chrome/browser/chromeos/login/easy_unlock/bootstrap_manager.h
deleted file mode 100644
index 88879c8..0000000
--- a/chrome/browser/chromeos/login/easy_unlock/bootstrap_manager.h
+++ /dev/null
@@ -1,48 +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_CHROMEOS_LOGIN_EASY_UNLOCK_BOOTSTRAP_MANAGER_H_
-#define CHROME_BROWSER_CHROMEOS_LOGIN_EASY_UNLOCK_BOOTSTRAP_MANAGER_H_
-
-#include <string>
-
-#include "base/macros.h"
-
-class AccountId;
-class PrefRegistrySimple;
-
-namespace chromeos {
-
-// BootstrapManager manages bootstrap user specific values such as tracking
-// pending bootstrap and clearing such state.
-class BootstrapManager {
- public:
-  static void RegisterPrefs(PrefRegistrySimple* registry);
-
-  class Delegate {
-   public:
-    virtual void RemovePendingBootstrapUser(const AccountId& account_id) = 0;
-
-   protected:
-    virtual ~Delegate() {}
-  };
-
-  explicit BootstrapManager(Delegate* delegate);
-  ~BootstrapManager();
-
-  void AddPendingBootstrap(const AccountId& account_id);
-  void FinishPendingBootstrap(const AccountId& account_id);
-  void RemoveAllPendingBootstrap();
-
-  bool HasPendingBootstrap(const AccountId& account_id) const;
-
- private:
-  Delegate* delegate_;
-
-  DISALLOW_COPY_AND_ASSIGN(BootstrapManager);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_EASY_UNLOCK_BOOTSTRAP_MANAGER_H_
diff --git a/chrome/browser/chromeos/login/easy_unlock/bootstrap_user_context_initializer.cc b/chrome/browser/chromeos/login/easy_unlock/bootstrap_user_context_initializer.cc
deleted file mode 100644
index d2434ec..0000000
--- a/chrome/browser/chromeos/login/easy_unlock/bootstrap_user_context_initializer.cc
+++ /dev/null
@@ -1,212 +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 "chrome/browser/chromeos/login/easy_unlock/bootstrap_user_context_initializer.h"
-
-#include <vector>
-
-#include "base/strings/string_util.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
-#include "chrome/browser/chromeos/login/session/user_session_manager.h"
-#include "chrome/browser/chromeos/profiles/profile_helper.h"
-#include "chrome/browser/signin/easy_unlock_service_signin_chromeos.h"
-#include "components/user_manager/known_user.h"
-#include "components/user_manager/user_manager.h"
-#include "components/user_manager/user_names.h"
-#include "crypto/random.h"
-#include "google_apis/gaia/gaia_constants.h"
-#include "google_apis/gaia/gaia_urls.h"
-
-namespace chromeos {
-
-namespace {
-
-const int kMaxGaiaRetries = 5;
-const int kUserKeyByteSize = 16;
-
-}  // namespace
-
-BootstrapUserContextInitializer::CompleteCallback*
-    BootstrapUserContextInitializer::complete_callback_for_testing_ = NULL;
-
-// static
-void BootstrapUserContextInitializer::SetCompleteCallbackForTesting(
-    CompleteCallback* callback) {
-  complete_callback_for_testing_ = callback;
-}
-
-BootstrapUserContextInitializer::BootstrapUserContextInitializer()
-    : random_key_used_(false),
-      weak_ptr_factory_(this) {
-}
-
-BootstrapUserContextInitializer::~BootstrapUserContextInitializer() {
-}
-
-void BootstrapUserContextInitializer::Start(const std::string& auth_code,
-                                            const CompleteCallback& callback) {
-  DCHECK(!callback.is_null());
-  callback_ = callback;
-
-  user_context_.SetAuthFlow(UserContext::AUTH_FLOW_EASY_BOOTSTRAP);
-  StartTokenFetch(auth_code);
-}
-
-void BootstrapUserContextInitializer::StartTokenFetch(
-    const std::string& auth_code) {
-  DCHECK(!token_fetcher_);
-
-  gaia::OAuthClientInfo client_info;
-  GaiaUrls* gaia_urls = GaiaUrls::GetInstance();
-  client_info.client_id = gaia_urls->oauth2_chrome_client_id();
-  client_info.client_secret = gaia_urls->oauth2_chrome_client_secret();
-
-  token_fetcher_.reset(
-      new gaia::GaiaOAuthClient(g_browser_process->system_request_context()));
-  token_fetcher_->GetTokensFromAuthCode(client_info, auth_code, kMaxGaiaRetries,
-                                        this);
-}
-
-void BootstrapUserContextInitializer::StartCheckExistingKeys() {
-  // Use random key for the first time user.
-  if (!user_manager::UserManager::Get()->IsKnownUser(
-          user_context_.GetAccountId())) {
-    CreateRandomKey();
-    return;
-  }
-
-  EasyUnlockKeyManager* key_manager =
-      UserSessionManager::GetInstance()->GetEasyUnlockKeyManager();
-  key_manager->GetDeviceDataList(
-      UserContext(user_context_.GetAccountId()),
-      base::Bind(&BootstrapUserContextInitializer::OnGetEasyUnlockData,
-                 weak_ptr_factory_.GetWeakPtr()));
-}
-
-void BootstrapUserContextInitializer::OnGetEasyUnlockData(
-    bool success,
-    const EasyUnlockDeviceKeyDataList& data_list) {
-  // Existing user must have Smart lock keys to use bootstrap flow.
-  if (!success || data_list.empty()) {
-    LOG(ERROR) << "Unable to get Easy unlock key data.";
-    Notify(false);
-    return;
-  }
-
-  EasyUnlockService* service =
-      EasyUnlockService::Get(ProfileHelper::GetSigninProfile());
-  service->AddObserver(this);
-
-  static_cast<EasyUnlockServiceSignin*>(service)
-      ->SetCurrentUser(user_context_.GetAccountId());
-  OnScreenlockStateChanged(service->GetScreenlockState());
-}
-
-void BootstrapUserContextInitializer::OnEasyUnlockAuthenticated(
-    EasyUnlockAuthAttempt::Type auth_attempt_type,
-    bool success,
-    const AccountId& account_id,
-    const std::string& key_secret,
-    const std::string& key_label) {
-  DCHECK_EQ(EasyUnlockAuthAttempt::TYPE_SIGNIN, auth_attempt_type);
-  if (!success || key_secret.empty()) {
-    LOG(ERROR) << "Failed to sign-in using existing Smart lock key.";
-    Notify(false);
-    return;
-  }
-
-  user_context_.SetKey(Key(key_secret));
-  user_context_.GetKey()->SetLabel(key_label);
-  Notify(true);
-}
-
-void BootstrapUserContextInitializer::CreateRandomKey() {
-  std::string random_initial_key;
-  crypto::RandBytes(base::WriteInto(&random_initial_key, kUserKeyByteSize + 1),
-                    kUserKeyByteSize);
-  user_context_.SetKey(Key(random_initial_key));
-  random_key_used_ = true;
-  Notify(true);
-}
-
-void BootstrapUserContextInitializer::Notify(bool success) {
-  if (complete_callback_for_testing_)
-    complete_callback_for_testing_->Run(success, user_context_);
-
-  if (callback_.is_null())
-    return;
-
-  callback_.Run(success, user_context_);
-}
-
-void BootstrapUserContextInitializer::OnGetTokensResponse(
-    const std::string& refresh_token,
-    const std::string& access_token,
-    int expires_in_seconds) {
-  user_context_.SetRefreshToken(refresh_token);
-
-  gaia::OAuthClientInfo client_info;
-  GaiaUrls* gaia_urls = GaiaUrls::GetInstance();
-  client_info.client_id = gaia_urls->oauth2_chrome_client_id();
-  client_info.client_secret = gaia_urls->oauth2_chrome_client_secret();
-
-  std::vector<std::string> scopes;
-  scopes.push_back(GaiaConstants::kGoogleUserInfoEmail);
-  scopes.push_back(GaiaConstants::kGoogleUserInfoProfile);
-
-  token_fetcher_->RefreshToken(client_info, refresh_token, scopes,
-                               kMaxGaiaRetries, this);
-}
-
-void BootstrapUserContextInitializer::OnRefreshTokenResponse(
-    const std::string& access_token,
-    int expires_in_seconds) {
-  token_fetcher_->GetUserInfo(access_token, kMaxGaiaRetries, this);
-}
-
-void BootstrapUserContextInitializer::OnGetUserInfoResponse(
-    std::unique_ptr<base::DictionaryValue> user_info) {
-  std::string email;
-  std::string gaia_id;
-  if (!user_info->GetString("email", &email) ||
-      !user_info->GetString("id", &gaia_id)) {
-    LOG(ERROR) << "Bad user info.";
-    Notify(false);
-    return;
-  }
-
-  user_context_.SetAccountId(user_manager::known_user::GetAccountId(
-      user_manager::CanonicalizeUserID(email), gaia_id, AccountType::GOOGLE));
-  StartCheckExistingKeys();
-}
-
-void BootstrapUserContextInitializer::OnOAuthError() {
-  LOG(ERROR) << "Auth error.";
-  Notify(false);
-}
-
-void BootstrapUserContextInitializer::OnNetworkError(int response_code) {
-  LOG(ERROR) << "Network error.";
-  Notify(false);
-}
-
-void BootstrapUserContextInitializer::OnScreenlockStateChanged(
-    proximity_auth::ScreenlockState state) {
-  // TODO(xiyuan): Add timeout and hook up with error UI after
-  //     http://crbug.com/471067.
-  if (state != proximity_auth::ScreenlockState::AUTHENTICATED)
-    return;
-
-  EasyUnlockService* service =
-      EasyUnlockService::Get(ProfileHelper::GetSigninProfile());
-  service->RemoveObserver(this);
-
-  service->AttemptAuth(
-      user_context_.GetAccountId(),
-      base::Bind(&BootstrapUserContextInitializer::OnEasyUnlockAuthenticated,
-                 weak_ptr_factory_.GetWeakPtr()));
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/easy_unlock/bootstrap_user_context_initializer.h b/chrome/browser/chromeos/login/easy_unlock/bootstrap_user_context_initializer.h
deleted file mode 100644
index a384475..0000000
--- a/chrome/browser/chromeos/login/easy_unlock/bootstrap_user_context_initializer.h
+++ /dev/null
@@ -1,94 +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 CHROME_BROWSER_CHROMEOS_LOGIN_EASY_UNLOCK_BOOTSTRAP_USER_CONTEXT_INITIALIZER_H_
-#define CHROME_BROWSER_CHROMEOS_LOGIN_EASY_UNLOCK_BOOTSTRAP_USER_CONTEXT_INITIALIZER_H_
-
-#include <memory>
-#include <string>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_types.h"
-#include "chrome/browser/signin/easy_unlock_auth_attempt.h"
-#include "chrome/browser/signin/easy_unlock_service_observer.h"
-#include "chromeos/login/auth/user_context.h"
-#include "google_apis/gaia/gaia_oauth_client.h"
-
-class AccountId;
-
-namespace chromeos {
-
-// Performs initialization work for adding a new account via Easy bootstrap.
-// The class takes an authorization code then prepares a UserContext that
-// could be used to create a new account.
-class BootstrapUserContextInitializer final
-    : public gaia::GaiaOAuthClient::Delegate,
-      public EasyUnlockServiceObserver {
- public:
-  // Callback type to be invoked after initialization work is done.
-  typedef base::Callback<void(bool success, const UserContext& user_context)>
-      CompleteCallback;
-
-  BootstrapUserContextInitializer();
-  ~BootstrapUserContextInitializer() override;
-
-  // Run initialization work with given |auth_code|. |callback| will be invoked
-  // when the work is done.
-  void Start(const std::string& auth_code, const CompleteCallback& callback);
-
-  const UserContext& user_context() const { return user_context_; }
-  bool random_key_used() const { return random_key_used_; }
-
-  static void SetCompleteCallbackForTesting(CompleteCallback* callback);
-
- private:
-  void Notify(bool success);
-
-  // Starts to check existing Smart lock keys to use.
-  void StartCheckExistingKeys();
-
-  void OnGetEasyUnlockData(bool success,
-                           const EasyUnlockDeviceKeyDataList& data_list);
-  void OnEasyUnlockAuthenticated(EasyUnlockAuthAttempt::Type auth_attempt_type,
-                                 bool success,
-                                 const AccountId& account_id,
-                                 const std::string& key_secret,
-                                 const std::string& key_label);
-  void CreateRandomKey();
-
-  // Start refresh token and user info fetching.
-  void StartTokenFetch(const std::string& auth_code);
-
-  // gaia::GaiaOAuthClient::Delegate
-  void OnGetTokensResponse(const std::string& refresh_token,
-                           const std::string& access_token,
-                           int expires_in_seconds) override;
-  void OnRefreshTokenResponse(const std::string& access_token,
-                              int expires_in_seconds) override;
-  void OnGetUserInfoResponse(
-      std::unique_ptr<base::DictionaryValue> user_info) override;
-  void OnOAuthError() override;
-  void OnNetworkError(int response_code) override;
-
-  // EasyUnlockServiceObserver:
-  void OnScreenlockStateChanged(proximity_auth::ScreenlockState state) override;
-
-  CompleteCallback callback_;
-  std::unique_ptr<gaia::GaiaOAuthClient> token_fetcher_;
-
-  UserContext user_context_;
-  bool random_key_used_;
-
-  base::WeakPtrFactory<BootstrapUserContextInitializer> weak_ptr_factory_;
-
-  static CompleteCallback* complete_callback_for_testing_;
-
-  DISALLOW_COPY_AND_ASSIGN(BootstrapUserContextInitializer);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_EASY_UNLOCK_BOOTSTRAP_USER_CONTEXT_INITIALIZER_H_
diff --git a/chrome/browser/chromeos/login/easy_unlock/bootstrap_user_flow.cc b/chrome/browser/chromeos/login/easy_unlock/bootstrap_user_flow.cc
deleted file mode 100644
index 30b1eb0..0000000
--- a/chrome/browser/chromeos/login/easy_unlock/bootstrap_user_flow.cc
+++ /dev/null
@@ -1,186 +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/chromeos/login/easy_unlock/bootstrap_user_flow.h"
-
-#include "base/bind.h"
-#include "base/sys_info.h"
-#include "chrome/browser/chromeos/login/easy_unlock/bootstrap_manager.h"
-#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
-#include "chrome/browser/chromeos/login/session/user_session_manager.h"
-#include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
-#include "chrome/browser/lifetime/application_lifetime.h"
-#include "chrome/browser/signin/easy_unlock_service.h"
-#include "chrome/browser/signin/easy_unlock_service_regular.h"
-#include "components/proximity_auth/screenlock_bridge.h"
-#include "components/signin/core/account_id/account_id.h"
-
-namespace chromeos {
-
-BootstrapUserFlow::BootstrapUserFlow(const UserContext& user_context,
-                                     bool is_new_account)
-    : ExtendedUserFlow(user_context.GetAccountId()),
-      user_context_(user_context),
-      is_new_account_(is_new_account),
-      finished_(false),
-      user_profile_(nullptr),
-      weak_ptr_factory_(this) {
-  ChromeUserManager::Get()->GetBootstrapManager()->AddPendingBootstrap(
-      user_context_.GetAccountId());
-}
-
-BootstrapUserFlow::~BootstrapUserFlow() {
-}
-
-void BootstrapUserFlow::StartAutoPairing() {
-  DCHECK(user_profile_);
-
-  VLOG(2) << "BootstrapUserFlow StartAutoPairing";
-
-  EasyUnlockService* service = EasyUnlockService::Get(user_profile_);
-  if (!service->IsAllowed()) {
-    // TODO(xiyuan): Show error UI.
-    LOG(ERROR) << "Bootstrapped failed because EasyUnlock service not allowed.";
-    chrome::AttemptUserExit();
-    return;
-  }
-
-  service->StartAutoPairing(base::Bind(&BootstrapUserFlow::SetAutoPairingResult,
-                                       weak_ptr_factory_.GetWeakPtr()));
-}
-
-void BootstrapUserFlow::SetAutoPairingResult(bool success,
-                                             const std::string& error_message) {
-  VLOG(2) << "BootstrapUserFlow::SetAutoPairingResult"
-          << ", success=" << success;
-
-  if (!success) {
-    // TODO(xiyuan): Show error UI.
-    LOG(ERROR) << "Easy bootstrap auto pairing failed, err=" << error_message;
-    chrome::AttemptUserExit();
-    return;
-  }
-
-  // TODO(xiyuan): Remove this and properly mock EasyUnlockKeyManager.
-  if (!base::SysInfo::IsRunningOnChromeOS()) {
-    Finish();
-    return;
-  }
-
-  chromeos::UserSessionManager::GetInstance()
-      ->GetEasyUnlockKeyManager()
-      ->RefreshKeys(
-          user_context_,
-          *EasyUnlockService::Get(user_profile_)->GetRemoteDevices(),
-          base::Bind(&BootstrapUserFlow::OnKeysRefreshed,
-                     weak_ptr_factory_.GetWeakPtr()));
-}
-
-void BootstrapUserFlow::OnKeysRefreshed(bool success) {
-  if (!success) {
-    // TODO(xiyuan): Show error UI.
-    LOG(ERROR) << "Easy bootstrap failed to refresh cryptohome keys.";
-    chrome::AttemptUserExit();
-    return;
-  }
-
-  EasyUnlockService::Get(user_profile_)
-      ->SetHardlockState(EasyUnlockScreenlockStateHandler::NO_HARDLOCK);
-  RemoveBootstrapRandomKey();
-}
-
-void BootstrapUserFlow::RemoveBootstrapRandomKey() {
-  scoped_refptr<ExtendedAuthenticator> authenticator(
-      ExtendedAuthenticator::Create(this));
-
-  const char kLegacyKeyLabel[] = "legacy-0";
-  authenticator->RemoveKey(
-      user_context_,
-      kLegacyKeyLabel,
-      base::Bind(&BootstrapUserFlow::OnBootstrapRandomKeyRemoved,
-                 weak_ptr_factory_.GetWeakPtr()));
-}
-
-void BootstrapUserFlow::OnBootstrapRandomKeyRemoved() {
-  Finish();
-}
-
-void BootstrapUserFlow::Finish() {
-  VLOG(2) << "BootstrapUserFlow::Finish";
-  finished_ = true;
-
-  ChromeUserManager::Get()->GetBootstrapManager()->FinishPendingBootstrap(
-      user_context_.GetAccountId());
-  UserSessionManager::GetInstance()->DoBrowserLaunch(user_profile_, host());
-
-  user_profile_ = nullptr;
-  UnregisterFlowSoon();
-}
-
-bool BootstrapUserFlow::CanLockScreen() {
-  return false;
-}
-
-bool BootstrapUserFlow::CanStartArc() {
-  return false;
-}
-
-bool BootstrapUserFlow::ShouldLaunchBrowser() {
-  return finished_;
-}
-
-bool BootstrapUserFlow::ShouldSkipPostLoginScreens() {
-  return true;
-}
-
-bool BootstrapUserFlow::HandleLoginFailure(
-    const chromeos::AuthFailure& failure) {
-  NOTREACHED();
-  return false;
-}
-
-void BootstrapUserFlow::HandleLoginSuccess(
-    const chromeos::UserContext& context) {
-}
-
-bool BootstrapUserFlow::HandlePasswordChangeDetected() {
-  NOTREACHED();
-  return false;
-}
-
-void BootstrapUserFlow::HandleOAuthTokenStatusChange(
-    user_manager::User::OAuthTokenStatus status) {
-  if (status == user_manager::User::OAUTH2_TOKEN_STATUS_INVALID) {
-    // TODO(xiyuan): Show error UI.
-    LOG(ERROR) << "Bootstrapped failed because of bad refresh token.";
-    chrome::AttemptUserExit();
-    return;
-  }
-}
-
-void BootstrapUserFlow::LaunchExtraSteps(Profile* user_profile) {
-  user_profile_ = user_profile;
-
-  // Auto pairing only when a random key is used to boostrap cryptohome.
-  if (is_new_account_) {
-    StartAutoPairing();
-    return;
-  }
-
-  Finish();
-}
-
-bool BootstrapUserFlow::SupportsEarlyRestartToApplyFlags() {
-  return false;
-}
-
-void BootstrapUserFlow::OnAuthenticationFailure(
-    ExtendedAuthenticator::AuthState state) {
-  // TODO(xiyuan): Show error UI.
-  LOG(ERROR) << "Bootstrapped failed because authenticator falure"
-             << ", state=" << state;
-  chrome::AttemptUserExit();
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/easy_unlock/bootstrap_user_flow.h b/chrome/browser/chromeos/login/easy_unlock/bootstrap_user_flow.h
deleted file mode 100644
index 4f39b2a..0000000
--- a/chrome/browser/chromeos/login/easy_unlock/bootstrap_user_flow.h
+++ /dev/null
@@ -1,72 +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_CHROMEOS_LOGIN_EASY_UNLOCK_BOOTSTRAP_USER_FLOW_H_
-#define CHROME_BROWSER_CHROMEOS_LOGIN_EASY_UNLOCK_BOOTSTRAP_USER_FLOW_H_
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "chrome/browser/chromeos/login/user_flow.h"
-#include "chromeos/login/auth/extended_authenticator.h"
-#include "chromeos/login/auth/user_context.h"
-
-class Profile;
-
-namespace chromeos {
-
-// BootstrapUserFlow executes post cryptohome mount bootstraping tasks:
-// 1. Performs Easy unlock pairing with the user's phone;
-// 2. Creates easy unlock cryptohome keys;
-// 3. Drops temp random cryptohome key;
-// After these tasks, it finishes and resumes user session.
-class BootstrapUserFlow final
-    : public ExtendedUserFlow,
-      public ExtendedAuthenticator::NewAuthStatusConsumer {
- public:
-  // Constructs a BootstrapUserFlow. |user_context| is the user this flow
-  // represents and contains the user id and key needed for cryptohome
-  // operations. |is_new_account| is a boolean flag of whether the user
-  // is being added to the device.
-  BootstrapUserFlow(const UserContext& user_context, bool is_new_account);
-  ~BootstrapUserFlow() override;
-
- private:
-  void StartAutoPairing();
-  void SetAutoPairingResult(bool success, const std::string& error_message);
-
-  void OnKeysRefreshed(bool success);
-  void RemoveBootstrapRandomKey();
-  void OnBootstrapRandomKeyRemoved();
-  void Finish();
-
-  // chromeos::ExtendedUserFlow
-  bool CanLockScreen() override;
-  bool CanStartArc() override;
-  bool ShouldLaunchBrowser() override;
-  bool ShouldSkipPostLoginScreens() override;
-  bool HandleLoginFailure(const chromeos::AuthFailure& failure) override;
-  void HandleLoginSuccess(const chromeos::UserContext& context) override;
-  bool HandlePasswordChangeDetected() override;
-  void HandleOAuthTokenStatusChange(
-      user_manager::User::OAuthTokenStatus status) override;
-  void LaunchExtraSteps(Profile* user_profile) override;
-  bool SupportsEarlyRestartToApplyFlags() override;
-
-  // ExtendedAuthenticator::NewAuthStatusConsumer
-  void OnAuthenticationFailure(ExtendedAuthenticator::AuthState state) override;
-
-  UserContext user_context_;
-  const bool is_new_account_;
-
-  bool finished_;
-  Profile* user_profile_;
-
-  base::WeakPtrFactory<BootstrapUserFlow> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(BootstrapUserFlow);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_EASY_UNLOCK_BOOTSTRAP_USER_FLOW_H_
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc
index 45459b12..4644ed0b 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -30,8 +30,6 @@
 #include "chrome/browser/chromeos/customization/customization_document.h"
 #include "chrome/browser/chromeos/login/arc_kiosk_controller.h"
 #include "chrome/browser/chromeos/login/auth/chrome_login_performer.h"
-#include "chrome/browser/chromeos/login/easy_unlock/bootstrap_user_context_initializer.h"
-#include "chrome/browser/chromeos/login/easy_unlock/bootstrap_user_flow.h"
 #include "chrome/browser/chromeos/login/enterprise_user_session_metrics.h"
 #include "chrome/browser/chromeos/login/helper.h"
 #include "chrome/browser/chromeos/login/screens/encryption_migration_screen.h"
@@ -852,12 +850,10 @@
   //                          Regular        SAML
   //  /ServiceLogin              T            T
   //  /ChromeOsEmbeddedSetup     F            T
-  //  Bootstrap experiment       F            N/A
   const bool has_auth_cookies =
       login_performer_->auth_mode() == LoginPerformer::AUTH_MODE_EXTENSION &&
       (user_context.GetAccessToken().empty() ||
-       user_context.GetAuthFlow() == UserContext::AUTH_FLOW_GAIA_WITH_SAML) &&
-      user_context.GetAuthFlow() != UserContext::AUTH_FLOW_EASY_BOOTSTRAP;
+       user_context.GetAuthFlow() == UserContext::AUTH_FLOW_GAIA_WITH_SAML);
 
   // LoginPerformer instance will delete itself in case of successful auth.
   login_performer_->set_delegate(nullptr);
@@ -1592,16 +1588,6 @@
     time_init_ = base::Time();  // Reset to null.
   }
 
-  if (user_context.GetAuthFlow() == UserContext::AUTH_FLOW_EASY_BOOTSTRAP) {
-    bootstrap_user_context_initializer_.reset(
-        new BootstrapUserContextInitializer());
-    bootstrap_user_context_initializer_->Start(
-        user_context.GetAuthCode(),
-        base::Bind(&ExistingUserController::OnBootstrapUserContextInitialized,
-                   weak_factory_.GetWeakPtr()));
-    return;
-  }
-
   // Fetch OAuth2 tokens if we have an auth code.
   if (!user_context.GetAuthCode().empty()) {
     oauth2_token_initializer_.reset(new OAuth2TokenInitializer);
@@ -1660,26 +1646,6 @@
   PerformLogin(user_context, LoginPerformer::AUTH_MODE_INTERNAL);
 }
 
-void ExistingUserController::OnBootstrapUserContextInitialized(
-    bool success,
-    const UserContext& user_context) {
-  if (!success) {
-    LOG(ERROR) << "Easy bootstrap failed.";
-    OnAuthFailure(AuthFailure(AuthFailure::NETWORK_AUTH_FAILED));
-    return;
-  }
-
-  // Setting a customized login user flow to perform additional initializations
-  // for bootstrap after the user session is started.
-  ChromeUserManager::Get()->SetUserFlow(
-      user_context.GetAccountId(),
-      new BootstrapUserFlow(
-          user_context,
-          bootstrap_user_context_initializer_->random_key_used()));
-
-  PerformLogin(user_context, LoginPerformer::AUTH_MODE_EXTENSION);
-}
-
 void ExistingUserController::OnOAuth2TokensFetched(
     bool success,
     const UserContext& user_context) {
diff --git a/chrome/browser/chromeos/login/existing_user_controller.h b/chrome/browser/chromeos/login/existing_user_controller.h
index c7281c6d..fd0848c7 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.h
+++ b/chrome/browser/chromeos/login/existing_user_controller.h
@@ -47,7 +47,6 @@
 
 namespace chromeos {
 
-class BootstrapUserContextInitializer;
 class CrosSettings;
 class LoginDisplayHost;
 class OAuth2TokenInitializer;
@@ -281,10 +280,6 @@
   void DoLogin(const UserContext& user_context,
                const SigninSpecifics& specifics);
 
-  // Callback invoked when |bootstrap_user_context_initializer_| has finished.
-  void OnBootstrapUserContextInitialized(bool success,
-                                         const UserContext& user_context);
-
   // Callback invoked when |oauth2_token_initializer_| has finished.
   void OnOAuth2TokensFetched(bool success, const UserContext& user_context);
 
@@ -414,9 +409,6 @@
   std::unique_ptr<CrosSettings::ObserverSubscription>
       local_account_auto_login_delay_subscription_;
 
-  std::unique_ptr<BootstrapUserContextInitializer>
-      bootstrap_user_context_initializer_;
-
   std::unique_ptr<OAuth2TokenInitializer> oauth2_token_initializer_;
 
   std::unique_ptr<TokenHandleUtil> token_handle_util_;
diff --git a/chrome/browser/chromeos/login/kiosk_browsertest.cc b/chrome/browser/chromeos/login/kiosk_browsertest.cc
index 332cbd7..689bbd1c 100644
--- a/chrome/browser/chromeos/login/kiosk_browsertest.cc
+++ b/chrome/browser/chromeos/login/kiosk_browsertest.cc
@@ -67,15 +67,19 @@
 #include "extensions/browser/app_window/native_app_window.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/manifest.h"
+#include "extensions/common/switches.h"
 #include "extensions/components/native_app_window/native_app_window_views.h"
 #include "extensions/test/extension_test_message_listener.h"
 #include "extensions/test/result_catcher.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_switches.h"
 #include "google_apis/gaia/gaia_urls.h"
+#include "media/audio/mock_audio_manager.h"
+#include "media/audio/test_audio_thread.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "ui/aura/window.h"
 #include "ui/base/accelerators/accelerator.h"
+#include "ui/keyboard/keyboard_switches.h"
 
 namespace em = enterprise_management;
 
@@ -119,6 +123,11 @@
 //         detail/aaedpojejpghjkedenggihopfhfijcko
 const char kTestGetVolumeListKioskApp[] = "aaedpojejpghjkedenggihopfhfijcko";
 
+// An app to test Kiosk virtual keyboard API chrome.virtualKeyboard.* .
+// Source files are in
+//     chrome/test/data/chromeos/app_mode/virtual_keyboard/src/
+const char kTestVirtualKeyboardKioskApp[] = "fmmbbdiapbcicajbpkpkdbcgidgppada";
+
 // Testing apps for testing kiosk multi-app feature. All the crx files are in
 //    chrome/test/data/chromeos/app_mode/webstore/downloads.
 
@@ -2297,6 +2306,51 @@
   EXPECT_EQ(extensions::Manifest::EXTERNAL_POLICY, GetInstalledAppLocation());
 }
 
+// Specialized test fixture for testing kiosk mode where virtual keyboard is
+// enabled.
+class KioskVirtualKeyboardTest : public KioskTest {
+ public:
+  KioskVirtualKeyboardTest() {}
+  ~KioskVirtualKeyboardTest() override = default;
+
+ protected:
+  // KioskTest overrides:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    KioskTest::SetUpCommandLine(command_line);
+    command_line->AppendSwitchASCII(
+        extensions::switches::kWhitelistedExtensionID,
+        kTestVirtualKeyboardKioskApp);
+    command_line->AppendSwitch(keyboard::switches::kEnableVirtualKeyboard);
+  }
+
+  // Use class variable for sane lifetime.
+  std::unique_ptr<media::MockAudioManager> mock_audio_manager_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(KioskVirtualKeyboardTest);
+};
+
+// Verifies that chrome.virtualKeyboard.restrictFeatures and related private
+// APIs work.
+IN_PROC_BROWSER_TEST_F(KioskVirtualKeyboardTest, RestrictFeatures) {
+  // Mock existence of audio input.
+  // We cannot do this in SetUp because it's overriden in RunTestOnMainThread.
+  mock_audio_manager_ = base::MakeUnique<media::MockAudioManager>(
+      base::MakeUnique<media::TestAudioThread>());
+  mock_audio_manager_->SetHasInputDevices(true);
+
+  set_test_app_id(kTestVirtualKeyboardKioskApp);
+  set_test_app_version("0.1");
+  set_test_crx_file(test_app_id() + ".crx");
+
+  extensions::ResultCatcher catcher;
+  StartAppLaunchFromLoginScreen(SimulateNetworkOnlineClosure());
+  ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
+
+  // Shutdown should be done in the same thread, thus not in the destructor.
+  mock_audio_manager_->Shutdown();
+}
+
 // Specialized test fixture for testing kiosk mode on the
 // hidden WebUI initialization flow for slow hardware.
 class KioskHiddenWebUITest : public KioskTest,
diff --git a/chrome/browser/chromeos/login/saml/saml_browsertest.cc b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
index ea97d9691..98ef2c9 100644
--- a/chrome/browser/chromeos/login/saml/saml_browsertest.cc
+++ b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
@@ -113,34 +113,34 @@
 
 namespace {
 
-const char kGAIASIDCookieName[] = "SID";
-const char kGAIALSIDCookieName[] = "LSID";
+constexpr char kGAIASIDCookieName[] = "SID";
+constexpr char kGAIALSIDCookieName[] = "LSID";
 
-const char kTestAuthSIDCookie1[] = "fake-auth-SID-cookie-1";
-const char kTestAuthSIDCookie2[] = "fake-auth-SID-cookie-2";
-const char kTestAuthLSIDCookie1[] = "fake-auth-LSID-cookie-1";
-const char kTestAuthLSIDCookie2[] = "fake-auth-LSID-cookie-2";
+constexpr char kTestAuthSIDCookie1[] = "fake-auth-SID-cookie-1";
+constexpr char kTestAuthSIDCookie2[] = "fake-auth-SID-cookie-2";
+constexpr char kTestAuthLSIDCookie1[] = "fake-auth-LSID-cookie-1";
+constexpr char kTestAuthLSIDCookie2[] = "fake-auth-LSID-cookie-2";
 
-const char kFirstSAMLUserEmail[] = "bob@example.com";
-const char kSecondSAMLUserEmail[] = "alice@example.com";
-const char kHTTPSAMLUserEmail[] = "carol@example.com";
-const char kNonSAMLUserEmail[] = "dan@example.com";
-const char kDifferentDomainSAMLUserEmail[] = "eve@example.test";
+constexpr char kFirstSAMLUserEmail[] = "bob@example.com";
+constexpr char kSecondSAMLUserEmail[] = "alice@example.com";
+constexpr char kHTTPSAMLUserEmail[] = "carol@example.com";
+constexpr char kNonSAMLUserEmail[] = "dan@example.com";
+constexpr char kDifferentDomainSAMLUserEmail[] = "eve@example.test";
 
-const char kIdPHost[] = "login.example.com";
-const char kAdditionalIdPHost[] = "login2.example.com";
+constexpr char kIdPHost[] = "login.example.com";
+constexpr char kAdditionalIdPHost[] = "login2.example.com";
 
-const char kSAMLIdPCookieName[] = "saml";
-const char kSAMLIdPCookieValue1[] = "value-1";
-const char kSAMLIdPCookieValue2[] = "value-2";
+constexpr char kSAMLIdPCookieName[] = "saml";
+constexpr char kSAMLIdPCookieValue1[] = "value-1";
+constexpr char kSAMLIdPCookieValue2[] = "value-2";
 
-const char kRelayState[] = "RelayState";
+constexpr char kRelayState[] = "RelayState";
 
-const char kTestUserinfoToken[] = "fake-userinfo-token";
-const char kTestRefreshToken[] = "fake-refresh-token";
-const char kPolicy[] = "{\"managed_users\": [\"*\"]}";
+constexpr char kTestUserinfoToken[] = "fake-userinfo-token";
+constexpr char kTestRefreshToken[] = "fake-refresh-token";
+constexpr char kPolicy[] = "{\"managed_users\": [\"*\"]}";
 
-const char kAffiliationID[] = "some-affiliation-id";
+constexpr char kAffiliationID[] = "some-affiliation-id";
 
 // FakeSamlIdp serves IdP auth form and the form submission. The form is
 // served with the template's RelayState placeholder expanded to the real
@@ -1197,6 +1197,8 @@
 
   fake_gaia_->SetFakeMergeSessionParams(user_id, auth_sid_cookie,
                                         auth_lsid_cookie);
+  SetupFakeGaiaForLogin(user_id, "", kTestRefreshToken);
+
   SetSignFormField("Email", "fake_user");
   SetSignFormField("Password", "fake_password");
 
@@ -1255,6 +1257,10 @@
 
   WaitForSigninScreen();
 
+  fake_gaia_->SetFakeMergeSessionParams(kNonSAMLUserEmail, kFakeSIDCookie,
+                                        kFakeLSIDCookie);
+  SetupFakeGaiaForLogin(kNonSAMLUserEmail, "", kTestRefreshToken);
+
   // Log in without SAML.
   GetLoginDisplay()->ShowSigninScreenForCreds(kNonSAMLUserEmail, "password");
 
diff --git a/chrome/browser/chromeos/login/screens/user_image_screen.cc b/chrome/browser/chromeos/login/screens/user_image_screen.cc
index 5095f9e..528071f 100644
--- a/chrome/browser/chromeos/login/screens/user_image_screen.cc
+++ b/chrome/browser/chromeos/login/screens/user_image_screen.cc
@@ -51,6 +51,8 @@
 constexpr const char kContextKeyIsCameraPresent[] = "isCameraPresent";
 constexpr const char kContextKeyProfilePictureDataURL[] =
     "profilePictureDataURL";
+constexpr const char kContextKeyIsProfilePictureAvailable[] =
+    "isProfilePictureAvailable";
 constexpr const char kContextKeySelectedImageIndex[] = "selectedImageIndex";
 constexpr const char kContextKeySelectedImageURL[] = "selectedImageURL";
 
@@ -95,6 +97,8 @@
 void UserImageScreen::OnPhotoTaken(const std::string& raw_data) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   user_photo_ = gfx::ImageSkia();
+  std::vector<unsigned char> photo_data(raw_data.begin(), raw_data.end());
+  user_photo_data_ = base::RefCountedBytes::TakeVector(&photo_data);
   ImageDecoder::Cancel(this);
   ImageDecoder::Start(this, raw_data);
 }
@@ -126,16 +130,20 @@
   UserImageManager* image_manager = GetUserImageManager();
   int uma_index = 0;
   switch (selected_image_) {
-    case user_manager::User::USER_IMAGE_EXTERNAL:
+    case user_manager::User::USER_IMAGE_EXTERNAL: {
       // Photo decoding may not have been finished yet.
       if (user_photo_.isNull()) {
         accept_photo_after_decoding_ = true;
         return;
       }
-      image_manager->SaveUserImage(user_manager::UserImage::CreateAndEncode(
-          user_photo_, user_manager::UserImage::FORMAT_JPEG));
+      std::unique_ptr<user_manager::UserImage> user_image =
+          base::MakeUnique<user_manager::UserImage>(
+              user_photo_, user_photo_data_.get(),
+              user_manager::UserImage::FORMAT_PNG);
+      user_image->MarkAsSafe();
+      image_manager->SaveUserImage(std::move(user_image));
       uma_index = default_user_image::kHistogramImageFromCamera;
-      break;
+    } break;
     case user_manager::User::USER_IMAGE_PROFILE:
       image_manager->SaveUserImageFromProfileImage();
       uma_index = default_user_image::kHistogramImageFromProfile;
@@ -221,8 +229,15 @@
       kContextKeySelectedImageURL,
       default_user_image::GetDefaultImageUrl(selected_image_));
 
-  // Start fetching the profile image.
-  GetUserImageManager()->DownloadProfileImage(kProfileDownloadReason);
+  const user_manager::User* user = GetUser();
+  // Active Directory accounts do not use a profile image so skip the download
+  // and inform the UI that no profile image exists.
+  if (user && user->IsActiveDirectoryUser()) {
+    GetContextEditor().SetBoolean(kContextKeyIsProfilePictureAvailable, false);
+  } else {
+    // Start fetching the profile image.
+    GetUserImageManager()->DownloadProfileImage(kProfileDownloadReason);
+  }
 }
 
 void UserImageScreen::Hide() {
diff --git a/chrome/browser/chromeos/login/screens/user_image_screen.h b/chrome/browser/chromeos/login/screens/user_image_screen.h
index b58aba25..868f06f98 100644
--- a/chrome/browser/chromeos/login/screens/user_image_screen.h
+++ b/chrome/browser/chromeos/login/screens/user_image_screen.h
@@ -130,6 +130,9 @@
   // Last user photo, if taken.
   gfx::ImageSkia user_photo_;
 
+  // Data for |user_photo_|.
+  scoped_refptr<base::RefCountedBytes> user_photo_data_;
+
   // If |true|, decoded photo should be immediately accepted (i.e., both
   // HandleTakePhoto and HandleImageAccepted have already been called but we're
   // still waiting for  photo image decoding to finish.
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc
index f78f80f..dbd2283 100644
--- a/chrome/browser/chromeos/login/session/user_session_manager.cc
+++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -75,6 +75,7 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/signin/account_tracker_service_factory.h"
 #include "chrome/browser/signin/easy_unlock_service.h"
+#include "chrome/browser/signin/signin_error_controller_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/supervised_user/child_accounts/child_account_service.h"
 #include "chrome/browser/supervised_user/child_accounts/child_account_service_factory.h"
@@ -105,6 +106,7 @@
 #include "components/session_manager/core/session_manager.h"
 #include "components/signin/core/account_id/account_id.h"
 #include "components/signin/core/browser/account_tracker_service.h"
+#include "components/signin/core/browser/signin_error_controller.h"
 #include "components/signin/core/browser/signin_manager_base.h"
 #include "components/user_manager/known_user.h"
 #include "components/user_manager/user.h"
@@ -285,28 +287,8 @@
   if (user_manager::UserManager::Get()->IsLoggedInAsSupervisedUser())
     return false;
 
-  // When running Mus+ash, the flags stored in Profile Prefs will contain
-  // --mash, while the browser command line will not (and should not) have
-  // it, so ignore it for the purpose of comparison.
-  // TODO(mfomitchev): Find a better way. crbug.com/690083
-  bool in_mash = false;
-  base::CommandLine user_flags_no_mash = user_flags;
-
-#if BUILDFLAG(ENABLE_PACKAGE_MASH_SERVICES)
-  in_mash = user_flags.HasSwitch(::switches::kMash);
-  if (in_mash) {
-    base::CommandLine::SwitchMap switches = user_flags.GetSwitches();
-    switches.erase(::switches::kMash);
-    user_flags_no_mash = base::CommandLine(user_flags.GetProgram());
-    for (const std::pair<std::string, base::CommandLine::StringType>& sw :
-         switches) {
-      user_flags_no_mash.AppendSwitchNative(sw.first, sw.second);
-    }
-  }
-#endif  // BUILDFLAG(ENABLE_PACKAGE_MASH_SERVICES)
-
   if (about_flags::AreSwitchesIdenticalToCurrentCommandLine(
-          user_flags_no_mash, *base::CommandLine::ForCurrentProcess(),
+          user_flags, *base::CommandLine::ForCurrentProcess(),
           out_command_line_difference)) {
     return false;
   }
@@ -314,7 +296,7 @@
   // TODO(mfomitchev): Browser restart doesn't currently work in Mus+ash.
   // So if we are running Mustash and we need to restart - just crash right
   // here. crbug.com/690140
-  CHECK(!in_mash);
+  CHECK(!user_flags.HasSwitch(::switches::kMash));
 
   return true;
 }
@@ -845,7 +827,15 @@
   bool connection_error = false;
   switch (state) {
     case OAuth2LoginManager::SESSION_RESTORE_DONE:
-      user_status = user_manager::User::OAUTH2_TOKEN_STATUS_VALID;
+      // Session restore done does not always mean valid token because the
+      // merge session operation could be skipped when the first account in
+      // Gaia cookies matches the primary account in TokenService. However
+      // the token could still be invalid in some edge cases. See
+      // http://crbug.com/760610
+      user_status =
+          SigninErrorControllerFactory::GetForProfile(user_profile)->HasError()
+              ? user_manager::User::OAUTH2_TOKEN_STATUS_INVALID
+              : user_manager::User::OAUTH2_TOKEN_STATUS_VALID;
       break;
     case OAuth2LoginManager::SESSION_RESTORE_FAILED:
       user_status = user_manager::User::OAUTH2_TOKEN_STATUS_INVALID;
diff --git a/chrome/browser/chromeos/login/signin/auth_sync_observer.cc b/chrome/browser/chromeos/login/signin/auth_sync_observer.cc
index 95a5cd0..48ad4c2 100644
--- a/chrome/browser/chromeos/login/signin/auth_sync_observer.cc
+++ b/chrome/browser/chromeos/login/signin/auth_sync_observer.cc
@@ -10,65 +10,97 @@
 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
 #include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/signin/signin_error_controller_factory.h"
+#include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "components/browser_sync/profile_sync_service.h"
-#include "components/prefs/pref_service.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 #include "components/user_manager/user_manager.h"
 #include "components/user_manager/user_type.h"
-#include "google_apis/gaia/gaia_auth_util.h"
-
-class Profile;
-
-namespace browser_sync {
-class ProfileSyncService;
-}  // namespace browser_sync
 
 namespace chromeos {
 
-AuthSyncObserver::AuthSyncObserver(Profile* profile)
-    : profile_(profile) {
+// static
+bool AuthSyncObserver::ShouldObserve(Profile* profile) {
+  const user_manager::User* const user =
+      ProfileHelper::Get()->GetUserByProfile(profile);
+  return user && (user->HasGaiaAccount() ||
+                  user->GetType() == user_manager::USER_TYPE_SUPERVISED);
 }
 
-AuthSyncObserver::~AuthSyncObserver() {
+AuthSyncObserver::AuthSyncObserver(Profile* profile) : profile_(profile) {
+  DCHECK(ShouldObserve(profile));
 }
 
+AuthSyncObserver::~AuthSyncObserver() {}
+
 void AuthSyncObserver::StartObserving() {
-  browser_sync::ProfileSyncService* sync_service =
+  browser_sync::ProfileSyncService* const sync_service =
       ProfileSyncServiceFactory::GetForProfile(profile_);
   if (sync_service)
     sync_service->AddObserver(this);
+
+  SigninErrorController* const error_controller =
+      SigninErrorControllerFactory::GetForProfile(profile_);
+  if (error_controller) {
+    error_controller->AddObserver(this);
+    OnErrorChanged();
+  }
 }
 
 void AuthSyncObserver::Shutdown() {
-  browser_sync::ProfileSyncService* sync_service =
+  browser_sync::ProfileSyncService* const sync_service =
       ProfileSyncServiceFactory::GetForProfile(profile_);
   if (sync_service)
     sync_service->RemoveObserver(this);
+
+  SigninErrorController* const error_controller =
+      SigninErrorControllerFactory::GetForProfile(profile_);
+  if (error_controller)
+    error_controller->RemoveObserver(this);
 }
 
 void AuthSyncObserver::OnStateChanged(syncer::SyncService* sync) {
-  DCHECK(user_manager::UserManager::Get()->IsLoggedInAsUserWithGaiaAccount() ||
-         user_manager::UserManager::Get()->IsLoggedInAsSupervisedUser());
-  const user_manager::User* user =
+  HandleAuthError(sync->GetAuthError());
+}
+
+void AuthSyncObserver::OnErrorChanged() {
+  SigninErrorController* const error_controller =
+      SigninErrorControllerFactory::GetForProfile(profile_);
+  const std::string error_account_id = error_controller->error_account_id();
+
+  const std::string primary_account_id =
+      SigninManagerFactory::GetForProfile(profile_)
+          ->GetAuthenticatedAccountId();
+
+  // Bail if there is an error account id and it is not the primary account id.
+  if (!error_account_id.empty() && error_account_id != primary_account_id)
+    return;
+
+  HandleAuthError(error_controller->auth_error());
+}
+
+void AuthSyncObserver::HandleAuthError(
+    const GoogleServiceAuthError& auth_error) {
+  const user_manager::User* const user =
       ProfileHelper::Get()->GetUserByProfile(profile_);
-  GoogleServiceAuthError::State state = sync->GetAuthError().state();
-  if (state != GoogleServiceAuthError::NONE &&
-      state != GoogleServiceAuthError::CONNECTION_FAILED &&
-      state != GoogleServiceAuthError::SERVICE_UNAVAILABLE &&
-      state != GoogleServiceAuthError::REQUEST_CANCELED) {
+  DCHECK(user->HasGaiaAccount() ||
+         user->GetType() == user_manager::USER_TYPE_SUPERVISED);
+
+  if (auth_error.IsPersistentError()) {
     // Invalidate OAuth2 refresh token to force Gaia sign-in flow. This is
     // needed because sign-out/sign-in solution is suggested to the user.
-    // TODO(nkostylev): Remove after crosbug.com/25978 is implemented.
-    LOG(WARNING) << "Invalidate OAuth token because of a sync error: "
-                 << sync->GetAuthError().ToString();
+    LOG(WARNING) << "Invalidate OAuth token because of an auth error: "
+                 << auth_error.ToString();
     const AccountId& account_id = user->GetAccountId();
     DCHECK(account_id.is_valid());
-    // TODO(nkostyelv): Change observer after active user has changed.
+
     user_manager::User::OAuthTokenStatus old_status =
         user->oauth_token_status();
     user_manager::UserManager::Get()->SaveUserOAuthStatus(
         account_id, user_manager::User::OAUTH2_TOKEN_STATUS_INVALID);
     RecordReauthReason(account_id, ReauthReason::SYNC_FAILED);
+
     if (user->GetType() == user_manager::USER_TYPE_SUPERVISED &&
         old_status != user_manager::User::OAUTH2_TOKEN_STATUS_INVALID) {
        // Attempt to restore token from file.
@@ -81,7 +113,7 @@
       base::RecordAction(
           base::UserMetricsAction("ManagedUsers_Chromeos_Sync_Invalidated"));
     }
-  } else if (state == GoogleServiceAuthError::NONE) {
+  } else if (auth_error.state() == GoogleServiceAuthError::NONE) {
     if (user->GetType() == user_manager::USER_TYPE_SUPERVISED &&
         user->oauth_token_status() ==
             user_manager::User::OAUTH2_TOKEN_STATUS_INVALID) {
diff --git a/chrome/browser/chromeos/login/signin/auth_sync_observer.h b/chrome/browser/chromeos/login/signin/auth_sync_observer.h
index a513a2b48..0647c35 100644
--- a/chrome/browser/chromeos/login/signin/auth_sync_observer.h
+++ b/chrome/browser/chromeos/login/signin/auth_sync_observer.h
@@ -7,23 +7,30 @@
 
 #include <string>
 
-#include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "components/signin/core/browser/signin_error_controller.h"
 #include "components/sync/driver/sync_service_observer.h"
 
+class GoogleServiceAuthError;
 class Profile;
 
 namespace chromeos {
 
 // This class is responsible for detecting authentication problems reported
-// by sync service and
+// by sync service and SigninErrorController on a user profile.
 class AuthSyncObserver : public KeyedService,
-                         public syncer::SyncServiceObserver {
+                         public syncer::SyncServiceObserver,
+                         public SigninErrorController::Observer {
  public:
-  explicit AuthSyncObserver(Profile* user_profile);
+  // Whether |profile| should be observed. Currently, this returns true only
+  // when |profile| is a user profile of a gaia user or a supervised user.
+  static bool ShouldObserve(Profile* profile);
+
+  explicit AuthSyncObserver(Profile* profile);
   ~AuthSyncObserver() override;
 
+  // Starts to observe SyncService and SigninErrorController.
   void StartObserving();
 
  private:
@@ -35,10 +42,16 @@
   // syncer::SyncServiceObserver implementation.
   void OnStateChanged(syncer::SyncService* sync) override;
 
+  // SigninErrorController::Observer implementation.
+  void OnErrorChanged() override;
+
+  // Handles an auth error.
+  void HandleAuthError(const GoogleServiceAuthError& auth_error);
+
   // Called on attempt to restore supervised user token.
   void OnSupervisedTokenLoaded(const std::string& token);
 
-  Profile* profile_;
+  Profile* const profile_;
 
   DISALLOW_COPY_AND_ASSIGN(AuthSyncObserver);
 };
diff --git a/chrome/browser/chromeos/login/signin/auth_sync_observer_factory.cc b/chrome/browser/chromeos/login/signin/auth_sync_observer_factory.cc
index 7bbd5b7..fd314e96 100644
--- a/chrome/browser/chromeos/login/signin/auth_sync_observer_factory.cc
+++ b/chrome/browser/chromeos/login/signin/auth_sync_observer_factory.cc
@@ -6,6 +6,7 @@
 
 #include "chrome/browser/chromeos/login/signin/auth_sync_observer.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/signin_error_controller_factory.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 
@@ -16,6 +17,7 @@
         "AuthSyncObserver",
         BrowserContextDependencyManager::GetInstance()) {
   DependsOn(ProfileSyncServiceFactory::GetInstance());
+  DependsOn(SigninErrorControllerFactory::GetInstance());
 }
 
 AuthSyncObserverFactory::~AuthSyncObserverFactory() {
@@ -24,6 +26,9 @@
 // static
 AuthSyncObserver* AuthSyncObserverFactory::GetForProfile(
     Profile* profile) {
+  if (!AuthSyncObserver::ShouldObserve(profile))
+    return nullptr;
+
   return static_cast<AuthSyncObserver*>(
       GetInstance()->GetServiceForBrowserContext(profile, true));
 }
diff --git a/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc b/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc
index 9983614..8907663 100644
--- a/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc
+++ b/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <map>
+#include <memory>
 #include <string>
 #include <utility>
 
@@ -23,6 +25,7 @@
 #include "chrome/browser/extensions/chrome_extension_test_notification_observer.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
+#include "chrome/browser/signin/signin_error_controller_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.h"
@@ -37,7 +40,9 @@
 #include "components/prefs/pref_service.h"
 #include "components/signin/core/account_id/account_id.h"
 #include "components/signin/core/browser/account_tracker_service.h"
+#include "components/signin/core/browser/fake_auth_status_provider.h"
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_error_controller.h"
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/notification_service.h"
@@ -45,8 +50,6 @@
 #include "extensions/browser/process_manager.h"
 #include "extensions/test/extension_test_message_listener.h"
 #include "extensions/test/result_catcher.h"
-#include "google_apis/gaia/gaia_constants.h"
-#include "google_apis/gaia/gaia_urls.h"
 #include "net/cookies/canonical_cookie.h"
 #include "net/cookies/cookie_store.h"
 #include "net/test/embedded_test_server/http_request.h"
@@ -77,10 +80,6 @@
 const char kTestSessionLSIDCookie[] = "fake-session-LSID-cookie";
 const char kTestSession2SIDCookie[] = "fake-session2-SID-cookie";
 const char kTestSession2LSIDCookie[] = "fake-session2-LSID-cookie";
-const char kTestUserinfoToken[] = "fake-userinfo-token";
-const char kTestLoginToken[] = "fake-login-token";
-const char kTestSyncToken[] = "fake-sync-token";
-const char kTestAuthLoginToken[] = "fake-oauthlogin-token";
 
 std::string PickAccountId(Profile* profile,
                           const std::string& gaia_id,
@@ -110,8 +109,8 @@
 
     waiting_for_state_ = true;
     login_manager->AddObserver(this);
-    runner_ = new content::MessageLoopRunner;
-    runner_->Run();
+    run_loop_ = std::make_unique<base::RunLoop>();
+    run_loop_->Run();
     login_manager->RemoveObserver(this);
   }
 
@@ -130,14 +129,14 @@
 
     final_state_ = state;
     waiting_for_state_ = false;
-    runner_->Quit();
+    run_loop_->Quit();
   }
 
   Profile* profile_;
   std::set<OAuth2LoginManager::SessionRestoreState> states_;
   bool waiting_for_state_;
   OAuth2LoginManager::SessionRestoreState final_state_;
-  scoped_refptr<content::MessageLoopRunner> runner_;
+  std::unique_ptr<base::RunLoop> run_loop_;
 
   DISALLOW_COPY_AND_ASSIGN(OAuth2LoginManagerStateWaiter);
 };
@@ -166,12 +165,56 @@
   DISALLOW_COPY_AND_ASSIGN(ThreadBlocker);
 };
 
+// Helper class that is added as a RequestMonitor of embedded test server to
+// wait for a request to happen and defer it until Unblock is called.
+class RequestDeferrer {
+ public:
+  RequestDeferrer()
+      : blocking_event_(base::WaitableEvent::ResetPolicy::MANUAL,
+                        base::WaitableEvent::InitialState::NOT_SIGNALED),
+        start_event_(base::WaitableEvent::ResetPolicy::MANUAL,
+                     base::WaitableEvent::InitialState::NOT_SIGNALED) {}
+
+  void UnblockRequest() { blocking_event_.Signal(); }
+
+  void WaitForRequestToStart() {
+    // If we have already served the request, bail out.
+    if (start_event_.IsSignaled())
+      return;
+
+    run_loop_ = std::make_unique<base::RunLoop>();
+    run_loop_->Run();
+  }
+
+  void InterceptRequest(const HttpRequest& request) {
+    start_event_.Signal();
+    content::BrowserThread::PostTask(
+        content::BrowserThread::UI, FROM_HERE,
+        base::BindOnce(&RequestDeferrer::QuitRunnerOnUIThread,
+                       base::Unretained(this)));
+    blocking_event_.Wait();
+  }
+
+ private:
+  void QuitRunnerOnUIThread() {
+    if (run_loop_)
+      run_loop_->Quit();
+  }
+
+  base::WaitableEvent blocking_event_;
+  base::WaitableEvent start_event_;
+  std::unique_ptr<base::RunLoop> run_loop_;
+
+  DISALLOW_COPY_AND_ASSIGN(RequestDeferrer);
+};
+
 }  // namespace
 
 class OAuth2Test : public OobeBaseTest {
  protected:
   OAuth2Test() {}
 
+  // OobeBaseTest overrides.
   void SetUpCommandLine(base::CommandLine* command_line) override {
     OobeBaseTest::SetUpCommandLine(command_line);
 
@@ -180,6 +223,11 @@
     command_line->AppendSwitch(switches::kDisableSync);
   }
 
+  void RegisterAdditionalRequestHandlers() override {
+    embedded_test_server()->RegisterRequestMonitor(
+        base::Bind(&OAuth2Test::InterceptRequest, base::Unretained(this)));
+  }
+
   void SetupGaiaServerForNewAccount() {
     FakeGaia::MergeSessionParams params;
     params.auth_sid_cookie = kTestAuthSIDCookie;
@@ -191,14 +239,14 @@
     params.session_sid_cookie = kTestSessionSIDCookie;
     params.session_lsid_cookie = kTestSessionLSIDCookie;
     fake_gaia_->SetMergeSessionParams(params);
-    SetupGaiaServerWithAccessTokens();
+    SetupFakeGaiaForLogin(kTestEmail, kTestGaiaId, kTestRefreshToken);
   }
 
   void SetupGaiaServerForUnexpiredAccount() {
     FakeGaia::MergeSessionParams params;
     params.email = kTestEmail;
     fake_gaia_->SetMergeSessionParams(params);
-    SetupGaiaServerWithAccessTokens();
+    SetupFakeGaiaForLogin(kTestEmail, kTestGaiaId, kTestRefreshToken);
   }
 
   void SetupGaiaServerForExpiredAccount() {
@@ -207,7 +255,7 @@
     params.session_sid_cookie = kTestSession2SIDCookie;
     params.session_lsid_cookie = kTestSession2LSIDCookie;
     fake_gaia_->SetMergeSessionParams(params);
-    SetupGaiaServerWithAccessTokens();
+    SetupFakeGaiaForLogin(kTestEmail, kTestGaiaId, kTestRefreshToken);
   }
 
   void LoginAsExistingUser() {
@@ -305,51 +353,6 @@
     return false;
   }
 
-  void SetupGaiaServerWithAccessTokens() {
-    fake_gaia_->MapEmailToGaiaId(kTestEmail, kTestGaiaId);
-
-    // Configure OAuth authentication.
-    GaiaUrls* gaia_urls = GaiaUrls::GetInstance();
-
-    // This token satisfies the userinfo.email request from
-    // DeviceOAuth2TokenService used in token validation.
-    FakeGaia::AccessTokenInfo userinfo_token_info;
-    userinfo_token_info.token = kTestUserinfoToken;
-    userinfo_token_info.scopes.insert(
-        "https://www.googleapis.com/auth/userinfo.email");
-    userinfo_token_info.audience = gaia_urls->oauth2_chrome_client_id();
-    userinfo_token_info.email = kTestEmail;
-    fake_gaia_->IssueOAuthToken(kTestRefreshToken, userinfo_token_info);
-
-    FakeGaia::AccessTokenInfo userinfo_profile_token_info;
-    userinfo_profile_token_info.token = kTestUserinfoToken;
-    userinfo_profile_token_info.scopes.insert(
-        "https://www.googleapis.com/auth/userinfo.profile");
-    userinfo_profile_token_info.audience = gaia_urls->oauth2_chrome_client_id();
-    userinfo_profile_token_info.email = kTestEmail;
-    fake_gaia_->IssueOAuthToken(kTestRefreshToken, userinfo_profile_token_info);
-
-    // The any-api access token for accessing the token minting endpoint.
-    FakeGaia::AccessTokenInfo login_token_info;
-    login_token_info.token = kTestLoginToken;
-    login_token_info.scopes.insert(GaiaConstants::kAnyApiOAuth2Scope);
-    login_token_info.audience = gaia_urls->oauth2_chrome_client_id();
-    fake_gaia_->IssueOAuthToken(kTestRefreshToken, login_token_info);
-
-    // The /auth/chromesync access token for accessing sync endpoint.
-    FakeGaia::AccessTokenInfo sync_token_info;
-    sync_token_info.token = kTestSyncToken;
-    sync_token_info.scopes.insert(GaiaConstants::kChromeSyncOAuth2Scope);
-    sync_token_info.audience = gaia_urls->oauth2_chrome_client_id();
-    fake_gaia_->IssueOAuthToken(kTestRefreshToken, sync_token_info);
-
-    FakeGaia::AccessTokenInfo auth_login_token_info;
-    auth_login_token_info.token = kTestAuthLoginToken;
-    auth_login_token_info.scopes.insert(GaiaConstants::kOAuth1LoginScope);
-    auth_login_token_info.audience = gaia_urls->oauth2_chrome_client_id();
-    fake_gaia_->IssueOAuthToken(kTestRefreshToken, auth_login_token_info);
-  }
-
   void CheckSessionState(OAuth2LoginManager::SessionRestoreState state) {
     OAuth2LoginManager* login_manager =
          OAuth2LoginManagerFactory::GetInstance()->GetForProfile(
@@ -396,7 +399,25 @@
     return login_manager->restore_strategy_;
   }
 
+  void InterceptRequest(const HttpRequest& request) {
+    const GURL request_url =
+        GURL("http://localhost").Resolve(request.relative_url);
+    auto it = request_deferers_.find(request_url.path());
+    if (it == request_deferers_.end())
+      return;
+
+    it->second->InterceptRequest(request);
+  }
+
+  void AddRequestDeferer(const std::string& path,
+                         RequestDeferrer* request_deferer) {
+    DCHECK(request_deferers_.find(path) == request_deferers_.end());
+    request_deferers_[path] = request_deferer;
+  }
+
  private:
+  std::map<std::string, RequestDeferrer*> request_deferers_;
+
   DISALLOW_COPY_AND_ASSIGN(OAuth2Test);
 };
 
@@ -410,8 +431,8 @@
     content::BrowserThread::PostTask(
         content::BrowserThread::IO, FROM_HERE,
         base::BindOnce(&CookieReader::ReadCookiesOnIOThread, this));
-    runner_ = new content::MessageLoopRunner;
-    runner_->Run();
+    run_loop_ = std::make_unique<base::RunLoop>();
+    run_loop_->Run();
   }
 
   std::string GetCookieValue(const std::string& name) {
@@ -444,13 +465,11 @@
         base::BindOnce(&CookieReader::OnCookiesReadyOnUIThread, this));
   }
 
-  void OnCookiesReadyOnUIThread() {
-    runner_->Quit();
-  }
+  void OnCookiesReadyOnUIThread() { run_loop_->Quit(); }
 
   scoped_refptr<net::URLRequestContextGetter> context_;
   net::CookieList cookie_list_;
-  scoped_refptr<content::MessageLoopRunner> runner_;
+  std::unique_ptr<base::RunLoop> run_loop_;
 
   DISALLOW_COPY_AND_ASSIGN(CookieReader);
 };
@@ -616,14 +635,72 @@
   WaitForMergeSessionCompletion(OAuth2LoginManager::SESSION_RESTORE_FAILED);
 }
 
-const char kGooglePageContent[] =
+// Sets up a new user with stored refresh token.
+IN_PROC_BROWSER_TEST_F(OAuth2Test, PRE_SetInvalidTokenStatus) {
+  StartNewUserSession(true);
+}
+
+// Tests that an auth error reported by SigninErrorController marks invalid auth
+// token status despite OAuth2LoginManager thinks merge session is done
+// successfully
+IN_PROC_BROWSER_TEST_F(OAuth2Test, SetInvalidTokenStatus) {
+  RequestDeferrer list_accounts_request_deferer;
+  AddRequestDeferer("/ListAccounts", &list_accounts_request_deferer);
+
+  SetupGaiaServerForUnexpiredAccount();
+  SimulateNetworkOnline();
+
+  // Waits for login screen to be ready.
+  content::WindowedNotificationObserver(
+      chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
+      content::NotificationService::AllSources())
+      .Wait();
+
+  // Signs in as the existing user created in pre test.
+  ExistingUserController* const controller =
+      ExistingUserController::current_controller();
+  UserContext user_context(
+      AccountId::FromUserEmailGaiaId(kTestEmail, kTestGaiaId));
+  user_context.SetKey(Key(kTestAccountPassword));
+  controller->Login(user_context, SigninSpecifics());
+
+  // Wait until /ListAccounts request happens so that an auth error can be
+  // generated after user profile is available but before merge session
+  // finishes.
+  list_accounts_request_deferer.WaitForRequestToStart();
+
+  // Make sure that merge session is not finished.
+  OAuth2LoginManager* const login_manager =
+      OAuth2LoginManagerFactory::GetInstance()->GetForProfile(profile());
+  ASSERT_NE(OAuth2LoginManager::SESSION_RESTORE_DONE, login_manager->state());
+
+  // Generate an auth error.
+  SigninErrorController* const error_controller =
+      SigninErrorControllerFactory::GetForProfile(profile());
+  FakeAuthStatusProvider auth_provider(error_controller);
+  auth_provider.SetAuthError(
+      kTestEmail, GoogleServiceAuthError(
+                      GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS));
+
+  // Let go /ListAccounts request.
+  list_accounts_request_deferer.UnblockRequest();
+
+  // Wait for the session merge to finish with success.
+  WaitForMergeSessionCompletion(OAuth2LoginManager::SESSION_RESTORE_DONE);
+
+  // User oauth2 token status should be marked as invalid because of auth error
+  // and regardless of the merge session outcome.
+  EXPECT_EQ(GetOAuthStatusFromLocalState(kTestEmail),
+            user_manager::User::OAUTH2_TOKEN_STATUS_INVALID);
+}
+
+constexpr char kGooglePageContent[] =
     "<html><title>Hello!</title><script>alert('hello');</script>"
     "<body>Hello Google!</body></html>";
-const char kRandomPageContent[] =
+constexpr char kRandomPageContent[] =
     "<html><title>SomthingElse</title><body>I am SomethingElse</body></html>";
-const char kHelloPagePath[] = "/hello_google";
-const char kRandomPagePath[] = "/non_google_page";
-
+constexpr char kHelloPagePath[] = "/hello_google";
+constexpr char kRandomPagePath[] = "/non_google_page";
 
 // FakeGoogle serves content of http://www.google.com/hello_google page for
 // merge session tests.
@@ -672,78 +749,29 @@
     if (start_event_.IsSignaled())
       return;
 
-    runner_ = new content::MessageLoopRunner;
-    runner_->Run();
+    run_loop_ = std::make_unique<base::RunLoop>();
+    run_loop_->Run();
   }
 
  private:
   void QuitRunnerOnUIThread() {
-    if (runner_.get())
-      runner_->Quit();
+    if (run_loop_)
+      run_loop_->Quit();
   }
   // This event will tell us when we actually see HTTP request on the server
   // side. It should be signalled only after the page/XHR throttle had been
   // removed (after merge session completes).
   base::WaitableEvent start_event_;
-  scoped_refptr<content::MessageLoopRunner> runner_;
+  std::unique_ptr<base::RunLoop> run_loop_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeGoogle);
 };
 
-// FakeGaia specialization that can delay /MergeSession handler until
-// we explicitly call DelayedFakeGaia::UnblockMergeSession().
-class DelayedFakeGaia : public FakeGaia {
- public:
-  DelayedFakeGaia()
-      : blocking_event_(base::WaitableEvent::ResetPolicy::MANUAL,
-                        base::WaitableEvent::InitialState::NOT_SIGNALED),
-        start_event_(base::WaitableEvent::ResetPolicy::MANUAL,
-                     base::WaitableEvent::InitialState::NOT_SIGNALED) {}
-
-  void UnblockMergeSession() {
-    blocking_event_.Signal();
-  }
-
-  void WaitForMergeSessionToStart() {
-    // If we have already served the request, bail out.
-    if (start_event_.IsSignaled())
-      return;
-
-    runner_ = new content::MessageLoopRunner;
-    runner_->Run();
-  }
-
- private:
-  // FakeGaia overrides.
-  void HandleMergeSession(const HttpRequest& request,
-                          BasicHttpResponse* http_response) override {
-    start_event_.Signal();
-    content::BrowserThread::PostTask(
-        content::BrowserThread::UI, FROM_HERE,
-        base::BindOnce(&DelayedFakeGaia::QuitRunnerOnUIThread,
-                       base::Unretained(this)));
-    blocking_event_.Wait();
-    FakeGaia::HandleMergeSession(request, http_response);
-  }
-
-  void QuitRunnerOnUIThread() {
-    if (runner_.get())
-      runner_->Quit();
-  }
-
-  base::WaitableEvent blocking_event_;
-  base::WaitableEvent start_event_;
-  scoped_refptr<content::MessageLoopRunner> runner_;
-
-  DISALLOW_COPY_AND_ASSIGN(DelayedFakeGaia);
-};
-
 class MergeSessionTest : public OAuth2Test {
  protected:
-  MergeSessionTest() : delayed_fake_gaia_(new DelayedFakeGaia()) {
-    fake_gaia_.reset(delayed_fake_gaia_);
-  }
+  MergeSessionTest() = default;
 
+  // OAuth2Test overrides.
   void SetUpCommandLine(base::CommandLine* command_line) override {
     OAuth2Test::SetUpCommandLine(command_line);
 
@@ -760,19 +788,19 @@
     non_google_page_url_ = non_google_url.Resolve(kRandomPagePath);
   }
 
-  void SetUp() override {
+  void RegisterAdditionalRequestHandlers() override {
+    OAuth2Test::RegisterAdditionalRequestHandlers();
+    AddRequestDeferer("/MergeSession", &merge_session_deferer_);
+
     embedded_test_server()->RegisterRequestHandler(base::Bind(
         &FakeGoogle::HandleRequest, base::Unretained(&fake_google_)));
-    OAuth2Test::SetUp();
   }
 
  protected:
-  void UnblockMergeSession() {
-    delayed_fake_gaia_->UnblockMergeSession();
-  }
+  void UnblockMergeSession() { merge_session_deferer_.UnblockRequest(); }
 
   void WaitForMergeSessionToStart() {
-    delayed_fake_gaia_->WaitForMergeSessionToStart();
+    merge_session_deferer_.WaitForRequestToStart();
   }
 
   void JsExpect(content::WebContents* contents,
@@ -809,7 +837,7 @@
   }
 
   FakeGoogle fake_google_;
-  DelayedFakeGaia* delayed_fake_gaia_;
+  RequestDeferrer merge_session_deferer_;
   GURL fake_google_page_url_;
   GURL non_google_page_url_;
 
diff --git a/chrome/browser/chromeos/login/test/oobe_base_test.cc b/chrome/browser/chromeos/login/test/oobe_base_test.cc
index df875259..c9f1706 100644
--- a/chrome/browser/chromeos/login/test/oobe_base_test.cc
+++ b/chrome/browser/chromeos/login/test/oobe_base_test.cc
@@ -30,6 +30,7 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/test/browser_test_utils.h"
 #include "google_apis/gaia/gaia_switches.h"
+#include "google_apis/gaia/gaia_urls.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
@@ -37,8 +38,11 @@
 namespace chromeos {
 
 namespace {
-const char kGAIAHost[] = "accounts.google.com";
-}
+
+constexpr char kGAIAHost[] = "accounts.google.com";
+constexpr char kTestAllScopeAccessToken[] = "fake-all-scope-token";
+
+}  // namespace
 
 // static
 const char OobeBaseTest::kFakeUserEmail[] = "fake-email@gmail.com";
@@ -60,6 +64,8 @@
 OobeBaseTest::~OobeBaseTest() {
 }
 
+void OobeBaseTest::RegisterAdditionalRequestHandlers() {}
+
 void OobeBaseTest::SetUp() {
   base::FilePath test_data_dir;
   PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
@@ -160,9 +166,6 @@
       kGAIAHost, embedded_test_server()->base_url()));
 }
 
-void OobeBaseTest::RegisterAdditionalRequestHandlers() {
-}
-
 void OobeBaseTest::SimulateNetworkOffline() {
   NetworkPortalDetector::CaptivePortalState offline_state;
   offline_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE;
@@ -277,4 +280,18 @@
   ExecuteJsInSigninFrame(js);
 }
 
+void OobeBaseTest::SetupFakeGaiaForLogin(const std::string& user_email,
+                                         const std::string& gaia_id,
+                                         const std::string& refresh_token) {
+  if (!gaia_id.empty())
+    fake_gaia_->MapEmailToGaiaId(user_email, gaia_id);
+
+  FakeGaia::AccessTokenInfo token_info;
+  token_info.token = kTestAllScopeAccessToken;
+  token_info.audience = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
+  token_info.email = user_email;
+  token_info.any_scope = true;
+  fake_gaia_->IssueOAuthToken(refresh_token, token_info);
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/test/oobe_base_test.h b/chrome/browser/chromeos/login/test/oobe_base_test.h
index 431d040b..30160e7 100644
--- a/chrome/browser/chromeos/login/test/oobe_base_test.h
+++ b/chrome/browser/chromeos/login/test/oobe_base_test.h
@@ -97,6 +97,15 @@
   void SetSignFormField(const std::string& field_id,
                         const std::string& field_value);
 
+  // Sets up fake gaia for the login code:
+  // - Maps |user_email| to |gaia_id|. If |gaia_id| is empty, |user_email| will
+  //   be mapped to kDefaultGaiaId in FakeGaia;
+  // - Issues a special all-scope access token associated with the test refresh
+  //   token;
+  void SetupFakeGaiaForLogin(const std::string& user_email,
+                             const std::string& gaia_id,
+                             const std::string& refresh_token);
+
   std::unique_ptr<FakeGaia> fake_gaia_;
   NetworkPortalDetectorTestImpl* network_portal_detector_;
 
diff --git a/chrome/browser/chromeos/login/ui/webui_login_view.cc b/chrome/browser/chromeos/login/ui/webui_login_view.cc
index dbf0c49..5c09561 100644
--- a/chrome/browser/chromeos/login/ui/webui_login_view.cc
+++ b/chrome/browser/chromeos/login/ui/webui_login_view.cc
@@ -46,6 +46,7 @@
 #include "chromeos/network/network_state_handler.h"
 #include "components/content_settings/core/common/content_settings_pattern.h"
 #include "components/password_manager/core/browser/password_manager.h"
+#include "components/session_manager/core/session_manager.h"
 #include "components/web_modal/web_contents_modal_dialog_manager.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/render_frame_host.h"
@@ -85,7 +86,6 @@
 const char kAccelNameDeviceRequisitionShark[] = "device_requisition_shark";
 const char kAccelNameAppLaunchBailout[] = "app_launch_bailout";
 const char kAccelNameAppLaunchNetworkConfig[] = "app_launch_network_config";
-const char kAccelNameToggleEasyBootstrap[] = "toggle_easy_bootstrap";
 const char kAccelNameBootstrappingSlave[] = "bootstrapping_slave";
 
 // A class to change arrow key traversal behavior when it's alive.
@@ -152,9 +152,6 @@
   accel_map_[ui::Accelerator(ui::VKEY_X,
       ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN)] =
       kAccelNameEnableDebugging;
-  accel_map_[ui::Accelerator(
-      ui::VKEY_B, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN)] =
-      kAccelNameToggleEasyBootstrap;
 
   accel_map_[ui::Accelerator(
       ui::VKEY_D, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN)] =
@@ -603,6 +600,13 @@
   if (ash_util::IsRunningInMash())
     return true;
 
+  // The focus should not move to the system tray if voice interaction OOOBE is
+  // active.
+  if (LoginDisplayHost::default_host() &&
+      LoginDisplayHost::default_host()->IsVoiceInteractionOobe()) {
+    return false;
+  }
+
   // If shift+tab is used (|reverse| is true) and views-based shelf is shown,
   // focus goes to the shelf widget. If views-based shelf is disabled, focus
   // goes to the system tray, because the web-UI shelf has already been
diff --git a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc
index 906a446..a8cda98 100644
--- a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc
+++ b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc
@@ -185,7 +185,6 @@
 
   SupervisedUserManager::RegisterPrefs(registry);
   SessionLengthLimiter::RegisterPrefs(registry);
-  BootstrapManager::RegisterPrefs(registry);
   enterprise_user_session_metrics::RegisterPrefs(registry);
 }
 
@@ -202,7 +201,6 @@
       cros_settings_(CrosSettings::Get()),
       device_local_account_policy_service_(NULL),
       supervised_user_manager_(new SupervisedUserManagerImpl(this)),
-      bootstrap_manager_(new BootstrapManager(this)),
       weak_factory_(this) {
   UpdateNumberOfUsers();
 
@@ -298,10 +296,6 @@
   registrar_.RemoveAll();
 }
 
-BootstrapManager* ChromeUserManagerImpl::GetBootstrapManager() {
-  return bootstrap_manager_.get();
-}
-
 MultiProfileUserController*
 ChromeUserManagerImpl::GetMultiProfileUserController() {
   return multi_profile_user_controller_.get();
@@ -496,9 +490,11 @@
           ManagerPasswordServiceFactory::GetForProfile(profile);
 
         if (!profile->IsOffTheRecord()) {
-          AuthSyncObserver* sync_observer =
-              AuthSyncObserverFactory::GetInstance()->GetForProfile(profile);
-          sync_observer->StartObserving();
+          if (AuthSyncObserver::ShouldObserve(profile)) {
+            AuthSyncObserver* sync_observer =
+                AuthSyncObserverFactory::GetInstance()->GetForProfile(profile);
+            sync_observer->StartObserving();
+          }
           multi_profile_user_controller_->StartObserving(profile);
         }
       }
@@ -670,9 +666,6 @@
   // This process also should not trigger EnsureUsersLoaded again.
   if (supervised_user_manager_->HasFailedUserCreationTransaction())
     supervised_user_manager_->RollbackUserCreationTransaction();
-
-  // Abandon all unfinished bootstraps.
-  bootstrap_manager_->RemoveAllPendingBootstrap();
 }
 
 void ChromeUserManagerImpl::PerformPostUserListLoadingActions() {
@@ -845,11 +838,6 @@
   GetLocalState()->CommitPendingWrite();
 }
 
-bool ChromeUserManagerImpl::HasPendingBootstrap(
-    const AccountId& account_id) const {
-  return bootstrap_manager_->HasPendingBootstrap(account_id);
-}
-
 void ChromeUserManagerImpl::PublicAccountUserLoggedIn(
     user_manager::User* user) {
   SetIsCurrentUserNew(true);
@@ -1222,12 +1210,6 @@
       chrome::DialogIdentifier::MULTIPROFILES_SESSION_ABORTED);
 }
 
-void ChromeUserManagerImpl::RemovePendingBootstrapUser(
-    const AccountId& account_id) {
-  DCHECK(HasPendingBootstrap(account_id));
-  RemoveNonOwnerUserInternal(account_id, nullptr);
-}
-
 void ChromeUserManagerImpl::UpdateNumberOfUsers() {
   size_t users = GetLoggedInUsers().size();
   if (users) {
diff --git a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.h b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.h
index a3f4eba8..12aefa83 100644
--- a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.h
+++ b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.h
@@ -16,7 +16,6 @@
 #include "base/observer_list.h"
 #include "base/synchronization/lock.h"
 #include "base/time/time.h"
-#include "chrome/browser/chromeos/login/easy_unlock/bootstrap_manager.h"
 #include "chrome/browser/chromeos/login/user_flow.h"
 #include "chrome/browser/chromeos/login/users/affiliation.h"
 #include "chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.h"
@@ -55,8 +54,7 @@
       public content::NotificationObserver,
       public policy::CloudExternalDataPolicyObserver::Delegate,
       public policy::DeviceLocalAccountPolicyService::Observer,
-      public MultiProfileUserControllerDelegate,
-      public BootstrapManager::Delegate {
+      public MultiProfileUserControllerDelegate {
  public:
   ~ChromeUserManagerImpl() override;
 
@@ -67,7 +65,6 @@
   static void RegisterPrefs(PrefRegistrySimple* registry);
 
   // UserManagerInterface implementation:
-  BootstrapManager* GetBootstrapManager() override;
   MultiProfileUserController* GetMultiProfileUserController() override;
   UserImageManager* GetUserImageManager(const AccountId& account_id) override;
   SupervisedUserManager* GetSupervisedUserManager() override;
@@ -169,7 +166,6 @@
   void RegularUserLoggedIn(const AccountId& account_id) override;
   void RegularUserLoggedInAsEphemeral(const AccountId& account_id) override;
   void SupervisedUserLoggedIn(const AccountId& account_id) override;
-  bool HasPendingBootstrap(const AccountId& account_id) const override;
 
  private:
   friend class SupervisedUserManagerImpl;
@@ -218,9 +214,6 @@
   // MultiProfileUserControllerDelegate implementation:
   void OnUserNotAllowed(const std::string& user_email) override;
 
-  // BootstrapManager::Delegate implementation:
-  void RemovePendingBootstrapUser(const AccountId& account_id) override;
-
   // Update the number of users.
   void UpdateNumberOfUsers();
 
@@ -278,8 +271,6 @@
   std::unique_ptr<policy::CloudExternalDataPolicyObserver>
       wallpaper_policy_observer_;
 
-  std::unique_ptr<BootstrapManager> bootstrap_manager_;
-
   base::WeakPtrFactory<ChromeUserManagerImpl> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ChromeUserManagerImpl);
diff --git a/chrome/browser/chromeos/login/users/fake_chrome_user_manager.cc b/chrome/browser/chromeos/login/users/fake_chrome_user_manager.cc
index 1dcb01e..53157bf 100644
--- a/chrome/browser/chromeos/login/users/fake_chrome_user_manager.cc
+++ b/chrome/browser/chromeos/login/users/fake_chrome_user_manager.cc
@@ -149,10 +149,6 @@
   }
 }
 
-BootstrapManager* FakeChromeUserManager::GetBootstrapManager() {
-  return bootstrap_manager_;
-}
-
 MultiProfileUserController*
 FakeChromeUserManager::GetMultiProfileUserController() {
   return multi_profile_user_controller_;
diff --git a/chrome/browser/chromeos/login/users/fake_chrome_user_manager.h b/chrome/browser/chromeos/login/users/fake_chrome_user_manager.h
index 20084fb4..e224a35b 100644
--- a/chrome/browser/chromeos/login/users/fake_chrome_user_manager.h
+++ b/chrome/browser/chromeos/login/users/fake_chrome_user_manager.h
@@ -151,7 +151,6 @@
                         bool is_current_user_owner) const override;
 
   // UserManagerInterface override.
-  BootstrapManager* GetBootstrapManager() override;
   MultiProfileUserController* GetMultiProfileUserController() override;
   UserImageManager* GetUserImageManager(const AccountId& account_id) override;
   SupervisedUserManager* GetSupervisedUserManager() override;
@@ -176,10 +175,6 @@
     owner_account_id_ = owner_account_id;
   }
 
-  void set_bootstrap_manager(BootstrapManager* bootstrap_manager) {
-    bootstrap_manager_ = bootstrap_manager;
-  }
-
   void set_multi_profile_user_controller(
       MultiProfileUserController* controller) {
     multi_profile_user_controller_ = controller;
@@ -199,7 +194,6 @@
   bool fake_ephemeral_users_enabled_ = false;
   bool current_user_new_ = false;
 
-  BootstrapManager* bootstrap_manager_ = nullptr;
   MultiProfileUserController* multi_profile_user_controller_ = nullptr;
 
   // If set this is the active user. If empty, the first created user is the
diff --git a/chrome/browser/chromeos/login/users/mock_user_manager.cc b/chrome/browser/chromeos/login/users/mock_user_manager.cc
index 0ead43d..4563a8b 100644
--- a/chrome/browser/chromeos/login/users/mock_user_manager.cc
+++ b/chrome/browser/chromeos/login/users/mock_user_manager.cc
@@ -64,10 +64,6 @@
   return GetActiveUser();
 }
 
-BootstrapManager* MockUserManager::GetBootstrapManager() {
-  return nullptr;
-}
-
 MultiProfileUserController* MockUserManager::GetMultiProfileUserController() {
   return nullptr;
 }
diff --git a/chrome/browser/chromeos/login/users/mock_user_manager.h b/chrome/browser/chromeos/login/users/mock_user_manager.h
index edceae1..7b56c15 100644
--- a/chrome/browser/chromeos/login/users/mock_user_manager.h
+++ b/chrome/browser/chromeos/login/users/mock_user_manager.h
@@ -130,7 +130,6 @@
   const user_manager::User* GetPrimaryUser() const override;
 
   // ChromeUserManager overrides:
-  BootstrapManager* GetBootstrapManager() override;
   MultiProfileUserController* GetMultiProfileUserController() override;
   UserImageManager* GetUserImageManager(const AccountId& account_id) override;
   SupervisedUserManager* GetSupervisedUserManager() override;
diff --git a/chrome/browser/chromeos/login/users/user_manager_interface.h b/chrome/browser/chromeos/login/users/user_manager_interface.h
index 10e0238..446cba12 100644
--- a/chrome/browser/chromeos/login/users/user_manager_interface.h
+++ b/chrome/browser/chromeos/login/users/user_manager_interface.h
@@ -13,7 +13,6 @@
 
 namespace chromeos {
 
-class BootstrapManager;
 class MultiProfileUserController;
 class SupervisedUserManager;
 class UserFlow;
@@ -25,7 +24,6 @@
   UserManagerInterface() {}
   virtual ~UserManagerInterface() {}
 
-  virtual BootstrapManager* GetBootstrapManager() = 0;
   virtual MultiProfileUserController* GetMultiProfileUserController() = 0;
   virtual UserImageManager* GetUserImageManager(
       const AccountId& account_id) = 0;
diff --git a/chrome/browser/chromeos/policy/device_off_hours_controller.cc b/chrome/browser/chromeos/policy/device_off_hours_controller.cc
index 3d1c3cde..fb2abb7 100644
--- a/chrome/browser/chromeos/policy/device_off_hours_controller.cc
+++ b/chrome/browser/chromeos/policy/device_off_hours_controller.cc
@@ -30,9 +30,10 @@
 constexpr base::TimeDelta kDay = base::TimeDelta::FromDays(1);
 constexpr base::TimeDelta kWeek = base::TimeDelta::FromDays(7);
 
-// Put time in milliseconds which is added to GMT to get local time to |offset|
-// considering current daylight time. Return true if there was no error.
-bool GetTimezoneOffset(const std::string& timezone, int* offset) {
+// Put time in milliseconds which is added to local time to get GMT time to
+// |offset| considering current daylight time. Return true if there was no
+// error.
+bool GetOffsetFromTimezoneToGmt(const std::string& timezone, int* offset) {
   auto zone = base::WrapUnique(
       icu::TimeZone::createTimeZone(icu::UnicodeString::fromUTF8(timezone)));
   if (*zone == icu::TimeZone::getUnknown()) {
@@ -59,7 +60,8 @@
   }
   if (day_light)
     gmt_offset += dst_offset;
-  *offset = gmt_offset;
+  // -|gmt_offset| is time which is added to local time to get GMT time.
+  *offset = -gmt_offset;
   return true;
 }
 
@@ -121,37 +123,19 @@
   return base::make_optional(container.timezone());
 }
 
-// Convert input WeeklyTime structure to GMT timezone considering daylight time.
-// |gmt_offset| is time in milliseconds which is added to GMT to get input time.
-off_hours::WeeklyTime ConvertWeeklyTimeToGmt(
-    const off_hours::WeeklyTime& weekly_time,
-    int gmt_offset) {
-  // Convert time in milliseconds to GMT time considering day offset.
-  int gmt_time = weekly_time.milliseconds() - gmt_offset;
-  // Make |time_in_gmt| positive number (add number of milliseconds per week)
-  // for easier evaluation.
-  gmt_time += kWeek.InMilliseconds();
-  // Get milliseconds from the start of the day.
-  int gmt_milliseconds = gmt_time % kDay.InMilliseconds();
-  int day_offset = gmt_time / kDay.InMilliseconds();
-  // Convert day of week to GMT timezone considering week is cyclic. +/- 1 is
-  // because day of week is from 1 to 7.
-  int gmt_day_of_week = (weekly_time.day_of_week() + day_offset - 1) % 7 + 1;
-  return off_hours::WeeklyTime(gmt_day_of_week, gmt_milliseconds);
-}
-
 // Convert time intervals from |timezone| to GMT timezone.
 std::vector<off_hours::OffHoursInterval> ConvertIntervalsToGmt(
     const std::vector<off_hours::OffHoursInterval>& intervals,
     const std::string& timezone) {
   int gmt_offset = 0;
-  bool no_offset_error = GetTimezoneOffset(timezone, &gmt_offset);
+  bool no_offset_error = GetOffsetFromTimezoneToGmt(timezone, &gmt_offset);
   if (!no_offset_error)
     return {};
   std::vector<off_hours::OffHoursInterval> gmt_intervals;
   for (const auto& interval : intervals) {
-    auto gmt_start = ConvertWeeklyTimeToGmt(interval.start(), gmt_offset);
-    auto gmt_end = ConvertWeeklyTimeToGmt(interval.end(), gmt_offset);
+    // |gmt_offset| is added to input time to get GMT time.
+    auto gmt_start = interval.start().AddMilliseconds(gmt_offset);
+    auto gmt_end = interval.end().AddMilliseconds(gmt_offset);
     gmt_intervals.push_back(off_hours::OffHoursInterval(gmt_start, gmt_end));
   }
   return gmt_intervals;
diff --git a/chrome/browser/chromeos/policy/login_policy_test_base.cc b/chrome/browser/chromeos/policy/login_policy_test_base.cc
index 85db1eab..0af6aba 100644
--- a/chrome/browser/chromeos/policy/login_policy_test_base.cc
+++ b/chrome/browser/chromeos/policy/login_policy_test_base.cc
@@ -13,23 +13,20 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/test/test_utils.h"
 #include "google_apis/gaia/fake_gaia.h"
-#include "google_apis/gaia/gaia_constants.h"
-#include "google_apis/gaia/gaia_urls.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace policy {
 
 namespace {
 
-const char kTestAuthCode[] = "fake-auth-code";
-const char kTestGaiaUberToken[] = "fake-uber-token";
-const char kTestAuthLoginAccessToken[] = "fake-access-token";
-const char kTestRefreshToken[] = "fake-refresh-token";
-const char kTestAuthSIDCookie[] = "fake-auth-SID-cookie";
-const char kTestAuthLSIDCookie[] = "fake-auth-LSID-cookie";
-const char kTestSessionSIDCookie[] = "fake-session-SID-cookie";
-const char kTestSessionLSIDCookie[] = "fake-session-LSID-cookie";
-const char kTestUserinfoToken[] = "fake-userinfo-token";
+constexpr char kTestAuthCode[] = "fake-auth-code";
+constexpr char kTestGaiaUberToken[] = "fake-uber-token";
+constexpr char kTestAuthLoginAccessToken[] = "fake-access-token";
+constexpr char kTestRefreshToken[] = "fake-refresh-token";
+constexpr char kTestAuthSIDCookie[] = "fake-auth-SID-cookie";
+constexpr char kTestAuthLSIDCookie[] = "fake-auth-LSID-cookie";
+constexpr char kTestSessionSIDCookie[] = "fake-session-SID-cookie";
+constexpr char kTestSessionLSIDCookie[] = "fake-session-LSID-cookie";
 
 }  // namespace
 
@@ -60,7 +57,7 @@
 
 void LoginPolicyTestBase::SetUpOnMainThread() {
   SetMergeSessionParams();
-  SetUpGaiaServerWithAccessTokens();
+  SetupFakeGaiaForLogin(kAccountId, "", kTestRefreshToken);
   OobeBaseTest::SetUpOnMainThread();
 }
 
@@ -72,16 +69,6 @@
     base::DictionaryValue* policy) const {
 }
 
-void LoginPolicyTestBase::SetUpGaiaServerWithAccessTokens() {
-  FakeGaia::AccessTokenInfo token_info;
-  token_info.token = kTestUserinfoToken;
-  token_info.scopes.insert(GaiaConstants::kDeviceManagementServiceOAuth);
-  token_info.scopes.insert(GaiaConstants::kOAuthWrapBridgeUserInfoScope);
-  token_info.audience = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
-  token_info.email = kAccountId;
-  fake_gaia_->IssueOAuthToken(kTestRefreshToken, token_info);
-}
-
 void LoginPolicyTestBase::SetMergeSessionParams() {
   FakeGaia::MergeSessionParams params;
   params.auth_sid_cookie = kTestAuthSIDCookie;
diff --git a/chrome/browser/chromeos/policy/off_hours/off_hours_interval.cc b/chrome/browser/chromeos/policy/off_hours/off_hours_interval.cc
index 8bb1051..bbe8ba9 100644
--- a/chrome/browser/chromeos/policy/off_hours/off_hours_interval.cc
+++ b/chrome/browser/chromeos/policy/off_hours/off_hours_interval.cc
@@ -23,6 +23,8 @@
 }
 
 bool OffHoursInterval::Contains(const WeeklyTime& w) const {
+  if (w.GetDurationTo(end_).is_zero())
+    return false;
   base::TimeDelta interval_duration = start_.GetDurationTo(end_);
   return start_.GetDurationTo(w) + w.GetDurationTo(end_) == interval_duration;
 }
diff --git a/chrome/browser/chromeos/policy/off_hours/off_hours_interval.h b/chrome/browser/chromeos/policy/off_hours/off_hours_interval.h
index 0022f4e..dd782d2200 100644
--- a/chrome/browser/chromeos/policy/off_hours/off_hours_interval.h
+++ b/chrome/browser/chromeos/policy/off_hours/off_hours_interval.h
@@ -15,6 +15,7 @@
 
 // Represents non-emply time interval [start, end) between two weekly times.
 // Interval can be wrapped across the end of the week.
+// Interval is empty if start = end. Empty intervals isn't allowed.
 class OffHoursInterval {
  public:
   OffHoursInterval(const WeeklyTime& start, const WeeklyTime& end);
diff --git a/chrome/browser/chromeos/policy/off_hours/off_hours_interval_unittest.cc b/chrome/browser/chromeos/policy/off_hours/off_hours_interval_unittest.cc
new file mode 100644
index 0000000..082e491a
--- /dev/null
+++ b/chrome/browser/chromeos/policy/off_hours/off_hours_interval_unittest.cc
@@ -0,0 +1,185 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/policy/off_hours/off_hours_interval.h"
+
+#include <tuple>
+#include <utility>
+
+#include "base/time/time.h"
+#include "base/values.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+
+using policy::off_hours::WeeklyTime;
+using policy::off_hours::OffHoursInterval;
+
+namespace {
+
+enum {
+  kMonday = 1,
+  kTuesday = 2,
+  kWednesday = 3,
+  kThursday = 4,
+  kFriday = 5,
+  kSaturday = 6,
+  kSunday = 7,
+};
+
+const int kMinutesInHour = 60;
+
+constexpr base::TimeDelta kMinute = base::TimeDelta::FromMinutes(1);
+
+}  // namespace
+
+class SingleOffHoursIntervalTest
+    : public testing::TestWithParam<std::tuple<int, int, int, int>> {
+ protected:
+  int start_day_of_week() const { return std::get<0>(GetParam()); }
+  int start_time() const { return std::get<1>(GetParam()); }
+  int end_day_of_week() const { return std::get<2>(GetParam()); }
+  int end_time() const { return std::get<3>(GetParam()); }
+};
+
+TEST_P(SingleOffHoursIntervalTest, Constructor) {
+  WeeklyTime start =
+      WeeklyTime(start_day_of_week(), start_time() * kMinute.InMilliseconds());
+  WeeklyTime end =
+      WeeklyTime(end_day_of_week(), end_time() * kMinute.InMilliseconds());
+  OffHoursInterval interval = OffHoursInterval(start, end);
+  EXPECT_EQ(interval.start().day_of_week(), start_day_of_week());
+  EXPECT_EQ(interval.start().milliseconds(),
+            start_time() * kMinute.InMilliseconds());
+  EXPECT_EQ(interval.end().day_of_week(), end_day_of_week());
+  EXPECT_EQ(interval.end().milliseconds(),
+            end_time() * kMinute.InMilliseconds());
+}
+
+TEST_P(SingleOffHoursIntervalTest, ToValue) {
+  WeeklyTime start = WeeklyTime(start_day_of_week(), start_time());
+  WeeklyTime end = WeeklyTime(end_day_of_week(), end_time());
+  OffHoursInterval interval = OffHoursInterval(start, end);
+  std::unique_ptr<base::DictionaryValue> interval_value = interval.ToValue();
+  base::DictionaryValue expected_interval_value;
+  expected_interval_value.SetDictionary("start", start.ToValue());
+  expected_interval_value.SetDictionary("end", end.ToValue());
+  EXPECT_EQ(*interval_value, expected_interval_value);
+}
+
+INSTANTIATE_TEST_CASE_P(OneMinuteInterval,
+                        SingleOffHoursIntervalTest,
+                        testing::Values(std::make_tuple(kWednesday,
+                                                        kMinutesInHour,
+                                                        kWednesday,
+                                                        kMinutesInHour + 1)));
+INSTANTIATE_TEST_CASE_P(
+    TheLongestInterval,
+    SingleOffHoursIntervalTest,
+    testing::Values(
+        std::make_tuple(kMonday, 0, kSunday, 24 * kMinutesInHour - 1)));
+
+INSTANTIATE_TEST_CASE_P(RandomInterval,
+                        SingleOffHoursIntervalTest,
+                        testing::Values(std::make_tuple(kTuesday,
+                                                        10 * kMinutesInHour,
+                                                        kFriday,
+                                                        14 * kMinutesInHour +
+                                                            15)));
+
+class OffHoursIntervalAndWeeklyTimeTest
+    : public testing::TestWithParam<
+          std::tuple<int, int, int, int, int, int, bool>> {
+ protected:
+  int start_day_of_week() const { return std::get<0>(GetParam()); }
+  int start_time() const { return std::get<1>(GetParam()); }
+  int end_day_of_week() const { return std::get<2>(GetParam()); }
+  int end_time() const { return std::get<3>(GetParam()); }
+  int current_day_of_week() const { return std::get<4>(GetParam()); }
+  int current_time() const { return std::get<5>(GetParam()); }
+  bool expected_contains() const { return std::get<6>(GetParam()); }
+};
+
+TEST_P(OffHoursIntervalAndWeeklyTimeTest, Contains) {
+  WeeklyTime start =
+      WeeklyTime(start_day_of_week(), start_time() * kMinute.InMilliseconds());
+  WeeklyTime end =
+      WeeklyTime(end_day_of_week(), end_time() * kMinute.InMilliseconds());
+  OffHoursInterval interval = OffHoursInterval(start, end);
+  WeeklyTime weekly_time = WeeklyTime(
+      current_day_of_week(), current_time() * kMinute.InMilliseconds());
+  EXPECT_EQ(interval.Contains(weekly_time), expected_contains());
+}
+
+INSTANTIATE_TEST_CASE_P(TheLongestInterval,
+                        OffHoursIntervalAndWeeklyTimeTest,
+                        testing::Values(std::make_tuple(kMonday,
+                                                        0,
+                                                        kSunday,
+                                                        24 * kMinutesInHour - 1,
+                                                        kWednesday,
+                                                        10 * kMinutesInHour,
+                                                        true),
+                                        std::make_tuple(kSunday,
+                                                        24 * kMinutesInHour - 1,
+                                                        kMonday,
+                                                        0,
+                                                        kWednesday,
+                                                        10 * kMinutesInHour,
+                                                        false)));
+
+INSTANTIATE_TEST_CASE_P(
+    TheShortestInterval,
+    OffHoursIntervalAndWeeklyTimeTest,
+    testing::Values(std::make_tuple(kMonday,
+                                    0,
+                                    kMonday,
+                                    1,
+                                    kTuesday,
+                                    9 * kMinutesInHour,
+                                    false),
+                    std::make_tuple(kMonday, 0, kMonday, 1, kMonday, 1, false),
+                    std::make_tuple(kMonday, 0, kMonday, 1, kMonday, 0, true)));
+
+INSTANTIATE_TEST_CASE_P(
+    CheckStartInterval,
+    OffHoursIntervalAndWeeklyTimeTest,
+    testing::Values(std::make_tuple(kTuesday,
+                                    10 * kMinutesInHour + 30,
+                                    kFriday,
+                                    14 * kMinutesInHour + 45,
+                                    kTuesday,
+                                    10 * kMinutesInHour + 30,
+                                    true)));
+
+INSTANTIATE_TEST_CASE_P(
+    CheckEndInterval,
+    OffHoursIntervalAndWeeklyTimeTest,
+    testing::Values(std::make_tuple(kTuesday,
+                                    10 * kMinutesInHour + 30,
+                                    kFriday,
+                                    14 * kMinutesInHour + 45,
+                                    kFriday,
+                                    14 * kMinutesInHour + 45,
+                                    false)));
+
+INSTANTIATE_TEST_CASE_P(RandomInterval,
+                        OffHoursIntervalAndWeeklyTimeTest,
+                        testing::Values(std::make_tuple(kFriday,
+                                                        17 * kMinutesInHour +
+                                                            60,
+                                                        kMonday,
+                                                        9 * kMinutesInHour,
+                                                        kSunday,
+                                                        14 * kMinutesInHour,
+                                                        true),
+                                        std::make_tuple(kMonday,
+                                                        9 * kMinutesInHour,
+                                                        kFriday,
+                                                        17 * kMinutesInHour,
+                                                        kSunday,
+                                                        14 * kMinutesInHour,
+                                                        false)));
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/policy/off_hours/weekly_time.cc b/chrome/browser/chromeos/policy/off_hours/weekly_time.cc
index 5f9a80c..fcf6dee 100644
--- a/chrome/browser/chromeos/policy/off_hours/weekly_time.cc
+++ b/chrome/browser/chromeos/policy/off_hours/weekly_time.cc
@@ -10,10 +10,11 @@
 namespace off_hours {
 namespace {
 
-constexpr base::TimeDelta kDay = base::TimeDelta::FromDays(1);
 constexpr base::TimeDelta kWeek = base::TimeDelta::FromDays(7);
-constexpr base::TimeDelta kMinute = base::TimeDelta::FromMinutes(1);
+constexpr base::TimeDelta kDay = base::TimeDelta::FromDays(1);
 constexpr base::TimeDelta kHour = base::TimeDelta::FromHours(1);
+constexpr base::TimeDelta kMinute = base::TimeDelta::FromMinutes(1);
+constexpr base::TimeDelta kSecond = base::TimeDelta::FromSeconds(1);
 
 }  // namespace
 
@@ -25,19 +26,6 @@
   DCHECK_LT(milliseconds, kDay.InMilliseconds());
 }
 
-WeeklyTime WeeklyTime::GetCurrentWeeklyTime() {
-  base::Time::Exploded exploded;
-  base::Time::Now().UTCExplode(&exploded);
-  int day_of_week = exploded.day_of_week;
-  // Exploded contains 0-based day of week (0 = Sunday, etc.)
-  if (day_of_week == 0)
-    day_of_week = 7;
-  return WeeklyTime(day_of_week,
-                    exploded.hour * kHour.InMilliseconds() +
-                        exploded.minute * kMinute.InMilliseconds() +
-                        exploded.second * 1000);
-}
-
 std::unique_ptr<base::DictionaryValue> WeeklyTime::ToValue() const {
   auto weekly_time = base::MakeUnique<base::DictionaryValue>();
   weekly_time->SetInteger("day_of_week", day_of_week_);
@@ -53,5 +41,34 @@
   return base::TimeDelta::FromMilliseconds(duration);
 }
 
+WeeklyTime WeeklyTime::AddMilliseconds(int milliseconds) const {
+  milliseconds %= kWeek.InMilliseconds();
+  // Make |milliseconds| positive number (add number of milliseconds per week)
+  // for easier evaluation.
+  milliseconds += kWeek.InMilliseconds();
+  int shifted_milliseconds = milliseconds_ + milliseconds;
+  // Get milliseconds from the start of the day.
+  int result_milliseconds = shifted_milliseconds % kDay.InMilliseconds();
+  int day_offset = shifted_milliseconds / kDay.InMilliseconds();
+  // Convert day of week considering week is cyclic. +/- 1 is
+  // because day of week is from 1 to 7.
+  int result_day_of_week = (day_of_week_ + day_offset - 1) % 7 + 1;
+  return WeeklyTime(result_day_of_week, result_milliseconds);
+}
+
+// static
+WeeklyTime WeeklyTime::GetCurrentWeeklyTime() {
+  base::Time::Exploded exploded;
+  base::Time::Now().UTCExplode(&exploded);
+  int day_of_week = exploded.day_of_week;
+  // Exploded contains 0-based day of week (0 = Sunday, etc.)
+  if (day_of_week == 0)
+    day_of_week = 7;
+  return WeeklyTime(day_of_week,
+                    exploded.hour * kHour.InMilliseconds() +
+                        exploded.minute * kMinute.InMilliseconds() +
+                        exploded.second * kSecond.InMilliseconds());
+}
+
 }  // namespace off_hours
 }  // namespace policy
diff --git a/chrome/browser/chromeos/policy/off_hours/weekly_time.h b/chrome/browser/chromeos/policy/off_hours/weekly_time.h
index ac3d1ed..123f42bb 100644
--- a/chrome/browser/chromeos/policy/off_hours/weekly_time.h
+++ b/chrome/browser/chromeos/policy/off_hours/weekly_time.h
@@ -36,6 +36,9 @@
   // (i.e. [Friday 17:00, Monday 9:00) )
   base::TimeDelta GetDurationTo(const WeeklyTime& other) const;
 
+  // Add milliseconds to WeeklyTime.
+  WeeklyTime AddMilliseconds(int milliseconds) const;
+
   // Return current time in WeeklyTime structure.
   static WeeklyTime GetCurrentWeeklyTime();
 
diff --git a/chrome/browser/chromeos/policy/off_hours/weekly_time_unittest.cc b/chrome/browser/chromeos/policy/off_hours/weekly_time_unittest.cc
new file mode 100644
index 0000000..2382624c
--- /dev/null
+++ b/chrome/browser/chromeos/policy/off_hours/weekly_time_unittest.cc
@@ -0,0 +1,202 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/policy/off_hours/weekly_time.h"
+
+#include <tuple>
+#include <utility>
+
+#include "base/time/time.h"
+#include "base/values.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+
+using policy::off_hours::WeeklyTime;
+
+namespace {
+
+enum {
+  kMonday = 1,
+  kTuesday = 2,
+  kWednesday = 3,
+  kThursday = 4,
+  kFriday = 5,
+  kSaturday = 6,
+  kSunday = 7,
+};
+
+const int kMinutesInHour = 60;
+
+constexpr base::TimeDelta kMinute = base::TimeDelta::FromMinutes(1);
+constexpr base::TimeDelta kHour = base::TimeDelta::FromHours(1);
+constexpr base::TimeDelta kWeek = base::TimeDelta::FromDays(7);
+
+}  // namespace
+
+class SingleWeeklyTimeTest
+    : public testing::TestWithParam<std::tuple<int, int>> {
+ public:
+  int day_of_week() const { return std::get<0>(GetParam()); }
+  int minutes() const { return std::get<1>(GetParam()); }
+};
+
+TEST_P(SingleWeeklyTimeTest, Constructor) {
+  WeeklyTime weekly_time =
+      WeeklyTime(day_of_week(), minutes() * kMinute.InMilliseconds());
+  EXPECT_EQ(weekly_time.day_of_week(), day_of_week());
+  EXPECT_EQ(weekly_time.milliseconds(), minutes() * kMinute.InMilliseconds());
+}
+
+TEST_P(SingleWeeklyTimeTest, ToValue) {
+  WeeklyTime weekly_time =
+      WeeklyTime(day_of_week(), minutes() * kMinute.InMilliseconds());
+  std::unique_ptr<base::DictionaryValue> weekly_time_value =
+      weekly_time.ToValue();
+  base::DictionaryValue expected_weekly_time;
+  expected_weekly_time.SetInteger("day_of_week", day_of_week());
+  expected_weekly_time.SetInteger("time", minutes() * kMinute.InMilliseconds());
+  EXPECT_EQ(*weekly_time_value, expected_weekly_time);
+}
+
+INSTANTIATE_TEST_CASE_P(TheSmallestCase,
+                        SingleWeeklyTimeTest,
+                        testing::Values(std::make_tuple(kMonday, 0)));
+
+INSTANTIATE_TEST_CASE_P(
+    TheBiggestCase,
+    SingleWeeklyTimeTest,
+    testing::Values(std::make_tuple(kSunday, 24 * kMinutesInHour - 1)));
+
+INSTANTIATE_TEST_CASE_P(
+    RandomCase,
+    SingleWeeklyTimeTest,
+    testing::Values(std::make_tuple(kWednesday, 15 * kMinutesInHour + 30)));
+
+class TwoWeeklyTimesAndDurationTest
+    : public testing::TestWithParam<
+          std::tuple<int, int, int, int, base::TimeDelta>> {
+ public:
+  int day1() const { return std::get<0>(GetParam()); }
+  int minutes1() const { return std::get<1>(GetParam()); }
+  int day2() const { return std::get<2>(GetParam()); }
+  int minutes2() const { return std::get<3>(GetParam()); }
+  base::TimeDelta expected_duration() const { return std::get<4>(GetParam()); }
+};
+
+TEST_P(TwoWeeklyTimesAndDurationTest, GetDuration) {
+  WeeklyTime weekly_time1 =
+      WeeklyTime(day1(), minutes1() * kMinute.InMilliseconds());
+  WeeklyTime weekly_time2 =
+      WeeklyTime(day2(), minutes2() * kMinute.InMilliseconds());
+  EXPECT_EQ(weekly_time1.GetDurationTo(weekly_time2), expected_duration());
+}
+
+INSTANTIATE_TEST_CASE_P(ZeroDuration,
+                        TwoWeeklyTimesAndDurationTest,
+                        testing::Values(std::make_tuple(kWednesday,
+                                                        kMinutesInHour,
+                                                        kWednesday,
+                                                        kMinutesInHour,
+                                                        base::TimeDelta())));
+
+INSTANTIATE_TEST_CASE_P(TheLongestDuration,
+                        TwoWeeklyTimesAndDurationTest,
+                        testing::Values(std::make_tuple(kMonday,
+                                                        0,
+                                                        kSunday,
+                                                        24 * kMinutesInHour - 1,
+                                                        kWeek - kMinute)));
+
+INSTANTIATE_TEST_CASE_P(
+    DifferentDurations,
+    TwoWeeklyTimesAndDurationTest,
+    testing::Values(
+        std::make_tuple(kThursday, 54, kThursday, kMinutesInHour + 54, kHour),
+        std::make_tuple(kSunday, 24 * kMinutesInHour - 1, kMonday, 0, kMinute),
+        std::make_tuple(kSaturday,
+                        15 * kMinutesInHour + 30,
+                        kFriday,
+                        17 * kMinutesInHour + 45,
+                        base::TimeDelta::FromDays(6) +
+                            base::TimeDelta::FromHours(2) +
+                            base::TimeDelta::FromMinutes(15))));
+
+class TwoWeeklyTimesAndOffsetTest
+    : public testing::TestWithParam<std::tuple<int, int, int, int, int>> {
+ public:
+  int day_of_week() const { return std::get<0>(GetParam()); }
+  int minutes() const { return std::get<1>(GetParam()); }
+  int offset_minutes() const { return std::get<2>(GetParam()); }
+  int expected_day() const { return std::get<3>(GetParam()); }
+  int expected_minutes() const { return std::get<4>(GetParam()); }
+};
+
+TEST_P(TwoWeeklyTimesAndOffsetTest, AddMilliseconds) {
+  WeeklyTime weekly_time =
+      WeeklyTime(day_of_week(), minutes() * kMinute.InMilliseconds());
+  WeeklyTime result_weekly_time =
+      weekly_time.AddMilliseconds(offset_minutes() * kMinute.InMilliseconds());
+  EXPECT_EQ(result_weekly_time.day_of_week(), expected_day());
+  EXPECT_EQ(result_weekly_time.milliseconds(),
+            expected_minutes() * kMinute.InMilliseconds());
+}
+
+INSTANTIATE_TEST_CASE_P(
+    ZeroOffset,
+    TwoWeeklyTimesAndOffsetTest,
+    testing::Values(std::make_tuple(kTuesday,
+                                    15 * kMinutesInHour + 30,
+                                    0,
+                                    kTuesday,
+                                    15 * kMinutesInHour + 30)));
+
+INSTANTIATE_TEST_CASE_P(
+    TheSmallestOffset,
+    TwoWeeklyTimesAndOffsetTest,
+    testing::Values(std::make_tuple(kWednesday,
+                                    15 * kMinutesInHour + 30,
+                                    -13 * kMinutesInHour,
+                                    kWednesday,
+                                    2 * kMinutesInHour + 30),
+                    std::make_tuple(kMonday,
+                                    9 * kMinutesInHour + 30,
+                                    -13 * kMinutesInHour,
+                                    kSunday,
+                                    20 * kMinutesInHour + 30)));
+
+INSTANTIATE_TEST_CASE_P(
+    TheBiggestOffset,
+    TwoWeeklyTimesAndOffsetTest,
+    testing::Values(std::make_tuple(kTuesday,
+                                    10 * kMinutesInHour + 30,
+                                    13 * kMinutesInHour,
+                                    kTuesday,
+                                    23 * kMinutesInHour + 30),
+                    std::make_tuple(kSunday,
+                                    21 * kMinutesInHour + 30,
+                                    13 * kMinutesInHour,
+                                    kMonday,
+                                    10 * kMinutesInHour + 30)));
+
+INSTANTIATE_TEST_CASE_P(
+    DifferentOffsets,
+    TwoWeeklyTimesAndOffsetTest,
+    testing::Values(std::make_tuple(kWednesday,
+                                    10 * kMinutesInHour + 47,
+                                    5 * kMinutesInHour + 30,
+                                    kWednesday,
+                                    16 * kMinutesInHour + 17),
+                    std::make_tuple(kMonday,
+                                    10 * kMinutesInHour + 47,
+                                    6 * kMinutesInHour + 15,
+                                    kMonday,
+                                    17 * kMinutesInHour + 2),
+                    std::make_tuple(kThursday,
+                                    22 * kMinutesInHour + 24,
+                                    -7 * kMinutesInHour,
+                                    kThursday,
+                                    15 * kMinutesInHour + 24)));
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/policy/system_log_uploader.cc b/chrome/browser/chromeos/policy/system_log_uploader.cc
index 02d516b..a8fce4d 100644
--- a/chrome/browser/chromeos/policy/system_log_uploader.cc
+++ b/chrome/browser/chromeos/policy/system_log_uploader.cc
@@ -26,12 +26,15 @@
 #include "components/policy/core/browser/browser_policy_connector.h"
 #include "net/http/http_request_headers.h"
 
+namespace policy {
+
 namespace {
+
 // The maximum number of successive retries.
 const int kMaxNumRetries = 1;
 
 // String constant defining the url tail we upload system logs to.
-const char* kSystemLogUploadUrlTail = "/upload";
+constexpr char kSystemLogUploadUrlTail[] = "/upload";
 
 // The cutoff point (in bytes) after which log contents are ignored.
 const size_t kLogCutoffSize = 50 * 1024 * 1024;  // 50 MiB.
@@ -61,16 +64,15 @@
     data.erase(pos != std::string::npos ? pos + 1 : 0);
     data += "... [truncated]\n";
   }
-  return policy::SystemLogUploader::RemoveSensitiveData(anonymizer, data);
+  return SystemLogUploader::RemoveSensitiveData(anonymizer, data);
 }
 
 // Reads the system log files as binary files, anonymizes data, stores the files
 // as pairs (file name, data) and returns. Called on blocking thread.
-std::unique_ptr<policy::SystemLogUploader::SystemLogs> ReadFiles() {
-  std::unique_ptr<policy::SystemLogUploader::SystemLogs> system_logs(
-      new policy::SystemLogUploader::SystemLogs());
+std::unique_ptr<SystemLogUploader::SystemLogs> ReadFiles() {
+  auto system_logs = std::make_unique<SystemLogUploader::SystemLogs>();
   feedback::AnonymizerTool anonymizer;
-  for (auto* file_path : kSystemLogFileNames) {
+  for (const char* file_path : kSystemLogFileNames) {
     if (!base::PathExists(base::FilePath(file_path)))
       continue;
     system_logs->push_back(std::make_pair(
@@ -82,7 +84,7 @@
 
 // An implementation of the |SystemLogUploader::Delegate|, that is used to
 // create an upload job and load system logs from the disk.
-class SystemLogDelegate : public policy::SystemLogUploader::Delegate {
+class SystemLogDelegate : public SystemLogUploader::Delegate {
  public:
   explicit SystemLogDelegate(
       scoped_refptr<base::SequencedTaskRunner> task_runner);
@@ -91,9 +93,9 @@
   // SystemLogUploader::Delegate:
   void LoadSystemLogs(const LogUploadCallback& upload_callback) override;
 
-  std::unique_ptr<policy::UploadJob> CreateUploadJob(
+  std::unique_ptr<UploadJob> CreateUploadJob(
       const GURL& upload_url,
-      policy::UploadJob::Delegate* delegate) override;
+      UploadJob::Delegate* delegate) override;
 
  private:
   // TaskRunner used for scheduling upload the upload task.
@@ -117,9 +119,9 @@
       base::Bind(&ReadFiles), upload_callback);
 }
 
-std::unique_ptr<policy::UploadJob> SystemLogDelegate::CreateUploadJob(
+std::unique_ptr<UploadJob> SystemLogDelegate::CreateUploadJob(
     const GURL& upload_url,
-    policy::UploadJob::Delegate* delegate) {
+    UploadJob::Delegate* delegate) {
   chromeos::DeviceOAuth2TokenService* device_oauth2_token_service =
       chromeos::DeviceOAuth2TokenServiceFactory::Get();
 
@@ -129,17 +131,17 @@
       device_oauth2_token_service->GetRobotAccountId();
 
   SYSLOG(INFO) << "Creating upload job for system log";
-  return std::unique_ptr<policy::UploadJob>(new policy::UploadJobImpl(
+  return std::make_unique<UploadJobImpl>(
       upload_url, robot_account_id, device_oauth2_token_service,
       system_request_context, delegate,
-      base::WrapUnique(new policy::UploadJobImpl::RandomMimeBoundaryGenerator),
-      task_runner_));
+      std::make_unique<UploadJobImpl::RandomMimeBoundaryGenerator>(),
+      task_runner_);
 }
 
 // Returns the system log upload frequency.
 base::TimeDelta GetUploadFrequency() {
   base::TimeDelta upload_frequency(base::TimeDelta::FromMilliseconds(
-      policy::SystemLogUploader::kDefaultUploadDelayMs));
+      SystemLogUploader::kDefaultUploadDelayMs));
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kSystemLogUploadFrequency)) {
     std::string string_value =
@@ -154,14 +156,12 @@
 }
 
 std::string GetUploadUrl() {
-  return policy::BrowserPolicyConnector::GetDeviceManagementUrl() +
+  return BrowserPolicyConnector::GetDeviceManagementUrl() +
          kSystemLogUploadUrlTail;
 }
 
 }  // namespace
 
-namespace policy {
-
 // Determines the time between log uploads.
 const int64_t SystemLogUploader::kDefaultUploadDelayMs =
     12 * 60 * 60 * 1000;  // 12 hours
@@ -193,7 +193,7 @@
       upload_enabled_(false),
       weak_factory_(this) {
   if (!syslog_delegate_)
-    syslog_delegate_.reset(new SystemLogDelegate(task_runner));
+    syslog_delegate_ = std::make_unique<SystemLogDelegate>(task_runner);
   DCHECK(syslog_delegate_);
   SYSLOG(INFO) << "Creating system log uploader.";
 
@@ -250,7 +250,7 @@
 
 // static
 std::string SystemLogUploader::RemoveSensitiveData(
-    feedback::AnonymizerTool* const anonymizer,
+    feedback::AnonymizerTool* anonymizer,
     const std::string& data) {
   return anonymizer->Anonymize(data);
 }
@@ -264,18 +264,17 @@
   // If trusted values are not available, register this function to be called
   // back when they are available.
   chromeos::CrosSettings* settings = chromeos::CrosSettings::Get();
-  if (chromeos::CrosSettingsProvider::TRUSTED !=
-      settings->PrepareTrustedValues(
-          base::Bind(&SystemLogUploader::RefreshUploadSettings,
-                     weak_factory_.GetWeakPtr()))) {
+  auto trust_status = settings->PrepareTrustedValues(base::Bind(
+      &SystemLogUploader::RefreshUploadSettings, weak_factory_.GetWeakPtr()));
+  if (trust_status != chromeos::CrosSettingsProvider::TRUSTED)
     return;
-  }
 
   // CrosSettings are trusted - we want to use the last trusted values, by
   // default do not upload system logs.
   if (!settings->GetBoolean(chromeos::kSystemLogUploadEnabled,
-                            &upload_enabled_))
+                            &upload_enabled_)) {
     upload_enabled_ = false;
+  }
 }
 
 void SystemLogUploader::UploadSystemLogs(
diff --git a/chrome/browser/chromeos/policy/system_log_uploader.h b/chrome/browser/chromeos/policy/system_log_uploader.h
index bd20f14..608df1a 100644
--- a/chrome/browser/chromeos/policy/system_log_uploader.h
+++ b/chrome/browser/chromeos/policy/system_log_uploader.h
@@ -37,7 +37,12 @@
  public:
   // Structure that stores the system log files as pairs: (file name, loaded
   // from the disk binary file data).
-  typedef std::vector<std::pair<std::string, std::string>> SystemLogs;
+  using SystemLogs = std::vector<std::pair<std::string, std::string>>;
+
+  // Remove lines from |data| that contain common PII (IP addresses, BSSIDs,
+  // SSIDs, URLs, e-mail addresses).
+  static std::string RemoveSensitiveData(feedback::AnonymizerTool* anonymizer,
+                                         const std::string& data);
 
   // Refresh constants.
   static const int64_t kDefaultUploadDelayMs;
@@ -53,8 +58,8 @@
   // from the disk and create an upload job.
   class Delegate {
    public:
-    typedef base::Callback<void(std::unique_ptr<SystemLogs> system_logs)>
-        LogUploadCallback;
+    using LogUploadCallback =
+        base::Callback<void(std::unique_ptr<SystemLogs> system_logs)>;
 
     virtual ~Delegate() {}
 
@@ -70,7 +75,7 @@
 
   // Constructor. Callers can inject their own Delegate. A nullptr can be passed
   // for |syslog_delegate| to use the default implementation.
-  explicit SystemLogUploader(
+  SystemLogUploader(
       std::unique_ptr<Delegate> syslog_delegate,
       const scoped_refptr<base::SequencedTaskRunner>& task_runner);
 
@@ -80,20 +85,14 @@
   // ever happened.
   base::Time last_upload_attempt() const { return last_upload_attempt_; }
 
+  void ScheduleNextSystemLogUploadImmediately();
+
   // UploadJob::Delegate:
   // Callbacks handle success and failure results of upload, destroy the
   // upload job.
   void OnSuccess() override;
   void OnFailure(UploadJob::ErrorCode error_code) override;
 
-  // Remove lines from |data| that contain common PII (IP addresses, BSSIDs,
-  // SSIDs, URLs, e-mail addresses).
-  static std::string RemoveSensitiveData(
-      feedback::AnonymizerTool* const anonymizer,
-      const std::string& data);
-
-  void ScheduleNextSystemLogUploadImmediately();
-
  private:
   // Updates the system log upload enabled field from settings.
   void RefreshUploadSettings();
diff --git a/chrome/browser/chromeos/power/freezer_cgroup_process_manager.cc b/chrome/browser/chromeos/power/freezer_cgroup_process_manager.cc
index ab50c344..1c3f361 100644
--- a/chrome/browser/chromeos/power/freezer_cgroup_process_manager.cc
+++ b/chrome/browser/chromeos/power/freezer_cgroup_process_manager.cc
@@ -61,7 +61,14 @@
     if (!enabled_) {
       LOG(WARNING) << "Cgroup freezer does not exist or is not writable. "
                    << "Unable to freeze renderer processes.";
+      return;
     }
+
+    // Thaw renderers on startup. This helps robustness for the case where we
+    // start up with renderers in frozen state, for example after the previous
+    // Chrome process crashed at a point in time after suspend where it still
+    // hadn't thawed renderers yet.
+    ThawRenderers(base::Bind([](bool) {}));
   }
 
   void SetShouldFreezeRenderer(base::ProcessHandle handle, bool frozen) {
diff --git a/chrome/browser/chromeos/power/renderer_freezer.cc b/chrome/browser/chromeos/power/renderer_freezer.cc
index 187618c..53d8cef 100644
--- a/chrome/browser/chromeos/power/renderer_freezer.cc
+++ b/chrome/browser/chromeos/power/renderer_freezer.cc
@@ -19,6 +19,7 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
@@ -154,7 +155,7 @@
     content::WebContents* web_contents = locker->delegate()->GetWebContents();
     if (web_contents) {
       delegate_->SetShouldFreezeRenderer(
-          web_contents->GetRenderProcessHost()->GetHandle(), false);
+          web_contents->GetMainFrame()->GetProcess()->GetHandle(), false);
     }
   }
 }
diff --git a/chrome/browser/chromeos/printing/doc/cups_printer_management.md b/chrome/browser/chromeos/printing/doc/cups_printer_management.md
index 7a093ea..7344609 100644
--- a/chrome/browser/chromeos/printing/doc/cups_printer_management.md
+++ b/chrome/browser/chromeos/printing/doc/cups_printer_management.md
@@ -72,9 +72,9 @@
 It provides this information both via an Observer interface, for consumers that
 require live updates to changes in availability, and also via a simpler "Give me
 all the printers of this type" interface for simpler consumers that just need to
-know the state of the world at a given point in time.  `CupsPrinterManager` is
+know the state of the world at a given point in time.  `CupsPrintersManager` is
 also where the logic to determine whether a given detected printer is
-automatically configurable (and this belongs in the *Automatic* category) or not
+automatically configurable (and thus belongs in the *Automatic* category) or not
 (and thus belongs in the *Discovered* category).
 
 There are 4 primary consumers of `CupsPrintersManager` information:
@@ -83,7 +83,7 @@
   (`printing/backend/print_backend_chromeos.cc`).  This is the ChromeOS
   implementation of the backend print API used by Chrome.
 * The PrintPreview dialog proxy
-  (`chrome/browser/ui/webui/print_preview/printer_backend_proxy_chromeos.cc`).
+  (`chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc`).
   This is mostly a thread workaround to access the stuff in the print backend.
 * The ChromeOS printers settings
   page. (`chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc`
diff --git a/chrome/browser/chromeos/printing/printer_configurer.cc b/chrome/browser/chromeos/printing/printer_configurer.cc
index 41fbfbc..7f5a05a 100644
--- a/chrome/browser/chromeos/printing/printer_configurer.cc
+++ b/chrome/browser/chromeos/printing/printer_configurer.cc
@@ -19,6 +19,7 @@
 #include "base/memory/ref_counted.h"
 #include "chrome/browser/chromeos/printing/ppd_provider_factory.h"
 #include "chrome/browser/component_updater/cros_component_installer.h"
+#include "chrome/browser/local_discovery/endpoint_resolver.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_features.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
@@ -26,6 +27,8 @@
 #include "chromeos/printing/ppd_provider.h"
 #include "chromeos/printing/printer_configuration.h"
 #include "content/public/browser/browser_thread.h"
+#include "net/base/host_port_pair.h"
+#include "net/base/ip_endpoint.h"
 #include "third_party/cros_system_api/dbus/debugd/dbus-constants.h"
 
 const std::map<const std::string, const std::string>&
@@ -58,7 +61,9 @@
 class PrinterConfigurerImpl : public PrinterConfigurer {
  public:
   explicit PrinterConfigurerImpl(Profile* profile)
-      : ppd_provider_(CreatePpdProvider(profile)), weak_factory_(this) {}
+      : endpoint_resolver_(new local_discovery::EndpointResolver()),
+        ppd_provider_(CreatePpdProvider(profile)),
+        weak_factory_(this) {}
 
   PrinterConfigurerImpl(const PrinterConfigurerImpl&) = delete;
   PrinterConfigurerImpl& operator=(const PrinterConfigurerImpl&) = delete;
@@ -71,6 +76,25 @@
     DCHECK(!printer.id().empty());
     DCHECK(!printer.uri().empty());
 
+    if (!printer.RequiresIpResolution()) {
+      StartConfiguration(printer, callback);
+      return;
+    }
+
+    auto printer_copy = base::MakeUnique<Printer>(printer);
+    // Resolve the uri to an ip with a mutable copy of the printer.
+    endpoint_resolver_->Start(
+        printer.GetHostAndPort(),
+        base::Bind(&PrinterConfigurerImpl::OnIpResolved,
+                   weak_factory_.GetWeakPtr(), base::Passed(&printer_copy),
+                   callback));
+  }
+
+ private:
+  // Run installation for a printer with a resolved uri.  |callback| is called
+  // with the result of the setup when it is complete.
+  void StartConfiguration(const Printer& printer,
+                          const PrinterSetupCallback& callback) {
     if (!printer.IsIppEverywhere()) {
       ppd_provider_->ResolvePpd(
           printer.ppd_reference(),
@@ -88,7 +112,25 @@
                    weak_factory_.GetWeakPtr(), callback));
   }
 
- private:
+  // Callback for when the IP for a zeroconf printer has been resolved.  If the
+  // request was successful, sets the |effective_uri| on |printer| with
+  // |endpoint| then continues setup. |cb| is called with a result reporting the
+  // success or failure of the setup operation, eventually.
+  void OnIpResolved(std::unique_ptr<Printer> printer,
+                    const PrinterSetupCallback& cb,
+                    const net::IPEndPoint& endpoint) {
+    if (!endpoint.address().IsValid()) {
+      // |endpoint| does not have a valid address. Address was not resolved.
+      cb.Run(kPrinterUnreachable);
+      return;
+    }
+
+    std::string effective_uri = printer->ReplaceHostAndPort(endpoint);
+    printer->set_effective_uri(effective_uri);
+
+    StartConfiguration(*printer, cb);
+  }
+
   void OnAddedPrinter(const Printer& printer,
                       const PrinterSetupCallback& cb,
                       int32_t result_code) {
@@ -219,6 +261,7 @@
     }
   }
 
+  std::unique_ptr<local_discovery::EndpointResolver> endpoint_resolver_;
   scoped_refptr<PpdProvider> ppd_provider_;
   base::WeakPtrFactory<PrinterConfigurerImpl> weak_factory_;
 };
diff --git a/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc b/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc
index 27615fb..8ee92ad 100644
--- a/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc
+++ b/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc
@@ -65,9 +65,6 @@
   client->GetWiMaxStatus(base::Bind(&DebugDaemonLogSource::OnGetWiMaxStatus,
                                     weak_ptr_factory_.GetWeakPtr()));
   ++num_pending_requests_;
-  client->GetUserLogFiles(base::Bind(&DebugDaemonLogSource::OnGetUserLogFiles,
-                                     weak_ptr_factory_.GetWeakPtr()));
-  ++num_pending_requests_;
 
   if (scrub_) {
     client->GetScrubbedBigLogs(base::Bind(&DebugDaemonLogSource::OnGetLogs,
@@ -155,11 +152,11 @@
         FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
         base::Bind(&DebugDaemonLogSource::ReadUserLogFiles, user_log_files,
                    profile_dirs, response),
-        base::Bind(&DebugDaemonLogSource::MergeResponse,
+        base::Bind(&DebugDaemonLogSource::MergeUserLogFilesResponse,
                    weak_ptr_factory_.GetWeakPtr(), base::Owned(response)));
   } else {
     (*response_)[kUserLogFileKeyName] = kNotAvailable;
-    RequestCompleted();
+    callback_.Run(response_.get());
   }
 }
 
@@ -187,11 +184,12 @@
   }
 }
 
-void DebugDaemonLogSource::MergeResponse(SystemLogsResponse* response) {
+void DebugDaemonLogSource::MergeUserLogFilesResponse(
+    SystemLogsResponse* response) {
   for (SystemLogsResponse::const_iterator it = response->begin();
        it != response->end(); ++it)
     response_->insert(*it);
-  RequestCompleted();
+  callback_.Run(response_.get());
 }
 
 void DebugDaemonLogSource::RequestCompleted() {
@@ -201,7 +199,12 @@
   --num_pending_requests_;
   if (num_pending_requests_ > 0)
     return;
-  callback_.Run(response_.get());
+  // When all other logs are collected, fetch the user logs, because any errors
+  // fetching the other logs is reported in the user logs.
+  chromeos::DebugDaemonClient* client =
+      chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
+  client->GetUserLogFiles(base::Bind(&DebugDaemonLogSource::OnGetUserLogFiles,
+                                     weak_ptr_factory_.GetWeakPtr()));
 }
 
 }  // namespace system_logs
diff --git a/chrome/browser/chromeos/system_logs/debug_daemon_log_source.h b/chrome/browser/chromeos/system_logs/debug_daemon_log_source.h
index 3b537ef..73208189 100644
--- a/chrome/browser/chromeos/system_logs/debug_daemon_log_source.h
+++ b/chrome/browser/chromeos/system_logs/debug_daemon_log_source.h
@@ -49,10 +49,13 @@
       SystemLogsResponse* response);
 
   // Merge the responses from ReadUserLogFiles into the main response dict and
-  // call RequestComplete to indicate that the user log files read is complete.
-  void MergeResponse(SystemLogsResponse* response);
+  // invoke the callback_.Run method with the assumption that all other logs
+  // have already been collected.
+  void MergeUserLogFilesResponse(SystemLogsResponse* response);
 
-  // Sends the data to the callback_ when all the requests are completed
+  // When all the requests are completed, send one last request to collect the
+  // user logs and complete the collection by invoking the callback's Run
+  // method.
   void RequestCompleted();
 
   std::unique_ptr<SystemLogsResponse> response_;
diff --git a/chrome/browser/chromeos/system_logs/single_log_file_log_source.cc b/chrome/browser/chromeos/system_logs/single_log_file_log_source.cc
index 192373a..f0d85dd 100644
--- a/chrome/browser/chromeos/system_logs/single_log_file_log_source.cc
+++ b/chrome/browser/chromeos/system_logs/single_log_file_log_source.cc
@@ -35,28 +35,28 @@
 // Converts a logs source type to the corresponding file path, relative to the
 // base system log directory path. In the future, if non-file source types are
 // added, this function should return an empty file path.
-base::FilePath GetLogFileSourceRelativeFilePath(
+base::FilePath::StringType GetLogFileSourceRelativeFilePathValue(
     SingleLogFileLogSource::SupportedSource source) {
   switch (source) {
     case SupportedSource::kMessages:
-      return base::FilePath("messages");
+      return "messages";
     case SupportedSource::kUiLatest:
-      return base::FilePath("ui/ui.LATEST");
+      return "ui/ui.LATEST";
     case SupportedSource::kAtrusLog:
-      return base::FilePath("atrus.log");
+      return "atrus.log";
     case SupportedSource::kNetLog:
-      return base::FilePath("net.log");
+      return "net.log";
     case SupportedSource::kEventLog:
-      return base::FilePath("eventlog.txt");
+      return "eventlog.txt";
     case SupportedSource::kUpdateEngineLog:
-      return base::FilePath("update_engine.log");
+      return "update_engine.log";
     case SupportedSource::kPowerdLatest:
-      return base::FilePath("power_manager/powerd.LATEST");
+      return "power_manager/powerd.LATEST";
     case SupportedSource::kPowerdPrevious:
-      return base::FilePath("power_manager/powerd.PREVIOUS");
+      return "power_manager/powerd.PREVIOUS";
   }
   NOTREACHED();
-  return base::FilePath();
+  return base::FilePath::StringType();
 }
 
 // Returns the inode value of file at |path|, or 0 if it doesn't exist or is
@@ -168,7 +168,7 @@
 }  // namespace
 
 SingleLogFileLogSource::SingleLogFileLogSource(SupportedSource source_type)
-    : SystemLogsSource(GetLogFileSourceRelativeFilePath(source_type).value()),
+    : SystemLogsSource(GetLogFileSourceRelativeFilePathValue(source_type)),
       source_type_(source_type),
       log_file_dir_path_(kDefaultSystemLogDirPath),
       num_bytes_read_(0),
@@ -187,18 +187,19 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(!callback.is_null());
 
-  SystemLogsResponse* response = new SystemLogsResponse;
+  auto response = std::make_unique<SystemLogsResponse>();
+  auto* response_ptr = response.get();
   base::PostTaskWithTraitsAndReply(
       FROM_HERE,
       base::TaskTraits(base::MayBlock(), base::TaskPriority::BACKGROUND),
       base::Bind(&SingleLogFileLogSource::ReadFile,
                  weak_ptr_factory_.GetWeakPtr(),
-                 kMaxNumAllowedLogRotationsDuringFileRead, response),
-      base::Bind(callback, base::Owned(response)));
+                 kMaxNumAllowedLogRotationsDuringFileRead, response_ptr),
+      base::Bind(callback, base::Owned(response.release())));
 }
 
 base::FilePath SingleLogFileLogSource::GetLogFilePath() const {
-  return base::FilePath(log_file_dir_path_).Append(source_name());
+  return log_file_dir_path_.Append(source_name());
 }
 
 void SingleLogFileLogSource::ReadFile(size_t num_rotations_allowed,
diff --git a/chrome/browser/chromeos/ui/echo_dialog_view.cc b/chrome/browser/chromeos/ui/echo_dialog_view.cc
index ecfd936..a8670973 100644
--- a/chrome/browser/chromeos/ui/echo_dialog_view.cc
+++ b/chrome/browser/chromeos/ui/echo_dialog_view.cc
@@ -57,17 +57,15 @@
   label_ = new views::StyledLabel(text, this);
 
   views::StyledLabel::RangeStyleInfo service_name_style;
-  service_name_style.font_style = gfx::Font::UNDERLINE;
+  service_name_style.custom_font =
+      label_->GetDefaultFontList().DeriveWithStyle(gfx::Font::UNDERLINE);
   service_name_style.tooltip = origin;
   label_->AddStyleRange(
       gfx::Range(offsets[0], offsets[0] + service_name.length()),
       service_name_style);
 
-  views::StyledLabel::RangeStyleInfo link_style =
-      views::StyledLabel::RangeStyleInfo::CreateForLink();
-  link_style.font_style = gfx::Font::NORMAL;
   label_->AddStyleRange(gfx::Range(offsets[1], offsets[1] + link.length()),
-                        link_style);
+                        views::StyledLabel::RangeStyleInfo::CreateForLink());
 
   SetLabelBorderAndBounds();
 
@@ -86,11 +84,8 @@
       IDS_ECHO_DISABLED_CONSENT_DIALOG_TEXT, link, &offset);
 
   label_ = new views::StyledLabel(text, this);
-
-  views::StyledLabel::RangeStyleInfo link_style =
-      views::StyledLabel::RangeStyleInfo::CreateForLink();
-  link_style.font_style = gfx::Font::NORMAL;
-  label_->AddStyleRange(gfx::Range(offset, offset + link.length()), link_style);
+  label_->AddStyleRange(gfx::Range(offset, offset + link.length()),
+                        views::StyledLabel::RangeStyleInfo::CreateForLink());
 
   SetLabelBorderAndBounds();
 
diff --git a/chrome/browser/crash_recovery_browsertest.cc b/chrome/browser/crash_recovery_browsertest.cc
index cdad735..96fa5295 100644
--- a/chrome/browser/crash_recovery_browsertest.cc
+++ b/chrome/browser/crash_recovery_browsertest.cc
@@ -110,8 +110,10 @@
                                                 &title_after_crash));
   EXPECT_NE(title_before_crash, title_after_crash);
   ASSERT_TRUE(GetActiveWebContents()->GetMainFrame()->GetView()->IsShowing());
-  ASSERT_FALSE(
-      GetActiveWebContents()->GetRenderProcessHost()->IsProcessBackgrounded());
+  ASSERT_FALSE(GetActiveWebContents()
+                   ->GetMainFrame()
+                   ->GetProcess()
+                   ->IsProcessBackgrounded());
 }
 
 // Test that reload after a crash forces a cache revalidation.
diff --git a/chrome/browser/data_use_measurement/chrome_data_use_ascriber_service.cc b/chrome/browser/data_use_measurement/chrome_data_use_ascriber_service.cc
index c0a6776..ede8d89 100644
--- a/chrome/browser/data_use_measurement/chrome_data_use_ascriber_service.cc
+++ b/chrome/browser/data_use_measurement/chrome_data_use_ascriber_service.cc
@@ -136,7 +136,7 @@
       content::BrowserThread::IO, FROM_HERE,
       base::BindOnce(&ChromeDataUseAscriber::DidStartMainFrameNavigation,
                      base::Unretained(ascriber_), navigation_handle->GetURL(),
-                     web_contents->GetRenderProcessHost()->GetID(),
+                     web_contents->GetMainFrame()->GetProcess()->GetID(),
                      web_contents->GetMainFrame()->GetRoutingID(),
                      navigation_handle));
 }
@@ -157,7 +157,7 @@
       base::BindOnce(&ChromeDataUseAscriber::ReadyToCommitMainFrameNavigation,
                      base::Unretained(ascriber_),
                      navigation_handle->GetGlobalRequestID(),
-                     web_contents->GetRenderProcessHost()->GetID(),
+                     web_contents->GetMainFrame()->GetProcess()->GetID(),
                      web_contents->GetMainFrame()->GetRoutingID()));
 }
 
@@ -177,7 +177,7 @@
       base::BindOnce(
           &ChromeDataUseAscriber::DidFinishMainFrameNavigation,
           base::Unretained(ascriber_),
-          web_contents->GetRenderProcessHost()->GetID(),
+          web_contents->GetMainFrame()->GetProcess()->GetID(),
           web_contents->GetMainFrame()->GetRoutingID(),
           navigation_handle->GetURL(), navigation_handle->IsSameDocument(),
           navigation_handle->GetPageTransition(), base::TimeTicks::Now()));
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc
index ba046b0..72b7064 100644
--- a/chrome/browser/devtools/devtools_sanity_browsertest.cc
+++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -136,6 +136,7 @@
     "files/devtools/emulate_network_conditions.html";
 const char kDispatchKeyEventShowsAutoFill[] =
     "files/devtools/dispatch_key_event_shows_auto_fill.html";
+const char kDOMWarningsTestPage[] = "files/devtools/dom_warnings_page.html";
 
 template <typename... T>
 void DispatchOnTestSuiteSkipCheck(DevToolsWindow* window,
@@ -1683,6 +1684,10 @@
   CloseDevToolsWindow();
 }
 
+IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestDOMWarnings) {
+  RunTest("testDOMWarnings", kDOMWarningsTestPage);
+}
+
 // Tests that console messages are not duplicated on navigation back.
 #if defined(OS_WIN)
 // Flaking on windows swarm try runs: crbug.com/409285.
diff --git a/chrome/browser/download/download_service_factory.cc b/chrome/browser/download/download_service_factory.cc
index c37af5b..fa1ab9f2 100644
--- a/chrome/browser/download/download_service_factory.cc
+++ b/chrome/browser/download/download_service_factory.cc
@@ -4,12 +4,16 @@
 
 #include "chrome/browser/download/download_service_factory.h"
 
+#include <memory>
+#include <utility>
+
 #include "base/files/file_path.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/singleton.h"
 #include "base/sequenced_task_runner.h"
 #include "base/task_scheduler/post_task.h"
 #include "base/task_scheduler/task_traits.h"
+#include "chrome/browser/background_fetch/background_fetch_download_client.h"
 #include "chrome/browser/download/download_task_scheduler_impl.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
@@ -59,6 +63,10 @@
       base::MakeUnique<offline_pages::OfflinePrefetchDownloadClient>(context)));
 #endif  // BUILDFLAG(ENABLE_OFFLINE_PAGES)
 
+  clients->insert(
+      std::make_pair(download::DownloadClient::BACKGROUND_FETCH,
+                     base::MakeUnique<BackgroundFetchDownloadClient>(context)));
+
   auto* download_manager = content::BrowserContext::GetDownloadManager(context);
 
   base::FilePath storage_dir;
diff --git a/chrome/browser/download/download_service_factory.h b/chrome/browser/download/download_service_factory.h
index ef49d79..2c93700 100644
--- a/chrome/browser/download/download_service_factory.h
+++ b/chrome/browser/download/download_service_factory.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_SERVICE_FACTORY_H_
 
 #include "base/macros.h"
+#include "chrome/browser/download/download_service_factory.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 
 namespace base {
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn
index 3db2fd35..62d4aad 100644
--- a/chrome/browser/extensions/BUILD.gn
+++ b/chrome/browser/extensions/BUILD.gn
@@ -5,6 +5,7 @@
 import("//build/config/features.gni")
 import("//build/config/ui.gni")
 import("//chrome/common/features.gni")
+import("//components/nacl/features.gni")
 import("//extensions/features/features.gni")
 import("//media/media_options.gni")
 import("//mojo/public/tools/bindings/mojom.gni")
diff --git a/chrome/browser/extensions/active_tab_permission_granter.cc b/chrome/browser/extensions/active_tab_permission_granter.cc
index 593628c..4fcaae71 100644
--- a/chrome/browser/extensions/active_tab_permission_granter.cc
+++ b/chrome/browser/extensions/active_tab_permission_granter.cc
@@ -4,6 +4,9 @@
 
 #include "chrome/browser/extensions/active_tab_permission_granter.h"
 
+#include <set>
+#include <vector>
+
 #include "chrome/browser/extensions/extension_action_runner.h"
 #include "chrome/browser/profiles/profile.h"
 #include "content/public/browser/navigation_entry.h"
@@ -136,10 +139,9 @@
                      new_hosts,
                      tab_id_);
       SendMessageToProcesses(
-          ProcessManager::Get(web_contents()->GetBrowserContext())->
-              GetRenderFrameHostsForExtension(extension->id()),
-          web_contents()->GetRenderProcessHost(),
-          update_message);
+          ProcessManager::Get(web_contents()->GetBrowserContext())
+              ->GetRenderFrameHostsForExtension(extension->id()),
+          web_contents()->GetMainFrame()->GetProcess(), update_message);
 
       // If more things ever need to know about this, we should consider making
       // an observer class.
@@ -218,9 +220,8 @@
 
   CreateMessageFunction clear_message =
       base::Bind(&CreateClearMessage, extension_ids, tab_id_);
-  SendMessageToProcesses(frame_hosts,
-                         web_contents()->GetRenderProcessHost(),
-                         clear_message);
+  SendMessageToProcesses(
+      frame_hosts, web_contents()->GetMainFrame()->GetProcess(), clear_message);
 
   granted_extensions_.Clear();
 }
diff --git a/chrome/browser/extensions/api/chrome_extensions_api_client.cc b/chrome/browser/extensions/api/chrome_extensions_api_client.cc
index 58646f7..7354bf8 100644
--- a/chrome/browser/extensions/api/chrome_extensions_api_client.cc
+++ b/chrome/browser/extensions/api/chrome_extensions_api_client.cc
@@ -160,9 +160,10 @@
 }
 
 std::unique_ptr<VirtualKeyboardDelegate>
-ChromeExtensionsAPIClient::CreateVirtualKeyboardDelegate() const {
+ChromeExtensionsAPIClient::CreateVirtualKeyboardDelegate(
+    content::BrowserContext* browser_context) const {
 #if defined(OS_CHROMEOS)
-  return base::MakeUnique<ChromeVirtualKeyboardDelegate>();
+  return base::MakeUnique<ChromeVirtualKeyboardDelegate>(browser_context);
 #else
   return nullptr;
 #endif
diff --git a/chrome/browser/extensions/api/chrome_extensions_api_client.h b/chrome/browser/extensions/api/chrome_extensions_api_client.h
index eb300332..7c5e18d 100644
--- a/chrome/browser/extensions/api/chrome_extensions_api_client.h
+++ b/chrome/browser/extensions/api/chrome_extensions_api_client.h
@@ -52,8 +52,8 @@
       RulesCacheDelegate* cache_delegate) const override;
   std::unique_ptr<DevicePermissionsPrompt> CreateDevicePermissionsPrompt(
       content::WebContents* web_contents) const override;
-  std::unique_ptr<VirtualKeyboardDelegate> CreateVirtualKeyboardDelegate()
-      const override;
+  std::unique_ptr<VirtualKeyboardDelegate> CreateVirtualKeyboardDelegate(
+      content::BrowserContext* browser_context) const override;
   ManagementAPIDelegate* CreateManagementAPIDelegate() const override;
   MetricsPrivateDelegate* GetMetricsPrivateDelegate() override;
   NetworkingCastPrivateDelegate* GetNetworkingCastPrivateDelegate() override;
diff --git a/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc b/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc
index 0bfff943..d5aecb7 100644
--- a/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc
+++ b/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc
@@ -67,15 +67,15 @@
 
     for (auto& source_list : source_lists) {
       switch (source_list->GetMediaListType()) {
-        case DesktopMediaID::SOURCE_NONE:
+        case DesktopMediaID::TYPE_NONE:
           break;
-        case DesktopMediaID::SOURCE_SCREEN:
+        case DesktopMediaID::TYPE_SCREEN:
           show_screens = true;
           break;
-        case DesktopMediaID::SOURCE_WINDOW:
+        case DesktopMediaID::TYPE_WINDOW:
           show_windows = true;
           break;
-        case DesktopMediaID::SOURCE_WEB_CONTENTS:
+        case DesktopMediaID::TYPE_WEB_CONTENTS:
           show_tabs = true;
           break;
       }
@@ -132,7 +132,7 @@
   }
 
   std::unique_ptr<DesktopMediaList> CreateMediaList(
-      DesktopMediaID::Source type) override {
+      DesktopMediaID::Type type) override {
     EXPECT_LE(current_test_, tests_count_);
     return std::unique_ptr<DesktopMediaList>(new FakeDesktopMediaList(type));
   }
@@ -190,7 +190,7 @@
       {true, true, false, false, content::DesktopMediaID()},
       // chooseMedia()
       {true, true, false, false,
-       content::DesktopMediaID(content::DesktopMediaID::SOURCE_SCREEN,
+       content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
                                content::DesktopMediaID::kNullId)},
       // screensOnly()
       {true, false, false, false, content::DesktopMediaID()},
@@ -200,21 +200,19 @@
       {false, false, true, false, content::DesktopMediaID()},
       // audioShareNoApproval()
       {true, true, true, true,
-       content::DesktopMediaID(content::DesktopMediaID::SOURCE_WEB_CONTENTS,
-                               123, content::DesktopMediaID::CAPTURE_VIDEO)},
+       content::DesktopMediaID(content::DesktopMediaID::TYPE_WEB_CONTENTS, 123,
+                               false)},
       // audioShareApproval()
       {true, true, true, true,
-       content::DesktopMediaID(content::DesktopMediaID::SOURCE_WEB_CONTENTS,
-                               123,
-                               content::DesktopMediaID::CAPTURE_VIDEO |
-                                   content::DesktopMediaID::CAPTURE_AUDIO)},
+       content::DesktopMediaID(content::DesktopMediaID::TYPE_WEB_CONTENTS, 123,
+                               true)},
       // chooseMediaAndGetStream()
       {true, true, false, false,
-       content::DesktopMediaID(content::DesktopMediaID::SOURCE_SCREEN,
+       content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
                                webrtc::kFullDesktopScreenId)},
       // chooseMediaAndTryGetStreamWithInvalidId()
       {true, true, false, false,
-       content::DesktopMediaID(content::DesktopMediaID::SOURCE_SCREEN,
+       content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
                                webrtc::kFullDesktopScreenId)},
       // cancelDialog()
       {true, true, false, false, content::DesktopMediaID(), true},
@@ -225,29 +223,24 @@
 
       // tabShareWithAudioGetStream()
       //{false, false, true, true,
-      // content::DesktopMediaID(content::DesktopMediaID::SOURCE_WEB_CONTENTS,
-      // 0,
+      // content::DesktopMediaID(content::DesktopMediaID::TYPE_WEB_CONTENTS, 0,
       //                         true)},
       // windowShareWithAudioGetStream()
       //{false, true, false, true,
-      // content::DesktopMediaID(content::DesktopMediaID::SOURCE_WINDOW, 0,
-      // true)},
+      //content::DesktopMediaID(content::DesktopMediaID::TYPE_WINDOW, 0, true)},
       // screenShareWithAudioGetStream()
       {true, false, false, true,
-       content::DesktopMediaID(content::DesktopMediaID::SOURCE_SCREEN,
-                               webrtc::kFullDesktopScreenId,
-                               content::DesktopMediaID::CAPTURE_VIDEO |
-                                   content::DesktopMediaID::CAPTURE_AUDIO)},
+       content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
+                               webrtc::kFullDesktopScreenId, true)},
       // tabShareWithoutAudioGetStream()
       //{false, false, true, true,
-      // content::DesktopMediaID(content::DesktopMediaID::SOURCE_WEB_CONTENTS,
-      // 0)},
+      //content::DesktopMediaID(content::DesktopMediaID::TYPE_WEB_CONTENTS, 0)},
       // windowShareWithoutAudioGetStream()
       //{false, true, false, true,
-      // content::DesktopMediaID(content::DesktopMediaID::SOURCE_WINDOW, 0)},
+      // content::DesktopMediaID(content::DesktopMediaID::TYPE_WINDOW, 0)},
       // screenShareWithoutAudioGetStream()
       {true, false, false, true,
-       content::DesktopMediaID(content::DesktopMediaID::SOURCE_SCREEN,
+       content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
                                webrtc::kFullDesktopScreenId)},
   };
   picker_factory_.SetTestFlags(test_flags, arraysize(test_flags));
@@ -275,13 +268,13 @@
 
   TestFlags test_flags[] = {
       {true, true, false, false,
-       content::DesktopMediaID(content::DesktopMediaID::SOURCE_SCREEN,
+       content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
                                content::DesktopMediaID::kNullId)},
       {true, true, false, false,
-       content::DesktopMediaID(content::DesktopMediaID::SOURCE_SCREEN,
+       content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
                                content::DesktopMediaID::kNullId)},
       {true, true, false, false,
-       content::DesktopMediaID(content::DesktopMediaID::SOURCE_SCREEN,
+       content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
                                content::DesktopMediaID::kNullId),
        true},
   };
diff --git a/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc b/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc
index 0d3f8c97..93df4fd4 100644
--- a/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc
+++ b/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc
@@ -114,14 +114,14 @@
         std::unique_ptr<DesktopMediaList> screen_list;
         if (g_picker_factory) {
           screen_list =
-              g_picker_factory->CreateMediaList(DesktopMediaID::SOURCE_SCREEN);
+              g_picker_factory->CreateMediaList(DesktopMediaID::TYPE_SCREEN);
         } else {
 #if defined(USE_ASH)
           screen_list = base::MakeUnique<DesktopMediaListAsh>(
-              DesktopMediaID::SOURCE_SCREEN);
+              DesktopMediaID::TYPE_SCREEN);
 #else   // !defined(USE_ASH)
           screen_list = base::MakeUnique<NativeDesktopMediaList>(
-              content::DesktopMediaID::SOURCE_SCREEN,
+              content::DesktopMediaID::TYPE_SCREEN,
               webrtc::DesktopCapturer::CreateScreenCapturer(
                   content::CreateDesktopCaptureOptions()));
 #endif  // !defined(USE_ASH)
@@ -137,11 +137,11 @@
         std::unique_ptr<DesktopMediaList> window_list;
         if (g_picker_factory) {
           window_list =
-              g_picker_factory->CreateMediaList(DesktopMediaID::SOURCE_WINDOW);
+              g_picker_factory->CreateMediaList(DesktopMediaID::TYPE_WINDOW);
         } else {
 #if defined(USE_ASH)
           window_list = base::MakeUnique<DesktopMediaListAsh>(
-              DesktopMediaID::SOURCE_WINDOW);
+              DesktopMediaID::TYPE_WINDOW);
 #else   // !defined(USE_ASH)
           // NativeDesktopMediaList calls the capturers on a background thread.
           // This means that the two DesktopCapturer instances (for screens and
@@ -149,7 +149,7 @@
           // instance. DesktopCaptureOptions owns X connection, which cannot be
           // used on multiple threads concurrently.
           window_list = base::MakeUnique<NativeDesktopMediaList>(
-              content::DesktopMediaID::SOURCE_WINDOW,
+              content::DesktopMediaID::TYPE_WINDOW,
               webrtc::DesktopCapturer::CreateWindowCapturer(
                   content::CreateDesktopCaptureOptions()));
 #endif  // !defined(USE_ASH)
@@ -167,7 +167,7 @@
         std::unique_ptr<DesktopMediaList> tab_list;
         if (g_picker_factory) {
           tab_list = g_picker_factory->CreateMediaList(
-              DesktopMediaID::SOURCE_WEB_CONTENTS);
+              DesktopMediaID::TYPE_WEB_CONTENTS);
         } else {
           tab_list = base::MakeUnique<TabDesktopMediaList>();
         }
@@ -232,7 +232,7 @@
 void DesktopCaptureChooseDesktopMediaFunctionBase::OnPickerDialogResults(
     DesktopMediaID source) {
   std::string result;
-  if (source.source_type != DesktopMediaID::SOURCE_NONE && web_contents()) {
+  if (source.type != DesktopMediaID::TYPE_NONE && web_contents()) {
     DesktopStreamsRegistry* registry =
         MediaCaptureDevicesDispatcher::GetInstance()->
         GetDesktopStreamsRegistry();
@@ -250,7 +250,7 @@
   }
 
   api::desktop_capture::ChooseDesktopMedia::Results::Options options;
-  options.can_request_audio_track = source.is_audio_capture();
+  options.can_request_audio_track = source.audio_share;
   results_ = api::desktop_capture::ChooseDesktopMedia::Results::Create(result,
                                                                        options);
   SendResponse(true);
diff --git a/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.h b/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.h
index c626d0d..a5643287 100644
--- a/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.h
+++ b/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.h
@@ -30,7 +30,7 @@
    public:
     virtual std::unique_ptr<DesktopMediaPicker> CreatePicker() = 0;
     virtual std::unique_ptr<DesktopMediaList> CreateMediaList(
-        content::DesktopMediaID::Source type) = 0;
+        content::DesktopMediaID::Type type) = 0;
 
    protected:
     PickerFactory() = default;
diff --git a/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc b/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc
index d0b197c..73578c6 100644
--- a/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc
+++ b/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/extensions/api/developer_private/inspectable_views_finder.h"
 
+#include <set>
+
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/extensions/api/developer_private.h"
 #include "content/public/browser/render_frame_host.h"
@@ -193,10 +195,10 @@
     if (url.is_empty())
       url = window->initial_url();
 
-    content::RenderProcessHost* process = web_contents->GetRenderProcessHost();
-    result->push_back(ConstructView(
-        url, process->GetID(), web_contents->GetMainFrame()->GetRoutingID(),
-        false, false, GetViewType(web_contents)));
+    content::RenderFrameHost* main_frame = web_contents->GetMainFrame();
+    result->push_back(ConstructView(url, main_frame->GetProcess()->GetID(),
+                                    main_frame->GetRoutingID(), false, false,
+                                    GetViewType(web_contents)));
   }
 }
 
diff --git a/chrome/browser/extensions/api/dial/dial_api.cc b/chrome/browser/extensions/api/dial/dial_api.cc
index 8cb70bf..1dd4d588 100644
--- a/chrome/browser/extensions/api/dial/dial_api.cc
+++ b/chrome/browser/extensions/api/dial/dial_api.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/time/time.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/api/dial/dial_api_factory.h"
 #include "chrome/browser/media/router/discovery/dial/device_description_fetcher.h"
 #include "chrome/browser/media/router/discovery/dial/dial_registry.h"
@@ -19,6 +20,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_system.h"
+#include "net/url_request/url_request_context.h"
 #include "url/gurl.h"
 
 using base::TimeDelta;
@@ -34,6 +36,7 @@
     : RefcountedKeyedService(
           BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)),
       profile_(profile),
+      system_request_context_(g_browser_process->system_request_context()),
       dial_registry_(nullptr),
       num_on_device_list_listeners_(0) {
   EventRouter::Get(profile)->RegisterObserver(
@@ -53,6 +56,8 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!dial_registry_) {
     dial_registry_ = media_router::DialRegistry::GetInstance();
+    dial_registry_->SetNetLog(
+        system_request_context_->GetURLRequestContext()->net_log());
     dial_registry_->RegisterObserver(this);
     if (test_device_data_) {
       dial_registry_->AddDeviceForTest(*test_device_data_);
diff --git a/chrome/browser/extensions/api/dial/dial_api.h b/chrome/browser/extensions/api/dial/dial_api.h
index ee842663..e81ec17 100644
--- a/chrome/browser/extensions/api/dial/dial_api.h
+++ b/chrome/browser/extensions/api/dial/dial_api.h
@@ -8,12 +8,14 @@
 #include <memory>
 
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "chrome/browser/media/router/discovery/dial/dial_device_data.h"
 #include "chrome/browser/media/router/discovery/dial/dial_registry.h"
 #include "chrome/common/extensions/api/dial.h"
 #include "components/keyed_service/core/refcounted_keyed_service.h"
 #include "extensions/browser/api/async_api_function.h"
 #include "extensions/browser/event_router.h"
+#include "net/url_request/url_request_context_getter.h"
 
 namespace media_router {
 class DeviceDescriptionFetcher;
@@ -92,6 +94,11 @@
 
   Profile* profile_;
 
+  // Used to get its NetLog on the IOThread. It uses the same NetLog as the
+  // Profile, but the Profile's URLRequestContextGetter isn't ready when DialAPI
+  // is created.
+  scoped_refptr<net::URLRequestContextGetter> system_request_context_;
+
   // Created lazily on first access on the IO thread. Does not take ownership of
   // |dial_registry_|.
   media_router::DialRegistry* dial_registry_;
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
index f9614b2..b4d3fb3 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -44,6 +44,7 @@
 #include "content/public/browser/download_item.h"
 #include "content/public/browser/download_manager.h"
 #include "content/public/browser/notification_service.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_features.h"
@@ -279,16 +280,13 @@
         ui::PAGE_TRANSITION_LINK);
     EventRouter::Get(current_browser()->profile())
         ->AddEventListener(downloads::OnCreated::kEventName,
-                           tab->GetRenderProcessHost(),
-                           GetExtensionId());
+                           tab->GetMainFrame()->GetProcess(), GetExtensionId());
     EventRouter::Get(current_browser()->profile())
         ->AddEventListener(downloads::OnChanged::kEventName,
-                           tab->GetRenderProcessHost(),
-                           GetExtensionId());
+                           tab->GetMainFrame()->GetProcess(), GetExtensionId());
     EventRouter::Get(current_browser()->profile())
         ->AddEventListener(downloads::OnErased::kEventName,
-                           tab->GetRenderProcessHost(),
-                           GetExtensionId());
+                           tab->GetMainFrame()->GetProcess(), GetExtensionId());
   }
 
   content::RenderProcessHost* AddFilenameDeterminer() {
@@ -300,9 +298,8 @@
         ui::PAGE_TRANSITION_LINK);
     EventRouter::Get(current_browser()->profile())
         ->AddEventListener(downloads::OnDeterminingFilename::kEventName,
-                           tab->GetRenderProcessHost(),
-                           GetExtensionId());
-    return tab->GetRenderProcessHost();
+                           tab->GetMainFrame()->GetProcess(), GetExtensionId());
+    return tab->GetMainFrame()->GetProcess();
   }
 
   void RemoveFilenameDeterminer(content::RenderProcessHost* host) {
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api.cc b/chrome/browser/extensions/api/input_ime/input_ime_api.cc
index cbc8907..a18d7b4 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api.cc
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api.cc
@@ -27,6 +27,12 @@
 namespace {
 const char kErrorEngineNotAvailable[] = "Engine is not available";
 const char kErrorSetKeyEventsFail[] = "Could not send key events";
+
+bool IsKeyboardRestricted() {
+  const keyboard::KeyboardConfig config = keyboard::GetKeyboardConfig();
+  return !(config.spell_check && config.auto_complete && config.auto_correct &&
+           config.voice_input && config.handwriting);
+}
 }
 namespace ui {
 
@@ -202,7 +208,9 @@
   // This is a hack, but tricking the virtual keyboard to think the
   // current input context is password will disable all keyboard features
   // that are not supported in restricted keyboard mode.
-  if (keyboard::GetKeyboardRestricted() &&
+  // TODO(oka): Remove this hack once VK extension starts to honor the
+  // virtualKeyboardPrivate.GetKeyboardConfig parameters.
+  if (IsKeyboardRestricted() &&
       input_context.type != ui::TEXT_INPUT_TYPE_TELEPHONE &&
       input_context.type != ui::TEXT_INPUT_TYPE_NUMBER) {
     return "password";
@@ -237,19 +245,19 @@
 
 bool ImeObserver::ConvertInputContextAutoCorrect(
     ui::IMEEngineHandlerInterface::InputContext input_context) {
-  return !keyboard::GetKeyboardRestricted() &&
+  return keyboard::GetKeyboardConfig().auto_correct &&
          !(input_context.flags & ui::TEXT_INPUT_FLAG_AUTOCORRECT_OFF);
 }
 
 bool ImeObserver::ConvertInputContextAutoComplete(
     ui::IMEEngineHandlerInterface::InputContext input_context) {
-  return !keyboard::GetKeyboardRestricted() &&
+  return keyboard::GetKeyboardConfig().auto_complete &&
          !(input_context.flags & ui::TEXT_INPUT_FLAG_AUTOCOMPLETE_OFF);
 }
 
 bool ImeObserver::ConvertInputContextSpellCheck(
     ui::IMEEngineHandlerInterface::InputContext input_context) {
-  return !keyboard::GetKeyboardRestricted() &&
+  return keyboard::GetKeyboardConfig().spell_check &&
          !(input_context.flags & ui::TEXT_INPUT_FLAG_SPELLCHECK_OFF);
 }
 
diff --git a/chrome/browser/extensions/api/processes/processes_api.cc b/chrome/browser/extensions/api/processes/processes_api.cc
index 4e96a3a8..63c005e 100644
--- a/chrome/browser/extensions/api/processes/processes_api.cc
+++ b/chrome/browser/extensions/api/processes/processes_api.cc
@@ -7,6 +7,9 @@
 #include <stdint.h>
 
 #include <algorithm>
+#include <memory>
+#include <set>
+#include <utility>
 
 #include "base/lazy_instance.h"
 #include "base/metrics/histogram_macros.h"
@@ -20,6 +23,7 @@
 #include "chrome/common/extensions/api/processes.h"
 #include "content/public/browser/browser_child_process_host.h"
 #include "content/public/browser/child_process_data.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/child_process_host.h"
@@ -459,7 +463,9 @@
                             base::IntToString(tab_id)));
   }
 
-  const int process_id = contents->GetRenderProcessHost()->GetID();
+  // TODO(https://crbug.com/767563): chrome.processes.getProcessIdForTab API
+  // incorrectly assumes a *single* renderer process per tab.
+  const int process_id = contents->GetMainFrame()->GetProcess()->GetID();
   return RespondNow(ArgumentList(
       api::processes::GetProcessIdForTab::Results::Create(process_id)));
 }
diff --git a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
index aaf3441..251299b 100644
--- a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
+++ b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
@@ -21,6 +21,8 @@
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/common/url_constants.h"
 #include "components/user_manager/user_manager.h"
+#include "extensions/browser/event_router.h"
+#include "extensions/common/api/virtual_keyboard.h"
 #include "extensions/common/api/virtual_keyboard_private.h"
 #include "media/audio/audio_system.h"
 #include "ui/aura/window_tree_host.h"
@@ -60,8 +62,9 @@
 
 namespace extensions {
 
-ChromeVirtualKeyboardDelegate::ChromeVirtualKeyboardDelegate()
-    : weak_factory_(this) {
+ChromeVirtualKeyboardDelegate::ChromeVirtualKeyboardDelegate(
+    content::BrowserContext* browser_context)
+    : browser_context_(browser_context), weak_factory_(this) {
   weak_this_ = weak_factory_.GetWeakPtr();
 }
 
@@ -77,6 +80,12 @@
                      weak_this_, std::move(on_settings_callback)));
 }
 
+void ChromeVirtualKeyboardDelegate::OnKeyboardConfigChanged() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  GetKeyboardConfig(base::Bind(
+      &ChromeVirtualKeyboardDelegate::DispatchConfigChangeEvent, weak_this_));
+}
+
 bool ChromeVirtualKeyboardDelegate::HideKeyboard() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   keyboard::KeyboardController* controller =
@@ -113,17 +122,6 @@
     ash::Shell::Get()->CreateKeyboard();
 }
 
-void ChromeVirtualKeyboardDelegate::SetKeyboardRestricted(bool restricted) {
-  if (keyboard::GetKeyboardRestricted() == restricted)
-    return;
-
-  keyboard::SetKeyboardRestricted(restricted);
-
-  // Force virtual keyboard reload.
-  if (keyboard::IsKeyboardEnabled())
-    ash::Shell::Get()->CreateKeyboard();
-}
-
 bool ChromeVirtualKeyboardDelegate::LockKeyboard(bool state) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   keyboard::KeyboardController* controller =
@@ -184,7 +182,7 @@
 
 void ChromeVirtualKeyboardDelegate::OnHasInputDevices(
     OnKeyboardSettingsCallback on_settings_callback,
-    bool has_input_devices) {
+    bool has_audio_input_devices) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   std::unique_ptr<base::DictionaryValue> results(new base::DictionaryValue());
   results->SetString("layout", keyboard::GetKeyboardLayout());
@@ -193,6 +191,7 @@
   results->SetBoolean("a11ymode", keyboard::GetAccessibilityKeyboardEnabled());
   results->SetBoolean("hotrodmode", keyboard::GetHotrodKeyboardEnabled());
   std::unique_ptr<base::ListValue> features(new base::ListValue());
+
   features->AppendString(GenerateFeatureFlag(
       "floatingvirtualkeyboard", keyboard::IsFloatingVirtualKeyboardEnabled()));
   features->AppendString(
@@ -200,11 +199,92 @@
   features->AppendString(GenerateFeatureFlag(
       "gestureediting", keyboard::IsGestureEditingEnabled()));
   features->AppendString(GenerateFeatureFlag(
-      "voiceinput", has_input_devices && keyboard::IsVoiceInputEnabled()));
-  features->AppendString(GenerateFeatureFlag(
       "experimental", keyboard::IsExperimentalInputViewEnabled()));
+
+  const keyboard::KeyboardConfig config = keyboard::GetKeyboardConfig();
+  // TODO(oka): Change this to use config.voice_input.
+  features->AppendString(GenerateFeatureFlag(
+      "voiceinput", has_audio_input_devices && config.voice_input &&
+                        !base::CommandLine::ForCurrentProcess()->HasSwitch(
+                            keyboard::switches::kDisableVoiceInput)));
+  features->AppendString(
+      GenerateFeatureFlag("autocomplete", config.auto_complete));
+  features->AppendString(
+      GenerateFeatureFlag("autocorrect", config.auto_correct));
+  features->AppendString(GenerateFeatureFlag("spellcheck", config.spell_check));
+  features->AppendString(
+      GenerateFeatureFlag("handwriting", config.handwriting));
+
   results->Set("features", std::move(features));
+
   std::move(on_settings_callback).Run(std::move(results));
 }
 
+void ChromeVirtualKeyboardDelegate::DispatchConfigChangeEvent(
+    std::unique_ptr<base::DictionaryValue> settings) {
+  EventRouter* router = EventRouter::Get(browser_context_);
+
+  if (!router->HasEventListener(
+          keyboard_api::OnKeyboardConfigChanged::kEventName))
+    return;
+
+  auto event_args = std::make_unique<base::ListValue>();
+  event_args->Append(std::move(settings));
+
+  auto event = std::make_unique<extensions::Event>(
+      extensions::events::VIRTUAL_KEYBOARD_PRIVATE_ON_KEYBOARD_CONFIG_CHANGED,
+      keyboard_api::OnKeyboardConfigChanged::kEventName, std::move(event_args),
+      browser_context_);
+  router->BroadcastEvent(std::move(event));
+}
+
+api::virtual_keyboard::FeatureRestrictions
+ChromeVirtualKeyboardDelegate::RestrictFeatures(
+    const api::virtual_keyboard::RestrictFeatures::Params& params) {
+  const api::virtual_keyboard::FeatureRestrictions& restrictions =
+      params.restrictions;
+  api::virtual_keyboard::FeatureRestrictions update;
+  keyboard::KeyboardConfig config = keyboard::GetKeyboardConfig();
+  if (restrictions.spell_check_enabled &&
+      config.spell_check != *restrictions.spell_check_enabled) {
+    update.spell_check_enabled =
+        std::make_unique<bool>(*restrictions.spell_check_enabled);
+    config.spell_check = *restrictions.spell_check_enabled;
+  }
+  if (restrictions.auto_complete_enabled &&
+      config.auto_complete != *restrictions.auto_complete_enabled) {
+    update.auto_complete_enabled =
+        std::make_unique<bool>(*restrictions.auto_complete_enabled);
+    config.auto_complete = *restrictions.auto_complete_enabled;
+  }
+  if (restrictions.auto_correct_enabled &&
+      config.auto_correct != *restrictions.auto_correct_enabled) {
+    update.auto_correct_enabled =
+        std::make_unique<bool>(*restrictions.auto_correct_enabled);
+    config.auto_correct = *restrictions.auto_correct_enabled;
+  }
+  if (restrictions.voice_input_enabled &&
+      config.voice_input != *restrictions.voice_input_enabled) {
+    update.voice_input_enabled =
+        std::make_unique<bool>(*restrictions.voice_input_enabled);
+    config.voice_input = *restrictions.voice_input_enabled;
+  }
+  if (restrictions.handwriting_enabled &&
+      config.handwriting != *restrictions.handwriting_enabled) {
+    update.handwriting_enabled =
+        std::make_unique<bool>(*restrictions.handwriting_enabled);
+    config.handwriting = *restrictions.handwriting_enabled;
+  }
+
+  if (keyboard::UpdateKeyboardConfig(config)) {
+    // This reloads virtual keyboard even if it exists. This ensures virtual
+    // keyboard gets the correct state through
+    // chrome.virtualKeyboardPrivate.getKeyboardConfig.
+    // TODO(oka): Extension should reload on it's own by receiving event
+    if (keyboard::IsKeyboardEnabled())
+      ash::Shell::Get()->CreateKeyboard();
+  }
+  return update;
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.h b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.h
index d29ca89..562d77c 100644
--- a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.h
+++ b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.h
@@ -10,7 +10,9 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "content/public/browser/browser_context.h"
 #include "extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h"
+#include "extensions/common/api/virtual_keyboard.h"
 
 namespace media {
 class AudioSystem;
@@ -20,16 +22,20 @@
 
 class ChromeVirtualKeyboardDelegate : public VirtualKeyboardDelegate {
  public:
-  ChromeVirtualKeyboardDelegate();
+  explicit ChromeVirtualKeyboardDelegate(
+      content::BrowserContext* browser_context);
   ~ChromeVirtualKeyboardDelegate() override;
 
+  // TODO(oka): Create ChromeVirtualKeyboardPrivateDelegate class and move all
+  // the methods except for RestrictFeatures into the class for clear separation
+  // of virtualKeyboard and virtualKeyboardPrivate API.
   void GetKeyboardConfig(
       OnKeyboardSettingsCallback on_settings_callback) override;
+  void OnKeyboardConfigChanged() override;
   bool HideKeyboard() override;
   bool InsertText(const base::string16& text) override;
   bool OnKeyboardLoaded() override;
   void SetHotrodKeyboard(bool enable) override;
-  void SetKeyboardRestricted(bool restricted) override;
   bool LockKeyboard(bool state) override;
   bool SendKeyEvent(const std::string& type,
                     int char_value,
@@ -41,10 +47,16 @@
   bool SetVirtualKeyboardMode(int mode_enum) override;
   bool SetRequestedKeyboardState(int state_enum) override;
 
+  api::virtual_keyboard::FeatureRestrictions RestrictFeatures(
+      const api::virtual_keyboard::RestrictFeatures::Params& params) override;
+
  private:
   void OnHasInputDevices(OnKeyboardSettingsCallback on_settings_callback,
-                         bool has_input_devices);
+                         bool has_audio_input_devices);
+  void DispatchConfigChangeEvent(
+      std::unique_ptr<base::DictionaryValue> settings);
 
+  content::BrowserContext* browser_context_;
   std::unique_ptr<media::AudioSystem> audio_system_;
   base::WeakPtr<ChromeVirtualKeyboardDelegate> weak_this_;
   base::WeakPtrFactory<ChromeVirtualKeyboardDelegate> weak_factory_;
diff --git a/chrome/browser/extensions/api/web_view/chrome_web_view_internal_api.cc b/chrome/browser/extensions/api/web_view/chrome_web_view_internal_api.cc
index a3f56b99..11110d1 100644
--- a/chrome/browser/extensions/api/web_view/chrome_web_view_internal_api.cc
+++ b/chrome/browser/extensions/api/web_view/chrome_web_view_internal_api.cc
@@ -4,10 +4,13 @@
 
 #include "chrome/browser/extensions/api/web_view/chrome_web_view_internal_api.h"
 
+#include <memory>
+
 #include "chrome/browser/extensions/api/context_menus/context_menus_api.h"
 #include "chrome/browser/extensions/api/context_menus/context_menus_api_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/extensions/api/chrome_web_view_internal.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "extensions/common/error_utils.h"
 
@@ -27,7 +30,7 @@
       Profile::FromBrowserContext(browser_context())->IsOffTheRecord(),
       MenuItem::ExtensionKey(
           extension_id(),
-          GetSenderWebContents()->GetRenderProcessHost()->GetID(),
+          GetSenderWebContents()->GetMainFrame()->GetProcess()->GetID(),
           params->instance_id));
 
   if (params->create_properties.id.get()) {
@@ -61,7 +64,7 @@
       profile->IsOffTheRecord(),
       MenuItem::ExtensionKey(
           extension_id(),
-          GetSenderWebContents()->GetRenderProcessHost()->GetID(),
+          GetSenderWebContents()->GetMainFrame()->GetProcess()->GetID(),
           params->instance_id));
 
   if (params->id.as_string)
@@ -89,7 +92,7 @@
       Profile::FromBrowserContext(browser_context())->IsOffTheRecord(),
       MenuItem::ExtensionKey(
           extension_id(),
-          GetSenderWebContents()->GetRenderProcessHost()->GetID(),
+          GetSenderWebContents()->GetMainFrame()->GetProcess()->GetID(),
           params->instance_id));
 
   if (params->menu_item_id.as_string) {
@@ -125,7 +128,7 @@
       MenuManager::Get(Profile::FromBrowserContext(browser_context()));
   menu_manager->RemoveAllContextItems(MenuItem::ExtensionKey(
       extension_id(),
-      GetSenderWebContents()->GetRenderProcessHost()->GetID(),
+      GetSenderWebContents()->GetMainFrame()->GetProcess()->GetID(),
       params->instance_id));
 
   SendResponse(true);
diff --git a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc
index 63ed6ecd..fd35426 100644
--- a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc
+++ b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/extensions/extension_tab_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "content/public/browser/media_device_id.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_registry.h"
@@ -170,7 +171,7 @@
         expected_origin.spec().c_str(), security_origin.c_str());
     return nullptr;
   }
-  return contents->GetRenderProcessHost();
+  return contents->GetMainFrame()->GetProcess();
 }
 
 bool WebrtcAudioPrivateGetSinksFunction::RunAsync() {
diff --git a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_event_log_apitest.cc b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_event_log_apitest.cc
index f5c6b44..e13d805 100644
--- a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_event_log_apitest.cc
+++ b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_event_log_apitest.cc
@@ -21,6 +21,7 @@
 #include "chrome/browser/media/webrtc/webrtc_browsertest_base.h"
 #include "chrome/browser/media/webrtc/webrtc_browsertest_common.h"
 #include "chrome/common/chrome_switches.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
 #include "extensions/browser/api_test_utils.h"
@@ -224,7 +225,7 @@
 
   // Check that the file exists and is non-empty.
   content::RenderProcessHost* render_process_host =
-      left_tab->GetRenderProcessHost();
+      left_tab->GetMainFrame()->GetProcess();
   ASSERT_NE(render_process_host, nullptr);
   int render_process_id = render_process_host->GetID();
   base::FilePath full_file_name =
@@ -299,7 +300,7 @@
   // The log has stopped automatically. Check that the file exists and is
   // non-empty.
   content::RenderProcessHost* render_process_host =
-      left_tab->GetRenderProcessHost();
+      left_tab->GetMainFrame()->GetProcess();
   ASSERT_NE(render_process_host, nullptr);
   int render_process_id = render_process_host->GetID();
   base::FilePath full_file_name =
diff --git a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
index 58be6b7..8f7c92d 100644
--- a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
+++ b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_switches.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/web_contents.h"
@@ -92,7 +93,7 @@
         expected_origin.spec().c_str(), security_origin.c_str());
     return nullptr;
   }
-  return contents->GetRenderProcessHost();
+  return contents->GetMainFrame()->GetProcess();
 }
 
 scoped_refptr<WebRtcLoggingHandlerHost>
diff --git a/chrome/browser/extensions/app_process_apitest.cc b/chrome/browser/extensions/app_process_apitest.cc
index fe1aca0..a650aec 100644
--- a/chrome/browser/extensions/app_process_apitest.cc
+++ b/chrome/browser/extensions/app_process_apitest.cc
@@ -20,6 +20,7 @@
 #include "components/sync/model/string_ordinal.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/notification_service.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/site_instance.h"
@@ -94,9 +95,12 @@
         WindowOpenDisposition::NEW_FOREGROUND_TAB,
         ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
     LOG(INFO) << "Nav 1.";
-    EXPECT_TRUE(process_map->Contains(
-        browser()->tab_strip_model()->GetWebContentsAt(1)->
-            GetRenderProcessHost()->GetID()));
+    EXPECT_TRUE(process_map->Contains(browser()
+                                          ->tab_strip_model()
+                                          ->GetWebContentsAt(1)
+                                          ->GetMainFrame()
+                                          ->GetProcess()
+                                          ->GetID()));
     EXPECT_FALSE(browser()->tab_strip_model()->GetWebContentsAt(1)->GetWebUI());
 
     content::WindowedNotificationObserver tab_added_observer(
@@ -108,9 +112,12 @@
     ui_test_utils::NavigateToURL(browser(),
                                  base_url.Resolve("path2/empty.html"));
     LOG(INFO) << "Nav 2.";
-    EXPECT_TRUE(process_map->Contains(
-        browser()->tab_strip_model()->GetWebContentsAt(2)->
-            GetRenderProcessHost()->GetID()));
+    EXPECT_TRUE(process_map->Contains(browser()
+                                          ->tab_strip_model()
+                                          ->GetWebContentsAt(2)
+                                          ->GetMainFrame()
+                                          ->GetProcess()
+                                          ->GetID()));
     EXPECT_FALSE(browser()->tab_strip_model()->GetWebContentsAt(2)->GetWebUI());
 
     // We should have opened 2 new extension tabs. Including the original blank
@@ -120,7 +127,8 @@
     ASSERT_EQ(3, browser()->tab_strip_model()->count());
     WebContents* tab1 = browser()->tab_strip_model()->GetWebContentsAt(1);
     WebContents* tab2 = browser()->tab_strip_model()->GetWebContentsAt(2);
-    EXPECT_NE(tab1->GetRenderProcessHost(), tab2->GetRenderProcessHost());
+    EXPECT_NE(tab1->GetMainFrame()->GetProcess(),
+              tab2->GetMainFrame()->GetProcess());
 
     // Opening tabs with window.open should keep the page in the opener's
     // process.
@@ -166,9 +174,12 @@
       browser(), base_url.Resolve("path1/empty.html"),
       WindowOpenDisposition::NEW_FOREGROUND_TAB,
       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
-  EXPECT_TRUE(process_map->Contains(
-      browser()->tab_strip_model()->GetWebContentsAt(1)->
-          GetRenderProcessHost()->GetID()));
+  EXPECT_TRUE(process_map->Contains(browser()
+                                        ->tab_strip_model()
+                                        ->GetWebContentsAt(1)
+                                        ->GetMainFrame()
+                                        ->GetProcess()
+                                        ->GetID()));
   EXPECT_FALSE(browser()->tab_strip_model()->GetWebContentsAt(1)->GetWebUI());
   LOG(INFO) << "Nav 1.";
 
@@ -176,9 +187,12 @@
       browser(), base_url.Resolve("path2/empty.html"),
       WindowOpenDisposition::NEW_FOREGROUND_TAB,
       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
-  EXPECT_TRUE(process_map->Contains(
-      browser()->tab_strip_model()->GetWebContentsAt(2)->
-          GetRenderProcessHost()->GetID()));
+  EXPECT_TRUE(process_map->Contains(browser()
+                                        ->tab_strip_model()
+                                        ->GetWebContentsAt(2)
+                                        ->GetMainFrame()
+                                        ->GetProcess()
+                                        ->GetID()));
   EXPECT_FALSE(browser()->tab_strip_model()->GetWebContentsAt(2)->GetWebUI());
   LOG(INFO) << "Nav 2.";
 
@@ -190,9 +204,12 @@
   LOG(INFO) << "New tab.";
   ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path3/empty.html"));
   LOG(INFO) << "Nav 3.";
-  EXPECT_FALSE(process_map->Contains(
-      browser()->tab_strip_model()->GetWebContentsAt(3)->
-          GetRenderProcessHost()->GetID()));
+  EXPECT_FALSE(process_map->Contains(browser()
+                                         ->tab_strip_model()
+                                         ->GetWebContentsAt(3)
+                                         ->GetMainFrame()
+                                         ->GetProcess()
+                                         ->GetID()));
   EXPECT_FALSE(browser()->tab_strip_model()->GetWebContentsAt(3)->GetWebUI());
 
   // We should have opened 3 new extension tabs. Including the original blank
@@ -202,12 +219,16 @@
   ASSERT_EQ(4, browser()->tab_strip_model()->count());
   WebContents* tab = browser()->tab_strip_model()->GetWebContentsAt(1);
 
-  EXPECT_EQ(tab->GetRenderProcessHost(),
-            browser()->tab_strip_model()->GetWebContentsAt(2)->
-                GetRenderProcessHost());
-  EXPECT_NE(tab->GetRenderProcessHost(),
-            browser()->tab_strip_model()->GetWebContentsAt(3)->
-                GetRenderProcessHost());
+  EXPECT_EQ(tab->GetMainFrame()->GetProcess(), browser()
+                                                   ->tab_strip_model()
+                                                   ->GetWebContentsAt(2)
+                                                   ->GetMainFrame()
+                                                   ->GetProcess());
+  EXPECT_NE(tab->GetMainFrame()->GetProcess(), browser()
+                                                   ->tab_strip_model()
+                                                   ->GetWebContentsAt(3)
+                                                   ->GetMainFrame()
+                                                   ->GetProcess());
 
   // Now let's do the same using window.open. The same should happen.
   ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile()));
@@ -233,21 +254,27 @@
   NavigateInRenderer(browser()->tab_strip_model()->GetWebContentsAt(3),
                      app_url);
   LOG(INFO) << "NavigateTabHelper 2.";
-  EXPECT_NE(tab->GetRenderProcessHost(),
-            browser()->tab_strip_model()->GetWebContentsAt(2)->
-                GetRenderProcessHost());
-  EXPECT_EQ(tab->GetRenderProcessHost(),
-            browser()->tab_strip_model()->GetWebContentsAt(3)->
-                GetRenderProcessHost());
+  EXPECT_NE(tab->GetMainFrame()->GetProcess(), browser()
+                                                   ->tab_strip_model()
+                                                   ->GetWebContentsAt(2)
+                                                   ->GetMainFrame()
+                                                   ->GetProcess());
+  EXPECT_EQ(tab->GetMainFrame()->GetProcess(), browser()
+                                                   ->tab_strip_model()
+                                                   ->GetWebContentsAt(3)
+                                                   ->GetMainFrame()
+                                                   ->GetProcess());
 
   // If one of the popup tabs navigates back to the app, window.opener should
   // be valid.
   NavigateInRenderer(browser()->tab_strip_model()->GetWebContentsAt(6),
                      app_url);
   LOG(INFO) << "NavigateTabHelper 3.";
-  EXPECT_EQ(tab->GetRenderProcessHost(),
-            browser()->tab_strip_model()->GetWebContentsAt(6)->
-                GetRenderProcessHost());
+  EXPECT_EQ(tab->GetMainFrame()->GetProcess(), browser()
+                                                   ->tab_strip_model()
+                                                   ->GetWebContentsAt(6)
+                                                   ->GetMainFrame()
+                                                   ->GetProcess());
   bool windowOpenerValid = false;
   ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
       browser()->tab_strip_model()->GetWebContentsAt(6),
@@ -315,9 +342,12 @@
       browser(), base_url.Resolve("path1/empty.html"),
       WindowOpenDisposition::NEW_FOREGROUND_TAB,
       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
-  EXPECT_FALSE(process_map->Contains(
-      browser()->tab_strip_model()->GetWebContentsAt(1)->
-          GetRenderProcessHost()->GetID()));
+  EXPECT_FALSE(process_map->Contains(browser()
+                                         ->tab_strip_model()
+                                         ->GetWebContentsAt(1)
+                                         ->GetMainFrame()
+                                         ->GetProcess()
+                                         ->GetID()));
   EXPECT_FALSE(browser()->tab_strip_model()->GetWebContentsAt(1)->GetWebUI());
 
   content::WindowedNotificationObserver tab_added_observer(
@@ -326,9 +356,12 @@
   chrome::NewTab(browser());
   tab_added_observer.Wait();
   ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path2/empty.html"));
-  EXPECT_FALSE(process_map->Contains(
-      browser()->tab_strip_model()->GetWebContentsAt(2)->
-          GetRenderProcessHost()->GetID()));
+  EXPECT_FALSE(process_map->Contains(browser()
+                                         ->tab_strip_model()
+                                         ->GetWebContentsAt(2)
+                                         ->GetMainFrame()
+                                         ->GetProcess()
+                                         ->GetID()));
   EXPECT_FALSE(browser()->tab_strip_model()->GetWebContentsAt(2)->GetWebUI());
 
   // We should have opened 2 new bookmark app tabs. Including the original blank
@@ -336,9 +369,11 @@
   // process-per-site-instance model, each should be in its own process.
   ASSERT_EQ(3, browser()->tab_strip_model()->count());
   WebContents* tab = browser()->tab_strip_model()->GetWebContentsAt(1);
-  EXPECT_NE(tab->GetRenderProcessHost(),
-            browser()->tab_strip_model()->GetWebContentsAt(2)->
-                GetRenderProcessHost());
+  EXPECT_NE(tab->GetMainFrame()->GetProcess(), browser()
+                                                   ->tab_strip_model()
+                                                   ->GetWebContentsAt(2)
+                                                   ->GetMainFrame()
+                                                   ->GetProcess());
 
   // Now let's do the same using window.open. The same should happen.
   ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile()));
@@ -353,14 +388,18 @@
       browser()->tab_strip_model()->GetWebContentsAt(2)->GetRenderViewHost();
   NavigateInRenderer(browser()->tab_strip_model()->GetWebContentsAt(2),
                      non_app_url);
-  EXPECT_EQ(host2->GetProcess(),
-            browser()->tab_strip_model()->GetWebContentsAt(2)->
-                GetRenderProcessHost());
+  EXPECT_EQ(host2->GetProcess(), browser()
+                                     ->tab_strip_model()
+                                     ->GetWebContentsAt(2)
+                                     ->GetMainFrame()
+                                     ->GetProcess());
   NavigateInRenderer(browser()->tab_strip_model()->GetWebContentsAt(2),
                      app_url);
-  EXPECT_EQ(host2->GetProcess(),
-            browser()->tab_strip_model()->GetWebContentsAt(2)->
-                GetRenderProcessHost());
+  EXPECT_EQ(host2->GetProcess(), browser()
+                                     ->tab_strip_model()
+                                     ->GetWebContentsAt(2)
+                                     ->GetMainFrame()
+                                     ->GetProcess());
 }
 
 // Tests that app process switching works properly in the following scenario:
@@ -398,10 +437,16 @@
   EXPECT_EQ("/extensions/api_test/app_process/path1/empty.html",
             browser()->tab_strip_model()->GetWebContentsAt(2)->
                 GetController().GetLastCommittedEntry()->GetURL().path());
-  EXPECT_EQ(browser()->tab_strip_model()->GetWebContentsAt(1)->
-                GetRenderProcessHost(),
-            browser()->tab_strip_model()->GetWebContentsAt(2)->
-                GetRenderProcessHost());
+  EXPECT_EQ(browser()
+                ->tab_strip_model()
+                ->GetWebContentsAt(1)
+                ->GetMainFrame()
+                ->GetProcess(),
+            browser()
+                ->tab_strip_model()
+                ->GetWebContentsAt(2)
+                ->GetMainFrame()
+                ->GetProcess());
 }
 
 // Ensure that re-navigating to a URL after installing or uninstalling it as an
@@ -422,8 +467,8 @@
   ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path1/empty.html"));
   LOG(INFO) << "Loading path1/empty.html - done.";
   WebContents* contents = browser()->tab_strip_model()->GetWebContentsAt(0);
-  EXPECT_FALSE(process_map->Contains(
-      contents->GetRenderProcessHost()->GetID()));
+  EXPECT_FALSE(
+      process_map->Contains(contents->GetMainFrame()->GetProcess()->GetID()));
 
   // Load app and re-navigate to the page.
   LOG(INFO) << "Loading extension.";
@@ -434,8 +479,8 @@
   LOG(INFO) << "Loading path1/empty.html.";
   ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path1/empty.html"));
   LOG(INFO) << "Loading path1/empty.html - done.";
-  EXPECT_TRUE(process_map->Contains(
-      contents->GetRenderProcessHost()->GetID()));
+  EXPECT_TRUE(
+      process_map->Contains(contents->GetMainFrame()->GetProcess()->GetID()));
 
   // Disable app and re-navigate to the page.
   LOG(INFO) << "Disabling extension.";
@@ -444,8 +489,8 @@
   LOG(INFO) << "Loading path1/empty.html.";
   ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path1/empty.html"));
   LOG(INFO) << "Loading path1/empty.html - done.";
-  EXPECT_FALSE(process_map->Contains(
-      contents->GetRenderProcessHost()->GetID()));
+  EXPECT_FALSE(
+      process_map->Contains(contents->GetMainFrame()->GetProcess()->GetID()));
 }
 
 // Ensure that reloading a URL after installing or uninstalling it as an app
@@ -474,8 +519,8 @@
   ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path1/empty.html"));
   LOG(INFO) << "Navigate to path1/empty.html - done.";
   WebContents* contents = browser()->tab_strip_model()->GetWebContentsAt(0);
-  EXPECT_FALSE(process_map->Contains(
-      contents->GetRenderProcessHost()->GetID()));
+  EXPECT_FALSE(
+      process_map->Contains(contents->GetMainFrame()->GetProcess()->GetID()));
 
   // Enable app and reload the page.
   LOG(INFO) << "Enabling extension.";
@@ -490,8 +535,8 @@
   chrome::Reload(browser(), WindowOpenDisposition::CURRENT_TAB);
   reload_observer.Wait();
   LOG(INFO) << "Reloading - done.";
-  EXPECT_TRUE(process_map->Contains(
-      contents->GetRenderProcessHost()->GetID()));
+  EXPECT_TRUE(
+      process_map->Contains(contents->GetMainFrame()->GetProcess()->GetID()));
 
   // Disable app and reload the page.
   LOG(INFO) << "Disabling extension.";
@@ -506,8 +551,8 @@
   chrome::Reload(browser(), WindowOpenDisposition::CURRENT_TAB);
   reload_observer2.Wait();
   LOG(INFO) << "Reloading - done.";
-  EXPECT_FALSE(process_map->Contains(
-      contents->GetRenderProcessHost()->GetID()));
+  EXPECT_FALSE(
+      process_map->Contains(contents->GetMainFrame()->GetProcess()->GetID()));
 }
 
 // Ensure that reloading a URL with JavaScript after installing or uninstalling
@@ -536,8 +581,8 @@
   ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path1/empty.html"));
   LOG(INFO) << "Navigate to path1/empty.html - done.";
   WebContents* contents = browser()->tab_strip_model()->GetWebContentsAt(0);
-  EXPECT_FALSE(process_map->Contains(
-      contents->GetRenderProcessHost()->GetID()));
+  EXPECT_FALSE(
+      process_map->Contains(contents->GetMainFrame()->GetProcess()->GetID()));
 
   // Enable app and reload via JavaScript.
   LOG(INFO) << "Enabling extension.";
@@ -552,8 +597,8 @@
   ASSERT_TRUE(content::ExecuteScript(contents, "location.reload();"));
   js_reload_observer.Wait();
   LOG(INFO) << "Executing location.reload() - done.";
-  EXPECT_TRUE(process_map->Contains(
-      contents->GetRenderProcessHost()->GetID()));
+  EXPECT_TRUE(
+      process_map->Contains(contents->GetMainFrame()->GetProcess()->GetID()));
 
   // Disable app and reload via JavaScript.
   LOG(INFO) << "Disabling extension.";
@@ -568,8 +613,8 @@
   ASSERT_TRUE(content::ExecuteScript(contents, "location = location;"));
   js_reload_observer2.Wait();
   LOG(INFO) << "Executing location = location - done.";
-  EXPECT_FALSE(process_map->Contains(
-      contents->GetRenderProcessHost()->GetID()));
+  EXPECT_FALSE(
+      process_map->Contains(contents->GetMainFrame()->GetProcess()->GetID()));
 }
 
 // Tests that if we have a non-app process (path3/container.html) that has an
@@ -590,9 +635,12 @@
 
   ui_test_utils::NavigateToURL(browser(),
                                base_url.Resolve("path3/container.html"));
-  EXPECT_FALSE(process_map->Contains(
-      browser()->tab_strip_model()->GetWebContentsAt(0)->
-          GetRenderProcessHost()->GetID()));
+  EXPECT_FALSE(process_map->Contains(browser()
+                                         ->tab_strip_model()
+                                         ->GetWebContentsAt(0)
+                                         ->GetMainFrame()
+                                         ->GetProcess()
+                                         ->GetID()));
 
   const BrowserList* active_browser_list = BrowserList::GetInstance();
   EXPECT_EQ(2U, active_browser_list->size());
@@ -721,8 +769,11 @@
 
   ui_test_utils::NavigateToURL(browser(),
                                base_url.Resolve("path1/container.html"));
-  content::RenderProcessHost* process =
-      browser()->tab_strip_model()->GetWebContentsAt(0)->GetRenderProcessHost();
+  content::RenderProcessHost* process = browser()
+                                            ->tab_strip_model()
+                                            ->GetWebContentsAt(0)
+                                            ->GetMainFrame()
+                                            ->GetProcess();
   EXPECT_TRUE(process_map->Contains(process->GetID()));
 
   // Popup window should be in the app's process if site isolation is off;
@@ -735,7 +786,7 @@
 
   bool should_be_in_same_process = !content::AreAllSitesIsolatedForTesting();
   content::RenderProcessHost* popup_process =
-      popup_contents->GetRenderProcessHost();
+      popup_contents->GetMainFrame()->GetProcess();
   EXPECT_EQ(should_be_in_same_process, process == popup_process);
   EXPECT_EQ(should_be_in_same_process,
             process_map->Contains(popup_process->GetID()));
@@ -758,8 +809,8 @@
   // Load the app, chrome.app.isInstalled should be true.
   ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path1/empty.html"));
   WebContents* contents = browser()->tab_strip_model()->GetWebContentsAt(0);
-  EXPECT_TRUE(process_map->Contains(
-      contents->GetRenderProcessHost()->GetID()));
+  EXPECT_TRUE(
+      process_map->Contains(contents->GetMainFrame()->GetProcess()->GetID()));
   bool is_installed = false;
   ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
       contents,
diff --git a/chrome/browser/extensions/bookmark_app_helper.cc b/chrome/browser/extensions/bookmark_app_helper.cc
index f3fd165..d2763557 100644
--- a/chrome/browser/extensions/bookmark_app_helper.cc
+++ b/chrome/browser/extensions/bookmark_app_helper.cc
@@ -593,16 +593,19 @@
 
 void BookmarkAppHelper::CreateFromAppBanner(
     const CreateBookmarkAppCallback& callback,
+    const GURL& manifest_url,
     const content::Manifest& manifest) {
   DCHECK(!manifest.short_name.is_null() || !manifest.name.is_null());
   DCHECK(manifest.start_url.is_valid());
 
   callback_ = callback;
-  OnDidGetManifest(GURL(), manifest);
+  OnDidGetManifest(manifest_url, manifest);
 }
 
 void BookmarkAppHelper::OnDidGetManifest(const GURL& manifest_url,
                                          const content::Manifest& manifest) {
+  DCHECK(manifest_url.is_valid() || manifest.IsEmpty());
+
   if (contents_->IsBeingDestroyed())
     return;
 
diff --git a/chrome/browser/extensions/bookmark_app_helper.h b/chrome/browser/extensions/bookmark_app_helper.h
index 4145489..113745508 100644
--- a/chrome/browser/extensions/bookmark_app_helper.h
+++ b/chrome/browser/extensions/bookmark_app_helper.h
@@ -107,6 +107,7 @@
 
   // Begins the asynchronous bookmark app creation from an app banner.
   void CreateFromAppBanner(const CreateBookmarkAppCallback& callback,
+                           const GURL& manifest_url,
                            const content::Manifest& manifest);
 
  protected:
diff --git a/chrome/browser/extensions/bookmark_app_helper_unittest.cc b/chrome/browser/extensions/bookmark_app_helper_unittest.cc
index 4114df7..1f829b8 100644
--- a/chrome/browser/extensions/bookmark_app_helper_unittest.cc
+++ b/chrome/browser/extensions/bookmark_app_helper_unittest.cc
@@ -29,6 +29,7 @@
 
 namespace {
 
+const char kManifestUrl[] = "http://www.chromium.org/manifest.json";
 const char kAppUrl[] = "http://www.chromium.org/index.html";
 const char kAlternativeAppUrl[] = "http://www.notchromium.org";
 const char kAppScope[] = "http://www.chromium.org/scope/";
@@ -297,8 +298,9 @@
     extension_ = extension;
   }
 
-  void CompleteGetManifest(const content::Manifest& manifest) {
-    BookmarkAppHelper::OnDidGetManifest(GURL(), manifest);
+  void CompleteGetManifest(const char* manifest_url,
+                           const content::Manifest& manifest) {
+    BookmarkAppHelper::OnDidGetManifest(GURL(manifest_url), manifest);
   }
 
   void CompleteIconDownload(
@@ -367,7 +369,7 @@
   manifest.start_url = GURL(kAppUrl);
   manifest.name = base::NullableString16(base::UTF8ToUTF16(kAppTitle), false);
   manifest.scope = GURL(kAppScope);
-  helper.CompleteGetManifest(manifest);
+  helper.CompleteGetManifest(kManifestUrl, manifest);
 
   std::map<GURL, std::vector<SkBitmap> > icon_map;
   helper.CompleteIconDownload(true, icon_map);
@@ -402,7 +404,7 @@
   content::Manifest manifest;
   manifest.start_url = GURL(kAppUrl);
   manifest.name = base::NullableString16(base::UTF8ToUTF16(kAppTitle), false);
-  helper.CompleteGetManifest(manifest);
+  helper.CompleteGetManifest(kManifestUrl, manifest);
 
   std::map<GURL, std::vector<SkBitmap>> icon_map;
   helper.CompleteIconDownload(true, icon_map);
@@ -427,7 +429,7 @@
   helper.Create(base::Bind(&TestBookmarkAppHelper::CreationComplete,
                            base::Unretained(&helper)));
 
-  helper.CompleteGetManifest(content::Manifest());
+  helper.CompleteGetManifest(kManifestUrl, content::Manifest());
   std::map<GURL, std::vector<SkBitmap>> icon_map;
   helper.CompleteIconDownload(true, icon_map);
   content::RunAllTasksUntilIdle();
diff --git a/chrome/browser/extensions/bookmark_app_url_redirector_browsertest.cc b/chrome/browser/extensions/bookmark_app_url_redirector_browsertest.cc
index 4b95f40e..e8e8603 100644
--- a/chrome/browser/extensions/bookmark_app_url_redirector_browsertest.cc
+++ b/chrome/browser/extensions/bookmark_app_url_redirector_browsertest.cc
@@ -5,8 +5,11 @@
 #include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
+#include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/extensions/bookmark_app_helper.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
+#include "chrome/browser/prerender/prerender_manager.h"
+#include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/extensions/app_launch_params.h"
@@ -19,6 +22,7 @@
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/render_frame_host.h"
+#include "content/public/common/context_menu_params.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_frame_navigation_observer.h"
 #include "content/public/test/test_utils.h"
@@ -26,6 +30,7 @@
 #include "extensions/browser/notification_types.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/http_response.h"
+#include "net/url_request/url_fetcher.h"
 
 using namespace net::test_server;
 
@@ -69,15 +74,51 @@
   ui_test_utils::UrlLoadObserver url_observer(
       target_url, content::NotificationService::AllSources());
   std::string script = base::StringPrintf(
+      "(() => {"
       "const link = document.createElement('a');"
       "link.href = '%s';"
       "link.target = '%s';"
       "document.body.appendChild(link);"
       "const event = new MouseEvent('click', {'view': window});"
-      "link.dispatchEvent(event);",
+      "link.dispatchEvent(event);"
+      "})();",
       target_url.spec().c_str(),
       target == LinkTarget::SELF ? "_self" : "_blank");
-  EXPECT_TRUE(content::ExecuteScript(web_contents, script));
+  ASSERT_TRUE(content::ExecuteScript(web_contents, script));
+  url_observer.Wait();
+}
+
+// Creates a <form> element with a |target_url| action and |method| method. Adds
+// the form to the DOM with a button and clicks the button. Returns once
+// |target_url| has been loaded.
+//
+// If |method| is net::URLFetcher::RequestType::GET, |target_url| should contain
+// an empty query string, since that URL will be loaded when submitting the form
+// e.g. "https://www.example.com/?".
+void SubmitFormAndWait(content::WebContents* web_contents,
+                       const GURL& target_url,
+                       net::URLFetcher::RequestType method) {
+  if (method == net::URLFetcher::RequestType::GET) {
+    ASSERT_TRUE(target_url.has_query());
+    ASSERT_TRUE(target_url.query().empty());
+  }
+
+  ui_test_utils::UrlLoadObserver url_observer(
+      target_url, content::NotificationService::AllSources());
+  std::string script = base::StringPrintf(
+      "(() => {"
+      "const form = document.createElement('form');"
+      "form.action = '%s';"
+      "form.method = '%s';"
+      "const button = document.createElement('input');"
+      "button.type = 'submit';"
+      "form.appendChild(button);"
+      "document.body.appendChild(form);"
+      "button.dispatchEvent(new MouseEvent('click', {'view': window}));"
+      "})();",
+      target_url.spec().c_str(),
+      method == net::URLFetcher::RequestType::POST ? "post" : "get");
+  ASSERT_TRUE(content::ExecuteScript(web_contents, script));
   url_observer.Wait();
 }
 
@@ -118,6 +159,7 @@
         base::BindRepeating([](const HttpRequest& request) {
           auto response = base::MakeUnique<BasicHttpResponse>();
           response->set_content_type("text/html");
+          response->AddCustomHeader("Access-Control-Allow-Origin", "*");
           return static_cast<std::unique_ptr<HttpResponse>>(
               std::move(response));
         }));
@@ -163,9 +205,33 @@
     return chrome::FindLastActive();
   }
 
+  // Navigates the active tab in |browser| to the launching page.
+  void NavigateToLaunchingPage(Browser* browser) {
+    ui_test_utils::NavigateToURL(browser, GetLaunchingPageURL());
+  }
+
   // Navigates the active tab to the launching page.
-  void NavigateToLaunchingPage() {
-    ui_test_utils::NavigateToURL(browser(), GetLaunchingPageURL());
+  void NavigateToLaunchingPage() { NavigateToLaunchingPage(browser()); }
+
+  // Checks that, after running |action|, the initial tab's window doesn't have
+  // any new tabs, the initial tab did not navigate, and that no new windows
+  // have been opened.
+  void TestTabActionDoesNotNavigateOrOpenAppWindow(
+      const base::Closure& action) {
+    size_t num_browsers = chrome::GetBrowserCount(profile());
+    int num_tabs = browser()->tab_strip_model()->count();
+    content::WebContents* initial_tab =
+        browser()->tab_strip_model()->GetActiveWebContents();
+    GURL initial_url = initial_tab->GetLastCommittedURL();
+
+    action.Run();
+
+    EXPECT_EQ(num_browsers, chrome::GetBrowserCount(profile()));
+    EXPECT_EQ(browser(), chrome::FindLastActive());
+    EXPECT_EQ(num_tabs, browser()->tab_strip_model()->count());
+    EXPECT_EQ(initial_tab,
+              browser()->tab_strip_model()->GetActiveWebContents());
+    EXPECT_EQ(initial_url, initial_tab->GetLastCommittedURL());
   }
 
   // Checks that, after running |action|, the initial tab's window doesn't have
@@ -193,28 +259,36 @@
   }
 
   // Checks that no new windows are opened after running |action| and that the
-  // existing window is still the active one and navigated to |target_url|.
-  // Returns true if there were no errors.
-  bool TestTabActionDoesNotOpenAppWindow(const GURL& target_url,
+  // existing |browser| window is still the active one and navigated to
+  // |target_url|. Returns true if there were no errors.
+  bool TestTabActionDoesNotOpenAppWindow(Browser* browser,
+                                         const GURL& target_url,
                                          const base::Closure& action) {
     content::WebContents* initial_tab =
-        browser()->tab_strip_model()->GetActiveWebContents();
-    int num_tabs = browser()->tab_strip_model()->count();
-    size_t num_browsers = chrome::GetBrowserCount(profile());
+        browser->tab_strip_model()->GetActiveWebContents();
+    int num_tabs = browser->tab_strip_model()->count();
+    size_t num_browsers = chrome::GetBrowserCount(browser->profile());
 
     action.Run();
 
-    EXPECT_EQ(num_tabs, browser()->tab_strip_model()->count());
-    EXPECT_EQ(num_browsers, chrome::GetBrowserCount(profile()));
-    EXPECT_EQ(browser(), chrome::FindLastActive());
-    EXPECT_EQ(initial_tab,
-              browser()->tab_strip_model()->GetActiveWebContents());
+    EXPECT_EQ(num_tabs, browser->tab_strip_model()->count());
+    EXPECT_EQ(num_browsers, chrome::GetBrowserCount(browser->profile()));
+    EXPECT_EQ(browser, chrome::FindLastActive());
+    EXPECT_EQ(initial_tab, browser->tab_strip_model()->GetActiveWebContents());
     EXPECT_EQ(target_url, initial_tab->GetLastCommittedURL());
 
     return !HasFailure();
   }
 
   // Checks that no new windows are opened after running |action| and that the
+  // main browser window is still the active one and navigated to |target_url|.
+  // Returns true if there were no errors.
+  bool TestTabActionDoesNotOpenAppWindow(const GURL& target_url,
+                                         const base::Closure& action) {
+    return TestTabActionDoesNotOpenAppWindow(browser(), target_url, action);
+  }
+
+  // Checks that no new windows are opened after running |action| and that the
   // iframe in the initial tab navigated to |target_url|. Returns true if there
   // were no errors.
   bool TestIFrameActionDoesNotOpenAppWindow(const GURL& target_url,
@@ -426,6 +500,142 @@
                  out_of_scope_url, LinkTarget::SELF));
 }
 
+// Tests that submitting a form using POST does not open a new app window.
+IN_PROC_BROWSER_TEST_F(BookmarkAppUrlRedirectorBrowserTest,
+                       PostFormSubmission) {
+  InstallTestBookmarkApp();
+  NavigateToLaunchingPage();
+
+  const GURL in_scope_url = embedded_test_server()->GetURL(kInScopeUrlPath);
+  TestTabActionDoesNotOpenAppWindow(
+      in_scope_url,
+      base::Bind(&SubmitFormAndWait,
+                 browser()->tab_strip_model()->GetActiveWebContents(),
+                 in_scope_url, net::URLFetcher::RequestType::POST));
+}
+
+// Tests that submitting a form using GET does not open a new app window.
+IN_PROC_BROWSER_TEST_F(BookmarkAppUrlRedirectorBrowserTest, GetFormSubmission) {
+  InstallTestBookmarkApp();
+  NavigateToLaunchingPage();
+
+  GURL::Replacements replacements;
+  replacements.SetQuery("", url::Component(0, 0));
+  const GURL in_scope_form_url = embedded_test_server()
+                                     ->GetURL(kInScopeUrlPath)
+                                     .ReplaceComponents(replacements);
+  TestTabActionDoesNotOpenAppWindow(
+      in_scope_form_url,
+      base::Bind(&SubmitFormAndWait,
+                 browser()->tab_strip_model()->GetActiveWebContents(),
+                 in_scope_form_url, net::URLFetcher::RequestType::GET));
+}
+
+// Tests that prerender links don't open the app.
+IN_PROC_BROWSER_TEST_F(BookmarkAppUrlRedirectorBrowserTest, PrerenderLinks) {
+  prerender::PrerenderManager::SetMode(
+      prerender::PrerenderManager::PRERENDER_MODE_ENABLED);
+
+  InstallTestBookmarkApp();
+  NavigateToLaunchingPage();
+
+  TestTabActionDoesNotNavigateOrOpenAppWindow(base::Bind(
+      [](content::WebContents* web_contents, const GURL& target_url) {
+        std::string script = base::StringPrintf(
+            "(() => {"
+            "const prerender_link = document.createElement('link');"
+            "prerender_link.rel = 'prerender';"
+            "prerender_link.href = '%s';"
+            "prerender_link.addEventListener('webkitprerenderstop',"
+            "() => window.domAutomationController.send(true));"
+            "document.body.appendChild(prerender_link);"
+            "})();",
+            target_url.spec().c_str());
+        bool result;
+        ASSERT_TRUE(content::ExecuteScriptAndExtractBool(web_contents, script,
+                                                         &result));
+        ASSERT_TRUE(result);
+      },
+      browser()->tab_strip_model()->GetActiveWebContents(),
+      embedded_test_server()->GetURL(kInScopeUrlPath)));
+}
+
+// Tests fetch calls don't open a new App window.
+IN_PROC_BROWSER_TEST_F(BookmarkAppUrlRedirectorBrowserTest, Fetch) {
+  InstallTestBookmarkApp();
+  NavigateToLaunchingPage();
+
+  TestTabActionDoesNotNavigateOrOpenAppWindow(base::Bind(
+      [](content::WebContents* web_contents, const GURL& target_url) {
+        std::string script = base::StringPrintf(
+            "(() => {"
+            "fetch('%s').then(response => {"
+            "  window.domAutomationController.send(response.ok);"
+            "});"
+            "})();",
+            target_url.spec().c_str());
+        bool result;
+        ASSERT_TRUE(content::ExecuteScriptAndExtractBool(web_contents, script,
+                                                         &result));
+        ASSERT_TRUE(result);
+      },
+      browser()->tab_strip_model()->GetActiveWebContents(),
+      embedded_test_server()->GetURL(kInScopeUrlPath)));
+}
+
+// Tests that clicking "Open link in incognito window" to an in-scope URL opens
+// an incognito window and not an app window.
+IN_PROC_BROWSER_TEST_F(BookmarkAppUrlRedirectorBrowserTest, OpenInIncognito) {
+  InstallTestBookmarkApp();
+  NavigateToLaunchingPage();
+
+  size_t num_browsers = chrome::GetBrowserCount(profile());
+  int num_tabs = browser()->tab_strip_model()->count();
+  content::WebContents* initial_tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  GURL initial_url = initial_tab->GetLastCommittedURL();
+
+  const GURL in_scope_url = embedded_test_server()->GetURL(kInScopeUrlPath);
+  ui_test_utils::UrlLoadObserver url_observer(
+      in_scope_url, content::NotificationService::AllSources());
+  content::ContextMenuParams params;
+  params.page_url = initial_url;
+  params.link_url = in_scope_url;
+  TestRenderViewContextMenu menu(initial_tab->GetMainFrame(), params);
+  menu.Init();
+  menu.ExecuteCommand(IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD,
+                      0 /* event_flags */);
+  url_observer.Wait();
+
+  Browser* incognito_browser = chrome::FindLastActive();
+  EXPECT_EQ(incognito_browser->profile(), profile()->GetOffTheRecordProfile());
+  EXPECT_NE(browser(), incognito_browser);
+  EXPECT_EQ(in_scope_url, incognito_browser->tab_strip_model()
+                              ->GetActiveWebContents()
+                              ->GetLastCommittedURL());
+
+  EXPECT_EQ(num_browsers, chrome::GetBrowserCount(profile()));
+  EXPECT_EQ(num_tabs, browser()->tab_strip_model()->count());
+  EXPECT_EQ(initial_tab, browser()->tab_strip_model()->GetActiveWebContents());
+  EXPECT_EQ(initial_url, initial_tab->GetLastCommittedURL());
+}
+
+// Tests that clicking a link to an in-scope URL when in incognito does not open
+// an App window.
+IN_PROC_BROWSER_TEST_F(BookmarkAppUrlRedirectorBrowserTest,
+                       InScopeUrlIncognito) {
+  InstallTestBookmarkApp();
+  Browser* incognito_browser = CreateIncognitoBrowser();
+  NavigateToLaunchingPage(incognito_browser);
+
+  const GURL in_scope_url = embedded_test_server()->GetURL(kInScopeUrlPath);
+  TestTabActionDoesNotOpenAppWindow(
+      incognito_browser, in_scope_url,
+      base::Bind(&ClickLinkAndWait,
+                 incognito_browser->tab_strip_model()->GetActiveWebContents(),
+                 in_scope_url, LinkTarget::SELF));
+}
+
 // Tests that clicking links inside a website for an installed app doesn't open
 // a new browser window.
 IN_PROC_BROWSER_TEST_F(BookmarkAppUrlRedirectorBrowserTest,
diff --git a/chrome/browser/extensions/content_verifier_browsertest.cc b/chrome/browser/extensions/content_verifier_browsertest.cc
index 256abe8..8b50cff 100644
--- a/chrome/browser/extensions/content_verifier_browsertest.cc
+++ b/chrome/browser/extensions/content_verifier_browsertest.cc
@@ -392,7 +392,7 @@
     visitor_->OnExternalExtensionUpdateUrlFound(
         ExternalInstallInfoUpdateUrl(
             extension_id_, std::string() /* install_parameter */,
-            base::MakeUnique<GURL>(extension_urls::GetWebstoreUpdateUrl()),
+            extension_urls::GetWebstoreUpdateUrl(),
             Manifest::EXTERNAL_POLICY_DOWNLOAD, 0 /* creation_flags */,
             true /* mark_acknowledged */),
         true /* is_initial_load */);
diff --git a/chrome/browser/extensions/display_info_provider_chromeos.cc b/chrome/browser/extensions/display_info_provider_chromeos.cc
index a56cb8ac..c8adf03 100644
--- a/chrome/browser/extensions/display_info_provider_chromeos.cc
+++ b/chrome/browser/extensions/display_info_provider_chromeos.cc
@@ -775,7 +775,7 @@
 bool DisplayInfoProviderChromeOS::ShowNativeTouchCalibration(
     const std::string& id,
     std::string* error,
-    const DisplayInfoProvider::TouchCalibrationCallback& callback) {
+    DisplayInfoProvider::TouchCalibrationCallback callback) {
   if (ash_util::IsRunningInMash()) {
     // TODO(crbug.com/682402): Mash support.
     NOTIMPLEMENTED();
@@ -795,7 +795,8 @@
     return false;
   }
 
-  GetTouchCalibrator()->StartCalibration(display, callback);
+  GetTouchCalibrator()->StartCalibration(
+      display, false /* is_custom_calibration */, std::move(callback));
   return true;
 }
 
@@ -817,8 +818,8 @@
   touch_calibration_target_id_ = id;
   custom_touch_calibration_active_ = true;
 
-  // Enable un-transformed touch input.
-  ash::Shell::Get()->touch_transformer_controller()->SetForCalibration(true);
+  GetTouchCalibrator()->StartCalibration(
+      display, true /* is_custom_calibration */, base::Callback<void(bool)>());
   return true;
 }
 
@@ -881,8 +882,7 @@
   }
 
   gfx::Size display_size(bounds.width, bounds.height);
-  ash::Shell::Get()->display_manager()->SetTouchCalibrationData(
-      display.id(), calibration_points, display_size);
+  GetTouchCalibrator()->CompleteCalibration(calibration_points, display_size);
   return true;
 }
 
@@ -901,14 +901,15 @@
     return false;
   }
 
-  ash::Shell::Get()->display_manager()->ClearTouchCalibrationData(display.id());
+  ash::Shell::Get()->display_manager()->ClearTouchCalibrationData(
+      display.id(), base::nullopt);
   return true;
 }
 
 bool DisplayInfoProviderChromeOS::IsNativeTouchCalibrationActive(
     std::string* error) {
   // If native touch calibration UX is active, set error and return false.
-  if (GetTouchCalibrator()->is_calibrating()) {
+  if (GetTouchCalibrator()->IsCalibrating()) {
     *error = kNativeTouchCalibrationActiveError;
     return true;
   }
diff --git a/chrome/browser/extensions/display_info_provider_chromeos.h b/chrome/browser/extensions/display_info_provider_chromeos.h
index b27e98ab..5535b5db 100644
--- a/chrome/browser/extensions/display_info_provider_chromeos.h
+++ b/chrome/browser/extensions/display_info_provider_chromeos.h
@@ -47,9 +47,9 @@
       const api::system_display::Insets& delta) override;
   bool OverscanCalibrationReset(const std::string& id) override;
   bool OverscanCalibrationComplete(const std::string& id) override;
-  bool ShowNativeTouchCalibration(
-      const std::string& id, std::string* error,
-      const TouchCalibrationCallback& callback) override;
+  bool ShowNativeTouchCalibration(const std::string& id,
+                                  std::string* error,
+                                  TouchCalibrationCallback callback) override;
   bool StartCustomTouchCalibration(const std::string& id,
                                    std::string* error) override;
   bool CompleteCustomTouchCalibration(
diff --git a/chrome/browser/extensions/display_info_provider_chromeos_unittest.cc b/chrome/browser/extensions/display_info_provider_chromeos_unittest.cc
index 17de45c9..472c7ec 100644
--- a/chrome/browser/extensions/display_info_provider_chromeos_unittest.cc
+++ b/chrome/browser/extensions/display_info_provider_chromeos_unittest.cc
@@ -1482,89 +1482,6 @@
   EXPECT_EQ(expected_err, error);
 }
 
-TEST_F(DisplayInfoProviderChromeosTest, CustomTouchCalibrationSuccess) {
-  UpdateDisplay("1200x600,600x1000*2");
-
-  const int64_t internal_display_id =
-      display::test::DisplayManagerTestApi(display_manager())
-          .SetFirstDisplayAsInternalDisplay();
-
-  display::DisplayIdList display_id_list =
-      display_manager()->GetCurrentDisplayIdList();
-
-  // Pick the non internal display Id.
-  const int64_t display_id = display_id_list[0] == internal_display_id
-                                 ? display_id_list[1]
-                                 : display_id_list[0];
-
-  display::test::DisplayManagerTestApi(display_manager())
-      .SetTouchSupport(display_id, display::Display::TOUCH_SUPPORT_AVAILABLE);
-
-  std::string id = base::Int64ToString(display_id);
-
-  api::system_display::TouchCalibrationPairQuad pairs;
-  api::system_display::Bounds bounds;
-
-  pairs.pair1.display_point.x = 10;
-  pairs.pair1.display_point.y = 11;
-  pairs.pair2.display_point.x = 12;
-  pairs.pair2.display_point.y = 13;
-  pairs.pair3.display_point.x = 14;
-  pairs.pair3.display_point.y = 15;
-  pairs.pair4.display_point.x = 16;
-  pairs.pair4.display_point.y = 17;
-
-  pairs.pair1.touch_point.x = 20;
-  pairs.pair1.touch_point.y = 21;
-  pairs.pair2.touch_point.x = 22;
-  pairs.pair2.touch_point.y = 23;
-  pairs.pair3.touch_point.x = 24;
-  pairs.pair3.touch_point.y = 25;
-  pairs.pair4.touch_point.x = 26;
-  pairs.pair4.touch_point.y = 27;
-
-  bounds.width = 600;
-  bounds.height = 1000;
-
-  std::string error;
-  DisplayInfoProvider::Get()->StartCustomTouchCalibration(id, &error);
-  error.clear();
-  bool success = DisplayInfoProvider::Get()->CompleteCustomTouchCalibration(
-      pairs, bounds, &error);
-
-  ASSERT_TRUE(success);
-  EXPECT_EQ(error, "");
-
-  const display::ManagedDisplayInfo& info =
-      display_manager()->GetDisplayInfo(display_id);
-
-  ASSERT_TRUE(info.has_touch_calibration_data());
-  const display::TouchCalibrationData& data = info.GetTouchCalibrationData();
-
-  EXPECT_EQ(pairs.pair1.display_point.x, data.point_pairs[0].first.x());
-  EXPECT_EQ(pairs.pair2.display_point.x, data.point_pairs[1].first.x());
-  EXPECT_EQ(pairs.pair3.display_point.x, data.point_pairs[2].first.x());
-  EXPECT_EQ(pairs.pair4.display_point.x, data.point_pairs[3].first.x());
-
-  EXPECT_EQ(pairs.pair1.display_point.y, data.point_pairs[0].first.y());
-  EXPECT_EQ(pairs.pair2.display_point.y, data.point_pairs[1].first.y());
-  EXPECT_EQ(pairs.pair3.display_point.y, data.point_pairs[2].first.y());
-  EXPECT_EQ(pairs.pair4.display_point.y, data.point_pairs[3].first.y());
-
-  EXPECT_EQ(pairs.pair1.touch_point.x, data.point_pairs[0].second.x());
-  EXPECT_EQ(pairs.pair2.touch_point.x, data.point_pairs[1].second.x());
-  EXPECT_EQ(pairs.pair3.touch_point.x, data.point_pairs[2].second.x());
-  EXPECT_EQ(pairs.pair4.touch_point.x, data.point_pairs[3].second.x());
-
-  EXPECT_EQ(pairs.pair1.touch_point.y, data.point_pairs[0].second.y());
-  EXPECT_EQ(pairs.pair2.touch_point.y, data.point_pairs[1].second.y());
-  EXPECT_EQ(pairs.pair3.touch_point.y, data.point_pairs[2].second.y());
-  EXPECT_EQ(pairs.pair4.touch_point.y, data.point_pairs[3].second.y());
-
-  EXPECT_EQ(bounds.width, data.bounds.width());
-  EXPECT_EQ(bounds.height, data.bounds.height());
-}
-
 class DisplayInfoProviderChromeosTouchviewTest
     : public DisplayInfoProviderChromeosTest {
  public:
diff --git a/chrome/browser/extensions/extension_messages_apitest.cc b/chrome/browser/extensions/extension_messages_apitest.cc
index c1c7d15..e49021c1 100644
--- a/chrome/browser/extensions/extension_messages_apitest.cc
+++ b/chrome/browser/extensions/extension_messages_apitest.cc
@@ -1326,6 +1326,12 @@
   EXPECT_EQ(1, message_count);
 }
 
+// Tests that messages over a certain size are not sent.
+// https://crbug.com/766713.
+IN_PROC_BROWSER_TEST_F(MessagingApiTest, LargeMessages) {
+  ASSERT_TRUE(RunExtensionTest("messaging/large_messages"));
+}
+
 }  // namespace
 
 };  // namespace extensions
diff --git a/chrome/browser/extensions/extension_modules_apitest.cc b/chrome/browser/extensions/extension_modules_apitest.cc
new file mode 100644
index 0000000..39ed408
--- /dev/null
+++ b/chrome/browser/extensions/extension_modules_apitest.cc
@@ -0,0 +1,11 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/extension_apitest.h"
+
+using ExtensionModuleTest = ExtensionApiTest;
+
+IN_PROC_BROWSER_TEST_F(ExtensionModuleTest, TestModulesAvailable) {
+  ASSERT_TRUE(RunExtensionTest("modules")) << message_;
+}
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 66404cb..612e3f7c 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -76,6 +76,7 @@
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_file_task_runner.h"
 #include "extensions/browser/extension_host.h"
+#include "extensions/browser/extension_registrar.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/browser/extension_util.h"
@@ -83,7 +84,6 @@
 #include "extensions/browser/external_install_info.h"
 #include "extensions/browser/install_flag.h"
 #include "extensions/browser/lazy_background_task_queue.h"
-#include "extensions/browser/renderer_startup_helper.h"
 #include "extensions/browser/runtime_data.h"
 #include "extensions/browser/uninstall_reason.h"
 #include "extensions/browser/update_observer.h"
@@ -236,7 +236,7 @@
   // install source.  In this case, signal that this extension will not be
   // installed by returning false.
   if (!pending_extension_manager()->AddFromExternalUpdateUrl(
-          info.extension_id, info.install_parameter, *info.update_url,
+          info.extension_id, info.install_parameter, info.update_url,
           info.download_location, info.creation_flags,
           info.mark_acknowledged)) {
     return false;
@@ -331,10 +331,9 @@
       extensions_enabled_(extensions_enabled),
       ready_(ready),
       shared_module_service_(new extensions::SharedModuleService(profile_)),
-      renderer_helper_(
-          extensions::RendererStartupHelperFactory::GetForBrowserContext(
-              profile_)),
-      app_data_migrator_(new extensions::AppDataMigrator(profile_, registry_)) {
+      app_data_migrator_(new extensions::AppDataMigrator(profile_, registry_)),
+      extension_registrar_(
+          std::make_unique<extensions::ExtensionRegistrar>(profile_)) {
   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   TRACE_EVENT0("browser,startup", "ExtensionService::ExtensionService::ctor");
 
@@ -900,11 +899,12 @@
   if (IsExtensionEnabled(extension_id) ||
       extension_prefs_->IsExtensionBlacklisted(extension_id))
     return;
-  const Extension* extension =
+  scoped_refptr<const Extension> extension =
       registry_->disabled_extensions().GetByID(extension_id);
 
   ManagementPolicy* policy = system_->management_policy();
-  if (extension && policy->MustRemainDisabled(extension, nullptr, nullptr)) {
+  if (extension &&
+      policy->MustRemainDisabled(extension.get(), nullptr, nullptr)) {
     UMA_HISTOGRAM_COUNTS_100("Extensions.EnableDeniedByPolicy", 1);
     return;
   }
@@ -916,12 +916,10 @@
     return;
 
   // Move it over to the enabled list.
-  registry_->AddEnabled(make_scoped_refptr(extension));
-  registry_->RemoveDisabled(extension->id());
+  extension_registrar_->EnableExtension(extension);
+  NotifyExtensionLoaded(extension.get());
 
-  NotifyExtensionLoaded(extension);
-
-  MaybeSpinUpLazyBackgroundPage(extension);
+  MaybeSpinUpLazyBackgroundPage(extension.get());
 }
 
 void ExtensionService::DisableExtension(const std::string& extension_id,
@@ -980,11 +978,11 @@
 
   // Move it over to the disabled list. Don't send a second unload notification
   // for terminated extensions being disabled.
-  registry_->AddDisabled(make_scoped_refptr(extension));
   if (registry_->enabled_extensions().Contains(extension->id())) {
-    registry_->RemoveEnabled(extension->id());
-    NotifyExtensionUnloaded(extension, UnloadedExtensionReason::DISABLE);
+    extension_registrar_->DisableExtension(extension);
+    PostDeactivateExtension(extension);
   } else {
+    registry_->AddDisabled(make_scoped_refptr(extension));
     registry_->RemoveTerminated(extension->id());
   }
 }
@@ -1096,28 +1094,6 @@
 }
 
 void ExtensionService::NotifyExtensionLoaded(const Extension* extension) {
-  // The URLRequestContexts need to be first to know that the extension
-  // was loaded, otherwise a race can arise where a renderer that is created
-  // for the extension may try to load an extension URL with an extension id
-  // that the request context doesn't yet know about. The profile is responsible
-  // for ensuring its URLRequestContexts appropriately discover the loaded
-  // extension.
-  system_->RegisterExtensionWithRequestContexts(
-      extension,
-      base::Bind(&ExtensionService::OnExtensionRegisteredWithRequestContexts,
-                 AsWeakPtr(), make_scoped_refptr(extension)));
-
-  renderer_helper_->OnExtensionLoaded(*extension);
-
-  // Tell subsystems that use the ExtensionRegistryObserver::OnExtensionLoaded
-  // about the new extension.
-  //
-  // NOTE: It is important that this happen after notifying the renderers about
-  // the new extensions so that if we navigate to an extension URL in
-  // ExtensionRegistryObserver::OnExtensionLoaded the renderer is guaranteed to
-  // know about it.
-  registry_->TriggerOnLoaded(extension);
-
   // TODO(kalman): Convert ExtensionSpecialStoragePolicy to a
   // BrowserContextKeyedService and use ExtensionRegistryObserver.
   profile_->GetExtensionSpecialStoragePolicy()->
@@ -1153,25 +1129,12 @@
   }
 }
 
-void ExtensionService::OnExtensionRegisteredWithRequestContexts(
-    scoped_refptr<const extensions::Extension> extension) {
-  registry_->AddReady(extension);
-  if (registry_->enabled_extensions().Contains(extension->id()))
-    registry_->TriggerOnReady(extension.get());
-}
-
-void ExtensionService::NotifyExtensionUnloaded(const Extension* extension,
-                                               UnloadedExtensionReason reason) {
-  registry_->TriggerOnUnloaded(extension, reason);
-
-  renderer_helper_->OnExtensionUnloaded(*extension);
-
-  system_->UnregisterExtensionWithRequestContexts(extension->id(), reason);
-
+void ExtensionService::PostDeactivateExtension(
+    scoped_refptr<const Extension> extension) {
   // TODO(kalman): Convert ExtensionSpecialStoragePolicy to a
   // BrowserContextKeyedService and use ExtensionRegistryObserver.
-  profile_->GetExtensionSpecialStoragePolicy()->
-      RevokeRightsForExtension(extension);
+  profile_->GetExtensionSpecialStoragePolicy()->RevokeRightsForExtension(
+      extension.get());
 
 #if defined(OS_CHROMEOS)
   // Revoke external file access for the extension from its file system context.
@@ -1375,42 +1338,37 @@
 
 void ExtensionService::UnloadExtension(const std::string& extension_id,
                                        UnloadedExtensionReason reason) {
-  // Make sure the extension gets deleted after we return from this function.
   int include_mask =
       ExtensionRegistry::EVERYTHING & ~ExtensionRegistry::TERMINATED;
   scoped_refptr<const Extension> extension(
       registry_->GetExtensionById(extension_id, include_mask));
 
-  // This method can be called via PostTask, so the extension may have been
-  // unloaded by the time this runs.
-  if (!extension.get()) {
-    // In case the extension may have crashed/uninstalled. Allow the profile to
-    // clean up its RequestContexts.
-    system_->UnregisterExtensionWithRequestContexts(extension_id, reason);
+  // TODO(michaelpg): Move this block to ExtensionRegistrar once it learns to
+  // reload extensions.
+  if (extension) {
+    // Keep information about the extension so that we can reload it later
+    // even if it's not permanently installed.
+    unloaded_extension_paths_[extension->id()] = extension->path();
+
+    // Clean up if the extension is meant to be enabled after a reload.
+    reloading_extensions_.erase(extension->id());
+  }
+
+  bool already_disabled =
+      registry_->disabled_extensions().Contains(extension_id);
+  extension_registrar_->RemoveExtension(extension_id, reason);
+
+  // If the extension was only in the terminated set, the removal notification
+  // will be sent when UntrackTerminatedExtension is called.
+  if (!extension)
     return;
-  }
 
-  // Keep information about the extension so that we can reload it later
-  // even if it's not permanently installed.
-  unloaded_extension_paths_[extension->id()] = extension->path();
+  if (!already_disabled)
+    PostDeactivateExtension(extension);
 
-  // Clean up if the extension is meant to be enabled after a reload.
-  reloading_extensions_.erase(extension->id());
-
-  if (registry_->disabled_extensions().Contains(extension->id())) {
-    registry_->RemoveDisabled(extension->id());
-    // Make sure the profile cleans up its RequestContexts when an already
-    // disabled extension is unloaded (since they are also tracking the disabled
-    // extensions).
-    system_->UnregisterExtensionWithRequestContexts(extension_id, reason);
-    // Don't send the unloaded notification. It was sent when the extension
-    // was disabled.
-  } else {
-    // Remove the extension from the enabled list.
-    registry_->RemoveEnabled(extension->id());
-    NotifyExtensionUnloaded(extension.get(), reason);
-  }
-
+  // TODO(michaelpg): Move to ExtensionRegistrar::RemoveExtension() once that
+  // can call PostDeactivateExtension() on a delegate. For now, keep this here
+  // so it runs in the same order.
   content::NotificationService::current()->Notify(
       extensions::NOTIFICATION_EXTENSION_REMOVED,
       content::Source<Profile>(profile_),
@@ -1500,7 +1458,8 @@
     if (!Manifest::IsUnpackedLocation(extension->location()))
       CHECK_GE(version_compare_result, 0);
   }
-  // If the extension was disabled for a reload, then enable it.
+
+  // If the extension was disabled for a reload, we will enable it.
   bool reloading = reloading_extensions_.erase(extension->id()) > 0;
 
   // Set the upgraded bit; we consider reloads upgrades.
@@ -1569,7 +1528,7 @@
                                        syncer::StringOrdinal());
     }
 
-    registry_->AddEnabled(extension);
+    extension_registrar_->EnableExtension(extension);
     NotifyExtensionLoaded(extension);
   }
   system_->runtime_data()->SetBeingUpgraded(extension->id(), false);
@@ -2099,9 +2058,7 @@
          Manifest::IsExternalLocation(existing->location()));
 
     if (!is_default_apps_migration) {
-      DCHECK(info.version.get());
-
-      switch (existing->version()->CompareTo(*info.version)) {
+      switch (existing->version()->CompareTo(info.version)) {
         case -1:  // existing version is older, we should upgrade
           break;
         case 0:  // existing version is same, do nothing
@@ -2111,7 +2068,7 @@
                        << info.extension_id
                        << "that is older than current version. Current version "
                        << "is: " << existing->VersionString() << ". New "
-                       << "version is: " << info.version->GetString()
+                       << "version is: " << info.version.GetString()
                        << ". Keeping current version.";
           return false;
       }
@@ -2120,7 +2077,7 @@
 
   // If the extension is already pending, don't start an install.
   if (!pending_extension_manager()->AddFromExternalFile(
-          info.extension_id, info.crx_location, *info.version,
+          info.extension_id, info.crx_location, info.version,
           info.creation_flags, info.mark_acknowledged)) {
     return false;
   }
@@ -2129,7 +2086,7 @@
   scoped_refptr<CrxInstaller> installer(CrxInstaller::CreateSilent(this));
   installer->set_install_source(info.crx_location);
   installer->set_expected_id(info.extension_id);
-  installer->set_expected_version(*info.version,
+  installer->set_expected_version(info.version,
                                   true /* fail_install_if_unexpected */);
   installer->set_install_cause(extension_misc::INSTALL_CAUSE_EXTERNAL_FILE);
   installer->set_install_immediately(info.install_immediately);
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index a9bfaca1..a6b157e 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -58,12 +58,12 @@
 class CrxInstaller;
 class ExtensionActionStorageManager;
 class ExtensionErrorController;
+class ExtensionRegistrar;
 class ExtensionRegistry;
 class ExtensionSystem;
 class ExtensionUpdater;
 class ExternalInstallManager;
 class OneShotEvent;
-class RendererStartupHelper;
 class SharedModuleService;
 class UpdateObserver;
 }  // namespace extensions
@@ -150,7 +150,9 @@
   virtual void CheckForUpdatesSoon() = 0;
 
   // Adds |extension| to this ExtensionService and notifies observers that the
-  // extensions have been loaded.
+  // extension has been loaded.
+  // TODO(michaelpg): Refactor this function into single-purpose functions and
+  // migrate common code into ExtensionRegistrar.
   virtual void AddExtension(const extensions::Extension* extension) = 0;
 
   // Check if we have preferences for the component extension and, if not or if
@@ -515,17 +517,16 @@
                                 const std::string& install_parameter);
 
   // Handles sending notification that |extension| was loaded.
+  // TODO(michaelpg): Move to a delegate provided to ExtensionRegistrar, so
+  // ExtensionRegistrar is responsible for calling this at the right times.
   void NotifyExtensionLoaded(const extensions::Extension* extension);
 
-  // Completes extension loading after URLRequestContexts have been updated
-  // on the IO thread.
-  void OnExtensionRegisteredWithRequestContexts(
+  // Handles updating the profile when |extension| is disabled or removed.
+  // TODO(michaelpg): Move to a delegate provided to ExtensionRegistrar, so
+  // ExtensionRegistrar is responsible for calling this at the right times.
+  void PostDeactivateExtension(
       scoped_refptr<const extensions::Extension> extension);
 
-  // Handles sending notification that |extension| was unloaded.
-  void NotifyExtensionUnloaded(const extensions::Extension* extension,
-                               extensions::UnloadedExtensionReason reason);
-
   // Common helper to finish installing the given extension.
   void FinishInstallation(const extensions::Extension* extension);
 
@@ -719,15 +720,14 @@
   // The SharedModuleService used to check for import dependencies.
   std::unique_ptr<extensions::SharedModuleService> shared_module_service_;
 
-  // The associated RendererStartupHelper. Guaranteed to outlive the
-  // ExtensionSystem, and thus us.
-  extensions::RendererStartupHelper* renderer_helper_;
-
   base::ObserverList<extensions::UpdateObserver, true> update_observers_;
 
   // Migrates app data when upgrading a legacy packaged app to a platform app
   std::unique_ptr<extensions::AppDataMigrator> app_data_migrator_;
 
+  // Helper to register and unregister extensions.
+  std::unique_ptr<extensions::ExtensionRegistrar> extension_registrar_;
+
   using InstallGateRegistry = std::map<extensions::ExtensionPrefs::DelayReason,
                                        extensions::InstallGate*>;
   InstallGateRegistry install_delayer_registry_;
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index 55684e9..6a10015 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -277,8 +277,8 @@
     Manifest::Location location,
     Extension::InitFromValueFlags flags) {
   return base::MakeUnique<ExternalInstallInfoFile>(
-      extension_id, base::MakeUnique<base::Version>(version_str), path,
-      location, flags, false, false);
+      extension_id, base::Version(version_str), path, location, flags, false,
+      false);
 }
 
 // Helper function to persist the passed directories and file paths in
@@ -422,13 +422,13 @@
       base::FilePath crx_path;
 
       EXPECT_TRUE(provider_->GetExtensionDetails(info.extension_id, NULL, &v1));
-      EXPECT_STREQ(info.version->GetString().c_str(), v1->GetString().c_str());
+      EXPECT_EQ(info.version.GetString(), v1->GetString());
 
       std::unique_ptr<base::Version> v2;
       EXPECT_TRUE(
           provider_->GetExtensionDetails(info.extension_id, &location, &v2));
-      EXPECT_STREQ(info.version->GetString().c_str(), v1->GetString().c_str());
-      EXPECT_STREQ(info.version->GetString().c_str(), v2->GetString().c_str());
+      EXPECT_EQ(info.version.GetString(), v1->GetString());
+      EXPECT_EQ(info.version.GetString(), v2->GetString());
       EXPECT_EQ(crx_location_, location);
 
       // Remove it so we won't count it ever again.
@@ -4487,12 +4487,12 @@
   base::FilePath path = data_dir().AppendASCII("good.crx");
 
   // Register and install an external extension.
-  std::unique_ptr<base::Version> version(new base::Version("1.0.0.0"));
+  base::Version version("1.0.0.0");
   content::WindowedNotificationObserver observer(
       extensions::NOTIFICATION_CRX_INSTALLER_DONE,
       content::NotificationService::AllSources());
   std::unique_ptr<ExternalInstallInfoFile> info(new ExternalInstallInfoFile(
-      good_crx, std::move(version), path, Manifest::EXTERNAL_PREF,
+      good_crx, version, path, Manifest::EXTERNAL_PREF,
       Extension::FROM_BOOKMARK, false /* mark_acknowledged */,
       false /* install_immediately */));
   ASSERT_TRUE(service()->OnExternalExtensionFileFound(*info));
@@ -5988,7 +5988,7 @@
   EXPECT_FALSE(pending->IsIdPending(kGoodId));
 
   // Skip install when the location is the same.
-  std::unique_ptr<GURL> good_update_url(new GURL(kGoodUpdateURL));
+  GURL good_update_url(kGoodUpdateURL);
   std::unique_ptr<ExternalInstallInfoUpdateUrl> info(
       new ExternalInstallInfoUpdateUrl(
           kGoodId, std::string(), std::move(good_update_url),
@@ -6051,12 +6051,9 @@
       service()->pending_extension_manager();
   EXPECT_FALSE(pending->IsIdPending(kGoodId));
 
-  std::unique_ptr<base::Version> older_version_ptr(
-      new base::Version(older_version));
   std::unique_ptr<ExternalInstallInfoFile> info(new ExternalInstallInfoFile(
-      kGoodId, std::move(older_version_ptr), kInvalidPathToCrx,
-      Manifest::INTERNAL, kCreationFlags, kDontMarkAcknowledged,
-      kDontInstallImmediately));
+      kGoodId, older_version, kInvalidPathToCrx, Manifest::INTERNAL,
+      kCreationFlags, kDontMarkAcknowledged, kDontInstallImmediately));
   {
     // Simulate an external source adding the extension as INTERNAL.
     content::WindowedNotificationObserver observer(
@@ -6133,29 +6130,29 @@
   // older, or the same, and succeed if the version is newer.
 
   // Older than the installed version...
-  info->version.reset(new base::Version(older_version));
+  info->version = older_version;
   EXPECT_FALSE(service()->OnExternalExtensionFileFound(*info));
   EXPECT_FALSE(pending->IsIdPending(kGoodId));
 
   // Same version as the installed version...
-  info->version.reset(new base::Version(ext->VersionString()));
+  info->version = *ext->version();
   EXPECT_FALSE(service()->OnExternalExtensionFileFound(*info));
   EXPECT_FALSE(pending->IsIdPending(kGoodId));
 
   // Newer than the installed version...
-  info->version.reset(new base::Version(newer_version));
+  info->version = newer_version;
   EXPECT_TRUE(service()->OnExternalExtensionFileFound(*info));
   EXPECT_TRUE(pending->IsIdPending(kGoodId));
 
   // An external install for a higher priority install source should succeed
   // if the version is greater.  |older_version| is not...
-  info->version.reset(new base::Version(older_version));
+  info->version = older_version;
   info->crx_location = Manifest::EXTERNAL_PREF;
   EXPECT_FALSE(service()->OnExternalExtensionFileFound(*info));
   EXPECT_TRUE(pending->IsIdPending(kGoodId));
 
   // |newer_version| is newer.
-  info->version.reset(new base::Version(newer_version));
+  info->version = newer_version;
   EXPECT_TRUE(service()->OnExternalExtensionFileFound(*info));
   EXPECT_TRUE(pending->IsIdPending(kGoodId));
 
@@ -6189,9 +6186,8 @@
 
   // An external provider starts installing from a local crx.
   std::unique_ptr<ExternalInstallInfoFile> info(new ExternalInstallInfoFile(
-      kGoodId, base::MakeUnique<base::Version>(kVersion123),
-      kInvalidPathToCrx, Manifest::EXTERNAL_PREF, kCreationFlags,
-      kDontMarkAcknowledged, kDontInstallImmediately));
+      kGoodId, kVersion123, kInvalidPathToCrx, Manifest::EXTERNAL_PREF,
+      kCreationFlags, kDontMarkAcknowledged, kDontInstallImmediately));
   EXPECT_TRUE(service()->OnExternalExtensionFileFound(*info));
 
   const extensions::PendingExtensionInfo* pending_info;
@@ -6200,14 +6196,14 @@
   EXPECT_EQ(pending_info->version(), kVersion123);
 
   // Adding a newer version overrides the currently pending version.
-  info->version.reset(new base::Version(kVersion124));
+  info->version = kVersion124;
   EXPECT_TRUE(service()->OnExternalExtensionFileFound(*info));
   EXPECT_TRUE((pending_info = pending->GetById(kGoodId)));
   EXPECT_TRUE(pending_info->version().IsValid());
   EXPECT_EQ(pending_info->version(), kVersion124);
 
   // Adding an older version fails.
-  info->version.reset(new base::Version(kVersion123));
+  info->version = kVersion123;
   EXPECT_FALSE(service()->OnExternalExtensionFileFound(*info));
   EXPECT_TRUE((pending_info = pending->GetById(kGoodId)));
   EXPECT_TRUE(pending_info->version().IsValid());
@@ -6222,10 +6218,9 @@
   EXPECT_EQ(pending_info->version(), kVersion124);
 
   // Adding the latest version from the webstore overrides a specific version.
-  GURL kUpdateUrl("http://example.com/update");
   std::unique_ptr<ExternalInstallInfoUpdateUrl> update_info(
       new ExternalInstallInfoUpdateUrl(
-          kGoodId, std::string(), base::MakeUnique<GURL>(kUpdateUrl),
+          kGoodId, std::string(), GURL("http://example.com/update"),
           Manifest::EXTERNAL_POLICY_DOWNLOAD, Extension::NO_FLAGS, false));
   EXPECT_TRUE(service()->OnExternalExtensionUpdateUrlFound(*update_info, true));
   EXPECT_TRUE((pending_info = pending->GetById(kGoodId)));
@@ -6280,9 +6275,8 @@
 
   // Fake an external file from external_extensions.json.
   bool AddPendingExternalPrefFileInstall() {
-    std::unique_ptr<base::Version> version(new base::Version("1.0.0.0"));
     std::unique_ptr<ExternalInstallInfoFile> info(new ExternalInstallInfoFile(
-        crx_id_, std::move(version), crx_path_, Manifest::EXTERNAL_PREF,
+        crx_id_, base::Version("1.0.0.0"), crx_path_, Manifest::EXTERNAL_PREF,
         Extension::NO_FLAGS, false, false));
     return service()->OnExternalExtensionFileFound(*info);
   }
@@ -6300,11 +6294,10 @@
   // Fake a policy install.
   bool AddPendingPolicyInstall() {
     // Get path to the CRX with id |kGoodId|.
-    std::unique_ptr<GURL> empty_url(new GURL());
     std::unique_ptr<ExternalInstallInfoUpdateUrl> info(
-        new ExternalInstallInfoUpdateUrl(
-            crx_id_, std::string(), std::move(empty_url),
-            Manifest::EXTERNAL_POLICY_DOWNLOAD, Extension::NO_FLAGS, false));
+        new ExternalInstallInfoUpdateUrl(crx_id_, std::string(), GURL(),
+                                         Manifest::EXTERNAL_POLICY_DOWNLOAD,
+                                         Extension::NO_FLAGS, false));
     return service()->OnExternalExtensionUpdateUrlFound(*info, true);
   }
 
diff --git a/chrome/browser/extensions/external_provider_impl.cc b/chrome/browser/extensions/external_provider_impl.cc
index a0379e9..902455638 100644
--- a/chrome/browser/extensions/external_provider_impl.cc
+++ b/chrome/browser/extensions/external_provider_impl.cc
@@ -384,9 +384,8 @@
         path = base_path.Append(external_crx);
       }
 
-      std::unique_ptr<base::Version> version(
-          new base::Version(external_version));
-      if (!version->IsValid()) {
+      base::Version version(external_version);
+      if (!version.IsValid()) {
         LOG(WARNING) << "Malformed extension dictionary for extension: "
                      << extension_id.c_str() << ".  Invalid version string \""
                      << external_version << "\".";
@@ -394,8 +393,8 @@
       }
       external_file_extensions->push_back(
           base::MakeUnique<ExternalInstallInfoFile>(
-              extension_id, std::move(version), path, crx_location_,
-              creation_flags, auto_acknowledge_, install_immediately_));
+              extension_id, version, path, crx_location_, creation_flags,
+              auto_acknowledge_, install_immediately_));
     } else {  // if (has_external_update_url)
       CHECK(has_external_update_url);  // Checking of keys above ensures this.
       if (download_location_ == Manifest::INVALID_LOCATION) {
@@ -403,8 +402,8 @@
                      << "extensions from update URLs.";
         continue;
       }
-      std::unique_ptr<GURL> update_url(new GURL(external_update_url));
-      if (!update_url->is_valid()) {
+      GURL update_url(external_update_url);
+      if (!update_url.is_valid()) {
         LOG(WARNING) << "Malformed extension dictionary for extension: "
                      << extension_id.c_str() << ".  Key " << kExternalUpdateUrl
                      << " has value \"" << external_update_url
diff --git a/chrome/browser/extensions/isolated_app_browsertest.cc b/chrome/browser/extensions/isolated_app_browsertest.cc
index 71f8f2b..90f06b5 100644
--- a/chrome/browser/extensions/isolated_app_browsertest.cc
+++ b/chrome/browser/extensions/isolated_app_browsertest.cc
@@ -484,25 +484,42 @@
   // We should now have four tabs, the first and third sharing a process.
   // The second one is an independent instance in a separate process.
   ASSERT_EQ(4, browser()->tab_strip_model()->count());
-  int process_id_0 = browser()->tab_strip_model()->GetWebContentsAt(0)->
-      GetRenderProcessHost()->GetID();
-  int process_id_1 = browser()->tab_strip_model()->GetWebContentsAt(1)->
-      GetRenderProcessHost()->GetID();
+  int process_id_0 = browser()
+                         ->tab_strip_model()
+                         ->GetWebContentsAt(0)
+                         ->GetMainFrame()
+                         ->GetProcess()
+                         ->GetID();
+  int process_id_1 = browser()
+                         ->tab_strip_model()
+                         ->GetWebContentsAt(1)
+                         ->GetMainFrame()
+                         ->GetProcess()
+                         ->GetID();
   EXPECT_NE(process_id_0, process_id_1);
-  EXPECT_EQ(process_id_0,
-            browser()->tab_strip_model()->GetWebContentsAt(2)->
-                GetRenderProcessHost()->GetID());
-  EXPECT_NE(process_id_0,
-            browser()->tab_strip_model()->GetWebContentsAt(3)->
-                GetRenderProcessHost()->GetID());
+  EXPECT_EQ(process_id_0, browser()
+                              ->tab_strip_model()
+                              ->GetWebContentsAt(2)
+                              ->GetMainFrame()
+                              ->GetProcess()
+                              ->GetID());
+  EXPECT_NE(process_id_0, browser()
+                              ->tab_strip_model()
+                              ->GetWebContentsAt(3)
+                              ->GetMainFrame()
+                              ->GetProcess()
+                              ->GetID());
 
   // Navigating the second tab out of the app should cause a process swap.
   const GURL& non_app_url(base_url.Resolve("non_app/main.html"));
   NavigateInRenderer(browser()->tab_strip_model()->GetWebContentsAt(1),
                      non_app_url);
-  EXPECT_NE(process_id_1,
-            browser()->tab_strip_model()->GetWebContentsAt(1)->
-                GetRenderProcessHost()->GetID());
+  EXPECT_NE(process_id_1, browser()
+                              ->tab_strip_model()
+                              ->GetWebContentsAt(1)
+                              ->GetMainFrame()
+                              ->GetProcess()
+                              ->GetID());
 }
 
 // This test no longer passes, since we don't properly isolate sessionStorage
diff --git a/chrome/browser/extensions/process_management_browsertest.cc b/chrome/browser/extensions/process_management_browsertest.cc
index 44b868f..24bd9f3 100644
--- a/chrome/browser/extensions/process_management_browsertest.cc
+++ b/chrome/browser/extensions/process_management_browsertest.cc
@@ -165,26 +165,53 @@
 
   // Get tab processes.
   ASSERT_EQ(9, browser()->tab_strip_model()->count());
-  content::RenderProcessHost* isolated1_host =
-      browser()->tab_strip_model()->GetWebContentsAt(0)->GetRenderProcessHost();
-  content::RenderProcessHost* ntp1_host =
-      browser()->tab_strip_model()->GetWebContentsAt(1)->GetRenderProcessHost();
-  content::RenderProcessHost* hosted1_host =
-      browser()->tab_strip_model()->GetWebContentsAt(2)->GetRenderProcessHost();
-  content::RenderProcessHost* web1_host =
-      browser()->tab_strip_model()->GetWebContentsAt(3)->GetRenderProcessHost();
+  content::RenderProcessHost* isolated1_host = browser()
+                                                   ->tab_strip_model()
+                                                   ->GetWebContentsAt(0)
+                                                   ->GetMainFrame()
+                                                   ->GetProcess();
+  content::RenderProcessHost* ntp1_host = browser()
+                                              ->tab_strip_model()
+                                              ->GetWebContentsAt(1)
+                                              ->GetMainFrame()
+                                              ->GetProcess();
+  content::RenderProcessHost* hosted1_host = browser()
+                                                 ->tab_strip_model()
+                                                 ->GetWebContentsAt(2)
+                                                 ->GetMainFrame()
+                                                 ->GetProcess();
+  content::RenderProcessHost* web1_host = browser()
+                                              ->tab_strip_model()
+                                              ->GetWebContentsAt(3)
+                                              ->GetMainFrame()
+                                              ->GetProcess();
 
-  content::RenderProcessHost* isolated2_host =
-      browser()->tab_strip_model()->GetWebContentsAt(4)->GetRenderProcessHost();
-  content::RenderProcessHost* ntp2_host =
-      browser()->tab_strip_model()->GetWebContentsAt(5)->GetRenderProcessHost();
-  content::RenderProcessHost* hosted2_host =
-      browser()->tab_strip_model()->GetWebContentsAt(6)->GetRenderProcessHost();
-  content::RenderProcessHost* web2_host =
-      browser()->tab_strip_model()->GetWebContentsAt(7)->GetRenderProcessHost();
+  content::RenderProcessHost* isolated2_host = browser()
+                                                   ->tab_strip_model()
+                                                   ->GetWebContentsAt(4)
+                                                   ->GetMainFrame()
+                                                   ->GetProcess();
+  content::RenderProcessHost* ntp2_host = browser()
+                                              ->tab_strip_model()
+                                              ->GetWebContentsAt(5)
+                                              ->GetMainFrame()
+                                              ->GetProcess();
+  content::RenderProcessHost* hosted2_host = browser()
+                                                 ->tab_strip_model()
+                                                 ->GetWebContentsAt(6)
+                                                 ->GetMainFrame()
+                                                 ->GetProcess();
+  content::RenderProcessHost* web2_host = browser()
+                                              ->tab_strip_model()
+                                              ->GetWebContentsAt(7)
+                                              ->GetMainFrame()
+                                              ->GetProcess();
 
-  content::RenderProcessHost* second_isolated1_host =
-      browser()->tab_strip_model()->GetWebContentsAt(8)->GetRenderProcessHost();
+  content::RenderProcessHost* second_isolated1_host = browser()
+                                                          ->tab_strip_model()
+                                                          ->GetWebContentsAt(8)
+                                                          ->GetMainFrame()
+                                                          ->GetProcess();
 
   // Get extension processes.
   extensions::ProcessManager* process_manager =
diff --git a/chrome/browser/extensions/process_manager_browsertest.cc b/chrome/browser/extensions/process_manager_browsertest.cc
index b8b6fd4..7aeea7a0 100644
--- a/chrome/browser/extensions/process_manager_browsertest.cc
+++ b/chrome/browser/extensions/process_manager_browsertest.cc
@@ -1001,9 +1001,9 @@
   content::ChildProcessSecurityPolicy* policy =
       content::ChildProcessSecurityPolicy::GetInstance();
   EXPECT_FALSE(policy->HasSpecificPermissionForOrigin(
-      web_tab->GetRenderProcessHost()->GetID(), app_origin));
+      web_tab->GetMainFrame()->GetProcess()->GetID(), app_origin));
   EXPECT_TRUE(policy->HasSpecificPermissionForOrigin(
-      guest->GetRenderProcessHost()->GetID(), app_origin));
+      guest->GetMainFrame()->GetProcess()->GetID(), app_origin));
 
   // Try navigating the web tab to each nested URL with the app's origin.  This
   // should be blocked.
@@ -1126,7 +1126,7 @@
   content::WebContents* popup = OpenPopup(main_frame, popup_url);
   EXPECT_NE(popup, tab);
   ASSERT_EQ(2, browser()->tab_strip_model()->count());
-  EXPECT_NE(popup->GetRenderProcessHost(), main_frame->GetProcess());
+  EXPECT_NE(popup->GetMainFrame()->GetProcess(), main_frame->GetProcess());
 
   // Ensure the popup's window.opener is defined.
   bool is_opener_defined = false;
@@ -1174,8 +1174,8 @@
   content::WebContents* popup = OpenPopup(extension_frame, popup_url);
   EXPECT_NE(popup, tab);
   ASSERT_EQ(2, browser()->tab_strip_model()->count());
-  EXPECT_NE(popup->GetRenderProcessHost(), extension_frame->GetProcess());
-  EXPECT_EQ(popup->GetRenderProcessHost(), main_frame->GetProcess());
+  EXPECT_NE(popup->GetMainFrame()->GetProcess(), extension_frame->GetProcess());
+  EXPECT_EQ(popup->GetMainFrame()->GetProcess(), main_frame->GetProcess());
 
   // Ensure the popup's window.opener is defined.
   bool is_opener_defined = false;
diff --git a/chrome/browser/extensions/webstore_installer.cc b/chrome/browser/extensions/webstore_installer.cc
index 84abd9b..688cd37a 100644
--- a/chrome/browser/extensions/webstore_installer.cc
+++ b/chrome/browser/extensions/webstore_installer.cc
@@ -633,11 +633,11 @@
     ReportFailure(kDownloadDirectoryError, FAILURE_REASON_OTHER);
     return;
   }
-  if (!contents->GetRenderProcessHost()) {
+  if (!contents->GetRenderViewHost()) {
     ReportFailure(kDownloadDirectoryError, FAILURE_REASON_OTHER);
     return;
   }
-  if (!contents->GetRenderViewHost()) {
+  if (!contents->GetRenderViewHost()->GetProcess()) {
     ReportFailure(kDownloadDirectoryError, FAILURE_REASON_OTHER);
     return;
   }
@@ -656,7 +656,8 @@
   // We will navigate the current tab to this url to start the download. The
   // download system will then pass the crx to the CrxInstaller.
   RecordDownloadSource(DOWNLOAD_INITIATED_BY_WEBSTORE_INSTALLER);
-  int render_process_host_id = contents->GetRenderProcessHost()->GetID();
+  int render_process_host_id =
+      contents->GetRenderViewHost()->GetProcess()->GetID();
   int render_view_host_routing_id =
       contents->GetRenderViewHost()->GetRoutingID();
 
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 8ea9a14..b549905f 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1378,6 +1378,12 @@
     "Improved translate target language and triggering logic by considering "
     "information from User Language Profile (ULP).";
 
+const char kTranslateRankerEnforcementName[] =
+    "Enforce TranslateRanker decisions";
+const char kTranslateRankerEnforcementDescription[] =
+    "Improved Translate UI triggering logic. TranslateRanker decides whether "
+    "or not Translate UI should be triggered in a given context.";
+
 const char kTrySupportedChannelLayoutsName[] =
     "Causes audio output streams to check if channel layouts other than the "
     "default hardware layout are available.";
@@ -1554,6 +1560,9 @@
 const char kAndroidViewPasswordsDescription[] =
     "Enables copying and viewing passwords in settings.";
 
+const char kAsyncDnsName[] = "Async DNS resolver";
+const char kAsyncDnsDescription[] = "Enables the built-in DNS resolver.";
+
 const char kAutofillAccessoryViewName[] =
     "Autofill suggestions as keyboard accessory view";
 const char kAutofillAccessoryViewDescription[] =
@@ -1574,6 +1583,10 @@
 const char kChromeHomeExpandButtonDescription[] =
     "Enables the expand button for Chrome Home.";
 
+const char kChromeHomePromoName[] = "Chrome Home Promo";
+const char kChromeHomePromoDescription[] =
+    "Force the Chrome Home promotion to show each time the browser restarts.";
+
 const char kChromeHomeSwipeLogicName[] = "Chrome Home Swipe Logic";
 const char kChromeHomeSwipeLogicDescription[] =
     "Various swipe logic options for Chrome Home for sheet expansion.";
@@ -1657,11 +1670,6 @@
     "If enabled, the content suggestions settings will be available from the "
     "main settings menu.";
 
-const char kEnableContentSuggestionsShowSummaryName[] =
-    "Show content suggestions summaries.";
-const char kEnableContentSuggestionsShowSummaryDescription[] =
-    "If enabled, the content suggestions summaries will be shown.";
-
 const char kEnableContentSuggestionsThumbnailDominantColorName[] =
     "Use content suggestions thumbnail dominant color.";
 const char kEnableContentSuggestionsThumbnailDominantColorDescription[] =
@@ -2759,15 +2767,6 @@
 
 #endif  // defined(USE_ASH)
 
-#if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX)
-
-const char kShowCertLinkOnPageInfoName[] = "Show certificate link";
-const char kShowCertLinkOnPageInfoDescription[] =
-    "Add a link from the Page Info bubble to the certificate viewer for HTTPS "
-    "sites.";
-
-#endif  // defined(TOOLKIT_VIEWS) || defined(OS_MACOSX)
-
 #if defined(TOOLKIT_VIEWS) || defined(OS_ANDROID)
 
 const char kAutofillCreditCardUploadName[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index cfaf5a9..8c45ac0 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -850,6 +850,9 @@
 extern const char kTranslateLanguageByUlpName[];
 extern const char kTranslateLanguageByUlpDescription[];
 
+extern const char kTranslateRankerEnforcementName[];
+extern const char kTranslateRankerEnforcementDescription[];
+
 extern const char kTrySupportedChannelLayoutsName[];
 extern const char kTrySupportedChannelLayoutsDescription[];
 
@@ -960,6 +963,9 @@
 extern const char kAndroidViewPasswordsName[];
 extern const char kAndroidViewPasswordsDescription[];
 
+extern const char kAsyncDnsName[];
+extern const char kAsyncDnsDescription[];
+
 extern const char kAutofillAccessoryViewName[];
 extern const char kAutofillAccessoryViewDescription[];
 
@@ -972,6 +978,9 @@
 extern const char kChromeHomeExpandButtonName[];
 extern const char kChromeHomeExpandButtonDescription[];
 
+extern const char kChromeHomePromoName[];
+extern const char kChromeHomePromoDescription[];
+
 extern const char kChromeHomeSwipeLogicName[];
 extern const char kChromeHomeSwipeLogicDescription[];
 extern const char kChromeHomeSwipeLogicRestrictArea[];
@@ -1022,9 +1031,6 @@
 extern const char kEnableContentSuggestionsSettingsName[];
 extern const char kEnableContentSuggestionsSettingsDescription[];
 
-extern const char kEnableContentSuggestionsShowSummaryName[];
-extern const char kEnableContentSuggestionsShowSummaryDescription[];
-
 extern const char kEnableContentSuggestionsThumbnailDominantColorName[];
 extern const char kEnableContentSuggestionsThumbnailDominantColorDescription[];
 
@@ -1701,13 +1707,6 @@
 
 #endif  // defined(USE_ASH)
 
-#if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX)
-
-extern const char kShowCertLinkOnPageInfoName[];
-extern const char kShowCertLinkOnPageInfoDescription[];
-
-#endif  // defined(TOOLKIT_VIEWS) || defined(OS_MACOSX)
-
 #if defined(TOOLKIT_VIEWS) || defined(OS_ANDROID)
 
 extern const char kAutofillCreditCardUploadName[];
diff --git a/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc b/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc
index 0f9a06a..d96ce084 100644
--- a/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc
+++ b/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h"
 
+#include <map>
+
 #include "base/metrics/user_metrics.h"
 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
 #include "chrome/browser/permissions/permission_manager.h"
@@ -182,7 +184,7 @@
 
   content::WebContents* web_contents =
       web_view_guest()->embedder_web_contents();
-  int render_process_id = web_contents->GetRenderProcessHost()->GetID();
+  int render_process_id = web_contents->GetMainFrame()->GetProcess()->GetID();
   int render_frame_id = web_contents->GetMainFrame()->GetRoutingID();
 
   const PermissionRequestID request_id(
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc
index 22541c3e..5b2a568 100644
--- a/chrome/browser/io_thread.cc
+++ b/chrome/browser/io_thread.cc
@@ -34,13 +34,13 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/data_usage/tab_id_annotator.h"
 #include "chrome/browser/data_use_measurement/chrome_data_use_ascriber.h"
-#include "chrome/browser/net/async_dns_field_trial.h"
 #include "chrome/browser/net/chrome_mojo_proxy_resolver_factory.h"
 #include "chrome/browser/net/chrome_network_delegate.h"
 #include "chrome/browser/net/dns_probe_service.h"
 #include "chrome/browser/net/proxy_service_factory.h"
 #include "chrome/browser/net/sth_distributor_provider.h"
 #include "chrome/common/chrome_content_client.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "components/certificate_transparency/tree_state_tracker.h"
@@ -328,7 +328,7 @@
                  base::Unretained(this)));
   auth_android_negotiate_account_type_.MoveToThread(io_thread_proxy);
 #endif
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
   gssapi_library_name_ = local_state->GetString(prefs::kGSSAPILibraryName);
 #endif
 #if defined(OS_CHROMEOS)
@@ -354,11 +354,9 @@
           BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)));
 
   base::Value* dns_client_enabled_default =
-      new base::Value(chrome_browser_net::ConfigureAsyncDnsFieldTrial());
+      new base::Value(base::FeatureList::IsEnabled(features::kAsyncDns));
   local_state->SetDefaultPrefValue(prefs::kBuiltInDnsClientEnabled,
                                    dns_client_enabled_default);
-  chrome_browser_net::LogAsyncDnsPrefSource(
-      local_state->FindPreference(prefs::kBuiltInDnsClientEnabled));
 
   dns_client_enabled_.Init(prefs::kBuiltInDnsClientEnabled,
                            local_state,
@@ -650,7 +648,7 @@
       auth_schemes_, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
   globals_->http_auth_preferences.reset(new net::HttpAuthPreferences(
       supported_schemes
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
       ,
       gssapi_library_name_
 #endif
diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h
index 38ccae1..de92a52 100644
--- a/chrome/browser/io_thread.h
+++ b/chrome/browser/io_thread.h
@@ -301,7 +301,7 @@
 #if defined(OS_ANDROID)
   StringPrefMember auth_android_negotiate_account_type_;
 #endif
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
   // No PrefMember for the GSSAPI library name, since changing it after startup
   // requires unloading the existing GSSAPI library, which could cause all sorts
   // of problems for, for example, active Negotiate transactions.
diff --git a/chrome/browser/loader/OWNERS b/chrome/browser/loader/OWNERS
index 921bcfb..d9c26fbb 100644
--- a/chrome/browser/loader/OWNERS
+++ b/chrome/browser/loader/OWNERS
@@ -1,3 +1,3 @@
 file://content/browser/loader/OWNERS
 
-per-file data_reduction_proxy_resource_throttle_android.*=sgurun@chromium.org
+per-file data_reduction_proxy_resource_throttle_android.*=bengr@chromium.org
diff --git a/chrome/browser/logging_chrome_unittest.cc b/chrome/browser/logging_chrome_unittest.cc
index 236b4b4d..aefc52d 100644
--- a/chrome/browser/logging_chrome_unittest.cc
+++ b/chrome/browser/logging_chrome_unittest.cc
@@ -4,10 +4,12 @@
 
 #include <memory>
 
+#include "base/command_line.h"
 #include "base/environment.h"
 #include "base/files/file_path.h"
 #include "chrome/common/env_vars.h"
 #include "chrome/common/logging_chrome.h"
+#include "content/public/common/content_switches.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 class ChromeLoggingTest : public testing::Test {
@@ -29,15 +31,23 @@
     env->SetVar(env_vars::kLogFileName, environment_filename_);
   }
 
+  void SetLogFileFlag(const std::string& value) {
+    cmd_line_.AppendSwitchASCII(switches::kLogFile, value);
+  }
+
+  const base::CommandLine& cmd_line() { return cmd_line_; }
+
  private:
   std::string environment_filename_;  // Saves real environment value.
+  base::CommandLine cmd_line_ =
+      base::CommandLine(base::CommandLine::NO_PROGRAM);
 };
 
 // Tests the log file name getter without an environment variable.
 TEST_F(ChromeLoggingTest, LogFileName) {
   SaveEnvironmentVariable(std::string());
 
-  base::FilePath filename = logging::GetLogFileName();
+  base::FilePath filename = logging::GetLogFileName(cmd_line());
   ASSERT_NE(base::FilePath::StringType::npos,
             filename.value().find(FILE_PATH_LITERAL("chrome_debug.log")));
 
@@ -46,10 +56,32 @@
 
 // Tests the log file name getter with an environment variable.
 TEST_F(ChromeLoggingTest, EnvironmentLogFileName) {
-  SaveEnvironmentVariable("test value");
+  SaveEnvironmentVariable("test env value");
 
-  base::FilePath filename = logging::GetLogFileName();
-  ASSERT_EQ(base::FilePath(FILE_PATH_LITERAL("test value")).value(),
+  base::FilePath filename = logging::GetLogFileName(cmd_line());
+  ASSERT_EQ(base::FilePath(FILE_PATH_LITERAL("test env value")).value(),
+            filename.value());
+
+  RestoreEnvironmentVariable();
+}
+
+// Tests the log file name getter with a command-line flag.
+TEST_F(ChromeLoggingTest, FlagLogFileName) {
+  SetLogFileFlag("test flag value");
+
+  base::FilePath filename = logging::GetLogFileName(cmd_line());
+  ASSERT_EQ(base::FilePath(FILE_PATH_LITERAL("test flag value")).value(),
+            filename.value());
+}
+
+// Tests the log file name getter with with an environment variable and a
+// command-line flag. The flag takes precedence.
+TEST_F(ChromeLoggingTest, EnvironmentAndFlagLogFileName) {
+  SaveEnvironmentVariable("test env value");
+  SetLogFileFlag("test flag value");
+
+  base::FilePath filename = logging::GetLogFileName(cmd_line());
+  ASSERT_EQ(base::FilePath(FILE_PATH_LITERAL("test flag value")).value(),
             filename.value());
 
   RestoreEnvironmentVariable();
diff --git a/chrome/browser/mash_service_registry.cc b/chrome/browser/mash_service_registry.cc
new file mode 100644
index 0000000..7e9861a
--- /dev/null
+++ b/chrome/browser/mash_service_registry.cc
@@ -0,0 +1,57 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/mash_service_registry.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "mash/quick_launch/public/interfaces/constants.mojom.h"
+#include "mash/quick_launch/quick_launch.h"
+#include "services/ui/public/interfaces/constants.mojom.h"
+
+#if defined(OS_CHROMEOS)
+#include "ash/public/interfaces/constants.mojom.h"  // nogncheck
+#endif                                              // defined(OS_CHROMEOS)
+
+#if defined(OS_LINUX) && !defined(OS_ANDROID)
+#include "components/font_service/public/interfaces/constants.mojom.h"
+#endif  // defined(OS_LINUX) && !defined(OS_ANDROID)
+
+namespace {
+
+struct Service {
+  const char* name;
+  const char* description;
+};
+
+constexpr Service kServices[] = {
+    {mash::quick_launch::mojom::kServiceName, "Quick Launch"},
+    {ui::mojom::kServiceName, "UI Service"},
+#if defined(OS_CHROMEOS)
+    {ash::mojom::kServiceName, "Ash Window Manager and Shell"},
+    {"accessibility_autoclick", "Ash Accessibility Autoclick"},
+    {"touch_hud", "Ash Touch Hud"},
+#endif  // defined(OS_CHROMEOS)
+#if defined(OS_LINUX) && !defined(OS_ANDROID)
+    {font_service::mojom::kServiceName, "Font Service"},
+#endif  // defined(OS_LINUX) && !defined(OS_ANDROID)
+};
+
+}  // namespace
+
+void RegisterOutOfProcessServicesForMash(
+    content::ContentBrowserClient::OutOfProcessServiceMap* services) {
+  for (size_t i = 0; i < arraysize(kServices); ++i) {
+    (*services)[kServices[i].name] =
+        base::ASCIIToUTF16(kServices[i].description);
+  }
+}
+
+bool IsMashServiceName(const std::string& name) {
+  for (size_t i = 0; i < arraysize(kServices); ++i) {
+    if (name == kServices[i].name)
+      return true;
+  }
+  return false;
+}
diff --git a/chrome/browser/mash_service_registry.h b/chrome/browser/mash_service_registry.h
new file mode 100644
index 0000000..7fc58de
--- /dev/null
+++ b/chrome/browser/mash_service_registry.h
@@ -0,0 +1,19 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_MASH_SERVICE_REGISTRY_H_
+#define CHROME_BROWSER_MASH_SERVICE_REGISTRY_H_
+
+#include <string>
+
+#include "content/public/browser/content_browser_client.h"
+
+// Starts one of Mash's embedded services.
+void RegisterOutOfProcessServicesForMash(
+    content::ContentBrowserClient::OutOfProcessServiceMap* services);
+
+// Returns true if |name| identifies a mash related service.
+bool IsMashServiceName(const std::string& name);
+
+#endif  // CHROME_BROWSER_MASH_SERVICE_REGISTRY_H_
diff --git a/chrome/browser/media/router/discovery/dial/dial_media_sink_service_impl.cc b/chrome/browser/media/router/discovery/dial/dial_media_sink_service_impl.cc
index d718b42b..71bd0e8 100644
--- a/chrome/browser/media/router/discovery/dial/dial_media_sink_service_impl.cc
+++ b/chrome/browser/media/router/discovery/dial/dial_media_sink_service_impl.cc
@@ -7,6 +7,7 @@
 #include "chrome/browser/media/router/discovery/dial/dial_device_data.h"
 #include "chrome/browser/profiles/profile.h"
 #include "content/public/browser/browser_thread.h"
+#include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
 
 using content::BrowserThread;
@@ -35,6 +36,8 @@
 
   dial_registry_ =
       test_dial_registry_ ? test_dial_registry_ : DialRegistry::GetInstance();
+  dial_registry_->SetNetLog(
+      request_context_->GetURLRequestContext()->net_log());
   dial_registry_->RegisterObserver(this);
   dial_registry_->OnListenerAdded();
   MediaSinkServiceBase::StartTimer();
diff --git a/chrome/browser/media/router/discovery/dial/dial_registry.cc b/chrome/browser/media/router/discovery/dial/dial_registry.cc
index 7d800eb..3c980b7 100644
--- a/chrome/browser/media/router/discovery/dial/dial_registry.cc
+++ b/chrome/browser/media/router/discovery/dial/dial_registry.cc
@@ -16,7 +16,6 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/media/router/discovery/dial/dial_device_data.h"
 #include "chrome/browser/media/router/discovery/dial/dial_service.h"
-#include "components/net_log/chrome_net_log.h"
 #include "content/public/browser/browser_thread.h"
 
 using base::Time;
@@ -65,9 +64,14 @@
                          base::LeakySingletonTraits<DialRegistry>>::get();
 }
 
+void DialRegistry::SetNetLog(net::NetLog* net_log) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  if (!net_log_)
+    net_log_ = net_log;
+}
+
 std::unique_ptr<DialService> DialRegistry::CreateDialService() {
-  DCHECK(g_browser_process->net_log());
-  return base::MakeUnique<DialServiceImpl>(g_browser_process->net_log());
+  return base::MakeUnique<DialServiceImpl>(net_log_);
 }
 
 void DialRegistry::ClearDialService() {
diff --git a/chrome/browser/media/router/discovery/dial/dial_registry.h b/chrome/browser/media/router/discovery/dial/dial_registry.h
index 1091e18..f033959 100644
--- a/chrome/browser/media/router/discovery/dial/dial_registry.h
+++ b/chrome/browser/media/router/discovery/dial/dial_registry.h
@@ -25,6 +25,10 @@
 class Clock;
 }
 
+namespace net {
+class NetLog;
+}
+
 namespace media_router {
 
 // Keeps track of devices that have responded to discovery requests and notifies
@@ -58,6 +62,11 @@
 
   static DialRegistry* GetInstance();
 
+  // Sets the NetLog object used for logging. Should be called right after
+  // GetInstance(). If the registry already has a NetLog, does nothing. The
+  // NetLog should live at least as long as the IO Thread.
+  void SetNetLog(net::NetLog* net_log);
+
   // Called by the DIAL API when event listeners are added or removed. The dial
   // service is started after the first listener is added and stopped after the
   // last listener is removed.
@@ -191,6 +200,9 @@
   // DIAL API owns this DIAL registry.
   base::ObserverList<Observer> observers_;
 
+  // Set just after construction, only used on the IO thread.
+  net::NetLog* net_log_ = nullptr;
+
   std::unique_ptr<base::Clock> clock_;
 
   FRIEND_TEST_ALL_PREFIXES(DialRegistryTest, TestAddRemoveListeners);
diff --git a/chrome/browser/media/router/discovery/dial/dial_service.cc b/chrome/browser/media/router/discovery/dial/dial_service.cc
index c1cfa4a..4133eee 100644
--- a/chrome/browser/media/router/discovery/dial/dial_service.cc
+++ b/chrome/browser/media/router/discovery/dial/dial_service.cc
@@ -32,7 +32,7 @@
 #include "net/http/http_response_headers.h"
 #include "net/http/http_util.h"
 #include "net/log/net_log.h"
-#include "net/log/net_log_source_type.h"
+#include "net/log/net_log_source.h"
 #include "url/gurl.h"
 
 #if defined(OS_CHROMEOS)
@@ -175,15 +175,14 @@
 
 bool DialServiceImpl::DialSocket::CreateAndBindSocket(
     const IPAddress& bind_ip_address,
-    net::NetLog* net_log,
-    net::NetLogSource net_log_source) {
+    net::NetLog* net_log) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(!socket_);
   DCHECK(bind_ip_address.IsIPv4());
 
   net::RandIntCallback rand_cb = base::Bind(&base::RandInt);
   socket_ = base::MakeUnique<UDPSocket>(net::DatagramSocket::RANDOM_BIND,
-                                        rand_cb, net_log, net_log_source);
+                                        rand_cb, net_log, net::NetLogSource());
 
   // 0 means bind a random port
   net::IPEndPoint address(bind_ip_address, 0);
@@ -398,8 +397,6 @@
   DCHECK(success);
   send_address_ = net::IPEndPoint(address, kDialRequestPort);
   send_buffer_ = new StringIOBuffer(BuildRequest());
-  net_log_source_.type = net::NetLogSourceType::UDP_SOCKET;
-  net_log_source_.id = net_log_->NextID();
 }
 
 DialServiceImpl::~DialServiceImpl() {
@@ -524,8 +521,7 @@
 
 void DialServiceImpl::BindAndAddSocket(const IPAddress& bind_ip_address) {
   std::unique_ptr<DialServiceImpl::DialSocket> dial_socket(CreateDialSocket());
-  if (dial_socket->CreateAndBindSocket(bind_ip_address, net_log_,
-                                       net_log_source_))
+  if (dial_socket->CreateAndBindSocket(bind_ip_address, net_log_))
     dial_sockets_.push_back(std::move(dial_socket));
 }
 
diff --git a/chrome/browser/media/router/discovery/dial/dial_service.h b/chrome/browser/media/router/discovery/dial/dial_service.h
index de210557..daacaed 100644
--- a/chrome/browser/media/router/discovery/dial/dial_service.h
+++ b/chrome/browser/media/router/discovery/dial/dial_service.h
@@ -15,7 +15,6 @@
 #include "base/task/cancelable_task_tracker.h"
 #include "base/timer/timer.h"
 #include "net/base/ip_address.h"
-#include "net/log/net_log_source.h"
 #include "net/socket/udp_socket.h"
 
 namespace net {
@@ -114,11 +113,9 @@
     explicit DialSocket(DialServiceImpl* dial_service);
     ~DialSocket();
 
-    // Creates a socket using |net_log| and |net_log_source| and binds it to
-    // |bind_ip_address|.
+    // Creates a socket using |net_log| and binds it to |bind_ip_address|.
     bool CreateAndBindSocket(const net::IPAddress& bind_ip_address,
-                             net::NetLog* net_log,
-                             net::NetLogSource net_log_source);
+                             net::NetLog* net_log);
 
     // Sends a single discovery request |send_buffer| to |send_address|
     // over the socket.
@@ -231,9 +228,6 @@
   // The NetLog for this service.
   net::NetLog* const net_log_;
 
-  // The NetLog source for this service.
-  net::NetLogSource net_log_source_;
-
   // The multicast address:port for search requests.
   net::IPEndPoint send_address_;
 
diff --git a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.cc b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.cc
index deeef006..f153c8e 100644
--- a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.cc
+++ b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.cc
@@ -7,15 +7,19 @@
 #include "base/memory/ptr_util.h"
 #include "base/metrics/field_trial_params.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/time/default_clock.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/media/router/discovery/media_sink_service_base.h"
 #include "chrome/browser/media/router/media_router_feature.h"
 #include "chrome/common/media_router/discovery/media_sink_internal.h"
 #include "chrome/common/media_router/discovery/media_sink_service.h"
 #include "chrome/common/media_router/media_sink.h"
+#include "components/cast_channel/cast_channel_enum.h"
 #include "components/cast_channel/cast_socket_service.h"
+#include "components/cast_channel/logger.h"
 #include "components/net_log/chrome_net_log.h"
 #include "net/base/backoff_entry.h"
+#include "net/base/net_errors.h"
 
 namespace {
 
@@ -37,6 +41,82 @@
   return media_router::MediaSinkInternal(sink, extra_data);
 }
 
+void RecordError(cast_channel::ChannelError channel_error,
+                 cast_channel::LastError last_error) {
+  media_router::MediaRouterChannelError error_code =
+      media_router::MediaRouterChannelError::UNKNOWN;
+
+  switch (channel_error) {
+    // TODO(crbug.com/767204): Add in errors for transient socket and timeout
+    // errors, but only after X number of occurences.
+    case cast_channel::ChannelError::UNKNOWN:
+      error_code = media_router::MediaRouterChannelError::UNKNOWN;
+      break;
+    case cast_channel::ChannelError::AUTHENTICATION_ERROR:
+      error_code = media_router::MediaRouterChannelError::AUTHENTICATION;
+      break;
+    case cast_channel::ChannelError::CONNECT_ERROR:
+      error_code = media_router::MediaRouterChannelError::CONNECT;
+      break;
+    case cast_channel::ChannelError::CONNECT_TIMEOUT:
+      error_code = media_router::MediaRouterChannelError::CONNECT_TIMEOUT;
+      break;
+    case cast_channel::ChannelError::PING_TIMEOUT:
+      error_code = media_router::MediaRouterChannelError::PING_TIMEOUT;
+      break;
+    default:
+      // Do nothing and let the standard launch failure issue surface.
+      break;
+  }
+
+  // If we have details, we may override the generic error codes set above.
+  // TODO(crbug.com/767204): Expand and refine below as we see more actual
+  // reports.
+
+  // General certificate errors
+  if ((last_error.challenge_reply_error ==
+           cast_channel::ChallengeReplyError::PEER_CERT_EMPTY ||
+       last_error.challenge_reply_error ==
+           cast_channel::ChallengeReplyError::FINGERPRINT_NOT_FOUND ||
+       last_error.challenge_reply_error ==
+           cast_channel::ChallengeReplyError::CERT_PARSING_FAILED ||
+       last_error.challenge_reply_error ==
+           cast_channel::ChallengeReplyError::CANNOT_EXTRACT_PUBLIC_KEY) ||
+      (last_error.net_return_value <=
+           net::ERR_CERT_COMMON_NAME_INVALID &&  // CERT_XXX errors
+       last_error.net_return_value > net::ERR_CERT_END) ||
+      last_error.channel_event ==
+          cast_channel::ChannelEvent::SSL_SOCKET_CONNECT_FAILED ||
+      last_error.channel_event ==
+          cast_channel::ChannelEvent::SEND_AUTH_CHALLENGE_FAILED ||
+      last_error.channel_event ==
+          cast_channel::ChannelEvent::AUTH_CHALLENGE_REPLY_INVALID) {
+    error_code = media_router::MediaRouterChannelError::GENERAL_CERTIFICATE;
+  }
+
+  // Certificate timing errors
+  if (last_error.channel_event ==
+          cast_channel::ChannelEvent::SSL_CERT_EXCESSIVE_LIFETIME ||
+      last_error.net_return_value == net::ERR_CERT_DATE_INVALID) {
+    error_code = media_router::MediaRouterChannelError::CERTIFICATE_TIMING;
+  }
+
+  // Network/firewall access denied
+  if (last_error.net_return_value == net::ERR_NETWORK_ACCESS_DENIED) {
+    error_code = media_router::MediaRouterChannelError::NETWORK;
+  }
+
+  // Authentication errors (assumed active ssl manipulation)
+  if (last_error.challenge_reply_error ==
+          cast_channel::ChallengeReplyError::CERT_NOT_SIGNED_BY_TRUSTED_CA ||
+      last_error.challenge_reply_error ==
+          cast_channel::ChallengeReplyError::SIGNED_BLOBS_MISMATCH) {
+    error_code = media_router::MediaRouterChannelError::AUTHENTICATION;
+  }
+
+  media_router::CastAnalytics::RecordDeviceChannelError(error_code);
+}
+
 }  // namespace
 
 namespace media_router {
@@ -100,7 +180,8 @@
       network_monitor_(network_monitor),
       backoff_policy_(kDefaultBackoffPolicy),
       task_runner_(task_runner),
-      net_log_(g_browser_process->net_log()) {
+      net_log_(g_browser_process->net_log()),
+      clock_(new base::DefaultClock()) {
   DETACH_FROM_SEQUENCE(sequence_checker_);
   DCHECK(cast_socket_service_);
   DCHECK(network_monitor_);
@@ -121,6 +202,11 @@
   task_runner_ = task_runner;
 }
 
+void CastMediaSinkServiceImpl::SetClockForTest(
+    std::unique_ptr<base::Clock> clock) {
+  clock_ = std::move(clock);
+}
+
 // MediaSinkService implementation
 void CastMediaSinkServiceImpl::Start() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -180,6 +266,10 @@
            << cast_channel::ChannelErrorToString(error_state)
            << " [channel_id]: " << socket.id();
 
+  cast_channel::LastError last_error =
+      cast_socket_service_->GetLogger()->GetLastError(socket.id());
+  RecordError(error_state, last_error);
+
   net::IPEndPoint ip_endpoint = socket.ip_endpoint();
   // Need a PostTask() here because RemoveSocket() will release the memory of
   // |socket|. Need to make sure all tasks on |socket| finish before deleting
@@ -264,7 +354,8 @@
   cast_socket_service_->OpenSocket(
       ip_endpoint, net_log_,
       base::BindOnce(&CastMediaSinkServiceImpl::OnChannelOpened, AsWeakPtr(),
-                     cast_sink, std::move(backoff_entry), sink_source),
+                     cast_sink, std::move(backoff_entry), sink_source,
+                     clock_->Now()),
       this);
 }
 
@@ -272,6 +363,7 @@
     const MediaSinkInternal& cast_sink,
     std::unique_ptr<net::BackoffEntry> backoff_entry,
     SinkSource sink_source,
+    base::Time start_time,
     cast_channel::CastSocket* socket) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(socket);
@@ -281,6 +373,9 @@
   if (backoff_entry)
     backoff_entry->InformOfRequest(succeeded);
 
+  CastAnalytics::RecordDeviceChannelOpenDuration(succeeded,
+                                                 clock_->Now() - start_time);
+
   if (succeeded) {
     OnChannelOpenSucceeded(cast_sink, socket, sink_source);
   } else {
@@ -303,6 +398,8 @@
     DVLOG(1) << "Fail to open channel after all retry attempts: "
              << ip_endpoint.ToString() << " [error_state]: "
              << cast_channel::ChannelErrorToString(error_state);
+
+    CastAnalytics::RecordCastChannelConnectResult(false);
     return;
   }
 
@@ -326,11 +423,7 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(socket);
 
-  // Record the sink source if this channel opening results in a new sink.
-  if (!base::ContainsKey(current_sinks_map_,
-                         cast_sink.cast_data().ip_endpoint.address())) {
-    metrics_.RecordResolvedFromSource(sink_source);
-  }
+  CastAnalytics::RecordCastChannelConnectResult(true);
 
   media_router::CastSinkExtraData extra_data = cast_sink.cast_data();
   extra_data.capabilities = cast_channel::CastDeviceCapability::AUDIO_OUT;
@@ -343,6 +436,13 @@
 
   // Add or update existing cast sink.
   auto& ip_address = cast_sink.cast_data().ip_endpoint.address();
+  auto sink_it = current_sinks_map_.find(ip_address);
+  if (sink_it == current_sinks_map_.end()) {
+    metrics_.RecordResolvedFromSource(sink_source);
+  } else if (sink_it->second.cast_data().discovered_by_dial &&
+             !cast_sink.cast_data().discovered_by_dial) {
+    metrics_.RecordResolvedFromSource(SinkSource::kDialMdns);
+  }
   current_sinks_map_[ip_address] = cast_sink;
 
   MediaSinkServiceBase::RestartTimer();
@@ -362,6 +462,7 @@
   if (base::ContainsKey(current_sinks_map_, ip_endpoint.address())) {
     DVLOG(2) << "Sink discovered by mDNS, skip adding [name]: "
              << sink.sink().name();
+    metrics_.RecordResolvedFromSource(SinkSource::kMdnsDial);
     return;
   }
 
diff --git a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.h b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.h
index b12a63d..c66d37f 100644
--- a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.h
+++ b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.h
@@ -46,6 +46,7 @@
 
   void SetTaskRunnerForTest(
       scoped_refptr<base::SequencedTaskRunner> task_runner);
+  void SetClockForTest(std::unique_ptr<base::Clock> clock);
 
   // MediaSinkService implementation
   void Start() override;
@@ -134,11 +135,13 @@
   // |cast_sink|: Cast sink created from mDNS service description or DIAL sink.
   // |backoff_entry|: backoff entry passed to |OnChannelErrorMayRetry| callback
   // if open channel fails.
+  // |start_time|: time at which corresponding |OpenChannel| was called.
   // |socket|: raw pointer of newly created cast channel. Does not take
   // ownership of |socket|.
   void OnChannelOpened(const MediaSinkInternal& cast_sink,
                        std::unique_ptr<net::BackoffEntry> backoff_entry,
                        SinkSource sink_source,
+                       base::Time start_time,
                        cast_channel::CastSocket* socket);
 
   // Invoked by |OnChannelOpened| if opening cast channel failed. It will retry
@@ -223,6 +226,8 @@
   // Owned by |g_browser_process|.
   net::NetLog* const net_log_;
 
+  std::unique_ptr<base::Clock> clock_;
+
   SEQUENCE_CHECKER(sequence_checker_);
 
   DISALLOW_COPY_AND_ASSIGN(CastMediaSinkServiceImpl);
diff --git a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl_unittest.cc b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl_unittest.cc
index 56e7541..3b342db 100644
--- a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl_unittest.cc
+++ b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl_unittest.cc
@@ -5,8 +5,10 @@
 #include "chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
+#include "base/test/histogram_tester.h"
 #include "base/test/mock_callback.h"
 #include "base/test/scoped_feature_list.h"
+#include "base/test/simple_test_clock.h"
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/timer/mock_timer.h"
 #include "chrome/browser/media/router/media_router_feature.h"
@@ -24,7 +26,9 @@
 using ::testing::SaveArg;
 using ::testing::WithArgs;
 using ::testing::_;
+using base::Bucket;
 using cast_channel::ChannelError;
+using testing::ElementsAre;
 
 namespace {
 
@@ -157,12 +161,13 @@
 }
 
 TEST_F(CastMediaSinkServiceImplTest, TestMultipleOnChannelOpenSucceeded) {
-  auto cast_sink1 = CreateCastSink(1);
-  auto cast_sink2 = CreateCastSink(2);
-  auto cast_sink3 = CreateCastSink(3);
-  auto ip_endpoint1 = CreateIPEndPoint(1);
-  auto ip_endpoint2 = CreateIPEndPoint(2);
-  auto ip_endpoint3 = CreateIPEndPoint(3);
+  MediaSinkInternal cast_sink1 = CreateCastSink(1);
+  MediaSinkInternal cast_sink2 = CreateCastSink(2);
+  MediaSinkInternal cast_sink3 = CreateCastSink(3);
+
+  CastSinkExtraData extra_data = cast_sink3.cast_data();
+  extra_data.discovered_by_dial = true;
+  cast_sink3.set_cast_data(extra_data);
 
   cast_channel::MockCastSocket socket2;
   socket2.set_id(2);
@@ -171,10 +176,41 @@
 
   // Current round of Dns discovery finds service1 and service 2.
   // Fail to open channel 1.
+  base::HistogramTester tester;
   media_sink_service_impl_.OnChannelOpenSucceeded(
       cast_sink2, &socket2, CastMediaSinkServiceImpl::SinkSource::kMdns);
+  EXPECT_THAT(
+      tester.GetAllSamples(
+          CastDeviceCountMetrics::kHistogramCastCachedSinkResolved),
+      ElementsAre(Bucket(
+          static_cast<int>(CastMediaSinkServiceImpl::SinkSource::kMdns), 1)));
+
+  media_sink_service_impl_.OnChannelOpenSucceeded(
+      cast_sink3, &socket3, CastMediaSinkServiceImpl::SinkSource::kDial);
+  EXPECT_THAT(
+      tester.GetAllSamples(
+          CastDeviceCountMetrics::kHistogramCastCachedSinkResolved),
+      ElementsAre(
+          Bucket(static_cast<int>(CastMediaSinkServiceImpl::SinkSource::kMdns),
+                 1),
+          Bucket(static_cast<int>(CastMediaSinkServiceImpl::SinkSource::kDial),
+                 1)));
+
+  extra_data.discovered_by_dial = false;
+  cast_sink3.set_cast_data(extra_data);
   media_sink_service_impl_.OnChannelOpenSucceeded(
       cast_sink3, &socket3, CastMediaSinkServiceImpl::SinkSource::kMdns);
+  EXPECT_THAT(
+      tester.GetAllSamples(
+          CastDeviceCountMetrics::kHistogramCastCachedSinkResolved),
+      ElementsAre(
+          Bucket(static_cast<int>(CastMediaSinkServiceImpl::SinkSource::kMdns),
+                 1),
+          Bucket(static_cast<int>(CastMediaSinkServiceImpl::SinkSource::kDial),
+                 1),
+          Bucket(
+              static_cast<int>(CastMediaSinkServiceImpl::SinkSource::kDialMdns),
+              1)));
 
   // Verify sink content
   EXPECT_CALL(mock_sink_discovered_cb_,
@@ -316,6 +352,11 @@
   net::IPEndPoint ip_endpoint2 = CreateIPEndPoint(2);
   net::IPEndPoint ip_endpoint3 = CreateIPEndPoint(3);
 
+  base::SimpleTestClock* clock = new base::SimpleTestClock();
+  base::Time start_time = base::Time::Now();
+  clock->SetNow(start_time);
+  media_sink_service_impl_.SetClockForTest(base::WrapUnique(clock));
+
   EXPECT_CALL(*mock_cast_socket_service_,
               OpenSocketInternal(ip_endpoint1, _, _, _));
   EXPECT_CALL(*mock_cast_socket_service_,
@@ -330,9 +371,16 @@
   cast_channel::MockCastSocket socket2;
   socket2.set_id(2);
   socket2.SetErrorState(cast_channel::ChannelError::NONE);
+
+  base::TimeDelta delta = base::TimeDelta::FromSeconds(2);
+  clock->Advance(delta);
+  base::HistogramTester tester;
+
   media_sink_service_impl_.OnChannelOpened(
       cast_sink2, nullptr, CastMediaSinkServiceImpl::SinkSource::kMdns,
-      &socket2);
+      start_time, &socket2);
+  tester.ExpectUniqueSample(CastAnalytics::kHistogramCastMdnsChannelOpenSuccess,
+                            delta.InMilliseconds(), 1);
 
   EXPECT_CALL(*mock_cast_socket_service_,
               OpenSocketInternal(ip_endpoint2, _, _, _));
@@ -353,10 +401,10 @@
   socket3.SetErrorState(cast_channel::ChannelError::NONE);
   media_sink_service_impl_.OnChannelOpened(
       cast_sink1, nullptr, CastMediaSinkServiceImpl::SinkSource::kMdns,
-      &socket1);
+      start_time, &socket1);
   media_sink_service_impl_.OnChannelOpened(
       cast_sink3, nullptr, CastMediaSinkServiceImpl::SinkSource::kMdns,
-      &socket3);
+      start_time, &socket3);
 
   EXPECT_CALL(mock_sink_discovered_cb_,
               Run(std::vector<MediaSinkInternal>(
@@ -395,8 +443,14 @@
   EXPECT_CALL(*mock_cast_socket_service_, OpenSocketInternal(_, _, _, _))
       .Times(0);
 
+  base::HistogramTester tester;
   media_sink_service_impl_.OnError(
       socket, cast_channel::ChannelError::CHANNEL_NOT_OPEN);
+
+  tester.ExpectTotalCount(CastAnalytics::kHistogramCastChannelError, 1);
+  EXPECT_THAT(tester.GetAllSamples(CastAnalytics::kHistogramCastChannelError),
+              ElementsAre(Bucket(
+                  static_cast<int>(MediaRouterChannelError::UNKNOWN), 1)));
   mock_time_task_runner_->RunUntilIdle();
 }
 
diff --git a/chrome/browser/media/router/discovery/media_sink_discovery_metrics.cc b/chrome/browser/media/router/discovery/media_sink_discovery_metrics.cc
index 22597ad..72a286c 100644
--- a/chrome/browser/media/router/discovery/media_sink_discovery_metrics.cc
+++ b/chrome/browser/media/router/discovery/media_sink_discovery_metrics.cc
@@ -76,4 +76,40 @@
                             kTotalCount);
 }
 
+// static
+const char CastAnalytics::kHistogramCastChannelConnectResult[] =
+    "MediaRouter.Cast.Channel.ConnectResult";
+const char CastAnalytics::kHistogramCastChannelError[] =
+    "MediaRouter.Cast.Channel.Error";
+const char CastAnalytics::kHistogramCastMdnsChannelOpenSuccess[] =
+    "MediaRouter.Cast.Mdns.Channel.Open_Success";
+const char CastAnalytics::kHistogramCastMdnsChannelOpenFailure[] =
+    "MediaRouter.Cast.Mdns.Channel.Open_Failure";
+
+// static
+void CastAnalytics::RecordCastChannelConnectResult(
+    bool channel_opened_successfully) {
+  UMA_HISTOGRAM_BOOLEAN(kHistogramCastChannelConnectResult,
+                        channel_opened_successfully);
+}
+
+// static
+void CastAnalytics::RecordDeviceChannelError(
+    MediaRouterChannelError channel_error) {
+  DCHECK_LT(channel_error, MediaRouterChannelError::TOTAL_COUNT);
+  UMA_HISTOGRAM_ENUMERATION(kHistogramCastChannelError, channel_error,
+                            MediaRouterChannelError::TOTAL_COUNT);
+}
+
+// static
+void CastAnalytics::RecordDeviceChannelOpenDuration(
+    bool success,
+    const base::TimeDelta& duration) {
+  if (success) {
+    UMA_HISTOGRAM_TIMES(kHistogramCastMdnsChannelOpenSuccess, duration);
+  } else {
+    UMA_HISTOGRAM_TIMES(kHistogramCastMdnsChannelOpenFailure, duration);
+  }
+}
+
 }  // namespace media_router
diff --git a/chrome/browser/media/router/discovery/media_sink_discovery_metrics.h b/chrome/browser/media/router/discovery/media_sink_discovery_metrics.h
index 9d4c2203..d19047f 100644
--- a/chrome/browser/media/router/discovery/media_sink_discovery_metrics.h
+++ b/chrome/browser/media/router/discovery/media_sink_discovery_metrics.h
@@ -12,6 +12,21 @@
 
 namespace media_router {
 
+// Possible values for channel open errors.
+enum class MediaRouterChannelError {
+  UNKNOWN = 0,
+  AUTHENTICATION = 1,
+  CONNECT = 2,
+  GENERAL_CERTIFICATE = 3,
+  CERTIFICATE_TIMING = 4,
+  NETWORK = 5,
+  CONNECT_TIMEOUT = 6,
+  PING_TIMEOUT = 7,
+
+  // Note = Add entries only immediately above this line.
+  TOTAL_COUNT = 8
+};
+
 class DeviceCountMetrics {
  public:
   DeviceCountMetrics();
@@ -56,8 +71,10 @@
     kMdns = 1,
     kDial = 2,
     kConnectionRetry = 3,
+    kMdnsDial = 4,  // Device was first discovered via mDNS, then by DIAL.
+    kDialMdns = 5,  // Device was first discovered via DIAL, then by mDNS.
 
-    kTotalCount = 3,
+    kTotalCount = 6,
   };
 
   static const char kHistogramCastKnownDeviceCount[];
@@ -71,6 +88,19 @@
   void RecordResolvedFromSource(SinkSource sink_source);
 };
 
+class CastAnalytics {
+ public:
+  static const char kHistogramCastChannelConnectResult[];
+  static const char kHistogramCastChannelError[];
+  static const char kHistogramCastMdnsChannelOpenSuccess[];
+  static const char kHistogramCastMdnsChannelOpenFailure[];
+
+  static void RecordCastChannelConnectResult(bool channel_opened_successfully);
+  static void RecordDeviceChannelError(MediaRouterChannelError channel_error);
+  static void RecordDeviceChannelOpenDuration(bool success,
+                                              const base::TimeDelta& duration);
+};
+
 }  // namespace media_router
 
 #endif  // CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_MEDIA_SINK_DISCOVERY_METRICS_H_
diff --git a/chrome/browser/media/router/discovery/media_sink_discovery_metrics_unittest.cc b/chrome/browser/media/router/discovery/media_sink_discovery_metrics_unittest.cc
index 3af4669c..76d8454 100644
--- a/chrome/browser/media/router/discovery/media_sink_discovery_metrics_unittest.cc
+++ b/chrome/browser/media/router/discovery/media_sink_discovery_metrics_unittest.cc
@@ -9,9 +9,11 @@
 #include "base/test/histogram_tester.h"
 #include "base/test/simple_test_clock.h"
 #include "base/time/time.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using base::Bucket;
+using testing::ElementsAre;
 
 namespace media_router {
 
@@ -91,4 +93,53 @@
       CastDeviceCountMetrics::kHistogramCastKnownDeviceCount, 10, 2);
 }
 
+TEST(CastAnalyticsTest, RecordCastChannelConnectResult) {
+  base::HistogramTester tester;
+  tester.ExpectTotalCount(CastAnalytics::kHistogramCastChannelConnectResult, 0);
+  CastAnalytics::RecordCastChannelConnectResult(true);
+  CastAnalytics::RecordCastChannelConnectResult(false);
+  CastAnalytics::RecordCastChannelConnectResult(true);
+  tester.ExpectTotalCount(CastAnalytics::kHistogramCastChannelConnectResult, 3);
+  EXPECT_THAT(
+      tester.GetAllSamples(CastAnalytics::kHistogramCastChannelConnectResult),
+      ElementsAre(Bucket(false, 1), Bucket(true, 2)));
+}
+
+TEST(CastAnalyticsTest, RecordDeviceChannelError) {
+  base::HistogramTester tester;
+  const MediaRouterChannelError error1 =
+      MediaRouterChannelError::AUTHENTICATION;
+  const MediaRouterChannelError error2 = MediaRouterChannelError::CONNECT;
+  const MediaRouterChannelError error3 =
+      MediaRouterChannelError::GENERAL_CERTIFICATE;
+
+  tester.ExpectTotalCount(CastAnalytics::kHistogramCastChannelError, 0);
+  CastAnalytics::RecordDeviceChannelError(error1);
+  CastAnalytics::RecordDeviceChannelError(error2);
+  CastAnalytics::RecordDeviceChannelError(error2);
+  CastAnalytics::RecordDeviceChannelError(error3);
+  tester.ExpectTotalCount(CastAnalytics::kHistogramCastChannelError, 4);
+  EXPECT_THAT(tester.GetAllSamples(CastAnalytics::kHistogramCastChannelError),
+              ElementsAre(Bucket(static_cast<int>(error1), 1),
+                          Bucket(static_cast<int>(error2), 2),
+                          Bucket(static_cast<int>(error3), 1)));
+}
+
+TEST(CastAnalyticsTest, RecordDeviceChannelOpenDuration) {
+  base::HistogramTester tester;
+  const base::TimeDelta delta = base::TimeDelta::FromMilliseconds(10);
+
+  tester.ExpectTotalCount(CastAnalytics::kHistogramCastMdnsChannelOpenSuccess,
+                          0);
+  CastAnalytics::RecordDeviceChannelOpenDuration(true, delta);
+  tester.ExpectUniqueSample(CastAnalytics::kHistogramCastMdnsChannelOpenSuccess,
+                            delta.InMilliseconds(), 1);
+
+  tester.ExpectTotalCount(CastAnalytics::kHistogramCastMdnsChannelOpenFailure,
+                          0);
+  CastAnalytics::RecordDeviceChannelOpenDuration(false, delta);
+  tester.ExpectUniqueSample(CastAnalytics::kHistogramCastMdnsChannelOpenFailure,
+                            delta.InMilliseconds(), 1);
+}
+
 }  // namespace media_router
diff --git a/chrome/browser/media/webrtc/desktop_capture_access_handler.cc b/chrome/browser/media/webrtc/desktop_capture_access_handler.cc
index d423aef..cbb52d3 100644
--- a/chrome/browser/media/webrtc/desktop_capture_access_handler.cc
+++ b/chrome/browser/media/webrtc/desktop_capture_access_handler.cc
@@ -74,111 +74,81 @@
 base::string16 GetStopSharingUIString(
     const base::string16& application_title,
     const base::string16& registered_extension_name,
-    const content::DesktopMediaID& media_id) {
-  if (!media_id.is_audio_capture()) {
-    DCHECK(media_id.is_video_capture());
+    bool capture_audio,
+    content::DesktopMediaID::Type capture_type) {
+  if (!capture_audio) {
     if (application_title == registered_extension_name) {
-      switch (media_id.source_type) {
-        case content::DesktopMediaID::SOURCE_SCREEN:
+      switch (capture_type) {
+        case content::DesktopMediaID::TYPE_SCREEN:
           return l10n_util::GetStringFUTF16(
               IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_TEXT, application_title);
-        case content::DesktopMediaID::SOURCE_WINDOW:
+        case content::DesktopMediaID::TYPE_WINDOW:
           return l10n_util::GetStringFUTF16(
               IDS_MEDIA_WINDOW_CAPTURE_NOTIFICATION_TEXT, application_title);
-        case content::DesktopMediaID::SOURCE_WEB_CONTENTS:
+        case content::DesktopMediaID::TYPE_WEB_CONTENTS:
           return l10n_util::GetStringFUTF16(
               IDS_MEDIA_TAB_CAPTURE_NOTIFICATION_TEXT, application_title);
-        case content::DesktopMediaID::SOURCE_NONE:
+        case content::DesktopMediaID::TYPE_NONE:
           NOTREACHED();
       }
     } else {
-      switch (media_id.source_type) {
-        case content::DesktopMediaID::SOURCE_SCREEN:
+      switch (capture_type) {
+        case content::DesktopMediaID::TYPE_SCREEN:
           return l10n_util::GetStringFUTF16(
               IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_TEXT_DELEGATED,
               registered_extension_name, application_title);
-        case content::DesktopMediaID::SOURCE_WINDOW:
+        case content::DesktopMediaID::TYPE_WINDOW:
           return l10n_util::GetStringFUTF16(
               IDS_MEDIA_WINDOW_CAPTURE_NOTIFICATION_TEXT_DELEGATED,
               registered_extension_name, application_title);
-        case content::DesktopMediaID::SOURCE_WEB_CONTENTS:
+        case content::DesktopMediaID::TYPE_WEB_CONTENTS:
           return l10n_util::GetStringFUTF16(
               IDS_MEDIA_TAB_CAPTURE_NOTIFICATION_TEXT_DELEGATED,
               registered_extension_name, application_title);
-        case content::DesktopMediaID::SOURCE_NONE:
+        case content::DesktopMediaID::TYPE_NONE:
           NOTREACHED();
       }
     }
-  } else if (media_id.is_video_capture() && media_id.is_audio_capture()) {
-    // Audio and screen capture
+  } else {  // The case with audio
     if (application_title == registered_extension_name) {
-      switch (media_id.source_type) {
-        case content::DesktopMediaID::SOURCE_SCREEN:
+      switch (capture_type) {
+        case content::DesktopMediaID::TYPE_SCREEN:
           return l10n_util::GetStringFUTF16(
               IDS_MEDIA_SCREEN_CAPTURE_WITH_AUDIO_NOTIFICATION_TEXT,
               application_title);
-        case content::DesktopMediaID::SOURCE_WEB_CONTENTS:
+        case content::DesktopMediaID::TYPE_WEB_CONTENTS:
           return l10n_util::GetStringFUTF16(
               IDS_MEDIA_TAB_CAPTURE_WITH_AUDIO_NOTIFICATION_TEXT,
               application_title);
-        case content::DesktopMediaID::SOURCE_NONE:
-        case content::DesktopMediaID::SOURCE_WINDOW:
+        case content::DesktopMediaID::TYPE_NONE:
+        case content::DesktopMediaID::TYPE_WINDOW:
           NOTREACHED();
       }
     } else {
-      switch (media_id.source_type) {
-        case content::DesktopMediaID::SOURCE_SCREEN:
+      switch (capture_type) {
+        case content::DesktopMediaID::TYPE_SCREEN:
           return l10n_util::GetStringFUTF16(
               IDS_MEDIA_SCREEN_CAPTURE_WITH_AUDIO_NOTIFICATION_TEXT_DELEGATED,
               registered_extension_name, application_title);
-        case content::DesktopMediaID::SOURCE_WEB_CONTENTS:
+        case content::DesktopMediaID::TYPE_WEB_CONTENTS:
           return l10n_util::GetStringFUTF16(
               IDS_MEDIA_TAB_CAPTURE_WITH_AUDIO_NOTIFICATION_TEXT_DELEGATED,
               registered_extension_name, application_title);
-        case content::DesktopMediaID::SOURCE_NONE:
-        case content::DesktopMediaID::SOURCE_WINDOW:
+        case content::DesktopMediaID::TYPE_NONE:
+        case content::DesktopMediaID::TYPE_WINDOW:
           NOTREACHED();
       }
     }
-  } else {
-    // Audio-only capture.
-    DCHECK(media_id.is_audio_capture() && !media_id.is_video_capture());
-    return application_title == registered_extension_name
-               ? l10n_util::GetStringFUTF16(
-                     IDS_MEDIA_SYSTEM_AUDIO_CAPTURE_NOTIFICATION_TEXT,
-                     application_title)
-               : l10n_util::GetStringFUTF16(
-                     IDS_MEDIA_SYSTEM_AUDIO_CAPTURE_NOTIFICATION_TEXT_DELEGATED,
-                     registered_extension_name, application_title);
   }
   return base::string16();
 }
-
-base::string16 GetConfirmationUIString(
-    const content::MediaStreamRequest& request,
-    const base::string16& application_name) {
-  if (request.video_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE &&
-      request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE) {
-    return l10n_util::GetStringFUTF16(
-        IDS_MEDIA_SCREEN_AND_AUDIO_CAPTURE_CONFIRMATION_TEXT, application_name);
-  } else if (request.video_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE &&
-             request.audio_type == content::MEDIA_NO_SERVICE) {
-    return l10n_util::GetStringFUTF16(
-        IDS_MEDIA_SCREEN_CAPTURE_CONFIRMATION_TEXT, application_name);
-  } else if (request.video_type == content::MEDIA_NO_SERVICE &&
-             request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE) {
-    return l10n_util::GetStringFUTF16(
-        IDS_MEDIA_SYSTEM_AUDIO_CAPTURE_CONFIRMATION_TEXT, application_name);
-  }
-  return base::string16();
-}
-
 // Helper to get list of media stream devices for desktop capture in |devices|.
 // Registers to display notification if |display_notification| is true.
 // Returns an instance of MediaStreamUI to be passed to content layer.
 std::unique_ptr<content::MediaStreamUI> GetDevicesForDesktopCapture(
     content::MediaStreamDevices* devices,
-    const content::DesktopMediaID& media_id,
+    content::DesktopMediaID media_id,
+    bool capture_audio,
     bool disable_local_echo,
     bool display_notification,
     const base::string16& application_title,
@@ -187,23 +157,18 @@
   std::unique_ptr<content::MediaStreamUI> ui;
 
   DVLOG(2) << __func__ << ": media_id " << media_id.ToString()
-           << ", video_capture " << media_id.is_video_capture()
-           << ", audio_capture " << media_id.is_audio_capture()
-           << ", disable_local_echo " << disable_local_echo
-           << ", display_notification " << display_notification
-           << ", application_title " << application_title << ", extension_name "
+           << ", capture_audio " << capture_audio << ", disable_local_echo "
+           << disable_local_echo << ", display_notification "
+           << display_notification << ", application_title "
+           << application_title << ", extension_name "
            << registered_extension_name;
 
   // Add selected desktop source to the list.
-  if (media_id.source_type == content::DesktopMediaID::SOURCE_SCREEN &&
-      media_id.is_video_capture()) {
-    devices->push_back(
-        content::MediaStreamDevice(content::MEDIA_DESKTOP_VIDEO_CAPTURE,
-                                   media_id.ToString(), media_id.ToString()));
-  }
-
-  if (media_id.is_audio_capture()) {
-    if (media_id.source_type == content::DesktopMediaID::SOURCE_WEB_CONTENTS) {
+  devices->push_back(
+      content::MediaStreamDevice(content::MEDIA_DESKTOP_VIDEO_CAPTURE,
+                                 media_id.ToString(), media_id.ToString()));
+  if (capture_audio) {
+    if (media_id.type == content::DesktopMediaID::TYPE_WEB_CONTENTS) {
       content::WebContentsMediaCaptureId web_id = media_id.web_contents_id;
       web_id.disable_local_echo = disable_local_echo;
       devices->push_back(
@@ -230,7 +195,8 @@
   }
 
   ui = ScreenCaptureNotificationUI::Create(GetStopSharingUIString(
-      application_title, registered_extension_name, media_id));
+      application_title, registered_extension_name, capture_audio,
+      media_id.type));
 
   return ui;
 }
@@ -273,12 +239,7 @@
   content::MediaStreamDevices devices;
   std::unique_ptr<content::MediaStreamUI> ui;
 
-  DCHECK(request.video_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE ||
-         request.video_type == content::MEDIA_NO_SERVICE);
-  DCHECK(request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE ||
-         request.audio_type == content::MEDIA_NO_SERVICE);
-  DCHECK(request.video_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE ||
-         request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE);
+  DCHECK_EQ(request.video_type, content::MEDIA_DESKTOP_VIDEO_CAPTURE);
 
   UpdateExtensionTrusted(request, extension);
 
@@ -336,38 +297,40 @@
           base::UTF8ToUTF16(request.security_origin.spec());
       if (extension)
         application_name = base::UTF8ToUTF16(extension->name());
+      base::string16 confirmation_text = l10n_util::GetStringFUTF16(
+          request.audio_type == content::MEDIA_NO_SERVICE
+              ? IDS_MEDIA_SCREEN_CAPTURE_CONFIRMATION_TEXT
+              : IDS_MEDIA_SCREEN_AND_AUDIO_CAPTURE_CONFIRMATION_TEXT,
+          application_name);
       chrome::MessageBoxResult result = chrome::ShowQuestionMessageBox(
           parent_window,
           l10n_util::GetStringFUTF16(
               IDS_MEDIA_SCREEN_CAPTURE_CONFIRMATION_TITLE, application_name),
-          GetConfirmationUIString(request, application_name));
+          confirmation_text);
       is_approved = (result == chrome::MESSAGE_BOX_RESULT_YES);
     }
 
     if (is_approved) {
       content::DesktopMediaID screen_id;
-      if (request.video_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE) {
 #if defined(OS_CHROMEOS)
-        screen_id = content::DesktopMediaID::RegisterAuraWindow(
-            content::DesktopMediaID::SOURCE_SCREEN,
-            ash::Shell::Get()->GetPrimaryRootWindow());
+      screen_id = content::DesktopMediaID::RegisterAuraWindow(
+          content::DesktopMediaID::TYPE_SCREEN,
+          ash::Shell::Get()->GetPrimaryRootWindow());
 #else   // defined(OS_CHROMEOS)
-        screen_id =
-            content::DesktopMediaID(content::DesktopMediaID::SOURCE_SCREEN,
-                                    webrtc::kFullDesktopScreenId);
+      screen_id = content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
+                                          webrtc::kFullDesktopScreenId);
 #endif  // !defined(OS_CHROMEOS)
-      }
 
-      screen_id.set_audio_capture(request.audio_type ==
-                                      content::MEDIA_DESKTOP_AUDIO_CAPTURE &&
-                                  loopback_audio_supported);
+      bool capture_audio =
+          (request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE &&
+           loopback_audio_supported);
 
       // Determine if the extension is required to display a notification.
       const bool display_notification = ShouldDisplayNotification(extension);
 
       ui = GetDevicesForDesktopCapture(
-          &devices, screen_id, request.disable_local_echo, display_notification,
-          application_title, application_title);
+          &devices, screen_id, capture_audio, request.disable_local_echo,
+          display_notification, application_title, application_title);
       DCHECK(!devices.empty());
     }
 
@@ -412,8 +375,7 @@
   content::MediaStreamDevices devices;
   std::unique_ptr<content::MediaStreamUI> ui;
 
-  if (request.video_type != content::MEDIA_DESKTOP_VIDEO_CAPTURE &&
-      request.audio_type != content::MEDIA_DESKTOP_AUDIO_CAPTURE) {
+  if (request.video_type != content::MEDIA_DESKTOP_VIDEO_CAPTURE) {
     callback.Run(devices, content::MEDIA_DEVICE_INVALID_STATE, std::move(ui));
     return;
   }
@@ -426,11 +388,6 @@
     return;
   }
 
-  if (!request.requested_audio_device_id.empty()) {
-    LOG(WARNING)
-        << "Setting a device id for system audio capture is not supported.";
-  }
-
   // The extension name that the stream is registered with.
   std::string original_extension_name;
   // Resolve DesktopMediaID for the specified device id.
@@ -455,7 +412,7 @@
   }
 
   // Received invalid device id.
-  if (media_id.source_type == content::DesktopMediaID::SOURCE_NONE) {
+  if (media_id.type == content::DesktopMediaID::TYPE_NONE) {
     callback.Run(devices, content::MEDIA_DEVICE_INVALID_STATE, std::move(ui));
     return;
   }
@@ -468,7 +425,7 @@
 
   // This value essentially from the checkbox on picker window, so it
   // corresponds to user permission.
-  const bool audio_permitted = media_id.is_audio_capture();
+  const bool audio_permitted = media_id.audio_share;
 
   // This value essentially from whether getUserMedia requests audio stream.
   const bool audio_requested =
@@ -478,24 +435,25 @@
   // can support audio sharing. Currently audio is only supported for screen and
   // tab/webcontents capture streams.
   const bool audio_supported =
-      (media_id.source_type == content::DesktopMediaID::SOURCE_SCREEN &&
+      (media_id.type == content::DesktopMediaID::TYPE_SCREEN &&
        loopback_audio_supported) ||
-      media_id.source_type == content::DesktopMediaID::SOURCE_WEB_CONTENTS;
+      media_id.type == content::DesktopMediaID::TYPE_WEB_CONTENTS;
 
   const bool check_audio_permission =
       !base::CommandLine::ForCurrentProcess()->HasSwitch(
           extensions::switches::kDisableDesktopCaptureAudio);
-  media_id.set_audio_capture(
+  const bool capture_audio =
       (check_audio_permission ? audio_permitted : true) && audio_requested &&
-      audio_supported);
+      audio_supported;
 
   // Determine if the extension is required to display a notification.
   const bool display_notification = ShouldDisplayNotification(extension);
 
-  ui = GetDevicesForDesktopCapture(
-      &devices, media_id, request.disable_local_echo, display_notification,
-      GetApplicationTitle(web_contents, extension),
-      base::UTF8ToUTF16(original_extension_name));
+  ui = GetDevicesForDesktopCapture(&devices, media_id, capture_audio,
+                                   request.disable_local_echo,
+                                   display_notification,
+                                   GetApplicationTitle(web_contents, extension),
+                                   base::UTF8ToUTF16(original_extension_name));
   UpdateExtensionTrusted(request, extension);
   callback.Run(devices, content::MEDIA_DEVICE_OK, std::move(ui));
 }
diff --git a/chrome/browser/media/webrtc/desktop_media_list.h b/chrome/browser/media/webrtc/desktop_media_list.h
index 2c9bbb72..8e02a8a 100644
--- a/chrome/browser/media/webrtc/desktop_media_list.h
+++ b/chrome/browser/media/webrtc/desktop_media_list.h
@@ -56,7 +56,7 @@
   virtual int GetSourceCount() const = 0;
   virtual const Source& GetSource(int index) const = 0;
 
-  virtual content::DesktopMediaID::Source GetMediaListType() const = 0;
+  virtual content::DesktopMediaID::Type GetMediaListType() const = 0;
 };
 
 #endif  // CHROME_BROWSER_MEDIA_WEBRTC_DESKTOP_MEDIA_LIST_H_
diff --git a/chrome/browser/media/webrtc/desktop_media_list_ash.cc b/chrome/browser/media/webrtc/desktop_media_list_ash.cc
index 41ebf5c..c5763fb 100644
--- a/chrome/browser/media/webrtc/desktop_media_list_ash.cc
+++ b/chrome/browser/media/webrtc/desktop_media_list_ash.cc
@@ -21,12 +21,12 @@
 
 }  // namespace
 
-DesktopMediaListAsh::DesktopMediaListAsh(content::DesktopMediaID::Source type)
+DesktopMediaListAsh::DesktopMediaListAsh(content::DesktopMediaID::Type type)
     : DesktopMediaListBase(
           base::TimeDelta::FromMilliseconds(kDefaultUpdatePeriod)),
       weak_factory_(this) {
-  DCHECK(type == content::DesktopMediaID::SOURCE_SCREEN ||
-         type == content::DesktopMediaID::SOURCE_WINDOW);
+  DCHECK(type == content::DesktopMediaID::TYPE_SCREEN ||
+         type == content::DesktopMediaID::TYPE_WINDOW);
   type_ = type;
 }
 
@@ -57,7 +57,7 @@
     if (!(*it)->IsVisible() || !(*it)->CanFocus())
       continue;
     content::DesktopMediaID id = content::DesktopMediaID::RegisterAuraWindow(
-        content::DesktopMediaID::SOURCE_WINDOW, *it);
+        content::DesktopMediaID::TYPE_WINDOW, *it);
     if (id.aura_id == view_dialog_id_.aura_id)
       continue;
     SourceDescription window_source(id, (*it)->GetTitle());
@@ -74,10 +74,10 @@
   aura::Window::Windows root_windows = ash::Shell::GetAllRootWindows();
 
   for (size_t i = 0; i < root_windows.size(); ++i) {
-    if (type_ == content::DesktopMediaID::SOURCE_SCREEN) {
+    if (type_ == content::DesktopMediaID::TYPE_SCREEN) {
       SourceDescription screen_source(
           content::DesktopMediaID::RegisterAuraWindow(
-              content::DesktopMediaID::SOURCE_SCREEN, root_windows[i]),
+              content::DesktopMediaID::TYPE_SCREEN, root_windows[i]),
           root_windows[i]->GetTitle());
 
       if (root_windows[i] == ash::Shell::GetPrimaryRootWindow())
diff --git a/chrome/browser/media/webrtc/desktop_media_list_ash.h b/chrome/browser/media/webrtc/desktop_media_list_ash.h
index 72107ef2..3ed50caa 100644
--- a/chrome/browser/media/webrtc/desktop_media_list_ash.h
+++ b/chrome/browser/media/webrtc/desktop_media_list_ash.h
@@ -24,7 +24,7 @@
 // native windows.
 class DesktopMediaListAsh : public DesktopMediaListBase {
  public:
-  explicit DesktopMediaListAsh(content::DesktopMediaID::Source type);
+  explicit DesktopMediaListAsh(content::DesktopMediaID::Type type);
   ~DesktopMediaListAsh() override;
 
  private:
diff --git a/chrome/browser/media/webrtc/desktop_media_list_ash_unittest.cc b/chrome/browser/media/webrtc/desktop_media_list_ash_unittest.cc
index ebd988d..af66a267 100644
--- a/chrome/browser/media/webrtc/desktop_media_list_ash_unittest.cc
+++ b/chrome/browser/media/webrtc/desktop_media_list_ash_unittest.cc
@@ -44,7 +44,7 @@
     ash::AshTestBase::TearDown();
   }
 
-  void CreateList(content::DesktopMediaID::Source type) {
+  void CreateList(content::DesktopMediaID::Type type) {
     list_.reset(new DesktopMediaListAsh(type));
     list_->SetThumbnailSize(gfx::Size(kThumbnailSize, kThumbnailSize));
 
@@ -64,7 +64,7 @@
 }
 
 TEST_F(DesktopMediaListAshTest, ScreenOnly) {
-  CreateList(content::DesktopMediaID::SOURCE_SCREEN);
+  CreateList(content::DesktopMediaID::TYPE_SCREEN);
 
   std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
 
@@ -78,7 +78,7 @@
 }
 
 TEST_F(DesktopMediaListAshTest, WindowOnly) {
-  CreateList(content::DesktopMediaID::SOURCE_WINDOW);
+  CreateList(content::DesktopMediaID::TYPE_WINDOW);
 
   std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
 
diff --git a/chrome/browser/media/webrtc/desktop_media_list_base.cc b/chrome/browser/media/webrtc/desktop_media_list_base.cc
index 227e646..6c69a4b 100644
--- a/chrome/browser/media/webrtc/desktop_media_list_base.cc
+++ b/chrome/browser/media/webrtc/desktop_media_list_base.cc
@@ -49,7 +49,7 @@
   return sources_[index];
 }
 
-DesktopMediaID::Source DesktopMediaListBase::GetMediaListType() const {
+DesktopMediaID::Type DesktopMediaListBase::GetMediaListType() const {
   return type_;
 }
 
diff --git a/chrome/browser/media/webrtc/desktop_media_list_base.h b/chrome/browser/media/webrtc/desktop_media_list_base.h
index 8c6b43c..746df12 100644
--- a/chrome/browser/media/webrtc/desktop_media_list_base.h
+++ b/chrome/browser/media/webrtc/desktop_media_list_base.h
@@ -30,7 +30,7 @@
   void StartUpdating(DesktopMediaListObserver* observer) override;
   int GetSourceCount() const override;
   const Source& GetSource(int index) const override;
-  content::DesktopMediaID::Source GetMediaListType() const override;
+  content::DesktopMediaID::Type GetMediaListType() const override;
 
   static uint32_t GetImageHash(const gfx::Image& image);
 
@@ -60,10 +60,10 @@
 
   // ID of the hosting dialog.
   content::DesktopMediaID view_dialog_id_ =
-      content::DesktopMediaID(content::DesktopMediaID::SOURCE_NONE, -1);
+      content::DesktopMediaID(content::DesktopMediaID::TYPE_NONE, -1);
 
   // Desktop media type of the list.
-  content::DesktopMediaID::Source type_ = content::DesktopMediaID::SOURCE_NONE;
+  content::DesktopMediaID::Type type_ = content::DesktopMediaID::TYPE_NONE;
 
  private:
   // Time interval between mode updates.
diff --git a/chrome/browser/media/webrtc/fake_desktop_media_list.cc b/chrome/browser/media/webrtc/fake_desktop_media_list.cc
index a996c903..24c2b42 100644
--- a/chrome/browser/media/webrtc/fake_desktop_media_list.cc
+++ b/chrome/browser/media/webrtc/fake_desktop_media_list.cc
@@ -10,13 +10,13 @@
 
 using content::DesktopMediaID;
 
-FakeDesktopMediaList::FakeDesktopMediaList(DesktopMediaID::Source type)
+FakeDesktopMediaList::FakeDesktopMediaList(DesktopMediaID::Type type)
     : observer_(NULL), type_(type) {}
 FakeDesktopMediaList::~FakeDesktopMediaList() {}
 
 void FakeDesktopMediaList::AddSource(int id) {
   AddSourceByFullMediaID(
-      content::DesktopMediaID(DesktopMediaID::SOURCE_WINDOW, id));
+      content::DesktopMediaID(DesktopMediaID::TYPE_WINDOW, id));
 }
 
 void FakeDesktopMediaList::AddSourceByFullMediaID(
@@ -74,6 +74,6 @@
   return sources_[index];
 }
 
-DesktopMediaID::Source FakeDesktopMediaList::GetMediaListType() const {
+DesktopMediaID::Type FakeDesktopMediaList::GetMediaListType() const {
   return type_;
 }
diff --git a/chrome/browser/media/webrtc/fake_desktop_media_list.h b/chrome/browser/media/webrtc/fake_desktop_media_list.h
index 6dc75cdd..1d36650 100644
--- a/chrome/browser/media/webrtc/fake_desktop_media_list.h
+++ b/chrome/browser/media/webrtc/fake_desktop_media_list.h
@@ -11,7 +11,7 @@
 
 class FakeDesktopMediaList : public DesktopMediaList {
  public:
-  explicit FakeDesktopMediaList(content::DesktopMediaID::Source type);
+  explicit FakeDesktopMediaList(content::DesktopMediaID::Type type);
   ~FakeDesktopMediaList() override;
 
   void AddSource(int id);
@@ -28,13 +28,13 @@
   void StartUpdating(DesktopMediaListObserver* observer) override;
   int GetSourceCount() const override;
   const Source& GetSource(int index) const override;
-  content::DesktopMediaID::Source GetMediaListType() const override;
+  content::DesktopMediaID::Type GetMediaListType() const override;
 
  private:
   std::vector<Source> sources_;
   DesktopMediaListObserver* observer_;
   gfx::ImageSkia thumbnail_;
-  const content::DesktopMediaID::Source type_;
+  const content::DesktopMediaID::Type type_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeDesktopMediaList);
 };
diff --git a/chrome/browser/media/webrtc/native_desktop_media_list.cc b/chrome/browser/media/webrtc/native_desktop_media_list.cc
index fccb3c31..87ba07f 100644
--- a/chrome/browser/media/webrtc/native_desktop_media_list.cc
+++ b/chrome/browser/media/webrtc/native_desktop_media_list.cc
@@ -83,7 +83,7 @@
     : public webrtc::DesktopCapturer::Callback {
  public:
   Worker(base::WeakPtr<NativeDesktopMediaList> media_list,
-         DesktopMediaID::Source type,
+         DesktopMediaID::Type type,
          std::unique_ptr<webrtc::DesktopCapturer> capturer);
   ~Worker() override;
 
@@ -101,7 +101,7 @@
 
   base::WeakPtr<NativeDesktopMediaList> media_list_;
 
-  DesktopMediaID::Source type_;
+  DesktopMediaID::Type type_;
   std::unique_ptr<webrtc::DesktopCapturer> capturer_;
 
   std::unique_ptr<webrtc::DesktopFrame> current_frame_;
@@ -113,7 +113,7 @@
 
 NativeDesktopMediaList::Worker::Worker(
     base::WeakPtr<NativeDesktopMediaList> media_list,
-    DesktopMediaID::Source type,
+    DesktopMediaID::Type type,
     std::unique_ptr<webrtc::DesktopCapturer> capturer)
     : media_list_(media_list), type_(type), capturer_(std::move(capturer)) {
   capturer_->Start(this);
@@ -135,7 +135,7 @@
   base::string16 title;
   for (size_t i = 0; i < sources.size(); ++i) {
     switch (type_) {
-      case DesktopMediaID::SOURCE_SCREEN:
+      case DesktopMediaID::TYPE_SCREEN:
         // Just in case 'Screen' is inflected depending on the screen number,
         // use plural formatter.
         title = mutiple_sources
@@ -146,7 +146,7 @@
                           IDS_DESKTOP_MEDIA_PICKER_SINGLE_SCREEN_NAME);
         break;
 
-      case DesktopMediaID::SOURCE_WINDOW:
+      case DesktopMediaID::TYPE_WINDOW:
         // Skip the picker dialog window.
         if (sources[i].id == view_dialog_id)
           continue;
@@ -212,7 +212,7 @@
 }
 
 NativeDesktopMediaList::NativeDesktopMediaList(
-    DesktopMediaID::Source type,
+    DesktopMediaID::Type type,
     std::unique_ptr<webrtc::DesktopCapturer> capturer)
     : DesktopMediaListBase(
           base::TimeDelta::FromMilliseconds(kDefaultUpdatePeriod)),
@@ -247,7 +247,7 @@
 #if defined(USE_AURA)
   // Associate aura id with native id.
   for (auto& source : sources) {
-    if (source.id.source_type != DesktopMediaID::SOURCE_WINDOW)
+    if (source.id.type != DesktopMediaID::TYPE_WINDOW)
       continue;
 
     aura::Window* aura_window = NULL;
@@ -260,7 +260,7 @@
 #endif  // defined(USE_X11)
     if (aura_window) {
       DesktopMediaID aura_id = DesktopMediaID::RegisterAuraWindow(
-          DesktopMediaID::SOURCE_WINDOW, aura_window);
+          DesktopMediaID::TYPE_WINDOW, aura_window);
       source.id.aura_id = aura_id.aura_id;
     }
   }
diff --git a/chrome/browser/media/webrtc/native_desktop_media_list.h b/chrome/browser/media/webrtc/native_desktop_media_list.h
index 0240a1e5..08ebbb78 100644
--- a/chrome/browser/media/webrtc/native_desktop_media_list.h
+++ b/chrome/browser/media/webrtc/native_desktop_media_list.h
@@ -21,7 +21,7 @@
 // native windows.
 class NativeDesktopMediaList : public DesktopMediaListBase {
  public:
-  NativeDesktopMediaList(content::DesktopMediaID::Source type,
+  NativeDesktopMediaList(content::DesktopMediaID::Type type,
                          std::unique_ptr<webrtc::DesktopCapturer> capturer);
   ~NativeDesktopMediaList() override;
 
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 106e2e7..8cd3fae 100644
--- a/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc
+++ b/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc
@@ -214,7 +214,7 @@
 #endif
     // Get the aura window's id.
     DesktopMediaID aura_id = DesktopMediaID::RegisterAuraWindow(
-        DesktopMediaID::SOURCE_WINDOW, aura_window);
+        DesktopMediaID::TYPE_WINDOW, aura_window);
     native_aura_id_map_[window.id] = aura_id.aura_id;
 
     window_list_.push_back(window);
@@ -250,7 +250,7 @@
   void AddWindowsAndVerify(bool has_view_dialog) {
     window_capturer_ = new FakeWindowCapturer();
     model_ = base::MakeUnique<NativeDesktopMediaList>(
-        DesktopMediaID::SOURCE_WINDOW, base::WrapUnique(window_capturer_));
+        DesktopMediaID::TYPE_WINDOW, base::WrapUnique(window_capturer_));
 
     // Set update period to reduce the time it takes to run tests.
     model_->SetUpdatePeriod(base::TimeDelta::FromMilliseconds(20));
@@ -274,7 +274,7 @@
 
     // Set view dialog window ID as the first window id.
     if (has_view_dialog) {
-      DesktopMediaID dialog_window_id(DesktopMediaID::SOURCE_WINDOW,
+      DesktopMediaID dialog_window_id(DesktopMediaID::TYPE_WINDOW,
                                       window_list_[0].id);
       model_->SetViewDialogWindowId(dialog_window_id);
       window_count--;
@@ -301,8 +301,7 @@
     run_loop.Run();
 
     for (size_t i = 0; i < window_count; ++i) {
-      EXPECT_EQ(model_->GetSource(i).id.source_type,
-                DesktopMediaID::SOURCE_WINDOW);
+      EXPECT_EQ(model_->GetSource(i).id.type, DesktopMediaID::TYPE_WINDOW);
       EXPECT_EQ(model_->GetSource(i).name, base::UTF8ToUTF16("Test window"));
       int index = has_view_dialog ? i + 1 : i;
       int native_id = window_list_[index].id;
@@ -339,7 +338,7 @@
 
 TEST_F(NativeDesktopMediaListTest, ScreenOnly) {
   model_ = base::MakeUnique<NativeDesktopMediaList>(
-      DesktopMediaID::SOURCE_SCREEN, base::MakeUnique<FakeScreenCapturer>());
+      DesktopMediaID::TYPE_SCREEN, base::MakeUnique<FakeScreenCapturer>());
 
   // Set update period to reduce the time it takes to run tests.
   model_->SetUpdatePeriod(base::TimeDelta::FromMilliseconds(20));
@@ -356,7 +355,7 @@
   model_->StartUpdating(&observer_);
   run_loop.Run();
 
-  EXPECT_EQ(model_->GetSource(0).id.source_type, DesktopMediaID::SOURCE_SCREEN);
+  EXPECT_EQ(model_->GetSource(0).id.type, DesktopMediaID::TYPE_SCREEN);
   EXPECT_EQ(model_->GetSource(0).id.id, 0);
 }
 
@@ -382,8 +381,7 @@
 
   run_loop.Run();
 
-  EXPECT_EQ(model_->GetSource(index).id.source_type,
-            DesktopMediaID::SOURCE_WINDOW);
+  EXPECT_EQ(model_->GetSource(index).id.type, DesktopMediaID::TYPE_WINDOW);
   EXPECT_EQ(model_->GetSource(index).id.id, index);
 }
 
@@ -405,8 +403,7 @@
   run_loop.Run();
 
   int native_id = window_list_.back().id;
-  EXPECT_EQ(model_->GetSource(index).id.source_type,
-            DesktopMediaID::SOURCE_WINDOW);
+  EXPECT_EQ(model_->GetSource(index).id.type, DesktopMediaID::TYPE_WINDOW);
   EXPECT_EQ(model_->GetSource(index).id.id, native_id);
   EXPECT_EQ(model_->GetSource(index).id.aura_id,
             native_aura_id_map_[native_id]);
diff --git a/chrome/browser/media/webrtc/screen_capture_infobar_delegate_android.cc b/chrome/browser/media/webrtc/screen_capture_infobar_delegate_android.cc
index b2eb3ad..2d9e4ae 100644
--- a/chrome/browser/media/webrtc/screen_capture_infobar_delegate_android.cc
+++ b/chrome/browser/media/webrtc/screen_capture_infobar_delegate_android.cc
@@ -90,7 +90,7 @@
   std::unique_ptr<content::MediaStreamUI> ui;
   if (result == content::MEDIA_DEVICE_OK) {
     content::DesktopMediaID screen_id = content::DesktopMediaID(
-        content::DesktopMediaID::SOURCE_SCREEN, webrtc::kFullDesktopScreenId);
+        content::DesktopMediaID::TYPE_SCREEN, webrtc::kFullDesktopScreenId);
     devices.push_back(content::MediaStreamDevice(
         content::MEDIA_DESKTOP_VIDEO_CAPTURE, screen_id.ToString(), "Screen"));
 
diff --git a/chrome/browser/media/webrtc/tab_desktop_media_list.cc b/chrome/browser/media/webrtc/tab_desktop_media_list.cc
index 47bc5d73..d15724e 100644
--- a/chrome/browser/media/webrtc/tab_desktop_media_list.cc
+++ b/chrome/browser/media/webrtc/tab_desktop_media_list.cc
@@ -60,7 +60,7 @@
     : DesktopMediaListBase(
           base::TimeDelta::FromMilliseconds(kDefaultUpdatePeriod)),
       weak_factory_(this) {
-  type_ = DesktopMediaID::SOURCE_WEB_CONTENTS;
+  type_ = DesktopMediaID::TYPE_WEB_CONTENTS;
   thumbnail_task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
       {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
 }
@@ -101,7 +101,7 @@
       content::RenderFrameHost* main_frame = contents->GetMainFrame();
       DCHECK(main_frame);
       DesktopMediaID media_id(
-          DesktopMediaID::SOURCE_WEB_CONTENTS, DesktopMediaID::kNullId,
+          DesktopMediaID::TYPE_WEB_CONTENTS, DesktopMediaID::kNullId,
           content::WebContentsMediaCaptureId(main_frame->GetProcess()->GetID(),
                                              main_frame->GetRoutingID()));
 
diff --git a/chrome/browser/media/webrtc/tab_desktop_media_list_unittest.cc b/chrome/browser/media/webrtc/tab_desktop_media_list_unittest.cc
index e315d7e8..07323f8 100644
--- a/chrome/browser/media/webrtc/tab_desktop_media_list_unittest.cc
+++ b/chrome/browser/media/webrtc/tab_desktop_media_list_unittest.cc
@@ -225,8 +225,8 @@
     base::RunLoop().Run();
 
     for (int i = 0; i < kDefaultSourceCount; ++i) {
-      EXPECT_EQ(list_->GetSource(i).id.source_type,
-                content::DesktopMediaID::SOURCE_WEB_CONTENTS);
+      EXPECT_EQ(list_->GetSource(i).id.type,
+                content::DesktopMediaID::TYPE_WEB_CONTENTS);
     }
 
     observer_.VerifyAndClearExpectations();
diff --git a/chrome/browser/media/webrtc/window_icon_util_chromeos.cc b/chrome/browser/media/webrtc/window_icon_util_chromeos.cc
index 46ef8a6..530f013 100644
--- a/chrome/browser/media/webrtc/window_icon_util_chromeos.cc
+++ b/chrome/browser/media/webrtc/window_icon_util_chromeos.cc
@@ -9,7 +9,7 @@
 #include "ui/aura/window.h"
 
 gfx::ImageSkia GetWindowIcon(content::DesktopMediaID id) {
-  DCHECK_EQ(content::DesktopMediaID::SOURCE_WINDOW, id.source_type);
+  DCHECK_EQ(content::DesktopMediaID::TYPE_WINDOW, id.type);
   aura::Window* window = content::DesktopMediaID::GetAuraWindowById(id);
   if (!window)
     return gfx::ImageSkia();
diff --git a/chrome/browser/media/webrtc/window_icon_util_mac.mm b/chrome/browser/media/webrtc/window_icon_util_mac.mm
index 4c2d2c991..690c875 100644
--- a/chrome/browser/media/webrtc/window_icon_util_mac.mm
+++ b/chrome/browser/media/webrtc/window_icon_util_mac.mm
@@ -11,7 +11,7 @@
 #include "third_party/libyuv/include/libyuv/convert_argb.h"
 
 gfx::ImageSkia GetWindowIcon(content::DesktopMediaID id) {
-  DCHECK(id.source_type == content::DesktopMediaID::SOURCE_WINDOW);
+  DCHECK(id.type == content::DesktopMediaID::TYPE_WINDOW);
 
   CGWindowID ids[1];
   ids[0] = id.id;
@@ -62,4 +62,4 @@
   CFRelease(cf_data);
 
   return gfx::ImageSkia::CreateFrom1xBitmap(result);
-}
+}
\ No newline at end of file
diff --git a/chrome/browser/media/webrtc/window_icon_util_ozone.cc b/chrome/browser/media/webrtc/window_icon_util_ozone.cc
index 6817b4f..f519648 100644
--- a/chrome/browser/media/webrtc/window_icon_util_ozone.cc
+++ b/chrome/browser/media/webrtc/window_icon_util_ozone.cc
@@ -8,7 +8,7 @@
 #include "ui/aura/client/aura_constants.h"
 
 gfx::ImageSkia GetWindowIcon(content::DesktopMediaID id) {
-  DCHECK_EQ(content::DesktopMediaID::SOURCE_WINDOW, id.source_type);
+  DCHECK_EQ(content::DesktopMediaID::TYPE_WINDOW, id.type);
   // TODO(tonikitoo): can we make the implementation of
   // chrome/browser/media/webrtc/window_icon_util_chromeos.cc generic
   // enough so we can reuse it here?
diff --git a/chrome/browser/media/webrtc/window_icon_util_win.cc b/chrome/browser/media/webrtc/window_icon_util_win.cc
index 97df38a..7e3b2ec 100644
--- a/chrome/browser/media/webrtc/window_icon_util_win.cc
+++ b/chrome/browser/media/webrtc/window_icon_util_win.cc
@@ -7,7 +7,7 @@
 #include "ui/gfx/icon_util.h"
 
 gfx::ImageSkia GetWindowIcon(content::DesktopMediaID id) {
-  DCHECK(id.source_type == content::DesktopMediaID::SOURCE_WINDOW);
+  DCHECK(id.type == content::DesktopMediaID::TYPE_WINDOW);
 
   HWND hwnd = reinterpret_cast<HWND>(id.id);
 
diff --git a/chrome/browser/media/webrtc/window_icon_util_x11.cc b/chrome/browser/media/webrtc/window_icon_util_x11.cc
index 06ab59d7..927b938 100644
--- a/chrome/browser/media/webrtc/window_icon_util_x11.cc
+++ b/chrome/browser/media/webrtc/window_icon_util_x11.cc
@@ -13,7 +13,7 @@
 #include "ui/gfx/x/x11_types.h"
 
 gfx::ImageSkia GetWindowIcon(content::DesktopMediaID id) {
-  DCHECK(id.source_type == content::DesktopMediaID::SOURCE_WINDOW);
+  DCHECK(id.type == content::DesktopMediaID::TYPE_WINDOW);
 
   Display* display = gfx::GetXDisplay();
   Atom property = gfx::GetAtom("_NET_WM_ICON");
diff --git a/chrome/browser/media_galleries/media_file_system_registry.cc b/chrome/browser/media_galleries/media_file_system_registry.cc
index 6efcadf..6d5ad1e 100644
--- a/chrome/browser/media_galleries/media_file_system_registry.cc
+++ b/chrome/browser/media_galleries/media_file_system_registry.cc
@@ -31,6 +31,7 @@
 #include "components/storage_monitor/storage_monitor.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_details.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_process_host_observer.h"
 #include "content/public/browser/render_view_host.h"
@@ -163,7 +164,7 @@
 
 void RPHReferenceManager::ReferenceFromWebContents(
     content::WebContents* contents) {
-  RenderProcessHost* rph = contents->GetRenderProcessHost();
+  RenderProcessHost* rph = contents->GetMainFrame()->GetProcess();
   if (!base::ContainsKey(observer_map_, rph)) {
     observer_map_[rph] = base::MakeUnique<RPHObserver>(this, rph);
   }
@@ -241,7 +242,7 @@
 
 void RPHReferenceManager::OnWebContentsDestroyedOrNavigated(
     WebContents* contents) {
-  RenderProcessHost* rph = contents->GetRenderProcessHost();
+  RenderProcessHost* rph = contents->GetMainFrame()->GetProcess();
   auto rph_info = observer_map_.find(rph);
   DCHECK(rph_info != observer_map_.end());
 
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc
index 912d07a..397ed07 100644
--- a/chrome/browser/metrics/chrome_metrics_service_client.cc
+++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -208,10 +208,10 @@
 
   if (metrics_reporting_enabled) {
     // Enable reading any existing saved metrics.
-    file_metrics_provider->RegisterSource(
+    file_metrics_provider->RegisterSource(metrics::FileMetricsProvider::Params(
         metrics_file,
         metrics::FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_FILE,
-        association, metrics_name);
+        association, metrics_name));
   } else {
     // When metrics reporting is not enabled, any existing file should be
     // deleted in order to preserve user privacy.
@@ -246,10 +246,11 @@
         ChromeMetricsServiceClient::kBrowserMetricsName);
     if (metrics_reporting_enabled) {
       file_metrics_provider->RegisterSource(
-          browser_metrics_upload_dir,
-          metrics::FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_DIR,
-          metrics::FileMetricsProvider::ASSOCIATE_INTERNAL_PROFILE,
-          ChromeMetricsServiceClient::kBrowserMetricsName);
+          metrics::FileMetricsProvider::Params(
+              browser_metrics_upload_dir,
+              metrics::FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_DIR,
+              metrics::FileMetricsProvider::ASSOCIATE_INTERNAL_PROFILE,
+              ChromeMetricsServiceClient::kBrowserMetricsName));
 
       base::FilePath active_path;
       base::GlobalHistogramAllocator::ConstructFilePaths(
@@ -258,10 +259,10 @@
       // Register data that will be populated for the current run. "Active"
       // files need an empty "prefs_key" because they update the file itself.
       file_metrics_provider->RegisterSource(
-          active_path,
-          metrics::FileMetricsProvider::SOURCE_HISTOGRAMS_ACTIVE_FILE,
-          metrics::FileMetricsProvider::ASSOCIATE_CURRENT_RUN,
-          base::StringPiece());
+          metrics::FileMetricsProvider::Params(
+              active_path,
+              metrics::FileMetricsProvider::SOURCE_HISTOGRAMS_ACTIVE_FILE,
+              metrics::FileMetricsProvider::ASSOCIATE_CURRENT_RUN));
     } else {
       // When metrics reporting is not enabled, any existing files should be
       // deleted in order to preserve user privacy.
@@ -279,11 +280,11 @@
   // Read metrics file from setup.exe.
   base::FilePath program_dir;
   base::PathService::Get(base::DIR_EXE, &program_dir);
-  file_metrics_provider->RegisterSource(
+  file_metrics_provider->RegisterSource(metrics::FileMetricsProvider::Params(
       program_dir.AppendASCII(installer::kSetupHistogramAllocatorName),
       metrics::FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_DIR,
       metrics::FileMetricsProvider::ASSOCIATE_CURRENT_RUN,
-      installer::kSetupHistogramAllocatorName);
+      installer::kSetupHistogramAllocatorName));
 #endif
 
   return file_metrics_provider;
diff --git a/chrome/browser/metrics/chrome_metrics_services_manager_client.cc b/chrome/browser/metrics/chrome_metrics_services_manager_client.cc
index f00964e..9b01aaa3 100644
--- a/chrome/browser/metrics/chrome_metrics_services_manager_client.cc
+++ b/chrome/browser/metrics/chrome_metrics_services_manager_client.cc
@@ -46,17 +46,23 @@
 #include "chromeos/settings/cros_settings_names.h"
 #endif  // defined(OS_CHROMEOS)
 
-namespace {
+namespace metrics {
 
-// Name of the variations param that defines the sampling rate.
-const char kRateParamName[] = "sampling_rate_per_mille";
-
+namespace internal {
 // Metrics reporting feature. This feature, along with user consent, controls if
 // recording and reporting are enabled. If the feature is enabled, but no
 // consent is given, then there will be no recording or reporting.
 const base::Feature kMetricsReportingFeature{"MetricsReporting",
                                              base::FEATURE_ENABLED_BY_DEFAULT};
 
+}  // namespace internal
+}  // namespace metrics
+
+namespace {
+
+// Name of the variations param that defines the sampling rate.
+const char kRateParamName[] = "sampling_rate_per_mille";
+
 // Posts |GoogleUpdateSettings::StoreMetricsClientInfo| on blocking pool thread
 // because it needs access to IO and cannot work from UI thread.
 void PostStoreMetricsClientInfo(const metrics::ClientInfo& client_info) {
@@ -180,7 +186,7 @@
   // Setup the feature.
   const std::string& group_name = trial->GetGroupNameWithoutActivation();
   feature_list->RegisterFieldTrialOverride(
-      kMetricsReportingFeature.name,
+      metrics::internal::kMetricsReportingFeature.name,
       group_name == kSampledOutGroup
           ? base::FeatureList::OVERRIDE_DISABLE_FEATURE
           : base::FeatureList::OVERRIDE_ENABLE_FEATURE,
@@ -196,7 +202,8 @@
   if (!IsClientEligibleForSampling())
     return true;
 
-  return base::FeatureList::IsEnabled(kMetricsReportingFeature);
+  return base::FeatureList::IsEnabled(
+      metrics::internal::kMetricsReportingFeature);
 }
 
 // static
@@ -207,7 +214,7 @@
     return false;
 
   std::string rate_str = variations::GetVariationParamValueByFeature(
-      kMetricsReportingFeature, kRateParamName);
+      metrics::internal::kMetricsReportingFeature, kRateParamName);
   if (rate_str.empty())
     return false;
 
@@ -253,6 +260,10 @@
   return enabled_state_provider_->IsReportingEnabled();
 }
 
+bool ChromeMetricsServicesManagerClient::IsMetricsConsentGiven() {
+  return enabled_state_provider_->IsConsentGiven();
+}
+
 #if defined(OS_WIN)
 void ChromeMetricsServicesManagerClient::UpdateRunningServices(
     bool may_record,
diff --git a/chrome/browser/metrics/chrome_metrics_services_manager_client.h b/chrome/browser/metrics/chrome_metrics_services_manager_client.h
index a851aaf62..5eb0071 100644
--- a/chrome/browser/metrics/chrome_metrics_services_manager_client.h
+++ b/chrome/browser/metrics/chrome_metrics_services_manager_client.h
@@ -22,6 +22,11 @@
 namespace metrics {
 class EnabledStateProvider;
 class MetricsStateManager;
+
+// Used only for testing.
+namespace internal {
+extern const base::Feature kMetricsReportingFeature;
+}
 }
 
 namespace version_info {
@@ -72,6 +77,7 @@
   CreateEntropyProvider() override;
   net::URLRequestContextGetter* GetURLRequestContext() override;
   bool IsMetricsReportingEnabled() override;
+  bool IsMetricsConsentGiven() override;
 
 #if defined(OS_WIN)
   // On Windows, the client controls whether Crashpad can upload crash reports.
diff --git a/chrome/browser/metrics/extensions_metrics_provider.cc b/chrome/browser/metrics/extensions_metrics_provider.cc
index 75c3bfb..aaa952f 100644
--- a/chrome/browser/metrics/extensions_metrics_provider.cc
+++ b/chrome/browser/metrics/extensions_metrics_provider.cc
@@ -13,17 +13,30 @@
 
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/install_verifier.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "components/metrics/metrics_log.h"
 #include "components/metrics/metrics_state_manager.h"
 #include "components/metrics/proto/system_profile.pb.h"
+#include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
+#include "extensions/common/disable_reason.h"
+#include "extensions/common/extension.h"
 #include "extensions/common/extension_set.h"
+#include "extensions/common/manifest.h"
+#include "extensions/common/manifest_constants.h"
+#include "extensions/common/manifest_handlers/background_info.h"
+#include "extensions/common/manifest_url_handlers.h"
 #include "third_party/smhasher/src/City.h"
 
+using extensions::Extension;
+using extensions::Manifest;
+using metrics::ExtensionInstallProto;
+
 namespace {
 
 // The number of possible hash keys that a client may use.  The UMA client_id
@@ -114,6 +127,219 @@
   return state;
 }
 
+ExtensionInstallProto::Type GetType(Manifest::Type type) {
+  switch (type) {
+    case Manifest::TYPE_UNKNOWN:
+      return ExtensionInstallProto::UNKNOWN_TYPE;
+    case Manifest::TYPE_EXTENSION:
+      return ExtensionInstallProto::EXTENSION;
+    case Manifest::TYPE_THEME:
+      return ExtensionInstallProto::THEME;
+    case Manifest::TYPE_USER_SCRIPT:
+      return ExtensionInstallProto::USER_SCRIPT;
+    case Manifest::TYPE_HOSTED_APP:
+      return ExtensionInstallProto::HOSTED_APP;
+    case Manifest::TYPE_LEGACY_PACKAGED_APP:
+      return ExtensionInstallProto::LEGACY_PACKAGED_APP;
+    case Manifest::TYPE_PLATFORM_APP:
+      return ExtensionInstallProto::PLATFORM_APP;
+    case Manifest::TYPE_SHARED_MODULE:
+      return ExtensionInstallProto::SHARED_MODULE;
+    case Manifest::NUM_LOAD_TYPES:
+      NOTREACHED();
+      // Fall through.
+  }
+  return ExtensionInstallProto::UNKNOWN_TYPE;
+}
+
+ExtensionInstallProto::InstallLocation GetInstallLocation(
+    Manifest::Location location) {
+  switch (location) {
+    case Manifest::INVALID_LOCATION:
+      return ExtensionInstallProto::UNKNOWN_LOCATION;
+    case Manifest::INTERNAL:
+      return ExtensionInstallProto::INTERNAL;
+    case Manifest::EXTERNAL_PREF:
+      return ExtensionInstallProto::EXTERNAL_PREF;
+    case Manifest::EXTERNAL_REGISTRY:
+      return ExtensionInstallProto::EXTERNAL_REGISTRY;
+    case Manifest::UNPACKED:
+      return ExtensionInstallProto::UNPACKED;
+    case Manifest::COMPONENT:
+      return ExtensionInstallProto::COMPONENT;
+    case Manifest::EXTERNAL_PREF_DOWNLOAD:
+      return ExtensionInstallProto::EXTERNAL_PREF_DOWNLOAD;
+    case Manifest::EXTERNAL_POLICY_DOWNLOAD:
+      return ExtensionInstallProto::EXTERNAL_POLICY_DOWNLOAD;
+    case Manifest::COMMAND_LINE:
+      return ExtensionInstallProto::COMMAND_LINE;
+    case Manifest::EXTERNAL_POLICY:
+      return ExtensionInstallProto::EXTERNAL_POLICY;
+    case Manifest::EXTERNAL_COMPONENT:
+      return ExtensionInstallProto::EXTERNAL_COMPONENT;
+    case Manifest::NUM_LOCATIONS:
+      NOTREACHED();
+      // Fall through.
+  }
+  return ExtensionInstallProto::UNKNOWN_LOCATION;
+}
+
+ExtensionInstallProto::ActionType GetActionType(const Manifest& manifest) {
+  // Arbitrary order; each of these is mutually exclusive.
+  if (manifest.HasKey(extensions::manifest_keys::kBrowserAction))
+    return ExtensionInstallProto::BROWSER_ACTION;
+  if (manifest.HasKey(extensions::manifest_keys::kPageAction))
+    return ExtensionInstallProto::PAGE_ACTION;
+  if (manifest.HasKey(extensions::manifest_keys::kSystemIndicator))
+    return ExtensionInstallProto::SYSTEM_INDICATOR;
+  return ExtensionInstallProto::NO_ACTION;
+}
+
+ExtensionInstallProto::BackgroundScriptType GetBackgroundScriptType(
+    const Extension& extension) {
+  // Arbitrary order; each of these is mutally exclusive.
+  if (extensions::BackgroundInfo::HasPersistentBackgroundPage(&extension))
+    return ExtensionInstallProto::PERSISTENT_BACKGROUND_PAGE;
+  if (extensions::BackgroundInfo::HasLazyBackgroundPage(&extension))
+    return ExtensionInstallProto::EVENT_PAGE;
+
+  // If an extension had neither a persistent nor lazy background page, it must
+  // not have a background page.
+  DCHECK(!extensions::BackgroundInfo::HasBackgroundPage(&extension));
+  return ExtensionInstallProto::NO_BACKGROUND_SCRIPT;
+}
+
+static_assert(extensions::disable_reason::DISABLE_REASON_LAST == (1LL << 17),
+              "Adding a new disable reason? Be sure to include the new reason "
+              "below, update the test to exercise it, and then adjust this "
+              "value for DISABLE_REASON_LAST");
+std::vector<ExtensionInstallProto::DisableReason> GetDisableReasons(
+    const extensions::ExtensionId& id,
+    extensions::ExtensionPrefs* prefs) {
+  static struct {
+    extensions::disable_reason::DisableReason disable_reason;
+    ExtensionInstallProto::DisableReason proto_disable_reason;
+  } disable_reason_map[] = {
+      {extensions::disable_reason::DISABLE_USER_ACTION,
+       ExtensionInstallProto::USER_ACTION},
+      {extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE,
+       ExtensionInstallProto::PERMISSIONS_INCREASE},
+      {extensions::disable_reason::DISABLE_RELOAD,
+       ExtensionInstallProto::RELOAD},
+      {extensions::disable_reason::DISABLE_UNSUPPORTED_REQUIREMENT,
+       ExtensionInstallProto::UNSUPPORTED_REQUIREMENT},
+      {extensions::disable_reason::DISABLE_SIDELOAD_WIPEOUT,
+       ExtensionInstallProto::SIDELOAD_WIPEOUT},
+      {extensions::disable_reason::DEPRECATED_DISABLE_UNKNOWN_FROM_SYNC,
+       ExtensionInstallProto::UNKNOWN_FROM_SYNC},
+      {extensions::disable_reason::DISABLE_NOT_VERIFIED,
+       ExtensionInstallProto::NOT_VERIFIED},
+      {extensions::disable_reason::DISABLE_GREYLIST,
+       ExtensionInstallProto::GREYLIST},
+      {extensions::disable_reason::DISABLE_CORRUPTED,
+       ExtensionInstallProto::CORRUPTED},
+      {extensions::disable_reason::DISABLE_REMOTE_INSTALL,
+       ExtensionInstallProto::REMOTE_INSTALL},
+      {extensions::disable_reason::DISABLE_EXTERNAL_EXTENSION,
+       ExtensionInstallProto::EXTERNAL_EXTENSION},
+      {extensions::disable_reason::DISABLE_UPDATE_REQUIRED_BY_POLICY,
+       ExtensionInstallProto::UPDATE_REQUIRED_BY_POLICY},
+      {extensions::disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED,
+       ExtensionInstallProto::CUSTODIAN_APPROVAL_REQUIRED},
+      {extensions::disable_reason::DISABLE_BLOCKED_BY_POLICY,
+       ExtensionInstallProto::BLOCKED_BY_POLICY},
+  };
+
+  int disable_reasons = prefs->GetDisableReasons(id);
+  std::vector<ExtensionInstallProto::DisableReason> reasons;
+  for (const auto& entry : disable_reason_map) {
+    int mask = static_cast<int>(entry.disable_reason);
+    if ((disable_reasons & mask) != 0) {
+      reasons.push_back(entry.proto_disable_reason);
+      disable_reasons &= ~mask;
+    }
+  }
+  DCHECK_EQ(extensions::disable_reason::DisableReason::DISABLE_NONE,
+            disable_reasons);
+
+  return reasons;
+}
+
+ExtensionInstallProto::BlacklistState GetBlacklistState(
+    const extensions::ExtensionId& id,
+    extensions::ExtensionPrefs* prefs) {
+  extensions::BlacklistState state = prefs->GetExtensionBlacklistState(id);
+  switch (state) {
+    case extensions::NOT_BLACKLISTED:
+      return ExtensionInstallProto::NOT_BLACKLISTED;
+    case extensions::BLACKLISTED_MALWARE:
+      return ExtensionInstallProto::BLACKLISTED_MALWARE;
+    case extensions::BLACKLISTED_SECURITY_VULNERABILITY:
+      return ExtensionInstallProto::BLACKLISTED_SECURITY_VULNERABILITY;
+    case extensions::BLACKLISTED_CWS_POLICY_VIOLATION:
+      return ExtensionInstallProto::BLACKLISTED_CWS_POLICY_VIOLATION;
+    case extensions::BLACKLISTED_POTENTIALLY_UNWANTED:
+      return ExtensionInstallProto::BLACKLISTED_POTENTIALLY_UNWANTED;
+    case extensions::BLACKLISTED_UNKNOWN:
+      return ExtensionInstallProto::BLACKLISTED_UNKNOWN;
+  }
+  NOTREACHED();
+  return ExtensionInstallProto::BLACKLISTED_UNKNOWN;
+}
+
+// Creates the install proto for a given |extension|. |now| is the current
+// time, and |time_since_last_sample| is the elapsed time since the previous
+// sample was recorded. These are curried in for testing purposes.
+metrics::ExtensionInstallProto ConstructInstallProto(
+    const extensions::Extension& extension,
+    extensions::ExtensionPrefs* prefs,
+    base::Time last_sample_time) {
+  ExtensionInstallProto install;
+  install.set_type(GetType(extension.manifest()->type()));
+  install.set_install_location(GetInstallLocation(extension.location()));
+  install.set_manifest_version(extension.manifest_version());
+  install.set_action_type(GetActionType(*extension.manifest()));
+  install.set_has_file_access(
+      (extension.creation_flags() & Extension::ALLOW_FILE_ACCESS) != 0);
+  install.set_has_incognito_access(prefs->IsIncognitoEnabled(extension.id()));
+  install.set_is_from_store(extension.from_webstore());
+  install.set_updates_from_store(
+      extensions::ManifestURL::UpdatesFromGallery(&extension));
+  install.set_is_from_bookmark(extension.from_bookmark());
+  install.set_is_converted_from_user_script(
+      extension.converted_from_user_script());
+  install.set_is_default_installed(extension.was_installed_by_default());
+  install.set_is_oem_installed(extension.was_installed_by_oem());
+  install.set_background_script_type(GetBackgroundScriptType(extension));
+  for (const ExtensionInstallProto::DisableReason reason :
+       GetDisableReasons(extension.id(), prefs)) {
+    install.add_disable_reasons(reason);
+  }
+  install.set_blacklist_state(GetBlacklistState(extension.id(), prefs));
+  install.set_installed_in_this_sample_period(
+      prefs->GetInstallTime(extension.id()) >= last_sample_time);
+
+  return install;
+}
+
+// Returns all the extension installs for a given |profile|.
+std::vector<metrics::ExtensionInstallProto> GetInstallsForProfile(
+    Profile* profile,
+    base::Time last_sample_time) {
+  extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(profile);
+  std::unique_ptr<extensions::ExtensionSet> extensions =
+      extensions::ExtensionRegistry::Get(profile)
+          ->GenerateInstalledExtensionsSet();
+  std::vector<ExtensionInstallProto> installs;
+  installs.reserve(extensions->size());
+  for (const auto& extension : *extensions) {
+    installs.push_back(
+        ConstructInstallProto(*extension, prefs, last_sample_time));
+  }
+
+  return installs;
+}
+
 }  // namespace
 
 ExtensionsMetricsProvider::ExtensionsMetricsProvider(
@@ -178,6 +404,24 @@
     metrics::SystemProfileProto* system_profile) {
   ProvideOffStoreMetric(system_profile);
   ProvideOccupiedBucketMetric(system_profile);
+  ProvideExtensionInstallsMetrics(system_profile);
+}
+
+// static
+metrics::ExtensionInstallProto
+ExtensionsMetricsProvider::ConstructInstallProtoForTesting(
+    const extensions::Extension& extension,
+    extensions::ExtensionPrefs* prefs,
+    base::Time last_sample_time) {
+  return ConstructInstallProto(extension, prefs, last_sample_time);
+}
+
+// static
+std::vector<metrics::ExtensionInstallProto>
+ExtensionsMetricsProvider::GetInstallsForProfileForTesting(
+    Profile* profile,
+    base::Time last_sample_time) {
+  return GetInstallsForProfile(profile, last_sample_time);
 }
 
 void ExtensionsMetricsProvider::ProvideOffStoreMetric(
@@ -235,3 +479,16 @@
     system_profile->add_occupied_extension_bucket(*it);
   }
 }
+
+void ExtensionsMetricsProvider::ProvideExtensionInstallsMetrics(
+    metrics::SystemProfileProto* system_profile) {
+  std::vector<Profile*> profiles =
+      g_browser_process->profile_manager()->GetLoadedProfiles();
+  last_sample_time_ = base::Time::Now();
+  for (Profile* profile : profiles) {
+    std::vector<ExtensionInstallProto> installs =
+        GetInstallsForProfile(profile, last_sample_time_);
+    for (ExtensionInstallProto& install : installs)
+      system_profile->add_extension_install()->Swap(&install);
+  }
+}
diff --git a/chrome/browser/metrics/extensions_metrics_provider.h b/chrome/browser/metrics/extensions_metrics_provider.h
index 8bdb8fb3..e0e9ce5 100644
--- a/chrome/browser/metrics/extensions_metrics_provider.h
+++ b/chrome/browser/metrics/extensions_metrics_provider.h
@@ -9,13 +9,18 @@
 
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "base/macros.h"
+#include "base/time/time.h"
 #include "components/metrics/metrics_provider.h"
+#include "components/metrics/proto/extension_install.pb.h"
 
 class Profile;
 
 namespace extensions {
+class Extension;
+class ExtensionPrefs;
 class ExtensionSet;
 }
 
@@ -39,6 +44,14 @@
   void ProvideSystemProfileMetrics(
       metrics::SystemProfileProto* system_profile) override;
 
+  static metrics::ExtensionInstallProto ConstructInstallProtoForTesting(
+      const extensions::Extension& extension,
+      extensions::ExtensionPrefs* prefs,
+      base::Time last_sample_time);
+  static std::vector<metrics::ExtensionInstallProto>
+  GetInstallsForProfileForTesting(Profile* profile,
+                                  base::Time last_sample_time);
+
  protected:
   // Exposed for the sake of mocking in test code.
 
@@ -68,6 +81,11 @@
   // SystemProfileProto object.
   void ProvideOccupiedBucketMetric(metrics::SystemProfileProto* system_profile);
 
+  // Writes information about the installed extensions for all profiles into
+  // the proto.
+  void ProvideExtensionInstallsMetrics(
+      metrics::SystemProfileProto* system_profile);
+
   // The MetricsStateManager from which the client ID is obtained.
   metrics::MetricsStateManager* metrics_state_manager_;
 
@@ -76,6 +94,9 @@
   // GetMetricsProfile() can return a consistent value.
   Profile* cached_profile_;
 
+  // The time of our last recorded sample.
+  base::Time last_sample_time_;
+
   DISALLOW_COPY_AND_ASSIGN(ExtensionsMetricsProvider);
 };
 
diff --git a/chrome/browser/metrics/extensions_metrics_provider_unittest.cc b/chrome/browser/metrics/extensions_metrics_provider_unittest.cc
index 632fefd5..7350a4e 100644
--- a/chrome/browser/metrics/extensions_metrics_provider_unittest.cc
+++ b/chrome/browser/metrics/extensions_metrics_provider_unittest.cc
@@ -6,21 +6,38 @@
 
 #include <stdint.h>
 
+#include <algorithm>
 #include <memory>
 #include <string>
 
 #include "base/strings/string16.h"
+#include "base/test/scoped_task_environment.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_service_test_base.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile_manager.h"
 #include "components/metrics/client_info.h"
 #include "components/metrics/metrics_service.h"
 #include "components/metrics/metrics_state_manager.h"
+#include "components/metrics/proto/extension_install.pb.h"
 #include "components/metrics/proto/system_profile.pb.h"
 #include "components/metrics/test_enabled_state_provider.h"
 #include "components/prefs/testing_pref_service.h"
+#include "extensions/browser/extension_prefs.h"
+#include "extensions/common/disable_reason.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_builder.h"
 #include "extensions/common/extension_set.h"
+#include "extensions/common/value_builder.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using metrics::ExtensionInstallProto;
+using extensions::Extension;
+using extensions::ExtensionBuilder;
+using extensions::Manifest;
+using extensions::DictionaryBuilder;
+
 namespace {
 
 void StoreNoClientInfoBackup(const metrics::ClientInfo& /* client_info */) {
@@ -105,6 +122,10 @@
 // TestExtensionsMetricsProvider is encoded properly.
 TEST(ExtensionsMetricsProvider, SystemProtoEncoding) {
   metrics::SystemProfileProto system_profile;
+  base::test::ScopedTaskEnvironment task_environment;
+  TestingProfileManager testing_profile_manager(
+      TestingBrowserProcess::GetGlobal());
+  ASSERT_TRUE(testing_profile_manager.SetUp());
   TestingPrefServiceSimple local_state;
   metrics::TestEnabledStateProvider enabled_state_provider(true, true);
   metrics::MetricsService::RegisterPrefs(local_state.registry());
@@ -118,3 +139,269 @@
   EXPECT_EQ(10, system_profile.occupied_extension_bucket(0));
   EXPECT_EQ(1007, system_profile.occupied_extension_bucket(1));
 }
+
+class ExtensionMetricsProviderInstallsTest
+    : public extensions::ExtensionServiceTestBase {
+ public:
+  ExtensionMetricsProviderInstallsTest() {}
+  ~ExtensionMetricsProviderInstallsTest() override {}
+
+  void SetUp() override {
+    ExtensionServiceTestBase::SetUp();
+    InitializeEmptyExtensionService();
+    prefs_ = extensions::ExtensionPrefs::Get(profile());
+
+    last_sample_time_ = base::Time::Now() - base::TimeDelta::FromMinutes(30);
+  }
+
+  ExtensionInstallProto ConstructProto(const Extension& extension) {
+    return ExtensionsMetricsProvider::ConstructInstallProtoForTesting(
+        extension, prefs_, last_sample_time_);
+  }
+  std::vector<ExtensionInstallProto> GetInstallsForProfile() {
+    return ExtensionsMetricsProvider::GetInstallsForProfileForTesting(
+        profile(), last_sample_time_);
+  }
+
+  extensions::ExtensionPrefs* prefs() { return prefs_; }
+  void set_last_sample_time(base::Time last_sample_time) {
+    last_sample_time_ = last_sample_time;
+  }
+
+ private:
+  extensions::ExtensionPrefs* prefs_ = nullptr;
+  base::Time last_sample_time_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExtensionMetricsProviderInstallsTest);
+};
+
+// Tests the various aspects of constructing a relevant proto for a given
+// extension installation.
+TEST_F(ExtensionMetricsProviderInstallsTest, TestProtoConstruction) {
+  auto add_extension = [this](const Extension* extension) {
+    prefs()->OnExtensionInstalled(extension, Extension::ENABLED,
+                                  syncer::StringOrdinal(),
+                                  extensions::kInstallFlagNone, std::string());
+  };
+
+  {
+    // Test basic prototype construction. All fields should be present, except
+    // disable reasons (which should be empty).
+    scoped_refptr<const Extension> extension =
+        ExtensionBuilder("test").SetLocation(Manifest::INTERNAL).Build();
+    add_extension(extension.get());
+    ExtensionInstallProto install = ConstructProto(*extension);
+    EXPECT_TRUE(install.has_type());
+    EXPECT_EQ(ExtensionInstallProto::EXTENSION, install.type());
+
+    EXPECT_TRUE(install.has_install_location());
+    EXPECT_EQ(ExtensionInstallProto::INTERNAL, install.install_location());
+
+    EXPECT_TRUE(install.has_manifest_version());
+    EXPECT_EQ(2, install.manifest_version());
+
+    EXPECT_TRUE(install.has_action_type());
+    EXPECT_EQ(ExtensionInstallProto::NO_ACTION, install.action_type());
+
+    EXPECT_TRUE(install.has_has_file_access());
+    EXPECT_FALSE(install.has_file_access());
+
+    EXPECT_TRUE(install.has_has_incognito_access());
+    EXPECT_FALSE(install.has_incognito_access());
+
+    EXPECT_TRUE(install.has_updates_from_store());
+    EXPECT_FALSE(install.updates_from_store());
+
+    EXPECT_TRUE(install.has_is_from_bookmark());
+    EXPECT_FALSE(install.is_from_bookmark());
+
+    EXPECT_TRUE(install.has_is_converted_from_user_script());
+    EXPECT_FALSE(install.is_converted_from_user_script());
+
+    EXPECT_TRUE(install.has_is_default_installed());
+    EXPECT_FALSE(install.is_default_installed());
+
+    EXPECT_TRUE(install.has_is_oem_installed());
+    EXPECT_FALSE(install.is_oem_installed());
+
+    EXPECT_TRUE(install.has_background_script_type());
+    EXPECT_EQ(ExtensionInstallProto::NO_BACKGROUND_SCRIPT,
+              install.background_script_type());
+
+    EXPECT_EQ(0, install.disable_reasons_size());
+
+    EXPECT_TRUE(install.has_blacklist_state());
+    EXPECT_EQ(ExtensionInstallProto::NOT_BLACKLISTED,
+              install.blacklist_state());
+
+    EXPECT_TRUE(install.has_installed_in_this_sample_period());
+    EXPECT_TRUE(install.installed_in_this_sample_period());
+  }
+
+  // It's not helpful to exhaustively test each possible variation of each
+  // field in the proto (since in many cases the test code would then be
+  // re-writing the original code), but we test a few of the more interesting
+  // cases.
+
+  {
+    // Test the type() field; extensions of different types should be reported
+    // as such.
+    scoped_refptr<const Extension> extension =
+        ExtensionBuilder("app", ExtensionBuilder::Type::PLATFORM_APP)
+            .SetLocation(Manifest::INTERNAL)
+            .Build();
+    add_extension(extension.get());
+    ExtensionInstallProto install = ConstructProto(*extension);
+    EXPECT_EQ(ExtensionInstallProto::PLATFORM_APP, install.type());
+  }
+
+  {
+    // Test the install location.
+    scoped_refptr<const Extension> extension =
+        ExtensionBuilder("unpacked").SetLocation(Manifest::UNPACKED).Build();
+    add_extension(extension.get());
+    ExtensionInstallProto install = ConstructProto(*extension);
+    EXPECT_EQ(ExtensionInstallProto::UNPACKED, install.install_location());
+  }
+
+  {
+    // Test the extension action as a browser action.
+    scoped_refptr<const Extension> extension =
+        ExtensionBuilder("browser_action")
+            .SetLocation(Manifest::INTERNAL)
+            .SetAction(ExtensionBuilder::ActionType::BROWSER_ACTION)
+            .Build();
+    add_extension(extension.get());
+    ExtensionInstallProto install = ConstructProto(*extension);
+    EXPECT_EQ(ExtensionInstallProto::BROWSER_ACTION, install.action_type());
+  }
+
+  {
+    // Test the extension action as a page action.
+    scoped_refptr<const Extension> extension =
+        ExtensionBuilder("page_action")
+            .SetLocation(Manifest::INTERNAL)
+            .SetAction(ExtensionBuilder::ActionType::PAGE_ACTION)
+            .Build();
+    add_extension(extension.get());
+    ExtensionInstallProto install = ConstructProto(*extension);
+    EXPECT_EQ(ExtensionInstallProto::PAGE_ACTION, install.action_type());
+  }
+
+  {
+    // Test the disable reasons field.
+    scoped_refptr<const Extension> extension =
+        ExtensionBuilder("disable_reasons")
+            .SetLocation(Manifest::INTERNAL)
+            .Build();
+    add_extension(extension.get());
+    prefs()->SetExtensionDisabled(
+        extension->id(), extensions::disable_reason::DISABLE_USER_ACTION);
+    {
+      ExtensionInstallProto install = ConstructProto(*extension);
+      ASSERT_EQ(1, install.disable_reasons_size());
+      EXPECT_EQ(ExtensionInstallProto::USER_ACTION,
+                install.disable_reasons().Get(0));
+    }
+    // Adding additional disable reasons should result in all reasons being
+    // reported.
+    prefs()->AddDisableReason(extension->id(),
+                              extensions::disable_reason::DISABLE_CORRUPTED);
+    {
+      ExtensionInstallProto install = ConstructProto(*extension);
+      ASSERT_EQ(2, install.disable_reasons_size());
+      EXPECT_EQ(ExtensionInstallProto::USER_ACTION,
+                install.disable_reasons().Get(0));
+      EXPECT_EQ(ExtensionInstallProto::CORRUPTED,
+                install.disable_reasons().Get(1));
+    }
+  }
+
+  {
+    // Test that event pages are reported correctly.
+    DictionaryBuilder background;
+    background.SetBoolean("persistent", false)
+        .Set("scripts", extensions::ListBuilder().Append("script.js").Build());
+    scoped_refptr<const Extension> extension =
+        ExtensionBuilder("event_page")
+            .SetLocation(Manifest::INTERNAL)
+            .MergeManifest(DictionaryBuilder()
+                               .Set("background", background.Build())
+                               .Build())
+            .Build();
+    add_extension(extension.get());
+    ExtensionInstallProto install = ConstructProto(*extension);
+    EXPECT_EQ(ExtensionInstallProto::EVENT_PAGE,
+              install.background_script_type());
+  }
+
+  {
+    // Test that persistent background pages are reported correctly.
+    DictionaryBuilder background;
+    background.SetBoolean("persistent", true)
+        .Set("scripts", extensions::ListBuilder().Append("script.js").Build());
+    scoped_refptr<const Extension> extension =
+        ExtensionBuilder("persisent_background")
+            .SetLocation(Manifest::INTERNAL)
+            .MergeManifest(DictionaryBuilder()
+                               .Set("background", background.Build())
+                               .Build())
+            .Build();
+    add_extension(extension.get());
+    ExtensionInstallProto install = ConstructProto(*extension);
+    EXPECT_EQ(ExtensionInstallProto::PERSISTENT_BACKGROUND_PAGE,
+              install.background_script_type());
+  }
+
+  {
+    // Test changing the blacklist state.
+    scoped_refptr<const Extension> extension =
+        ExtensionBuilder("blacklist").SetLocation(Manifest::INTERNAL).Build();
+    add_extension(extension.get());
+    prefs()->SetExtensionBlacklistState(
+        extension->id(), extensions::BLACKLISTED_SECURITY_VULNERABILITY);
+    ExtensionInstallProto install = ConstructProto(*extension);
+    EXPECT_EQ(ExtensionInstallProto::BLACKLISTED_SECURITY_VULNERABILITY,
+              install.blacklist_state());
+  }
+
+  {
+    // Test that the installed_in_this_sample_period boolean is correctly
+    // reported.
+    scoped_refptr<const Extension> extension =
+        ExtensionBuilder("installtime").SetLocation(Manifest::INTERNAL).Build();
+    add_extension(extension.get());
+    set_last_sample_time(base::Time::Now() + base::TimeDelta::FromMinutes(60));
+    ExtensionInstallProto install = ConstructProto(*extension);
+    EXPECT_FALSE(install.installed_in_this_sample_period());
+  }
+}
+
+// Tests that we retrieve all extensions associated with a given profile.
+TEST_F(ExtensionMetricsProviderInstallsTest,
+       TestGettingAllExtensionsInProfile) {
+  scoped_refptr<const Extension> extension =
+      ExtensionBuilder("extension").Build();
+  service()->AddExtension(extension.get());
+  scoped_refptr<const Extension> app =
+      ExtensionBuilder("app", ExtensionBuilder::Type::PLATFORM_APP).Build();
+  service()->AddExtension(app.get());
+  service()->DisableExtension(app->id(),
+                              extensions::disable_reason::DISABLE_USER_ACTION);
+
+  std::vector<ExtensionInstallProto> installs = GetInstallsForProfile();
+  // There should be two installs total.
+  ASSERT_EQ(2u, installs.size());
+  // One should be the extension, and the other should be the app. We don't
+  // check the specifics of the proto, since that's tested above.
+  EXPECT_TRUE(std::any_of(installs.begin(), installs.end(),
+                          [](const ExtensionInstallProto& install) {
+                            return install.type() ==
+                                   ExtensionInstallProto::EXTENSION;
+                          }));
+  EXPECT_TRUE(std::any_of(installs.begin(), installs.end(),
+                          [](const ExtensionInstallProto& install) {
+                            return install.type() ==
+                                   ExtensionInstallProto::PLATFORM_APP;
+                          }));
+}
diff --git a/chrome/browser/metrics/renderer_uptime_web_contents_observer.cc b/chrome/browser/metrics/renderer_uptime_web_contents_observer.cc
index f9c11ee2..cd3945c 100644
--- a/chrome/browser/metrics/renderer_uptime_web_contents_observer.cc
+++ b/chrome/browser/metrics/renderer_uptime_web_contents_observer.cc
@@ -6,6 +6,7 @@
 
 #include "base/memory/ptr_util.h"
 #include "chrome/browser/metrics/renderer_uptime_tracker.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 
 DEFINE_WEB_CONTENTS_USER_DATA_KEY(metrics::RendererUptimeWebContentsObserver);
@@ -32,7 +33,7 @@
 
 void RendererUptimeWebContentsObserver::DocumentAvailableInMainFrame() {
   RendererUptimeTracker::Get()->OnLoadInMainFrame(
-      web_contents()->GetRenderProcessHost()->GetID());
+      web_contents()->GetMainFrame()->GetProcess()->GetID());
 }
 
 }  // namespace metrics
diff --git a/chrome/browser/metrics/thread_watcher.cc b/chrome/browser/metrics/thread_watcher.cc
index 41c3eab..fce991e 100644
--- a/chrome/browser/metrics/thread_watcher.cc
+++ b/chrome/browser/metrics/thread_watcher.cc
@@ -552,8 +552,12 @@
                 unresponsive_threshold, crash_on_hang_threads);
   StartWatching(BrowserThread::IO, "IO", kSleepTime, kUnresponsiveTime,
                 unresponsive_threshold, crash_on_hang_threads);
+  StartWatching(BrowserThread::DB, "DB", kSleepTime, kUnresponsiveTime,
+                unresponsive_threshold, crash_on_hang_threads);
   StartWatching(BrowserThread::FILE, "FILE", kSleepTime, kUnresponsiveTime,
                 unresponsive_threshold, crash_on_hang_threads);
+  StartWatching(BrowserThread::CACHE, "CACHE", kSleepTime, kUnresponsiveTime,
+                unresponsive_threshold, crash_on_hang_threads);
 }
 
 // static
diff --git a/chrome/browser/metrics/thread_watcher_report_hang.cc b/chrome/browser/metrics/thread_watcher_report_hang.cc
index 917eeec..9ba6a7f 100644
--- a/chrome/browser/metrics/thread_watcher_report_hang.cc
+++ b/chrome/browser/metrics/thread_watcher_report_hang.cc
@@ -50,39 +50,60 @@
   ReportThreadHang();
 }
 
+NOINLINE void ThreadUnresponsive_DB() {
+  volatile int inhibit_comdat = __LINE__;
+  ALLOW_UNUSED_LOCAL(inhibit_comdat);
+  ReportThreadHang();
+}
+
 NOINLINE void ThreadUnresponsive_FILE() {
   volatile int inhibit_comdat = __LINE__;
   ALLOW_UNUSED_LOCAL(inhibit_comdat);
   ReportThreadHang();
 }
 
+NOINLINE void ThreadUnresponsive_FILE_USER_BLOCKING() {
+  volatile int inhibit_comdat = __LINE__;
+  ALLOW_UNUSED_LOCAL(inhibit_comdat);
+  ReportThreadHang();
+}
+
 NOINLINE void ThreadUnresponsive_PROCESS_LAUNCHER() {
   volatile int inhibit_comdat = __LINE__;
   ALLOW_UNUSED_LOCAL(inhibit_comdat);
   ReportThreadHang();
 }
 
+NOINLINE void ThreadUnresponsive_CACHE() {
+  volatile int inhibit_comdat = __LINE__;
+  ALLOW_UNUSED_LOCAL(inhibit_comdat);
+  ReportThreadHang();
+}
+
 NOINLINE void ThreadUnresponsive_IO() {
   volatile int inhibit_comdat = __LINE__;
   ALLOW_UNUSED_LOCAL(inhibit_comdat);
   ReportThreadHang();
 }
 
-NOINLINE void CrashBecauseThreadWasUnresponsive(
-    content::BrowserThread::ID thread_id) {
-  switch (thread_id) {
-    case content::BrowserThread::UI:
-      return ThreadUnresponsive_UI();
-    case content::BrowserThread::FILE:
-      return ThreadUnresponsive_FILE();
-    case content::BrowserThread::PROCESS_LAUNCHER:
-      return ThreadUnresponsive_PROCESS_LAUNCHER();
-    case content::BrowserThread::IO:
-      return ThreadUnresponsive_IO();
-    case content::BrowserThread::ID_COUNT:
-      NOTREACHED();
-      break;
-  }
+NOINLINE void CrashBecauseThreadWasUnresponsive(int thread_id) {
+  // TODO(rtenneti): The following is a temporary change to check thread_id
+  // numbers explicitly so that we will have minimum code. Will change after the
+  // test run to use content::BrowserThread::ID enum.
+  if (thread_id == 0)
+    return ThreadUnresponsive_UI();
+  else if (thread_id == 1)
+    return ThreadUnresponsive_DB();
+  else if (thread_id == 2)
+    return ThreadUnresponsive_FILE();
+  else if (thread_id == 3)
+    return ThreadUnresponsive_FILE_USER_BLOCKING();
+  else if (thread_id == 4)
+    return ThreadUnresponsive_PROCESS_LAUNCHER();
+  else if (thread_id == 5)
+    return ThreadUnresponsive_CACHE();
+  else if (thread_id == 6)
+    return ThreadUnresponsive_IO();
 }
 
 }  // namespace metrics
diff --git a/chrome/browser/metrics/thread_watcher_report_hang.h b/chrome/browser/metrics/thread_watcher_report_hang.h
index 16f82614..69acc85 100644
--- a/chrome/browser/metrics/thread_watcher_report_hang.h
+++ b/chrome/browser/metrics/thread_watcher_report_hang.h
@@ -6,7 +6,6 @@
 #define CHROME_BROWSER_METRICS_THREAD_WATCHER_REPORT_HANG_H_
 
 #include "base/compiler_specific.h"
-#include "content/public/browser/browser_thread.h"
 
 namespace metrics {
 
@@ -20,8 +19,7 @@
 
 // This function makes it possible to tell from the callstack alone what thread
 // was unresponsive.
-NOINLINE void CrashBecauseThreadWasUnresponsive(
-    content::BrowserThread::ID thread_id);
+NOINLINE void CrashBecauseThreadWasUnresponsive(int thread_id);
 
 }  // namespace metrics
 
diff --git a/chrome/browser/metrics/ukm_browsertest.cc b/chrome/browser/metrics/ukm_browsertest.cc
index d224665..b67153ae 100644
--- a/chrome/browser/metrics/ukm_browsertest.cc
+++ b/chrome/browser/metrics/ukm_browsertest.cc
@@ -5,6 +5,7 @@
 #include "base/run_loop.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
+#include "chrome/browser/metrics/chrome_metrics_services_manager_client.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
@@ -49,10 +50,12 @@
  public:
   UkmBrowserTest() : SyncTest(SINGLE_CLIENT) {}
 
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    SyncTest::SetUpCommandLine(command_line);
-    command_line->AppendSwitchASCII(switches::kEnableFeatures,
-                                    ukm::kUkmFeature.name);
+  void SetUp() override {
+    // Explicitly enable UKM and disable the MetricsReporting (which should
+    // not affect UKM).
+    scoped_feature_list_.InitWithFeatures({ukm::kUkmFeature},
+                                          {internal::kMetricsReportingFeature});
+    SyncTest::SetUp();
   }
 
  protected:
@@ -97,6 +100,7 @@
   ukm::UkmService* ukm_service() {
     return static_cast<ukm::UkmService*>(ukm::UkmRecorder::Get());
   }
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 // Make sure that UKM is disabled while an incognito window is open.
@@ -223,6 +227,36 @@
   ChromeMetricsServiceAccessor::SetMetricsAndCrashReportingForTesting(nullptr);
 }
 
+// Make sure that UKM is not affected by MetricsReporting Feature (sampling).
+IN_PROC_BROWSER_TEST_F(UkmBrowserTest, MetricsReportingCheck) {
+  // Need to set the Metrics Default to OPT_OUT to trigger MetricsReporting.
+  DCHECK(g_browser_process);
+  PrefService* local_state = g_browser_process->local_state();
+  metrics::ForceRecordMetricsReportingDefaultState(
+      local_state, metrics::EnableMetricsDefault::OPT_OUT);
+  // Verify that kMetricsReportingFeature is disabled (i.e. other metrics
+  // services will be sampled out).
+  EXPECT_FALSE(
+      base::FeatureList::IsEnabled(internal::kMetricsReportingFeature));
+
+  // Enable metrics recording and update MetricsServicesManager.
+  bool metrics_enabled = true;
+  ChromeMetricsServiceAccessor::SetMetricsAndCrashReportingForTesting(
+      &metrics_enabled);
+  g_browser_process->GetMetricsServicesManager()->UpdateUploadPermissions(true);
+
+  Profile* profile = ProfileManager::GetActiveUserProfile();
+  std::unique_ptr<ProfileSyncServiceHarness> harness =
+      EnableSyncForProfile(profile);
+
+  Browser* sync_browser = CreateBrowser(profile);
+  EXPECT_TRUE(ukm_enabled());
+
+  harness->service()->RequestStop(browser_sync::ProfileSyncService::CLEAR_DATA);
+  CloseBrowserSynchronously(sync_browser);
+  ChromeMetricsServiceAccessor::SetMetricsAndCrashReportingForTesting(nullptr);
+}
+
 // TODO(crbug/745939): Add a tests for disable w/ multiprofiles.
 
 // TODO(crbug/745939): Add a tests for guest profile.
diff --git a/chrome/browser/nacl_host/test/BUILD.gn b/chrome/browser/nacl_host/test/BUILD.gn
index 0715b33..0de6e09 100644
--- a/chrome/browser/nacl_host/test/BUILD.gn
+++ b/chrome/browser/nacl_host/test/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/features.gni")
+import("//components/nacl/features.gni")
 
 if (enable_nacl && (is_linux || is_win)) {
   executable("mock_nacl_gdb") {
diff --git a/chrome/browser/net/async_dns_field_trial.cc b/chrome/browser/net/async_dns_field_trial.cc
deleted file mode 100644
index c46ceb1..0000000
--- a/chrome/browser/net/async_dns_field_trial.cc
+++ /dev/null
@@ -1,107 +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.
-
-#include "chrome/browser/net/async_dns_field_trial.h"
-
-#include "base/metrics/field_trial.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/strings/string_util.h"
-#include "build/build_config.h"
-
-namespace chrome_browser_net {
-
-namespace {
-
-// Source of the default value of the async DNS pref; used in histograms.
-enum PrefDefaultSource {
-  PLATFORM,
-  FIELD_TRIAL,
-  HARD_CODED_DEFAULT,
-  MAX_PREF_DEFAULT_SOURCE
-};
-
-// Source of the actual value of the async DNS pref; used in histograms.
-enum PrefSource {
-  MANAGED_PREF,
-  SUPERVISED_PREF,
-  EXTENSION_PREF,
-  COMMAND_LINE_PREF,
-  USER_PREF,
-  RECOMMENDED_PREF,
-  DEFAULT_PREF,
-  UNKNOWN_PREF,
-  MAX_PREF_SOURCE
-};
-
-void HistogramPrefDefaultSource(PrefDefaultSource source, bool enabled) {
-  if (enabled) {
-    UMA_HISTOGRAM_ENUMERATION("AsyncDNS.PrefDefaultSource_Enabled",
-                              source,
-                              MAX_PREF_DEFAULT_SOURCE);
-  } else {
-    UMA_HISTOGRAM_ENUMERATION("AsyncDNS.PrefDefaultSource_Disabled",
-                              source,
-                              MAX_PREF_DEFAULT_SOURCE);
-  }
-}
-
-void HistogramPrefSource(PrefSource source, bool enabled) {
-  if (enabled) {
-    UMA_HISTOGRAM_ENUMERATION("AsyncDNS.PrefSource_Enabled",
-                              source,
-                              MAX_PREF_SOURCE);
-  } else {
-    UMA_HISTOGRAM_ENUMERATION("AsyncDNS.PrefSource_Disabled",
-                              source,
-                              MAX_PREF_SOURCE);
-  }
-}
-
-}  // namespace
-
-bool ConfigureAsyncDnsFieldTrial() {
-#if defined(OS_CHROMEOS) || defined(OS_MACOSX)
-  const bool kDefault = true;
-#else
-  const bool kDefault = false;
-#endif
-
-  // Configure the AsyncDns field trial as follows:
-  // groups AsyncDnsA and AsyncDnsB: return true,
-  // groups SystemDnsA and SystemDnsB: return false,
-  // otherwise (trial absent): return default.
-  std::string group_name = base::FieldTrialList::FindFullName("AsyncDns");
-  if (!group_name.empty()) {
-    const bool enabled = base::StartsWith(group_name, "AsyncDns",
-                                          base::CompareCase::INSENSITIVE_ASCII);
-    HistogramPrefDefaultSource(FIELD_TRIAL, enabled);
-    return enabled;
-  }
-  HistogramPrefDefaultSource(HARD_CODED_DEFAULT, kDefault);
-  return kDefault;
-}
-
-void LogAsyncDnsPrefSource(const PrefService::Preference* pref) {
-  CHECK(pref);
-
-  const base::Value* value = pref->GetValue();
-  CHECK(value);
-
-  bool enabled;
-  bool got_value = value->GetAsBoolean(&enabled);
-  CHECK(got_value);
-
-  if (pref->IsManaged())
-    HistogramPrefSource(MANAGED_PREF, enabled);
-  else if (pref->IsExtensionControlled())
-    HistogramPrefSource(EXTENSION_PREF, enabled);
-  else if (pref->IsUserControlled())
-    HistogramPrefSource(USER_PREF, enabled);
-  else if (pref->IsDefaultValue())
-    HistogramPrefSource(DEFAULT_PREF, enabled);
-  else
-    HistogramPrefSource(UNKNOWN_PREF, enabled);
-}
-
-}  // namespace chrome_browser_net
diff --git a/chrome/browser/net/async_dns_field_trial.h b/chrome/browser/net/async_dns_field_trial.h
deleted file mode 100644
index f8fced04..0000000
--- a/chrome/browser/net/async_dns_field_trial.h
+++ /dev/null
@@ -1,21 +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 CHROME_BROWSER_NET_ASYNC_DNS_FIELD_TRIAL_H_
-#define CHROME_BROWSER_NET_ASYNC_DNS_FIELD_TRIAL_H_
-
-#include "components/prefs/pref_service.h"
-
-namespace chrome_browser_net {
-
-// Returns true when the async resolver should be used.
-bool ConfigureAsyncDnsFieldTrial();
-
-// Logs the derivation of the async DNS pref's actual value, for debugging.
-// Must be called on the UI thread, since it accesses prefs directly.
-void LogAsyncDnsPrefSource(const PrefService::Preference* pref);
-
-}  // namespace chrome_browser_net
-
-#endif  // CHROME_BROWSER_NET_ASYNC_DNS_FIELD_TRIAL_H_
diff --git a/chrome/browser/net/url_info.cc b/chrome/browser/net/url_info.cc
index 83a8ae3..758619d 100644
--- a/chrome/browser/net/url_info.cc
+++ b/chrome/browser/net/url_info.cc
@@ -130,27 +130,12 @@
   state_ = ASSIGNED;
   queue_duration_ = GetDuration();
   DLogResultsStats("DNS Prefetch assigned");
-  UMA_HISTOGRAM_TIMES("DNS.PrefetchQueue", queue_duration_);
 }
 
 void UrlInfo::RemoveFromQueue() {
   DCHECK(ASSIGNED == state_);
   state_ = old_prequeue_state_;
   DLogResultsStats("DNS Prefetch reset to prequeue");
-  const TimeDelta kBoundary = TimeDelta::FromSeconds(2);
-  if (queue_duration_ > kBoundary) {
-    UMA_HISTOGRAM_MEDIUM_TIMES("DNS.QueueRecycledDeltaOver2",
-                               queue_duration_ - kBoundary);
-    return;
-  }
-  // Make a custom linear histogram for the region from 0 to boundary.
-  static const size_t kBucketCount = 52;
-  static base::HistogramBase* histogram(NULL);
-  if (!histogram)
-    histogram = base::LinearHistogram::FactoryTimeGet(
-        "DNS.QueueRecycledUnder2", TimeDelta(), kBoundary, kBucketCount,
-        base::HistogramBase::kUmaTargetedHistogramFlag);
-  histogram->AddTime(queue_duration_);
 }
 
 void UrlInfo::SetPendingDeleteState() {
diff --git a/chrome/browser/notifications/OWNERS b/chrome/browser/notifications/OWNERS
index 62fa249..bedc61b 100644
--- a/chrome/browser/notifications/OWNERS
+++ b/chrome/browser/notifications/OWNERS
@@ -8,6 +8,10 @@
 # Mac files
 per-file *_mac*=rsesek@chromium.org
 
+# Windows files
+per-file *_win*=finnur@chromium.org
+per-file notification_template_builder*=finnur@chromium.org
+
 per-file *permission_context*=file://chrome/browser/permissions/PERMISSIONS_OWNERS
 
 # TEAM: platform-capabilities@chromium.org
diff --git a/chrome/browser/notifications/application_notifier_source.cc b/chrome/browser/notifications/application_notifier_source.cc
deleted file mode 100644
index 5fd578d7..0000000
--- a/chrome/browser/notifications/application_notifier_source.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/notifications/application_notifier_source.h"
-
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/extensions/chrome_app_icon_loader.h"
-#include "chrome/browser/notifications/notifier_state_tracker.h"
-#include "chrome/browser/notifications/notifier_state_tracker_factory.h"
-#include "chrome/browser/profiles/profile.h"
-#include "extensions/common/constants.h"
-#include "extensions/common/extension_set.h"
-#include "extensions/common/permissions/api_permission.h"
-#include "extensions/common/permissions/permissions_data.h"
-#include "ui/message_center/notifier_settings.h"
-
-ApplicationNotifierSource::ApplicationNotifierSource(Observer* observer)
-    : observer_(observer) {}
-
-ApplicationNotifierSource::~ApplicationNotifierSource() {}
-
-std::vector<std::unique_ptr<message_center::Notifier>>
-ApplicationNotifierSource::GetNotifierList(Profile* profile) {
-  std::vector<std::unique_ptr<message_center::Notifier>> notifiers;
-  const extensions::ExtensionSet& extension_set =
-      extensions::ExtensionRegistry::Get(profile)->enabled_extensions();
-  // The extension icon size has to be 32x32 at least to load bigger icons if
-  // the icon doesn't exist for the specified size, and in that case it falls
-  // back to the default icon. The fetched icon will be resized in the
-  // settings dialog. See chrome/browser/extensions/extension_icon_image.cc
-  // and crbug.com/222931
-  app_icon_loader_.reset(new extensions::ChromeAppIconLoader(
-      profile, extension_misc::EXTENSION_ICON_SMALL, this));
-  for (extensions::ExtensionSet::const_iterator iter = extension_set.begin();
-       iter != extension_set.end(); ++iter) {
-    const extensions::Extension* extension = iter->get();
-    if (!extension->permissions_data()->HasAPIPermission(
-            extensions::APIPermission::kNotifications)) {
-      continue;
-    }
-
-    // Hosted apps are no longer able to affect the notifications permission
-    // state for web notifications.
-    // TODO(dewittj): Deprecate the 'notifications' permission for hosted
-    // apps.
-    if (extension->is_hosted_app())
-      continue;
-
-    message_center::NotifierId notifier_id(
-        message_center::NotifierId::APPLICATION, extension->id());
-    NotifierStateTracker* const notifier_state_tracker =
-        NotifierStateTrackerFactory::GetForProfile(profile);
-    notifiers.emplace_back(new message_center::Notifier(
-        notifier_id, base::UTF8ToUTF16(extension->name()),
-        notifier_state_tracker->IsNotifierEnabled(notifier_id)));
-    app_icon_loader_->FetchImage(extension->id());
-  }
-
-  return notifiers;
-}
-
-void ApplicationNotifierSource::SetNotifierEnabled(
-    Profile* profile,
-    const message_center::NotifierId& notifier_id,
-    bool enabled) {
-  NotifierStateTrackerFactory::GetForProfile(profile)->SetNotifierEnabled(
-      notifier_id, enabled);
-  observer_->OnNotifierEnabledChanged(notifier_id, enabled);
-}
-
-message_center::NotifierId::NotifierType
-ApplicationNotifierSource::GetNotifierType() {
-  return message_center::NotifierId::APPLICATION;
-}
-
-void ApplicationNotifierSource::OnAppImageUpdated(const std::string& id,
-                                                  const gfx::ImageSkia& image) {
-  observer_->OnIconImageUpdated(
-      message_center::NotifierId(message_center::NotifierId::APPLICATION, id),
-      gfx::Image(image));
-}
diff --git a/chrome/browser/notifications/application_notifier_source.h b/chrome/browser/notifications/application_notifier_source.h
deleted file mode 100644
index 396d631..0000000
--- a/chrome/browser/notifications/application_notifier_source.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_NOTIFICATIONS_APPLICATION_NOTIFIER_SOURCE_H_
-#define CHROME_BROWSER_NOTIFICATIONS_APPLICATION_NOTIFIER_SOURCE_H_
-
-#include "chrome/browser/notifications/notifier_source.h"
-#include "chrome/browser/ui/app_icon_loader_delegate.h"
-
-class AppIconLoader;
-
-class ApplicationNotifierSource : public NotifierSource,
-                                  public AppIconLoaderDelegate {
- public:
-  explicit ApplicationNotifierSource(Observer* observer);
-  ~ApplicationNotifierSource() override;
-
-  std::vector<std::unique_ptr<message_center::Notifier>> GetNotifierList(
-      Profile* profile) override;
-
-  void SetNotifierEnabled(Profile* profile,
-                          const message_center::NotifierId& notifier_id,
-                          bool enabled) override;
-
-  message_center::NotifierId::NotifierType GetNotifierType() override;
-
- private:
-  // Overridden from AppIconLoaderDelegate.
-  void OnAppImageUpdated(const std::string& id,
-                         const gfx::ImageSkia& image) override;
-
-  std::unique_ptr<AppIconLoader> app_icon_loader_;
-
-  // Lifetime of parent must be longer than the source.
-  Observer* observer_;
-};
-
-#endif  // CHROME_BROWSER_NOTIFICATIONS_APPLICATION_NOTIFIER_SOURCE_H_
diff --git a/chrome/browser/notifications/arc_application_notifier_controller_chromeos.cc b/chrome/browser/notifications/arc_application_notifier_controller_chromeos.cc
new file mode 100644
index 0000000..3ac637b
--- /dev/null
+++ b/chrome/browser/notifications/arc_application_notifier_controller_chromeos.cc
@@ -0,0 +1,126 @@
+// 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/notifications/arc_application_notifier_controller_chromeos.h"
+
+#include <set>
+
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/profiles/profile.h"
+#include "ui/base/layout.h"
+#include "ui/display/display.h"
+#include "ui/display/screen.h"
+#include "ui/message_center/notifier_settings.h"
+
+namespace arc {
+
+namespace {
+constexpr int kArcAppIconSizeInDp = 48;
+}  // namespace
+
+ArcApplicationNotifierControllerChromeOS::
+    ArcApplicationNotifierControllerChromeOS(
+        NotifierController::Observer* observer)
+    : observer_(observer), last_profile_(nullptr) {}
+
+ArcApplicationNotifierControllerChromeOS::
+    ~ArcApplicationNotifierControllerChromeOS() {
+  StopObserving();
+}
+
+std::vector<std::unique_ptr<message_center::Notifier>>
+ArcApplicationNotifierControllerChromeOS::GetNotifierList(Profile* profile) {
+  package_to_app_ids_.clear();
+  icons_.clear();
+  StopObserving();
+
+  ArcAppListPrefs* const app_list = ArcAppListPrefs::Get(profile);
+  if (!app_list) {
+    // It can be null in unit tests.
+    return std::vector<std::unique_ptr<message_center::Notifier>>();
+  }
+  const std::vector<std::string>& app_ids = app_list->GetAppIds();
+  std::vector<std::unique_ptr<message_center::Notifier>> results;
+
+  last_profile_ = profile;
+  app_list->AddObserver(this);
+
+  for (const std::string& app_id : app_ids) {
+    const auto app = app_list->GetApp(app_id);
+    // Handle packages having multiple launcher activities.
+    if (!app || package_to_app_ids_.count(app->package_name))
+      continue;
+
+    const auto package = app_list->GetPackage(app->package_name);
+    if (!package || package->system)
+      continue;
+
+    // Load icons for notifier.
+    std::unique_ptr<ArcAppIcon> icon(
+        new ArcAppIcon(profile, app_id,
+                       // ARC icon is available only for 48x48 dips.
+                       kArcAppIconSizeInDp,
+                       // The life time of icon must shorter than |this|.
+                       this));
+    // Apply icon now to set the default image.
+    OnIconUpdated(icon.get());
+
+    // Add notifiers.
+    package_to_app_ids_.insert(std::make_pair(app->package_name, app_id));
+    message_center::NotifierId notifier_id(
+        message_center::NotifierId::ARC_APPLICATION, app_id);
+    std::unique_ptr<message_center::Notifier> notifier(
+        new message_center::Notifier(notifier_id, base::UTF8ToUTF16(app->name),
+                                     app->notifications_enabled));
+    notifier->icon = gfx::Image(icon->image_skia());
+    icons_.push_back(std::move(icon));
+    results.push_back(std::move(notifier));
+  }
+
+  return results;
+}
+
+void ArcApplicationNotifierControllerChromeOS::SetNotifierEnabled(
+    Profile* profile,
+    const message_center::NotifierId& notifier_id,
+    bool enabled) {
+  ArcAppListPrefs* const app_list = ArcAppListPrefs::Get(profile);
+  app_list->SetNotificationsEnabled(notifier_id.id, enabled);
+  // OnNotifierEnabledChanged will be invoked via ArcAppListPrefs::Observer.
+}
+
+void ArcApplicationNotifierControllerChromeOS::OnNotificationsEnabledChanged(
+    const std::string& package_name,
+    bool enabled) {
+  auto it = package_to_app_ids_.find(package_name);
+  if (it == package_to_app_ids_.end())
+    return;
+  observer_->OnNotifierEnabledChanged(
+      message_center::NotifierId(message_center::NotifierId::ARC_APPLICATION,
+                                 it->second),
+      enabled);
+}
+
+void ArcApplicationNotifierControllerChromeOS::OnNotifierSettingsClosing() {
+  icons_.clear();
+  package_to_app_ids_.clear();
+  StopObserving();
+}
+
+void ArcApplicationNotifierControllerChromeOS::OnIconUpdated(ArcAppIcon* icon) {
+  observer_->OnIconImageUpdated(
+      message_center::NotifierId(message_center::NotifierId::ARC_APPLICATION,
+                                 icon->app_id()),
+      gfx::Image(icon->image_skia()));
+}
+
+void ArcApplicationNotifierControllerChromeOS::StopObserving() {
+  if (!last_profile_)
+    return;
+  ArcAppListPrefs* const app_list = ArcAppListPrefs::Get(last_profile_);
+  app_list->RemoveObserver(this);
+  last_profile_ = nullptr;
+}
+
+}  // namespace arc
diff --git a/chrome/browser/notifications/arc_application_notifier_controller_chromeos.h b/chrome/browser/notifications/arc_application_notifier_controller_chromeos.h
new file mode 100644
index 0000000..29c14993
--- /dev/null
+++ b/chrome/browser/notifications/arc_application_notifier_controller_chromeos.h
@@ -0,0 +1,62 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_NOTIFICATIONS_ARC_APPLICATION_NOTIFIER_CONTROLLER_CHROMEOS_H_
+#define CHROME_BROWSER_NOTIFICATIONS_ARC_APPLICATION_NOTIFIER_CONTROLLER_CHROMEOS_H_
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "chrome/browser/notifications/notifier_controller.h"
+#include "chrome/browser/ui/app_list/arc/arc_app_icon.h"
+#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
+
+class Profile;
+
+namespace message_center {
+struct Notifier;
+}
+
+namespace arc {
+
+// TODO(hirono): Observe enabled flag change and notify it to message center.
+class ArcApplicationNotifierControllerChromeOS
+    : public NotifierController,
+      public ArcAppIcon::Observer,
+      public ArcAppListPrefs::Observer {
+ public:
+  explicit ArcApplicationNotifierControllerChromeOS(
+      NotifierController::Observer* observer);
+
+  ~ArcApplicationNotifierControllerChromeOS() override;
+
+  // TODO(hirono): Rewrite the function with new API to fetch package list.
+  std::vector<std::unique_ptr<message_center::Notifier>> GetNotifierList(
+      Profile* profile) override;
+  void SetNotifierEnabled(Profile* profile,
+                          const message_center::NotifierId& notifier_id,
+                          bool enabled) override;
+  void OnNotifierSettingsClosing() override;
+
+ private:
+  // Overriden from ArcAppIcon::Observer.
+  void OnIconUpdated(ArcAppIcon* icon) override;
+  void StopObserving();
+
+  // Overriden from ArcAppListPrefs::Observer.
+  void OnNotificationsEnabledChanged(const std::string& package_name,
+                                     bool enabled) override;
+
+  NotifierController::Observer* observer_;
+  std::vector<std::unique_ptr<ArcAppIcon>> icons_;
+  std::map<std::string, std::string> package_to_app_ids_;
+  Profile* last_profile_;
+};
+
+}  // namespace arc
+
+#endif  // CHROME_BROWSER_NOTIFICATIONS_ARC_APPLICATION_NOTIFIER_CONTROLLER_CHROMEOS_H_
diff --git a/chrome/browser/notifications/arc_application_notifier_source_chromeos.cc b/chrome/browser/notifications/arc_application_notifier_source_chromeos.cc
deleted file mode 100644
index 6db8f8a..0000000
--- a/chrome/browser/notifications/arc_application_notifier_source_chromeos.cc
+++ /dev/null
@@ -1,129 +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/notifications/arc_application_notifier_source_chromeos.h"
-
-#include <set>
-
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/profiles/profile.h"
-#include "ui/base/layout.h"
-#include "ui/display/display.h"
-#include "ui/display/screen.h"
-#include "ui/message_center/notifier_settings.h"
-
-namespace arc {
-
-namespace {
-constexpr int kArcAppIconSizeInDp = 48;
-}  // namespace
-
-ArcApplicationNotifierSourceChromeOS::ArcApplicationNotifierSourceChromeOS(
-    NotifierSource::Observer* observer)
-    : observer_(observer), last_profile_(nullptr) {}
-
-ArcApplicationNotifierSourceChromeOS::~ArcApplicationNotifierSourceChromeOS() {
-  StopObserving();
-}
-
-std::vector<std::unique_ptr<message_center::Notifier>>
-ArcApplicationNotifierSourceChromeOS::GetNotifierList(Profile* profile) {
-  package_to_app_ids_.clear();
-  icons_.clear();
-  StopObserving();
-
-  ArcAppListPrefs* const app_list = ArcAppListPrefs::Get(profile);
-  if (!app_list) {
-    // It can be null in unit tests.
-    return std::vector<std::unique_ptr<message_center::Notifier>>();
-  }
-  const std::vector<std::string>& app_ids = app_list->GetAppIds();
-  std::vector<std::unique_ptr<message_center::Notifier>> results;
-
-  last_profile_ = profile;
-  app_list->AddObserver(this);
-
-  for (const std::string& app_id : app_ids) {
-    const auto app = app_list->GetApp(app_id);
-    // Handle packages having multiple launcher activities.
-    if (!app || package_to_app_ids_.count(app->package_name))
-      continue;
-
-    const auto package = app_list->GetPackage(app->package_name);
-    if (!package || package->system)
-      continue;
-
-    // Load icons for notifier.
-    std::unique_ptr<ArcAppIcon> icon(
-        new ArcAppIcon(profile, app_id,
-                       // ARC icon is available only for 48x48 dips.
-                       kArcAppIconSizeInDp,
-                       // The life time of icon must shorter than |this|.
-                       this));
-    // Apply icon now to set the default image.
-    OnIconUpdated(icon.get());
-
-    // Add notifiers.
-    package_to_app_ids_.insert(std::make_pair(app->package_name, app_id));
-    message_center::NotifierId notifier_id(
-        message_center::NotifierId::ARC_APPLICATION, app_id);
-    std::unique_ptr<message_center::Notifier> notifier(
-        new message_center::Notifier(notifier_id, base::UTF8ToUTF16(app->name),
-                                     app->notifications_enabled));
-    notifier->icon = gfx::Image(icon->image_skia());
-    icons_.push_back(std::move(icon));
-    results.push_back(std::move(notifier));
-  }
-
-  return results;
-}
-
-void ArcApplicationNotifierSourceChromeOS::SetNotifierEnabled(
-    Profile* profile,
-    const message_center::NotifierId& notifier_id,
-    bool enabled) {
-  ArcAppListPrefs* const app_list = ArcAppListPrefs::Get(profile);
-  app_list->SetNotificationsEnabled(notifier_id.id, enabled);
-  // OnNotifierEnabledChanged will be invoked via ArcAppListPrefs::Observer.
-}
-
-void ArcApplicationNotifierSourceChromeOS::OnNotificationsEnabledChanged(
-    const std::string& package_name,
-    bool enabled) {
-  auto it = package_to_app_ids_.find(package_name);
-  if (it == package_to_app_ids_.end())
-    return;
-  observer_->OnNotifierEnabledChanged(
-      message_center::NotifierId(message_center::NotifierId::ARC_APPLICATION,
-                                 it->second),
-      enabled);
-}
-
-void ArcApplicationNotifierSourceChromeOS::OnNotifierSettingsClosing() {
-  icons_.clear();
-  package_to_app_ids_.clear();
-  StopObserving();
-}
-
-message_center::NotifierId::NotifierType
-ArcApplicationNotifierSourceChromeOS::GetNotifierType() {
-  return message_center::NotifierId::ARC_APPLICATION;
-}
-
-void ArcApplicationNotifierSourceChromeOS::OnIconUpdated(ArcAppIcon* icon) {
-  observer_->OnIconImageUpdated(
-      message_center::NotifierId(message_center::NotifierId::ARC_APPLICATION,
-                                 icon->app_id()),
-      gfx::Image(icon->image_skia()));
-}
-
-void ArcApplicationNotifierSourceChromeOS::StopObserving() {
-  if (!last_profile_)
-    return;
-  ArcAppListPrefs* const app_list = ArcAppListPrefs::Get(last_profile_);
-  app_list->RemoveObserver(this);
-  last_profile_ = nullptr;
-}
-
-}  // namespace arc
diff --git a/chrome/browser/notifications/arc_application_notifier_source_chromeos.h b/chrome/browser/notifications/arc_application_notifier_source_chromeos.h
deleted file mode 100644
index 1908d84..0000000
--- a/chrome/browser/notifications/arc_application_notifier_source_chromeos.h
+++ /dev/null
@@ -1,62 +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 CHROME_BROWSER_NOTIFICATIONS_ARC_APPLICATION_NOTIFIER_SOURCE_CHROMEOS_H_
-#define CHROME_BROWSER_NOTIFICATIONS_ARC_APPLICATION_NOTIFIER_SOURCE_CHROMEOS_H_
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "chrome/browser/notifications/notifier_source.h"
-#include "chrome/browser/ui/app_list/arc/arc_app_icon.h"
-#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
-
-class Profile;
-
-namespace message_center {
-struct Notifier;
-}
-
-namespace arc {
-
-// TODO(hirono): Observe enabled flag change and notify it to message center.
-class ArcApplicationNotifierSourceChromeOS : public NotifierSource,
-                                             public ArcAppIcon::Observer,
-                                             public ArcAppListPrefs::Observer {
- public:
-  explicit ArcApplicationNotifierSourceChromeOS(
-      NotifierSource::Observer* observer);
-
-  ~ArcApplicationNotifierSourceChromeOS() override;
-
-  // TODO(hirono): Rewrite the function with new API to fetch package list.
-  std::vector<std::unique_ptr<message_center::Notifier>> GetNotifierList(
-      Profile* profile) override;
-  void SetNotifierEnabled(Profile* profile,
-                          const message_center::NotifierId& notifier_id,
-                          bool enabled) override;
-  void OnNotifierSettingsClosing() override;
-  message_center::NotifierId::NotifierType GetNotifierType() override;
-
- private:
-  // Overriden from ArcAppIcon::Observer.
-  void OnIconUpdated(ArcAppIcon* icon) override;
-  void StopObserving();
-
-  // Overriden from ArcAppListPrefs::Observer.
-  void OnNotificationsEnabledChanged(const std::string& package_name,
-                                     bool enabled) override;
-
-  NotifierSource::Observer* observer_;
-  std::vector<std::unique_ptr<ArcAppIcon>> icons_;
-  std::map<std::string, std::string> package_to_app_ids_;
-  Profile* last_profile_;
-};
-
-}  // namespace arc
-
-#endif  // CHROME_BROWSER_NOTIFICATIONS_ARC_APPLICATION_NOTIFIER_SOURCE_CHROMEOS_H_
diff --git a/chrome/browser/notifications/extension_notifier_controller.cc b/chrome/browser/notifications/extension_notifier_controller.cc
new file mode 100644
index 0000000..1ac06bfe
--- /dev/null
+++ b/chrome/browser/notifications/extension_notifier_controller.cc
@@ -0,0 +1,78 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/notifications/extension_notifier_controller.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/extensions/chrome_app_icon_loader.h"
+#include "chrome/browser/notifications/notifier_state_tracker.h"
+#include "chrome/browser/notifications/notifier_state_tracker_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "extensions/common/constants.h"
+#include "extensions/common/extension_set.h"
+#include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/permissions_data.h"
+#include "ui/message_center/notifier_settings.h"
+
+ExtensionNotifierController::ExtensionNotifierController(Observer* observer)
+    : observer_(observer) {}
+
+ExtensionNotifierController::~ExtensionNotifierController() {}
+
+std::vector<std::unique_ptr<message_center::Notifier>>
+ExtensionNotifierController::GetNotifierList(Profile* profile) {
+  std::vector<std::unique_ptr<message_center::Notifier>> notifiers;
+  const extensions::ExtensionSet& extension_set =
+      extensions::ExtensionRegistry::Get(profile)->enabled_extensions();
+  // The extension icon size has to be 32x32 at least to load bigger icons if
+  // the icon doesn't exist for the specified size, and in that case it falls
+  // back to the default icon. The fetched icon will be resized in the
+  // settings dialog. See chrome/browser/extensions/extension_icon_image.cc
+  // and crbug.com/222931
+  app_icon_loader_.reset(new extensions::ChromeAppIconLoader(
+      profile, extension_misc::EXTENSION_ICON_SMALL, this));
+  for (extensions::ExtensionSet::const_iterator iter = extension_set.begin();
+       iter != extension_set.end(); ++iter) {
+    const extensions::Extension* extension = iter->get();
+    if (!extension->permissions_data()->HasAPIPermission(
+            extensions::APIPermission::kNotifications)) {
+      continue;
+    }
+
+    // Hosted apps are no longer able to affect the notifications permission
+    // state for web notifications.
+    // TODO(dewittj): Deprecate the 'notifications' permission for hosted
+    // apps.
+    if (extension->is_hosted_app())
+      continue;
+
+    message_center::NotifierId notifier_id(
+        message_center::NotifierId::APPLICATION, extension->id());
+    NotifierStateTracker* const notifier_state_tracker =
+        NotifierStateTrackerFactory::GetForProfile(profile);
+    notifiers.emplace_back(new message_center::Notifier(
+        notifier_id, base::UTF8ToUTF16(extension->name()),
+        notifier_state_tracker->IsNotifierEnabled(notifier_id)));
+    app_icon_loader_->FetchImage(extension->id());
+  }
+
+  return notifiers;
+}
+
+void ExtensionNotifierController::SetNotifierEnabled(
+    Profile* profile,
+    const message_center::NotifierId& notifier_id,
+    bool enabled) {
+  NotifierStateTrackerFactory::GetForProfile(profile)->SetNotifierEnabled(
+      notifier_id, enabled);
+  observer_->OnNotifierEnabledChanged(notifier_id, enabled);
+}
+
+void ExtensionNotifierController::OnAppImageUpdated(
+    const std::string& id,
+    const gfx::ImageSkia& image) {
+  observer_->OnIconImageUpdated(
+      message_center::NotifierId(message_center::NotifierId::APPLICATION, id),
+      gfx::Image(image));
+}
diff --git a/chrome/browser/notifications/extension_notifier_controller.h b/chrome/browser/notifications/extension_notifier_controller.h
new file mode 100644
index 0000000..3b66e650
--- /dev/null
+++ b/chrome/browser/notifications/extension_notifier_controller.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_NOTIFICATIONS_EXTENSION_NOTIFIER_CONTROLLER_H_
+#define CHROME_BROWSER_NOTIFICATIONS_EXTENSION_NOTIFIER_CONTROLLER_H_
+
+#include "chrome/browser/notifications/notifier_controller.h"
+#include "chrome/browser/ui/app_icon_loader_delegate.h"
+
+class AppIconLoader;
+
+// Controls extensions and apps. Each extension gets its own row in the settings
+// ui.
+class ExtensionNotifierController : public NotifierController,
+                                    public AppIconLoaderDelegate {
+ public:
+  explicit ExtensionNotifierController(Observer* observer);
+  ~ExtensionNotifierController() override;
+
+  std::vector<std::unique_ptr<message_center::Notifier>> GetNotifierList(
+      Profile* profile) override;
+
+  void SetNotifierEnabled(Profile* profile,
+                          const message_center::NotifierId& notifier_id,
+                          bool enabled) override;
+
+ private:
+  // Overridden from AppIconLoaderDelegate.
+  void OnAppImageUpdated(const std::string& id,
+                         const gfx::ImageSkia& image) override;
+
+  std::unique_ptr<AppIconLoader> app_icon_loader_;
+
+  // Lifetime of parent must be longer than the source.
+  Observer* observer_;
+};
+
+#endif  // CHROME_BROWSER_NOTIFICATIONS_EXTENSION_NOTIFIER_CONTROLLER_H_
diff --git a/chrome/browser/notifications/message_center_settings_controller.cc b/chrome/browser/notifications/message_center_settings_controller.cc
index 7a4732a6..f8c47a7 100644
--- a/chrome/browser/notifications/message_center_settings_controller.cc
+++ b/chrome/browser/notifications/message_center_settings_controller.cc
@@ -16,8 +16,8 @@
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/notifications/application_notifier_source.h"
-#include "chrome/browser/notifications/web_page_notifier_source.h"
+#include "chrome/browser/notifications/extension_notifier_controller.h"
+#include "chrome/browser/notifications/web_page_notifier_controller.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_attributes_entry.h"
 #include "chrome/browser/profiles/profile_attributes_storage.h"
@@ -30,8 +30,8 @@
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
-#include "chrome/browser/notifications/arc_application_notifier_source_chromeos.h"
-#include "chrome/browser/notifications/system_component_notifier_source_chromeos.h"
+#include "chrome/browser/notifications/arc_application_notifier_controller_chromeos.h"
+#include "chrome/browser/notifications/system_component_notifier_controller_chromeos.h"
 #endif
 
 using message_center::Notifier;
@@ -58,7 +58,8 @@
 ProfileNotifierGroup::ProfileNotifierGroup(const base::string16& display_name,
                                            const base::string16& login_info,
                                            const base::FilePath& profile_path)
-    : message_center::NotifierGroup(display_name, login_info), profile_(NULL) {
+    : message_center::NotifierGroup(display_name, login_info),
+      profile_(nullptr) {
   // Try to get the profile
   profile_ =
       g_browser_process->profile_manager()->GetProfileByPath(profile_path);
@@ -104,26 +105,23 @@
   profile_attributes_storage_.AddObserver(this);
   RebuildNotifierGroups(false);
 
+  sources_.insert(
+      std::make_pair(NotifierId::APPLICATION,
+                     std::make_unique<ExtensionNotifierController>(this)));
   sources_.insert(std::make_pair(
-      NotifierId::APPLICATION,
-      std::unique_ptr<NotifierSource>(new ApplicationNotifierSource(this))));
-  sources_.insert(std::make_pair(
-      NotifierId::WEB_PAGE,
-      std::unique_ptr<NotifierSource>(new WebPageNotifierSource(this))));
+      NotifierId::WEB_PAGE, std::make_unique<WebPageNotifierController>(this)));
 
 #if defined(OS_CHROMEOS)
   // UserManager may not exist in some tests.
   if (user_manager::UserManager::IsInitialized())
     user_manager::UserManager::Get()->AddSessionStateObserver(this);
   // For system components.
-  sources_.insert(
-      std::make_pair(NotifierId::SYSTEM_COMPONENT,
-                     std::unique_ptr<NotifierSource>(
-                         new SystemComponentNotifierSourceChromeOS(this))));
-  sources_.insert(
-      std::make_pair(NotifierId::ARC_APPLICATION,
-                     std::unique_ptr<NotifierSource>(
-                         new arc::ArcApplicationNotifierSourceChromeOS(this))));
+  sources_.insert(std::make_pair(
+      NotifierId::SYSTEM_COMPONENT,
+      std::make_unique<SystemComponentNotifierControllerChromeOS>(this)));
+  sources_.insert(std::make_pair(
+      NotifierId::ARC_APPLICATION,
+      std::make_unique<arc::ArcApplicationNotifierControllerChromeOS>(this)));
 #endif
 }
 
@@ -194,7 +192,7 @@
 
   UErrorCode error = U_ZERO_ERROR;
   std::unique_ptr<icu::Collator> collator(icu::Collator::createInstance(error));
-  NotifierComparator comparator(U_SUCCESS(error) ? collator.get() : NULL);
+  NotifierComparator comparator(U_SUCCESS(error) ? collator.get() : nullptr);
 
   std::sort(notifiers->begin(), notifiers->end(), comparator);
 }
@@ -258,12 +256,12 @@
   Profile* profile = notifier_groups_[current_notifier_group_]->profile();
 
   extensions::EventRouter* event_router = extensions::EventRouter::Get(profile);
-  std::unique_ptr<base::ListValue> args(new base::ListValue());
+  auto args = std::make_unique<base::ListValue>();
 
-  std::unique_ptr<extensions::Event> event(new extensions::Event(
+  auto event = std::make_unique<extensions::Event>(
       extensions::events::NOTIFICATIONS_ON_SHOW_SETTINGS,
       extensions::api::notifications::OnShowSettings::kEventName,
-      std::move(args)));
+      std::move(args));
   event_router->DispatchEventToExtension(extension_id, std::move(event));
 }
 
@@ -332,9 +330,8 @@
       chromeos::ProfileHelper::Get()->GetProfileByUserUnsafe(user);
   DCHECK(profile);
 
-  std::unique_ptr<message_center::ProfileNotifierGroup> group(
-      new message_center::ProfileNotifierGroup(
-          user->GetDisplayName(), user->GetDisplayName(), profile));
+  auto group = std::make_unique<message_center::ProfileNotifierGroup>(
+      user->GetDisplayName(), user->GetDisplayName(), profile);
 
   notifier_groups_.push_back(std::move(group));
   DispatchNotifierGroupChanged();
@@ -348,10 +345,9 @@
   std::vector<ProfileAttributesEntry*> entries =
       profile_attributes_storage_.GetAllProfilesAttributesSortedByName();
   for (auto* entry : entries) {
-    std::unique_ptr<message_center::ProfileNotifierGroup> group(
-        new message_center::ProfileNotifierGroup(
-            entry->GetName(), entry->GetUserName(), entry->GetPath()));
-    if (group->profile() == NULL)
+    auto group = std::make_unique<message_center::ProfileNotifierGroup>(
+        entry->GetName(), entry->GetUserName(), entry->GetPath());
+    if (!group->profile())
       continue;
 
 #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/notifications/message_center_settings_controller.h b/chrome/browser/notifications/message_center_settings_controller.h
index 0c731a03..0dfe670d 100644
--- a/chrome/browser/notifications/message_center_settings_controller.h
+++ b/chrome/browser/notifications/message_center_settings_controller.h
@@ -15,7 +15,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "build/build_config.h"
-#include "chrome/browser/notifications/notifier_source.h"
+#include "chrome/browser/notifications/notifier_controller.h"
 #include "chrome/browser/profiles/profile_attributes_storage.h"
 #include "chrome/browser/ui/app_icon_loader.h"
 #include "components/content_settings/core/common/content_settings.h"
@@ -26,7 +26,7 @@
 #include "components/user_manager/user_manager.h"
 #endif
 
-class NotifierSource;
+class NotifierController;
 
 namespace message_center {
 class ProfileNotifierGroup;
@@ -40,7 +40,7 @@
 #if defined(OS_CHROMEOS)
       public user_manager::UserManager::UserSessionStateObserver,
 #endif
-      public NotifierSource::Observer {
+      public NotifierController::Observer {
  public:
   explicit MessageCenterSettingsController(
       ProfileAttributesStorage& profile_attributes_storage);
@@ -81,7 +81,7 @@
       const base::string16& old_profile_name) override;
   void OnProfileAuthInfoChanged(const base::FilePath& profile_path) override;
 
-  // Overridden from NotifierSource::Observer.
+  // Overridden from NotifierController::Observer.
   void OnIconImageUpdated(const message_center::NotifierId&,
                           const gfx::Image&) override;
   void OnNotifierEnabledChanged(const message_center::NotifierId&,
@@ -112,7 +112,7 @@
 
   // Notifier source for each notifier type.
   std::map<message_center::NotifierId::NotifierType,
-           std::unique_ptr<NotifierSource>>
+           std::unique_ptr<NotifierController>>
       sources_;
 
   size_t current_notifier_group_;
diff --git a/chrome/browser/notifications/notification_permission_context_unittest.cc b/chrome/browser/notifications/notification_permission_context_unittest.cc
index eb6931fd..f5c7378c 100644
--- a/chrome/browser/notifications/notification_permission_context_unittest.cc
+++ b/chrome/browser/notifications/notification_permission_context_unittest.cc
@@ -4,6 +4,9 @@
 
 #include "chrome/browser/notifications/notification_permission_context.h"
 
+#include <memory>
+#include <string>
+
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/test/scoped_mock_time_message_loop_task_runner.h"
@@ -18,6 +21,7 @@
 #include "chrome/test/base/testing_profile.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "content/public/browser/permission_manager.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/test_browser_thread_bundle.h"
@@ -287,9 +291,9 @@
   GURL url("https://www.example.com");
   NavigateAndCommit(url);
 
-  const PermissionRequestID id(web_contents()->GetRenderProcessHost()->GetID(),
-                               web_contents()->GetMainFrame()->GetRoutingID(),
-                               -1);
+  const PermissionRequestID id(
+      web_contents()->GetMainFrame()->GetProcess()->GetID(),
+      web_contents()->GetMainFrame()->GetRoutingID(), -1);
 
   base::TestMockTimeTaskRunner* task_runner = SwitchToMockTime();
 
@@ -353,9 +357,9 @@
   GURL url("https://www.example.com");
   NavigateAndCommit(url);
 
-  const PermissionRequestID id(web_contents()->GetRenderProcessHost()->GetID(),
-                               web_contents()->GetMainFrame()->GetRoutingID(),
-                               -1);
+  const PermissionRequestID id(
+      web_contents()->GetMainFrame()->GetProcess()->GetID(),
+      web_contents()->GetMainFrame()->GetRoutingID(), -1);
 
   base::TestMockTimeTaskRunner* task_runner = SwitchToMockTime();
 
@@ -387,12 +391,12 @@
   NavigateAndCommit(url);
   web_contents()->WasShown();
 
-  const PermissionRequestID id0(web_contents()->GetRenderProcessHost()->GetID(),
-                                web_contents()->GetMainFrame()->GetRoutingID(),
-                                0);
-  const PermissionRequestID id1(web_contents()->GetRenderProcessHost()->GetID(),
-                                web_contents()->GetMainFrame()->GetRoutingID(),
-                                1);
+  const PermissionRequestID id0(
+      web_contents()->GetMainFrame()->GetProcess()->GetID(),
+      web_contents()->GetMainFrame()->GetRoutingID(), 0);
+  const PermissionRequestID id1(
+      web_contents()->GetMainFrame()->GetProcess()->GetID(),
+      web_contents()->GetMainFrame()->GetRoutingID(), 1);
 
   base::TestMockTimeTaskRunner* task_runner = SwitchToMockTime();
 
diff --git a/chrome/browser/notifications/notification_platform_bridge_linux.cc b/chrome/browser/notifications/notification_platform_bridge_linux.cc
index 970e721..4db3f4e8 100644
--- a/chrome/browser/notifications/notification_platform_bridge_linux.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_linux.cc
@@ -77,6 +77,9 @@
 const int kMaxImageWidth = 200;
 const int kMaxImageHeight = 100;
 
+// Notification on-screen time, in milliseconds.
+const int32_t kExpireTimeout = 25000;
+
 // The values in this enumeration correspond to those of the
 // Linux.NotificationPlatformBridge.InitializationStatus histogram, so
 // the ordering should not be changed.  New error codes should be
@@ -111,6 +114,15 @@
   return gfx::Image(*image_skia);
 }
 
+void EscapeUnsafeCharacters(std::string* message) {
+  // Canonical's notification development guidelines recommends only
+  // escaping the '&', '<', and '>' characters:
+  // https://wiki.ubuntu.com/NotificationDevelopmentGuidelines
+  base::ReplaceChars(*message, "&", "&amp;", message);
+  base::ReplaceChars(*message, "<", "&lt;", message);
+  base::ReplaceChars(*message, ">", "&gt;", message);
+}
+
 int NotificationPriorityToFdoUrgency(int priority) {
   enum FdoUrgency {
     LOW = 0,
@@ -512,11 +524,13 @@
           base::ContainsKey(capabilities_, kCapabilityBodyMarkup);
 
       if (notification->UseOriginAsContextMessage()) {
-        std::string url_display_text = net::EscapeForHTML(
+        std::string url_display_text =
             base::UTF16ToUTF8(url_formatter::FormatUrlForSecurityDisplay(
                 notification->origin_url(),
-                url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS)));
-        if (base::ContainsKey(capabilities_, kCapabilityBodyHyperlinks)) {
+                url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS));
+        EscapeUnsafeCharacters(&url_display_text);
+        if (body_markup &&
+            base::ContainsKey(capabilities_, kCapabilityBodyHyperlinks)) {
           body << "<a href=\""
                << net::EscapePath(notification->origin_url().spec()) << "\">"
                << url_display_text << "</a>";
@@ -527,13 +541,13 @@
         std::string context =
             base::UTF16ToUTF8(notification->context_message());
         if (body_markup)
-          context = net::EscapeForHTML(context);
+          EscapeUnsafeCharacters(&context);
         body << context;
       }
 
       std::string message = base::UTF16ToUTF8(notification->message());
       if (body_markup)
-        message = net::EscapeForHTML(message);
+        EscapeUnsafeCharacters(&message);
       if (body.tellp())
         body << "\n";
       body << message;
@@ -606,6 +620,14 @@
         NotificationPriorityToFdoUrgency(notification->priority()));
     hints_writer.CloseContainer(&urgency_writer);
 
+    if (notification->silent()) {
+      dbus::MessageWriter suppress_sound_writer(nullptr);
+      hints_writer.OpenDictEntry(&suppress_sound_writer);
+      suppress_sound_writer.AppendString("suppress-sound");
+      suppress_sound_writer.AppendVariantOfBool(true);
+      hints_writer.CloseContainer(&suppress_sound_writer);
+    }
+
     std::unique_ptr<base::Environment> env = base::Environment::Create();
     base::FilePath desktop_file(
         shell_integration_linux::GetDesktopName(env.get()));
@@ -636,8 +658,12 @@
 
     const int32_t kExpireTimeoutDefault = -1;
     const int32_t kExpireTimeoutNever = 0;
-    writer.AppendInt32(notification->never_timeout() ? kExpireTimeoutNever
-                                                     : kExpireTimeoutDefault);
+    writer.AppendInt32(
+        notification->never_timeout()
+            ? kExpireTimeoutNever
+            : base::ContainsKey(capabilities_, kCapabilityPersistence)
+                  ? kExpireTimeoutDefault
+                  : kExpireTimeout);
 
     std::unique_ptr<dbus::Response> response =
         notification_proxy_->CallMethodAndBlock(
diff --git a/chrome/browser/notifications/notification_platform_bridge_linux_unittest.cc b/chrome/browser/notifications/notification_platform_bridge_linux_unittest.cc
index 7195d9b..a6a7ad39 100644
--- a/chrome/browser/notifications/notification_platform_bridge_linux_unittest.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_linux_unittest.cc
@@ -84,6 +84,11 @@
     return *this;
   }
 
+  NotificationBuilder& SetSilent(bool silent) {
+    notification_.set_silent(silent);
+    return *this;
+  }
+
   NotificationBuilder& SetTitle(const base::string16& title) {
     notification_.set_title(title);
     return *this;
@@ -102,6 +107,7 @@
   std::string summary;
   std::string body;
   int32_t expire_timeout = 0;
+  bool silent = false;
 };
 
 const SkBitmap CreateBitmap(int width, int height) {
@@ -147,7 +153,13 @@
       EXPECT_TRUE(hints_reader.PopDictEntry(&dict_entry_reader));
       EXPECT_TRUE(dict_entry_reader.PopString(&str));
       dbus::MessageReader variant_reader(nullptr);
-      EXPECT_TRUE(dict_entry_reader.PopVariant(&variant_reader));
+      if (str == "suppress-sound") {
+        bool suppress_sound;
+        EXPECT_TRUE(dict_entry_reader.PopVariantOfBool(&suppress_sound));
+        request.silent = suppress_sound;
+      } else {
+        EXPECT_TRUE(dict_entry_reader.PopVariant(&variant_reader));
+      }
       EXPECT_FALSE(dict_entry_reader.HasMoreData());
     }
   }
@@ -349,14 +361,14 @@
       nullptr);
 }
 
-TEST_F(NotificationPlatformBridgeLinuxTest, NotificationTimeouts) {
-  const int32_t kExpireTimeoutDefault = -1;
+TEST_F(NotificationPlatformBridgeLinuxTest, NotificationTimeoutsNoPersistence) {
+  const int32_t kExpireTimeout = 25000;
   const int32_t kExpireTimeoutNever = 0;
   EXPECT_CALL(*mock_notification_proxy_.get(),
               CallMethodAndBlock(Calls("Notify"), _))
       .WillOnce(OnNotify(
           [=](const NotificationRequest& request) {
-            EXPECT_EQ(kExpireTimeoutDefault, request.expire_timeout);
+            EXPECT_EQ(kExpireTimeout, request.expire_timeout);
           },
           1))
       .WillOnce(OnNotify(
@@ -374,6 +386,25 @@
       NotificationBuilder("2").SetNeverTimeout(true).GetResult(), nullptr);
 }
 
+TEST_F(NotificationPlatformBridgeLinuxTest,
+       NotificationTimeoutWithPersistence) {
+  const int32_t kExpireTimeoutDefault = -1;
+  EXPECT_CALL(*mock_notification_proxy_.get(),
+              CallMethodAndBlock(Calls("Notify"), _))
+      .WillOnce(OnNotify(
+          [=](const NotificationRequest& request) {
+            EXPECT_EQ(kExpireTimeoutDefault, request.expire_timeout);
+          },
+          1));
+
+  CreateNotificationBridgeLinux(
+      std::vector<std::string>{"actions", "body", "persistence"}, true, true,
+      true);
+  notification_bridge_linux_->Display(
+      NotificationCommon::PERSISTENT, "", "", false,
+      NotificationBuilder("1").GetResult(), nullptr);
+}
+
 TEST_F(NotificationPlatformBridgeLinuxTest, NotificationImages) {
   const int kMaxImageWidth = 200;
   const int kMaxImageHeight = 100;
@@ -446,3 +477,46 @@
   CreateNotificationBridgeLinux(std::vector<std::string>{"actions"}, false,
                                 true, false);
 }
+
+TEST_F(NotificationPlatformBridgeLinuxTest, EscapeHtml) {
+  EXPECT_CALL(*mock_notification_proxy_.get(),
+              CallMethodAndBlock(Calls("Notify"), _))
+      .WillOnce(OnNotify(
+          [](const NotificationRequest& request) {
+            EXPECT_EQ("&lt;span id='1' class=\"2\"&gt;&amp;#39;&lt;/span&gt;",
+                      request.body);
+          },
+          1));
+
+  CreateNotificationBridgeLinux();
+  notification_bridge_linux_->Display(
+      NotificationCommon::PERSISTENT, "", "", false,
+      NotificationBuilder("")
+          .SetMessage(
+              base::ASCIIToUTF16("<span id='1' class=\"2\">&#39;</span>"))
+          .GetResult(),
+      nullptr);
+}
+
+TEST_F(NotificationPlatformBridgeLinuxTest, Silent) {
+  EXPECT_CALL(*mock_notification_proxy_.get(),
+              CallMethodAndBlock(Calls("Notify"), _))
+      .WillOnce(OnNotify(
+          [=](const NotificationRequest& request) {
+            EXPECT_FALSE(request.silent);
+          },
+          1))
+      .WillOnce(OnNotify(
+          [=](const NotificationRequest& request) {
+            EXPECT_TRUE(request.silent);
+          },
+          2));
+
+  CreateNotificationBridgeLinux();
+  notification_bridge_linux_->Display(
+      NotificationCommon::PERSISTENT, "", "", false,
+      NotificationBuilder("1").SetSilent(false).GetResult(), nullptr);
+  notification_bridge_linux_->Display(
+      NotificationCommon::PERSISTENT, "", "", false,
+      NotificationBuilder("2").SetSilent(true).GetResult(), nullptr);
+}
diff --git a/chrome/browser/notifications/notification_template_builder.cc b/chrome/browser/notifications/notification_template_builder.cc
index 4e69ad0..446c448 100644
--- a/chrome/browser/notifications/notification_template_builder.cc
+++ b/chrome/browser/notifications/notification_template_builder.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/notifications/notification_template_builder.h"
 
 #include "base/memory/ptr_util.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/url_formatter/elide_url.h"
@@ -15,17 +16,24 @@
 namespace {
 
 // Constants used for the XML element names and their attributes.
+const char kActionElement[] = "action";
+const char kActionsElement[] = "actions";
+const char kActivationType[] = "activationType";
+const char kArguments[] = "arguments";
+const char kBindingElement[] = "binding";
+const char kBindingElementTemplateAttribute[] = "template";
+const char kButtonIndex[] = "buttonIndex=";
+const char kContent[] = "content";
+const char kForeground[] = "foreground";
+const char kTextElement[] = "text";
+const char kTextElementIdAttribute[] = "id";
 const char kToastElement[] = "toast";
 const char kToastElementLaunchAttribute[] = "launch";
 const char kVisualElement[] = "visual";
-const char kBindingElement[] = "binding";
-const char kBindingElementTemplateAttribute[] = "template";
-const char kTextElement[] = "text";
-const char kTextElementIdAttribute[] = "id";
 
 // Name of the template used for default Chrome notifications.
 // https://msdn.microsoft.com/library/1a437614-4259-426b-8e3f-ca57368b2e7a
-const char kDefaultTemplate[] = "ToastText04";
+const char kDefaultTemplate[] = "ToastGeneric";
 
 // The XML version header that has to be stripped from the output.
 const char kXmlVersionHeader[] = "<?xml version=\"1.0\"?>\n";
@@ -55,8 +63,10 @@
                             builder->FormatOrigin(notification.origin_url()));
 
   builder->EndBindingElement();
-
   builder->EndVisualElement();
+
+  builder->AddActions(notification.buttons());
+
   builder->EndToastElement();
 
   return builder;
@@ -124,3 +134,39 @@
   xml_writer_->AppendElementContent(content);
   xml_writer_->EndElement();
 }
+
+void NotificationTemplateBuilder::AddActions(
+    const std::vector<message_center::ButtonInfo>& buttons) {
+  if (!buttons.size())
+    return;
+
+  StartActionsElement();
+
+  // TODO(finnur): Add inline replies.
+  for (size_t i = 0; i < buttons.size(); ++i) {
+    const auto& button = buttons[i];
+    WriteActionElement(button, i);
+  }
+
+  EndActionsElement();
+}
+
+void NotificationTemplateBuilder::StartActionsElement() {
+  xml_writer_->StartElement(kActionsElement);
+}
+
+void NotificationTemplateBuilder::EndActionsElement() {
+  xml_writer_->EndElement();
+}
+
+void NotificationTemplateBuilder::WriteActionElement(
+    const message_center::ButtonInfo& button,
+    int index) {
+  // TODO(finnur): Implement button images (imageUri).
+  xml_writer_->StartElement(kActionElement);
+  xml_writer_->AddAttribute(kActivationType, kForeground);
+  xml_writer_->AddAttribute(kContent, base::UTF16ToUTF8(button.title).c_str());
+  std::string param = std::string(kButtonIndex) + base::IntToString(index);
+  xml_writer_->AddAttribute(kArguments, param.c_str());
+  xml_writer_->EndElement();
+}
diff --git a/chrome/browser/notifications/notification_template_builder.h b/chrome/browser/notifications/notification_template_builder.h
index 40a5321..e0d2f0f1 100644
--- a/chrome/browser/notifications/notification_template_builder.h
+++ b/chrome/browser/notifications/notification_template_builder.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "base/macros.h"
 #include "base/strings/string16.h"
@@ -15,6 +16,7 @@
 class XmlWriter;
 
 namespace message_center {
+struct ButtonInfo;
 class Notification;
 }
 
@@ -68,6 +70,15 @@
   // https://docs.microsoft.com/en-us/uwp/schemas/tiles/toastschema/element-text
   void WriteTextElement(const std::string& id, const std::string& content);
 
+  // Writes the <actions> element.
+  // TODO(finnur): Add link to doc, once it becomes available.
+  void StartActionsElement();
+  void EndActionsElement();
+
+  // Fills in the details for the actions.
+  void AddActions(const std::vector<message_center::ButtonInfo>& buttons);
+  void WriteActionElement(const message_center::ButtonInfo& button, int index);
+
   // The XML writer to which the template will be written.
   std::unique_ptr<XmlWriter> xml_writer_;
 
diff --git a/chrome/browser/notifications/notification_template_builder_unittest.cc b/chrome/browser/notifications/notification_template_builder_unittest.cc
index 4bbb15a..f5ccc8f 100644
--- a/chrome/browser/notifications/notification_template_builder_unittest.cc
+++ b/chrome/browser/notifications/notification_template_builder_unittest.cc
@@ -52,6 +52,7 @@
   // the given |notification_data|, and writes that to |*xml_template|. Calls
   // must be wrapped in ASSERT_NO_FATAL_FAILURE().
   void BuildTemplate(const NotificationData& notification_data,
+                     const std::vector<message_center::ButtonInfo>& buttons,
                      base::string16* xml_template) {
     GURL origin_url(notification_data.origin);
 
@@ -61,6 +62,8 @@
         base::UTF8ToUTF16(notification_data.message), gfx::Image() /* icon */,
         base::string16() /* display_source */, origin_url,
         NotifierId(origin_url), RichNotificationData(), nullptr /* delegate */);
+    if (buttons.size())
+      notification.set_buttons(buttons);
 
     template_ =
         NotificationTemplateBuilder::Build(notification_data.id, notification);
@@ -79,13 +82,15 @@
 TEST_F(NotificationTemplateBuilderTest, SimpleToast) {
   NotificationData notification_data;
   base::string16 xml_template;
+  std::vector<message_center::ButtonInfo> buttons;
 
-  ASSERT_NO_FATAL_FAILURE(BuildTemplate(notification_data, &xml_template));
+  ASSERT_NO_FATAL_FAILURE(
+      BuildTemplate(notification_data, buttons, &xml_template));
 
   const wchar_t kExpectedXml[] =
       LR"(<toast launch="notification_id">
  <visual>
-  <binding template="ToastText04">
+  <binding template="ToastGeneric">
    <text id="1">My Title</text>
    <text id="2">My Message</text>
    <text id="3">example.com</text>
@@ -96,3 +101,33 @@
 
   EXPECT_EQ(xml_template, kExpectedXml);
 }
+
+TEST_F(NotificationTemplateBuilderTest, Buttons) {
+  NotificationData notification_data;
+  base::string16 xml_template;
+
+  std::vector<message_center::ButtonInfo> buttons;
+  buttons.emplace_back(base::ASCIIToUTF16("Button1"));
+  buttons.emplace_back(base::ASCIIToUTF16("Button2"));
+
+  ASSERT_NO_FATAL_FAILURE(
+      BuildTemplate(notification_data, buttons, &xml_template));
+
+  const wchar_t kExpectedXml[] =
+      LR"(<toast launch="notification_id">
+ <visual>
+  <binding template="ToastGeneric">
+   <text id="1">My Title</text>
+   <text id="2">My Message</text>
+   <text id="3">example.com</text>
+  </binding>
+ </visual>
+ <actions>
+  <action activationType="foreground" content="Button1" arguments="buttonIndex=0"/>
+  <action activationType="foreground" content="Button2" arguments="buttonIndex=1"/>
+ </actions>
+</toast>
+)";
+
+  EXPECT_EQ(xml_template, kExpectedXml);
+}
diff --git a/chrome/browser/notifications/notifier_controller.h b/chrome/browser/notifications/notifier_controller.h
new file mode 100644
index 0000000..9edb6d4
--- /dev/null
+++ b/chrome/browser/notifications/notifier_controller.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_NOTIFICATIONS_NOTIFIER_CONTROLLER_H_
+#define CHROME_BROWSER_NOTIFICATIONS_NOTIFIER_CONTROLLER_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/macros.h"
+#include "ui/message_center/notifier_settings.h"
+
+class Profile;
+
+namespace message_center {
+struct Notifier;
+}
+
+// An interface to control Notifiers, grouped by NotifierType. Controllers are
+// responsible for both collating display data and toggling settings in response
+// to user inputs.
+class NotifierController {
+ public:
+  class Observer {
+   public:
+    virtual void OnIconImageUpdated(const message_center::NotifierId& id,
+                                    const gfx::Image& image) = 0;
+    virtual void OnNotifierEnabledChanged(const message_center::NotifierId& id,
+                                          bool enabled) = 0;
+  };
+
+  NotifierController() = default;
+  virtual ~NotifierController() = default;
+
+  // Returns notifiers to display in the settings UI. Not all notifiers appear
+  // in settings. If the source starts loading for icon images, it needs to call
+  // Observer::OnIconImageUpdated after the icon is loaded.
+  virtual std::vector<std::unique_ptr<message_center::Notifier>>
+  GetNotifierList(Profile* profile) = 0;
+
+  // Set notifier enabled. |notifier_id| must have notifier type that can be
+  // handled by the source. It has responsibility to invoke
+  // Observer::OnNotifierEnabledChanged.
+  virtual void SetNotifierEnabled(Profile* profile,
+                                  const message_center::NotifierId& notifier_id,
+                                  bool enabled) = 0;
+
+  // Release temporary resouces tagged with notifier list that is returned last
+  // time.
+  virtual void OnNotifierSettingsClosing() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NotifierController);
+};
+
+#endif  // CHROME_BROWSER_NOTIFICATIONS_NOTIFIER_CONTROLLER_H_
diff --git a/chrome/browser/notifications/notifier_source.h b/chrome/browser/notifications/notifier_source.h
deleted file mode 100644
index c528046..0000000
--- a/chrome/browser/notifications/notifier_source.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_NOTIFICATIONS_NOTIFIER_SOURCE_H_
-#define CHROME_BROWSER_NOTIFICATIONS_NOTIFIER_SOURCE_H_
-
-#include <memory>
-#include <vector>
-
-#include "base/macros.h"
-#include "ui/message_center/notifier_settings.h"
-
-class Profile;
-
-namespace message_center {
-struct Notifier;
-}
-
-class NotifierSource {
- public:
-  class Observer {
-   public:
-    virtual void OnIconImageUpdated(const message_center::NotifierId& id,
-                                    const gfx::Image& image) = 0;
-    virtual void OnNotifierEnabledChanged(const message_center::NotifierId& id,
-                                          bool enabled) = 0;
-  };
-
-  NotifierSource() = default;
-  virtual ~NotifierSource() = default;
-
-  // Returns notifiers.
-  // If the source starts loading for icon images, it needs to call
-  // Observer::OnIconImageUpdated after the icon is loaded.
-  virtual std::vector<std::unique_ptr<message_center::Notifier>>
-  GetNotifierList(Profile* profile) = 0;
-
-  // Set notifier enabled. |notifier_id| must have notifier type that can be
-  // handled by the source. It has responsibility to invoke
-  // Observer::OnNotifierEnabledChanged.
-  virtual void SetNotifierEnabled(Profile* profile,
-                                  const message_center::NotifierId& notifier_id,
-                                  bool enabled) = 0;
-
-  // Release temporary resouces tagged with notifier list that is returned last
-  // time.
-  virtual void OnNotifierSettingsClosing() {}
-
-  // Notifier type provided by the source.
-  virtual message_center::NotifierId::NotifierType GetNotifierType() = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(NotifierSource);
-};
-
-#endif  // CHROME_BROWSER_NOTIFICATIONS_NOTIFIER_SOURCE_H_
diff --git a/chrome/browser/notifications/system_component_notifier_controller_chromeos.cc b/chrome/browser/notifications/system_component_notifier_controller_chromeos.cc
new file mode 100644
index 0000000..11a21e6
--- /dev/null
+++ b/chrome/browser/notifications/system_component_notifier_controller_chromeos.cc
@@ -0,0 +1,51 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/notifications/system_component_notifier_controller_chromeos.h"
+
+#include "ash/system/system_notifier.h"
+#include "chrome/browser/notifications/notifier_state_tracker.h"
+#include "chrome/browser/notifications/notifier_state_tracker_factory.h"
+#include "chrome/grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/message_center/notifier_settings.h"
+#include "ui/strings/grit/ui_strings.h"
+
+SystemComponentNotifierControllerChromeOS::
+    SystemComponentNotifierControllerChromeOS(Observer* observer)
+    : observer_(observer) {}
+
+std::vector<std::unique_ptr<message_center::Notifier>>
+SystemComponentNotifierControllerChromeOS::GetNotifierList(Profile* profile) {
+  std::vector<std::unique_ptr<message_center::Notifier>> notifiers;
+  NotifierStateTracker* const notifier_state_tracker =
+      NotifierStateTrackerFactory::GetForProfile(profile);
+
+  // Screenshot notification feature is only for ChromeOS. See
+  // crbug.com/238358
+  const base::string16& screenshot_name =
+      l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_NOTIFIER_SCREENSHOT_NAME);
+  message_center::NotifierId screenshot_notifier_id(
+      message_center::NotifierId::SYSTEM_COMPONENT,
+      ash::system_notifier::kNotifierScreenshot);
+  message_center::Notifier* const screenshot_notifier =
+      new message_center::Notifier(
+          screenshot_notifier_id, screenshot_name,
+          notifier_state_tracker->IsNotifierEnabled(screenshot_notifier_id));
+  screenshot_notifier->icon =
+      ui::ResourceBundle::GetSharedInstance().GetImageNamed(
+          IDR_SCREENSHOT_NOTIFICATION_ICON);
+  notifiers.emplace_back(screenshot_notifier);
+  return notifiers;
+}
+
+void SystemComponentNotifierControllerChromeOS::SetNotifierEnabled(
+    Profile* profile,
+    const message_center::NotifierId& notifier_id,
+    bool enabled) {
+  NotifierStateTrackerFactory::GetForProfile(profile)->SetNotifierEnabled(
+      notifier_id, enabled);
+  observer_->OnNotifierEnabledChanged(notifier_id, enabled);
+}
diff --git a/chrome/browser/notifications/system_component_notifier_controller_chromeos.h b/chrome/browser/notifications/system_component_notifier_controller_chromeos.h
new file mode 100644
index 0000000..4f59a32a
--- /dev/null
+++ b/chrome/browser/notifications/system_component_notifier_controller_chromeos.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_NOTIFICATIONS_SYSTEM_COMPONENT_NOTIFIER_CONTROLLER_CHROMEOS_H_
+#define CHROME_BROWSER_NOTIFICATIONS_SYSTEM_COMPONENT_NOTIFIER_CONTROLLER_CHROMEOS_H_
+
+#include "chrome/browser/notifications/notifier_controller.h"
+
+// TODO(estade): remove this class. See crbug.com/766846
+class SystemComponentNotifierControllerChromeOS : public NotifierController {
+ public:
+  explicit SystemComponentNotifierControllerChromeOS(Observer* observer);
+  std::vector<std::unique_ptr<message_center::Notifier>> GetNotifierList(
+      Profile* profile) override;
+  void SetNotifierEnabled(Profile* profile,
+                          const message_center::NotifierId& notifier_id,
+                          bool enabled) override;
+
+ private:
+  // Lifetime of parent must be longer than the source.
+  Observer* observer_;
+};
+
+#endif  // CHROME_BROWSER_NOTIFICATIONS_SYSTEM_COMPONENT_NOTIFIER_CONTROLLER_CHROMEOS_H_
diff --git a/chrome/browser/notifications/system_component_notifier_source_chromeos.cc b/chrome/browser/notifications/system_component_notifier_source_chromeos.cc
deleted file mode 100644
index aa85ea2..0000000
--- a/chrome/browser/notifications/system_component_notifier_source_chromeos.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/notifications/system_component_notifier_source_chromeos.h"
-
-#include "ash/system/system_notifier.h"
-#include "chrome/browser/notifications/notifier_state_tracker.h"
-#include "chrome/browser/notifications/notifier_state_tracker_factory.h"
-#include "chrome/grit/theme_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/message_center/notifier_settings.h"
-#include "ui/strings/grit/ui_strings.h"
-
-SystemComponentNotifierSourceChromeOS::SystemComponentNotifierSourceChromeOS(
-    Observer* observer)
-    : observer_(observer) {}
-
-std::vector<std::unique_ptr<message_center::Notifier>>
-SystemComponentNotifierSourceChromeOS::GetNotifierList(Profile* profile) {
-  std::vector<std::unique_ptr<message_center::Notifier>> notifiers;
-  NotifierStateTracker* const notifier_state_tracker =
-      NotifierStateTrackerFactory::GetForProfile(profile);
-
-  // Screenshot notification feature is only for ChromeOS. See
-  // crbug.com/238358
-  const base::string16& screenshot_name =
-      l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_NOTIFIER_SCREENSHOT_NAME);
-  message_center::NotifierId screenshot_notifier_id(
-      message_center::NotifierId::SYSTEM_COMPONENT,
-      ash::system_notifier::kNotifierScreenshot);
-  message_center::Notifier* const screenshot_notifier =
-      new message_center::Notifier(
-          screenshot_notifier_id, screenshot_name,
-          notifier_state_tracker->IsNotifierEnabled(screenshot_notifier_id));
-  screenshot_notifier->icon =
-      ui::ResourceBundle::GetSharedInstance().GetImageNamed(
-          IDR_SCREENSHOT_NOTIFICATION_ICON);
-  notifiers.emplace_back(screenshot_notifier);
-  return notifiers;
-}
-
-void SystemComponentNotifierSourceChromeOS::SetNotifierEnabled(
-    Profile* profile,
-    const message_center::NotifierId& notifier_id,
-    bool enabled) {
-  NotifierStateTrackerFactory::GetForProfile(profile)->SetNotifierEnabled(
-      notifier_id, enabled);
-  observer_->OnNotifierEnabledChanged(notifier_id, enabled);
-}
-
-message_center::NotifierId::NotifierType
-SystemComponentNotifierSourceChromeOS::GetNotifierType() {
-  return message_center::NotifierId::SYSTEM_COMPONENT;
-}
diff --git a/chrome/browser/notifications/system_component_notifier_source_chromeos.h b/chrome/browser/notifications/system_component_notifier_source_chromeos.h
deleted file mode 100644
index 0bed96c..0000000
--- a/chrome/browser/notifications/system_component_notifier_source_chromeos.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_NOTIFICATIONS_SYSTEM_COMPONENT_NOTIFIER_SOURCE_CHROMEOS_H_
-#define CHROME_BROWSER_NOTIFICATIONS_SYSTEM_COMPONENT_NOTIFIER_SOURCE_CHROMEOS_H_
-
-#include "chrome/browser/notifications/notifier_source.h"
-
-class SystemComponentNotifierSourceChromeOS : public NotifierSource {
- public:
-  explicit SystemComponentNotifierSourceChromeOS(Observer* observer);
-  std::vector<std::unique_ptr<message_center::Notifier>> GetNotifierList(
-      Profile* profile) override;
-  void SetNotifierEnabled(Profile* profile,
-                          const message_center::NotifierId& notifier_id,
-                          bool enabled) override;
-  message_center::NotifierId::NotifierType GetNotifierType() override;
-
- private:
-  // Lifetime of parent must be longer than the source.
-  Observer* observer_;
-};
-
-#endif  // CHROME_BROWSER_NOTIFICATIONS_SYSTEM_COMPONENT_NOTIFIER_SOURCE_CHROMEOS_H_
diff --git a/chrome/browser/notifications/web_page_notifier_controller.cc b/chrome/browser/notifications/web_page_notifier_controller.cc
new file mode 100644
index 0000000..2fd724e
--- /dev/null
+++ b/chrome/browser/notifications/web_page_notifier_controller.cc
@@ -0,0 +1,141 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/notifications/web_page_notifier_controller.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "base/task/cancelable_task_tracker.h"
+#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
+#include "chrome/browser/favicon/favicon_service_factory.h"
+#include "chrome/browser/notifications/desktop_notification_profile_util.h"
+#include "chrome/browser/notifications/notifier_state_tracker.h"
+#include "chrome/browser/notifications/notifier_state_tracker_factory.h"
+#include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/content_settings/core/common/content_settings.h"
+#include "components/favicon/core/favicon_service.h"
+
+WebPageNotifierController::WebPageNotifierController(Observer* observer)
+    : observer_(observer) {}
+
+WebPageNotifierController::~WebPageNotifierController() {}
+
+std::vector<std::unique_ptr<message_center::Notifier>>
+WebPageNotifierController::GetNotifierList(Profile* profile) {
+  std::vector<std::unique_ptr<message_center::Notifier>> notifiers;
+
+  ContentSettingsForOneType settings;
+  DesktopNotificationProfileUtil::GetNotificationsSettings(profile, &settings);
+
+  favicon::FaviconService* const favicon_service =
+      FaviconServiceFactory::GetForProfile(profile,
+                                           ServiceAccessType::EXPLICIT_ACCESS);
+  favicon_tracker_.reset(new base::CancelableTaskTracker());
+  patterns_.clear();
+  for (ContentSettingsForOneType::const_iterator iter = settings.begin();
+       iter != settings.end(); ++iter) {
+    if (iter->primary_pattern == ContentSettingsPattern::Wildcard() &&
+        iter->secondary_pattern == ContentSettingsPattern::Wildcard() &&
+        iter->source != "preference") {
+      continue;
+    }
+
+    std::string url_pattern = iter->primary_pattern.ToString();
+    base::string16 name = base::UTF8ToUTF16(url_pattern);
+    GURL url(url_pattern);
+    message_center::NotifierId notifier_id(url);
+    NotifierStateTracker* const notifier_state_tracker =
+        NotifierStateTrackerFactory::GetForProfile(profile);
+    notifiers.emplace_back(new message_center::Notifier(
+        notifier_id, name,
+        notifier_state_tracker->IsNotifierEnabled(notifier_id)));
+    patterns_[url_pattern] = iter->primary_pattern;
+    // Note that favicon service obtains the favicon from history. This means
+    // that it will fail to obtain the image if there are no history data for
+    // that URL.
+    favicon_service->GetFaviconImageForPageURL(
+        url,
+        base::Bind(&WebPageNotifierController::OnFaviconLoaded,
+                   base::Unretained(this), url),
+        favicon_tracker_.get());
+  }
+
+  return notifiers;
+}
+
+void WebPageNotifierController::SetNotifierEnabled(
+    Profile* profile,
+    const message_center::NotifierId& notifier_id,
+    bool enabled) {
+  // WEB_PAGE notifier cannot handle in DesktopNotificationService
+  // since it has the exact URL pattern.
+  // TODO(mukai): fix this.
+  ContentSetting default_setting =
+      HostContentSettingsMapFactory::GetForProfile(profile)
+          ->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_NOTIFICATIONS, NULL);
+
+  DCHECK(default_setting == CONTENT_SETTING_ALLOW ||
+         default_setting == CONTENT_SETTING_BLOCK ||
+         default_setting == CONTENT_SETTING_ASK);
+
+  // The content setting for notifications needs to clear when it changes to
+  // the default value or get explicitly set when it differs from the
+  // default.
+  bool differs_from_default_value =
+      (default_setting != CONTENT_SETTING_ALLOW && enabled) ||
+      (default_setting == CONTENT_SETTING_ALLOW && !enabled);
+
+  if (differs_from_default_value) {
+    if (notifier_id.url.is_valid()) {
+      if (enabled) {
+        DesktopNotificationProfileUtil::GrantPermission(profile,
+                                                        notifier_id.url);
+      } else {
+        DesktopNotificationProfileUtil::DenyPermission(profile,
+                                                       notifier_id.url);
+      }
+    } else {
+      LOG(ERROR) << "Invalid url pattern: "
+                 << notifier_id.url.possibly_invalid_spec();
+    }
+  } else {
+    ContentSettingsPattern pattern;
+
+    const auto& iter = patterns_.find(notifier_id.url.possibly_invalid_spec());
+    if (iter != patterns_.end()) {
+      pattern = iter->second;
+    } else if (notifier_id.url.is_valid()) {
+      pattern = ContentSettingsPattern::FromURLNoWildcard(notifier_id.url);
+    } else {
+      LOG(ERROR) << "Invalid url pattern: "
+                 << notifier_id.url.possibly_invalid_spec();
+    }
+
+    if (pattern.IsValid()) {
+      // Note that we don't use
+      // DesktopNotificationProfileUtil::ClearSetting()
+      // here because pattern might be from user manual input and not match
+      // the default one used by ClearSetting().
+      HostContentSettingsMapFactory::GetForProfile(profile)
+          ->SetContentSettingCustomScope(
+              pattern, ContentSettingsPattern::Wildcard(),
+              CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
+              content_settings::ResourceIdentifier(), CONTENT_SETTING_DEFAULT);
+    }
+  }
+
+  observer_->OnNotifierEnabledChanged(notifier_id, enabled);
+}
+
+void WebPageNotifierController::OnNotifierSettingsClosing() {
+  DCHECK(favicon_tracker_.get());
+  favicon_tracker_->TryCancelAll();
+  patterns_.clear();
+}
+
+void WebPageNotifierController::OnFaviconLoaded(
+    const GURL& url,
+    const favicon_base::FaviconImageResult& favicon_result) {
+  observer_->OnIconImageUpdated(message_center::NotifierId(url),
+                                favicon_result.image);
+}
diff --git a/chrome/browser/notifications/web_page_notifier_controller.h b/chrome/browser/notifications/web_page_notifier_controller.h
new file mode 100644
index 0000000..055b2715
--- /dev/null
+++ b/chrome/browser/notifications/web_page_notifier_controller.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_NOTIFICATIONS_WEB_PAGE_NOTIFIER_CONTROLLER_H_
+#define CHROME_BROWSER_NOTIFICATIONS_WEB_PAGE_NOTIFIER_CONTROLLER_H_
+
+#include "chrome/browser/notifications/notifier_controller.h"
+#include "components/content_settings/core/common/content_settings_pattern.h"
+
+namespace base {
+class CancelableTaskTracker;
+}
+
+namespace favicon_base {
+struct FaviconImageResult;
+}
+
+class WebPageNotifierController : public NotifierController {
+ public:
+  explicit WebPageNotifierController(Observer* observer);
+  ~WebPageNotifierController() override;
+
+  std::vector<std::unique_ptr<message_center::Notifier>> GetNotifierList(
+      Profile* profile) override;
+
+  void SetNotifierEnabled(Profile* profile,
+                          const message_center::NotifierId& notifier_id,
+                          bool enabled) override;
+
+  void OnNotifierSettingsClosing() override;
+
+ private:
+  void OnFaviconLoaded(const GURL& url,
+                       const favicon_base::FaviconImageResult& favicon_result);
+
+  std::map<std::string, ContentSettingsPattern> patterns_;
+
+  // The task tracker for loading favicons.
+  std::unique_ptr<base::CancelableTaskTracker> favicon_tracker_;
+
+  // Lifetime of parent must be longer than the source.
+  Observer* observer_;
+};
+
+#endif  // CHROME_BROWSER_NOTIFICATIONS_WEB_PAGE_NOTIFIER_CONTROLLER_H_
diff --git a/chrome/browser/notifications/web_page_notifier_source.cc b/chrome/browser/notifications/web_page_notifier_source.cc
deleted file mode 100644
index 760753aa..0000000
--- a/chrome/browser/notifications/web_page_notifier_source.cc
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/notifications/web_page_notifier_source.h"
-
-#include "base/strings/utf_string_conversions.h"
-#include "base/task/cancelable_task_tracker.h"
-#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
-#include "chrome/browser/favicon/favicon_service_factory.h"
-#include "chrome/browser/notifications/desktop_notification_profile_util.h"
-#include "chrome/browser/notifications/notifier_state_tracker.h"
-#include "chrome/browser/notifications/notifier_state_tracker_factory.h"
-#include "components/content_settings/core/browser/host_content_settings_map.h"
-#include "components/content_settings/core/common/content_settings.h"
-#include "components/favicon/core/favicon_service.h"
-
-WebPageNotifierSource::WebPageNotifierSource(Observer* observer)
-    : observer_(observer) {}
-
-WebPageNotifierSource::~WebPageNotifierSource() {}
-
-std::vector<std::unique_ptr<message_center::Notifier>>
-WebPageNotifierSource::GetNotifierList(Profile* profile) {
-  std::vector<std::unique_ptr<message_center::Notifier>> notifiers;
-
-  ContentSettingsForOneType settings;
-  DesktopNotificationProfileUtil::GetNotificationsSettings(profile, &settings);
-
-  favicon::FaviconService* const favicon_service =
-      FaviconServiceFactory::GetForProfile(profile,
-                                           ServiceAccessType::EXPLICIT_ACCESS);
-  favicon_tracker_.reset(new base::CancelableTaskTracker());
-  patterns_.clear();
-  for (ContentSettingsForOneType::const_iterator iter = settings.begin();
-       iter != settings.end(); ++iter) {
-    if (iter->primary_pattern == ContentSettingsPattern::Wildcard() &&
-        iter->secondary_pattern == ContentSettingsPattern::Wildcard() &&
-        iter->source != "preference") {
-      continue;
-    }
-
-    std::string url_pattern = iter->primary_pattern.ToString();
-    base::string16 name = base::UTF8ToUTF16(url_pattern);
-    GURL url(url_pattern);
-    message_center::NotifierId notifier_id(url);
-    NotifierStateTracker* const notifier_state_tracker =
-        NotifierStateTrackerFactory::GetForProfile(profile);
-    notifiers.emplace_back(new message_center::Notifier(
-        notifier_id, name,
-        notifier_state_tracker->IsNotifierEnabled(notifier_id)));
-    patterns_[url_pattern] = iter->primary_pattern;
-    // Note that favicon service obtains the favicon from history. This means
-    // that it will fail to obtain the image if there are no history data for
-    // that URL.
-    favicon_service->GetFaviconImageForPageURL(
-        url,
-        base::Bind(&WebPageNotifierSource::OnFaviconLoaded,
-                   base::Unretained(this), url),
-        favicon_tracker_.get());
-  }
-
-  return notifiers;
-}
-
-void WebPageNotifierSource::SetNotifierEnabled(
-    Profile* profile,
-    const message_center::NotifierId& notifier_id,
-    bool enabled) {
-  // WEB_PAGE notifier cannot handle in DesktopNotificationService
-  // since it has the exact URL pattern.
-  // TODO(mukai): fix this.
-  ContentSetting default_setting =
-      HostContentSettingsMapFactory::GetForProfile(profile)
-          ->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_NOTIFICATIONS, NULL);
-
-  DCHECK(default_setting == CONTENT_SETTING_ALLOW ||
-         default_setting == CONTENT_SETTING_BLOCK ||
-         default_setting == CONTENT_SETTING_ASK);
-
-  // The content setting for notifications needs to clear when it changes to
-  // the default value or get explicitly set when it differs from the
-  // default.
-  bool differs_from_default_value =
-      (default_setting != CONTENT_SETTING_ALLOW && enabled) ||
-      (default_setting == CONTENT_SETTING_ALLOW && !enabled);
-
-  if (differs_from_default_value) {
-    if (notifier_id.url.is_valid()) {
-      if (enabled) {
-        DesktopNotificationProfileUtil::GrantPermission(profile,
-                                                        notifier_id.url);
-      } else {
-        DesktopNotificationProfileUtil::DenyPermission(profile,
-                                                       notifier_id.url);
-      }
-    } else {
-      LOG(ERROR) << "Invalid url pattern: "
-                 << notifier_id.url.possibly_invalid_spec();
-    }
-  } else {
-    ContentSettingsPattern pattern;
-
-    const auto& iter = patterns_.find(notifier_id.url.possibly_invalid_spec());
-    if (iter != patterns_.end()) {
-      pattern = iter->second;
-    } else if (notifier_id.url.is_valid()) {
-      pattern = ContentSettingsPattern::FromURLNoWildcard(notifier_id.url);
-    } else {
-      LOG(ERROR) << "Invalid url pattern: "
-                 << notifier_id.url.possibly_invalid_spec();
-    }
-
-    if (pattern.IsValid()) {
-      // Note that we don't use
-      // DesktopNotificationProfileUtil::ClearSetting()
-      // here because pattern might be from user manual input and not match
-      // the default one used by ClearSetting().
-      HostContentSettingsMapFactory::GetForProfile(profile)
-          ->SetContentSettingCustomScope(
-              pattern, ContentSettingsPattern::Wildcard(),
-              CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
-              content_settings::ResourceIdentifier(), CONTENT_SETTING_DEFAULT);
-    }
-  }
-
-  observer_->OnNotifierEnabledChanged(notifier_id, enabled);
-}
-
-void WebPageNotifierSource::OnNotifierSettingsClosing() {
-  DCHECK(favicon_tracker_.get());
-  favicon_tracker_->TryCancelAll();
-  patterns_.clear();
-}
-
-message_center::NotifierId::NotifierType
-WebPageNotifierSource::GetNotifierType() {
-  return message_center::NotifierId::WEB_PAGE;
-}
-
-void WebPageNotifierSource::OnFaviconLoaded(
-    const GURL& url,
-    const favicon_base::FaviconImageResult& favicon_result) {
-  observer_->OnIconImageUpdated(message_center::NotifierId(url),
-                                favicon_result.image);
-}
diff --git a/chrome/browser/notifications/web_page_notifier_source.h b/chrome/browser/notifications/web_page_notifier_source.h
deleted file mode 100644
index 8e23c1a..0000000
--- a/chrome/browser/notifications/web_page_notifier_source.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_NOTIFICATIONS_WEB_PAGE_NOTIFIER_SOURCE_H_
-#define CHROME_BROWSER_NOTIFICATIONS_WEB_PAGE_NOTIFIER_SOURCE_H_
-
-#include "chrome/browser/notifications/notifier_source.h"
-#include "components/content_settings/core/common/content_settings_pattern.h"
-
-namespace base {
-class CancelableTaskTracker;
-}
-
-namespace favicon_base {
-struct FaviconImageResult;
-}
-
-class WebPageNotifierSource : public NotifierSource {
- public:
-  explicit WebPageNotifierSource(Observer* observer);
-  ~WebPageNotifierSource() override;
-
-  std::vector<std::unique_ptr<message_center::Notifier>> GetNotifierList(
-      Profile* profile) override;
-
-  void SetNotifierEnabled(Profile* profile,
-                          const message_center::NotifierId& notifier_id,
-                          bool enabled) override;
-
-  void OnNotifierSettingsClosing() override;
-
-  message_center::NotifierId::NotifierType GetNotifierType() override;
-
- private:
-  void OnFaviconLoaded(const GURL& url,
-                       const favicon_base::FaviconImageResult& favicon_result);
-
-  std::map<std::string, ContentSettingsPattern> patterns_;
-
-  // The task tracker for loading favicons.
-  std::unique_ptr<base::CancelableTaskTracker> favicon_tracker_;
-
-  // Lifetime of parent must be longer than the source.
-  Observer* observer_;
-};
-
-#endif  // CHROME_BROWSER_NOTIFICATIONS_WEB_PAGE_NOTIFIER_SOURCE_H_
diff --git a/chrome/browser/ntp_snippets/download_suggestions_provider.cc b/chrome/browser/ntp_snippets/download_suggestions_provider.cc
index b50bf36..9b1649e 100644
--- a/chrome/browser/ntp_snippets/download_suggestions_provider.cc
+++ b/chrome/browser/ntp_snippets/download_suggestions_provider.cc
@@ -138,7 +138,8 @@
 bool IsClientIdForOfflinePageDownload(
     offline_pages::ClientPolicyController* policy_controller,
     const offline_pages::ClientId& client_id) {
-  return policy_controller->IsSupportedByDownload(client_id.name_space);
+  return policy_controller->IsSupportedByDownload(client_id.name_space) &&
+         !policy_controller->IsSuggested(client_id.name_space);
 }
 
 }  // namespace
@@ -735,7 +736,9 @@
       retained_dismissed_ids.insert(id_within_category);
     } else {
       if (!IsDownloadOutdated(GetOfflinePagePublishedTime(item),
-                              item.last_access_time)) {
+                              item.last_access_time) &&
+          IsClientIdForOfflinePageDownload(
+              offline_page_model_->GetPolicyController(), item.client_id)) {
         items.push_back(&item);
       }
     }
diff --git a/chrome/browser/ntp_snippets/download_suggestions_provider_unittest.cc b/chrome/browser/ntp_snippets/download_suggestions_provider_unittest.cc
index a8c68400..f13bef97 100644
--- a/chrome/browser/ntp_snippets/download_suggestions_provider_unittest.cc
+++ b/chrome/browser/ntp_snippets/download_suggestions_provider_unittest.cc
@@ -1162,3 +1162,33 @@
   // |OnDownloadItemDestroyed| is called from items's destructor.
   downloads_manager()->mutable_items()->clear();
 }
+
+TEST_F(DownloadSuggestionsProviderTest, ShouldNotShowSuggestedDownloads) {
+  IgnoreOnCategoryStatusChangedToAvailable();
+  IgnoreOnSuggestionInvalidated();
+
+  std::vector<OfflinePageItem> offline_pages = CreateDummyOfflinePages({0, 1});
+
+  offline_pages[0].url = GURL("http://dummy.com/0");
+  offline_pages[0].creation_time = kOutdatedTime;
+  offline_pages[0].last_access_time = kNotOutdatedTime;
+
+  // Suggested page should be ignored.
+  offline_pages[1].client_id.name_space = "suggested_articles";
+  offline_pages[1].url = GURL("http://dummy.com/1");
+  offline_pages[1].creation_time = kNotOutdatedTime;
+  offline_pages[1].last_access_time = offline_pages[1].creation_time;
+
+  *(offline_pages_model()->mutable_items()) = offline_pages;
+
+  // Even though page 0 was created long time ago, it should be reported because
+  // it has been visited recently.
+  EXPECT_CALL(
+      *observer(),
+      OnNewSuggestions(_, downloads_category(),
+                       UnorderedElementsAre(HasUrl("http://dummy.com/0"))));
+  auto test_clock = base::MakeUnique<base::SimpleTestClock>();
+  test_clock->SetNow(now);
+  CreateProvider(/*show_assets=*/false, /*show_offline_pages=*/true,
+                 std::move(test_clock));
+}
diff --git a/chrome/browser/offline_pages/android/downloads/offline_page_download_bridge.cc b/chrome/browser/offline_pages/android/downloads/offline_page_download_bridge.cc
index c72c6a2..0b43b5c 100644
--- a/chrome/browser/offline_pages/android/downloads/offline_page_download_bridge.cc
+++ b/chrome/browser/offline_pages/android/downloads/offline_page_download_bridge.cc
@@ -215,7 +215,7 @@
   // In other cases, use the RenderProcessHost ID + RenderFrameHost ID to get
   // the WebContents.
   return base::Bind(&GetWebContentsByFrameID,
-                    web_contents->GetRenderProcessHost()->GetID(),
+                    web_contents->GetMainFrame()->GetProcess()->GetID(),
                     web_contents->GetMainFrame()->GetRoutingID());
 }
 
diff --git a/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer.cc
index 765d238a..a2bd341 100644
--- a/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer.cc
@@ -12,9 +12,24 @@
 UseCounterPageLoadMetricsObserver::UseCounterPageLoadMetricsObserver() {}
 UseCounterPageLoadMetricsObserver::~UseCounterPageLoadMetricsObserver() {}
 
+page_load_metrics::PageLoadMetricsObserver::ObservePolicy
+UseCounterPageLoadMetricsObserver::OnCommit(
+    content::NavigationHandle* navigation_handle,
+    ukm::SourceId source_id) {
+  // Verify that no feature usage is observed before commit
+  DCHECK(features_recorded_.count() <= 0);
+  UMA_HISTOGRAM_ENUMERATION(internal::kFeaturesHistogramName,
+                            WebFeature::kPageVisits,
+                            WebFeature::kNumberOfFeatures);
+  features_recorded_.set(static_cast<size_t>(WebFeature::kPageVisits));
+  return CONTINUE_OBSERVING;
+}
+
 void UseCounterPageLoadMetricsObserver::OnFeaturesUsageObserved(
     const Features& features) {
   for (auto feature : features.features) {
+    // Verify that kPageVisits is only observed at most once per observer.
+    DCHECK(feature != WebFeature::kPageVisits);
     // The usage of each feature should be only measured once. With OOPIF,
     // multiple child frames may send the same feature to the browser, skip if
     // feature has already been measured.
diff --git a/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer.h
index 86f6c288..fd44482e6 100644
--- a/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer.h
@@ -25,6 +25,8 @@
   ~UseCounterPageLoadMetricsObserver() override;
 
   // page_load_metrics::PageLoadMetricsObserver.
+  ObservePolicy OnCommit(content::NavigationHandle* navigation_handle,
+                         ukm::SourceId source_id) override;
   void OnFeaturesUsageObserved(
       const page_load_metrics::mojom::PageLoadFeatures&) override;
 
diff --git a/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer_unittest.cc
index f4ffadfb..2dcac50 100644
--- a/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer_unittest.cc
@@ -32,6 +32,10 @@
           page_load_metrics::mojom::PageLoadFeatures()) {
     NavigateAndCommit(GURL(kTestUrl));
     SimulateFeaturesUpdate(first_features);
+    // Verify that kPageVisits is observed on commit.
+    histogram_tester().ExpectBucketCount(
+        internal::kFeaturesHistogramName,
+        static_cast<base::Histogram::Sample>(WebFeature::kPageVisits), 1);
     for (auto feature : first_features.features) {
       histogram_tester().ExpectBucketCount(
           internal::kFeaturesHistogramName,
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 6e82eb2..a850e62 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
@@ -1155,6 +1155,9 @@
   histogram_tester_.ExpectBucketCount(
       internal::kFeaturesHistogramName,
       static_cast<int32_t>(WebFeature::kV8Element_Animate_Method), 1);
+  histogram_tester_.ExpectBucketCount(
+      internal::kFeaturesHistogramName,
+      static_cast<int32_t>(WebFeature::kPageVisits), 1);
 }
 
 // Test UseCounter Features observed in a child frame are recorded, exactly
@@ -1176,6 +1179,9 @@
   histogram_tester_.ExpectBucketCount(
       internal::kFeaturesHistogramName,
       static_cast<int32_t>(WebFeature::kV8Element_Animate_Method), 1);
+  histogram_tester_.ExpectBucketCount(
+      internal::kFeaturesHistogramName,
+      static_cast<int32_t>(WebFeature::kPageVisits), 1);
 }
 
 // Test UseCounter Features observed in multiple child frames are recorded,
@@ -1199,6 +1205,9 @@
   histogram_tester_.ExpectBucketCount(
       internal::kFeaturesHistogramName,
       static_cast<int32_t>(WebFeature::kV8Element_Animate_Method), 1);
+  histogram_tester_.ExpectBucketCount(
+      internal::kFeaturesHistogramName,
+      static_cast<int32_t>(WebFeature::kPageVisits), 1);
 }
 
 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, LoadingMetrics) {
diff --git a/chrome/browser/payments/chrome_payment_request_delegate.cc b/chrome/browser/payments/chrome_payment_request_delegate.cc
index 14883a8..e4f1008 100644
--- a/chrome/browser/payments/chrome_payment_request_delegate.cc
+++ b/chrome/browser/payments/chrome_payment_request_delegate.cc
@@ -115,7 +115,8 @@
       GetAddressInputStorage().release(), GetApplicationLocale());
 }
 
-AddressNormalizer* ChromePaymentRequestDelegate::GetAddressNormalizer() {
+autofill::AddressNormalizer*
+ChromePaymentRequestDelegate::GetAddressNormalizer() {
   return &address_normalizer_;
 }
 
diff --git a/chrome/browser/payments/chrome_payment_request_delegate.h b/chrome/browser/payments/chrome_payment_request_delegate.h
index ff219b71..cd69bcb 100644
--- a/chrome/browser/payments/chrome_payment_request_delegate.h
+++ b/chrome/browser/payments/chrome_payment_request_delegate.h
@@ -9,7 +9,7 @@
 #include <string>
 
 #include "base/macros.h"
-#include "components/payments/core/address_normalizer_impl.h"
+#include "components/autofill/core/browser/address_normalizer_impl.h"
 #include "components/payments/core/payment_request_delegate.h"
 
 namespace content {
@@ -38,7 +38,7 @@
       const autofill::CreditCard& credit_card,
       base::WeakPtr<autofill::payments::FullCardRequest::ResultDelegate>
           result_delegate) override;
-  AddressNormalizer* GetAddressNormalizer() override;
+  autofill::AddressNormalizer* GetAddressNormalizer() override;
   autofill::RegionDataLoader* GetRegionDataLoader() override;
   ukm::UkmRecorder* GetUkmRecorder() override;
   std::string GetAuthenticatedEmail() const override;
@@ -56,7 +56,7 @@
   content::WebContents* web_contents_;
 
   // The address normalizer to use for the duration of the Payment Request.
-  AddressNormalizerImpl address_normalizer_;
+  autofill::AddressNormalizerImpl address_normalizer_;
 
   DISALLOW_COPY_AND_ASSIGN(ChromePaymentRequestDelegate);
 };
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index 7cd3e6c..8a1ba11 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -48,6 +48,7 @@
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/plugin_service.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
@@ -523,7 +524,8 @@
   GURL invalid_link_url("chrome://settings");
 
   GURL unfiltered_valid_link_url(valid_link_url);
-  content::RenderProcessHost* rph = guest_contents->GetRenderProcessHost();
+  content::RenderProcessHost* rph =
+      guest_contents->GetMainFrame()->GetProcess();
   rph->FilterURL(true, &valid_link_url);
   rph->FilterURL(true, &invalid_link_url);
 
diff --git a/chrome/browser/permissions/permission_context_base_feature_policy_unittest.cc b/chrome/browser/permissions/permission_context_base_feature_policy_unittest.cc
index 3b27eb7..a2c654e 100644
--- a/chrome/browser/permissions/permission_context_base_feature_policy_unittest.cc
+++ b/chrome/browser/permissions/permission_context_base_feature_policy_unittest.cc
@@ -94,7 +94,7 @@
 TEST_F(PermissionContextBaseFeaturePolicyTest, FeatureDisabled) {
   // Disable the feature.
   base::test::ScopedFeatureList feature_list;
-  feature_list.Init();
+  feature_list.InitAndDisableFeature(features::kUseFeaturePolicyForPermissions);
 
   content::RenderFrameHost* parent = GetMainRFH(kOrigin1);
 
diff --git a/chrome/browser/permissions/permission_context_base_unittest.cc b/chrome/browser/permissions/permission_context_base_unittest.cc
index d68422eb..29698b2 100644
--- a/chrome/browser/permissions/permission_context_base_unittest.cc
+++ b/chrome/browser/permissions/permission_context_base_unittest.cc
@@ -249,7 +249,7 @@
     base::HistogramTester histograms;
 
     const PermissionRequestID id(
-        web_contents()->GetRenderProcessHost()->GetID(),
+        web_contents()->GetMainFrame()->GetProcess()->GetID(),
         web_contents()->GetMainFrame()->GetRoutingID(), -1);
     permission_context.SetRespondPermissionCallback(
         base::Bind(&PermissionContextBaseTests::RespondToPermission,
@@ -310,7 +310,7 @@
       TestPermissionContext permission_context(profile(),
                                                content_settings_type);
       const PermissionRequestID id(
-          web_contents()->GetRenderProcessHost()->GetID(),
+          web_contents()->GetMainFrame()->GetProcess()->GetID(),
           web_contents()->GetMainFrame()->GetRoutingID(), i);
 
       permission_context.SetRespondPermissionCallback(
@@ -361,7 +361,7 @@
 
     TestPermissionContext permission_context(profile(), content_settings_type);
     const PermissionRequestID id(
-        web_contents()->GetRenderProcessHost()->GetID(),
+        web_contents()->GetMainFrame()->GetProcess()->GetID(),
         web_contents()->GetMainFrame()->GetRoutingID(), -1);
 
     permission_context.SetRespondPermissionCallback(
@@ -400,7 +400,7 @@
             profile(), CONTENT_SETTINGS_TYPE_GEOLOCATION);
 
         const PermissionRequestID id(
-            web_contents()->GetRenderProcessHost()->GetID(),
+            web_contents()->GetMainFrame()->GetProcess()->GetID(),
             web_contents()->GetMainFrame()->GetRoutingID(), i);
 
         permission_context.SetRespondPermissionCallback(
@@ -485,7 +485,7 @@
           profile(), CONTENT_SETTINGS_TYPE_MIDI_SYSEX);
 
       const PermissionRequestID id(
-          web_contents()->GetRenderProcessHost()->GetID(),
+          web_contents()->GetMainFrame()->GetProcess()->GetID(),
           web_contents()->GetMainFrame()->GetRoutingID(), i);
       permission_context.SetRespondPermissionCallback(
           base::Bind(&PermissionContextBaseTests::RespondToPermission,
@@ -546,7 +546,7 @@
                          std::string());
 
     const PermissionRequestID id(
-        web_contents()->GetRenderProcessHost()->GetID(),
+        web_contents()->GetMainFrame()->GetProcess()->GetID(),
         web_contents()->GetMainFrame()->GetRoutingID(), -1);
     permission_context.RequestPermission(
         web_contents(), id, url, true /* user_gesture */,
@@ -569,7 +569,7 @@
     SetUpUrl(url);
 
     const PermissionRequestID id(
-        web_contents()->GetRenderProcessHost()->GetID(),
+        web_contents()->GetMainFrame()->GetProcess()->GetID(),
         web_contents()->GetMainFrame()->GetRoutingID(), -1);
     permission_context.SetRespondPermissionCallback(
         base::Bind(&PermissionContextBaseTests::RespondToPermission,
@@ -624,10 +624,10 @@
     SetUpUrl(url);
 
     const PermissionRequestID id0(
-        web_contents()->GetRenderProcessHost()->GetID(),
+        web_contents()->GetMainFrame()->GetProcess()->GetID(),
         web_contents()->GetMainFrame()->GetRoutingID(), 0);
     const PermissionRequestID id1(
-        web_contents()->GetRenderProcessHost()->GetID(),
+        web_contents()->GetMainFrame()->GetProcess()->GetID(),
         web_contents()->GetMainFrame()->GetRoutingID(), 1);
 
     bool persist = (response == CONTENT_SETTING_ALLOW ||
@@ -675,7 +675,7 @@
         ->SetSafeBrowsingDatabaseManagerAndTimeoutForTesting(db_manager,
                                                              timeout);
     const PermissionRequestID id(
-        web_contents()->GetRenderProcessHost()->GetID(),
+        web_contents()->GetMainFrame()->GetProcess()->GetID(),
         web_contents()->GetMainFrame()->GetRoutingID(), -1);
 
     // A response only needs to be made to the permission request if we do not
diff --git a/chrome/browser/plugins/chrome_plugin_service_filter_unittest.cc b/chrome/browser/plugins/chrome_plugin_service_filter_unittest.cc
index 7e2ffc2..2bab889e 100644
--- a/chrome/browser/plugins/chrome_plugin_service_filter_unittest.cc
+++ b/chrome/browser/plugins/chrome_plugin_service_filter_unittest.cc
@@ -34,6 +34,7 @@
 #include "components/variations/variations_associated_data.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/plugin_service.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_constants.h"
@@ -94,7 +95,7 @@
                                    content::WebPluginInfo plugin_info,
                                    bool* is_available) {
     *is_available = filter_->IsPluginAvailable(
-        web_contents()->GetRenderProcessHost()->GetID(),
+        web_contents()->GetMainFrame()->GetProcess()->GetID(),
         web_contents()->GetMainFrame()->GetRoutingID(), resource_context,
         plugin_content_url, main_frame_origin, &plugin_info);
   }
diff --git a/chrome/browser/plugins/pdf_iframe_navigation_throttle.cc b/chrome/browser/plugins/pdf_iframe_navigation_throttle.cc
index 83445e14..8027836d 100644
--- a/chrome/browser/plugins/pdf_iframe_navigation_throttle.cc
+++ b/chrome/browser/plugins/pdf_iframe_navigation_throttle.cc
@@ -47,7 +47,8 @@
                                                              &pdf_plugin_info);
 
   ChromePluginServiceFilter* filter = ChromePluginServiceFilter::GetInstance();
-  int process_id = handle->GetWebContents()->GetRenderProcessHost()->GetID();
+  int process_id =
+      handle->GetWebContents()->GetMainFrame()->GetProcess()->GetID();
   int routing_id = handle->GetWebContents()->GetMainFrame()->GetRoutingID();
   content::ResourceContext* resource_context =
       handle->GetWebContents()->GetBrowserContext()->GetResourceContext();
diff --git a/chrome/browser/plugins/pdf_plugin_placeholder_observer.cc b/chrome/browser/plugins/pdf_plugin_placeholder_observer.cc
index e8ec95a..726f7bd 100644
--- a/chrome/browser/plugins/pdf_plugin_placeholder_observer.cc
+++ b/chrome/browser/plugins/pdf_plugin_placeholder_observer.cc
@@ -4,6 +4,9 @@
 
 #include "chrome/browser/plugins/pdf_plugin_placeholder_observer.h"
 
+#include <memory>
+#include <utility>
+
 #include "chrome/common/render_messages.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/child_process_security_policy.h"
@@ -93,7 +96,7 @@
         })");
   std::unique_ptr<content::DownloadUrlParameters> params =
       base::MakeUnique<content::DownloadUrlParameters>(
-          url, web_contents()->GetRenderProcessHost()->GetID(),
+          url, web_contents()->GetRenderViewHost()->GetProcess()->GetID(),
           web_contents()->GetRenderViewHost()->GetRoutingID(),
           render_frame_host->GetRoutingID(),
           storage_partition->GetURLRequestContext(), traffic_annotation);
diff --git a/chrome/browser/plugins/plugin_info_message_filter.cc b/chrome/browser/plugins/plugin_info_message_filter.cc
index c3ebde3..5a807cdf 100644
--- a/chrome/browser/plugins/plugin_info_message_filter.cc
+++ b/chrome/browser/plugins/plugin_info_message_filter.cc
@@ -39,6 +39,7 @@
 #include "components/content_settings/core/common/content_settings.h"
 #include "components/keyed_service/content/browser_context_keyed_service_shutdown_notifier_factory.h"
 #include "components/nacl/common/features.h"
+#include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
 #include "components/rappor/rappor_service_impl.h"
 #include "content/public/browser/browser_thread.h"
@@ -169,6 +170,11 @@
   always_authorize_plugins_.MoveToThread(
       content::BrowserThread::GetTaskRunnerForThread(
           content::BrowserThread::IO));
+  run_all_flash_in_allow_mode_.Init(prefs::kRunAllFlashInAllowMode,
+                                    profile->GetPrefs());
+  run_all_flash_in_allow_mode_.MoveToThread(
+      content::BrowserThread::GetTaskRunnerForThread(
+          content::BrowserThread::IO));
 }
 
 PluginInfoMessageFilter::Context::~Context() {
@@ -178,6 +184,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   always_authorize_plugins_.Destroy();
   allow_outdated_plugins_.Destroy();
+  run_all_flash_in_allow_mode_.Destroy();
 }
 
 PluginInfoMessageFilter::PluginInfoMessageFilter(int render_process_id,
@@ -217,6 +224,14 @@
   content::BrowserThread::DeleteOnUIThread::Destruct(this);
 }
 
+// static
+void PluginInfoMessageFilter::RegisterUserPrefs(
+    user_prefs::PrefRegistrySyncable* registry) {
+  registry->RegisterBooleanPref(prefs::kPluginsAllowOutdated, false);
+  registry->RegisterBooleanPref(prefs::kPluginsAlwaysAuthorize, false);
+  registry->RegisterBooleanPref(prefs::kRunAllFlashInAllowMode, false);
+}
+
 PluginInfoMessageFilter::~PluginInfoMessageFilter() {}
 
 struct PluginInfoMessageFilter::GetPluginInfo_Params {
@@ -388,7 +403,8 @@
 
   if (plugin_setting == CONTENT_SETTING_DETECT_IMPORTANT_CONTENT ||
       (plugin_setting == CONTENT_SETTING_ALLOW &&
-       PluginUtils::ShouldPreferHtmlOverPlugins(host_content_settings_map_))) {
+       PluginUtils::ShouldPreferHtmlOverPlugins(host_content_settings_map_) &&
+       !run_all_flash_in_allow_mode_.GetValue())) {
     *status = ChromeViewHostMsg_GetPluginInfo_Status::kPlayImportantContent;
   } else if (plugin_setting == CONTENT_SETTING_BLOCK) {
     // For managed users with the ASK policy, we allow manually running plugins
diff --git a/chrome/browser/plugins/plugin_info_message_filter.h b/chrome/browser/plugins/plugin_info_message_filter.h
index f2dc2dd..a6257c1 100644
--- a/chrome/browser/plugins/plugin_info_message_filter.h
+++ b/chrome/browser/plugins/plugin_info_message_filter.h
@@ -34,6 +34,10 @@
 class SingleThreadTaskRunner;
 }
 
+namespace component_updater {
+struct ComponentInfo;
+}
+
 namespace content {
 class ResourceContext;
 struct WebPluginInfo;
@@ -43,8 +47,8 @@
 class ExtensionRegistry;
 }
 
-namespace component_updater {
-struct ComponentInfo;
+namespace user_prefs {
+class PrefRegistrySyncable;
 }
 
 namespace url {
@@ -86,6 +90,7 @@
     bool IsPluginEnabled(const content::WebPluginInfo& plugin) const;
 
     void ShutdownOnUIThread();
+
    private:
     int render_process_id_;
     content::ResourceContext* resource_context_;
@@ -97,6 +102,7 @@
 
     BooleanPrefMember allow_outdated_plugins_;
     BooleanPrefMember always_authorize_plugins_;
+    BooleanPrefMember run_all_flash_in_allow_mode_;
   };
 
   PluginInfoMessageFilter(int render_process_id, Profile* profile);
@@ -105,6 +111,8 @@
   bool OnMessageReceived(const IPC::Message& message) override;
   void OnDestruct() const override;
 
+  static void RegisterUserPrefs(user_prefs::PrefRegistrySyncable* registry);
+
  private:
   friend struct content::BrowserThread::DeleteOnThread<
       content::BrowserThread::UI>;
diff --git a/chrome/browser/plugins/plugin_info_message_filter_unittest.cc b/chrome/browser/plugins/plugin_info_message_filter_unittest.cc
index 8baf5ff..6fedf21 100644
--- a/chrome/browser/plugins/plugin_info_message_filter_unittest.cc
+++ b/chrome/browser/plugins/plugin_info_message_filter_unittest.cc
@@ -32,6 +32,7 @@
 #include "url/origin.h"
 
 using content::PluginService;
+using testing::Eq;
 
 namespace {
 
@@ -273,6 +274,49 @@
   EXPECT_EQ(ChromeViewHostMsg_GetPluginInfo_Status::kBlockedNoLoading, status);
 }
 
+TEST_F(PluginInfoMessageFilterTest, RunAllFlashInAllowMode) {
+  filter_.set_plugin_enabled(fake_flash_path_, true);
+
+  // Make a real HTTP origin, as all Flash content from non-HTTP and non-FILE
+  // origins are blocked.
+  url::Origin main_frame_origin(GURL("http://example.com"));
+
+  ChromeViewHostMsg_GetPluginInfo_Status status;
+  content::WebPluginInfo plugin;
+  std::string actual_mime_type;
+  ASSERT_TRUE(context()->FindEnabledPlugin(
+      0, GURL(), main_frame_origin, content::kFlashPluginSwfMimeType, &status,
+      &plugin, &actual_mime_type, nullptr));
+  ASSERT_THAT(status, Eq(ChromeViewHostMsg_GetPluginInfo_Status::kAllowed));
+
+  HostContentSettingsMapFactory::GetForProfile(profile())
+      ->SetContentSettingDefaultScope(main_frame_origin.GetURL(), GURL(),
+                                      CONTENT_SETTINGS_TYPE_PLUGINS,
+                                      std::string(), CONTENT_SETTING_ALLOW);
+
+  ASSERT_FALSE(
+      profile()->GetPrefs()->GetBoolean(prefs::kRunAllFlashInAllowMode));
+
+  PluginMetadata::SecurityStatus security_status =
+      PluginMetadata::SECURITY_STATUS_UP_TO_DATE;
+  context()->DecidePluginStatus(GURL(), main_frame_origin, plugin,
+                                security_status, content::kFlashPluginName,
+                                &status);
+  EXPECT_THAT(
+      status,
+      Eq(ChromeViewHostMsg_GetPluginInfo_Status::kPlayImportantContent));
+
+  // Reset the status to allowed.
+  status = ChromeViewHostMsg_GetPluginInfo_Status::kAllowed;
+
+  profile()->GetPrefs()->SetBoolean(prefs::kRunAllFlashInAllowMode, true);
+
+  context()->DecidePluginStatus(GURL(), main_frame_origin, plugin,
+                                security_status, content::kFlashPluginName,
+                                &status);
+  EXPECT_THAT(status, Eq(ChromeViewHostMsg_GetPluginInfo_Status::kAllowed));
+}
+
 TEST_F(PluginInfoMessageFilterTest, GetPluginContentSetting) {
   HostContentSettingsMap* map =
       HostContentSettingsMapFactory::GetForProfile(profile());
diff --git a/chrome/browser/plugins/plugin_power_saver_browsertest.cc b/chrome/browser/plugins/plugin_power_saver_browsertest.cc
index 3f1f9e7..cbc7275 100644
--- a/chrome/browser/plugins/plugin_power_saver_browsertest.cc
+++ b/chrome/browser/plugins/plugin_power_saver_browsertest.cc
@@ -11,7 +11,6 @@
 #include "base/stl_util.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/stringprintf.h"
-#include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
@@ -20,10 +19,14 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/test_switches.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/policy/core/browser/browser_policy_connector.h"
+#include "components/policy/core/common/mock_configuration_policy_provider.h"
+#include "components/policy/policy_constants.h"
 #include "components/zoom/zoom_controller.h"
 #include "content/public/browser/readback_types.h"
 #include "content/public/browser/render_frame_host.h"
@@ -46,6 +49,9 @@
 #include "ui/gfx/codec/png_codec.h"
 #include "ui/gfx/geometry/point.h"
 
+using testing::_;
+using testing::Return;
+
 namespace {
 
 // Use fixed browser dimensions for pixel tests.
@@ -286,6 +292,12 @@
       command_line->AppendSwitch(switches::kDisableGpu);
   }
 
+  void SetUpInProcessBrowserTestFixture() override {
+    EXPECT_CALL(provider_, IsInitializationComplete(_))
+        .WillRepeatedly(Return(true));
+    policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
+  }
+
  protected:
   void LoadHTML(const std::string& file) {
     if (PixelTestsEnabled()) {
@@ -401,8 +413,8 @@
 #endif
   }
 
- private:
-  base::test::ScopedFeatureList feature_list;
+ protected:
+  policy::MockConfigurationPolicyProvider provider_;
 };
 
 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest, EssentialPlugins) {
@@ -582,3 +594,24 @@
   VerifyPluginIsThrottled(GetActiveWebContents(), "expand_to_peripheral");
   VerifyPluginMarkedEssential(GetActiveWebContents(), "expand_to_essential");
 }
+
+IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest, RunAllFlashInAllowMode) {
+  LoadHTML("/run_all_flash.html");
+  VerifyPluginIsThrottled(GetActiveWebContents(), "small");
+  VerifyPluginIsThrottled(GetActiveWebContents(), "cross_origin");
+
+  policy::PolicyMap policy;
+  policy.Set(policy::key::kRunAllFlashInAllowMode,
+             policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
+             policy::POLICY_SOURCE_CLOUD, base::MakeUnique<base::Value>(true),
+             nullptr);
+  provider_.UpdateChromePolicy(policy);
+  content::RunAllPendingInMessageLoop();
+
+  ASSERT_TRUE(browser()->profile()->GetPrefs()->GetBoolean(
+      prefs::kRunAllFlashInAllowMode));
+
+  LoadHTML("/run_all_flash.html");
+  VerifyPluginMarkedEssential(GetActiveWebContents(), "small");
+  VerifyPluginMarkedEssential(GetActiveWebContents(), "cross_origin");
+}
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index f3d9796c..f787bf2 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -315,6 +315,9 @@
   { key::kAllowOutdatedPlugins,
     prefs::kPluginsAllowOutdated,
     base::Value::Type::BOOLEAN },
+  { key::kRunAllFlashInAllowMode,
+    prefs::kRunAllFlashInAllowMode,
+    base::Value::Type::BOOLEAN },
   { key::kAlwaysAuthorizePlugins,
     prefs::kPluginsAlwaysAuthorize,
     base::Value::Type::BOOLEAN },
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index 12e92943..fbc673a 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -1202,9 +1202,8 @@
                           safe_search == 0  // ForceGoogleSafeSearch
                               ? nullptr
                               : base::MakeUnique<base::Value>(safe_search == 1),
-                          nullptr,  // ForceYouTubeSafetyMode
-                          nullptr   // ForceYouTubeRestrict
-                          );
+                          nullptr,   // ForceYouTubeSafetyMode
+                          nullptr);  // ForceYouTubeRestrict
     // Verify that the safe search pref behaves the way we expect.
     PrefService* prefs = browser()->profile()->GetPrefs();
     EXPECT_EQ(safe_search != 0,
@@ -3204,7 +3203,7 @@
         browser()->tab_strip_model()->GetActiveWebContents();
     EXPECT_EQ(request_url_,
               web_contents->GetMainFrame()->GetLastCommittedURL());
-    int render_process_id = web_contents->GetRenderProcessHost()->GetID();
+    int render_process_id = web_contents->GetMainFrame()->GetProcess()->GetID();
     int render_frame_id = web_contents->GetMainFrame()->GetRoutingID();
     return content::MediaStreamRequest(
         render_process_id, render_frame_id, 0, request_url_.GetOrigin(), false,
diff --git a/chrome/browser/predictors/loading_predictor_config.cc b/chrome/browser/predictors/loading_predictor_config.cc
index aa8cc30..b615945 100644
--- a/chrome/browser/predictors/loading_predictor_config.cc
+++ b/chrome/browser/predictors/loading_predictor_config.cc
@@ -6,6 +6,7 @@
 
 #include "base/metrics/field_trial_params.h"
 #include "chrome/browser/net/prediction_options.h"
+#include "chrome/browser/net/predictor.h"
 #include "chrome/browser/predictors/resource_prefetch_common.h"
 #include "chrome/browser/profiles/profile.h"
 #include "content/public/browser/browser_thread.h"
@@ -102,7 +103,7 @@
     : mode(0),
       max_navigation_lifetime_seconds(60),
       max_urls_to_track(500),
-      max_hosts_to_track(200),
+      max_hosts_to_track(chrome_browser_net::Predictor::kMaxReferrers),
       min_url_visit_count(2),
       max_resources_per_entry(50),
       max_origins_per_entry(50),
diff --git a/chrome/browser/predictors/resource_prefetch_predictor.cc b/chrome/browser/predictors/resource_prefetch_predictor.cc
index 6a896f9..dd9d816 100644
--- a/chrome/browser/predictors/resource_prefetch_predictor.cc
+++ b/chrome/browser/predictors/resource_prefetch_predictor.cc
@@ -280,20 +280,32 @@
     return;
   }
 
-  // Kick off history lookup to determine if we should record the URL.
-  history::HistoryService* history_service =
-      HistoryServiceFactory::GetForProfile(profile_,
-                                           ServiceAccessType::EXPLICIT_ACCESS);
-  DCHECK(history_service);
-  history_service->ScheduleDBTask(
-      std::unique_ptr<history::HistoryDBTask>(new GetUrlVisitCountTask(
-          std::move(summary),
-          base::BindOnce(&ResourcePrefetchPredictor::OnVisitCountLookup,
-                         weak_factory_.GetWeakPtr()))),
-      &history_lookup_consumer_);
+  history::HistoryService* history_service = nullptr;
+  if (config_.is_url_learning_enabled) {
+    // Kick off history lookup to determine if we should record the URL.
+    history_service = HistoryServiceFactory::GetForProfile(
+        profile_, ServiceAccessType::EXPLICIT_ACCESS);
+    DCHECK(history_service);
+    history_service->ScheduleDBTask(
+        std::unique_ptr<history::HistoryDBTask>(new GetUrlVisitCountTask(
+            std::move(summary),
+            base::BindOnce(&ResourcePrefetchPredictor::OnVisitCountLookup,
+                           weak_factory_.GetWeakPtr()))),
+        &history_lookup_consumer_);
+  } else {
+    // We won't record the URL data anyway so avoid the hop to the history
+    // sequence and back.
+    OnVisitCountLookup(0, *summary);
+  }
 
-  // Report readiness metric with 20% probability.
-  if (base::RandInt(1, 5) == 5) {
+  // Report readiness metric with 20% probability and only if the host learning
+  // is enabled.
+  if (config_.is_host_learning_enabled && base::RandInt(1, 5) == 5) {
+    if (!history_service) {
+      history_service = HistoryServiceFactory::GetForProfile(
+          profile_, ServiceAccessType::EXPLICIT_ACCESS);
+    }
+    DCHECK(history_service);
     history_service->TopHosts(
         kNumSampleHosts,
         base::Bind(&ResourcePrefetchPredictor::ReportDatabaseReadiness,
diff --git a/chrome/browser/predictors/resource_prefetch_predictor_browsertest.cc b/chrome/browser/predictors/resource_prefetch_predictor_browsertest.cc
index f4c83d1..8a18c4b6 100644
--- a/chrome/browser/predictors/resource_prefetch_predictor_browsertest.cc
+++ b/chrome/browser/predictors/resource_prefetch_predictor_browsertest.cc
@@ -323,9 +323,14 @@
   using URLRequestSummary = URLRequestSummary;
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
-    content::EnableFeatureWithParam(kSpeculativeResourcePrefetchingFeature,
-                                    kModeParamName, kExternalPrefetchingMode,
-                                    command_line);
+    command_line->AppendSwitchASCII("force-fieldtrials", "trial/group");
+    std::string params = base::StringPrintf(
+        "trial.group:%s/%s/%s/%s", kModeParamName, kExternalPrefetchingMode,
+        kEnableUrlLearningParamName, "true");
+    command_line->AppendSwitchASCII("force-fieldtrial-params", params);
+    std::string enabled_feature = base::StringPrintf(
+        "%s<trial", kSpeculativeResourcePrefetchingFeatureName);
+    command_line->AppendSwitchASCII("enable-features", enabled_feature);
   }
 
   void SetUpOnMainThread() override {
@@ -728,9 +733,10 @@
  protected:
   void SetUpCommandLine(base::CommandLine* command_line) override {
     command_line->AppendSwitchASCII("force-fieldtrials", "trial/group");
-    std::string parameter = base::StringPrintf(
-        "trial.group:%s/%s", kModeParamName, kPrefetchingMode);
-    command_line->AppendSwitchASCII("force-fieldtrial-params", parameter);
+    std::string params = base::StringPrintf(
+        "trial.group:%s/%s/%s/%s", kModeParamName, kPrefetchingMode,
+        kEnableUrlLearningParamName, "true");
+    command_line->AppendSwitchASCII("force-fieldtrial-params", params);
     std::string enabled_feature = base::StringPrintf(
         "%s<trial", kSpeculativeResourcePrefetchingFeatureName);
     command_line->AppendSwitchASCII("enable-features", enabled_feature);
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 10743d3c..46cf8d4 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -39,7 +39,6 @@
 #include "chrome/browser/notifications/notification_channels_provider_android.h"
 #include "chrome/browser/notifications/notifier_state_tracker.h"
 #include "chrome/browser/pepper_flash_settings_manager.h"
-#include "chrome/browser/plugins/plugin_finder.h"
 #include "chrome/browser/policy/policy_helpers.h"
 #include "chrome/browser/prefs/chrome_pref_service_factory.h"
 #include "chrome/browser/prefs/incognito_mode_prefs.h"
@@ -150,6 +149,8 @@
 #endif
 
 #if BUILDFLAG(ENABLE_PLUGINS)
+#include "chrome/browser/plugins/plugin_finder.h"
+#include "chrome/browser/plugins/plugin_info_message_filter.h"
 #include "chrome/browser/plugins/plugins_resource_service.h"
 #endif
 
@@ -458,7 +459,8 @@
   SCOPED_UMA_HISTOGRAM_TIMER("Settings.RegisterProfilePrefsTime");
   // User prefs. Please keep this list alphabetized.
   autofill::AutofillManager::RegisterProfilePrefs(registry);
-  syncer::SyncPrefs::RegisterProfilePrefs(registry);
+  browsing_data::prefs::RegisterBrowserUserPrefs(registry);
+  certificate_transparency::CTPolicyManager::RegisterPrefs(registry);
   ChromeContentBrowserClient::RegisterProfilePrefs(registry);
   ChromeVersionService::RegisterProfilePrefs(registry);
   chrome_browser_net::Predictor::RegisterProfilePrefs(registry);
@@ -489,6 +491,7 @@
   password_bubble_experiment::RegisterPrefs(registry);
   password_manager::PasswordManager::RegisterProfilePrefs(registry);
   payments::RegisterProfilePrefs(registry);
+  policy::URLBlacklistManager::RegisterProfilePrefs(registry);
   PrefProxyConfigTrackerImpl::RegisterProfilePrefs(registry);
   PrefsTabHelper::RegisterProfilePrefs(registry);
   Profile::RegisterProfilePrefs(registry);
@@ -499,14 +502,11 @@
   RegisterBrowserUserPrefs(registry);
   safe_browsing::RegisterProfilePrefs(registry);
   SessionStartupPref::RegisterProfilePrefs(registry);
+  syncer::SyncPrefs::RegisterProfilePrefs(registry);
   TemplateURLPrepopulateData::RegisterProfilePrefs(registry);
   translate::TranslatePrefs::RegisterProfilePrefs(registry);
   UINetworkQualityEstimatorService::RegisterProfilePrefs(registry);
   ZeroSuggestProvider::RegisterProfilePrefs(registry);
-  browsing_data::prefs::RegisterBrowserUserPrefs(registry);
-
-  policy::URLBlacklistManager::RegisterProfilePrefs(registry);
-  certificate_transparency::CTPolicyManager::RegisterPrefs(registry);
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
   ExtensionWebUI::RegisterProfilePrefs(registry);
@@ -524,6 +524,10 @@
   feature_engagement::SessionDurationUpdater::RegisterProfilePrefs(registry);
 #endif
 
+#if BUILDFLAG(ENABLE_PLUGINS)
+  PluginInfoMessageFilter::RegisterUserPrefs(registry);
+#endif
+
 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
   printing::StickySettings::RegisterProfilePrefs(registry);
 #endif
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc
index 86dc0119..c27664c 100644
--- a/chrome/browser/prerender/prerender_browsertest.cc
+++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -1055,7 +1055,7 @@
 
   ChannelDestructionWatcher channel_close_watcher;
   channel_close_watcher.WatchChannel(
-      GetActiveWebContents()->GetRenderProcessHost());
+      GetActiveWebContents()->GetMainFrame()->GetProcess());
   NavigateToDestURL();
   channel_close_watcher.WaitForChannelClose();
   fcp_waiter->Wait();
@@ -1173,7 +1173,7 @@
 
   ChannelDestructionWatcher channel_close_watcher;
   channel_close_watcher.WatchChannel(
-      GetActiveWebContents()->GetRenderProcessHost());
+      GetActiveWebContents()->GetMainFrame()->GetProcess());
   NavigateToDestURL();
   channel_close_watcher.WaitForChannelClose();
 
@@ -1290,7 +1290,7 @@
 
   ChannelDestructionWatcher channel_close_watcher;
   channel_close_watcher.WatchChannel(
-      GetActiveWebContents()->GetRenderProcessHost());
+      GetActiveWebContents()->GetMainFrame()->GetProcess());
   NavigateToDestURL();
   channel_close_watcher.WaitForChannelClose();
 
@@ -2046,8 +2046,11 @@
                    1);
 
   ChannelDestructionWatcher channel_close_watcher;
-  channel_close_watcher.WatchChannel(browser()->tab_strip_model()->
-      GetActiveWebContents()->GetRenderProcessHost());
+  channel_close_watcher.WatchChannel(browser()
+                                         ->tab_strip_model()
+                                         ->GetActiveWebContents()
+                                         ->GetMainFrame()
+                                         ->GetProcess());
   NavigateToDestURL();
   channel_close_watcher.WaitForChannelClose();
 
@@ -2061,8 +2064,11 @@
       FINAL_STATUS_USED, 2);
 
   ChannelDestructionWatcher channel_close_watcher;
-  channel_close_watcher.WatchChannel(browser()->tab_strip_model()->
-      GetActiveWebContents()->GetRenderProcessHost());
+  channel_close_watcher.WatchChannel(browser()
+                                         ->tab_strip_model()
+                                         ->GetActiveWebContents()
+                                         ->GetMainFrame()
+                                         ->GetProcess());
   NavigateToDestURL();
   channel_close_watcher.WaitForChannelClose();
 
@@ -2758,8 +2764,11 @@
   PrerenderTestURL("/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
 
   ChannelDestructionWatcher channel_close_watcher;
-  channel_close_watcher.WatchChannel(browser()->tab_strip_model()->
-      GetActiveWebContents()->GetRenderProcessHost());
+  channel_close_watcher.WatchChannel(browser()
+                                         ->tab_strip_model()
+                                         ->GetActiveWebContents()
+                                         ->GetMainFrame()
+                                         ->GetProcess());
   NavigateToDestURL();
   channel_close_watcher.WaitForChannelClose();
 
@@ -2779,8 +2788,11 @@
   PrerenderTestURL("/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
 
   ChannelDestructionWatcher channel_close_watcher;
-  channel_close_watcher.WatchChannel(browser()->tab_strip_model()->
-      GetActiveWebContents()->GetRenderProcessHost());
+  channel_close_watcher.WatchChannel(browser()
+                                         ->tab_strip_model()
+                                         ->GetActiveWebContents()
+                                         ->GetMainFrame()
+                                         ->GetProcess());
   NavigateToDestURL();
   channel_close_watcher.WaitForChannelClose();
 
diff --git a/chrome/browser/printing/print_preview_dialog_controller.cc b/chrome/browser/printing/print_preview_dialog_controller.cc
index ba6ea65..4ffe5d2 100644
--- a/chrome/browser/printing/print_preview_dialog_controller.cc
+++ b/chrome/browser/printing/print_preview_dialog_controller.cc
@@ -36,6 +36,7 @@
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_source.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_delegate.h"
 #include "ui/web_dialogs/web_dialog_delegate.h"
@@ -268,10 +269,9 @@
        iter != preview_dialog_map_.end(); ++iter) {
     WebContents* preview_dialog = iter->first;
     WebContents* initiator = iter->second;
-    if (preview_dialog->GetRenderProcessHost() == rph) {
+    if (preview_dialog->GetMainFrame()->GetProcess() == rph) {
       closed_preview_dialogs.push_back(preview_dialog);
-    } else if (initiator &&
-               initiator->GetRenderProcessHost() == rph) {
+    } else if (initiator && initiator->GetMainFrame()->GetProcess() == rph) {
       closed_initiators.push_back(initiator);
     }
   }
@@ -412,19 +412,19 @@
   // Multiple sites may share the same RenderProcessHost, so check if this
   // notification has already been added.
   content::Source<content::RenderProcessHost> rph_source(
-      contents->GetRenderProcessHost());
+      contents->GetMainFrame()->GetProcess());
   if (!registrar_.IsRegistered(this,
       content::NOTIFICATION_RENDERER_PROCESS_CLOSED, rph_source)) {
     // Not registered for this host yet, so add the notification and add the
     // host to the count map with a count of 1.
     registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
                    rph_source);
-    host_contents_count_map_[contents->GetRenderProcessHost()] = 1;
+    host_contents_count_map_[contents->GetMainFrame()->GetProcess()] = 1;
   } else {
     // This host's notification is already registered. Increment its count in
     // the map so that the notification will not be removed from the registry
     // until all web contents that use it are destroyed.
-    ++host_contents_count_map_[contents->GetRenderProcessHost()];
+    ++host_contents_count_map_[contents->GetMainFrame()->GetProcess()];
   }
 }
 
@@ -437,19 +437,19 @@
   // Multiple sites may share the same RenderProcessHost, so check if this
   // notification has already been added.
   content::Source<content::RenderProcessHost> rph_source(
-      contents->GetRenderProcessHost());
+      contents->GetMainFrame()->GetProcess());
   if (registrar_.IsRegistered(this,
       content::NOTIFICATION_RENDERER_PROCESS_CLOSED, rph_source)) {
-    if (host_contents_count_map_[contents->GetRenderProcessHost()] == 1) {
+    if (host_contents_count_map_[contents->GetMainFrame()->GetProcess()] == 1) {
       // This is the last contents that has this render process host, so we can
       // remove the notification.
       registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
                         rph_source);
-      host_contents_count_map_.erase(contents->GetRenderProcessHost());
+      host_contents_count_map_.erase(contents->GetMainFrame()->GetProcess());
     } else {
       // Other initializers and/or dialogs are still connected to the host, so
       // we can't remove the notification. Decrement the count in the map.
-      --host_contents_count_map_[contents->GetRenderProcessHost()];
+      --host_contents_count_map_[contents->GetMainFrame()->GetProcess()];
     }
   }
 }
diff --git a/chrome/browser/printing/print_preview_dialog_controller_browsertest.cc b/chrome/browser/printing/print_preview_dialog_controller_browsertest.cc
index 335becff..3466854 100644
--- a/chrome/browser/printing/print_preview_dialog_controller_browsertest.cc
+++ b/chrome/browser/printing/print_preview_dialog_controller_browsertest.cc
@@ -298,7 +298,7 @@
   ChromePluginServiceFilter* filter = ChromePluginServiceFilter::GetInstance();
   content::WebPluginInfo dummy_pdf_plugin_info = pdf_plugin_info;
   EXPECT_FALSE(filter->IsPluginAvailable(
-      initiator()->GetRenderProcessHost()->GetID(),
+      initiator()->GetMainFrame()->GetProcess()->GetID(),
       initiator()->GetMainFrame()->GetRoutingID(),
       browser()->profile()->GetResourceContext(), GURL(),
       url::Origin(GURL("http://google.com")), &dummy_pdf_plugin_info));
diff --git a/chrome/browser/printing/print_view_manager.cc b/chrome/browser/printing/print_view_manager.cc
index b0c12ce..9ce77943 100644
--- a/chrome/browser/printing/print_view_manager.cc
+++ b/chrome/browser/printing/print_view_manager.cc
@@ -76,7 +76,7 @@
       is_switching_to_system_dialog_(false) {
   if (PrintPreviewDialogController::IsPrintPreviewURL(web_contents->GetURL())) {
     EnableInternalPDFPluginForContents(
-        web_contents->GetRenderProcessHost()->GetID(),
+        web_contents->GetMainFrame()->GetProcess()->GetID(),
         web_contents->GetMainFrame()->GetRoutingID());
   }
 }
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index b2bfdfb..92fb929 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -736,10 +736,12 @@
       extensions::WebViewGuest::FromWebContents(source_web_contents_);
   MenuItem::ExtensionKey key;
   if (web_view_guest) {
-    key = MenuItem::ExtensionKey(
-        extension->id(),
-        web_view_guest->owner_web_contents()->GetRenderProcessHost()->GetID(),
-        web_view_guest->view_instance_id());
+    key = MenuItem::ExtensionKey(extension->id(),
+                                 web_view_guest->owner_web_contents()
+                                     ->GetMainFrame()
+                                     ->GetProcess()
+                                     ->GetID(),
+                                 web_view_guest->view_instance_id());
   } else {
     key = MenuItem::ExtensionKey(extension->id());
   }
diff --git a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
index 3578712..737a2fa 100644
--- a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
+++ b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
@@ -23,6 +23,7 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/notification_service.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
@@ -105,7 +106,7 @@
 
     WaitForLauncherThread();
     WaitForMessageProcessing(wc);
-    return ProcessFromHandle(wc->GetRenderProcessHost()->GetHandle());
+    return ProcessFromHandle(wc->GetMainFrame()->GetProcess()->GetHandle());
   }
 
   // Loads the given url in a new background tab and returns the handle of its
@@ -122,7 +123,7 @@
 
     WaitForLauncherThread();
     WaitForMessageProcessing(wc);
-    return ProcessFromHandle(wc->GetRenderProcessHost()->GetHandle());
+    return ProcessFromHandle(wc->GetMainFrame()->GetProcess()->GetHandle());
   }
 
   // Ensures that the backgrounding / foregrounding gets a chance to run.
@@ -164,7 +165,7 @@
     ui_test_utils::NavigateToURL(browser(), omnibox);
     EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
     tab1 = browser()->tab_strip_model()->GetWebContentsAt(tab_count - 1);
-    rph1 = tab1->GetRenderProcessHost();
+    rph1 = tab1->GetMainFrame()->GetProcess();
     EXPECT_EQ(omnibox, tab1->GetURL());
     EXPECT_EQ(host_count, RenderProcessHostCount());
 
@@ -180,7 +181,7 @@
     host_count++;
     EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
     tab1 = browser()->tab_strip_model()->GetWebContentsAt(tab_count - 1);
-    rph2 = tab1->GetRenderProcessHost();
+    rph2 = tab1->GetMainFrame()->GetProcess();
     EXPECT_EQ(tab1->GetURL(), page1);
     EXPECT_EQ(host_count, RenderProcessHostCount());
     EXPECT_NE(rph1, rph2);
@@ -196,7 +197,7 @@
     tab2 = browser()->tab_strip_model()->GetWebContentsAt(tab_count - 1);
     EXPECT_EQ(tab2->GetURL(), page2);
     EXPECT_EQ(host_count, RenderProcessHostCount());
-    EXPECT_EQ(tab2->GetRenderProcessHost(), rph2);
+    EXPECT_EQ(tab2->GetMainFrame()->GetProcess(), rph2);
 
     // Create another TYPE_WEBUI tab.  It should share the process with omnibox.
     // Note: intentionally create this tab after the TYPE_TABBED tabs to
@@ -212,7 +213,7 @@
     tab2 = browser()->tab_strip_model()->GetWebContentsAt(tab_count - 1);
     EXPECT_EQ(tab2->GetURL(), GURL(history));
     EXPECT_EQ(host_count, RenderProcessHostCount());
-    EXPECT_EQ(tab2->GetRenderProcessHost(), rph1);
+    EXPECT_EQ(tab2->GetMainFrame()->GetProcess(), rph1);
 
     // Create a TYPE_EXTENSION tab.  It should be in its own process.
     GURL extension_url("chrome-extension://" + extension->id());
@@ -225,7 +226,7 @@
     host_count++;
     EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
     tab1 = browser()->tab_strip_model()->GetWebContentsAt(tab_count - 1);
-    rph3 = tab1->GetRenderProcessHost();
+    rph3 = tab1->GetMainFrame()->GetProcess();
     EXPECT_EQ(tab1->GetURL(), extension_url);
     EXPECT_EQ(host_count, RenderProcessHostCount());
     EXPECT_NE(rph1, rph3);
@@ -573,7 +574,8 @@
 
   WebContents* wc1 = browser()->tab_strip_model()->GetWebContentsAt(0);
   WebContents* wc2 = browser()->tab_strip_model()->GetWebContentsAt(1);
-  EXPECT_EQ(wc1->GetRenderProcessHost(), wc2->GetRenderProcessHost());
+  EXPECT_EQ(wc1->GetMainFrame()->GetProcess(),
+            wc2->GetMainFrame()->GetProcess());
 
   // Create an object that will close the window on a process crash.
   WindowDestroyer destroyer(wc1, browser()->tab_strip_model());
@@ -585,7 +587,7 @@
   // Kill the renderer process, simulating a crash. This should the ProcessDied
   // method to be called. Alternatively, RenderProcessHost::OnChannelError can
   // be called to directly force a call to ProcessDied.
-  wc1->GetRenderProcessHost()->Shutdown(-1, true);
+  wc1->GetMainFrame()->GetProcess()->Shutdown(-1, true);
 
   observer.Wait();
 }
@@ -627,14 +629,14 @@
     // Create a new tab for the no audio page and confirm that the process of
     // each tab is different and that both are valid.
     audio_process_ = ProcessFromHandle(
-        audio_tab_web_contents_->GetRenderProcessHost()->GetHandle());
+        audio_tab_web_contents_->GetMainFrame()->GetProcess()->GetHandle());
     no_audio_process_ = ShowSingletonTab(no_audio_url_);
     ASSERT_NE(audio_process_.Pid(), no_audio_process_.Pid());
     ASSERT_TRUE(no_audio_process_.IsValid());
     ASSERT_TRUE(audio_process_.IsValid());
 #if defined(OS_MACOSX)
     port_provider_ = content::BrowserChildProcessHost::GetPortProvider();
-#endif //  defined(OS_MACOSX)
+#endif  //  defined(OS_MACOSX)
   }
 
  protected:
diff --git a/chrome/browser/resources/chromeos/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/chromevox/BUILD.gn
index 5f75f2a..6e5018a 100644
--- a/chrome/browser/resources/chromeos/chromevox/BUILD.gn
+++ b/chrome/browser/resources/chromeos/chromevox/BUILD.gn
@@ -4,6 +4,7 @@
 
 import("//build/config/features.gni")
 import("//chrome/common/features.gni")
+import("//components/nacl/features.gni")
 import("//testing/test.gni")
 import("//chrome/test/base/js2gtest.gni")
 import("run_jsbundler.gni")
diff --git a/chrome/browser/resources/chromeos/emulator/device_emulator_pages.html b/chrome/browser/resources/chromeos/emulator/device_emulator_pages.html
index de37404d..9d876d3 100644
--- a/chrome/browser/resources/chromeos/emulator/device_emulator_pages.html
+++ b/chrome/browser/resources/chromeos/emulator/device_emulator_pages.html
@@ -12,7 +12,6 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-icon-item.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-listbox/paper-listbox.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-toolbar/paper-toolbar.html">
 <link rel="import" href="audio_settings.html">
 <link rel="import" href="battery_settings.html">
 <link rel="import" href="bluetooth_settings.html">
diff --git a/chrome/browser/resources/chromeos/login/oobe_change_picture.html b/chrome/browser/resources/chromeos/login/oobe_change_picture.html
index 96fe322c..c8ec243 100644
--- a/chrome/browser/resources/chromeos/login/oobe_change_picture.html
+++ b/chrome/browser/resources/chromeos/login/oobe_change_picture.html
@@ -48,8 +48,8 @@
           image-src="[[getImageSrc_(selectedItem_)]]"
           image-type="[[getImageType_(selectedItem_)]]"
           discard-image-label="[[i18nDynamic(locale, 'discardPhoto')]]"
-          flip-photo-label="[[i18nDynamic(locale, 'flipPhoto')]]"
-          take-photo-label="[[i18nDynamic(locale, 'takePhoto')]]">
+          take-photo-label="[[i18nDynamic(locale, 'takePhoto')]]"
+          switch-mode-label="[[i18nDynamic(locale, 'switchMode')]]">
       </cr-picture-pane>
       <cr-picture-list id="pictureList"
           camera-present="[[cameraPresent]]"
@@ -58,7 +58,8 @@
           selected-item="{{selectedItem_}}"
           old-image-label="[[i18nDynamic(locale, 'photoFromCamera')]]"
           profile-image-label="[[i18nDynamic(locale, 'profilePhoto')]]"
-          take-photo-label="[[i18nDynamic(locale, 'takePhoto')]]">
+          take-photo-label="[[i18nDynamic(locale, 'takePhoto')]]"
+          switch-mode-label="[[i18nDynamic(locale, 'switchMode')]]">
       </cr-picture-list>
     </div>
   </template>
diff --git a/chrome/browser/resources/chromeos/login/oobe_change_picture.js b/chrome/browser/resources/chromeos/login/oobe_change_picture.js
index adf3d1e2..d1a25ec 100644
--- a/chrome/browser/resources/chromeos/login/oobe_change_picture.js
+++ b/chrome/browser/resources/chromeos/login/oobe_change_picture.js
@@ -77,8 +77,8 @@
   listeners: {
     'discard-image': 'onDiscardImage_',
     'image-activate': 'onImageActivate_',
-    'photo-flipped': 'onPhotoFlipped_',
     'photo-taken': 'onPhotoTaken_',
+    'switch-mode': 'onSwitchMode_',
   },
 
   /** @private {?CrPictureListElement} */
@@ -197,11 +197,11 @@
    * @param {!{detail: boolean}} event
    * @private
    */
-  onPhotoFlipped_: function(event) {
-    var flipped = event.detail;
-    var flipMessageId = flipped ? 'photoFlippedAccessibleText' :
-                                  'photoFlippedBackAccessibleText';
-    announceAccessibleMessage(loadTimeData.getString(flipMessageId));
+  onSwitchMode_: function(event) {
+    var videomode = event.detail;
+    var modeMessageId =
+        videomode ? 'videoModeAccessibleText' : 'photoModeAccessibleText';
+    announceAccessibleMessage(loadTimeData.getString(modeMessageId));
   },
 
   /** @private */
diff --git a/chrome/browser/resources/chromeos/login/oobe_dialog.js b/chrome/browser/resources/chromeos/login/oobe_dialog.js
index 5038f3ae2..4b4fc8b 100644
--- a/chrome/browser/resources/chromeos/login/oobe_dialog.js
+++ b/chrome/browser/resources/chromeos/login/oobe_dialog.js
@@ -68,7 +68,16 @@
    */
   show: function() {
     var focusedElements = this.getElementsByClassName('focus-on-show');
-    if (focusedElements.length > 0)
+    var focused = false;
+    for (var i = 0; i < focusedElements.length; ++i) {
+      if (focusedElements[i].hidden)
+        continue;
+
+      focused = true;
+      focusedElements[i].focus();
+      break;
+    }
+    if (!focused && focusedElements.length > 0)
       focusedElements[0].focus();
 
     this.fire('show-dialog');
diff --git a/chrome/browser/resources/chromeos/login/oobe_reset.html b/chrome/browser/resources/chromeos/login/oobe_reset.html
index d2c25425..1dd3aea 100644
--- a/chrome/browser/resources/chromeos/login/oobe_reset.html
+++ b/chrome/browser/resources/chromeos/login/oobe_reset.html
@@ -87,16 +87,16 @@
             hidden="[[isCancelHidden_(uiState_)]]">
           <div i18n-content="cancelButton"></div>
         </oobe-text-button>
-        <oobe-text-button inverse on-tap="onRestartTap_"
+        <oobe-text-button inverse on-tap="onRestartTap_" class="focus-on-show"
             hidden="[[!isState_(uiState_, 'restart-required-view')]]">
           <div i18n-content="resetButtonRestart"></div>
         </oobe-text-button>
-        <oobe-text-button inverse on-tap="onPowerwashTap_"
+        <oobe-text-button inverse on-tap="onPowerwashTap_" class="focus-on-show"
             hidden="[[!isState_(uiState_, 'rollback-proposal-view')]]"
             disabled="[[tpmFirmwareUpdateChecked_]]">
           <div i18n-content="resetButtonPowerwashAndRollback"></div>
         </oobe-text-button>
-        <oobe-text-button inverse on-tap="onPowerwashTap_"
+        <oobe-text-button inverse on-tap="onPowerwashTap_" class="focus-on-show"
             hidden="[[!isState_(uiState_, 'powerwash-proposal-view')]]">
           <div i18n-content="resetButtonPowerwash"></div>
         </oobe-text-button>
diff --git a/chrome/browser/resources/chromeos/login/oobe_reset.js b/chrome/browser/resources/chromeos/login/oobe_reset.js
index 7d57a1e4..cd1b643 100644
--- a/chrome/browser/resources/chromeos/login/oobe_reset.js
+++ b/chrome/browser/resources/chromeos/login/oobe_reset.js
@@ -45,6 +45,10 @@
     },
   },
 
+  focus: function() {
+    this.$.resetDialog.focus();
+  },
+
   /** @private */
   isState_: function(uiState_, state_) {
     return uiState_ == state_;
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_user_image.js b/chrome/browser/resources/chromeos/login/oobe_screen_user_image.js
index 7ade283..01e59d0 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_user_image.js
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_user_image.js
@@ -11,6 +11,7 @@
   var CONTEXT_KEY_SELECTED_IMAGE_INDEX = 'selectedImageIndex';
   var CONTEXT_KEY_SELECTED_IMAGE_URL = 'selectedImageURL';
   var CONTEXT_KEY_PROFILE_PICTURE_DATA_URL = 'profilePictureDataURL';
+  var CONTEXT_KEY_IS_PROFILE_PICTURE_AVAILABLE = 'isProfilePictureAvailable';
 
   return {
     EXTERNAL_API: ['setDefaultImages', 'hideCurtain'],
@@ -32,6 +33,14 @@
             if (url)
               $('changePicture').setProfileImageUrl(url, false /* selected */);
           });
+      this.context.addObserver(
+          CONTEXT_KEY_IS_PROFILE_PICTURE_AVAILABLE, function(available) {
+            if (!available) {
+              self.profileImageLoading = false;
+              // Empty url hides profile image selection choice.
+              $('changePicture').setProfileImageUrl('', false /* selected */);
+            }
+          });
 
       this.profileImageLoading = true;
       chrome.send('getImages');
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
index eaa8cd88f..8650c5a 100644
--- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
+++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
@@ -1005,16 +1005,10 @@
             'authenticateUser',
             [credentials.email, credentials.password, false]);
       } else if (credentials.authCode) {
-        if (credentials.hasOwnProperty('authCodeOnly') &&
-            credentials.authCodeOnly) {
-          chrome.send(
-              'completeAuthenticationAuthCodeOnly', [credentials.authCode]);
-        } else {
-          chrome.send('completeAuthentication', [
-            credentials.gaiaId, credentials.email, credentials.password,
-            credentials.authCode, credentials.usingSAML, credentials.gapsCookie
-          ]);
-        }
+        chrome.send('completeAuthentication', [
+          credentials.gaiaId, credentials.email, credentials.password,
+          credentials.authCode, credentials.usingSAML, credentials.gapsCookie
+        ]);
       } else {
         chrome.send('completeLogin', [
           credentials.gaiaId, credentials.email, credentials.password,
diff --git a/chrome/browser/resources/chromeos/login/screen_supervised_user_creation.css b/chrome/browser/resources/chromeos/login/screen_supervised_user_creation.css
index 7c5d716..fda6cbb 100644
--- a/chrome/browser/resources/chromeos/login/screen_supervised_user_creation.css
+++ b/chrome/browser/resources/chromeos/login/screen_supervised_user_creation.css
@@ -420,7 +420,7 @@
   display: none;
 }
 
-.camera.flip-x #supervised-user-creation-image-preview-img {
+.camera #supervised-user-creation-image-preview-img {
   transform: rotateY(180deg);
 }
 
@@ -447,14 +447,11 @@
   height: 220px;
   overflow: hidden;
   position: relative;
+  transform: rotateY(180deg);
   transition: transform 200ms linear;
   width: 220px;
 }
 
-.flip-x #supervised-user-creation-image-stream-crop {
-  transform: rotateY(180deg);
-}
-
 .supervised-user-creation-image-stream {
   border: solid 1px #cacaca;
   height: 220px;
@@ -478,30 +475,6 @@
   display: none;
 }
 
-#supervised-user-creation-flip-photo {
-  background: url(chrome://theme/IDR_MIRROR_FLIP) no-repeat;
-  border: none;
-  bottom: 44px;  /* 8px + image bottom. */
-  display: block;
-  height: 32px;
-  opacity: 0;
-  position: absolute;
-  right: 8px;
-  transition: opacity 75ms linear;
-  width: 32px;
-}
-
-html[dir=rtl] #supervised-user-creation-flip-photo {
-  left: 8px;
-  right: auto;
-}
-
-/* "Flip photo" button is hidden during flip animation. */
-.camera.online:not(.animation) #supervised-user-creation-flip-photo,
-.camera.phototaken:not(.animation) #supervised-user-creation-flip-photo {
-  opacity: 0.75;
-}
-
 #supervised-user-creation-discard-photo,
 #supervised-user-creation-take-photo {
   display: none;
diff --git a/chrome/browser/resources/chromeos/login/screen_supervised_user_creation.html b/chrome/browser/resources/chromeos/login/screen_supervised_user_creation.html
index baef507..42ac269 100644
--- a/chrome/browser/resources/chromeos/login/screen_supervised_user_creation.html
+++ b/chrome/browser/resources/chromeos/login/screen_supervised_user_creation.html
@@ -80,9 +80,6 @@
             <div class="spinner"></div>
           </div>
           <p id="supervised-user-creation-image-preview-caption"></p>
-            <button id="supervised-user-creation-flip-photo"
-                class="custom-appearance"
-                i18n-values="title:flipPhoto"></button>
           <button id="supervised-user-creation-discard-photo"
               i18n-values="title:discardPhoto"></button>
           <button id="supervised-user-creation-take-photo"
diff --git a/chrome/browser/resources/chromeos/login/screen_supervised_user_creation.js b/chrome/browser/resources/chromeos/login/screen_supervised_user_creation.js
index 069305e..1930d7b 100644
--- a/chrome/browser/resources/chromeos/login/screen_supervised_user_creation.js
+++ b/chrome/browser/resources/chromeos/login/screen_supervised_user_creation.js
@@ -583,7 +583,6 @@
 
           imageGrid.previewElement = previewElement;
           imageGrid.selectionType = 'default';
-          imageGrid.flipPhotoElement = this.getScreenElement('flip-photo');
 
           imageGrid.addEventListener(
               'activate', this.handleActivate_.bind(this));
@@ -603,8 +602,6 @@
               .addEventListener('click', this.handleDiscardPhoto_.bind(this));
 
           // Toggle 'animation' class for the duration of WebKit transition.
-          this.getScreenElement('flip-photo')
-              .addEventListener('click', this.handleFlipPhoto_.bind(this));
           this.getScreenElement('image-stream-crop')
               .addEventListener('transitionend', function(e) {
                 previewElement.classList.remove('animation');
@@ -1454,8 +1451,6 @@
           var imageGrid = this.getScreenElement('image-grid');
           this.updateNextButtonForUser_();
 
-          $('supervised-user-creation-flip-photo').tabIndex =
-              (imageGrid.selectionType == 'camera') ? 0 : -1;
           if (imageGrid.cameraLive || imageGrid.selectionType != 'camera')
             imageGrid.previewElement.classList.remove('phototaken');
           else
@@ -1488,19 +1483,6 @@
         },
 
         /**
-         * Handle camera-photo flip.
-         */
-        handleFlipPhoto_: function() {
-          var imageGrid = this.getScreenElement('image-grid');
-          imageGrid.previewElement.classList.add('animation');
-          imageGrid.flipPhoto = !imageGrid.flipPhoto;
-          var flipMessageId = imageGrid.flipPhoto ?
-              'photoFlippedAccessibleText' :
-              'photoFlippedBackAccessibleText';
-          announceAccessibleMessage(loadTimeData.getString(flipMessageId));
-        },
-
-        /**
          * Handle photo capture from the live camera stream.
          */
         handleTakePhoto_: function(e) {
diff --git a/chrome/browser/resources/chromeos/user_images_grid.js b/chrome/browser/resources/chromeos/user_images_grid.js
index e713eae..1d6b5ef 100644
--- a/chrome/browser/resources/chromeos/user_images_grid.js
+++ b/chrome/browser/resources/chromeos/user_images_grid.js
@@ -440,30 +440,6 @@
     },
 
     /**
-     * Whether the camera live stream and photo should be flipped horizontally.
-     * If setting this property results in photo update, 'photoupdated' event
-     * will be fired with 'dataURL' property containing the photo encoded as
-     * a data URL
-     * @type {boolean}
-     */
-    get flipPhoto() {
-      return this.flipPhoto_ || false;
-    },
-    set flipPhoto(value) {
-      if (this.flipPhoto_ == value)
-        return;
-      this.flipPhoto_ = value;
-      this.previewElement.classList.toggle('flip-x', value);
-      if (!this.cameraLive) {
-        // Flip current still photo.
-        var e = new Event('photoupdated');
-        e.dataURL = this.flipPhoto ? this.flipFrame_(this.previewImage_) :
-                                     this.previewImage_.src;
-        this.dispatchEvent(e);
-      }
-    },
-
-    /**
      * Performs photo capture from the live camera stream. 'phototaken' event
      * will be fired as soon as captured photo is available, with 'dataURL'
      * property containing the photo encoded as a data URL.
@@ -488,7 +464,7 @@
       }.bind(this));
       previewImg.src = canvas.toDataURL('image/png');
       var e = new Event('phototaken');
-      e.dataURL = this.flipPhoto ? this.flipFrame_(canvas) : previewImg.src;
+      e.dataURL = this.flipFrame_(canvas);
       this.dispatchEvent(e);
       return true;
     },
diff --git a/chrome/browser/resources/gaia_auth_host/authenticator.js b/chrome/browser/resources/gaia_auth_host/authenticator.js
index 2c3f836f..eb0fa11 100644
--- a/chrome/browser/resources/gaia_auth_host/authenticator.js
+++ b/chrome/browser/resources/gaia_auth_host/authenticator.js
@@ -73,7 +73,6 @@
     'constrained',   // Whether the extension is loaded in a constrained
                      // window.
     'clientId',      // Chrome client id.
-    'useEafe',       // Whether to use EAFE.
     'needPassword',  // Whether the host is interested in getting a password.
                      // If this set to |false|, |confirmPasswordCallback| is
                      // not called before dispatching |authCopleted|.
@@ -144,7 +143,6 @@
     this.newGapsCookie_ = null;
     this.readyFired_ = false;
 
-    this.useEafe_ = false;
     this.clientId_ = null;
 
     this.samlHandler_ = new cr.login.SamlHandler(this.webview_);
@@ -168,7 +166,6 @@
     this.webview_.addEventListener(
         'contentload', this.onContentLoad_.bind(this));
     this.webview_.addEventListener('loadabort', this.onLoadAbort_.bind(this));
-    this.webview_.addEventListener('loadstop', this.onLoadStop_.bind(this));
     this.webview_.addEventListener('loadcommit', this.onLoadCommit_.bind(this));
     this.webview_.request.onCompleted.addListener(
         this.onRequestCompleted_.bind(this),
@@ -232,7 +229,6 @@
         this.continueUrl_;
     this.isConstrainedWindow_ = data.constrained == '1';
     this.isNewGaiaFlow = data.isNewGaiaFlow;
-    this.useEafe_ = data.useEafe || false;
     this.clientId_ = data.clientId;
     this.gapsCookie_ = data.gapsCookie;
     this.gapsCookieSent_ = false;
@@ -562,17 +558,6 @@
       return false;
     }
 
-    // EAFE passes back auth code via message.
-    if (this.useEafe_ && typeof e.data == 'object' &&
-        e.data.hasOwnProperty('authorizationCode')) {
-      assert(!this.oauthCode_);
-      this.oauthCode_ = e.data.authorizationCode;
-      this.dispatchEvent(new CustomEvent(
-          'authCompleted',
-          {detail: {authCodeOnly: true, authCode: this.oauthCode_}}));
-      return;
-    }
-
     // Gaia messages must be an object with 'method' property.
     if (typeof e.data != 'object' || !e.data.hasOwnProperty('method')) {
       return false;
@@ -841,27 +826,6 @@
   };
 
   /**
-   * Invoked when the webview finishes loading a page.
-   * @private
-   */
-  Authenticator.prototype.onLoadStop_ = function(e) {
-    // Sends client id to EAFE on every loadstop after a small timeout. This is
-    // needed because EAFE sits behind SSO and initialize asynchrounouly
-    // and we don't know for sure when it is loaded and ready to listen
-    // for message. The postMessage is guarded by EAFE's origin.
-    if (this.useEafe_) {
-      // An arbitrary small timeout for delivering the initial message.
-      var EAFE_INITIAL_MESSAGE_DELAY_IN_MS = 500;
-      window.setTimeout(
-          (function() {
-            var msg = {'clientId': this.clientId_};
-            this.webview_.contentWindow.postMessage(msg, this.idpOrigin_);
-          }).bind(this),
-          EAFE_INITIAL_MESSAGE_DELAY_IN_MS);
-    }
-  };
-
-  /**
    * Invoked when the webview navigates withing the current document.
    * @private
    */
diff --git a/chrome/browser/resources/interventions_internals/index.html b/chrome/browser/resources/interventions_internals/index.html
index 4a9c2f59..addf058 100644
--- a/chrome/browser/resources/interventions_internals/index.html
+++ b/chrome/browser/resources/interventions_internals/index.html
@@ -12,9 +12,7 @@
   </head>
 
   <body>
-    <p>Interventions-Internals -- Comming soon!</p>
     <div id="previewsStatuses">
-      <p id="offlinePreviews"></p>
     </div>
   </body>
 </html>
diff --git a/chrome/browser/resources/interventions_internals/index.js b/chrome/browser/resources/interventions_internals/index.js
index f4cf661..f299ed3 100644
--- a/chrome/browser/resources/interventions_internals/index.js
+++ b/chrome/browser/resources/interventions_internals/index.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-cr.define('interventions_internals', function() {
+cr.define('interventions_internals', () => {
   let pageHandler = null;
 
   function init(handler) {
@@ -12,13 +12,23 @@
 
   function getPreviewsEnabled() {
     pageHandler.getPreviewsEnabled()
-        .then(function(response) {
-          let message = 'OfflinePreviews: ';
-          message += response.enabled ? 'Enabled' : 'Disabled';
-          $('offlinePreviews').textContent = message;
+        .then((response) => {
+          let statuses = $('previewsStatuses');
+
+          response.statuses.forEach((value, key) => {
+            let message = value.description + ': ';
+            message += value.enabled ? 'Enabled' : 'Disabled';
+
+            assert(!$(key), 'Component ' + key + ' already existed!');
+
+            let node = document.createElement('p');
+            node.setAttribute('id', key);
+            node.textContent = message;
+            statuses.appendChild(node);
+          });
         })
-        .catch(function(error) {
-          node.textContent = error.message;
+        .catch((error) => {
+          console.error(error.message);
         });
   }
 
@@ -31,10 +41,10 @@
   return Promise.resolve();
 };
 
-document.addEventListener('DOMContentLoaded', function() {
+document.addEventListener('DOMContentLoaded', () => {
   let pageHandler = null;
 
-  window.setupFn().then(function() {
+  window.setupFn().then(() => {
     if (window.testPageHandler) {
       pageHandler = window.testPageHandler;
     } else {
diff --git a/chrome/browser/resources/local_ntp/local_ntp.css b/chrome/browser/resources/local_ntp/local_ntp.css
index 0cbbe47..7c507af 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.css
+++ b/chrome/browser/resources/local_ntp/local_ntp.css
@@ -71,9 +71,14 @@
 }
 
 #logo-default,
+#logo-non-white,
+#logo-doodle {
+  position: absolute;
+}
+
+#logo-default,
 #logo-doodle {
   opacity: 0;
-  position: absolute;
 }
 
 #logo-default.fade,
@@ -81,7 +86,8 @@
   transition: opacity 130ms;
 }
 
-#logo-default {
+#logo-default,
+#logo-non-white {
   background-image: url(../../../../ui/webui/resources/images/google_logo.svg);
   background-repeat: no-repeat;
   height: 92px;
@@ -90,6 +96,24 @@
   width: 272px;
 }
 
+body.alternate-logo #logo-default,
+body.alternate-logo #logo-non-white {
+  -webkit-mask-image:
+      url(../../../../ui/webui/resources/images/google_logo.svg);
+  -webkit-mask-repeat: no-repeat;
+  -webkit-mask-size: 100%;
+  background: #eee;
+}
+
+#logo-default,
+.non-white-bg #logo-non-white {
+  display: block;
+}
+#logo-non-white,
+.non-white-bg #logo-default {
+  display: none;
+}
+
 #logo-doodle {
   /* Normally, logos are aligned with tiles and bounded to their left and right
    * edges. Doodles may be larger than this. In order that they are centered and
@@ -106,12 +130,79 @@
   margin: 0 auto;
 }
 
-body.alternate-logo #logo-default {
-  -webkit-mask-image:
-      url(../../../../ui/webui/resources/images/google_logo.svg);
-  -webkit-mask-repeat: no-repeat;
-  -webkit-mask-size: 100%;
-  background: #eee;
+.non-white-bg #logo-doodle-link {
+  display: none;
+}
+
+#logo-doodle-notifier {
+  display: none;
+}
+.non-white-bg #logo-doodle-notifier {
+  cursor: pointer;
+  display: inline-block;
+  height: 24px;
+  left: 148px;
+  position: relative;
+  top: 100px;
+  width: 24px;
+}
+@keyframes anim-pos {
+  0% { transform: translate(-98%, 0); }
+  100% { transform: translate(98%, 0); }
+}
+@keyframes anim-z-order {
+  0% { z-index: 100; }
+  100% { z-index: 1; }
+}
+.non-white-bg #logo-doodle-notifier .outer {
+  animation: anim-z-order 3520ms linear infinite;
+  height: 37.5%;
+  left: 50%;
+  margin-left: -18.75%;
+  margin-top: -18.75%;
+  position: absolute;
+  top: 50%;
+  width: 37.5%;
+}
+.non-white-bg #logo-doodle-notifier .inner {
+  animation: anim-pos 880ms cubic-bezier(0.445, 0.05, 0.55, 0.95)
+      infinite alternate;
+  border-radius: 50%;
+  height: 100%;
+  position: absolute;
+  transform: rotate(90deg);
+  width: 100%;
+}
+.non-white-bg #logo-doodle-notifier .ball0 {
+  animation-delay: 2640ms;
+  transform: rotate(45deg);
+}
+.non-white-bg #logo-doodle-notifier .ball1 {
+  animation-delay: 1760ms;
+  transform: rotate(135deg);
+}
+.non-white-bg #logo-doodle-notifier .ball2 {
+  transform: rotate(225deg);
+}
+.non-white-bg #logo-doodle-notifier .ball3 {
+  animation-delay: 880ms;
+  transform: rotate(315deg);
+}
+.non-white-bg #logo-doodle-notifier .ball0 .inner {
+  background: linear-gradient(
+      315deg, rgb(0, 85, 221), rgb(0, 119, 255), rgb(0, 119, 255));
+}
+.non-white-bg #logo-doodle-notifier .ball1 .inner {
+  background: linear-gradient(
+      225deg, rgb(221, 0, 0), rgb(238, 51, 51), rgb(255, 119, 85));
+}
+.non-white-bg #logo-doodle-notifier .ball2 .inner {
+  background: linear-gradient(
+      90deg, rgb(0, 119, 68), rgb(0, 153, 68), rgb(85, 187, 85));
+}
+.non-white-bg #logo-doodle-notifier .ball3 .inner {
+  background: linear-gradient(
+      0deg, rgb(255, 170, 51), rgb(255, 204, 0), rgb(255, 221, 102));
 }
 
 #fakebox {
diff --git a/chrome/browser/resources/local_ntp/local_ntp.html b/chrome/browser/resources/local_ntp/local_ntp.html
index 93d569b..82ed2ab 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.html
+++ b/chrome/browser/resources/local_ntp/local_ntp.html
@@ -28,10 +28,20 @@
       <div id="logo">
         <!-- The logo that is displayed in the absence of a doodle. -->
         <div id="logo-default" title="Google"></div>
+        <!-- Logo displayed when theme prevents doodles. Doesn't fade. -->
+        <div id="logo-non-white" title="Google"></div>
+        <!-- A doodle, if any: its link and image. -->
         <div id="logo-doodle">
           <a id="logo-doodle-link">
             <img id="logo-doodle-image"></img>
           </a>
+          <!-- A spinner, visible on dark-themed NTPs, prompting the doodle -->
+          <div id="logo-doodle-notifier">
+            <div class="outer ball0"><div class="inner"></div></div>
+            <div class="outer ball1"><div class="inner"></div></div>
+            <div class="outer ball2"><div class="inner"></div></div>
+            <div class="outer ball3"><div class="inner"></div></div>
+          </div>
         </div>
       </div>
       <div id="fakebox">
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js
index fb5a74f1..d3bc45ea 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.js
+++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -67,6 +67,7 @@
   LEFT_ALIGN_ATTRIBUTION: 'left-align-attribution',
   // Vertically centers the most visited section for a non-Google provided page.
   NON_GOOGLE_PAGE: 'non-google-page',
+  NON_WHITE_BG: 'non-white-bg',
   RTL: 'rtl'  // Right-to-left language text.
 };
 
@@ -89,6 +90,7 @@
   LOGO_DOODLE: 'logo-doodle',
   LOGO_DOODLE_IMAGE: 'logo-doodle-image',
   LOGO_DOODLE_LINK: 'logo-doodle-link',
+  LOGO_DOODLE_NOTIFIER: 'logo-doodle-notifier',
   NOTIFICATION: 'mv-notice',
   NOTIFICATION_CLOSE_BUTTON: 'mv-notice-x',
   NOTIFICATION_MESSAGE: 'mv-msg',
@@ -101,6 +103,15 @@
 
 
 /**
+ * Background colors considered "white". Used to determine if it is possible
+ * to display a Google Doodle, or if the notifier should be used instead.
+ * @type {Array<string>}
+ * @const
+ */
+var WHITE_BACKGROUND_COLORS = ['rgba(255,255,255,1)', 'rgba(0,0,0,0)'];
+
+
+/**
  * Enum for keycodes.
  * @enum {number}
  * @const
@@ -130,13 +141,36 @@
 
 
 /**
+ * Returns theme background info, first checking for history.state.notheme. If
+ * the page has notheme set, returns a fallback light-colored theme.
+ */
+function getThemeBackgroundInfo() {
+  if (history.state && history.state.notheme) {
+    return {
+      alternateLogo: false,
+      backgroundColorRgba: [255, 255, 255, 255],
+      colorRgba: [255, 255, 255, 255],
+      headerColorRgba: [150, 150, 150, 255],
+      linkColorRgba: [6, 55, 116, 255],
+      sectionBorderColorRgba: [150, 150, 150, 255],
+      textColorLightRgba: [102, 102, 102, 255],
+      textColorRgba: [0, 0, 0, 255],
+      usingDefaultTheme: true,
+    };
+  }
+  return ntpApiHandle.themeBackgroundInfo;
+}
+
+
+/**
  * Heuristic to determine whether a theme should be considered to be dark, so
  * the colors of various UI elements can be adjusted.
  * @param {ThemeBackgroundInfo|undefined} info Theme background information.
  * @return {boolean} Whether the theme is dark.
  * @private
  */
-function getIsThemeDark(info) {
+function getIsThemeDark() {
+  var info = getThemeBackgroundInfo();
   if (!info)
     return false;
   // Heuristic: light text implies dark theme.
@@ -151,8 +185,8 @@
  * @private
  */
 function renderTheme() {
-  var info = ntpApiHandle.themeBackgroundInfo;
-  var isThemeDark = getIsThemeDark(info);
+  var info = getThemeBackgroundInfo();
+  var isThemeDark = getIsThemeDark();
   $(IDS.NTP_CONTENTS).classList.toggle(CLASSES.DARK, isThemeDark);
   if (!info) {
     return;
@@ -166,6 +200,8 @@
 
   document.body.style.background = background;
   document.body.classList.toggle(CLASSES.ALTERNATE_LOGO, info.alternateLogo);
+  var isNonWhiteBackground = !WHITE_BACKGROUND_COLORS.includes(background);
+  document.body.classList.toggle(CLASSES.NON_WHITE_BG, isNonWhiteBackground);
   updateThemeAttribution(info.attributionUrl, info.imageHorizontalAlignment);
   setCustomThemeStyle(info);
 
@@ -199,7 +235,7 @@
     var oneGoogleBarApi = window.gbar.a;
     var oneGoogleBarPromise = oneGoogleBarApi.bf();
     oneGoogleBarPromise.then(function(oneGoogleBar) {
-      var isThemeDark = getIsThemeDark(ntpApiHandle.themeBackgroundInfo);
+      var isThemeDark = getIsThemeDark();
       var setForegroundStyle = oneGoogleBar.pc.bind(oneGoogleBar);
       setForegroundStyle(isThemeDark ? 1 : 0);
     });
@@ -586,7 +622,7 @@
       }
 
       // Got a (possibly empty) ddl object. Show logo or doodle.
-      showLogoOrDoodle(ddl.image, ddl.metadata);
+      showLogoOrDoodle(ddl.image || null, ddl.metadata || null);
       // If we got a valid ddl object (from cache), load a fresh one.
       if (ddl.v !== null) {
         loadDoodle(ddl.v, function(ddl) {
@@ -596,6 +632,17 @@
         });
       }
     });
+
+    // Set up doodle notifier (but it may be invisible).
+    var doodleNotifier = $(IDS.LOGO_DOODLE_NOTIFIER);
+    doodleNotifier.title = configData.translatedStrings.clickToViewDoodle;
+    doodleNotifier.addEventListener('click', function(e) {
+      e.preventDefault();
+      var state = window.history.state || {};
+      state.notheme = true;
+      window.history.replaceState(state, document.title);
+      onThemeChange();
+    });
   } else {
     document.body.classList.add(CLASSES.NON_GOOGLE_PAGE);
   }
diff --git a/chrome/browser/resources/local_ntp/most_visited_single.js b/chrome/browser/resources/local_ntp/most_visited_single.js
index b74ca6b7..b055f69 100644
--- a/chrome/browser/resources/local_ntp/most_visited_single.js
+++ b/chrome/browser/resources/local_ntp/most_visited_single.js
@@ -27,6 +27,21 @@
 
 
 /**
+ * The different sources where an NTP tile's title can originate from.
+ * Note: Keep in sync with components/ntp_tiles/tile_title_source.h
+ * @enum {number}
+ * @const
+ */
+var TileTitleSource = {
+  UNKNOWN: 0,
+  MANIFEST: 1,
+  META_TAG: 2,
+  TITLE: 3,
+  INFERRED: 4
+};
+
+
+/**
  * The different sources that an NTP tile can have.
  * Note: Keep in sync with components/ntp_tiles/tile_source.h
  * @enum {number}
@@ -113,23 +128,27 @@
 /**
  * Log impression of an NTP tile.
  * @param {number} tileIndex Position of the tile, >= 0 and < NUMBER_OF_TILES.
+ * @param {number} tileTitleSource The title's source from TileTitleSource.
  * @param {number} tileSource The source from TileSource.
  * @param {number} tileType The type from TileVisualType.
  */
-function logMostVisitedImpression(tileIndex, tileSource, tileType) {
+function logMostVisitedImpression(
+    tileIndex, tileTitleSource, tileSource, tileType) {
   chrome.embeddedSearch.newTabPage.logMostVisitedImpression(
-      tileIndex, tileSource, tileType);
+      tileIndex, tileTitleSource, tileSource, tileType);
 }
 
 /**
  * Log click on an NTP tile.
  * @param {number} tileIndex Position of the tile, >= 0 and < NUMBER_OF_TILES.
+ * @param {number} tileTitleSource The title's source from TileTitleSource.
  * @param {number} tileSource The source from TileSource.
  * @param {number} tileType The type from TileVisualType.
  */
-function logMostVisitedNavigation(tileIndex, tileSource, tileType) {
+function logMostVisitedNavigation(
+    tileIndex, tileTitleSource, tileSource, tileType) {
   chrome.embeddedSearch.newTabPage.logMostVisitedNavigation(
-      tileIndex, tileSource, tileType);
+      tileIndex, tileTitleSource, tileSource, tileType);
 }
 
 /**
@@ -387,7 +406,8 @@
   tile.title = data.title;
 
   tile.addEventListener('click', function(ev) {
-    logMostVisitedNavigation(position, data.tileSource, tileType);
+    logMostVisitedNavigation(
+        position, data.tileTitleSource, data.tileSource, tileType);
   });
 
   tile.addEventListener('keydown', function(event) {
@@ -447,7 +467,8 @@
   img.addEventListener('load', function(ev) {
     // Store the type for a potential later navigation.
     tileType = TileVisualType.THUMBNAIL;
-    logMostVisitedImpression(position, data.tileSource, tileType);
+    logMostVisitedImpression(
+        position, data.tileTitleSource, data.tileSource, tileType);
     // Note: It's important to call countLoad last, because that might emit the
     // NTP_ALL_TILES_LOADED event, which must happen after the impression log.
     countLoad();
@@ -457,7 +478,8 @@
     thumb.removeChild(img);
     // Store the type for a potential later navigation.
     tileType = TileVisualType.THUMBNAIL_FAILED;
-    logMostVisitedImpression(position, data.tileSource, tileType);
+    logMostVisitedImpression(
+        position, data.tileTitleSource, data.tileSource, tileType);
     // Note: It's important to call countLoad last, because that might emit the
     // NTP_ALL_TILES_LOADED event, which must happen after the impression log.
     countLoad();
diff --git a/chrome/browser/resources/md_downloads/manager.js b/chrome/browser/resources/md_downloads/manager.js
index 54ae328..3716f45 100644
--- a/chrome/browser/resources/md_downloads/manager.js
+++ b/chrome/browser/resources/md_downloads/manager.js
@@ -95,8 +95,16 @@
      * @private
      */
     insertItems_: function(index, list) {
-      this.splice.apply(this, ['items_', index, 0].concat(list));
+      // Insert |list| at the given |index| via Array#splice().
+      this.items_.splice.apply(this.items_, [index, 0].concat(list));
       this.updateHideDates_(index, index + list.length);
+      this.notifySplices('items_', [{
+                           index: index,
+                           addedCount: list.length,
+                           object: this.items_,
+                           type: 'splice',
+                           removed: [],
+                         }]);
 
       if (this.hasAttribute('loading')) {
         this.removeAttribute('loading');
@@ -195,12 +203,22 @@
      * @private
      */
     removeItem_: function(index) {
-      this.splice('items_', index, 1);
+      let removed = this.items_.splice(index, 1);
       this.updateHideDates_(index, index);
+      this.notifySplices('items_', [{
+                           index: index,
+                           addedCount: 0,
+                           object: this.items_,
+                           type: 'splice',
+                           removed: removed,
+                         }]);
       this.onListScroll_();
     },
 
     /**
+     * Updates whether dates should show for |this.items_[start - end]|. Note:
+     * this method does not trigger template bindings. Use notifySplices() or
+     * after calling this method to ensure items are redrawn.
      * @param {number} start
      * @param {number} end
      * @private
@@ -211,8 +229,7 @@
         if (!current)
           continue;
         const prev = this.items_[i - 1];
-        const hideDate = !!prev && prev.date_string == current.date_string;
-        this.set('items_.' + i + '.hideDate', hideDate);
+        current.hideDate = !!prev && prev.date_string == current.date_string;
       }
     },
 
@@ -222,8 +239,15 @@
      * @private
      */
     updateItem_: function(index, data) {
-      this.set('items_.' + index, data);
+      this.items_[index] = data;
       this.updateHideDates_(index, index);
+      this.notifySplices('items_', [{
+                           index: index,
+                           addedCount: 0,
+                           object: this.items_,
+                           type: 'splice',
+                           removed: [],
+                         }]);
       const list = /** @type {!IronListElement} */ (this.$['downloads-list']);
       list.updateSizeForItem(index);
     },
diff --git a/chrome/browser/resources/md_extensions/code_section.html b/chrome/browser/resources/md_extensions/code_section.html
index dff22ca..5878134 100644
--- a/chrome/browser/resources/md_extensions/code_section.html
+++ b/chrome/browser/resources/md_extensions/code_section.html
@@ -12,6 +12,7 @@
         color: var(--paper-grey-800);
         display: flex;
         font-family: monospace;
+        overflow: auto;
         white-space: pre;
       }
 
diff --git a/chrome/browser/resources/md_extensions/compiled_resources2.gyp b/chrome/browser/resources/md_extensions/compiled_resources2.gyp
index a7f5f2f7..eac2d1fd 100644
--- a/chrome/browser/resources/md_extensions/compiled_resources2.gyp
+++ b/chrome/browser/resources/md_extensions/compiled_resources2.gyp
@@ -102,6 +102,22 @@
       'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
     {
+      'target_name': 'kiosk_browser_proxy',
+      'dependencies': [
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+      ],
+      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+    },
+    {
+      'target_name': 'kiosk_dialog',
+      'dependencies': [
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
+        'kiosk_browser_proxy',
+      ],
+      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+    },
+    {
       'target_name': 'load_error',
       'dependencies': [
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
@@ -125,6 +141,7 @@
         'item_util',
         'load_error',
         'keyboard_shortcuts',
+        'kiosk_browser_proxy',
         'navigation_helper',
         'sidebar',
         'toolbar',
diff --git a/chrome/browser/resources/md_extensions/detail_view.html b/chrome/browser/resources/md_extensions/detail_view.html
index 504c5200..d0c6d2b 100644
--- a/chrome/browser/resources/md_extensions/detail_view.html
+++ b/chrome/browser/resources/md_extensions/detail_view.html
@@ -240,7 +240,8 @@
           <button class="icon-external" is="paper-icon-button-light"></button>
         </div>
       </div>
-      <button is="cr-link-row" hidden="[[isControlled_(data.controlledInfo)]]"
+      <button class="hr" is="cr-link-row"
+          hidden="[[isControlled_(data.controlledInfo)]]"
           icon-class="subpage-arrow" id="remove-extension"
           label="$i18n{itemRemoveExtension}" on-tap="onRemoveTap_">
       </button>
diff --git a/chrome/browser/resources/md_extensions/error_page.html b/chrome/browser/resources/md_extensions/error_page.html
index b3103aaa..07cb1ed 100644
--- a/chrome/browser/resources/md_extensions/error_page.html
+++ b/chrome/browser/resources/md_extensions/error_page.html
@@ -14,22 +14,35 @@
 <dom-module id="extensions-error-page">
   <template>
     <style include="cr-icons cr-hidden-style">
+      :host {
+        display: block;
+        height: 100%;
+        overflow: auto;
+      }
+
       #main {
         background-color: white;
-        height: 800px;
-        width: 90%;
+        display: flex;
+        flex-direction: column;
+        margin: auto;
+        min-height: 100%;
+        width: 640px;
       }
 
       #heading {
-        color: var(--paper-grey-600);
         height: 40px;
         margin-bottom: 30px;
         padding: 8px 12px 0;
+        @apply(--cr-title-text);
       }
 
       #errors-list {
         min-height: 100px;
-        padding: 0 10px;
+        padding: 0 var(--cr-section-padding);
+      }
+
+      #content-view {
+        padding: 0 var(--cr-section-padding);
       }
 
       .error-item {
@@ -39,6 +52,10 @@
         margin: 5px 0;
       }
 
+      .error-item button[is='paper-icon-button-light'] {
+        -webkit-margin-end: 0;
+      }
+
       .error-item.selected {
         background-color: #ccc;
       }
@@ -68,16 +85,18 @@
         </button>
         <span>$i18n{errorsPageHeading}</span>
       </div>
-      <iron-list id="errors-list" items="[[calculateShownItems_(data.*)]]">
+      <iron-list id="errors-list" items="[[calculateShownItems_(data.*)]]"
+          preserve-focus>
         <template>
-          <div class$="[[computeErrorClass_(selectedError_, item)]]"
+          <div class$="error-item [[computeErrorClass_(selectedError_, item)]]"
               error="[[item]]"
               tabindex$="[[tabIndex]]"
-              on-tap="onErrorItemTap_" on-keydown="onErrorItemKeydown_">
+              on-tap="onErrorItemAction_" on-keydown="onErrorItemAction_">
             <img class$="[[computeErrorIconClass_(item)]]">
             <div class="error-message">[[item.message]]</div>
             <button is="paper-icon-button-light" class="icon-delete-gray"
-                on-tap="onDeleteErrorTap_" tabindex$="[[tabIndex]]"></button>
+                on-tap="onDeleteErrorAction_" tabindex$="[[tabIndex]]"
+                on-keydown="onDeleteErrorAction_"></button>
           </div>
         </template>
       </iron-list>
diff --git a/chrome/browser/resources/md_extensions/error_page.js b/chrome/browser/resources/md_extensions/error_page.js
index 01bcf79..de481b6 100644
--- a/chrome/browser/resources/md_extensions/error_page.js
+++ b/chrome/browser/resources/md_extensions/error_page.js
@@ -64,6 +64,8 @@
      * @private
      */
     calculateShownItems_: function() {
+      // Render iron-list correctly after data changes.
+      setTimeout(() => this.$['errors-list'].fire('iron-resize'));
       return this.data.manifestErrors.concat(this.data.runtimeErrors);
     },
 
@@ -98,14 +100,16 @@
     },
 
     /**
-     * @param {!Event} event
+     * @param {!Event} e
      * @private
      */
-    onDeleteErrorTap_: function(event) {
-      // TODO(devlin): It would be cleaner if we could cast this to a
-      // PolymerDomRepeatEvent-type thing, but that doesn't exist yet.
-      const e = /** @type {!{model:Object}} */ (event);
-      this.delegate.deleteErrors(this.data.id, [e.model.item.id]);
+    onDeleteErrorAction_: function(e) {
+      if (e.type == 'keydown' && !((e.code == 'Space' || e.code == 'Enter')))
+        return;
+
+      this.delegate.deleteErrors(
+          this.data.id, [(/** @type {!{model:Object}} */ (e)).model.item.id]);
+      e.stopPropagation();
     },
 
     /**
@@ -146,7 +150,7 @@
      * @private
      */
     computeErrorClass_: function(selectedError, error) {
-      return selectedError == error ? 'error-item selected' : 'error-item';
+      return selectedError == error ? 'selected' : '';
     },
 
     /**
@@ -162,17 +166,11 @@
      * @param {!{model: !{item: (!RuntimeError|!ManifestError)}}} e
      * @private
      */
-    onErrorItemTap_: function(e) {
-      this.selectError_(e.model.item);
-    },
+    onErrorItemAction_: function(e) {
+      if (e.type == 'keydown' && !((e.code == 'Space' || e.code == 'Enter')))
+        return;
 
-    /**
-     * @param {!{model: !{item: (!RuntimeError|!ManifestError)}}} e
-     * @private
-     */
-    onErrorItemKeydown_: function(e) {
-      if (e.key == ' ' || e.key == 'Enter')
-        this.selectError_(e.model.item);
+      this.selectError_(e.model.item);
     },
   });
 
diff --git a/chrome/browser/resources/md_extensions/item.js b/chrome/browser/resources/md_extensions/item.js
index eb7c4c4..395361c 100644
--- a/chrome/browser/resources/md_extensions/item.js
+++ b/chrome/browser/resources/md_extensions/item.js
@@ -282,11 +282,11 @@
      */
     computeDevReloadButtonHidden_: function() {
       // Only display the reload spinner if the extension is unpacked and
-      // not terminated (since if it's terminated, we'll show a crashed reload
-      // buton).
+      // enabled. There's no point in reloading a disabled extension, and we'll
+      // show a crashed reload buton if it's terminated.
       const showIcon =
           this.data.location == chrome.developerPrivate.Location.UNPACKED &&
-          this.data.state != chrome.developerPrivate.ExtensionState.TERMINATED;
+          this.data.state == chrome.developerPrivate.ExtensionState.ENABLED;
       return !showIcon;
     },
 
diff --git a/chrome/browser/resources/md_extensions/kiosk_browser_proxy.html b/chrome/browser/resources/md_extensions/kiosk_browser_proxy.html
new file mode 100644
index 0000000..58f9bb8f
--- /dev/null
+++ b/chrome/browser/resources/md_extensions/kiosk_browser_proxy.html
@@ -0,0 +1,2 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<script src="kiosk_browser_proxy.js"></script>
diff --git a/chrome/browser/resources/md_extensions/kiosk_browser_proxy.js b/chrome/browser/resources/md_extensions/kiosk_browser_proxy.js
new file mode 100644
index 0000000..91e7a70d
--- /dev/null
+++ b/chrome/browser/resources/md_extensions/kiosk_browser_proxy.js
@@ -0,0 +1,108 @@
+// 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 A helper object used from the "Kiosk" dialog to interact with
+ * the browser.
+ */
+
+/**
+ * @typedef {{
+ *   kioskEnabled: boolean,
+ *   autoLaunchEnabled: boolean
+ * }}
+ */
+let KioskSettings;
+
+/**
+ * @typedef {{
+ *   id: string,
+ *   name: string,
+ *   iconURL: string,
+ *   autoLaunch: boolean,
+ *   isLoading: boolean
+ * }}
+ */
+let KioskApp;
+
+/**
+ * @typedef {{
+ *   apps: !Array<!KioskApp>,
+ *   disableBailout: boolean,
+ *   hasAutoLaunchApp: boolean
+ * }}
+ */
+let KioskAppSettings;
+
+cr.define('extensions', function() {
+
+  /** @interface */
+  class KioskBrowserProxy {
+    /** @param {string} appId */
+    addKioskApp(appId) {}
+
+    /** @param {string} appId */
+    disableKioskAutoLaunch(appId) {}
+
+    /** @param {string} appId */
+    enableKioskAutoLaunch(appId) {}
+
+    /** @return {!Promise<!KioskAppSettings>} */
+    getKioskAppSettings() {}
+
+    /** @return {!Promise<!KioskSettings>} */
+    initializeKioskAppSettings() {}
+
+    /** @param {string} appId */
+    removeKioskApp(appId) {}
+
+    /** @param {boolean} disableBailout */
+    setDisableBailoutShortcut(disableBailout) {}
+  }
+
+  /** @implements {extensions.KioskBrowserProxy} */
+  class KioskBrowserProxyImpl {
+    /** @override */
+    initializeKioskAppSettings() {
+      return cr.sendWithPromise('initializeKioskAppSettings');
+    }
+
+    /** @override */
+    getKioskAppSettings() {
+      return cr.sendWithPromise('getKioskAppSettings');
+    }
+
+    /** @override */
+    addKioskApp(appId) {
+      chrome.send('addKioskApp', [appId]);
+    }
+
+    /** @override */
+    disableKioskAutoLaunch(appId) {
+      chrome.send('disableKioskAutoLaunch', [appId]);
+    }
+
+    /** @override */
+    enableKioskAutoLaunch(appId) {
+      chrome.send('enableKioskAutoLaunch', [appId]);
+    }
+
+    /** @override */
+    removeKioskApp(appId) {
+      chrome.send('removeKioskApp', [appId]);
+    }
+
+    /** @override */
+    setDisableBailoutShortcut(disableBailout) {
+      chrome.send('setDisableBailoutShortcut', [disableBailout]);
+    }
+  }
+
+  cr.addSingletonGetter(KioskBrowserProxyImpl);
+
+  return {
+    KioskBrowserProxy: KioskBrowserProxy,
+    KioskBrowserProxyImpl: KioskBrowserProxyImpl,
+  };
+});
diff --git a/chrome/browser/resources/md_extensions/kiosk_dialog.html b/chrome/browser/resources/md_extensions/kiosk_dialog.html
new file mode 100644
index 0000000..97a42300
--- /dev/null
+++ b/chrome/browser/resources/md_extensions/kiosk_dialog.html
@@ -0,0 +1,144 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html">
+<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
+<link rel="import" href="chrome://resources/html/assert.html">
+<link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="chrome://resources/html/util.html">
+<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
+<link rel="import" href="kiosk_browser_proxy.html">
+
+<dom-module id="extensions-kiosk-dialog">
+  <template>
+    <style include="cr-shared-style paper-button-style cr-icons">
+      #add-kiosk-app {
+        --paper-input-container-input: {
+          font-size: inherit;
+        };
+        align-items: center;
+        display: flex;
+        margin-bottom: 10px;
+        margin-top: 20px;
+        width: 350px;
+      }
+
+      #add-kiosk-app paper-input {
+        flex: 1;
+      }
+
+      #add-kiosk-app paper-button {
+        -webkit-margin-start: 10px;
+      }
+
+      paper-button {
+        color: var(--google-blue-500);
+      }
+
+      #kiosk-apps-list {
+        border: 1px solid var(--paper-grey-300);
+        padding: 10px;
+      }
+
+      .list-item {
+        align-items: center;
+        border-bottom: 1px solid var(--paper-grey-300);
+        display: flex;
+        justify-content: space-between;
+        padding: 5px;
+      }
+
+      .list-item:last-of-type {
+        border-bottom: none;
+      }
+
+      .list-item:hover {
+        background-color: var(--paper-grey-300);
+      }
+
+      .item-icon {
+        vertical-align: middle;
+        width: 25px;
+      }
+
+      .item-controls {
+        visibility: hidden;
+      }
+
+      .list-item:hover .item-controls {
+        visibility: visible;
+      }
+    </style>
+    <dialog is="cr-dialog" id="dialog" close-text="$i18n{close}"
+        ignore-enter-key>
+      <div slot="title">$i18n{manageKioskApp}</div>
+      <div slot="body">
+        <div id="kiosk-apps-list">
+          <template is="dom-repeat" items="[[apps_]]">
+            <div class="list-item">
+              <div class="item-name">
+                <img class="item-icon" src="[[item.iconURL]]">
+                [[item.name]]
+                <span hidden="[[!item.autoLaunch]]">
+                  $i18n{kioskAutoLaunch}
+                </span>
+              </div>
+              <div class="item-controls">
+                <paper-button hidden="[[!canEditAutoLaunch_]]"
+                    on-tap="onAutoLaunchButtonTap_">
+                  [[getAutoLaunchButtonLabel_(item.autoLaunch,
+                      '$i18nPolymer{kioskDisableAutoLaunch}',
+                      '$i18nPolymer{kioskEnableAutoLaunch}')]]
+                </paper-button>
+                <button is="paper-icon-button-light" class="icon-delete-gray"
+                    on-tap="onDeleteAppTap_"></button>
+              </div>
+            </div>
+          </template>
+        </div>
+        <div id="add-kiosk-app">
+          <paper-input id="add-input" label="$i18n{kioskAddApp}"
+              placeholder="$i18n{kioskAddAppHint}" value="{{addAppInput_}}"
+              always-float-label invalid="[[errorAppId_]]"
+              error-message="[[getErrorMessage_(
+                  '$i18nPolymer{kioskInvalidApp}', errorAppId_)]]"
+              on-keydown="clearInputInvalid_">
+          </paper-input>
+          <paper-button id="add-button" on-tap="onAddAppTap_"
+              disabled="[[!addAppInput_]]">
+            $i18n{add}
+          </paper-button>
+        </div>
+        <paper-checkbox disabled="[[!canEditBailout_]]"
+            on-pointerdown="onBailoutTap_" checked="[[bailoutDisabled_]]"
+            hidden="[[!canEditAutoLaunch_]]">
+          $i18n{kioskDisableBailout}
+        </paper-checkbox>
+      </div>
+      <div slot="button-container">
+        <paper-button class="action-button" on-tap="onDoneTap_">
+          $i18n{done}
+        </paper-button>
+      </div>
+    </dialog>
+    <dialog is="cr-dialog" id="confirm-dialog" close-text="$i18n{close}"
+        ignore-enter-key on-close="stopPropagation_">
+      <div slot="title">$i18n{kioskDisableBailoutWarningTitle}</div>
+      <div slot="body">$i18n{kioskDisableBailoutWarningBody}</div>
+      <div slot="button-container">
+        <paper-button class="cancel-button" on-tap="onBailoutDialogCancelTap_">
+          $i18n{cancel}
+        </paper-button>
+        <paper-button class="action-button" on-tap="onBailoutDialogConfirmTap_">
+          $i18n{confirm}
+        </paper-button>
+      </div>
+    </dialog>
+  </template>
+  <script src="chrome://extensions/kiosk_dialog.js"></script>
+</dom-module>
diff --git a/chrome/browser/resources/md_extensions/kiosk_dialog.js b/chrome/browser/resources/md_extensions/kiosk_dialog.js
new file mode 100644
index 0000000..254c2c1
--- /dev/null
+++ b/chrome/browser/resources/md_extensions/kiosk_dialog.js
@@ -0,0 +1,185 @@
+// 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.
+
+cr.define('extensions', function() {
+  'use strict';
+
+  const KioskDialog = Polymer({
+    is: 'extensions-kiosk-dialog',
+    behaviors: [WebUIListenerBehavior],
+    properties: {
+      /** @private {?string} */
+      addAppInput_: {
+        type: String,
+        value: null,
+      },
+
+      /** @private {!Array<!KioskApp>} */
+      apps_: Array,
+
+      /** @private */
+      bailoutDisabled_: Boolean,
+
+      /** @private */
+      canEditAutoLaunch_: Boolean,
+
+      /** @private */
+      canEditBailout_: Boolean,
+
+      /** @private {?string} */
+      errorAppId_: String,
+    },
+
+    /** @private {?extensions.KioskBrowserProxy} */
+    kioskBrowserProxy_: null,
+
+    /** @override */
+    ready: function() {
+      this.kioskBrowserProxy_ = extensions.KioskBrowserProxyImpl.getInstance();
+    },
+
+    /** @override */
+    attached: function() {
+      this.kioskBrowserProxy_.initializeKioskAppSettings()
+          .then(params => {
+            this.canEditAutoLaunch_ = params.autoLaunchEnabled;
+            return this.kioskBrowserProxy_.getKioskAppSettings();
+          })
+          .then(this.setSettings_.bind(this));
+
+      this.addWebUIListener(
+          'kiosk-app-settings-changed', this.setSettings_.bind(this));
+      this.addWebUIListener('kiosk-app-updated', this.updateApp_.bind(this));
+      this.addWebUIListener('kiosk-app-error', this.showError_.bind(this));
+
+      this.$.dialog.showModal();
+    },
+
+    /**
+     * @param {!KioskAppSettings} settings
+     * @private
+     */
+    setSettings_: function(settings) {
+      this.apps_ = settings.apps;
+      this.bailoutDisabled_ = settings.disableBailout;
+      this.canEditBailout_ = settings.hasAutoLaunchApp;
+    },
+
+    /**
+     * @param {!KioskApp} app
+     * @private
+     */
+    updateApp_: function(app) {
+      const index = this.apps_.findIndex(a => a.id == app.id);
+      assert(index < this.apps_.length);
+      this.set('apps_.' + index, app);
+    },
+
+    /**
+     * @param {string} appId
+     * @private
+     */
+    showError_: function(appId) {
+      this.errorAppId_ = appId;
+    },
+
+    /**
+     * @param {string} errorMessage
+     * @return {string}
+     * @private
+     */
+    getErrorMessage_: function(errorMessage) {
+      return this.errorAppId_ + ' ' + errorMessage;
+    },
+
+    /** @private */
+    onAddAppTap_: function() {
+      assert(this.addAppInput_);
+      this.kioskBrowserProxy_.addKioskApp(this.addAppInput_);
+      this.addAppInput_ = null;
+    },
+
+    /** @private */
+    clearInputInvalid_: function() {
+      this.errorAppId_ = null;
+    },
+
+    /**
+     * @param {{model: {item: !KioskApp}}} event
+     * @private
+     */
+    onAutoLaunchButtonTap_: function(event) {
+      const app = event.model.item;
+      if (app.autoLaunch) {  // If the app is originally set to
+                             // auto-launch.
+        this.kioskBrowserProxy_.disableKioskAutoLaunch(app.id);
+      } else {
+        this.kioskBrowserProxy_.enableKioskAutoLaunch(app.id);
+      }
+    },
+
+    /**
+     * @param {!Event} event
+     * @private
+     */
+    onBailoutTap_: function(event) {
+      event.preventDefault();
+      if (this.bailoutDisabled_) {
+        this.kioskBrowserProxy_.setDisableBailoutShortcut(false);
+        this.bailoutDisabled_ = false;
+        this.$['confirm-dialog'].close();
+      } else {
+        this.$['confirm-dialog'].showModal();
+      }
+    },
+
+    /** @private */
+    onBailoutDialogCancelTap_: function() {
+      this.$['confirm-dialog'].cancel();
+    },
+
+    /** @private */
+    onBailoutDialogConfirmTap_: function() {
+      this.kioskBrowserProxy_.setDisableBailoutShortcut(true);
+      this.bailoutDisabled_ = true;
+      this.$['confirm-dialog'].close();
+    },
+
+    /** @private */
+    onDoneTap_: function() {
+      this.$.dialog.close();
+    },
+
+    /**
+     * @param {{model: {item: !KioskApp}}} event
+     * @private
+     */
+    onDeleteAppTap_: function(event) {
+      this.kioskBrowserProxy_.removeKioskApp(event.model.item.id);
+    },
+
+    /**
+     * @param {boolean} autoLaunched
+     * @param {string} disableStr
+     * @param {string} enableStr
+     * @return {string}
+     * @private
+     */
+    getAutoLaunchButtonLabel_: function(autoLaunched, disableStr, enableStr) {
+      return autoLaunched ? disableStr : enableStr;
+    },
+
+    /**
+     * @param {!Event} e
+     * @private
+     */
+    stopPropagation_: function(e) {
+      e.stopPropagation();
+    },
+  });
+
+  return {
+    KioskDialog: KioskDialog,
+  };
+});
diff --git a/chrome/browser/resources/md_extensions/manager.html b/chrome/browser/resources/md_extensions/manager.html
index af51391f..79f26db 100644
--- a/chrome/browser/resources/md_extensions/manager.html
+++ b/chrome/browser/resources/md_extensions/manager.html
@@ -24,6 +24,11 @@
 <link rel="import" href="chrome://extensions/view_manager.html">
 <link rel="stylesheet" href="chrome://resources/css/md_colors.css">
 
+<if expr="chromeos">
+<link rel="import" href="chrome://extensions/kiosk_browser_proxy.html">
+<link rel="import" href="chrome://extensions/kiosk_dialog.html">
+</if>
+
 <dom-module id="extensions-manager">
   <template>
     <style include="cr-shared-style">
@@ -60,9 +65,15 @@
     <extensions-toolbar in-dev-mode="[[inDevMode]]"
         on-pack-tap="onPackTap_" delegate="[[delegate]]"
         on-cr-toolbar-menu-tap="onMenuButtonTap_"
-        on-search-changed="onFilterChanged_">
+        on-search-changed="onFilterChanged_"
+<if expr="chromeos">
+        on-kiosk-tap="onKioskTap_"
+        kiosk-enabled="[[kioskEnabled_]]"
+</if>
+        >
     </extensions-toolbar>
-    <dialog id="drawer" is="cr-drawer" align="$i18n{textdirection}">
+    <dialog id="drawer" is="cr-drawer" heading="$i18n{toolbarTitle}"
+        align="$i18n{textdirection}">
       <div class="drawer-content">
         <extensions-sidebar id="sidebar"></extensions-sidebar>
       </div>
@@ -91,6 +102,13 @@
       </extensions-pack-dialog>
       <extensions-load-error id="load-error" delegate="[[delegate]]">
       </extensions-load-error>
+<if expr="chromeos">
+      <template is="dom-if" if="[[showKioskDialog_]]" restamp>
+        <extensions-kiosk-dialog id="kiosk-dialog"
+            on-close="onKioskDialogClose_">
+        </extensions-kiosk-dialog>
+      </template>
+</if>
     </div>
   </template>
   <script src="chrome://extensions/manager.js"></script>
diff --git a/chrome/browser/resources/md_extensions/manager.js b/chrome/browser/resources/md_extensions/manager.js
index dc065446..56e77d3 100644
--- a/chrome/browser/resources/md_extensions/manager.js
+++ b/chrome/browser/resources/md_extensions/manager.js
@@ -101,6 +101,20 @@
         type: Boolean,
         value: false,
       },
+
+      // <if expr="chromeos">
+      /** @private */
+      kioskEnabled_: {
+        type: Boolean,
+        value: false,
+      },
+
+      /** @private */
+      showKioskDialog_: {
+        type: Boolean,
+        value: false,
+      },
+      // </if>
     },
 
     /**
@@ -110,10 +124,12 @@
      */
     currentPage_: null,
 
+    /** @override */
     created: function() {
       this.readyPromiseResolver = new PromiseResolver();
     },
 
+    /** @override */
     ready: function() {
       this.toolbar =
           /** @type {extensions.Toolbar} */ (this.$$('extensions-toolbar'));
@@ -121,6 +137,14 @@
       extensions.navigation.onRouteChanged(newPage => {
         this.changePage_(newPage);
       });
+
+      // <if expr="chromeos">
+      extensions.KioskBrowserProxyImpl.getInstance()
+          .initializeKioskAppSettings()
+          .then(params => {
+            this.kioskEnabled_ = params.kioskEnabled;
+          });
+      // </if>
     },
 
     get keyboardShortcuts() {
@@ -336,6 +360,17 @@
       this.$['pack-dialog'].show();
     },
 
+    // <if expr="chromeos">
+    /** @private */
+    onKioskTap_: function() {
+      this.showKioskDialog_ = true;
+    },
+
+    onKioskDialogClose_: function() {
+      this.showKioskDialog_ = false;
+    },
+    // </if>
+
     /**
      * @param {!extensions.ShowingType} listType
      * @private
diff --git a/chrome/browser/resources/md_extensions/toolbar.html b/chrome/browser/resources/md_extensions/toolbar.html
index 585dada2..7a81383c2 100644
--- a/chrome/browser/resources/md_extensions/toolbar.html
+++ b/chrome/browser/resources/md_extensions/toolbar.html
@@ -84,6 +84,12 @@
         <paper-button id="update-now" on-tap="onUpdateNowTap_">
           $i18n{toolbarUpdateNow}
         </paper-button>
+<if expr="chromeos">
+        <paper-button id="kiosk-extensions" on-tap="onKioskTap_"
+            hidden$="[[!kioskEnabled]]">
+          $i18n{manageKioskApp}
+        </paper-button>
+</if>
       </div>
     </div>
   </template>
diff --git a/chrome/browser/resources/md_extensions/toolbar.js b/chrome/browser/resources/md_extensions/toolbar.js
index f7e5051..3bd0fc6 100644
--- a/chrome/browser/resources/md_extensions/toolbar.js
+++ b/chrome/browser/resources/md_extensions/toolbar.js
@@ -35,6 +35,10 @@
         type: Boolean,
         value: false,
       },
+
+      // <if expr="chromeos">
+      kioskEnabled: Boolean,
+      // </if>
     },
 
     /** @private */
@@ -52,6 +56,13 @@
       this.fire('pack-tap');
     },
 
+    // <if expr="chromeos">
+    /** @private */
+    onKioskTap_: function() {
+      this.fire('kiosk-tap');
+    },
+    // </if>
+
     /** @private */
     onUpdateNowTap_: function() {
       this.delegate.updateAllExtensions();
diff --git a/chrome/browser/resources/print_preview/data/app_state.js b/chrome/browser/resources/print_preview/data/app_state.js
index 0654144..489fda6 100644
--- a/chrome/browser/resources/print_preview/data/app_state.js
+++ b/chrome/browser/resources/print_preview/data/app_state.js
@@ -40,7 +40,7 @@
 
   /**
    * Origin of the RecentDestination.
-   * @type {string}
+   * @type {!print_preview.DestinationOrigin}
    */
   this.origin = destination.origin;
 
diff --git a/chrome/browser/resources/print_preview/data/destination_match.js b/chrome/browser/resources/print_preview/data/destination_match.js
index 3152abe..43e77b5 100644
--- a/chrome/browser/resources/print_preview/data/destination_match.js
+++ b/chrome/browser/resources/print_preview/data/destination_match.js
@@ -4,6 +4,24 @@
 
 cr.define('print_preview', function() {
   'use strict';
+  /**
+   * Converts DestinationOrigin to PrinterType.
+   * @param {!print_preview.DestinationOrigin} origin The printer's
+   *     destination origin.
+   * return {?print_preview.PrinterType} The corresponding PrinterType.
+   *     Returns null if no match is found.
+   */
+  var originToType = function(origin) {
+    if (origin === print_preview.DestinationOrigin.LOCAL ||
+        origin === print_preview.DestinationOrigin.CROS) {
+      return print_preview.PrinterType.LOCAL_PRINTER;
+    }
+    if (origin === print_preview.DestinationOrigin.PRIVET)
+      return print_preview.PrinterType.PRIVET_PRINTER;
+    if (origin === print_preview.DestinationOrigin.EXTENSION)
+      return print_preview.PrinterType.EXTENSION_PRINTER;
+    return null;
+  };
 
   /**
    * A set of key parameters describing a destination used to determine
@@ -88,9 +106,17 @@
       }
       return arrayContains(
           [print_preview.Destination.GooglePromotedId.DOCS], destination.id);
+    },
+
+    /**
+     * @return {?print_preview.PrinterType} The printer type of this
+     *     destination match. Will return null for Cloud destinations.
+     */
+    getType: function() {
+      return originToType(this.origins_[0]);
     }
   };
 
   // Export
-  return {DestinationMatch: DestinationMatch};
+  return {originToType: originToType, DestinationMatch: DestinationMatch};
 });
diff --git a/chrome/browser/resources/print_preview/data/destination_store.js b/chrome/browser/resources/print_preview/data/destination_store.js
index 92b44a3f..d136120d 100644
--- a/chrome/browser/resources/print_preview/data/destination_store.js
+++ b/chrome/browser/resources/print_preview/data/destination_store.js
@@ -645,7 +645,7 @@
     /**
      * Attempts to fetch capabilities of the destination identified by the
      * provided origin, id and account.
-     * @param {string | print_preview.DestinationOrigin} origin Destination
+     * @param {print_preview.DestinationOrigin} origin Destination
      *     origin.
      * @param {string} id Destination id.
      * @param {string} account User account destination is registered for.
@@ -663,39 +663,41 @@
       this.autoSelectMatchingDestination_ =
           this.createExactDestinationMatch_(origin, id);
 
-      if (origin == print_preview.DestinationOrigin.LOCAL ||
-          origin == print_preview.DestinationOrigin.CROS) {
-        this.nativeLayer_.getPrinterCapabilities(id).then(
-            this.onLocalDestinationCapabilitiesSet_.bind(this),
-            this.onGetCapabilitiesFail_.bind(
-                this,
-                /** @type {print_preview.DestinationOrigin} */ (origin), id));
+      var type = print_preview.originToType(origin);
+      if (type == print_preview.PrinterType.LOCAL_PRINTER) {
+        this.nativeLayer_.getPrinterCapabilities(id, type).then(
+            this.onCapabilitiesSet_.bind(this, origin, id),
+            this.onGetCapabilitiesFail_.bind(this, origin, id));
         return true;
       }
 
       if (this.cloudPrintInterface_ &&
           (origin == print_preview.DestinationOrigin.COOKIES ||
            origin == print_preview.DestinationOrigin.DEVICE)) {
-        this.cloudPrintInterface_.printer(
-            id,
-            /** @type {print_preview.DestinationOrigin} */ (origin), account);
+        this.cloudPrintInterface_.printer(id, origin, account);
         return true;
       }
 
-      if (origin == print_preview.DestinationOrigin.PRIVET) {
+      if (origin == print_preview.DestinationOrigin.PRIVET ||
+          origin == print_preview.DestinationOrigin.EXTENSION) {
         // TODO(noamsml): Resolve a specific printer instead of listing all
-        // privet printers in this case
-        var privetType = print_preview.PrinterType.PRIVET_PRINTER;
-        this.nativeLayer_.getPrinters(privetType)
-            .then(this.onDestinationSearchDone_.bind(this, privetType));
+        // privet or extension printers in this case.
+        this.startLoadDestinations(type);
 
         // Create a fake selectedDestination_ that is not actually in the
         // destination store. When the real destination is created, this
         // destination will be overwritten.
+        var params =
+            (origin === print_preview.DestinationOrigin.PRIVET) ? {} : {
+              description: '',
+              extensionId: extensionId,
+              extensionName: extensionName,
+              provisionalType: print_preview.DestinationProvisionalType.NONE
+            };
         this.selectedDestination_ = new print_preview.Destination(
-            id, print_preview.DestinationType.LOCAL,
-            print_preview.DestinationOrigin.PRIVET, name, false /*isRecent*/,
-            print_preview.DestinationConnectionStatus.ONLINE);
+            id, print_preview.DestinationType.LOCAL, origin, name,
+            false /*isRecent*/,
+            print_preview.DestinationConnectionStatus.ONLINE, params);
 
         if (capabilities) {
           this.selectedDestination_.capabilities = capabilities;
@@ -707,30 +709,6 @@
         }
         return true;
       }
-
-      if (origin == print_preview.DestinationOrigin.EXTENSION) {
-        // TODO(tbarzic): Add support for requesting a single extension's
-        // printer list.
-        this.startLoadDestinations(print_preview.PrinterType.EXTENSION_PRINTER);
-
-        this.selectedDestination_ = print_preview.parseExtensionDestination({
-          extensionId: extensionId,
-          extensionName: extensionName,
-          id: id,
-          name: name
-        });
-
-        if (capabilities) {
-          this.selectedDestination_.capabilities = capabilities;
-
-          cr.dispatchSimpleEvent(
-              this,
-              DestinationStore.EventType
-                  .CACHED_SELECTED_DESTINATION_INFO_READY);
-        }
-        return true;
-      }
-
       return false;
     },
 
@@ -741,16 +719,9 @@
      */
     fetchMatchingDestination_: function(destinationMatch) {
       this.autoSelectMatchingDestination_ = destinationMatch;
-
-      if (destinationMatch.matchOrigin(print_preview.DestinationOrigin.LOCAL) ||
-          destinationMatch.matchOrigin(print_preview.DestinationOrigin.CROS)) {
-        this.startLoadDestinations(print_preview.PrinterType.LOCAL_PRINTER);
-      } else if (destinationMatch.matchOrigin(
-                     print_preview.DestinationOrigin.PRIVET)) {
-        this.startLoadDestinations(print_preview.PrinterType.PRIVET_PRINTER);
-      } else if (destinationMatch.matchOrigin(
-                     print_preview.DestinationOrigin.EXTENSION)) {
-        this.startLoadDestinations(print_preview.PrinterType.EXTENSION_PRINTER);
+      var type = destinationMatch.getType();
+      if (type != null) {  // Local, Privet, or Extension.
+        this.startLoadDestinations(type);
       } else if (
           destinationMatch.matchOrigin(
               print_preview.DestinationOrigin.COOKIES) ||
@@ -932,24 +903,14 @@
       // Request destination capabilities from backend, since they are not
       // known yet.
       if (destination.capabilities == null) {
-        if (destination.isPrivet) {
-          this.nativeLayer_.getPrivetPrinterCapabilities(destination.id)
+        var type = print_preview.originToType(destination.origin);
+        if (type !== null) {
+          this.nativeLayer_.getPrinterCapabilities(destination.id, type)
               .then(
-                  this.onPrivetCapabilitiesSet_.bind(this),
-                  this.onGetCapabilitiesFail_.bind(
-                      this, destination.origin, destination.id));
-        } else if (destination.isExtension) {
-          this.nativeLayer_.getExtensionPrinterCapabilities(destination.id)
-              .then(
-                  this.onExtensionCapabilitiesSet_.bind(this, destination.id),
-                  this.onGetCapabilitiesFail_.bind(
-                      this, destination.origin, destination.id));
-        } else if (destination.isLocal) {
-          this.nativeLayer_.getPrinterCapabilities(destination.id)
-              .then(
-                  this.onLocalDestinationCapabilitiesSet_.bind(this),
-                  this.onGetCapabilitiesFail_.bind(
-                      this, destination.origin, destination.id));
+                  (caps) => this.onCapabilitiesSet_(
+                      destination.origin, destination.id, caps),
+                  () => this.onGetCapabilitiesFail_(
+                      destination.origin, destination.origin));
         } else {
           assert(
               this.cloudPrintInterface_ != null,
@@ -1224,8 +1185,11 @@
       assert(destination.constructor !== Array, 'Single printer expected');
       destination.capabilities_ = DestinationStore.localizeCapabilities_(
           assert(destination.capabilities_));
-      destination.capabilities_ =
-          DestinationStore.sortMediaSizes_(destination.capabilities_);
+      if (print_preview.originToType(destination.origin) !==
+          print_preview.PrinterType.LOCAL_PRINTER) {
+        destination.capabilities_ =
+            DestinationStore.sortMediaSizes_(destination.capabilities_);
+      }
       var existingDestination = this.destinationMap_[this.getKey_(destination)];
       if (existingDestination != null) {
         existingDestination.capabilities = destination.capabilities;
@@ -1349,56 +1313,39 @@
      * local destination. Updates the destination with new capabilities if the
      * destination already exists, otherwise it creates a new destination and
      * then updates its capabilities.
-     * @param {print_preview.PrinterCapabilitiesResponse} settingsInfo Contains
-     *     information about and capabilities of the local print destination.
+     * @param {!print_preview.DestinationOrigin} origin The origin of the
+     *     print destination.
+     * @param {string} id The id of the print destination.
+     * @param {!print_preview.CapabilitiesResponse} settingsInfo Contains
+     *     the capabilities of the print destination, and information about
+     *     the destination except in the case of extension printers.
      * @private
      */
-    onLocalDestinationCapabilitiesSet_: function(settingsInfo) {
-      var destinationId = settingsInfo['printerId'];
-      var printerName = settingsInfo['printerName'];
-      var printerDescription = settingsInfo['printerDescription'];
-      // PDF is special since we don't need to query the device for
-      // capabilities.
-      var origin = destinationId ==
-              print_preview.Destination.GooglePromotedId.SAVE_AS_PDF ?
-          print_preview.DestinationOrigin.LOCAL :
-          this.platformOrigin_;
-      var key = this.getDestinationKey_(origin, destinationId, '');
-      var destination = this.destinationMap_[key];
-      var capabilities =
-          DestinationStore.localizeCapabilities_(settingsInfo.capabilities);
-      // Special case for PDF printer (until local printers capabilities are
-      // reported in CDD format too).
-      if (destinationId ==
-          print_preview.Destination.GooglePromotedId.SAVE_AS_PDF) {
-        if (destination) {
-          destination.capabilities = capabilities;
-        }
-      } else {
-        if (destination) {
-          // In case there were multiple capabilities request for this local
-          // destination, just ignore the later ones.
-          if (destination.capabilities != null) {
-            return;
-          }
-          destination.capabilities = capabilities;
-        } else {
-          var isEnterprisePrinter = settingsInfo['cupsEnterprisePrinter'];
-          destination = print_preview.parseLocalDestination({
-            deviceName: destinationId,
-            printerName: printerName,
-            cupsEnterprisePrinter: isEnterprisePrinter,
-            printerDescription: printerDescription
-          });
-          destination.capabilities = capabilities;
-          this.insertDestination_(destination);
-        }
+    onCapabilitiesSet_: function(origin, id, settingsInfo) {
+      var dest = null;
+      if (origin !== print_preview.DestinationOrigin.PRIVET) {
+        var key = this.getDestinationKey_(origin, id, '');
+        dest = this.destinationMap_[key];
       }
-      if (this.selectedDestination_ &&
-          this.selectedDestination_.id == destinationId) {
-        cr.dispatchSimpleEvent(
-            this,
-            DestinationStore.EventType.SELECTED_DESTINATION_CAPABILITIES_READY);
+      if (!dest) {
+        // Ignore unrecognized extension printers
+        if (!settingsInfo.printer) {
+          assert(origin === print_preview.DestinationOrigin.EXTENSION);
+          return;
+        }
+        dest = print_preview.parseDestination(
+            print_preview.originToType(origin), assert(settingsInfo.printer));
+      }
+      if (dest) {
+        var updateDestination = destination => {
+          destination.capabilities = settingsInfo.capabilities;
+          this.updateDestination_(destination);
+        };
+        if (Array.isArray(dest)) {
+          dest.forEach(updateDestination);
+        } else {
+          updateDestination(dest);
+        }
       }
     },
 
@@ -1516,44 +1463,6 @@
     },
 
     /**
-     * Called when capabilities for a privet printer are set.
-     * @param {!print_preview.PrivetPrinterCapabilitiesResponse} printerInfo
-     *     Contains the privet printer's description and capabilities.
-     * @private
-     */
-    onPrivetCapabilitiesSet_: function(printerInfo) {
-      var destinations =
-          print_preview.parsePrivetDestination(printerInfo.printer);
-      var updateDestination = dest => {
-        dest.capabilities = printerInfo.capabilities;
-        this.updateDestination_(dest);
-      };
-
-      if (Array.isArray(destinations)) {
-        destinations.forEach(updateDestination);
-      } else {
-        updateDestination(destinations);
-      }
-    },
-
-    /**
-     * Called when capabilities for an extension managed printer are set.
-     * @param {string} printerId The printer Id.
-     * @param {!print_preview.Cdd} capabilities The printer's capabilities.
-     * @private
-     */
-    onExtensionCapabilitiesSet_: function(printerId, capabilities) {
-      var destinationKey = this.getDestinationKey_(
-          print_preview.DestinationOrigin.EXTENSION, printerId,
-          '' /* account */);
-      var destination = this.destinationMap_[destinationKey];
-      if (!destination)
-        return;
-      destination.capabilities = capabilities;
-      this.updateDestination_(destination);
-    },
-
-    /**
      * Called from print preview after the user was requested to sign in, and
      * did so successfully.
      */
diff --git a/chrome/browser/resources/print_preview/data/local_parsers.js b/chrome/browser/resources/print_preview/data/local_parsers.js
index a0257b8..9b09d62 100644
--- a/chrome/browser/resources/print_preview/data/local_parsers.js
+++ b/chrome/browser/resources/print_preview/data/local_parsers.js
@@ -116,8 +116,6 @@
   // Export
   return {
     parseDestination: parseDestination,
-    parseLocalDestination: parseLocalDestination,
-    parsePrivetDestination: parsePrivetDestination,
     parseExtensionDestination: parseExtensionDestination
   };
 });
diff --git a/chrome/browser/resources/print_preview/native_layer.js b/chrome/browser/resources/print_preview/native_layer.js
index 392fea0b..8c80941 100644
--- a/chrome/browser/resources/print_preview/native_layer.js
+++ b/chrome/browser/resources/print_preview/native_layer.js
@@ -28,17 +28,6 @@
 
 /**
  * @typedef {{
- *   printerId: string,
- *   printerName: string,
- *   printerDescription: string,
- *   cupsEnterprisePrinter: (boolean | undefined),
- *   capabilities: !print_preview.Cdd,
- * }}
- */
-print_preview.PrinterCapabilitiesResponse;
-
-/**
- * @typedef {{
  *   serviceName: string,
  *   name: string,
  *   hasLocalPrinting: boolean,
@@ -51,11 +40,13 @@
 
 /**
  * @typedef {{
- *   printer: !print_preview.PrivetPrinterDescription,
+ *   printer:(print_preview.PrivetPrinterDescription |
+ *            print_preview.LocalDestinationInfo |
+ *            undefined),
  *   capabilities: !print_preview.Cdd,
  * }}
  */
-print_preview.PrivetPrinterCapabilitiesResponse;
+print_preview.CapabilitiesResponse;
 
 /**
  * @typedef {{
@@ -174,42 +165,16 @@
      * Requests the destination's printing capabilities. Returns a promise that
      * will be resolved with the capabilities if they are obtained successfully.
      * @param {string} destinationId ID of the destination.
-     * @return {!Promise<!print_preview.PrinterCapabilitiesResponse>}
+     * @param {!print_preview.PrinterType} type The destination's printer type.
+     * @return {!Promise<!print_preview.CapabilitiesResponse>}
      */
-    getPrinterCapabilities(destinationId) {
+    getPrinterCapabilities(destinationId, type) {
       return cr.sendWithPromise(
           'getPrinterCapabilities', destinationId,
           destinationId ==
                   print_preview.Destination.GooglePromotedId.SAVE_AS_PDF ?
               print_preview.PrinterType.PDF_PRINTER :
-              print_preview.PrinterType.LOCAL_PRINTER);
-    }
-
-    /**
-     * Requests the privet destination's printing capabilities. Returns a
-     * promise that will be resolved with capabilities and printer information
-     * if capabilities are obtained successfully.
-     * @param {string} destinationId The ID of the destination
-     * @return {!Promise<!print_preview.PrivetPrinterCapabilitiesResponse>}
-     */
-    getPrivetPrinterCapabilities(destinationId) {
-      return cr.sendWithPromise(
-          'getExtensionOrPrivetPrinterCapabilities', destinationId,
-          print_preview.PrinterType.PRIVET_PRINTER);
-    }
-
-    /**
-     * Requests the extension destination's printing capabilities. Returns a
-     * promise that will be resolved with the capabilities if capabilities are
-     * obtained successfully.
-     * @param {string} destinationId The ID of the destination whose
-     *     capabilities are requested.
-     * @return {!Promise<!print_preview.Cdd>}
-     */
-    getExtensionPrinterCapabilities(destinationId) {
-      return cr.sendWithPromise(
-          'getExtensionOrPrivetPrinterCapabilities', destinationId,
-          print_preview.PrinterType.EXTENSION_PRINTER);
+              type);
     }
 
     /**
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.html b/chrome/browser/resources/settings/appearance_page/appearance_page.html
index 65c619a..7ac58459 100644
--- a/chrome/browser/resources/settings/appearance_page/appearance_page.html
+++ b/chrome/browser/resources/settings/appearance_page/appearance_page.html
@@ -37,51 +37,46 @@
         };
         width: 100%;  /* Pushes policy indicators to end. */
       }
+
+      /* The theme mixes a link and a paper-button divided by a separator with
+       * grit expressions and dom-if templates. That leads to a tricky thing
+       * to style correctly, these are a workaround. */
+      #themeRow paper-button {
+        -webkit-margin-end: 8px;
+      }
+
+      #themeRow .separator {
+         -webkit-margin-start: 0;
+      }
+
+      #useSystem {
+        -webkit-margin-start: calc(var(--cr-button-edge-spacing) * -1);
+      }
     </style>
     <settings-animated-pages id="pages" section="appearance"
         focus-config="[[focusConfig_]]">
       <neon-animatable route-path="default">
 <if expr="chromeos">
-        <div class="settings-box first two-line" id="wallpaperButton"
-            on-tap="openWallpaperManager_" actionable
-            hidden="[[!pageVisibility.setWallpaper]]">
-          <div class="start">
-            $i18n{setWallpaper}
-            <div class="secondary" id="wallpaperSecondary">
-              $i18n{openWallpaperApp}
-            </div>
-          </div>
+        <button icon-class="icon-external" id="wallpaperButton"
+            is="cr-link-row"
+            hidden="[[!pageVisibility.setWallpaper]]"
+            on-tap="openWallpaperManager_"
+            label="$i18n{setWallpaper}" sub-label="$i18n{openWallpaperApp}"
+            disabled="[[isWallpaperPolicyControlled_]]">
           <template is="dom-if" if="[[isWallpaperPolicyControlled_]]">
             <cr-policy-indicator id="wallpaperPolicyIndicator"
                 indicator-type="devicePolicy">
             </cr-policy-indicator>
           </template>
-          <button class="icon-external" id="showWallpaperManager"
-              is="paper-icon-button-light" aria-label="$i18n{setWallpaper}"
-              disabled="[[isWallpaperPolicyControlled_]]"
-              aria-describedby="wallpaperSecondary">
-          </button>
-        </div>
-        <div class="settings-box two-line"
-            hidden="[[!pageVisibility.setTheme]]">
+        </button>
+        <div class="hr"></div>
 </if>
-<if expr="not chromeos">
-        <div class="settings-box two-line first"
+        <div class="settings-row continuation" id="themeRow"
             hidden="[[!pageVisibility.setTheme]]">
-</if>
-          <a class="start two-line inherit-color no-outline" tabindex="-1"
-              target="_blank" href$="[[getThemeHref_(themeUrl_)]]">
-            <div class="flex">
-              $i18n{themes}
-              <div class="secondary" id="themesSecondary">
-                [[themeSublabel_]]
-              </div>
-            </div>
-            <button class="icon-external" is="paper-icon-button-light"
-                actionable aria-label="$i18n{themes}"
-                aria-describedby="themesSecondary">
-            </button>
-          </a>
+          <button class="first" icon-class="icon-external" is="cr-link-row"
+              hidden="[[!pageVisibility.setTheme]]"
+              label="$i18n{themes}" sub-label="[[themeSublabel_]]"
+              on-tap="openThemeUrl_"></button>
 <if expr="not is_linux or chromeos">
           <template is="dom-if" if="[[prefs.extensions.theme.id.value]]">
             <div class="separator"></div>
@@ -92,7 +87,8 @@
           </template>
 </if>
 <if expr="is_linux and not chromeos">
-          <div class="settings-row" hidden="[[!showThemesSecondary_(
+          <div class="settings-row continuation"
+              hidden="[[!showThemesSecondary_(
               prefs.extensions.theme.id.value, useSystemTheme_)]]"
               id="themesSecondaryActions">
             <div class="separator"></div>
@@ -170,7 +166,7 @@
               menu-options="[[fontSizeOptions_]]">
           </settings-dropdown-menu>
         </div>
-        <button is="cr-link-row"
+        <button class="hr" is="cr-link-row"
             icon-class="subpage-arrow" id="customize-fonts-subpage-trigger"
             label="$i18n{customizeFonts}" on-tap="onCustomizeFontsTap_">
         </button>
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.js b/chrome/browser/resources/settings/appearance_page/appearance_page.js
index 29a17fd06..e3c34ea 100644
--- a/chrome/browser/resources/settings/appearance_page/appearance_page.js
+++ b/chrome/browser/resources/settings/appearance_page/appearance_page.js
@@ -197,12 +197,11 @@
   },
 
   /**
-   * URL for either current theme or the theme gallery.
-   * @return {string}
+   * Open URL for either current theme or the theme gallery.
    * @private
    */
-  getThemeHref_: function() {
-    return this.themeUrl_ || loadTimeData.getString('themesGalleryUrl');
+  openThemeUrl_: function() {
+    window.open(this.themeUrl_ || loadTimeData.getString('themesGalleryUrl'));
   },
 
   // <if expr="chromeos">
diff --git a/chrome/browser/resources/settings/device_page/display.html b/chrome/browser/resources/settings/device_page/display.html
index 9dce6b4907..bd93f721 100644
--- a/chrome/browser/resources/settings/device_page/display.html
+++ b/chrome/browser/resources/settings/device_page/display.html
@@ -170,7 +170,7 @@
         </div>
       </template>
 
-      <button is="cr-link-row" icon-class="subpage-arrow" class="indented"
+      <button is="cr-link-row" icon-class="subpage-arrow" class="indented hr"
           id="overscan" label="$i18n{displayOverscanPageTitle}"
           sub-label="$i18n{displayOverscanPageText}" on-tap="onOverscanTap_">
       </button>
diff --git a/chrome/browser/resources/settings/internet_page/internet_config.html b/chrome/browser/resources/settings/internet_page/internet_config.html
index 6f2fcac..2f03b78 100644
--- a/chrome/browser/resources/settings/internet_page/internet_config.html
+++ b/chrome/browser/resources/settings/internet_page/internet_config.html
@@ -28,15 +28,13 @@
         </paper-button>
         <template is="dom-if" if="[[guid_]]">
           <paper-button class="primary-button" on-tap="onSaveTap_"
-              disabled="[[!saveIsEnabled_(propertiesReceived_, propertiesSent_,
-                  configProperties_.*, security_, eapProperties_.*)]]">
+              disabled="[[!saveIsEnabled_(isConfigured_, propertiesReceived_]]">
             $i18n{save}
           </paper-button>
         </template>
         <template is="dom-if" if="[[!guid_]]">
           <paper-button class="primary-button" on-tap="onConnectTap_"
-              disabled="[[!connectIsEnabled_(propertiesSent_,
-                  configProperties_.*, security_, eapProperties_.*)]]">
+              disabled="[[!connectIsEnabled_(isConfigured_, propertiesSent_)]]">
             $i18n{networkButtonConnect}
           </paper-button>
         </template>
@@ -44,7 +42,7 @@
     </div>
 
     <!-- Share (WiFi and WiMAX) -->
-    <template is="dom-if" if="[[shareIsVisible_(configProperties_.Type)]]">
+    <template is="dom-if" if="[[shareIsVisible_(type_)]]">
       <div class="settings-box">
         <div id="shareLabel" class="start">$i18n{networkConfigShare}</div>
         <paper-toggle-button id="share" checked="{{shareNetwork_}}"
@@ -56,26 +54,24 @@
     </template>
 
     <!-- SSID (WiFi) -->
-    <template is="dom-if"
-        if="[[isType_(NetworkType_.WI_FI, configProperties_.Type)]]">
+    <template is="dom-if" if="[[isType_(NetworkType_.WI_FI, type_)]]">
       <network-config-input id="ssid" label="$i18n{OncWiFi-SSID}"
           value="{{configProperties_.WiFi.SSID}}" disabled="[[guid_]]">
       </network-config-input>
     </template>
 
     <!-- Security (WiFi and Ethernet) -->
-    <template is="dom-if" if="[[securityIsVisible_(configProperties_.Type)]]">
+    <template is="dom-if" if="[[securityIsVisible_(type_)]]">
       <network-config-select id="security" label="$i18n{OncWiFi-Security}"
           value="{{security_}}"
-          disabled="[[!securityIsEnabled_(guid_, configProperties_.Type)]]"
-          items="[[getSecurityItems_(configProperties_.Type)]]"
+          disabled="[[!securityIsEnabled_(guid_, type_)]]"
+          items="[[getSecurityItems_(type_)]]"
           onc-prefix="WiFi.Security">
       </network-config-select>
     </template>
 
     <!-- Passphrase (WiFi) -->
-    <template is="dom-if"
-        if="[[configRequiresPassphrase_(configProperties_.Type, security_)]]">
+    <template is="dom-if" if="[[configRequiresPassphrase_(type_, security_)]]">
       <network-config-input label="$i18n{OncWiFi-Passphrase}"
           value="{{configProperties_.WiFi.Passphrase}}">
       </network-config-input>
@@ -93,7 +89,7 @@
           onc-prefix="EAP.Inner" hidden="[[!showEap_.Inner]]">
       </network-config-select>
       <network-config-select id="serverCa" label="$i18n{OncEAP-ServerCA}"
-          value="{{selectedServerCa_}}" items="[[serverCaCerts_]]"
+          value="{{selectedServerCaHash_}}" items="[[serverCaCerts_]]"
           hidden="[[!showEap_.ServerCA]]" cert-list>
       </network-config-select>
       <network-config-input label="$i18n{OncEAP-SubjectMatch}"
@@ -101,7 +97,7 @@
           hidden="[[!showEap_.SubjectMatch]]">
       </network-config-input>
       <network-config-select id="userCert" label="$i18n{OncEAP-UserCert}"
-          value="{{selectedUserCert_}}" items="[[userCerts_]]"
+          value="{{selectedUserCertHash_}}" items="[[userCerts_]]"
           hidden="[[!showEap_.UserCert]]" cert-list>
       </network-config-select>
       <network-config-input label="$i18n{OncEAP-Identity}"
diff --git a/chrome/browser/resources/settings/internet_page/internet_config.js b/chrome/browser/resources/settings/internet_page/internet_config.js
index c1082ad..da0db56 100644
--- a/chrome/browser/resources/settings/internet_page/internet_config.js
+++ b/chrome/browser/resources/settings/internet_page/internet_config.js
@@ -27,6 +27,12 @@
     guid_: String,
 
     /**
+     * The type of network is being configured.
+     * @private {!chrome.networkingPrivate.NetworkType}
+     */
+    type_: String,
+
+    /**
      * The current properties if an existing network being configured.
      * This will be undefined when configuring a new network.
      * @private {!chrome.networkingPrivate.NetworkProperties|undefined}
@@ -70,8 +76,8 @@
       },
     },
 
-    /** @private {!chrome.networkingPrivate.Certificate|undefined} */
-    selectedServerCa_: Object,
+    /** @private */
+    selectedServerCaHash_: String,
 
     /**
      * Used to populate the 'User certificate' dropdown.
@@ -84,8 +90,8 @@
       },
     },
 
-    /** @private {!chrome.networkingPrivate.Certificate|undefined} */
-    selectedUserCert_: Object,
+    /** @private */
+    selectedUserCertHash_: String,
 
     /**
      * The title to display (network name or type).
@@ -97,6 +103,15 @@
     },
 
     /**
+     * Whether all required properties have been set.
+     * @private
+     */
+    isConfigured_: {
+      type: Boolean,
+      value: false,
+    },
+
+    /**
      * Whether this network should be shared with other users of the device.
      * @private
      */
@@ -198,6 +213,9 @@
     'updateEapOuter_(eapProperties_.Outer)',
     'updateEapCerts_(eapProperties_.*, serverCaCerts_, userCerts_)',
     'updateShowEap_(configProperties_.*, eapProperties_.*, security_)',
+    // Multiple updateIsConfigured observers for different configurations.
+    'updateIsConfigured_(configProperties_.*, security_)',
+    'updateIsConfigured_(configProperties_, eapProperties_.*)',
   ],
 
   /** @const */
@@ -244,12 +262,13 @@
     // configurations until the current properties are loaded.
     var name = queryParams.get('name') || '';
     var typeParam = queryParams.get('type');
-    var type = typeParam ? CrOnc.getValidType(typeParam) : CrOnc.Type.WI_FI;
-    assert(type && type != CrOnc.Type.ALL);
+    this.type_ =
+        (typeParam && CrOnc.getValidType(typeParam)) || CrOnc.Type.WI_FI;
+    assert(this.type_ && this.type_ != CrOnc.Type.ALL);
     this.networkProperties_ = {
       GUID: this.guid_,
       Name: name,
-      Type: type,
+      Type: this.type_,
     };
     if (this.guid_) {
       this.networkingPrivate.getProperties(
@@ -270,7 +289,7 @@
     this.networkingPrivate.getCertificateLists(function(certificateLists) {
       var caCerts =
           [this.getDefaultCert_(this.i18n('networkCAUseDefault'), 'default')];
-      caCerts.concat(certificateLists.serverCaCertificates);
+      caCerts = caCerts.concat(certificateLists.serverCaCertificates);
       caCerts.push(this.getDefaultCert_(
           this.i18n('networkCADoNotCheck'), 'do-not-check'));
       this.set('serverCaCerts_', caCerts);
@@ -368,11 +387,11 @@
             Security: CrOnc.Security.NONE,
           };
         }
-        if (!this.guid_) {
+        this.security_ = configProperties.WiFi.Security || CrOnc.Security.NONE;
+        if (!this.guid_ && this.security_ == CrOnc.Security.NONE) {
           // Insecure WiFi networks are always shared (regardless of policy).
           // TODO(stevenjb): also check login state.
-          if (configProperties.WiFi.Security == CrOnc.Security.NONE)
-            this.shareNetwork_ = true;
+          this.shareNetwork_ = true;
         }
         // updateSecurity_ will ensure that EAP properties are set correctly.
         break;
@@ -386,6 +405,9 @@
           configProperties.Ethernet.EAP.Outer =
               configProperties.Ethernet.EAP.Outer || CrOnc.EAPType.LEAP;
         }
+        this.security_ = configProperties.Ethernet.EAP ?
+            CrOnc.Security.WPA_EAP :
+            CrOnc.Security.NONE;
         break;
       case CrOnc.Type.WI_MAX:
         if (properties.WiMAX) {
@@ -399,33 +421,13 @@
             AutoConnect: false,
           };
         }
+        this.security_ = CrOnc.Security.WPA_EAP;
         break;
     }
     this.configProperties_ = configProperties;
     this.set('eapProperties_', this.getEap_(this.configProperties_));
     if (!this.eapProperties_)
       this.showEap_ = null;
-    this.updateSecurityFromProperties_();
-  },
-
-  /** @private */
-  updateSecurityFromProperties_: function() {
-    var configProperties = this.configProperties_;
-    switch (configProperties.Type) {
-      case CrOnc.Type.ETHERNET:
-        this.security_ = configProperties.Ethernet.EAP ?
-            CrOnc.Security.WPA_EAP :
-            CrOnc.Security.NONE;
-        break;
-      case CrOnc.Type.WI_MAX:
-        this.security_ = CrOnc.Security.WPA_EAP;
-        break;
-      case CrOnc.Type.WI_FI:
-        this.security_ =
-            (configProperties.WiFi && configProperties.WiFi.Security) ||
-            CrOnc.Security.NONE;
-        break;
-    }
   },
 
   /**
@@ -434,7 +436,7 @@
    * @private
    */
   updateSecurity_: function() {
-    if (this.configProperties_.Type == CrOnc.Type.WI_FI)
+    if (this.type_ == CrOnc.Type.WI_FI)
       this.set('WiFi.Security', this.security_, this.configProperties_);
 
     if (this.security_ == CrOnc.Security.WPA_EAP) {
@@ -442,7 +444,7 @@
       eap.Outer = eap.Outer || CrOnc.EAPType.LEAP;
       this.setEap_(eap);
     } else {
-      this.setEap_(undefined);
+      this.setEap_(null);
     }
   },
 
@@ -472,17 +474,19 @@
     var eap = this.eapProperties_;
 
     var pem = eap && eap.ServerCAPEMs && eap.ServerCAPEMs[0];
-    this.selectedServerCa_ = (!!pem && this.serverCaCerts_.find(function(cert) {
-                               return cert.pem == pem;
-                             })) ||
+    var selectedServerCa = (!!pem && this.serverCaCerts_.find(function(cert) {
+                             return cert.pem == pem;
+                           })) ||
         this.serverCaCerts_[0];
+    this.selectedServerCaHash_ = selectedServerCa ? selectedServerCa.hash : '';
 
     var certId =
         eap && eap.ClientCertType == 'PKCS11Id' && eap.ClientCertPKCS11Id;
-    this.selectedUserCert_ = (!!certId && this.userCerts_.find(function(cert) {
-                               return cert.PKCS11Id == certId;
-                             })) ||
+    var selectedUserCert = (!!certId && this.userCerts_.find(function(cert) {
+                             return cert.PKCS11Id == certId;
+                           })) ||
         this.userCerts_[0];
+    this.selectedUserCertHash_ = selectedUserCert ? selectedUserCert.hash : '';
   },
 
   /** @private */
@@ -493,7 +497,7 @@
     }
 
     var outer = this.eapProperties_.Outer;
-    switch (this.configProperties_.Type) {
+    switch (this.type_) {
       case CrOnc.Type.WI_MAX:
         this.showEap_ = {
           Identity: true,
@@ -515,6 +519,7 @@
         };
         break;
     }
+    this.updateIsConfigured_();
   },
 
   /**
@@ -542,11 +547,11 @@
   },
 
   /**
-   * @param {!chrome.networkingPrivate.EAPProperties|undefined} eapProperties
+   * @param {?chrome.networkingPrivate.EAPProperties} eapProperties
    * @private
    */
   setEap_: function(eapProperties) {
-    switch (this.configProperties_.Type) {
+    switch (this.type_) {
       case CrOnc.Type.WI_FI:
         this.set('WiFi.EAP', eapProperties, this.configProperties_);
         break;
@@ -561,6 +566,30 @@
   },
 
   /**
+   * @return {boolean}
+   * @private
+   */
+  getIsConfigured_: function() {
+    if (this.type_ == CrOnc.Type.WI_FI) {
+      if (!this.get('WiFi.SSID', this.configProperties_))
+        return false;
+      if (this.configRequiresPassphrase_()) {
+        var passphrase = this.get('WiFi.Passphrase', this.configProperties_);
+        if (!passphrase || passphrase.length < this.MIN_PASSPHRASE_LENGTH)
+          return false;
+      }
+    }
+    if (this.security_ == CrOnc.Security.WPA_EAP)
+      return this.eapIsConfigured_();
+    return true;
+  },
+
+  /** @private */
+  updateIsConfigured_: function() {
+    this.isConfigured_ = this.getIsConfigured_();
+  },
+
+  /**
    * @param {CrOnc.Type} type The type to compare against.
    * @param {CrOnc.Type} networkType The current network type.
    * @return {boolean} True if the network type matches 'type'.
@@ -575,7 +604,7 @@
    * @private
    */
   saveIsEnabled_: function() {
-    return this.propertiesReceived_ && this.connectIsEnabled_();
+    return this.isConfigured_ && this.propertiesReceived_;
   },
 
   /**
@@ -583,20 +612,7 @@
    * @private
    */
   connectIsEnabled_: function() {
-    if (this.propertiesSent_)
-      return false;
-    if (this.configProperties_.Type == CrOnc.Type.WI_FI) {
-      if (!this.get('WiFi.SSID', this.configProperties_))
-        return false;
-      if (this.configRequiresPassphrase_()) {
-        var passphrase = this.get('WiFi.Passphrase', this.configProperties_);
-        if (!passphrase || passphrase.length < this.MIN_PASSPHRASE_LENGTH)
-          return false;
-      }
-    }
-    if (this.security_ == CrOnc.Security.WPA_EAP)
-      return this.eapPropertiesSet_();
-    return true;
+    return this.isConfigured_ && !this.propertiesSent_;
   },
 
   /**
@@ -604,8 +620,7 @@
    * @private
    */
   securityIsVisible_: function() {
-    return this.configProperties_.Type == CrOnc.Type.WI_FI ||
-        this.configProperties_.Type == CrOnc.Type.ETHERNET;
+    return this.type_ == CrOnc.Type.WI_FI || this.type_ == CrOnc.Type.ETHERNET;
   },
 
   /**
@@ -614,7 +629,7 @@
    */
   securityIsEnabled_: function() {
     // WiFi Security type cannot be changed once configured.
-    return !this.guid_ || this.configProperties_.Type == CrOnc.Type.ETHERNET;
+    return !this.guid_ || this.type_ == CrOnc.Type.ETHERNET;
   },
 
   /**
@@ -622,8 +637,7 @@
    * @private
    */
   shareIsVisible_: function() {
-    return this.configProperties_.Type == CrOnc.Type.WI_FI ||
-        this.configProperties_.Type == CrOnc.Type.WI_MAX;
+    return this.type_ == CrOnc.Type.WI_FI || this.type_ == CrOnc.Type.WI_MAX;
   },
 
   /**
@@ -644,7 +658,7 @@
         return false;
     }
 
-    if (this.configProperties_.Type == CrOnc.Type.WI_FI) {
+    if (this.type_ == CrOnc.Type.WI_FI) {
       // Insecure WiFi networks are always shared.
       if (this.security_ == CrOnc.Security.NONE)
         return false;
@@ -656,13 +670,13 @@
    * @return {boolean}
    * @private
    */
-  eapPropertiesSet_: function() {
+  eapIsConfigured_: function() {
     var eap = this.getEap_(this.configProperties_);
     if (!eap)
       return false;
     if (eap.Outer != CrOnc.EAPType.EAP_TLS)
       return true;
-    return !!this.selectedUserCert_ && !!this.selectedUserCert_.hash;
+    return !!this.selectedUserCertHash_;
   },
 
   /** @private */
@@ -685,7 +699,7 @@
    * @private
    */
   setEapProperties_: function(eap) {
-    var caHash = this.selectedServerCa_ && this.selectedServerCa_.hash || '';
+    var caHash = this.selectedServerCaHash_ || '';
 
     eap.UseSystemCAs = caHash == 'do-not-check';
 
@@ -695,7 +709,7 @@
         });
     eap.ServerCAPEMs = serverCa ? [serverCa.pem] : [];
 
-    var userHash = this.selectedUserCert_ && this.selectedUserCert_.hash;
+    var userHash = this.selectedUserCertHash_;
     var userCert = userHash && this.userCerts_.find(function(cert) {
       return cert.hash == userHash;
     });
@@ -756,7 +770,7 @@
   configRequiresPassphrase_: function() {
     // Note: 'Passphrase' is only used by WiFi; Ethernet and WiMAX use
     // EAP.Password.
-    return this.configProperties_.Type == CrOnc.Type.WI_FI &&
+    return this.type_ == CrOnc.Type.WI_FI &&
         (this.security_ == CrOnc.Security.WEP_PSK ||
          this.security_ == CrOnc.Security.WPA_PSK);
   },
diff --git a/chrome/browser/resources/settings/internet_page/network_config_select.html b/chrome/browser/resources/settings/internet_page/network_config_select.html
index b0e9976..48760661 100644
--- a/chrome/browser/resources/settings/internet_page/network_config_select.html
+++ b/chrome/browser/resources/settings/internet_page/network_config_select.html
@@ -11,7 +11,8 @@
       <select class="md-select" disabled="[[disabled]]"
           value="{{value::change}}" aria-labelledby="label">
         <template is="dom-repeat" items="[[items]]">
-          <option value="[[item]]" disabled="[[!getItemEnabled_(item)]]">
+          <option value="[[getItemValue_(item)]]"
+              disabled="[[!getItemEnabled_(item)]]">
             [[getItemLabel_(item, oncPrefix)]]
           </option>
         </template>
diff --git a/chrome/browser/resources/settings/internet_page/network_config_select.js b/chrome/browser/resources/settings/internet_page/network_config_select.js
index 8a8eeb7..473ca0b 100644
--- a/chrome/browser/resources/settings/internet_page/network_config_select.js
+++ b/chrome/browser/resources/settings/internet_page/network_config_select.js
@@ -27,7 +27,7 @@
     /** Prefix used to look up ONC property names. */
     oncPrefix: {
       type: String,
-      value: ''
+      value: '',
     },
 
     /** Select item value */
@@ -73,6 +73,17 @@
 
   /**
    * @param {string|!chrome.networkingPrivate.Certificate} item
+   * @return {string}
+   * @private
+   */
+  getItemValue_: function(item) {
+    if (this.certList)
+      return /** @type {chrome.networkingPrivate.Certificate}*/ (item).hash;
+    return /** @type {string} */ (item);
+  },
+
+  /**
+   * @param {string|!chrome.networkingPrivate.Certificate} item
    * @return {boolean}
    * @private
    */
diff --git a/chrome/browser/resources/settings/people_page/change_picture.html b/chrome/browser/resources/settings/people_page/change_picture.html
index 2b642c9..82cbc58 100644
--- a/chrome/browser/resources/settings/people_page/change_picture.html
+++ b/chrome/browser/resources/settings/people_page/change_picture.html
@@ -82,9 +82,9 @@
             image-src="[[getImageSrc_(selectedItem_)]]"
             image-type="[[getImageType_(selectedItem_)]]"
             discard-image-label="$i18n{discardPhoto}"
-            flip-photo-label="$i18n{flipPhoto}"
             preview-alt-text="$i18n{previewAltText}"
-            take-photo-label="$i18n{takePhoto}">
+            take-photo-label="$i18n{takePhoto}"
+            switch-mode-label="$i18n{switchMode}">
         </cr-picture-pane>
         <div id="authorCredit"
             hidden="[[!isAuthorCreditShown_(selectedItem_)]]">
@@ -103,7 +103,8 @@
           choose-file-label="$i18n{chooseFile}"
           old-image-label="$i18n{oldPhoto}"
           profile-image-label="$i18n{profilePhoto}"
-          take-photo-label="$i18n{takePhoto}">
+          take-photo-label="$i18n{takePhoto}"
+          switch-mode-label="$i18n{switchMode}">
       </cr-picture-list>
     </div>
   </template>
diff --git a/chrome/browser/resources/settings/people_page/change_picture.js b/chrome/browser/resources/settings/people_page/change_picture.js
index d41dc4c..b610c1d4 100644
--- a/chrome/browser/resources/settings/people_page/change_picture.js
+++ b/chrome/browser/resources/settings/people_page/change_picture.js
@@ -58,8 +58,8 @@
   listeners: {
     'discard-image': 'onDiscardImage_',
     'image-activate': 'onImageActivate_',
-    'photo-flipped': 'onPhotoFlipped_',
     'photo-taken': 'onPhotoTaken_',
+    'switch-mode': 'onSwitchMode_',
   },
 
   /** @private {?settings.ChangePictureBrowserProxy} */
@@ -209,11 +209,10 @@
    * @param {!{detail: boolean}} event
    * @private
    */
-  onPhotoFlipped_: function(event) {
-    var flipped = event.detail;
-    var flipMessageId = flipped ? 'photoFlippedAccessibleText' :
-                                  'photoFlippedBackAccessibleText';
-    announceAccessibleMessage(loadTimeData.getString(flipMessageId));
+  onSwitchMode_: function(event) {
+    var videomode = event.detail;
+    announceAccessibleMessage(this.i18n(
+        videomode ? 'videoModeAccessibleText' : 'photoModeAccessibleText'));
   },
 
   /** @private */
diff --git a/chrome/browser/resources/settings/people_page/settings_icon_flip.svg b/chrome/browser/resources/settings/people_page/settings_icon_flip.svg
deleted file mode 100644
index b95e714b..0000000
--- a/chrome/browser/resources/settings/people_page/settings_icon_flip.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FFFFFF" preserveAspectRatio="xMidYMid meet"><path d="M15 21h2v-2h-2v2zm4-12h2V7h-2v2zM3 5v14c0 1.1.9 2 2 2h4v-2H5V5h4V3H5c-1.1 0-2 .9-2 2zm16-2v2h2c0-1.1-.9-2-2-2zm-8 20h2V1h-2v22zm8-6h2v-2h-2v2zM15 5h2V3h-2v2zm4 8h2v-2h-2v2zm0 8c1.1 0 2-.9 2-2h-2v2z"></path></svg>
\ No newline at end of file
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html
index 9485e7c..52fff4a 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_page.html
+++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -219,7 +219,8 @@
               category="{{ContentSettingsTypes.AUTOMATIC_DOWNLOADS}}">
           </category-default-setting>
           <category-setting-exceptions
-              category="{{ContentSettingsTypes.AUTOMATIC_DOWNLOADS}}">
+              category="{{ContentSettingsTypes.AUTOMATIC_DOWNLOADS}}"
+              block-header="$i18n{siteSettingsBlock}">
           </category-setting-exceptions>
         </settings-subpage>
       </template>
@@ -232,7 +233,8 @@
               category="{{ContentSettingsTypes.BACKGROUND_SYNC}}">
           </category-default-setting>
           <category-setting-exceptions
-              category="{{ContentSettingsTypes.BACKGROUND_SYNC}}">
+              category="{{ContentSettingsTypes.BACKGROUND_SYNC}}"
+              block-header="$i18n{siteSettingsBlock}">
           </category-setting-exceptions>
         </settings-subpage>
       </template>
@@ -246,7 +248,8 @@
                   "$i18n{siteSettingsAskBeforeAccessingRecommended}">
           </category-default-setting>
           <category-setting-exceptions
-              category="{{ContentSettingsTypes.CAMERA}}" read-only-list>
+              category="{{ContentSettingsTypes.CAMERA}}" read-only-list
+              block-header="$i18n{siteSettingsBlock}">
           </category-setting-exceptions>
         </settings-subpage>
       </template>
@@ -271,7 +274,8 @@
              </button>
           </div>
           <category-setting-exceptions
-              category="{{ContentSettingsTypes.COOKIES}}">
+              category="{{ContentSettingsTypes.COOKIES}}"
+              block-header="$i18n{siteSettingsBlock}">
           </category-setting-exceptions>
         </settings-subpage>
       </template>
@@ -291,7 +295,8 @@
               toggle-on-label="$i18n{siteSettingsShowAllRecommended}">
           </category-default-setting>
           <category-setting-exceptions
-              category="{{ContentSettingsTypes.IMAGES}}">
+              category="{{ContentSettingsTypes.IMAGES}}"
+              block-header="$i18n{siteSettingsBlock}">
           </category-setting-exceptions>
         </settings-subpage>
       </template>
@@ -303,7 +308,8 @@
               category="{{ContentSettingsTypes.GEOLOCATION}}">
           </category-default-setting>
           <category-setting-exceptions
-              category="{{ContentSettingsTypes.GEOLOCATION}}" read-only-list>
+              category="{{ContentSettingsTypes.GEOLOCATION}}" read-only-list
+              block-header="$i18n{siteSettingsBlock}">
           </category-setting-exceptions>
         </settings-subpage>
       </template>
@@ -333,7 +339,8 @@
               category="{{ContentSettingsTypes.JAVASCRIPT}}">
           </category-default-setting>
           <category-setting-exceptions
-              category="{{ContentSettingsTypes.JAVASCRIPT}}">
+              category="{{ContentSettingsTypes.JAVASCRIPT}}"
+              block-header="$i18n{siteSettingsBlock}">
           </category-setting-exceptions>
         </settings-subpage>
       </template>
@@ -347,7 +354,8 @@
                 category="{{ContentSettingsTypes.SOUND}}">
             </category-default-setting>
             <category-setting-exceptions
-                category="{{ContentSettingsTypes.SOUND}}">
+                category="{{ContentSettingsTypes.SOUND}}"
+                block-header="$i18n{siteSettingsBlockSound}">
             </category-setting-exceptions>
           </settings-subpage>
        </template>
@@ -362,7 +370,8 @@
                   "$i18n{siteSettingsAskBeforeAccessingRecommended}">
           </category-default-setting>
           <category-setting-exceptions
-              category="{{ContentSettingsTypes.MIC}}" read-only-list>
+              category="{{ContentSettingsTypes.MIC}}" read-only-list
+              block-header="$i18n{siteSettingsBlock}">
           </category-setting-exceptions>
         </settings-subpage>
       </template>
@@ -374,7 +383,8 @@
               category="{{ContentSettingsTypes.NOTIFICATIONS}}">
           </category-default-setting>
           <category-setting-exceptions
-              category="{{ContentSettingsTypes.NOTIFICATIONS}}">
+              category="{{ContentSettingsTypes.NOTIFICATIONS}}"
+              block-header="$i18n{siteSettingsBlock}">
           </category-setting-exceptions>
         </settings-subpage>
       </template>
@@ -394,7 +404,8 @@
           </a>
 </if>
           <category-setting-exceptions
-              category="{{ContentSettingsTypes.PLUGINS}}">
+              category="{{ContentSettingsTypes.PLUGINS}}"
+              block-header="$i18n{siteSettingsBlock}">
           </category-setting-exceptions>
         </settings-subpage>
       </template>
@@ -405,7 +416,8 @@
               toggle-on-label="$i18n{siteSettingsAllowed}">
           </category-default-setting>
           <category-setting-exceptions
-              category="{{ContentSettingsTypes.POPUPS}}">
+              category="{{ContentSettingsTypes.POPUPS}}"
+              block-header="$i18n{siteSettingsBlock}">
           </category-setting-exceptions>
         </settings-subpage>
       </template>
@@ -420,7 +432,8 @@
             </category-default-setting>
             <category-setting-exceptions
                 category="{{ContentSettingsTypes.ADS}}"
-                read-only-list>
+                read-only-list
+                block-header="$i18n{siteSettingsBlock}">
             </category-setting-exceptions>
           </settings-subpage>
        </template>
@@ -434,7 +447,8 @@
               category="{{ContentSettingsTypes.UNSANDBOXED_PLUGINS}}">
           </category-default-setting>
           <category-setting-exceptions
-              category="{{ContentSettingsTypes.UNSANDBOXED_PLUGINS}}">
+              category="{{ContentSettingsTypes.UNSANDBOXED_PLUGINS}}"
+              block-header="$i18n{siteSettingsBlock}">
           </category-setting-exceptions>
         </settings-subpage>
       </template>
@@ -447,7 +461,8 @@
               category="{{ContentSettingsTypes.MIDI_DEVICES}}">
           </category-default-setting>
           <category-setting-exceptions
-              category="{{ContentSettingsTypes.MIDI_DEVICES}}" read-only-list>
+              category="{{ContentSettingsTypes.MIDI_DEVICES}}" read-only-list
+              block-header="$i18n{siteSettingsBlock}">
           </category-setting-exceptions>
         </settings-subpage>
       </template>
@@ -494,7 +509,8 @@
           <template is="dom-if"
               if="[[prefs.settings.privacy.drm_enabled.value]]">
             <category-setting-exceptions
-                category="{{ContentSettingsTypes.PROTECTED_CONTENT}}">
+                category="{{ContentSettingsTypes.PROTECTED_CONTENT}}"
+                block-header="$i18n{siteSettingsBlock}">
             </category-setting-exceptions>
           </template>
 </if>
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd
index f690e92..4ea3107 100644
--- a/chrome/browser/resources/settings/settings_resources.grd
+++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -76,7 +76,8 @@
                  type="chrome_html" />
       <structure name="IDR_SETTINGS_ALL_SITES_JS"
                  file="site_settings/all_sites.js"
-                 type="chrome_html" />
+                 type="chrome_html"
+                 preprocess="true" />
       <structure name="IDR_SETTINGS_CATEGORY_DEFAULT_SETTING_HTML"
                  file="site_settings/category_default_setting.html"
                  type="chrome_html" />
diff --git a/chrome/browser/resources/settings/settings_shared_css.html b/chrome/browser/resources/settings/settings_shared_css.html
index 10bd6924..ecaa3d9 100644
--- a/chrome/browser/resources/settings/settings_shared_css.html
+++ b/chrome/browser/resources/settings/settings_shared_css.html
@@ -90,7 +90,7 @@
       }
 
       /* Adjust the margin between the separator and the first button. */
-      .settings-box .separator + paper-button {
+      .separator + paper-button {
         -webkit-margin-start: calc(var(--cr-button-edge-spacing) * -1);
       }
 
@@ -339,7 +339,7 @@
       /* The separator a vertical line like a horizontal rule <hr> tag, but goes
        * the other way. An example is near the |sign out| button on the People
        * settings. */
-      :-webkit-any(.settings-box, .list-item) .separator {
+      .separator {
         -webkit-border-start: var(--settings-separator-line);
         -webkit-margin-end: var(--settings-box-row-padding);
         -webkit-margin-start: var(--settings-box-row-padding);
@@ -349,7 +349,7 @@
             var(--settings-separator-gaps));
       }
 
-      :-webkit-any(.settings-box, .list-item).two-line .separator {
+      .two-line .separator {
         height: calc(var(--settings-row-two-line-min-height) -
             2 * var(--settings-separator-gaps));
       }
diff --git a/chrome/browser/resources/settings/site_settings/all_sites.js b/chrome/browser/resources/settings/site_settings/all_sites.js
index 3ac0f36..23f37fd 100644
--- a/chrome/browser/resources/settings/site_settings/all_sites.js
+++ b/chrome/browser/resources/settings/site_settings/all_sites.js
@@ -46,6 +46,10 @@
     var types = Object.values(settings.ContentSettingsTypes);
     for (var i = 0; i < types.length; i++) {
       var type = types[i];
+      // <if expr="not chromeos">
+      if (type == settings.ContentSettingsTypes.PROTECTED_CONTENT)
+        continue;
+      // </if>
       if (type == settings.ContentSettingsTypes.PROTOCOL_HANDLERS ||
           type == settings.ContentSettingsTypes.USB_DEVICES ||
           type == settings.ContentSettingsTypes.ZOOM_LEVELS) {
diff --git a/chrome/browser/resources/settings/site_settings/category_setting_exceptions.html b/chrome/browser/resources/settings/site_settings/category_setting_exceptions.html
index ab0925d..091cc75 100644
--- a/chrome/browser/resources/settings/site_settings/category_setting_exceptions.html
+++ b/chrome/browser/resources/settings/site_settings/category_setting_exceptions.html
@@ -18,7 +18,7 @@
     <site-list
         category="[[category]]"
         category-subtype="[[ContentSetting.BLOCK]]"
-        category-header="$i18n{siteSettingsBlock}"
+        category-header="[[blockHeader]]"
         read-only-list="[[readOnlyList]]">
     </site-list>
     <site-list
diff --git a/chrome/browser/resources/settings/site_settings/category_setting_exceptions.js b/chrome/browser/resources/settings/site_settings/category_setting_exceptions.js
index 0d4a210..3bfe4e9 100644
--- a/chrome/browser/resources/settings/site_settings/category_setting_exceptions.js
+++ b/chrome/browser/resources/settings/site_settings/category_setting_exceptions.js
@@ -20,6 +20,11 @@
       type: Boolean,
       value: false,
     },
+
+    /**
+     * The heading text for the blocked exception list.
+     */
+    blockHeader: String,
   },
 
   /** @override */
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.cc
index e336f44..2c2e028 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.cc
@@ -570,11 +570,9 @@
       RecordCleanupResultHistogram(CLEANUP_RESULT_SUCCEEDED);
       delegate_->ResetTaggedProfiles(
           g_browser_process->profile_manager()->GetLoadedProfiles(),
-          // OnSettingsResetCompleted() will take care of transitioning to the
-          // kIdle state with IdleReason kCleaningSucceeded.
-          base::BindOnce(&ChromeCleanerControllerImpl::OnSettingsResetCompleted,
-                         base::Unretained(this)));
-      ResetCleanerDataAndInvalidateWeakPtrs();
+          base::BindOnce(&base::DoNothing));
+      idle_reason_ = IdleReason::kCleaningSucceeded;
+      SetStateAndNotifyObservers(State::kIdle);
       return;
     }
   }
@@ -598,9 +596,4 @@
   }
 }
 
-void ChromeCleanerControllerImpl::OnSettingsResetCompleted() {
-  idle_reason_ = IdleReason::kCleaningSucceeded;
-  SetStateAndNotifyObservers(State::kIdle);
-}
-
 }  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.h b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.h
index d52aa4c..d6f85d4 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.h
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.h
@@ -102,9 +102,6 @@
   void OnCleanerProcessDone(ChromeCleanerRunner::ProcessStatus process_status);
   void InitiateReboot();
 
-  // Invoked once settings reset is done for tagged profiles.
-  void OnSettingsResetCompleted();
-
   std::unique_ptr<ChromeCleanerControllerDelegate> real_delegate_;
   // Pointer to either real_delegate_ or one set by tests.
   ChromeCleanerControllerDelegate* delegate_;
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.cc b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
index 91a0e82..d94b027 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
@@ -30,6 +30,7 @@
 #include "components/safe_browsing/db/database_manager.h"
 #include "components/safe_browsing/features.h"
 #include "components/safe_browsing/password_protection/password_protection_request.h"
+#include "components/safe_browsing/triggers/trigger_throttler.h"
 #include "components/signin/core/browser/account_info.h"
 #include "components/signin/core/browser/account_tracker_service.h"
 #include "components/signin/core/browser/signin_manager.h"
@@ -112,6 +113,7 @@
               ServiceAccessType::EXPLICIT_ACCESS),
           HostContentSettingsMapFactory::GetForProfile(profile)),
       ui_manager_(sb_service->ui_manager()),
+      trigger_manager_(sb_service->trigger_manager()),
       profile_(profile),
       navigation_observer_manager_(sb_service->navigation_observer_manager()),
       pref_change_registrar_(new PrefChangeRegistrar) {
@@ -138,6 +140,14 @@
             LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
   }
 
+  // Before shutdown, if there is still unhandled password reuses, we set the
+  // kSafeBrowsingChangePasswordInSettingsEnabled to true. So next time when
+  // user starts a new session, change password card will show on Chrome
+  // settings page.
+  profile_->GetPrefs()->SetBoolean(
+      prefs::kSafeBrowsingChangePasswordInSettingsEnabled,
+      !unhandled_password_reuses_.empty());
+
   if (pref_change_registrar_)
     pref_change_registrar_->RemoveAll();
 }
@@ -159,7 +169,9 @@
     Profile* profile) {
   ChromePasswordProtectionService* service =
       ChromePasswordProtectionService::GetPasswordProtectionService(profile);
-  return service && !service->unhandled_password_reuses().empty();
+  return service && (!service->unhandled_password_reuses().empty() ||
+                     profile->GetPrefs()->GetBoolean(
+                         prefs::kSafeBrowsingChangePasswordInSettingsEnabled));
 }
 
 void ChromePasswordProtectionService::FillReferrerChain(
@@ -181,7 +193,7 @@
 
 void ChromePasswordProtectionService::ShowModalWarning(
     content::WebContents* web_contents,
-    const std::string& unused_verdict_token) {
+    const std::string& verdict_token) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   // TODO(jialiul): Use verdict_token field in post warning report.
   UpdateSecurityState(SB_THREAT_TYPE_PASSWORD_REUSE, web_contents);
@@ -195,6 +207,8 @@
     unhandled_password_reuses_[Origin(web_contents->GetLastCommittedURL())] =
         GetLastCommittedNavigationID(web_contents);
   }
+  // Starts preparing post-warning report.
+  MaybeStartThreatDetailsCollection(web_contents, verdict_token);
 }
 
 // TODO(jialiul): Handle user actions in separate functions.
@@ -238,7 +252,8 @@
           NOTREACHED();
           break;
       }
-      // TODO(jialiul): Sends post-warning reporting.
+      MaybeFinishCollectingThreatDetails(
+          web_contents, action == PasswordProtectionService::CHANGE_PASSWORD);
       break;
     case PasswordProtectionService::CHROME_SETTINGS:
       DCHECK_EQ(PasswordProtectionService::CHANGE_PASSWORD, action);
@@ -261,6 +276,46 @@
   observer_list_.RemoveObserver(observer);
 }
 
+void ChromePasswordProtectionService::MaybeStartThreatDetailsCollection(
+    content::WebContents* web_contents,
+    const std::string& token) {
+  // |trigger_manager_| can be null in test.
+  if (!trigger_manager_)
+    return;
+
+  security_interstitials::UnsafeResource resource;
+  resource.threat_type = SB_THREAT_TYPE_PASSWORD_REUSE;
+  resource.url = web_contents->GetLastCommittedURL();
+  resource.web_contents_getter = resource.GetWebContentsGetter(
+      web_contents->GetMainFrame()->GetProcess()->GetID(),
+      web_contents->GetMainFrame()->GetRoutingID());
+  resource.token = token;
+  // Ignores the return of |StartCollectingThreatDetails()| here and let
+  // TriggerManager decide whether it should start data collection.
+  trigger_manager_->StartCollectingThreatDetails(
+      safe_browsing::TriggerType::GAIA_PASSWORD_REUSE, web_contents, resource,
+      profile_->GetRequestContext(), /*history_service=*/nullptr,
+      TriggerManager::GetSBErrorDisplayOptions(*profile_->GetPrefs(),
+                                               *web_contents));
+}
+
+void ChromePasswordProtectionService::MaybeFinishCollectingThreatDetails(
+    content::WebContents* web_contents,
+    bool did_proceed) {
+  // |trigger_manager_| can be null in test.
+  if (!trigger_manager_)
+    return;
+
+  // Since we don't keep track the threat details in progress, it is safe to
+  // ignore the result of |FinishCollectingThreatDetails()|. TriggerManager will
+  // take care of whether report should be sent.
+  trigger_manager_->FinishCollectingThreatDetails(
+      safe_browsing::TriggerType::GAIA_PASSWORD_REUSE, web_contents,
+      base::TimeDelta::FromMilliseconds(0), did_proceed, /*num_visit=*/0,
+      TriggerManager::GetSBErrorDisplayOptions(*profile_->GetPrefs(),
+                                               *web_contents));
+}
+
 PrefService* ChromePasswordProtectionService::GetPrefs() {
   return profile_->GetPrefs();
 }
@@ -571,6 +626,7 @@
                                 nullptr,
                                 content_setting_map.get()),
       ui_manager_(ui_manager),
+      trigger_manager_(nullptr),
       profile_(profile) {
   InitializeAccountInfo();
 }
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.h b/chrome/browser/safe_browsing/chrome_password_protection_service.h
index 30627e8d..b538a18 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service.h
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service.h
@@ -10,6 +10,7 @@
 #include "base/observer_list.h"
 #include "build/build_config.h"
 #include "components/safe_browsing/password_protection/password_protection_service.h"
+#include "components/safe_browsing/triggers/trigger_manager.h"
 #include "components/sync/protocol/user_event_specifics.pb.h"
 #include "ui/base/ui_features.h"
 #include "url/origin.h"
@@ -96,6 +97,16 @@
   // Called during the destruction of the observer subclass.
   virtual void RemoveObserver(Observer* observer);
 
+  // Starts collecting threat details if user has extended reporting enabled and
+  // is not in incognito mode.
+  void MaybeStartThreatDetailsCollection(content::WebContents* web_contents,
+                                         const std::string& token);
+
+  // Sends threat details if user has extended reporting enabled and is not in
+  // incognito mode.
+  void MaybeFinishCollectingThreatDetails(content::WebContents* web_contents,
+                                          bool did_proceed);
+
   const std::map<Origin, int64_t>& unhandled_password_reuses() const {
     return unhandled_password_reuses_;
   }
@@ -197,6 +208,7 @@
       scoped_refptr<SafeBrowsingUIManager> ui_manager);
 
   scoped_refptr<SafeBrowsingUIManager> ui_manager_;
+  TriggerManager* trigger_manager_;
   // Profile associated with this instance.
   Profile* profile_;
   // AccountInfo associated with this |profile_|.
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service_browsertest.cc b/chrome/browser/safe_browsing/chrome_password_protection_service_browsertest.cc
index 717f9c2..923d0f1 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service_browsertest.cc
@@ -16,6 +16,7 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/prefs/pref_service.h"
+#include "components/safe_browsing/common/safe_browsing_prefs.h"
 #include "components/safe_browsing/features.h"
 #include "components/security_state/core/security_state.h"
 #include "components/signin/core/browser/account_info.h"
@@ -42,26 +43,35 @@
     InProcessBrowserTest::SetUp();
   }
 
-  ChromePasswordProtectionService* GetService() {
+  ChromePasswordProtectionService* GetService(bool is_incognito) {
     return ChromePasswordProtectionService::GetPasswordProtectionService(
-        browser()->profile());
+        is_incognito ? browser()->profile()->GetOffTheRecordProfile()
+                     : browser()->profile());
   }
 
-  void SimulateGaiaPasswordChange() {
-    browser()->profile()->GetPrefs()->SetString(
-        password_manager::prefs::kSyncPasswordHash, "new_password_hash");
+  void SimulateGaiaPasswordChange(bool is_incognito) {
+    if (is_incognito) {
+      browser()->profile()->GetOffTheRecordProfile()->GetPrefs()->SetString(
+          password_manager::prefs::kSyncPasswordHash, "new_password_hash");
+    } else {
+      browser()->profile()->GetPrefs()->SetString(
+          password_manager::prefs::kSyncPasswordHash, "new_password_hash");
+    }
   }
 
-  void SimulateAction(ChromePasswordProtectionService::WarningUIType ui_type,
+  void SimulateAction(ChromePasswordProtectionService* service,
+                      ChromePasswordProtectionService::WarningUIType ui_type,
                       ChromePasswordProtectionService::WarningAction action) {
-    for (auto& observer : GetService()->observer_list_) {
+    for (auto& observer : service->observer_list_) {
       if (ui_type == observer.GetObserverType()) {
         observer.InvokeActionForTesting(action);
       }
     }
   }
 
-  void SimulateGaiaPasswordChanged() { GetService()->OnGaiaPasswordChanged(); }
+  void SimulateGaiaPasswordChanged(ChromePasswordProtectionService* service) {
+    service->OnGaiaPasswordChanged();
+  }
 
   void GetSecurityInfo(content::WebContents* web_contents,
                        security_state::SecurityInfo* out_security_info) {
@@ -70,8 +80,8 @@
     helper->GetSecurityInfo(out_security_info);
   }
 
-  void SetDefaultProfileEmail() {
-    GetService()->account_info_->email = "foo@bar.com";
+  void SetDefaultProfileEmail(ChromePasswordProtectionService* service) {
+    service->account_info_->email = "foo@bar.com";
   }
 
  protected:
@@ -81,8 +91,8 @@
 
 IN_PROC_BROWSER_TEST_F(ChromePasswordProtectionServiceBrowserTest,
                        SuccessfullyChangePassword) {
-  ChromePasswordProtectionService* service = GetService();
-  SetDefaultProfileEmail();
+  ChromePasswordProtectionService* service = GetService(/*is_incognito=*/false);
+  SetDefaultProfileEmail(service);
   Profile* profile = browser()->profile();
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
@@ -112,7 +122,7 @@
 
   // Simulates clicking "Change Password" button on the modal dialog.
   // There should be only 1 observer in the list.
-  SimulateAction(ChromePasswordProtectionService::MODAL_DIALOG,
+  SimulateAction(service, ChromePasswordProtectionService::MODAL_DIALOG,
                  ChromePasswordProtectionService::CHANGE_PASSWORD);
   content::WebContents* new_web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
@@ -126,7 +136,7 @@
             new_web_contents->GetVisibleURL());
 
   // Simulates clicking "Change password" button on the chrome://settings card.
-  SimulateAction(ChromePasswordProtectionService::CHROME_SETTINGS,
+  SimulateAction(service, ChromePasswordProtectionService::CHROME_SETTINGS,
                  ChromePasswordProtectionService::CHANGE_PASSWORD);
   base::RunLoop().RunUntilIdle();
   // Verify myaccount.google.com or Google signin page should be opened in a
@@ -139,7 +149,7 @@
                   .DomainIs("google.com"));
 
   // Simulates user finished changing password.
-  SimulateGaiaPasswordChanged();
+  SimulateGaiaPasswordChanged(service);
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(
       ChromePasswordProtectionService::ShouldShowChangePasswordSettingUI(
@@ -152,7 +162,7 @@
 
 IN_PROC_BROWSER_TEST_F(ChromePasswordProtectionServiceBrowserTest,
                        MarkSiteAsLegitimate) {
-  ChromePasswordProtectionService* service = GetService();
+  ChromePasswordProtectionService* service = GetService(/*is_incognito=*/false);
   Profile* profile = browser()->profile();
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
@@ -182,7 +192,7 @@
 
   // Simulates clicking "Ignore" button on the modal dialog.
   // There should be only 1 observer in the list.
-  SimulateAction(ChromePasswordProtectionService::MODAL_DIALOG,
+  SimulateAction(service, ChromePasswordProtectionService::MODAL_DIALOG,
                  ChromePasswordProtectionService::IGNORE_WARNING);
   base::RunLoop().RunUntilIdle();
   // No new tab opens. SecurityInfo doesn't change.
@@ -211,7 +221,7 @@
 
 IN_PROC_BROWSER_TEST_F(ChromePasswordProtectionServiceBrowserTest,
                        OpenChromeSettingsViaPageInfo) {
-  ChromePasswordProtectionService* service = GetService();
+  ChromePasswordProtectionService* service = GetService(/*is_incognito=*/false);
   Profile* profile = browser()->profile();
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
@@ -222,7 +232,7 @@
   service->ShowModalWarning(web_contents, "unused_token");
   base::RunLoop().RunUntilIdle();
   // Simulates clicking "Ignore" to close dialog.
-  SimulateAction(ChromePasswordProtectionService::MODAL_DIALOG,
+  SimulateAction(service, ChromePasswordProtectionService::MODAL_DIALOG,
                  ChromePasswordProtectionService::IGNORE_WARNING);
   base::RunLoop().RunUntilIdle();
   ASSERT_TRUE(
@@ -253,7 +263,7 @@
 IN_PROC_BROWSER_TEST_F(ChromePasswordProtectionServiceBrowserTest,
                        VeriryUnhandledPasswordReuse) {
   histograms_.ExpectTotalCount(kGaiaPasswordChangeHistogramName, 0);
-  ChromePasswordProtectionService* service = GetService();
+  ChromePasswordProtectionService* service = GetService(/*is_incognito=*/false);
   ASSERT_TRUE(service);
   Profile* profile = browser()->profile();
   ui_test_utils::NavigateToURL(browser(), embedded_test_server()->GetURL("/"));
@@ -273,7 +283,7 @@
           profile));
 
   // Opens a new browser window.
-  Browser* browser2 = CreateBrowser(browser()->profile());
+  Browser* browser2 = CreateBrowser(profile);
   // Shows modal dialog on this new web_contents.
   content::WebContents* new_web_contents =
       browser2->tab_strip_model()->GetActiveWebContents();
@@ -286,7 +296,7 @@
           profile));
 
   // Simulates a Gaia password change.
-  SimulateGaiaPasswordChange();
+  SimulateGaiaPasswordChange(/*is_incognito=*/false);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0u, service->unhandled_password_reuses().size());
   EXPECT_FALSE(
@@ -296,6 +306,29 @@
               testing::ElementsAre(base::Bucket(2, 1)));
 }
 
+IN_PROC_BROWSER_TEST_F(ChromePasswordProtectionServiceBrowserTest,
+                       VerifyShouldShowChangePasswordSettingUI) {
+  Profile* profile = browser()->profile();
+  EXPECT_FALSE(
+      ChromePasswordProtectionService::ShouldShowChangePasswordSettingUI(
+          profile));
+  // Simulates previous session has unhandled password reuses.
+  profile->GetPrefs()->SetBoolean(
+      prefs::kSafeBrowsingChangePasswordInSettingsEnabled, true);
+
+  EXPECT_TRUE(
+      ChromePasswordProtectionService::ShouldShowChangePasswordSettingUI(
+          profile));
+
+  // Simulates a Gaia password change.
+  SimulateGaiaPasswordChanged(GetService(/*is_incognito=*/false));
+  EXPECT_FALSE(
+      ChromePasswordProtectionService::ShouldShowChangePasswordSettingUI(
+          profile));
+  EXPECT_FALSE(profile->GetPrefs()->GetBoolean(
+      prefs::kSafeBrowsingChangePasswordInSettingsEnabled));
+}
+
 // TODO(jialiul): Add more tests where multiple browser windows are involved.
 
 }  // namespace safe_browsing
diff --git a/chrome/browser/search/instant_service.cc b/chrome/browser/search/instant_service.cc
index f6ff35b..a09c472 100644
--- a/chrome/browser/search/instant_service.cc
+++ b/chrome/browser/search/instant_service.cc
@@ -224,6 +224,7 @@
     item.thumbnail = tile.thumbnail_url;
     item.favicon = tile.favicon_url;
     item.source = tile.source;
+    item.title_source = tile.title_source;
     most_visited_items_.push_back(item);
   }
 
diff --git a/chrome/browser/search/instant_service_unittest.cc b/chrome/browser/search/instant_service_unittest.cc
index 4a0334d..a817174 100644
--- a/chrome/browser/search/instant_service_unittest.cc
+++ b/chrome/browser/search/instant_service_unittest.cc
@@ -16,8 +16,11 @@
 using InstantServiceTest = InstantUnitTestBase;
 
 TEST_F(InstantServiceTest, GetNTPTileSuggestion) {
-  ntp_tiles::NTPTilesVector suggestions;
-  suggestions.push_back(ntp_tiles::NTPTile());
+  ntp_tiles::NTPTile some_tile;
+  some_tile.source = ntp_tiles::TileSource::TOP_SITES;
+  some_tile.title_source = ntp_tiles::TileTitleSource::TITLE_TAG;
+  ntp_tiles::NTPTilesVector suggestions{some_tile};
+
   std::map<ntp_tiles::SectionType, ntp_tiles::NTPTilesVector> suggestions_map;
   suggestions_map[ntp_tiles::SectionType::PERSONALIZED] = suggestions;
 
@@ -25,5 +28,6 @@
 
   auto items = instant_service_->most_visited_items_;
   ASSERT_EQ(1, (int)items.size());
-  ASSERT_EQ(ntp_tiles::TileSource::TOP_SITES, items[0].source);
+  EXPECT_EQ(ntp_tiles::TileSource::TOP_SITES, items[0].source);
+  EXPECT_EQ(ntp_tiles::TileTitleSource::TITLE_TAG, items[0].title_source);
 }
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc
index 5006e2c..809c30ef 100644
--- a/chrome/browser/search/local_ntp_source.cc
+++ b/chrome/browser/search/local_ntp_source.cc
@@ -129,6 +129,8 @@
     AddString(translated_strings.get(), "audioError",
               IDS_NEW_TAB_VOICE_AUDIO_ERROR);
     AddString(translated_strings.get(), "details", IDS_NEW_TAB_VOICE_DETAILS);
+    AddString(translated_strings.get(), "clickToViewDoodle",
+              IDS_CLICK_TO_VIEW_DOODLE);
     AddString(translated_strings.get(), "fakeboxMicrophoneTooltip",
               IDS_TOOLTIP_MIC_SEARCH);
     AddString(translated_strings.get(), "languageError",
diff --git a/chrome/browser/search/search.cc b/chrome/browser/search/search.cc
index a364ccf..9bfab12 100644
--- a/chrome/browser/search/search.cc
+++ b/chrome/browser/search/search.cc
@@ -25,6 +25,7 @@
 #include "components/search_engines/search_engine_type.h"
 #include "components/search_engines/template_url_service.h"
 #include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 
@@ -81,11 +82,9 @@
 }
 
 GURL TemplateURLRefToGURL(const TemplateURLRef& ref,
-                          const SearchTermsData& search_terms_data,
-                          bool append_extra_query_params) {
+                          const SearchTermsData& search_terms_data) {
   TemplateURLRef::SearchTermsArgs search_terms_args =
       TemplateURLRef::SearchTermsArgs(base::string16());
-  search_terms_args.append_extra_query_params = append_extra_query_params;
   return GURL(ref.ReplaceSearchTerms(search_terms_args, search_terms_data));
 }
 
@@ -170,9 +169,8 @@
     if (!profile || !template_url)
       return NewTabURLDetails(local_url, NEW_TAB_URL_BAD);
 
-    GURL search_provider_url =
-        TemplateURLRefToGURL(template_url->new_tab_url_ref(),
-                             UIThreadSearchTermsData(profile), false);
+    GURL search_provider_url = TemplateURLRefToGURL(
+        template_url->new_tab_url_ref(), UIThreadSearchTermsData(profile));
 
     if (ShouldShowLocalNewTab(search_provider_url, profile))
       return NewTabURLDetails(local_url, NEW_TAB_URL_VALID);
@@ -195,22 +193,10 @@
   NewTabURLState state;
 };
 
-base::string16 ExtractSearchTermsFromURL(Profile* profile, const GURL& url) {
-  const TemplateURL* template_url =
-      GetDefaultSearchProviderTemplateURL(profile);
-  base::string16 search_terms;
-  if (template_url)
-    template_url->ExtractSearchTermsFromURL(
-        url, UIThreadSearchTermsData(profile), &search_terms);
-  return search_terms;
-}
-
 }  // namespace
 
 bool ShouldAssignURLToInstantRenderer(const GURL& url, Profile* profile) {
-  return url.is_valid() &&
-         profile &&
-         IsInstantExtendedAPIEnabled() &&
+  return url.is_valid() && profile && IsInstantExtendedAPIEnabled() &&
          (url.SchemeIs(chrome::kChromeSearchScheme) ||
           IsInstantURL(url, profile));
 }
@@ -218,7 +204,7 @@
 bool IsRenderedInInstantProcess(const content::WebContents* contents,
                                 Profile* profile) {
   const content::RenderProcessHost* process_host =
-      contents->GetRenderProcessHost();
+      contents->GetMainFrame()->GetProcess();
   if (!process_host)
     return false;
 
@@ -261,8 +247,8 @@
   if (!IsInstantExtendedAPIEnabled())
     return url == chrome::kChromeUINewTabURL;
 
-  const base::string16 search_terms = ExtractSearchTermsFromURL(profile, url);
-  return profile && ((IsInstantURL(url, profile) && search_terms.empty()) ||
+  // TODO(treib,sfiera): Tolerate query params when detecting local NTPs.
+  return profile && (IsInstantURL(url, profile) ||
                      url == chrome::kChromeSearchLocalNtpUrl);
 }
 
@@ -290,6 +276,7 @@
   if (!IsInstantExtendedAPIEnabled())
     return false;
 
+  // TODO(treib,sfiera): Tolerate query params when detecting local NTPs.
   if (url == chrome::kChromeSearchLocalNtpUrl)
     return true;
 
@@ -311,7 +298,7 @@
     return result;
   for (const TemplateURLRef& ref : template_url->url_refs()) {
     result.push_back(
-        TemplateURLRefToGURL(ref, UIThreadSearchTermsData(profile), false));
+        TemplateURLRefToGURL(ref, UIThreadSearchTermsData(profile)));
   }
   return result;
 }
diff --git a/chrome/browser/search/search_unittest.cc b/chrome/browser/search/search_unittest.cc
index b6b366c4..74fa2a9 100644
--- a/chrome/browser/search/search_unittest.cc
+++ b/chrome/browser/search/search_unittest.cc
@@ -4,6 +4,9 @@
 
 #include <stddef.h>
 
+#include <map>
+#include <memory>
+
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -22,6 +25,7 @@
 #include "components/search/search.h"
 #include "components/search_engines/template_url_service.h"
 #include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/site_instance.h"
@@ -69,7 +73,7 @@
     InstantService* instant_service =
         InstantServiceFactory::GetForProfile(profile());
     return instant_service->IsInstantProcess(
-        contents->GetRenderProcessHost()->GetID());
+        contents->GetMainFrame()->GetProcess()->GetID());
   }
 };
 
@@ -184,7 +188,7 @@
     const scoped_refptr<content::SiteInstance> start_site_instance =
         contents->GetSiteInstance();
     const content::RenderProcessHost* start_rph =
-        contents->GetRenderProcessHost();
+        contents->GetMainFrame()->GetProcess();
     const content::RenderViewHost* start_rvh =
         contents->GetRenderViewHost();
 
@@ -200,7 +204,7 @@
               start_rvh == contents->GetRenderViewHost())
         << test.description;
     EXPECT_EQ(test.same_site_instance,
-              start_rph == contents->GetRenderProcessHost())
+              start_rph == contents->GetMainFrame()->GetProcess())
         << test.description;
   }
 }
@@ -221,7 +225,7 @@
     const scoped_refptr<content::SiteInstance> start_site_instance =
         contents->GetSiteInstance();
     const content::RenderProcessHost* start_rph =
-        contents->GetRenderProcessHost();
+        contents->GetMainFrame()->GetProcess();
     const content::RenderViewHost* start_rvh =
         contents->GetRenderViewHost();
 
@@ -244,7 +248,7 @@
               start_rvh == contents->GetRenderViewHost())
         << test.description;
     EXPECT_EQ(test.same_site_instance,
-              start_rph == contents->GetRenderProcessHost())
+              start_rph == contents->GetMainFrame()->GetProcess())
         << test.description;
   }
 }
diff --git a/chrome/browser/search_provider_logos/logo_service_factory.cc b/chrome/browser/search_provider_logos/logo_service_factory.cc
index a31b727c..7c62218 100644
--- a/chrome/browser/search_provider_logos/logo_service_factory.cc
+++ b/chrome/browser/search_provider_logos/logo_service_factory.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/search_provider_logos/logo_service.h"
+#include "components/search_provider_logos/logo_service_impl.h"
 #include "net/url_request/url_request_context_getter.h"
 
 #if defined(OS_ANDROID)
@@ -18,6 +19,7 @@
 #endif
 
 using search_provider_logos::LogoService;
+using search_provider_logos::LogoServiceImpl;
 
 #if defined(OS_ANDROID)
 using chrome::android::GetIsChromeHomeEnabled;
@@ -59,8 +61,8 @@
 #else
   bool use_gray_background = false;
 #endif
-  return new LogoService(profile->GetPath().Append(kCachedLogoDirectory),
-                         TemplateURLServiceFactory::GetForProfile(profile),
-                         base::MakeUnique<suggestions::ImageDecoderImpl>(),
-                         profile->GetRequestContext(), use_gray_background);
+  return new LogoServiceImpl(profile->GetPath().Append(kCachedLogoDirectory),
+                             TemplateURLServiceFactory::GetForProfile(profile),
+                             base::MakeUnique<suggestions::ImageDecoderImpl>(),
+                             profile->GetRequestContext(), use_gray_background);
 }
diff --git a/chrome/browser/signin/account_reconcilor_unittest.cc b/chrome/browser/signin/account_reconcilor_unittest.cc
index ee039e0..5125b90 100644
--- a/chrome/browser/signin/account_reconcilor_unittest.cc
+++ b/chrome/browser/signin/account_reconcilor_unittest.cc
@@ -325,6 +325,7 @@
   const char* cookies;
   bool is_first_reconcile;
   const char* gaia_api_calls;
+  const char* tokens_after_reconcile;
   const char* cookies_after_reconcile;
 };
 
@@ -348,123 +349,123 @@
     // - API calls:
     //   X: Logout all accounts.
     //   A, B, C: Merge account.
-    // -------------------------------------------------------------------
-    // Tokens | Cookies | First Run | Gaia calls | Cookies after reconcile
-    // -------------------------------------------------------------------
+    // -------------------------------------------------------------------------
+    // Tokens | Cookies | First Run | Gaia calls | Tokens after | Cookies after
+    // -------------------------------------------------------------------------
 
     // First reconcile (Chrome restart): Rebuild the Gaia cookie to match the
     // tokens. Make the Sync account the default account in the Gaia cookie.
     // Sync enabled.
-    {  "*AB",   "AB",     true,       "",          "AB"},
-    {  "*AB",   "BA",     true,       "XAB",       "AB"},
-    {  "*AB",   "A",      true,       "B",         "AB"},
-    {  "*AB",   "B",      true,       "XAB",       "AB"},
-    {  "*AB",   "",       true,       "AB",        "AB"},
+    {  "*AB",   "AB",     true,       "",          "*AB",         "AB"},
+    {  "*AB",   "BA",     true,       "XAB",       "*AB",         "AB"},
+    {  "*AB",   "A",      true,       "B",         "*AB",         "AB"},
+    {  "*AB",   "B",      true,       "XAB",       "*AB",         "AB"},
+    {  "*AB",   "",       true,       "AB",        "*AB",         "AB"},
     // Sync enabled, token error on primary.
-    {  "*xAB",  "AB",     true,       "X",         ""},
-    {  "*xAB",  "BA",     true,       "XB",        "B"},
-    {  "*xAB",  "A",      true,       "X",         ""},
-    {  "*xAB",  "B",      true,       "",          "B"},
-    {  "*xAB",  "",       true,       "B",         "B"},
+    {  "*xAB",  "AB",     true,       "X",         "*xA",         ""},
+    {  "*xAB",  "BA",     true,       "XB",        "*xAB",        "B"},
+    {  "*xAB",  "A",      true,       "X",         "*xA",         ""},
+    {  "*xAB",  "B",      true,       "",          "*xAB",        "B"},
+    {  "*xAB",  "",       true,       "B",         "*xAB",        "B"},
     // Sync enabled, token error on secondary.
-    {  "*AxB",  "AB",     true,       "XA",        "A"},
-    {  "*AxB",  "BA",     true,       "XA",        "A"},
-    {  "*AxB",  "A",      true,       "",          "A"},
-    {  "*AxB",  "B",      true,       "XA",        "A"},
-    {  "*AxB",  "",       true,       "A",         "A"},
+    {  "*AxB",  "AB",     true,       "XA",        "*AxB",        "A"},
+    {  "*AxB",  "BA",     true,       "XA",        "*AxB",        "A"},
+    {  "*AxB",  "A",      true,       "",          "*AxB",        "A"},
+    {  "*AxB",  "B",      true,       "XA",        "*AxB",        "A"},
+    {  "*AxB",  "",       true,       "A",         "*AxB",        "A"},
     // Sync enabled, token error on both accounts.
-    {  "*xAxB", "AB",     true,       "X",         ""},
-    {  "*xAxB", "BA",     true,       "X",         ""},
-    {  "*xAxB", "A",      true,       "X",         ""},
-    {  "*xAxB", "B",      true,       "X",         ""},
-    {  "*xAxB", "",       true,       "",          ""},
+    {  "*xAxB", "AB",     true,       "X",         "*xAxB",       ""},
+    {  "*xAxB", "BA",     true,       "X",         "*xAxB",       ""},
+    {  "*xAxB", "A",      true,       "X",         "*xAxB",       ""},
+    {  "*xAxB", "B",      true,       "X",         "*xAxB",       ""},
+    {  "*xAxB", "",       true,       "",          "*xAxB",       ""},
     // Sync disabled.
-    {  "AB",    "AB",     true,       "",          "AB"},
-    {  "AB",    "BA",     true,       "",          "BA"},
-    {  "AB",    "A",      true,       "B",         "AB"},
-    {  "AB",    "B",      true,       "A",         "BA"},
-    {  "AB",    "",       true,       "AB",        "AB"},
+    {  "AB",    "AB",     true,       "",          "AB",          "AB"},
+    {  "AB",    "BA",     true,       "",          "AB",          "BA"},
+    {  "AB",    "A",      true,       "B",         "AB",          "AB"},
+    {  "AB",    "B",      true,       "A",         "AB",          "BA"},
+    {  "AB",    "",       true,       "AB",        "AB",          "AB"},
     // Sync disabled, token error on first account.
-    {  "xAB",   "AB",     true,       "XB",        "B"},
-    {  "xAB",   "BA",     true,       "XB",        "B"},
-    {  "xAB",   "A",      true,       "XB",        "B"},
-    {  "xAB",   "B",      true,       "",          "B"},
-    {  "xAB",   "",       true,       "B",         "B"},
-    // Sync disabled, token error on second account.
-    {  "AxB",   "AB",     true,       "XA",        "A"},
-    {  "AxB",   "BA",     true,       "XA",        "A"},
-    {  "AxB",   "A",      true,       "",          "A"},
-    {  "AxB",   "B",      true,       "XA",        "A"},
-    {  "AxB",   "",       true,       "A",         "A"},
+    {  "xAB",   "AB",     true,       "XB",        "xAB",         "B"},
+    {  "xAB",   "BA",     true,       "XB",        "xAB",         "B"},
+    {  "xAB",   "A",      true,       "XB",        "xAB",         "B"},
+    {  "xAB",   "B",      true,       "",          "xAB",         "B"},
+    {  "xAB",   "",       true,       "B",         "xAB",         "B"},
+    // Sync disabled, token error on second account       .
+    {  "AxB",   "AB",     true,       "XA",        "AxB",         "A"},
+    {  "AxB",   "BA",     true,       "XA",        "AxB",         "A"},
+    {  "AxB",   "A",      true,       "",          "AxB",         "A"},
+    {  "AxB",   "B",      true,       "XA",        "AxB",         "A"},
+    {  "AxB",   "",       true,       "A",         "AxB",         "A"},
     // Sync disabled, token error on both accounts.
-    {  "xAxB",  "AB",     true,       "X",         ""},
-    {  "xAxB",  "BA",     true,       "X",         ""},
-    {  "xAxB",  "A",      true,       "X",         ""},
-    {  "xAxB",  "B",      true,       "X",         ""},
-    {  "xAxB",  "",       true,       "",          ""},
+    {  "xAxB",  "AB",     true,       "X",         "xAxB",        ""},
+    {  "xAxB",  "BA",     true,       "X",         "xAxB",        ""},
+    {  "xAxB",  "A",      true,       "X",         "xAxB",        ""},
+    {  "xAxB",  "B",      true,       "X",         "xAxB",        ""},
+    {  "xAxB",  "",       true,       "",          "xAxB",        ""},
 
     // Chrome is running: Do not change the order of accounts already present in
     // the Gaia cookies.
     // Sync enabled.
-    {  "*AB",   "AB",     false,      "",          "AB"},
-    {  "*AB",   "BA",     false,      "",          "BA"},
-    {  "*AB",   "A",      false,      "B",         "AB"},
-    {  "*AB",   "B",      false,      "A",         "BA"},
-    {  "*AB",   "",       false,      "AB",        "AB"},
+    {  "*AB",   "AB",     false,      "",          "*AB",         "AB"},
+    {  "*AB",   "BA",     false,      "",          "*AB",         "BA"},
+    {  "*AB",   "A",      false,      "B",         "*AB",         "AB"},
+    {  "*AB",   "B",      false,      "A",         "*AB",         "BA"},
+    {  "*AB",   "",       false,      "AB",        "*AB",         "AB"},
     // Sync enabled, token error on primary.
-    {  "*xAB",  "AB",     false,      "X",         ""},
-    {  "*xAB",  "BA",     false,      "XB",        "B"},
-    {  "*xAB",  "A",      false,      "X",         ""},
-    {  "*xAB",  "B",      false,      "",          "B"},
-    {  "*xAB",  "",       false,      "B",         "B"},
+    {  "*xAB",  "AB",     false,      "X",         "*xA",         ""},
+    {  "*xAB",  "BA",     false,      "XB",        "*xAB",        "B"},
+    {  "*xAB",  "A",      false,      "X",         "*xA",         ""},
+    {  "*xAB",  "B",      false,      "",          "*xAB",        "B"},
+    {  "*xAB",  "",       false,      "B",         "*xAB",        "B"},
     // Sync enabled, token error on secondary.
-    {  "*AxB",  "AB",     false,      "XA",        "A"},
+    {  "*AxB",  "AB",     false,      "XA",        "*AxB",        "A"},
     // TODO(droger): consider doing XA:
-    {  "*AxB",  "BA",     false,      "X",         ""},
-    {  "*AxB",  "A",      false,      "",          "A"},
+    {  "*AxB",  "BA",     false,      "X",         "*AxB",        ""},
+    {  "*AxB",  "A",      false,      "",          "*AxB",        "A"},
     // TODO(droger): consider doing XA:
-    {  "*AxB",  "B",      false,      "X",         ""},
-    {  "*AxB",  "",       false,      "A",         "A"},
+    {  "*AxB",  "B",      false,      "X",         "*AxB",        ""},
+    {  "*AxB",  "",       false,      "A",         "*AxB",        "A"},
     // Sync enabled, token error on both accounts.
-    {  "*xAxB", "AB",     false,      "X",         ""},
-    {  "*xAxB", "BA",     false,      "X",         ""},
-    {  "*xAxB", "A",      false,      "X",         ""},
-    {  "*xAxB", "B",      false,      "X",         ""},
-    {  "*xAxB", "",       false,      "",          ""},
+    {  "*xAxB", "AB",     false,      "X",         "*xAxB",       ""},
+    {  "*xAxB", "BA",     false,      "X",         "*xAxB",       ""},
+    {  "*xAxB", "A",      false,      "X",         "*xAxB",       ""},
+    {  "*xAxB", "B",      false,      "X",         "*xAxB",       ""},
+    {  "*xAxB", "",       false,      "",          "*xAxB",       ""},
     // Sync disabled.
-    {  "AB",    "AB",     false,      "",          "AB"},
-    {  "AB",    "BA",     false,      "",          "BA"},
-    {  "AB",    "A",      false,      "B",         "AB"},
-    {  "AB",    "B",      false,      "A",         "BA"},
-    {  "AB",    "",       false,      "AB",        "AB"},
+    {  "AB",    "AB",     false,      "",          "AB",          "AB"},
+    {  "AB",    "BA",     false,      "",          "AB",          "BA"},
+    {  "AB",    "A",      false,      "B",         "AB",          "AB"},
+    {  "AB",    "B",      false,      "A",         "AB",          "BA"},
+    {  "AB",    "",       false,      "AB",        "AB",          "AB"},
     // Sync disabled, token error on first account.
-    {  "xAB",   "AB",     false,      "X",         ""},
-    {  "xAB",   "BA",     false,      "XB",        "B"},
-    {  "xAB",   "A",      false,      "X",         ""},
-    {  "xAB",   "B",      false,      "",          "B"},
-    {  "xAB",   "",       false,      "B",         "B"},
+    {  "xAB",   "AB",     false,      "X",         "xA",          ""},
+    {  "xAB",   "BA",     false,      "XB",        "xAB",         "B"},
+    {  "xAB",   "A",      false,      "X",         "xA",          ""},
+    {  "xAB",   "B",      false,      "",          "xAB",         "B"},
+    {  "xAB",   "",       false,      "B",         "xAB",         "B"},
     // Sync disabled, token error on second account.
-    {  "AxB",   "AB",     false,      "XA",        "A"},
-    {  "AxB",   "BA",     false,      "X",         ""},
-    {  "AxB",   "A",      false,      "",          "A"},
-    {  "AxB",   "B",      false,      "X",         ""},
-    {  "AxB",   "",       false,      "A",         "A"},
+    {  "AxB",   "AB",     false,      "XA",        "AxB",         "A"},
+    {  "AxB",   "BA",     false,      "X",         "xB",          ""},
+    {  "AxB",   "A",      false,      "",          "AxB",         "A"},
+    {  "AxB",   "B",      false,      "X",         "xB",          ""},
+    {  "AxB",   "",       false,      "A",         "AxB",         "A"},
     // Sync disabled, token error on both accounts.
-    {  "xAxB",  "AB",     false,      "X",         ""},
-    {  "xAxB",  "BA",     false,      "X",         ""},
-    {  "xAxB",  "A",      false,      "X",         ""},
-    {  "xAxB",  "B",      false,      "X",         ""},
-    {  "xAxB",  "",       false,      "",          ""},
+    {  "xAxB",  "AB",     false,      "X",         "xAxB",        ""},
+    {  "xAxB",  "BA",     false,      "X",         "xAxB",        ""},
+    {  "xAxB",  "A",      false,      "X",         "xAxB",        ""},
+    {  "xAxB",  "B",      false,      "X",         "xAxB",        ""},
+    {  "xAxB",  "",       false,      "",          "xAxB",        ""},
 
     // Miscellaneous cases.
     // Check that unknown Gaia accounts are signed out.
-    {  "",      "A",      true,       "X",         ""},
-    {  "",      "A",      false,      "X",         ""},
-    {  "*A",    "AB",     true,       "XA",        "A"},
-    {  "*A",    "AB",     false,      "XA",        "A"},
+    {  "",      "A",      true,       "X",         "",            ""},
+    {  "",      "A",      false,      "X",         "",            ""},
+    {  "*A",    "AB",     true,       "XA",        "*A",          "A"},
+    {  "*A",    "AB",     false,      "XA",        "*A",          "A"},
     // Check that Gaia default account is kept in first position.
-    {  "AB",    "BC",     true,       "XBA",       "BA"},
-    {  "AB",    "BC",     false,      "XBA",       "BA"},
+    {  "AB",    "BC",     true,       "XBA",       "AB",          "BA"},
+    {  "AB",    "BC",     false,      "XBA",       "AB",          "BA"},
 };
 // clang-format on
 
@@ -478,12 +479,63 @@
     std::string gaia_id;
   };
 
+  struct Token {
+    std::string gaia_id;
+    std::string email;
+    bool is_authenticated;
+    bool has_error;
+  };
+
   AccountReconcilorTestDice() {
     accounts_['A'] = {"a@gmail.com", "A"};
     accounts_['B'] = {"b@gmail.com", "B"};
     accounts_['C'] = {"c@gmail.com", "C"};
   }
 
+  // Build Tokens from string.
+  std::vector<Token> ParseTokenString(const char* token_string) {
+    std::vector<Token> parsed_tokens;
+    bool is_authenticated = false;
+    bool has_error = false;
+    for (int i = 0; token_string[i] != '\0'; ++i) {
+      char token_code = token_string[i];
+      if (token_code == '*') {
+        is_authenticated = true;
+        continue;
+      }
+      if (token_code == 'x') {
+        has_error = true;
+        continue;
+      }
+      parsed_tokens.push_back({accounts_[token_code].gaia_id,
+                               accounts_[token_code].email, is_authenticated,
+                               has_error});
+      is_authenticated = false;
+      has_error = false;
+    }
+    return parsed_tokens;
+  }
+
+  // Checks that the tokens in the TokenService match the tokens.
+  void VerifyCurrentTokens(const std::vector<Token>& tokens) {
+    EXPECT_EQ(token_service()->GetAccounts().size(), tokens.size());
+    bool authenticated_account_found = false;
+    for (const Token& token : tokens) {
+      std::string account_id =
+          PickAccountIdForAccount(token.gaia_id, token.email);
+      EXPECT_TRUE(token_service()->RefreshTokenIsAvailable(account_id));
+      EXPECT_EQ(
+          token.has_error,
+          token_service()->GetDelegate()->RefreshTokenHasError(account_id));
+      if (token.is_authenticated) {
+        EXPECT_EQ(account_id, signin_manager()->GetAuthenticatedAccountId());
+        authenticated_account_found = true;
+      }
+    }
+    if (!authenticated_account_found)
+      EXPECT_EQ("", signin_manager()->GetAuthenticatedAccountId());
+  }
+
   std::map<char, Account> accounts_;
 };
 
@@ -493,35 +545,22 @@
   signin::ScopedAccountConsistencyDice scoped_dice;
 
   // Setup tokens.
-  bool signin = false;
-  bool token_error = false;
-  for (int i = 0; GetParam().tokens[i] != '\0'; ++i) {
-    char token_code = GetParam().tokens[i];
-    if (token_code == '*') {
-      signin = true;
-      continue;
-    }
-    if (token_code == 'x') {
-      token_error = true;
-      continue;
-    }
-
-    std::string account_id = PickAccountIdForAccount(
-        accounts_[token_code].gaia_id, accounts_[token_code].email);
-    if (signin) {
-      ConnectProfileToAccount(accounts_[token_code].gaia_id,
-                              accounts_[token_code].email);
-      signin = false;
-    } else {
+  std::vector<Token> tokens_before_reconcile =
+      ParseTokenString(GetParam().tokens);
+  for (const Token& token : tokens_before_reconcile) {
+    std::string account_id =
+        PickAccountIdForAccount(token.gaia_id, token.email);
+    if (token.is_authenticated)
+      ConnectProfileToAccount(token.gaia_id, token.email);
+    else
       token_service()->UpdateCredentials(account_id, "refresh_token");
-    }
-    if (token_error) {
+    if (token.has_error) {
       token_service_delegate()->SetLastErrorForAccount(
           account_id, GoogleServiceAuthError(
                           GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
-      token_error = false;
     }
   }
+  VerifyCurrentTokens(tokens_before_reconcile);
 
   // Setup cookies.
   std::string cookies(GetParam().cookies);
@@ -583,6 +622,7 @@
   }
   ASSERT_FALSE(reconcilor->is_reconcile_started_);
   ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
+  VerifyCurrentTokens(ParseTokenString(GetParam().tokens_after_reconcile));
   // Another reconcile is sometimes triggered if Chrome accounts have changed.
   // Allow it to finish.
   cookie_manager_service()->SetListAccountsResponseNoAccounts();
diff --git a/chrome/browser/signin/signin_util.cc b/chrome/browser/signin/signin_util.cc
index 7932788..5c6103b 100644
--- a/chrome/browser/signin/signin_util.cc
+++ b/chrome/browser/signin/signin_util.cc
@@ -38,4 +38,8 @@
   SetForceSigninPolicy(enable);
 }
 
+void ResetForceSigninForTesting() {
+  g_is_force_signin_enabled_cache = NOT_CACHED;
+}
+
 }  // namespace signin_util
diff --git a/chrome/browser/signin/signin_util.h b/chrome/browser/signin/signin_util.h
index 0c6ad88f..be53b9d8 100644
--- a/chrome/browser/signin/signin_util.h
+++ b/chrome/browser/signin/signin_util.h
@@ -14,6 +14,9 @@
 // Enable or disable force sign in for testing.
 void SetForceSigninForTesting(bool enable);
 
+// Reset force sign in to uninitialized state for testing.
+void ResetForceSigninForTesting();
+
 }  // namespace signin_util
 
 #endif  // CHROME_BROWSER_SIGNIN_SIGNIN_UTIL_H_
diff --git a/chrome/browser/signin/signin_util_unittest.cc b/chrome/browser/signin/signin_util_unittest.cc
index 0233f99..840fa49 100644
--- a/chrome/browser/signin/signin_util_unittest.cc
+++ b/chrome/browser/signin/signin_util_unittest.cc
@@ -16,11 +16,15 @@
  public:
   void SetUp() override {
     BrowserWithTestWindowTest::SetUp();
+    signin_util::ResetForceSigninForTesting();
 
     prefs_.reset(new TestingPrefServiceSimple());
   }
 
-  void TearDown() override { BrowserWithTestWindowTest::TearDown(); }
+  void TearDown() override {
+    signin_util::ResetForceSigninForTesting();
+    BrowserWithTestWindowTest::TearDown();
+  }
 
   std::unique_ptr<TestingPrefServiceSimple> prefs_;
 };
diff --git a/chrome/browser/ssl/captive_portal_helper_android.cc b/chrome/browser/ssl/captive_portal_helper_android.cc
index 53f49607..4ddaf76 100644
--- a/chrome/browser/ssl/captive_portal_helper_android.cc
+++ b/chrome/browser/ssl/captive_portal_helper_android.cc
@@ -12,7 +12,7 @@
 namespace chrome {
 namespace android {
 
-void AddCaptivePortalCertificateForTesting(
+void SetCaptivePortalCertificateForTesting(
     JNIEnv* env,
     const base::android::JavaParamRef<jclass>& jcaller,
     const base::android::JavaParamRef<jstring>& jhash) {
@@ -28,6 +28,16 @@
                      std::move(config_proto)));
 }
 
+void SetOSReportsCaptivePortalForTesting(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jclass>& jcaller,
+    jboolean os_reports_captive_portal) {
+  content::BrowserThread::PostTask(
+      content::BrowserThread::UI, FROM_HERE,
+      base::BindOnce(SSLErrorHandler::SetOSReportsCaptivePortalForTesting,
+                     os_reports_captive_portal));
+}
+
 std::string GetCaptivePortalServerUrl(JNIEnv* env) {
   return base::android::ConvertJavaStringToUTF8(
       Java_CaptivePortalHelper_getCaptivePortalServerUrl(env));
diff --git a/chrome/browser/ssl/ssl_browser_tests.cc b/chrome/browser/ssl/ssl_browser_tests.cc
index 5b2f39b7..d2dad83 100644
--- a/chrome/browser/ssl/ssl_browser_tests.cc
+++ b/chrome/browser/ssl/ssl_browser_tests.cc
@@ -2127,7 +2127,8 @@
   observer.Wait();
 
   // Both tabs should have the same process.
-  EXPECT_EQ(tab1->GetRenderProcessHost(), tab2->GetRenderProcessHost());
+  EXPECT_EQ(tab1->GetMainFrame()->GetProcess(),
+            tab2->GetMainFrame()->GetProcess());
 
   // The new tab has insecure content.
   CheckAuthenticationBrokenState(tab2, CertError::NONE,
@@ -5052,6 +5053,36 @@
                                SSLErrorHandler::CAPTIVE_PORTAL_CERT_FOUND, 1);
 }
 
+IN_PROC_BROWSER_TEST_F(SSLUITest, OSReportsCaptivePortal) {
+  ASSERT_TRUE(https_server_mismatched_.Start());
+  base::HistogramTester histograms;
+
+  SSLErrorHandler::SetOSReportsCaptivePortalForTesting(true);
+
+  // Navigate to an unsafe page on the server. The captive portal interstitial
+  // should be displayed since the OS reports a captive portal status.
+  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
+  SSLInterstitialTimerObserver interstitial_timer_observer(tab);
+  ui_test_utils::NavigateToURL(
+      browser(), https_server_mismatched_.GetURL("/ssl/blank_page.html"));
+  content::WaitForInterstitialAttach(tab);
+
+  InterstitialPage* interstitial_page = tab->GetInterstitialPage();
+  ASSERT_EQ(CaptivePortalBlockingPage::kTypeForTesting,
+            interstitial_page->GetDelegateForTesting()->GetTypeForTesting());
+  EXPECT_FALSE(interstitial_timer_observer.timer_started());
+
+  // Check that the histogram for the captive portal cert was recorded.
+  histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 3);
+  histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
+                               SSLErrorHandler::HANDLE_ALL, 1);
+  histograms.ExpectBucketCount(
+      SSLErrorHandler::GetHistogramNameForTesting(),
+      SSLErrorHandler::SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE, 1);
+  histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
+                               SSLErrorHandler::OS_REPORTS_CAPTIVE_PORTAL, 1);
+}
+
 namespace {
 
 // SPKI hash to captive-portal.badssl.com leaf certificate. This
diff --git a/chrome/browser/ssl/ssl_error_handler.cc b/chrome/browser/ssl/ssl_error_handler.cc
index 3792635..61a6166 100644
--- a/chrome/browser/ssl/ssl_error_handler.cc
+++ b/chrome/browser/ssl/ssl_error_handler.cc
@@ -55,6 +55,10 @@
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
 #endif  // #if defined(OS_WIN)
 
+#if defined(OS_ANDROID)
+#include "net/android/network_library.h"
+#endif  // #if defined(OS_ANDROID)
+
 namespace {
 
 const base::Feature kMITMSoftwareInterstitial{
@@ -298,6 +302,9 @@
 
   bool IsEnterpriseManaged() const;
 
+  void SetOSReportsCaptivePortalForTesting(bool os_reports_captive_portal);
+  bool DoesOSReportCaptivePortalForTesting() const;
+
  private:
   base::TimeDelta interstitial_delay_;
 
@@ -324,6 +331,13 @@
   };
   EnterpriseManaged is_enterprise_managed_for_testing_;
 
+  enum OSCaptivePortalStatus {
+    OS_CAPTIVE_PORTAL_STATUS_NOT_SET,
+    OS_CAPTIVE_PORTAL_STATUS_BEHIND_PORTAL,
+    OS_CAPTIVE_PORTAL_STATUS_NOT_BEHIND_PORTAL,
+  };
+  OSCaptivePortalStatus os_captive_portal_status_for_testing_;
+
   // SPKI hashes belonging to certs treated as captive portals. Null until the
   // first time IsKnownCaptivePortalCert() or SetErrorAssistantProto()
   // is called.
@@ -333,7 +347,8 @@
 ConfigSingleton::ConfigSingleton()
     : interstitial_delay_(
           base::TimeDelta::FromMilliseconds(kInterstitialDelayInMilliseconds)),
-      is_enterprise_managed_for_testing_(ENTERPRISE_MANAGED_STATUS_NOT_SET) {}
+      is_enterprise_managed_for_testing_(ENTERPRISE_MANAGED_STATUS_NOT_SET),
+      os_captive_portal_status_for_testing_(OS_CAPTIVE_PORTAL_STATUS_NOT_SET) {}
 
 base::TimeDelta ConfigSingleton::interstitial_delay() const {
   return interstitial_delay_;
@@ -426,6 +441,17 @@
   return false;
 }
 
+void ConfigSingleton::SetOSReportsCaptivePortalForTesting(
+    bool os_reports_captive_portal) {
+  os_captive_portal_status_for_testing_ =
+      os_reports_captive_portal ? OS_CAPTIVE_PORTAL_STATUS_BEHIND_PORTAL
+                                : OS_CAPTIVE_PORTAL_STATUS_NOT_BEHIND_PORTAL;
+}
+
+bool ConfigSingleton::DoesOSReportCaptivePortalForTesting() const {
+  return os_captive_portal_status_for_testing_;
+}
+
 void ConfigSingleton::SetErrorAssistantProto(
     std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig> proto) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -570,6 +596,7 @@
 
   // SSLErrorHandler::Delegate methods:
   void CheckForCaptivePortal() override;
+  bool DoesOSReportCaptivePortal() override;
   bool GetSuggestedUrl(const std::vector<std::string>& dns_names,
                        GURL* suggested_url) const override;
   void CheckSuggestedUrl(
@@ -613,6 +640,14 @@
 #endif
 }
 
+bool SSLErrorHandlerDelegateImpl::DoesOSReportCaptivePortal() {
+#if defined(OS_ANDROID)
+  return net::android::GetIsCaptivePortal();
+#else
+  return false;
+#endif
+}
+
 bool SSLErrorHandlerDelegateImpl::GetSuggestedUrl(
     const std::vector<std::string>& dns_names,
     GURL* suggested_url) const {
@@ -762,6 +797,13 @@
   return g_config.Pointer()->GetErrorAssistantProtoVersionIdForTesting();
 }
 
+// static
+void SSLErrorHandler::SetOSReportsCaptivePortalForTesting(
+    bool os_reports_captive_portal) {
+  g_config.Pointer()->SetOSReportsCaptivePortalForTesting(
+      os_reports_captive_portal);
+}
+
 bool SSLErrorHandler::IsTimerRunningForTesting() const {
   return timer_.IsRunning();
 }
@@ -803,6 +845,18 @@
     return;
   }
 
+  // Ideally, a captive portal interstitial should only be displayed if the only
+  // SSL error is a name mismatch error. However, captive portal detector always
+  // opens a new tab if it detects a portal ignoring the types of SSL errors. To
+  // be consistent with captive portal detector, use the result of OS detection
+  // without checking only_error_is_name_mismatch.
+  if (g_config.Pointer()->DoesOSReportCaptivePortalForTesting() ||
+      delegate_->DoesOSReportCaptivePortal()) {
+    RecordUMA(OS_REPORTS_CAPTIVE_PORTAL);
+    ShowCaptivePortalInterstitial(GURL());
+    return;
+  }
+
   const bool only_error_is_name_mismatch =
       IsOnlyCertError(net::CERT_STATUS_COMMON_NAME_INVALID);
 
diff --git a/chrome/browser/ssl/ssl_error_handler.h b/chrome/browser/ssl/ssl_error_handler.h
index 2b3ef24..e7ca1e5 100644
--- a/chrome/browser/ssl/ssl_error_handler.h
+++ b/chrome/browser/ssl/ssl_error_handler.h
@@ -79,6 +79,7 @@
     CAPTIVE_PORTAL_CERT_FOUND = 9,
     WWW_MISMATCH_FOUND_IN_SAN = 10,
     SHOW_MITM_SOFTWARE_INTERSTITIAL = 11,
+    OS_REPORTS_CAPTIVE_PORTAL = 12,
     SSL_ERROR_HANDLER_EVENT_COUNT
   };
 
@@ -88,6 +89,7 @@
    public:
     virtual ~Delegate() {}
     virtual void CheckForCaptivePortal() = 0;
+    virtual bool DoesOSReportCaptivePortal() = 0;
     virtual bool GetSuggestedUrl(const std::vector<std::string>& dns_names,
                                  GURL* suggested_url) const = 0;
     virtual void CheckSuggestedUrl(
@@ -136,6 +138,8 @@
   static bool IsEnterpriseManagedFlagSetForTesting();
   static std::string GetHistogramNameForTesting();
   static int GetErrorAssistantProtoVersionIdForTesting();
+  static void SetOSReportsCaptivePortalForTesting(
+      bool os_reports_captive_portal);
   bool IsTimerRunningForTesting() const;
 
  protected:
diff --git a/chrome/browser/ssl/ssl_error_handler_unittest.cc b/chrome/browser/ssl/ssl_error_handler_unittest.cc
index 4c319d82..e8b52b4a 100644
--- a/chrome/browser/ssl/ssl_error_handler_unittest.cc
+++ b/chrome/browser/ssl/ssl_error_handler_unittest.cc
@@ -151,6 +151,7 @@
                               const net::SSLInfo& ssl_info)
       : profile_(profile),
         captive_portal_checked_(false),
+        os_reports_captive_portal_(false),
         suggested_url_exists_(false),
         suggested_url_checked_(false),
         ssl_interstitial_shown_(false),
@@ -199,9 +200,11 @@
 
   void set_suggested_url_exists() { suggested_url_exists_ = true; }
   void set_non_overridable_error() { is_overridable_error_ = false; }
+  void set_os_reports_captive_portal() { os_reports_captive_portal_ = true; }
 
   void ClearSeenOperations() {
     captive_portal_checked_ = false;
+    os_reports_captive_portal_ = false;
     suggested_url_exists_ = false;
     suggested_url_checked_ = false;
     ssl_interstitial_shown_ = false;
@@ -217,6 +220,10 @@
     captive_portal_checked_ = true;
   }
 
+  bool DoesOSReportCaptivePortal() override {
+    return os_reports_captive_portal_;
+  }
+
   bool GetSuggestedUrl(const std::vector<std::string>& dns_names,
                        GURL* suggested_url) const override {
     if (!suggested_url_exists_)
@@ -258,6 +265,7 @@
 
   Profile* profile_;
   bool captive_portal_checked_;
+  bool os_reports_captive_portal_;
   bool suggested_url_exists_;
   bool suggested_url_checked_;
   bool ssl_interstitial_shown_;
@@ -847,6 +855,28 @@
 
 #endif  // BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
 
+// Test that a captive portal interstitial is shown if the OS reports a portal.
+TEST_F(SSLErrorHandlerNameMismatchTest, OSReportsCaptivePortal) {
+  base::HistogramTester histograms;
+  delegate()->set_os_reports_captive_portal();
+
+  EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
+  error_handler()->StartHandlingError();
+  EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
+  EXPECT_FALSE(delegate()->captive_portal_checked());
+  EXPECT_FALSE(delegate()->ssl_interstitial_shown());
+  EXPECT_TRUE(delegate()->captive_portal_interstitial_shown());
+
+  histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 3);
+  histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
+                               SSLErrorHandler::HANDLE_ALL, 1);
+  histograms.ExpectBucketCount(
+      SSLErrorHandler::GetHistogramNameForTesting(),
+      SSLErrorHandler::SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE, 1);
+  histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
+                               SSLErrorHandler::OS_REPORTS_CAPTIVE_PORTAL, 1);
+}
+
 TEST_F(SSLErrorHandlerNameMismatchTest,
        ShouldShowSSLInterstitialOnTimerExpiredWhenSuggestedUrlExists) {
   base::HistogramTester histograms;
diff --git a/chrome/browser/sync/test/integration/sessions_helper.cc b/chrome/browser/sync/test/integration/sessions_helper.cc
index c308adb..80a4219 100644
--- a/chrome/browser/sync/test/integration/sessions_helper.cc
+++ b/chrome/browser/sync/test/integration/sessions_helper.cc
@@ -133,7 +133,7 @@
   open_url_params.source_render_frame_id =
       source_contents->GetMainFrame()->GetRoutingID();
   open_url_params.source_render_process_id =
-      source_contents->GetRenderProcessHost()->GetID();
+      source_contents->GetMainFrame()->GetProcess()->GetID();
 
   content::WebContents* new_contents =
       source_contents->OpenURL(open_url_params);
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index bd5e0f1..ff96c41 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -8,6 +8,7 @@
 import("//build/config/ui.gni")
 import("//build/split_static_library.gni")
 import("//chrome/common/features.gni")
+import("//components/nacl/features.gni")
 import("//components/signin/features.gni")
 import("//extensions/features/features.gni")
 import("//media/media_options.gni")
@@ -78,6 +79,8 @@
     "blocked_content/blocked_window_params.h",
     "blocked_content/popup_blocker_tab_helper.cc",
     "blocked_content/popup_blocker_tab_helper.h",
+    "blocked_content/popup_opener_tab_helper.cc",
+    "blocked_content/popup_opener_tab_helper.h",
     "blocked_content/popup_tracker.cc",
     "blocked_content/popup_tracker.h",
     "blocked_content/scoped_visibility_tracker.cc",
@@ -92,8 +95,6 @@
     "bookmarks/bookmark_utils.h",
     "bookmarks/recently_used_folders_combo_model.cc",
     "bookmarks/recently_used_folders_combo_model.h",
-    "browser_commands_chromeos.cc",
-    "browser_commands_chromeos.h",
     "browser_commands_mac.cc",
     "browser_commands_mac.h",
     "browser_dialogs.cc",
@@ -145,7 +146,6 @@
     "passwords/password_manager_presenter.h",
     "passwords/password_ui_view.h",
     "permission_bubble/permission_prompt.h",
-    "platform_keys_certificate_selector_chromeos.h",
     "prefs/prefs_tab_helper.cc",
     "prefs/prefs_tab_helper.h",
     "process_singleton_dialog_linux.h",
@@ -207,8 +207,6 @@
     "uninstall_browser_prompt.h",
     "validation_message_bubble.h",
     "view_ids.h",
-    "views/platform_keys_certificate_selector_chromeos.cc",
-    "views/platform_keys_certificate_selector_chromeos.h",
     "web_contents_sizer.h",
     "webui/about_ui.cc",
     "webui/about_ui.h",
@@ -216,125 +214,6 @@
     "webui/bluetooth_internals/bluetooth_internals_ui.h",
     "webui/chrome_web_ui_controller_factory.cc",
     "webui/chrome_web_ui_controller_factory.h",
-
-    # Chrome OS specific files (filtered out by GN on non chromeos platforms)
-    "webui/chromeos/bluetooth_dialog_localized_strings_provider.cc",
-    "webui/chromeos/bluetooth_dialog_localized_strings_provider.h",
-    "webui/chromeos/cryptohome_ui.cc",
-    "webui/chromeos/cryptohome_ui.h",
-    "webui/chromeos/cryptohome_web_ui_handler.cc",
-    "webui/chromeos/cryptohome_web_ui_handler.h",
-    "webui/chromeos/drive_internals_ui.cc",
-    "webui/chromeos/drive_internals_ui.h",
-    "webui/chromeos/first_run/first_run_actor.cc",
-    "webui/chromeos/first_run/first_run_actor.h",
-    "webui/chromeos/first_run/first_run_handler.cc",
-    "webui/chromeos/first_run/first_run_handler.h",
-    "webui/chromeos/first_run/first_run_ui.cc",
-    "webui/chromeos/first_run/first_run_ui.h",
-    "webui/chromeos/image_source.cc",
-    "webui/chromeos/image_source.h",
-    "webui/chromeos/keyboard_overlay_ui.cc",
-    "webui/chromeos/keyboard_overlay_ui.h",
-    "webui/chromeos/login/active_directory_password_change_screen_handler.cc",
-    "webui/chromeos/login/active_directory_password_change_screen_handler.h",
-    "webui/chromeos/login/app_launch_splash_screen_handler.cc",
-    "webui/chromeos/login/app_launch_splash_screen_handler.h",
-    "webui/chromeos/login/arc_kiosk_splash_screen_handler.cc",
-    "webui/chromeos/login/arc_kiosk_splash_screen_handler.h",
-    "webui/chromeos/login/arc_terms_of_service_screen_handler.cc",
-    "webui/chromeos/login/arc_terms_of_service_screen_handler.h",
-    "webui/chromeos/login/auto_enrollment_check_screen_handler.cc",
-    "webui/chromeos/login/auto_enrollment_check_screen_handler.h",
-    "webui/chromeos/login/base_screen_handler.cc",
-    "webui/chromeos/login/base_screen_handler.h",
-    "webui/chromeos/login/base_webui_handler.cc",
-    "webui/chromeos/login/base_webui_handler.h",
-    "webui/chromeos/login/controller_pairing_screen_handler.cc",
-    "webui/chromeos/login/controller_pairing_screen_handler.h",
-    "webui/chromeos/login/core_oobe_handler.cc",
-    "webui/chromeos/login/core_oobe_handler.h",
-    "webui/chromeos/login/device_disabled_screen_handler.cc",
-    "webui/chromeos/login/device_disabled_screen_handler.h",
-    "webui/chromeos/login/enable_debugging_screen_handler.cc",
-    "webui/chromeos/login/enable_debugging_screen_handler.h",
-    "webui/chromeos/login/encryption_migration_screen_handler.cc",
-    "webui/chromeos/login/encryption_migration_screen_handler.h",
-    "webui/chromeos/login/enrollment_screen_handler.cc",
-    "webui/chromeos/login/enrollment_screen_handler.h",
-    "webui/chromeos/login/error_screen_handler.cc",
-    "webui/chromeos/login/error_screen_handler.h",
-    "webui/chromeos/login/eula_screen_handler.cc",
-    "webui/chromeos/login/eula_screen_handler.h",
-    "webui/chromeos/login/gaia_screen_handler.cc",
-    "webui/chromeos/login/gaia_screen_handler.h",
-    "webui/chromeos/login/hid_detection_screen_handler.cc",
-    "webui/chromeos/login/hid_detection_screen_handler.h",
-    "webui/chromeos/login/host_pairing_screen_handler.cc",
-    "webui/chromeos/login/host_pairing_screen_handler.h",
-    "webui/chromeos/login/kiosk_app_menu_handler.cc",
-    "webui/chromeos/login/kiosk_app_menu_handler.h",
-    "webui/chromeos/login/kiosk_autolaunch_screen_handler.cc",
-    "webui/chromeos/login/kiosk_autolaunch_screen_handler.h",
-    "webui/chromeos/login/kiosk_enable_screen_handler.cc",
-    "webui/chromeos/login/kiosk_enable_screen_handler.h",
-    "webui/chromeos/login/l10n_util.cc",
-    "webui/chromeos/login/l10n_util.h",
-    "webui/chromeos/login/native_window_delegate.h",
-    "webui/chromeos/login/network_dropdown.cc",
-    "webui/chromeos/login/network_dropdown.h",
-    "webui/chromeos/login/network_dropdown_handler.cc",
-    "webui/chromeos/login/network_dropdown_handler.h",
-    "webui/chromeos/login/network_screen_handler.cc",
-    "webui/chromeos/login/network_screen_handler.h",
-    "webui/chromeos/login/network_state_informer.cc",
-    "webui/chromeos/login/network_state_informer.h",
-    "webui/chromeos/login/oobe_display_chooser.cc",
-    "webui/chromeos/login/oobe_display_chooser.h",
-    "webui/chromeos/login/oobe_ui.cc",
-    "webui/chromeos/login/oobe_ui.h",
-    "webui/chromeos/login/reset_screen_handler.cc",
-    "webui/chromeos/login/reset_screen_handler.h",
-    "webui/chromeos/login/screenlock_icon_provider.cc",
-    "webui/chromeos/login/screenlock_icon_provider.h",
-    "webui/chromeos/login/screenlock_icon_source.cc",
-    "webui/chromeos/login/screenlock_icon_source.h",
-    "webui/chromeos/login/signin_screen_handler.cc",
-    "webui/chromeos/login/signin_screen_handler.h",
-    "webui/chromeos/login/supervised_user_creation_screen_handler.cc",
-    "webui/chromeos/login/supervised_user_creation_screen_handler.h",
-    "webui/chromeos/login/terms_of_service_screen_handler.cc",
-    "webui/chromeos/login/terms_of_service_screen_handler.h",
-    "webui/chromeos/login/update_screen_handler.cc",
-    "webui/chromeos/login/update_screen_handler.h",
-    "webui/chromeos/login/user_board_screen_handler.cc",
-    "webui/chromeos/login/user_board_screen_handler.h",
-    "webui/chromeos/login/user_image_screen_handler.cc",
-    "webui/chromeos/login/user_image_screen_handler.h",
-    "webui/chromeos/login/voice_interaction_value_prop_screen_handler.cc",
-    "webui/chromeos/login/voice_interaction_value_prop_screen_handler.h",
-    "webui/chromeos/login/wait_for_container_ready_screen_handler.cc",
-    "webui/chromeos/login/wait_for_container_ready_screen_handler.h",
-    "webui/chromeos/login/wrong_hwid_screen_handler.cc",
-    "webui/chromeos/login/wrong_hwid_screen_handler.h",
-    "webui/chromeos/mobile_setup_dialog.cc",
-    "webui/chromeos/mobile_setup_dialog.h",
-    "webui/chromeos/mobile_setup_ui.cc",
-    "webui/chromeos/mobile_setup_ui.h",
-    "webui/chromeos/network_element_localized_strings_provider.cc",
-    "webui/chromeos/network_element_localized_strings_provider.h",
-    "webui/chromeos/network_ui.cc",
-    "webui/chromeos/network_ui.h",
-    "webui/chromeos/power_ui.cc",
-    "webui/chromeos/power_ui.h",
-    "webui/chromeos/set_time_ui.cc",
-    "webui/chromeos/set_time_ui.h",
-    "webui/chromeos/sim_unlock_ui.cc",
-    "webui/chromeos/sim_unlock_ui.h",
-    "webui/chromeos/slow_trace_ui.cc",
-    "webui/chromeos/slow_trace_ui.h",
-    "webui/chromeos/slow_ui.cc",
-    "webui/chromeos/slow_ui.h",
     "webui/components_ui.cc",
     "webui/components_ui.h",
     "webui/constrained_web_dialog_ui.cc",
@@ -446,8 +325,6 @@
     "webui/user_actions/user_actions_ui_handler.h",
     "webui/version_handler.cc",
     "webui/version_handler.h",
-    "webui/version_handler_chromeos.cc",
-    "webui/version_handler_chromeos.h",
     "webui/version_ui.cc",
     "webui/version_ui.h",
     "window_sizer/window_sizer_mac.mm",
@@ -635,7 +512,6 @@
     "//ui/content_accelerators",
     "//ui/display",
     "//ui/display/manager",
-    "//ui/events",
     "//ui/events:gesture_detection",
     "//ui/gfx",
     "//ui/gfx/geometry",
@@ -653,19 +529,6 @@
   ]
   allow_circular_includes_from = []
 
-  if (enable_extensions) {
-    deps += [
-      "//components/drive",
-      "//components/guest_view/browser",
-      "//extensions/browser",
-      "//extensions/strings",
-    ]
-  }
-
-  if (is_chromeos && use_cras) {
-    defines += [ "USE_CRAS" ]
-  }
-
   if (is_android || is_linux) {
     sources += [
       "webui/sandbox_internals_ui.cc",
@@ -803,7 +666,6 @@
       "//device/vr/features",
       "//ui/android",
     ]
-    deps -= [ "//ui/events" ]
   } else {
     # !is_android
     sources += [
@@ -980,9 +842,6 @@
       "scoped_tabbed_browser_displayer.h",
       "search/instant_controller.cc",
       "search/instant_controller.h",
-      "settings_window_manager_chromeos.cc",
-      "settings_window_manager_chromeos.h",
-      "settings_window_manager_observer_chromeos.h",
       "singleton_tabs.cc",
       "singleton_tabs.h",
       "startup/automation_infobar_delegate.cc",
@@ -1076,8 +935,6 @@
       "unload_controller_web_contents_delegate.h",
       "user_manager.cc",
       "user_manager.h",
-      "views/toolbar/media_router_action_platform_delegate_views.cc",
-      "views/toolbar/media_router_action_platform_delegate_views.h",
       "webui/app_launcher_login_handler.cc",
       "webui/app_launcher_login_handler.h",
       "webui/bookmarks_ui.cc",
@@ -1101,12 +958,8 @@
       "webui/foreign_session_handler.cc",
       "webui/foreign_session_handler.h",
       "webui/help/version_updater.h",
-      "webui/help/version_updater_chromeos.cc",
-      "webui/help/version_updater_chromeos.h",
       "webui/help/version_updater_mac.h",
       "webui/help/version_updater_mac.mm",
-      "webui/help/version_updater_win.cc",
-      "webui/help/version_updater_win.h",
       "webui/history_login_handler.cc",
       "webui/history_login_handler.h",
       "webui/identity_internals_ui.cc",
@@ -1187,34 +1040,6 @@
       "webui/settings/browser_lifetime_handler.h",
       "webui/settings/change_password_handler.cc",
       "webui/settings/change_password_handler.h",
-      "webui/settings/chromeos/accessibility_handler.cc",
-      "webui/settings/chromeos/accessibility_handler.h",
-      "webui/settings/chromeos/android_apps_handler.cc",
-      "webui/settings/chromeos/android_apps_handler.h",
-      "webui/settings/chromeos/change_picture_handler.cc",
-      "webui/settings/chromeos/change_picture_handler.h",
-      "webui/settings/chromeos/cups_printers_handler.cc",
-      "webui/settings/chromeos/cups_printers_handler.h",
-      "webui/settings/chromeos/date_time_handler.cc",
-      "webui/settings/chromeos/date_time_handler.h",
-      "webui/settings/chromeos/device_keyboard_handler.cc",
-      "webui/settings/chromeos/device_keyboard_handler.h",
-      "webui/settings/chromeos/device_pointer_handler.cc",
-      "webui/settings/chromeos/device_pointer_handler.h",
-      "webui/settings/chromeos/device_power_handler.cc",
-      "webui/settings/chromeos/device_power_handler.h",
-      "webui/settings/chromeos/device_storage_handler.cc",
-      "webui/settings/chromeos/device_storage_handler.h",
-      "webui/settings/chromeos/device_stylus_handler.cc",
-      "webui/settings/chromeos/device_stylus_handler.h",
-      "webui/settings/chromeos/easy_unlock_settings_handler.cc",
-      "webui/settings/chromeos/easy_unlock_settings_handler.h",
-      "webui/settings/chromeos/fingerprint_handler.cc",
-      "webui/settings/chromeos/fingerprint_handler.h",
-      "webui/settings/chromeos/google_assistant_handler.cc",
-      "webui/settings/chromeos/google_assistant_handler.h",
-      "webui/settings/chromeos/internet_handler.cc",
-      "webui/settings/chromeos/internet_handler.h",
       "webui/settings/custom_home_pages_table_model.cc",
       "webui/settings/custom_home_pages_table_model.h",
       "webui/settings/downloads_handler.cc",
@@ -1314,76 +1139,13 @@
       "//services/device/public/interfaces",
       "//third_party/libaddressinput",
       "//third_party/libaddressinput:strings",
-    ]
-
-    if (enable_extensions) {
-      deps += [
-        "//apps",
-        "//extensions/common:mojo",
-      ]
-
-      if (!is_mac) {
-        deps += [ "//apps/ui/views" ]
-      }
-    }
-
-    if (is_mac && !mac_views_browser) {
-      sources -= [
-        # This file is compiled on GYP but never referenced on Mac. Since it's
-        # in a static library, it never gets pulled in and we never try to link
-        # it (it doesn't link). In GN, source sets force us to get this rule
-        # correct.
-        "views/toolbar/media_router_action_platform_delegate_views.cc",
-        "views/toolbar/media_router_action_platform_delegate_views.h",
-      ]
-    }
-
-    if (is_chromeos || is_mac || is_win) {
-      sources += [
-        "webui/cast/cast_ui.cc",
-        "webui/cast/cast_ui.h",
-      ]
-    }
-  }
-
-  if (enable_basic_printing || enable_print_preview) {
-    deps += [ "//printing" ]
-  }
-
-  if (enable_nacl) {
-    sources += [
-      "webui/nacl_ui.cc",
-      "webui/nacl_ui.h",
-    ]
-    deps += [ "//components/nacl/browser" ]
-  }
-  if (enable_plugins) {
-    sources += [
-      "hung_plugin_tab_helper.cc",
-      "hung_plugin_tab_helper.h",
-      "webui/flash_ui.cc",
-      "webui/flash_ui.h",
-    ]
-    deps += [ "//ppapi/proxy:ipc" ]
-  }
-  if (safe_browsing_mode == 1) {
-    deps += [
-      "//chrome/browser/safe_browsing:chunk_proto",
-      "//chrome/common/safe_browsing:proto",
-      "//components/safe_browsing:csd_proto",
-    ]
-  }
-
-  if (is_chromeos && !is_official_build) {
-    sources += [
-      "webui/chromeos/emulator/device_emulator_message_handler.cc",
-      "webui/chromeos/emulator/device_emulator_message_handler.h",
-      "webui/chromeos/emulator/device_emulator_ui.cc",
-      "webui/chromeos/emulator/device_emulator_ui.h",
+      "//ui/events",
     ]
   }
 
   if (is_chromeos) {
+    assert(enable_extensions)
+    assert(toolkit_views)
     sources += [
       "app_list/search/launcher_search/launcher_search_icon_image_loader.cc",
       "app_list/search/launcher_search/launcher_search_icon_image_loader.h",
@@ -1401,34 +1163,199 @@
       "ash/session_controller_client.h",
       "ash/system_tray_client.cc",
       "ash/system_tray_client.h",
+      "browser_commands_chromeos.cc",
+      "browser_commands_chromeos.h",
       "extensions/extension_installed_notification.cc",
       "extensions/extension_installed_notification.h",
-      "input_method/input_method_engine_base.cc",
-      "input_method/input_method_engine_base.h",
+      "platform_keys_certificate_selector_chromeos.h",
+      "settings_window_manager_chromeos.cc",
+      "settings_window_manager_chromeos.h",
+      "settings_window_manager_observer_chromeos.h",
+      "views/apps/app_info_dialog/arc_app_info_links_panel.cc",
+      "views/apps/app_info_dialog/arc_app_info_links_panel.h",
       "views/apps/chrome_native_app_window_views_aura_ash.cc",
       "views/apps/chrome_native_app_window_views_aura_ash.h",
+      "views/chrome_views_delegate_chromeos.cc",
+      "views/extensions/request_file_system_dialog_view.cc",
+      "views/extensions/request_file_system_dialog_view.h",
+      "views/frame/native_browser_frame_factory_chromeos.cc",
+      "views/ime_driver/input_method_bridge_chromeos.cc",
+      "views/ime_driver/input_method_bridge_chromeos.h",
       "views/intent_picker_bubble_view.cc",
       "views/intent_picker_bubble_view.h",
+      "views/platform_keys_certificate_selector_chromeos.cc",
+      "views/platform_keys_certificate_selector_chromeos.h",
 
       # On chromeos, file manager extension handles the file open/save dialog.
       "views/select_file_dialog_extension.cc",
       "views/select_file_dialog_extension.h",
       "views/select_file_dialog_extension_factory.cc",
       "views/select_file_dialog_extension_factory.h",
+      "webui/chromeos/bluetooth_dialog_localized_strings_provider.cc",
+      "webui/chromeos/bluetooth_dialog_localized_strings_provider.h",
       "webui/chromeos/bluetooth_pairing_ui.cc",
       "webui/chromeos/bluetooth_pairing_ui.h",
       "webui/chromeos/certificate_manager_dialog_ui.cc",
       "webui/chromeos/certificate_manager_dialog_ui.h",
+      "webui/chromeos/cryptohome_ui.cc",
+      "webui/chromeos/cryptohome_ui.h",
+      "webui/chromeos/cryptohome_web_ui_handler.cc",
+      "webui/chromeos/cryptohome_web_ui_handler.h",
+      "webui/chromeos/drive_internals_ui.cc",
+      "webui/chromeos/drive_internals_ui.h",
+      "webui/chromeos/first_run/first_run_actor.cc",
+      "webui/chromeos/first_run/first_run_actor.h",
+      "webui/chromeos/first_run/first_run_handler.cc",
+      "webui/chromeos/first_run/first_run_handler.h",
+      "webui/chromeos/first_run/first_run_ui.cc",
+      "webui/chromeos/first_run/first_run_ui.h",
+      "webui/chromeos/image_source.cc",
+      "webui/chromeos/image_source.h",
+      "webui/chromeos/keyboard_overlay_ui.cc",
+      "webui/chromeos/keyboard_overlay_ui.h",
+      "webui/chromeos/login/active_directory_password_change_screen_handler.cc",
+      "webui/chromeos/login/active_directory_password_change_screen_handler.h",
+      "webui/chromeos/login/app_launch_splash_screen_handler.cc",
+      "webui/chromeos/login/app_launch_splash_screen_handler.h",
+      "webui/chromeos/login/arc_kiosk_splash_screen_handler.cc",
+      "webui/chromeos/login/arc_kiosk_splash_screen_handler.h",
+      "webui/chromeos/login/arc_terms_of_service_screen_handler.cc",
+      "webui/chromeos/login/arc_terms_of_service_screen_handler.h",
+      "webui/chromeos/login/auto_enrollment_check_screen_handler.cc",
+      "webui/chromeos/login/auto_enrollment_check_screen_handler.h",
+      "webui/chromeos/login/base_screen_handler.cc",
+      "webui/chromeos/login/base_screen_handler.h",
+      "webui/chromeos/login/base_webui_handler.cc",
+      "webui/chromeos/login/base_webui_handler.h",
+      "webui/chromeos/login/controller_pairing_screen_handler.cc",
+      "webui/chromeos/login/controller_pairing_screen_handler.h",
+      "webui/chromeos/login/core_oobe_handler.cc",
+      "webui/chromeos/login/core_oobe_handler.h",
+      "webui/chromeos/login/device_disabled_screen_handler.cc",
+      "webui/chromeos/login/device_disabled_screen_handler.h",
+      "webui/chromeos/login/enable_debugging_screen_handler.cc",
+      "webui/chromeos/login/enable_debugging_screen_handler.h",
+      "webui/chromeos/login/encryption_migration_screen_handler.cc",
+      "webui/chromeos/login/encryption_migration_screen_handler.h",
+      "webui/chromeos/login/enrollment_screen_handler.cc",
+      "webui/chromeos/login/enrollment_screen_handler.h",
+      "webui/chromeos/login/error_screen_handler.cc",
+      "webui/chromeos/login/error_screen_handler.h",
+      "webui/chromeos/login/eula_screen_handler.cc",
+      "webui/chromeos/login/eula_screen_handler.h",
+      "webui/chromeos/login/gaia_screen_handler.cc",
+      "webui/chromeos/login/gaia_screen_handler.h",
+      "webui/chromeos/login/hid_detection_screen_handler.cc",
+      "webui/chromeos/login/hid_detection_screen_handler.h",
+      "webui/chromeos/login/host_pairing_screen_handler.cc",
+      "webui/chromeos/login/host_pairing_screen_handler.h",
+      "webui/chromeos/login/kiosk_app_menu_handler.cc",
+      "webui/chromeos/login/kiosk_app_menu_handler.h",
+      "webui/chromeos/login/kiosk_autolaunch_screen_handler.cc",
+      "webui/chromeos/login/kiosk_autolaunch_screen_handler.h",
+      "webui/chromeos/login/kiosk_enable_screen_handler.cc",
+      "webui/chromeos/login/kiosk_enable_screen_handler.h",
+      "webui/chromeos/login/l10n_util.cc",
+      "webui/chromeos/login/l10n_util.h",
+      "webui/chromeos/login/native_window_delegate.h",
+      "webui/chromeos/login/network_dropdown.cc",
+      "webui/chromeos/login/network_dropdown.h",
+      "webui/chromeos/login/network_dropdown_handler.cc",
+      "webui/chromeos/login/network_dropdown_handler.h",
+      "webui/chromeos/login/network_screen_handler.cc",
+      "webui/chromeos/login/network_screen_handler.h",
+      "webui/chromeos/login/network_state_informer.cc",
+      "webui/chromeos/login/network_state_informer.h",
+      "webui/chromeos/login/oobe_display_chooser.cc",
+      "webui/chromeos/login/oobe_display_chooser.h",
+      "webui/chromeos/login/oobe_ui.cc",
+      "webui/chromeos/login/oobe_ui.h",
+      "webui/chromeos/login/reset_screen_handler.cc",
+      "webui/chromeos/login/reset_screen_handler.h",
+      "webui/chromeos/login/screenlock_icon_provider.cc",
+      "webui/chromeos/login/screenlock_icon_provider.h",
+      "webui/chromeos/login/screenlock_icon_source.cc",
+      "webui/chromeos/login/screenlock_icon_source.h",
+      "webui/chromeos/login/signin_screen_handler.cc",
+      "webui/chromeos/login/signin_screen_handler.h",
+      "webui/chromeos/login/supervised_user_creation_screen_handler.cc",
+      "webui/chromeos/login/supervised_user_creation_screen_handler.h",
+      "webui/chromeos/login/terms_of_service_screen_handler.cc",
+      "webui/chromeos/login/terms_of_service_screen_handler.h",
+      "webui/chromeos/login/update_screen_handler.cc",
+      "webui/chromeos/login/update_screen_handler.h",
+      "webui/chromeos/login/user_board_screen_handler.cc",
+      "webui/chromeos/login/user_board_screen_handler.h",
+      "webui/chromeos/login/user_image_screen_handler.cc",
+      "webui/chromeos/login/user_image_screen_handler.h",
+      "webui/chromeos/login/voice_interaction_value_prop_screen_handler.cc",
+      "webui/chromeos/login/voice_interaction_value_prop_screen_handler.h",
+      "webui/chromeos/login/wait_for_container_ready_screen_handler.cc",
+      "webui/chromeos/login/wait_for_container_ready_screen_handler.h",
+      "webui/chromeos/login/wrong_hwid_screen_handler.cc",
+      "webui/chromeos/login/wrong_hwid_screen_handler.h",
+      "webui/chromeos/mobile_setup_dialog.cc",
+      "webui/chromeos/mobile_setup_dialog.h",
+      "webui/chromeos/mobile_setup_ui.cc",
+      "webui/chromeos/mobile_setup_ui.h",
+      "webui/chromeos/network_element_localized_strings_provider.cc",
+      "webui/chromeos/network_element_localized_strings_provider.h",
+      "webui/chromeos/network_ui.cc",
+      "webui/chromeos/network_ui.h",
+      "webui/chromeos/power_ui.cc",
+      "webui/chromeos/power_ui.h",
       "webui/chromeos/proxy_settings_ui.cc",
       "webui/chromeos/proxy_settings_ui.h",
+      "webui/chromeos/set_time_ui.cc",
+      "webui/chromeos/set_time_ui.h",
+      "webui/chromeos/sim_unlock_ui.cc",
+      "webui/chromeos/sim_unlock_ui.h",
+      "webui/chromeos/slow_trace_ui.cc",
+      "webui/chromeos/slow_trace_ui.h",
+      "webui/chromeos/slow_ui.cc",
+      "webui/chromeos/slow_ui.h",
       "webui/chromeos/user_image_source.cc",
       "webui/chromeos/user_image_source.h",
+      "webui/extensions/chromeos/kiosk_apps_handler.cc",
+      "webui/extensions/chromeos/kiosk_apps_handler.h",
       "webui/help/help_utils_chromeos.cc",
       "webui/help/help_utils_chromeos.h",
+      "webui/help/version_updater_chromeos.cc",
+      "webui/help/version_updater_chromeos.h",
+      "webui/settings/chromeos/accessibility_handler.cc",
+      "webui/settings/chromeos/accessibility_handler.h",
+      "webui/settings/chromeos/android_apps_handler.cc",
+      "webui/settings/chromeos/android_apps_handler.h",
+      "webui/settings/chromeos/change_picture_handler.cc",
+      "webui/settings/chromeos/change_picture_handler.h",
+      "webui/settings/chromeos/cups_printers_handler.cc",
+      "webui/settings/chromeos/cups_printers_handler.h",
+      "webui/settings/chromeos/date_time_handler.cc",
+      "webui/settings/chromeos/date_time_handler.h",
+      "webui/settings/chromeos/device_keyboard_handler.cc",
+      "webui/settings/chromeos/device_keyboard_handler.h",
+      "webui/settings/chromeos/device_pointer_handler.cc",
+      "webui/settings/chromeos/device_pointer_handler.h",
+      "webui/settings/chromeos/device_power_handler.cc",
+      "webui/settings/chromeos/device_power_handler.h",
+      "webui/settings/chromeos/device_storage_handler.cc",
+      "webui/settings/chromeos/device_storage_handler.h",
+      "webui/settings/chromeos/device_stylus_handler.cc",
+      "webui/settings/chromeos/device_stylus_handler.h",
+      "webui/settings/chromeos/easy_unlock_settings_handler.cc",
+      "webui/settings/chromeos/easy_unlock_settings_handler.h",
+      "webui/settings/chromeos/fingerprint_handler.cc",
+      "webui/settings/chromeos/fingerprint_handler.h",
+      "webui/settings/chromeos/google_assistant_handler.cc",
+      "webui/settings/chromeos/google_assistant_handler.h",
+      "webui/settings/chromeos/internet_handler.cc",
+      "webui/settings/chromeos/internet_handler.h",
       "webui/sys_internals/sys_internals_message_handler.cc",
       "webui/sys_internals/sys_internals_message_handler.h",
       "webui/sys_internals/sys_internals_ui.cc",
       "webui/sys_internals/sys_internals_ui.h",
+      "webui/version_handler_chromeos.cc",
+      "webui/version_handler_chromeos.h",
     ]
     deps += [
       "//chrome/browser/chromeos",
@@ -1441,14 +1368,26 @@
       "//ui/chromeos",
       "//ui/chromeos/events",
     ]
+    allow_circular_includes_from = [ "//chrome/browser/chromeos" ]
+
     if (enable_rlz) {
       deps += [ "//chrome/browser:rlz" ]
     }
-    allow_circular_includes_from = [ "//chrome/browser/chromeos" ]
+
+    if (!is_official_build) {
+      sources += [
+        "webui/chromeos/emulator/device_emulator_message_handler.cc",
+        "webui/chromeos/emulator/device_emulator_message_handler.h",
+        "webui/chromeos/emulator/device_emulator_ui.cc",
+        "webui/chromeos/emulator/device_emulator_ui.h",
+      ]
+    }
+
+    if (use_cras) {
+      defines += [ "USE_CRAS" ]
+    }
   }
-  if (use_cups) {
-    configs += [ "//printing:cups" ]
-  }
+
   if (use_ash) {
     sources += [
       "ash/app_list/app_list_controller_ash.cc",
@@ -1581,6 +1520,7 @@
       "views/touch_uma/touch_uma.h",
     ]
   }
+
   if (toolkit_views) {
     sources += [
       "autofill/save_card_bubble_controller_impl.cc",
@@ -1606,14 +1546,8 @@
       "views/apps/app_info_dialog/app_info_permissions_panel.h",
       "views/apps/app_info_dialog/app_info_summary_panel.cc",
       "views/apps/app_info_dialog/app_info_summary_panel.h",
-      "views/apps/app_window_native_widget_mac.h",
-      "views/apps/app_window_native_widget_mac.mm",
       "views/apps/chrome_native_app_window_views.cc",
       "views/apps/chrome_native_app_window_views.h",
-      "views/apps/chrome_native_app_window_views_mac.h",
-      "views/apps/chrome_native_app_window_views_mac.mm",
-      "views/apps/native_app_window_frame_view_mac.h",
-      "views/apps/native_app_window_frame_view_mac.mm",
       "views/autofill/card_unmask_prompt_views.cc",
       "views/autofill/card_unmask_prompt_views.h",
       "views/autofill/save_card_bubble_views.cc",
@@ -1631,14 +1565,14 @@
       "views/chrome_constrained_window_views_client.h",
       "views/chrome_views_delegate.cc",
       "views/chrome_views_delegate.h",
-      "views/chrome_views_delegate_mac.cc",
-      "views/chrome_views_delegate_win.cc",
       "views/collected_cookies_views.cc",
       "views/collected_cookies_views.h",
       "views/confirm_bubble_views.cc",
       "views/confirm_bubble_views.h",
       "views/content_setting_bubble_contents.cc",
       "views/content_setting_bubble_contents.h",
+      "views/content_setting_domain_list_view.cc",
+      "views/content_setting_domain_list_view.h",
       "views/cookie_info_view.cc",
       "views/cookie_info_view.h",
       "views/device_chooser_content_view.cc",
@@ -1662,8 +1596,6 @@
       "views/extensions/extension_uninstall_dialog_view.cc",
       "views/first_run_bubble.cc",
       "views/first_run_bubble.h",
-      "views/frame/native_widget_mac_frameless_nswindow.h",
-      "views/frame/native_widget_mac_frameless_nswindow.mm",
       "views/fullscreen_control/fullscreen_control_host.cc",
       "views/fullscreen_control/fullscreen_control_host.h",
       "views/fullscreen_control/fullscreen_control_popup.cc",
@@ -1672,6 +1604,8 @@
       "views/fullscreen_control/fullscreen_control_view.h",
       "views/global_error_bubble_view.cc",
       "views/global_error_bubble_view.h",
+      "views/harmony/bulleted_label_list_view.cc",
+      "views/harmony/bulleted_label_list_view.h",
       "views/harmony/chrome_layout_provider.cc",
       "views/harmony/chrome_layout_provider.h",
       "views/harmony/chrome_typography.cc",
@@ -1789,88 +1723,40 @@
       "//services/ui/public/cpp/input_devices",
     ]
 
-    if (use_aura) {
-      deps += [ "//components/ui_devtools/views" ]
-    }
-
     allow_circular_includes_from += [ "//chrome/browser/ui/views" ]
 
-    if (enable_extensions) {
-      deps += [ "//extensions/components/native_app_window" ]
+    if (is_mac) {
+      sources += [
+        "views/apps/app_window_native_widget_mac.h",
+        "views/apps/app_window_native_widget_mac.mm",
+        "views/apps/chrome_native_app_window_views_mac.h",
+        "views/apps/chrome_native_app_window_views_mac.mm",
+        "views/apps/native_app_window_frame_view_mac.h",
+        "views/apps/native_app_window_frame_view_mac.mm",
+        "views/chrome_views_delegate_mac.cc",
+        "views/frame/native_widget_mac_frameless_nswindow.h",
+        "views/frame/native_widget_mac_frameless_nswindow.mm",
+      ]
+    } else {
+      sources += [
+        "views/create_application_shortcut_view.cc",
+        "views/create_application_shortcut_view.h",
+
+        # TODO(ellyjones): Mus is not supported on Mac (there is no ui::Window
+        # apart from aura::Window, which is also not supported).
+        "views/ime_driver/ime_driver_mus.cc",
+        "views/ime_driver/ime_driver_mus.h",
+        "views/ime_driver/remote_text_input_client.cc",
+        "views/ime_driver/remote_text_input_client.h",
+        "views/ime_driver/simple_input_method.cc",
+        "views/ime_driver/simple_input_method.h",
+        "views/tabs/window_finder_mus.cc",
+        "views/tabs/window_finder_mus.h",
+      ]
+
+      deps += [ "//ui/views/mus" ]
     }
 
-    if (is_chromeos) {
-      sources += [
-        "views/apps/app_info_dialog/arc_app_info_links_panel.cc",
-        "views/apps/app_info_dialog/arc_app_info_links_panel.h",
-      ]
-    } else if (!is_mac || mac_views_browser) {
-      sources += [
-        "views/frame/opaque_browser_frame_view.cc",
-        "views/frame/opaque_browser_frame_view.h",
-        "views/frame/opaque_browser_frame_view_layout.cc",
-        "views/frame/opaque_browser_frame_view_layout.h",
-        "views/frame/opaque_browser_frame_view_layout_delegate.h",
-        "views/frame/opaque_browser_frame_view_linux.cc",
-        "views/frame/opaque_browser_frame_view_linux.h",
-        "views/frame/opaque_browser_frame_view_platform_specific.cc",
-        "views/frame/opaque_browser_frame_view_platform_specific.h",
-        "views/outdated_upgrade_bubble_view.cc",
-        "views/outdated_upgrade_bubble_view.h",
-        "views/profiles/forced_reauthentication_dialog_view.cc",
-        "views/profiles/forced_reauthentication_dialog_view.h",
-        "views/profiles/profile_chooser_view.cc",
-        "views/profiles/profile_chooser_view.h",
-        "views/screen_capture_notification_ui_views.cc",
-        "views/sync/one_click_signin_dialog_view.cc",
-        "views/sync/one_click_signin_dialog_view.h",
-      ]
-    }
-
-    # These files do Gtk+-based theming, but Gtk+ is not available on
-    # Ozone builds, or on common environments where Ozone will be used.
-    #
-    # TODO(tonikitoo): It seems sensible to make it possible to opt-in
-    # the use of these files in case Gtk is available with its Wayland.
-    if (use_aura && !use_ozone && is_desktop_linux) {
-      sources += [
-        "views/chrome_browser_main_extra_parts_views_linux.cc",
-        "views/chrome_browser_main_extra_parts_views_linux.h",
-      ]
-    }
-    if (enable_extensions && (!is_mac || mac_views_browser)) {
-      sources += [
-        "views/extensions/browser_action_drag_data.cc",
-        "views/extensions/browser_action_drag_data.h",
-        "views/extensions/extension_action_platform_delegate_views.cc",
-        "views/extensions/extension_action_platform_delegate_views.h",
-        "views/extensions/extension_dialog.cc",
-        "views/extensions/extension_dialog.h",
-        "views/extensions/extension_dialog_observer.cc",
-        "views/extensions/extension_dialog_observer.h",
-        "views/extensions/extension_popup.cc",
-        "views/extensions/extension_popup.h",
-        "views/extensions/extension_view_views.cc",
-        "views/extensions/extension_view_views.h",
-        "views/extensions/media_galleries_dialog_views.cc",
-        "views/extensions/media_galleries_dialog_views.h",
-        "views/extensions/media_gallery_checkbox_view.cc",
-        "views/extensions/media_gallery_checkbox_view.h",
-      ]
-      if (use_aura) {
-        sources += [
-          "views/extensions/extension_popup_aura.cc",
-          "views/extensions/extension_popup_aura.h",
-        ]
-        deps += [ "//ui/wm/public" ]
-      }
-      if (is_chromeos) {
-        sources += [
-          "views/extensions/request_file_system_dialog_view.cc",
-          "views/extensions/request_file_system_dialog_view.h",
-        ]
-      }
-    }
     if (!is_mac || mac_views_browser) {
       sources += [
         "javascript_dialogs/javascript_dialog.cc",
@@ -1902,13 +1788,8 @@
         "views/bubble_anchor_util_views.cc",
         "views/certificate_selector.cc",
         "views/certificate_selector.h",
-        "views/certificate_viewer_win.cc",
         "views/chrome_javascript_native_dialog_factory_views.cc",
-        "views/chrome_views_delegate_chromeos.cc",
         "views/chrome_web_dialog_view.cc",
-        "views/color_chooser_win.cc",
-        "views/conflicting_module_view_win.cc",
-        "views/conflicting_module_view_win.h",
         "views/constrained_web_dialog_delegate_views.cc",
         "views/download/download_feedback_dialog_view.cc",
         "views/download/download_feedback_dialog_view.h",
@@ -1950,8 +1831,6 @@
         "views/frame/browser_view_layout.h",
         "views/frame/browser_view_layout_delegate.h",
         "views/frame/browser_window_factory.cc",
-        "views/frame/browser_window_property_manager_win.cc",
-        "views/frame/browser_window_property_manager_win.h",
         "views/frame/contents_layout_manager.cc",
         "views/frame/contents_layout_manager.h",
         "views/frame/contents_web_view.cc",
@@ -1961,20 +1840,13 @@
         "views/frame/immersive_mode_controller_factory_views.cc",
         "views/frame/immersive_mode_controller_stub.cc",
         "views/frame/immersive_mode_controller_stub.h",
-        "views/frame/minimize_button_metrics_win.cc",
-        "views/frame/minimize_button_metrics_win.h",
         "views/frame/native_browser_frame.h",
         "views/frame/native_browser_frame_factory.cc",
         "views/frame/native_browser_frame_factory.h",
-        "views/frame/native_browser_frame_factory_chromeos.cc",
-        "views/frame/system_menu_insertion_delegate_win.cc",
-        "views/frame/system_menu_insertion_delegate_win.h",
         "views/frame/system_menu_model_builder.cc",
         "views/frame/system_menu_model_builder.h",
         "views/frame/system_menu_model_delegate.cc",
         "views/frame/system_menu_model_delegate.h",
-        "views/frame/taskbar_decorator_win.cc",
-        "views/frame/taskbar_decorator_win.h",
         "views/frame/top_container_view.cc",
         "views/frame/top_container_view.h",
         "views/frame/web_contents_close_handler.cc",
@@ -2043,14 +1915,8 @@
         "views/ssl_client_certificate_selector.h",
         "views/status_bubble_views.cc",
         "views/status_bubble_views.h",
-        "views/status_icons/status_icon_win.cc",
-        "views/status_icons/status_icon_win.h",
         "views/status_icons/status_tray_linux.cc",
         "views/status_icons/status_tray_linux.h",
-        "views/status_icons/status_tray_state_changer_win.cc",
-        "views/status_icons/status_tray_state_changer_win.h",
-        "views/status_icons/status_tray_win.cc",
-        "views/status_icons/status_tray_win.h",
         "views/tab_dialogs_views.cc",
         "views/tab_dialogs_views.h",
         "views/tab_icon_view.cc",
@@ -2077,8 +1943,6 @@
         "views/tabs/tab_strip_layout.h",
         "views/tabs/window_finder.cc",
         "views/tabs/window_finder.h",
-        "views/tabs/window_finder_chromeos.cc",
-        "views/tabs/window_finder_win.cc",
         "views/theme_copying_widget.cc",
         "views/theme_copying_widget.h",
         "views/toolbar/app_menu.cc",
@@ -2092,6 +1956,8 @@
         "views/toolbar/extension_toolbar_menu_view.h",
         "views/toolbar/home_button.cc",
         "views/toolbar/home_button.h",
+        "views/toolbar/media_router_action_platform_delegate_views.cc",
+        "views/toolbar/media_router_action_platform_delegate_views.h",
         "views/toolbar/reload_button.cc",
         "views/toolbar/reload_button.h",
         "views/toolbar/toolbar_action_view.cc",
@@ -2117,43 +1983,47 @@
         ]
       }
 
-      if (is_win) {
-        sources += [
-          "views/try_chrome_dialog.cc",
-          "views/try_chrome_dialog.h",
-        ]
-      }
-
-      if (!is_mac) {
-        sources += [
-          "views/create_application_shortcut_view.cc",
-          "views/create_application_shortcut_view.h",
-
-          # TODO(ellyjones): Mus is not supported on Mac (there is no ui::Window
-          # apart from aura::Window, which is also not supported).
-          "views/ime_driver/ime_driver_mus.cc",
-          "views/ime_driver/ime_driver_mus.h",
-          "views/ime_driver/input_method_bridge_chromeos.cc",
-          "views/ime_driver/input_method_bridge_chromeos.h",
-          "views/ime_driver/remote_text_input_client.cc",
-          "views/ime_driver/remote_text_input_client.h",
-          "views/ime_driver/simple_input_method.cc",
-          "views/ime_driver/simple_input_method.h",
-          "views/tabs/window_finder_mus.cc",
-          "views/tabs/window_finder_mus.h",
-        ]
-
-        deps += [ "//ui/views/mus" ]
-      }
-
       if (!is_chromeos) {
         sources += [
+          "views/frame/opaque_browser_frame_view.cc",
+          "views/frame/opaque_browser_frame_view.h",
+          "views/frame/opaque_browser_frame_view_layout.cc",
+          "views/frame/opaque_browser_frame_view_layout.h",
+          "views/frame/opaque_browser_frame_view_layout_delegate.h",
+          "views/frame/opaque_browser_frame_view_linux.cc",
+          "views/frame/opaque_browser_frame_view_linux.h",
+          "views/frame/opaque_browser_frame_view_platform_specific.cc",
+          "views/frame/opaque_browser_frame_view_platform_specific.h",
+          "views/outdated_upgrade_bubble_view.cc",
+          "views/outdated_upgrade_bubble_view.h",
+          "views/profiles/forced_reauthentication_dialog_view.cc",
+          "views/profiles/forced_reauthentication_dialog_view.h",
+          "views/profiles/profile_chooser_view.cc",
+          "views/profiles/profile_chooser_view.h",
           "views/profiles/signin_view_controller_delegate_views.cc",
           "views/profiles/signin_view_controller_delegate_views.h",
+          "views/screen_capture_notification_ui_views.cc",
+          "views/sync/one_click_signin_dialog_view.cc",
+          "views/sync/one_click_signin_dialog_view.h",
         ]
       }
     }
 
+    if (is_desktop_linux) {
+      sources += [ "views/chrome_views_delegate_linux.cc" ]
+    }
+
+    if (is_win) {
+      sources += [ "views/chrome_views_delegate_win.cc" ]
+    }
+
+    if (is_win || is_desktop_linux) {
+      sources += [
+        "views/native_widget_factory.cc",
+        "views/native_widget_factory.h",
+      ]
+    }
+
     if (use_ash) {
       sources += [
         "views/frame/browser_frame_ash.cc",
@@ -2172,21 +2042,23 @@
       ]
     }
 
-    if (is_win || is_desktop_linux) {
-      sources += [
-        "views/chrome_views_delegate_linux.cc",
-        "views/native_widget_factory.cc",
-        "views/native_widget_factory.h",
-      ]
+    if (use_aura) {
+      deps += [ "//components/ui_devtools/views" ]
+
+      # These files do Gtk+-based theming, but Gtk+ is not available on
+      # Ozone builds, or on common environments where Ozone will be used.
+      #
+      # TODO(tonikitoo): It seems sensible to make it possible to opt-in
+      # the use of these files in case Gtk is available with its Wayland.
+      if (!use_ozone && is_desktop_linux) {
+        sources += [
+          "views/chrome_browser_main_extra_parts_views_linux.cc",
+          "views/chrome_browser_main_extra_parts_views_linux.h",
+        ]
+      }
     }
   }
-  if (use_gio) {
-    deps += [ "//build/linux/libgio" ]
-  }
-  if (use_aura && !use_ozone && is_desktop_linux) {
-    # This is the only component that can interact with gtk.
-    deps += [ "//chrome/browser/ui/libgtkui" ]
-  }
+
   if (is_win || is_mac || is_desktop_linux) {
     sources += [
       "avatar_button_error_controller.cc",
@@ -2212,10 +2084,6 @@
       "sync/one_click_signin_sync_starter.h",
       "views/external_protocol_dialog.cc",
       "views/external_protocol_dialog.h",
-      "views/frame/avatar_button_manager.cc",
-      "views/frame/avatar_button_manager.h",
-      "views/profiles/avatar_button.cc",
-      "views/profiles/avatar_button.h",
       "views/profiles/avatar_button_style.h",
       "webui/app_launcher_page_ui.cc",
       "webui/app_launcher_page_ui.h",
@@ -2259,28 +2127,43 @@
       "webui/welcome_ui.cc",
       "webui/welcome_ui.h",
     ]
+
+    if (is_mac && !mac_views_browser) {
+      sources += [
+        "startup/session_crashed_infobar_delegate.cc",
+        "startup/session_crashed_infobar_delegate.h",
+      ]
+    } else {
+      sources += [
+        "views/frame/avatar_button_manager.cc",
+        "views/frame/avatar_button_manager.h",
+        "views/profiles/avatar_button.cc",
+        "views/profiles/avatar_button.h",
+      ]
+    }
+
     if (enable_dice_support) {
       sources += [
         "webui/signin/signin_dice_internals_handler.cc",
         "webui/signin/signin_dice_internals_handler.h",
       ]
     }
-    if (is_mac && !mac_views_browser) {
-      sources -= [
-        # This is not explicitly excluded in GYP, but I think the static
-        # library linking rules means it's never referenced when compiling in
-        # non-Views mode on Mac. It appears not to link in that case.
-        "views/frame/avatar_button_manager.cc",
-        "views/frame/avatar_button_manager.h",
-        "views/profiles/avatar_button.cc",
-        "views/profiles/avatar_button.h",
-      ]
-      sources += [
-        "startup/session_crashed_infobar_delegate.cc",
-        "startup/session_crashed_infobar_delegate.h",
-      ]
-    }
   }
+
+  if (is_win || is_desktop_linux || is_chromeos) {
+    sources += [
+      "input_method/input_method_engine_base.cc",
+      "input_method/input_method_engine_base.h",
+    ]
+  }
+
+  if (is_win || is_desktop_linux) {
+    sources += [
+      "input_method/input_method_engine.cc",
+      "input_method/input_method_engine.h",
+    ]
+  }
+
   if (use_aura) {
     sources += [
       "aura/accessibility/automation_manager_aura.cc",
@@ -2345,6 +2228,7 @@
       "//ui/keyboard:resources",
       "//ui/wm",
     ]
+
     if (!is_chromeos) {
       sources += [
         "views/frame/browser_non_client_frame_view_factory_views.cc",
@@ -2357,60 +2241,20 @@
       ]
     }
   }
-  if (use_nss_certs) {
+
+  if (is_chromeos || is_mac || is_win) {
     sources += [
-      "crypto_module_delegate_nss.cc",
-      "crypto_module_delegate_nss.h",
-      "crypto_module_password_dialog_nss.cc",
-      "crypto_module_password_dialog_nss.h",
-      "webui/certificate_manager_localized_strings_provider.cc",
-      "webui/certificate_manager_localized_strings_provider.h",
-      "webui/certificates_handler.cc",
-      "webui/certificates_handler.h",
+      "webui/cast/cast_ui.cc",
+      "webui/cast/cast_ui.h",
     ]
   }
+
   if (is_mac || is_win) {
     sources += [
       "webui/settings/native_certificates_handler.cc",
       "webui/settings/native_certificates_handler.h",
     ]
   }
-  if (enable_print_preview) {
-    sources += [
-      "webui/print_preview/extension_printer_handler.cc",
-      "webui/print_preview/extension_printer_handler.h",
-      "webui/print_preview/pdf_printer_handler.cc",
-      "webui/print_preview/pdf_printer_handler.h",
-      "webui/print_preview/print_preview_handler.cc",
-      "webui/print_preview/print_preview_handler.h",
-      "webui/print_preview/print_preview_ui.cc",
-      "webui/print_preview/print_preview_ui.h",
-      "webui/print_preview/printer_capabilities.cc",
-      "webui/print_preview/printer_capabilities.h",
-      "webui/print_preview/printer_handler.cc",
-      "webui/print_preview/printer_handler.h",
-      "webui/print_preview/sticky_settings.cc",
-      "webui/print_preview/sticky_settings.h",
-    ]
-
-    if (enable_service_discovery) {
-      sources += [
-        "webui/print_preview/privet_printer_handler.cc",
-        "webui/print_preview/privet_printer_handler.h",
-      ]
-    }
-    if (is_chromeos) {
-      sources += [
-        "webui/print_preview/local_printer_handler_chromeos.cc",
-        "webui/print_preview/local_printer_handler_chromeos.h",
-      ]
-    } else {
-      sources += [
-        "webui/print_preview/local_printer_handler_default.cc",
-        "webui/print_preview/local_printer_handler_default.h",
-      ]
-    }
-  }
 
   if (is_mac) {
     sources += [
@@ -2513,6 +2357,8 @@
       "cocoa/profiles/profile_menu_controller.mm",
       "cocoa/renderer_context_menu/render_view_context_menu_mac.h",
       "cocoa/renderer_context_menu/render_view_context_menu_mac.mm",
+      "cocoa/scoped_menu_bar_lock.h",
+      "cocoa/scoped_menu_bar_lock.mm",
       "cocoa/status_icons/status_icon_mac.h",
       "cocoa/status_icons/status_icon_mac.mm",
       "cocoa/status_icons/status_tray_mac.h",
@@ -3160,6 +3006,7 @@
   }
 
   if (is_win) {
+    assert(toolkit_views)
     sources += [
       "desktop_ios_promotion/desktop_ios_promotion_bubble_controller.cc",
       "desktop_ios_promotion/desktop_ios_promotion_bubble_controller.h",
@@ -3172,16 +3019,16 @@
       "desktop_ios_promotion/sms_service.h",
       "desktop_ios_promotion/sms_service_factory.cc",
       "desktop_ios_promotion/sms_service_factory.h",
-      "input_method/input_method_engine.cc",
-      "input_method/input_method_engine.h",
-      "input_method/input_method_engine_base.cc",
-      "input_method/input_method_engine_base.h",
       "network_profile_bubble.cc",
       "network_profile_bubble.h",
+      "views/certificate_viewer_win.cc",
       "views/chrome_cleaner_dialog_win.cc",
       "views/chrome_cleaner_dialog_win.h",
       "views/color_chooser_dialog.cc",
       "views/color_chooser_dialog.h",
+      "views/color_chooser_win.cc",
+      "views/conflicting_module_view_win.cc",
+      "views/conflicting_module_view_win.h",
       "views/critical_notification_bubble_view.cc",
       "views/critical_notification_bubble_view.h",
       "views/desktop_ios_promotion/desktop_ios_promotion_bubble_view.cc",
@@ -3191,14 +3038,31 @@
       "views/frame/browser_desktop_window_tree_host.h",
       "views/frame/browser_desktop_window_tree_host_win.cc",
       "views/frame/browser_desktop_window_tree_host_win.h",
+      "views/frame/browser_window_property_manager_win.cc",
+      "views/frame/browser_window_property_manager_win.h",
       "views/frame/glass_browser_frame_view.cc",
       "views/frame/glass_browser_frame_view.h",
+      "views/frame/minimize_button_metrics_win.cc",
+      "views/frame/minimize_button_metrics_win.h",
       "views/frame/native_browser_frame_factory_aurawin.cc",
+      "views/frame/system_menu_insertion_delegate_win.cc",
+      "views/frame/system_menu_insertion_delegate_win.h",
+      "views/frame/taskbar_decorator_win.cc",
+      "views/frame/taskbar_decorator_win.h",
       "views/frame/windows_10_caption_button.cc",
       "views/frame/windows_10_caption_button.h",
       "views/network_profile_bubble_view.cc",
       "views/settings_reset_prompt_dialog.cc",
       "views/settings_reset_prompt_dialog.h",
+      "views/status_icons/status_icon_win.cc",
+      "views/status_icons/status_icon_win.h",
+      "views/status_icons/status_tray_state_changer_win.cc",
+      "views/status_icons/status_tray_state_changer_win.h",
+      "views/status_icons/status_tray_win.cc",
+      "views/status_icons/status_tray_win.h",
+      "views/tabs/window_finder_win.cc",
+      "views/try_chrome_dialog.cc",
+      "views/try_chrome_dialog.h",
       "views/uninstall_view.cc",
       "views/uninstall_view.h",
       "webui/conflicts_handler.cc",
@@ -3220,7 +3084,6 @@
     ]
     deps += [
       "//components/search_engines",
-      "//google_update",
       "//third_party/iaccessible2",
       "//third_party/isimpledom",
       "//third_party/libphonenumber",
@@ -3228,12 +3091,14 @@
       "//ui/base/ime",
       "//ui/events:dom_keycode_converter",
     ]
-    if (!is_chrome_branded) {
-      deps -= [ "//google_update" ]
-      sources -= [
+
+    if (is_chrome_branded) {
+      sources += [
         "webui/help/version_updater_win.cc",
         "webui/help/version_updater_win.h",
       ]
+      deps += [ "//google_update" ]
+    } else {
       sources += [
         "webui/help/version_updater_basic.cc",
         "webui/help/version_updater_basic.h",
@@ -3252,12 +3117,9 @@
       ]
     }
   }
+
   if (is_desktop_linux) {
     sources += [
-      "input_method/input_method_engine.cc",
-      "input_method/input_method_engine.h",
-      "input_method/input_method_engine_base.cc",
-      "input_method/input_method_engine_base.h",
       "views/apps/chrome_app_window_client_views_linux.cc",
       "views/first_run_dialog.cc",
       "views/first_run_dialog.h",
@@ -3285,6 +3147,13 @@
         "views/frame/native_browser_frame_factory_aurax11.cc",
         "views/javascript_app_modal_dialog_views_x11.cc",
         "views/javascript_app_modal_dialog_views_x11.h",
+        "views/javascript_app_modal_event_blocker_x11.cc",
+        "views/javascript_app_modal_event_blocker_x11.h",
+      ]
+      configs += [ "//build/config/linux:x11" ]
+      deps += [
+        "//ui/events/devices",
+        "//ui/events/devices/x11",
       ]
     }
     if (use_ozone) {
@@ -3292,8 +3161,14 @@
         "views/frame/browser_desktop_window_tree_host_ozone.cc",
         "views/frame/native_browser_frame_factory_ozone.cc",
       ]
+    } else {
+      if (use_aura) {
+        # This is the only component that can interact with gtk.
+        deps += [ "//chrome/browser/ui/libgtkui" ]
+      }
     }
   }
+
   if (is_linux) {  # Both desktop Linux and ChromeOS.
     sources += [
       "certificate_dialogs.cc",
@@ -3309,29 +3184,19 @@
         deps += [ "//dbus" ]
       }
     }
-    if (use_x11) {
-      sources += [
-        "views/javascript_app_modal_event_blocker_x11.cc",
-        "views/javascript_app_modal_event_blocker_x11.h",
-      ]
-      configs += [ "//build/config/linux:x11" ]
-      deps += [
-        "//ui/events/devices",
-        "//ui/events/devices/x11",
-      ]
-      if (is_desktop_linux) {
-        sources += [ "views/tabs/window_finder_x11.cc" ]
-      }
-    }
-    if (use_ozone) {
+
+    # WindowFinder implementation selection is a bit tricky, so do all here
+    # to get it right and prevent ODR violations.
+    if (is_chromeos) {
+      sources += [ "views/tabs/window_finder_chromeos.cc" ]
+    } else if (use_x11) {
+      sources += [ "views/tabs/window_finder_x11.cc" ]
+    } else {
+      assert(use_ozone)
       sources += [ "views/tabs/window_finder_ozone.cc" ]
     }
   }
 
-  if (use_udev) {
-    deps += [ "//device/udev_linux" ]
-  }
-
   if (enable_app_list) {
     sources += [
       "app_list/app_context_menu.cc",
@@ -3502,12 +3367,20 @@
       "app_list/app_list_service_disabled_mac.mm",
     ]
   }
+
   if (enable_extensions) {
     deps += [
+      "//apps",
       "//chrome/browser/apps",
       "//chrome/browser/extensions",
       "//chrome/common/extensions/api",
       "//chrome/common/extensions/api:api_registration",
+      "//components/drive",
+      "//components/guest_view/browser",
+      "//extensions/browser",
+      "//extensions/common:mojo",
+      "//extensions/components/native_app_window",
+      "//extensions/strings",
     ]
     allow_circular_includes_from += [
       "//chrome/browser/apps",
@@ -3544,20 +3417,106 @@
       "extensions/icon_with_badge_image_source.h",
       "extensions/settings_api_bubble_helpers.cc",
       "extensions/settings_api_bubble_helpers.h",
-      "webui/extensions/chromeos/kiosk_apps_handler.cc",
-      "webui/extensions/chromeos/kiosk_apps_handler.h",
       "webui/extensions/extension_basic_info.cc",
       "webui/extensions/extension_basic_info.h",
       "webui/extensions/extension_icon_source.cc",
       "webui/extensions/extension_icon_source.h",
     ]
+
+    if (!is_mac) {
+      deps += [ "//apps/ui/views" ]
+    }
+    if (!is_mac || mac_views_browser) {
+      sources += [
+        "views/extensions/browser_action_drag_data.cc",
+        "views/extensions/browser_action_drag_data.h",
+        "views/extensions/extension_action_platform_delegate_views.cc",
+        "views/extensions/extension_action_platform_delegate_views.h",
+        "views/extensions/extension_dialog.cc",
+        "views/extensions/extension_dialog.h",
+        "views/extensions/extension_dialog_observer.cc",
+        "views/extensions/extension_dialog_observer.h",
+        "views/extensions/extension_popup.cc",
+        "views/extensions/extension_popup.h",
+        "views/extensions/extension_view_views.cc",
+        "views/extensions/extension_view_views.h",
+        "views/extensions/media_galleries_dialog_views.cc",
+        "views/extensions/media_galleries_dialog_views.h",
+        "views/extensions/media_gallery_checkbox_view.cc",
+        "views/extensions/media_gallery_checkbox_view.h",
+      ]
+    }
+    if (use_aura) {
+      sources += [
+        "views/extensions/extension_popup_aura.cc",
+        "views/extensions/extension_popup_aura.h",
+      ]
+      deps += [ "//ui/wm/public" ]
+    }
   }
-  if (enable_webrtc) {
+
+  if (enable_nacl) {
     sources += [
-      "webui/media/webrtc_logs_ui.cc",
-      "webui/media/webrtc_logs_ui.h",
+      "webui/nacl_ui.cc",
+      "webui/nacl_ui.h",
     ]
+    deps += [ "//components/nacl/browser" ]
   }
+
+  if (enable_plugins) {
+    sources += [
+      "hung_plugin_tab_helper.cc",
+      "hung_plugin_tab_helper.h",
+      "webui/flash_ui.cc",
+      "webui/flash_ui.h",
+    ]
+    deps += [ "//ppapi/proxy:ipc" ]
+  }
+
+  if (enable_basic_printing || enable_print_preview) {
+    deps += [ "//printing" ]
+    if (use_cups) {
+      configs += [ "//printing:cups" ]
+    }
+  }
+  if (enable_print_preview) {
+    sources += [
+      "webui/print_preview/extension_printer_handler.cc",
+      "webui/print_preview/extension_printer_handler.h",
+      "webui/print_preview/pdf_printer_handler.cc",
+      "webui/print_preview/pdf_printer_handler.h",
+      "webui/print_preview/print_preview_handler.cc",
+      "webui/print_preview/print_preview_handler.h",
+      "webui/print_preview/print_preview_ui.cc",
+      "webui/print_preview/print_preview_ui.h",
+      "webui/print_preview/printer_capabilities.cc",
+      "webui/print_preview/printer_capabilities.h",
+      "webui/print_preview/printer_handler.cc",
+      "webui/print_preview/printer_handler.h",
+      "webui/print_preview/sticky_settings.cc",
+      "webui/print_preview/sticky_settings.h",
+    ]
+
+    if (is_chromeos) {
+      sources += [
+        "webui/print_preview/local_printer_handler_chromeos.cc",
+        "webui/print_preview/local_printer_handler_chromeos.h",
+      ]
+    } else {
+      sources += [
+        "webui/print_preview/local_printer_handler_default.cc",
+        "webui/print_preview/local_printer_handler_default.h",
+      ]
+    }
+
+    if (enable_service_discovery) {
+      sources += [
+        "webui/print_preview/privet_printer_handler.cc",
+        "webui/print_preview/privet_printer_handler.h",
+      ]
+    }
+  }
+
   if (enable_service_discovery) {
     sources += [
       "webui/local_discovery/local_discovery_ui.cc",
@@ -3566,6 +3525,42 @@
       "webui/local_discovery/local_discovery_ui_handler.h",
     ]
   }
+
+  if (enable_webrtc) {
+    sources += [
+      "webui/media/webrtc_logs_ui.cc",
+      "webui/media/webrtc_logs_ui.h",
+    ]
+  }
+
+  if (safe_browsing_mode == 1) {
+    deps += [
+      "//chrome/browser/safe_browsing:chunk_proto",
+      "//chrome/common/safe_browsing:proto",
+      "//components/safe_browsing:csd_proto",
+    ]
+  }
+
+  if (use_gio) {
+    deps += [ "//build/linux/libgio" ]
+  }
+
+  if (use_nss_certs) {
+    sources += [
+      "crypto_module_delegate_nss.cc",
+      "crypto_module_delegate_nss.h",
+      "crypto_module_password_dialog_nss.cc",
+      "crypto_module_password_dialog_nss.h",
+      "webui/certificate_manager_localized_strings_provider.cc",
+      "webui/certificate_manager_localized_strings_provider.h",
+      "webui/certificates_handler.cc",
+      "webui/certificates_handler.h",
+    ]
+  }
+
+  if (use_udev) {
+    deps += [ "//device/udev_linux" ]
+  }
 }
 
 # In GYP this is part of test_support_common.
diff --git a/chrome/browser/ui/ash/chrome_keyboard_ui.cc b/chrome/browser/ui/ash/chrome_keyboard_ui.cc
index add326e..bf563851 100644
--- a/chrome/browser/ui/ash/chrome_keyboard_ui.cc
+++ b/chrome/browser/ui/ash/chrome_keyboard_ui.cc
@@ -27,6 +27,8 @@
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/common/bindings_policy.h"
+#include "extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h"
+#include "extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/view_type_utils.h"
@@ -230,6 +232,13 @@
     router->BroadcastEvent(std::move(event));
   }
 
+  void OnKeyboardConfigChanged() override {
+    extensions::VirtualKeyboardAPI* api =
+        extensions::BrowserContextKeyedAPIFactory<
+            extensions::VirtualKeyboardAPI>::Get(context_);
+    api->delegate()->OnKeyboardConfigChanged();
+  }
+
  private:
   content::BrowserContext* context_;
 
diff --git a/chrome/browser/ui/ash/chrome_new_window_client.cc b/chrome/browser/ui/ash/chrome_new_window_client.cc
index 92e099f..246e81c 100644
--- a/chrome/browser/ui/ash/chrome_new_window_client.cc
+++ b/chrome/browser/ui/ash/chrome_new_window_client.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/extensions/api/terminal/terminal_extension_helper.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_util.h"
+#include "chrome/browser/prefs/incognito_mode_prefs.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/sessions/tab_restore_service_factory.h"
 #include "chrome/browser/ui/ash/chrome_shell_delegate.h"
@@ -35,12 +36,21 @@
 
 namespace {
 
+ChromeNewWindowClient* g_instance = nullptr;
+
 void RestoreTabUsingProfile(Profile* profile) {
   sessions::TabRestoreService* service =
       TabRestoreServiceFactory::GetForProfile(profile);
   service->RestoreMostRecentEntry(nullptr);
 }
 
+bool IsIncognitoAllowed() {
+  Profile* profile = ProfileManager::GetActiveUserProfile();
+  return profile && profile->GetProfileType() != Profile::GUEST_PROFILE &&
+         IncognitoModePrefs::GetAvailability(profile->GetPrefs()) !=
+             IncognitoModePrefs::DISABLED;
+}
+
 }  // namespace
 
 ChromeNewWindowClient::ChromeNewWindowClient() : binding_(this) {
@@ -52,9 +62,20 @@
   ash::mojom::NewWindowClientAssociatedPtrInfo ptr_info;
   binding_.Bind(mojo::MakeRequest(&ptr_info));
   new_window_controller_->SetClient(std::move(ptr_info));
+
+  DCHECK(!g_instance);
+  g_instance = this;
 }
 
-ChromeNewWindowClient::~ChromeNewWindowClient() {}
+ChromeNewWindowClient::~ChromeNewWindowClient() {
+  DCHECK_EQ(g_instance, this);
+  g_instance = nullptr;
+}
+
+// static
+ChromeNewWindowClient* ChromeNewWindowClient::Get() {
+  return g_instance;
+}
 
 // TabRestoreHelper is used to restore a tab. In particular when the user
 // attempts to a restore a tab if the TabRestoreService hasn't finished loading
@@ -118,6 +139,9 @@
 }
 
 void ChromeNewWindowClient::NewWindow(bool is_incognito) {
+  if (is_incognito && !IsIncognitoAllowed())
+    return;
+
   Browser* browser = chrome::FindBrowserWithActiveWindow();
   Profile* profile = (browser && browser->profile())
                          ? browser->profile()->GetOriginalProfile()
diff --git a/chrome/browser/ui/ash/chrome_new_window_client.h b/chrome/browser/ui/ash/chrome_new_window_client.h
index f8bcb0f..57c6a22 100644
--- a/chrome/browser/ui/ash/chrome_new_window_client.h
+++ b/chrome/browser/ui/ash/chrome_new_window_client.h
@@ -16,6 +16,8 @@
   ChromeNewWindowClient();
   ~ChromeNewWindowClient() override;
 
+  static ChromeNewWindowClient* Get();
+
   // Overridden from ash::mojom::NewWindowClient:
   void NewTab() override;
   void NewWindow(bool incognito) override;
diff --git a/chrome/browser/ui/ash/chrome_new_window_client_browsertest.cc b/chrome/browser/ui/ash/chrome_new_window_client_browsertest.cc
index dfefd56..ea52ecf 100644
--- a/chrome/browser/ui/ash/chrome_new_window_client_browsertest.cc
+++ b/chrome/browser/ui/ash/chrome_new_window_client_browsertest.cc
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/new_window_controller.h"
-#include "ash/shell.h"
+#include "chrome/browser/ui/ash/chrome_new_window_client.h"
+
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/prefs/incognito_mode_prefs.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
@@ -48,7 +49,7 @@
   Profile* profile1 = ProfileManager::GetActiveUserProfile();
   Browser* browser1 = CreateBrowser(profile1);
   // The newly created window should be created for the current active profile.
-  ash::Shell::Get()->new_window_controller()->NewWindow(false);
+  ChromeNewWindowClient::Get()->NewWindow(false /* incognito */);
   EXPECT_EQ(GetLastActiveBrowser()->profile(), profile1);
 
   // Login another user and make sure the current active user changes.
@@ -59,25 +60,45 @@
   Browser* browser2 = CreateBrowser(profile2);
   // The newly created window should be created for the current active window's
   // profile, which is |profile2|.
-  ash::Shell::Get()->new_window_controller()->NewWindow(false);
+  ChromeNewWindowClient::Get()->NewWindow(false /* incognito */);
   EXPECT_EQ(GetLastActiveBrowser()->profile(), profile2);
 
   // After activating |browser1|, the newly created window should be created
   // against |browser1|'s profile.
   browser1->window()->Show();
-  ash::Shell::Get()->new_window_controller()->NewWindow(false);
+  ChromeNewWindowClient::Get()->NewWindow(false /* incognito */);
   EXPECT_EQ(GetLastActiveBrowser()->profile(), profile1);
 
   // Test for incognito windows.
   // The newly created incoginito window should be created against the current
   // active |browser1|'s profile.
   browser1->window()->Show();
-  ash::Shell::Get()->new_window_controller()->NewWindow(true);
+  ChromeNewWindowClient::Get()->NewWindow(true /* incognito */);
   EXPECT_EQ(GetLastActiveBrowser()->profile()->GetOriginalProfile(), profile1);
 
   // The newly created incoginito window should be created against the current
   // active |browser2|'s profile.
   browser2->window()->Show();
-  ash::Shell::Get()->new_window_controller()->NewWindow(true);
+  ChromeNewWindowClient::Get()->NewWindow(true /* incognito */);
   EXPECT_EQ(GetLastActiveBrowser()->profile()->GetOriginalProfile(), profile2);
 }
+
+IN_PROC_BROWSER_TEST_F(ChromeNewWindowClientBrowserTest, IncognitoDisabled) {
+  CreateAndStartUserSession(AccountId::FromUserEmail(kTestUserName1));
+  Profile* profile = ProfileManager::GetActiveUserProfile();
+  EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
+
+  // Disabling incognito mode disables creation of new incognito windows.
+  IncognitoModePrefs::SetAvailability(profile->GetPrefs(),
+                                      IncognitoModePrefs::DISABLED);
+  ChromeNewWindowClient::Get()->NewWindow(true /* incognito */);
+  EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
+
+  // Enabling incognito mode enables creation of new incognito windows.
+  IncognitoModePrefs::SetAvailability(profile->GetPrefs(),
+                                      IncognitoModePrefs::ENABLED);
+  ChromeNewWindowClient::Get()->NewWindow(true /* incognito */);
+  EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
+  EXPECT_EQ(Profile::INCOGNITO_PROFILE,
+            GetLastActiveBrowser()->profile()->GetProfileType());
+}
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc
index 7a99f1a..5f32ac4 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -363,10 +363,6 @@
   return content::ServiceManagerConnection::GetForProcess()->GetConnector();
 }
 
-bool ChromeShellDelegate::IsIncognitoAllowed() const {
-  return AccessibilityManager::Get()->IsIncognitoAllowed();
-}
-
 bool ChromeShellDelegate::IsRunningInForcedAppMode() const {
   return chrome::IsRunningInForcedAppMode();
 }
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.h b/chrome/browser/ui/ash/chrome_shell_delegate.h
index acfeb49..55a19855 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.h
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.h
@@ -30,7 +30,6 @@
 
   // ash::ShellDelegate overrides;
   service_manager::Connector* GetShellConnector() const override;
-  bool IsIncognitoAllowed() const override;
   bool IsRunningInForcedAppMode() const override;
   bool CanShowWindowForUser(aura::Window* window) const override;
   bool IsForceMaximizeOnFirstRun() const override;
diff --git a/chrome/browser/ui/ash/keyboard_end_to_end_browsertest.cc b/chrome/browser/ui/ash/keyboard_end_to_end_browsertest.cc
index 621a4a3..e40f821 100644
--- a/chrome/browser/ui/ash/keyboard_end_to_end_browsertest.cc
+++ b/chrome/browser/ui/ash/keyboard_end_to_end_browsertest.cc
@@ -16,13 +16,10 @@
 #include "ui/keyboard/keyboard_controller.h"
 #include "ui/keyboard/keyboard_switches.h"
 #include "ui/keyboard/keyboard_test_util.h"
+#include "ui/keyboard/keyboard_util.h"
 
 namespace {
 
-bool IsKeyboardVisible() {
-  return keyboard::KeyboardController::GetInstance()->keyboard_visible();
-}
-
 // Simulates a click on the middle of the DOM element with the given |id|.
 void ClickElementWithId(content::WebContents* web_contents,
                         const std::string& id) {
diff --git a/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc b/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc
index 705520f..a63cf93 100644
--- a/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc
@@ -256,7 +256,7 @@
   }
 
   ash::ShelfItemDelegate* GetShelfItemDelegate(const std::string& id) {
-    ash::ShelfModel* model = ash::Shell::Get()->shelf_model();
+    auto* model = ChromeLauncherController::instance()->shelf_model();
     return model->GetShelfItemDelegate(ash::ShelfID(id));
   }
 
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
index e46e1ca..c60f819 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
@@ -50,6 +50,7 @@
 #include "chrome/browser/ui/ash/launcher/multi_profile_browser_status_monitor.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
+#include "chrome/browser/ui/ash/session_controller_client.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_list.h"
@@ -231,8 +232,7 @@
 
   // On Chrome OS using multi profile we want to switch the content of the shelf
   // with a user change. Note that for unit tests the instance can be NULL.
-  if (chrome::MultiUserWindowManager::GetMultiProfileMode() !=
-      chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_OFF) {
+  if (SessionControllerClient::IsMultiProfileAvailable()) {
     user_switch_observer_.reset(
         new ChromeLauncherControllerUserSwitchObserver(this));
   }
@@ -240,8 +240,7 @@
   std::unique_ptr<AppWindowLauncherController> extension_app_window_controller;
   // Create our v1/v2 application / browser monitors which will inform the
   // launcher of status changes.
-  if (chrome::MultiUserWindowManager::GetMultiProfileMode() ==
-      chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_ON) {
+  if (SessionControllerClient::IsMultiProfileAvailable()) {
     // If running in separated destkop mode, we create the multi profile version
     // of status monitor.
     browser_status_monitor_.reset(new MultiProfileBrowserStatusMonitor(this));
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
index a553bf67..c808634 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
@@ -91,21 +91,24 @@
 namespace {
 
 // A callback that records the action taken when a shelf item is selected.
-void SelectItemCallback(ash::ShelfAction* action_taken,
-                        base::RunLoop* run_loop,
-                        ash::ShelfAction action,
-                        base::Optional<ash::MenuItemList>) {
+void ItemSelectedCallback(ash::ShelfAction* action_taken,
+                          base::RunLoop* run_loop,
+                          ash::ShelfAction action,
+                          base::Optional<ash::MenuItemList>) {
   *action_taken = action;
   run_loop->Quit();
 }
 
-// Calls ShelfItemDelegate::SelectItem with an event type and default arguments.
-ash::ShelfAction SelectItem(ash::ShelfItemDelegate* delegate,
-                            ui::EventType event_type) {
+// Calls ShelfItemDelegate::ItemSelected for the item with the given |id|, using
+// an event corresponding to the requested |event_type| (defaults to mouse) and
+// plumbs the requested |display_id| (invalid defaults to the primary display).
+ash::ShelfAction SelectItem(const ash::ShelfID& id,
+                            ui::EventType event_type = ui::ET_MOUSE_PRESSED,
+                            int64_t display_id = display::kInvalidDisplayId) {
   std::unique_ptr<ui::Event> event;
   if (event_type == ui::ET_MOUSE_PRESSED) {
     event =
-        base::MakeUnique<ui::MouseEvent>(event_type, gfx::Point(), gfx::Point(),
+        std::make_unique<ui::MouseEvent>(event_type, gfx::Point(), gfx::Point(),
                                          ui::EventTimeForNow(), ui::EF_NONE, 0);
   } else if (event_type == ui::ET_KEY_RELEASED) {
     event = base::MakeUnique<ui::KeyEvent>(event_type, ui::VKEY_UNKNOWN,
@@ -114,9 +117,11 @@
 
   base::RunLoop run_loop;
   ash::ShelfAction action = ash::SHELF_ACTION_NONE;
+  ash::ShelfModel* model = ChromeLauncherController::instance()->shelf_model();
+  ash::ShelfItemDelegate* delegate = model->GetShelfItemDelegate(id);
   delegate->ItemSelected(
-      std::move(event), display::kInvalidDisplayId, ash::LAUNCH_FROM_UNKNOWN,
-      base::BindOnce(&SelectItemCallback, &action, &run_loop));
+      std::move(event), display_id, ash::LAUNCH_FROM_UNKNOWN,
+      base::BindOnce(&ItemSelectedCallback, &action, &run_loop));
   run_loop.Run();
   return action;
 }
@@ -202,22 +207,15 @@
     extensions::PlatformAppBrowserTest::SetUpOnMainThread();
   }
 
-  ash::ShelfModel* shelf_model() { return ash::Shell::Get()->shelf_model(); }
+  ash::ShelfModel* shelf_model() { return controller_->shelf_model(); }
 
   ash::ShelfID CreateAppShortcutLauncherItem(const ash::ShelfID& shelf_id) {
     return controller_->CreateAppShortcutLauncherItem(
         shelf_id, shelf_model()->item_count());
   }
 
+  // Returns the last item in the shelf; note that panels are pinned to the end.
   const ash::ShelfItem& GetLastLauncherItem() {
-    // Unless there are any panels, the item at index [count - 1] will be
-    // the desired item.
-    return shelf_model()->items()[shelf_model()->item_count() - 1];
-  }
-
-  const ash::ShelfItem& GetLastLauncherPanelItem() {
-    // Panels show up on the right side of the shelf, so the desired item
-    // will be the last one.
     return shelf_model()->items()[shelf_model()->item_count() - 1];
   }
 
@@ -225,6 +223,18 @@
     return shelf_model()->GetShelfItemDelegate(id);
   }
 
+  AppWindow* CreateAppWindowAndRunLoop(content::BrowserContext* context,
+                                       const Extension* extension,
+                                       const AppWindow::CreateParams& params) {
+    AppWindow* window = CreateAppWindowFromParams(context, extension, params);
+    // The shelf items for panel app windows are controlled by Ash's
+    // ShelfWindowWatcher and added to Ash's ShelfModel. Spin a RunLoop to allow
+    // the shelf item to synchronize to Chrome's separate ShelfModel.
+    if (params.window_type == AppWindow::WINDOW_TYPE_PANEL)
+      base::RunLoop().RunUntilIdle();
+    return window;
+  }
+
   ChromeLauncherController* controller_;
 
  private:
@@ -244,16 +254,17 @@
 
 class ShelfAppBrowserTest : public ExtensionBrowserTest {
  protected:
-  ShelfAppBrowserTest() : shelf_(NULL), model_(NULL), controller_(NULL) {}
+  ShelfAppBrowserTest() {}
 
   ~ShelfAppBrowserTest() override {}
 
+  ash::ShelfModel* shelf_model() { return controller_->shelf_model(); }
+
   void SetUpOnMainThread() override {
     // Ensure ash starts the session and creates the shelf and controller.
     SessionControllerClient::FlushForTesting();
 
     shelf_ = Shelf::ForWindow(ash::Shell::GetPrimaryRootWindow());
-    model_ = ash::Shell::Get()->shelf_model();
     controller_ = ChromeLauncherController::instance();
     ASSERT_TRUE(controller_);
     ExtensionBrowserTest::SetUpOnMainThread();
@@ -294,24 +305,24 @@
     const std::string app_id = extension->id();
 
     // Then create a shortcut.
-    int item_count = model_->item_count();
+    int item_count = shelf_model()->item_count();
     ash::ShelfID shortcut_id = controller_->CreateAppShortcutLauncherItem(
         ash::ShelfID(app_id), item_count);
     controller_->SyncPinPosition(shortcut_id);
-    EXPECT_EQ(++item_count, model_->item_count());
-    const ash::ShelfItem& item = *model_->ItemByID(shortcut_id);
+    EXPECT_EQ(++item_count, shelf_model()->item_count());
+    const ash::ShelfItem& item = *shelf_model()->ItemByID(shortcut_id);
     EXPECT_EQ(ash::TYPE_PINNED_APP, item.type);
     return item.id;
   }
 
   ash::ShelfID PinFakeApp(const std::string& app_id) {
-    return controller_->CreateAppShortcutLauncherItem(ash::ShelfID(app_id),
-                                                      model_->item_count());
+    return controller_->CreateAppShortcutLauncherItem(
+        ash::ShelfID(app_id), shelf_model()->item_count());
   }
 
   // Get the index of an item which has the given type.
   int GetIndexOfShelfItemType(ash::ShelfItemType type) {
-    return model_->GetItemIndexForType(type);
+    return shelf_model()->GetItemIndexForType(type);
   }
 
   // Try to rip off |item_index|.
@@ -346,9 +357,9 @@
 
   // Creates a context menu for the existing browser shortcut item.
   std::unique_ptr<LauncherContextMenu> CreateBrowserItemContextMenu() {
-    int index = model_->GetItemIndexForType(ash::TYPE_BROWSER_SHORTCUT);
+    int index = shelf_model()->GetItemIndexForType(ash::TYPE_BROWSER_SHORTCUT);
     DCHECK_GE(index, 0);
-    ash::ShelfItem item = model_->items()[index];
+    ash::ShelfItem item = shelf_model()->items()[index];
     int64_t display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id();
     return LauncherContextMenu::Create(controller_, &item, display_id);
   }
@@ -357,9 +368,8 @@
     return menu->GetIndexOfCommandId(command_id) != -1;
   }
 
-  Shelf* shelf_;
-  ash::ShelfModel* model_;
-  ChromeLauncherController* controller_;
+  Shelf* shelf_ = nullptr;
+  ChromeLauncherController* controller_ = nullptr;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ShelfAppBrowserTest);
@@ -619,14 +629,14 @@
   EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id1)->status);
 
   // Activate first one.
-  Shelf::ActivateShelfItem(shelf_model()->ItemIndexByID(item_id1));
+  SelectItem(item_id1);
   EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(item_id1)->status);
   EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id2)->status);
   EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
   EXPECT_FALSE(window2->GetBaseWindow()->IsActive());
 
   // Activate second one.
-  Shelf::ActivateShelfItem(shelf_model()->ItemIndexByID(item_id2));
+  SelectItem(item_id2);
   EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id1)->status);
   EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(item_id2)->status);
   EXPECT_FALSE(window1->GetBaseWindow()->IsActive());
@@ -639,21 +649,22 @@
   EXPECT_FALSE(window2->GetBaseWindow()->IsActive());
   EXPECT_TRUE(window1b->GetBaseWindow()->IsActive());
 
-  // Activate launcher item for app1, this will activate the first app window.
-  Shelf::ActivateShelfItem(shelf_model()->ItemIndexByID(item_id1));
+  // Key events selecting app1's shelf item will cycle through its windows.
+  SelectItem(item_id1, ui::ET_KEY_RELEASED);
   EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
   EXPECT_FALSE(window1b->GetBaseWindow()->IsActive());
-  Shelf::ActivateShelfItem(shelf_model()->ItemIndexByID(item_id1));
+  SelectItem(item_id1, ui::ET_KEY_RELEASED);
+  EXPECT_FALSE(window1->GetBaseWindow()->IsActive());
   EXPECT_TRUE(window1b->GetBaseWindow()->IsActive());
 
   // Activate the second app again
-  Shelf::ActivateShelfItem(shelf_model()->ItemIndexByID(item_id2));
+  SelectItem(item_id2);
   EXPECT_FALSE(window1->GetBaseWindow()->IsActive());
   EXPECT_TRUE(window2->GetBaseWindow()->IsActive());
   EXPECT_FALSE(window1b->GetBaseWindow()->IsActive());
 
   // Activate the first app again
-  Shelf::ActivateShelfItem(shelf_model()->ItemIndexByID(item_id1));
+  SelectItem(item_id1);
   EXPECT_TRUE(window1b->GetBaseWindow()->IsActive());
   EXPECT_FALSE(window2->GetBaseWindow()->IsActive());
   EXPECT_FALSE(window1->GetBaseWindow()->IsActive());
@@ -682,25 +693,24 @@
   EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
 
   // Confirm that a controller item was created and is the correct state.
-  const ash::ShelfItem& item1 = GetLastLauncherItem();
-  ash::ShelfItemDelegate* item1_delegate = GetShelfItemDelegate(item1.id);
-  EXPECT_EQ(ash::TYPE_APP, item1.type);
-  EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
+  const ash::ShelfItem& item = GetLastLauncherItem();
+  EXPECT_EQ(ash::TYPE_APP, item.type);
+  EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
   // Since it is already active, clicking it should minimize.
-  SelectItem(item1_delegate, ui::ET_MOUSE_PRESSED);
+  SelectItem(item.id);
   EXPECT_FALSE(window1->GetNativeWindow()->IsVisible());
   EXPECT_FALSE(window1->GetBaseWindow()->IsActive());
   EXPECT_TRUE(window1->GetBaseWindow()->IsMinimized());
-  EXPECT_EQ(ash::STATUS_RUNNING, item1.status);
+  EXPECT_EQ(ash::STATUS_RUNNING, item.status);
   // Clicking the item again should activate the window again.
-  SelectItem(item1_delegate, ui::ET_MOUSE_PRESSED);
+  SelectItem(item.id);
   EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
   EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
-  EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
   // Maximizing a window should preserve state after minimize + click.
   window1->GetBaseWindow()->Maximize();
   window1->GetBaseWindow()->Minimize();
-  SelectItem(item1_delegate, ui::ET_MOUSE_PRESSED);
+  SelectItem(item.id);
   EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
   EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
   EXPECT_TRUE(window1->GetBaseWindow()->IsMaximized());
@@ -718,25 +728,26 @@
   EXPECT_TRUE(window1a->GetBaseWindow()->IsActive());
 
   // Ensure the same shelf item and delegate are used for |window1a|.
-  EXPECT_EQ(item1.id, GetLastLauncherItem().id);
-  EXPECT_EQ(item1_delegate, GetShelfItemDelegate(GetLastLauncherItem().id));
+  EXPECT_EQ(item.id, GetLastLauncherItem().id);
+  EXPECT_EQ(GetShelfItemDelegate(item.id),
+            GetShelfItemDelegate(GetLastLauncherItem().id));
 
   // The first click does nothing.
-  SelectItem(item1_delegate, ui::ET_MOUSE_PRESSED);
+  SelectItem(item.id);
   EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
   EXPECT_TRUE(window1a->GetNativeWindow()->IsVisible());
   EXPECT_FALSE(window1->GetBaseWindow()->IsActive());
   EXPECT_TRUE(window1a->GetBaseWindow()->IsActive());
   // The second neither.
-  SelectItem(item1_delegate, ui::ET_MOUSE_PRESSED);
+  SelectItem(item.id);
   EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
   EXPECT_TRUE(window1a->GetNativeWindow()->IsVisible());
   EXPECT_FALSE(window1->GetBaseWindow()->IsActive());
   EXPECT_TRUE(window1a->GetBaseWindow()->IsActive());
 }
 
-// Confirm that ash::ShelfWindowWatcher correctly handles app panels.
-IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, AppPanel) {
+// Confirm that item selection behavior for Chrome app panels is correct.
+IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, PanelItemClickBehavior) {
   // Enable experimental APIs to allow panel creation.
   base::CommandLine::ForCurrentProcess()->AppendSwitch(
       extensions::switches::kEnableExperimentalExtensionApis);
@@ -746,68 +757,32 @@
   params.window_type = AppWindow::WINDOW_TYPE_PANEL;
   params.focused = false;
   AppWindow* panel =
-      CreateAppWindowFromParams(browser()->profile(), extension1, params);
+      CreateAppWindowAndRunLoop(browser()->profile(), extension1, params);
   EXPECT_TRUE(panel->GetNativeWindow()->IsVisible());
   // Panels should not be active by default.
   EXPECT_FALSE(panel->GetBaseWindow()->IsActive());
   // Confirm that an item delegate was created and is in the correct state.
-  const ash::ShelfItem& item1 = GetLastLauncherPanelItem();
-  EXPECT_EQ(ash::TYPE_APP_PANEL, item1.type);
-  EXPECT_EQ(ash::STATUS_RUNNING, item1.status);
-  ash::ShelfItemDelegate* item1_delegate = GetShelfItemDelegate(item1.id);
+  const ash::ShelfItem& item = GetLastLauncherItem();
+  EXPECT_EQ(ash::TYPE_APP_PANEL, item.type);
+  EXPECT_EQ(ash::STATUS_RUNNING, item.status);
   EXPECT_EQ(ash::TYPE_APP_PANEL,
             panel->GetNativeWindow()->GetProperty(ash::kShelfItemTypeKey));
+  EXPECT_EQ(item.id.Serialize(),
+            *panel->GetNativeWindow()->GetProperty(ash::kShelfIDKey));
   // Click the item and confirm that the panel is activated.
-  SelectItem(item1_delegate, ui::ET_MOUSE_PRESSED);
+  EXPECT_EQ(ash::SHELF_ACTION_WINDOW_ACTIVATED, SelectItem(item.id));
   EXPECT_TRUE(panel->GetBaseWindow()->IsActive());
-  EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
   // Click the item again and confirm that the panel is minimized.
-  SelectItem(item1_delegate, ui::ET_MOUSE_PRESSED);
+  EXPECT_EQ(ash::SHELF_ACTION_WINDOW_MINIMIZED, SelectItem(item.id));
   EXPECT_TRUE(panel->GetBaseWindow()->IsMinimized());
-  EXPECT_EQ(ash::STATUS_RUNNING, item1.status);
+  EXPECT_EQ(ash::STATUS_RUNNING, item.status);
   // Click the item again and confirm that the panel is activated.
-  SelectItem(item1_delegate, ui::ET_MOUSE_PRESSED);
+  EXPECT_EQ(ash::SHELF_ACTION_WINDOW_ACTIVATED, SelectItem(item.id));
   EXPECT_TRUE(panel->GetNativeWindow()->IsVisible());
   EXPECT_TRUE(panel->GetBaseWindow()->IsActive());
   EXPECT_FALSE(panel->GetBaseWindow()->IsMinimized());
-  EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
-}
-
-// Confirm that click behavior for app panels is correct.
-IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, AppPanelClickBehavior) {
-  // Enable experimental APIs to allow panel creation.
-  base::CommandLine::ForCurrentProcess()->AppendSwitch(
-      extensions::switches::kEnableExperimentalExtensionApis);
-  // Launch a platform app and create a panel window for it.
-  const Extension* extension1 = LoadAndLaunchPlatformApp("launch", "Launched");
-  AppWindow::CreateParams params;
-  params.window_type = AppWindow::WINDOW_TYPE_PANEL;
-  params.focused = false;
-  AppWindow* panel =
-      CreateAppWindowFromParams(browser()->profile(), extension1, params);
-  EXPECT_TRUE(panel->GetNativeWindow()->IsVisible());
-  // Panels should not be active by default.
-  EXPECT_FALSE(panel->GetBaseWindow()->IsActive());
-  // Confirm that an item delegate was created and is in the correct state.
-  const ash::ShelfItem& item1 = GetLastLauncherPanelItem();
-  EXPECT_EQ(ash::TYPE_APP_PANEL, item1.type);
-  EXPECT_EQ(ash::STATUS_RUNNING, item1.status);
-  ash::ShelfItemDelegate* item1_delegate = GetShelfItemDelegate(item1.id);
-  EXPECT_EQ(ash::TYPE_APP_PANEL,
-            panel->GetNativeWindow()->GetProperty(ash::kShelfItemTypeKey));
-  // Click the item and confirm that the panel is activated.
-  SelectItem(item1_delegate, ui::ET_MOUSE_PRESSED);
-  EXPECT_TRUE(panel->GetBaseWindow()->IsActive());
-  EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
-  // Click the item again and confirm that the panel is minimized.
-  SelectItem(item1_delegate, ui::ET_MOUSE_PRESSED);
-  EXPECT_TRUE(panel->GetBaseWindow()->IsMinimized());
-  EXPECT_EQ(ash::STATUS_RUNNING, item1.status);
-  // Click the item again and confirm that the panel is activated.
-  SelectItem(item1_delegate, ui::ET_MOUSE_PRESSED);
-  EXPECT_TRUE(panel->GetNativeWindow()->IsVisible());
-  EXPECT_TRUE(panel->GetBaseWindow()->IsActive());
-  EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
 }
 
 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, BrowserActivation) {
@@ -818,10 +793,10 @@
   CreateAppWindow(browser()->profile(), extension1);
   ++item_count;
   ASSERT_EQ(item_count, shelf_model()->item_count());
-  const ash::ShelfItem& item1 = GetLastLauncherItem();
-  ash::ShelfID item_id1 = item1.id;
-  EXPECT_EQ(ash::TYPE_APP, item1.type);
-  EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
+  const ash::ShelfItem& item = GetLastLauncherItem();
+  ash::ShelfID item_id1 = item.id;
+  EXPECT_EQ(ash::TYPE_APP, item.type);
+  EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
 
   browser()->window()->Activate();
   EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id1)->status);
@@ -904,11 +879,7 @@
   EXPECT_TRUE(app_custom_icon_item_delegate->image_set_by_controller());
 
 // Ensure icon heights are correct (see test.js in app_icon/ test directory)
-#if defined(USE_ASH)
   EXPECT_EQ(ash::kShelfSize, app_item.image.height());
-#else
-  EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALL, app_item.image.height());
-#endif
   EXPECT_EQ(extension_misc::EXTENSION_ICON_LARGE,
             app_custom_icon_item.image.height());
   EXPECT_EQ(64, panel_item.image.height());
@@ -928,16 +899,16 @@
   TabStripModel* tab_strip = browser()->tab_strip_model();
   int tab_count = tab_strip->count();
   ash::ShelfID shortcut_id = CreateShortcut("app1");
-  EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status);
-  Shelf::ActivateShelfItem(model_->ItemIndexByID(shortcut_id));
+  EXPECT_EQ(ash::STATUS_CLOSED, shelf_model()->ItemByID(shortcut_id)->status);
+  SelectItem(shortcut_id);
   EXPECT_EQ(++tab_count, tab_strip->count());
-  EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut_id)->status);
   WebContents* tab = tab_strip->GetActiveWebContents();
   content::WebContentsDestroyedWatcher destroyed_watcher(tab);
   browser()->tab_strip_model()->CloseSelectedTabs();
   destroyed_watcher.Wait();
   EXPECT_EQ(--tab_count, tab_strip->count());
-  EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status);
+  EXPECT_EQ(ash::STATUS_CLOSED, shelf_model()->ItemByID(shortcut_id)->status);
 }
 
 // Tests behavior of launching app from shelf in the first display while the
@@ -983,8 +954,7 @@
   // Launches an app from the shelf of display 0 and expects a new tab is opened
   // in the uppermost browser in display 0.
   ash::ShelfID shortcut_id = CreateShortcut("app1");
-  Shelf::ActivateShelfItemOnDisplay(model_->ItemIndexByID(shortcut_id),
-                                    displays[1].id());
+  SelectItem(shortcut_id, ui::ET_MOUSE_PRESSED, displays[1].id());
   EXPECT_EQ(browser0->tab_strip_model()->count(), 1);
   EXPECT_EQ(browser1->tab_strip_model()->count(), 1);
   EXPECT_EQ(browser2->tab_strip_model()->count(), 2);
@@ -1022,8 +992,7 @@
   // Launches an app from the shelf of display 0 and expects a new browser with
   // one tab is opened in display 0.
   ash::ShelfID shortcut_id = CreateShortcut("app1");
-  Shelf::ActivateShelfItemOnDisplay(model_->ItemIndexByID(shortcut_id),
-                                    displays[1].id());
+  SelectItem(shortcut_id, ui::ET_MOUSE_PRESSED, displays[1].id());
   Browser* browser1 = browser_list->GetLastActive();
   EXPECT_EQ(browser_list->size(), 2U);
   EXPECT_NE(browser1, browser0);
@@ -1039,13 +1008,13 @@
                          WindowOpenDisposition::NEW_FOREGROUND_TAB);
   EXPECT_EQ(++tab_count, tab_strip->count());
   ash::ShelfID shortcut_id = CreateShortcut("app1");
-  EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut_id)->status);
   WebContents* tab = tab_strip->GetActiveWebContents();
   content::WebContentsDestroyedWatcher destroyed_watcher(tab);
   browser()->tab_strip_model()->CloseSelectedTabs();
   destroyed_watcher.Wait();
   EXPECT_EQ(--tab_count, tab_strip->count());
-  EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status);
+  EXPECT_EQ(ash::STATUS_CLOSED, shelf_model()->ItemByID(shortcut_id)->status);
 }
 
 // Launches an app in the background and then tries to open it. This is test for
@@ -1076,15 +1045,15 @@
   browser2->window()->Maximize();
 
   ash::ShelfID shortcut_id = CreateShortcut("app1");
-  Shelf::ActivateShelfItem(model_->ItemIndexByID(shortcut_id));
+  SelectItem(shortcut_id);
   EXPECT_EQ(++tab_count, tab_strip->count());
-  EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut_id)->status);
 
   browser()->window()->Activate();
-  EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut_id)).status);
+  EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(shortcut_id)->status);
 
-  Shelf::ActivateShelfItem(model_->ItemIndexByID(shortcut_id));
-  EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
+  SelectItem(shortcut_id);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut_id)->status);
 }
 
 // Activating the same app multiple times should launch only a single copy.
@@ -1115,75 +1084,75 @@
 
 // Launch 2 apps and toggle which is active.
 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, MultipleApps) {
-  int item_count = model_->item_count();
+  int item_count = shelf_model()->item_count();
   TabStripModel* tab_strip = browser()->tab_strip_model();
   int tab_count = tab_strip->count();
   ash::ShelfID shortcut1 = CreateShortcut("app1");
-  EXPECT_EQ(++item_count, model_->item_count());
+  EXPECT_EQ(++item_count, shelf_model()->item_count());
   ash::ShelfID shortcut2 = CreateShortcut("app2");
-  EXPECT_EQ(++item_count, model_->item_count());
+  EXPECT_EQ(++item_count, shelf_model()->item_count());
 
   // Launch first app.
-  Shelf::ActivateShelfItem(model_->ItemIndexByID(shortcut1));
+  SelectItem(shortcut1);
   EXPECT_EQ(++tab_count, tab_strip->count());
   WebContents* tab1 = tab_strip->GetActiveWebContents();
-  EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut1)->status);
 
   // Launch second app.
-  Shelf::ActivateShelfItem(model_->ItemIndexByID(shortcut2));
+  SelectItem(shortcut2);
   EXPECT_EQ(++tab_count, tab_strip->count());
   WebContents* tab2 = tab_strip->GetActiveWebContents();
   ASSERT_NE(tab1, tab2);
-  EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status);
-  EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status);
+  EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(shortcut1)->status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut2)->status);
 
   // Reactivate first app.
-  Shelf::ActivateShelfItem(model_->ItemIndexByID(shortcut1));
+  SelectItem(shortcut1);
   EXPECT_EQ(tab_count, tab_strip->count());
   EXPECT_EQ(tab_strip->GetActiveWebContents(), tab1);
-  EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status);
-  EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut2)).status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut1)->status);
+  EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(shortcut2)->status);
 
   // Open second tab for second app. This should activate it.
   ui_test_utils::NavigateToURLWithDisposition(
       browser(), GURL("http://www.example.com/path3/foo.html"),
       WindowOpenDisposition::NEW_FOREGROUND_TAB, 0);
   EXPECT_EQ(++tab_count, tab_strip->count());
-  EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status);
-  EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status);
+  EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(shortcut1)->status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut2)->status);
 
   // Reactivate first app.
-  Shelf::ActivateShelfItem(model_->ItemIndexByID(shortcut1));
+  SelectItem(shortcut1);
   EXPECT_EQ(tab_count, tab_strip->count());
   EXPECT_EQ(tab_strip->GetActiveWebContents(), tab1);
-  EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status);
-  EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut2)).status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut1)->status);
+  EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(shortcut2)->status);
 
   // And second again. This time the second tab should become active.
-  Shelf::ActivateShelfItem(model_->ItemIndexByID(shortcut2));
+  SelectItem(shortcut2);
   EXPECT_EQ(tab_count, tab_strip->count());
   EXPECT_EQ(tab_strip->GetActiveWebContents(), tab2);
-  EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status);
-  EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status);
+  EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(shortcut1)->status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut2)->status);
 }
 
 // Confirm that a page can be navigated from and to while maintaining the
 // correct running state.
 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, Navigation) {
   ash::ShelfID shortcut_id = CreateShortcut("app1");
-  EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status);
-  Shelf::ActivateShelfItem(model_->ItemIndexByID(shortcut_id));
-  EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
+  EXPECT_EQ(ash::STATUS_CLOSED, shelf_model()->ItemByID(shortcut_id)->status);
+  SelectItem(shortcut_id);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut_id)->status);
 
   // Navigate away.
   ui_test_utils::NavigateToURL(browser(),
                                GURL("http://www.example.com/path0/bar.html"));
-  EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status);
+  EXPECT_EQ(ash::STATUS_CLOSED, shelf_model()->ItemByID(shortcut_id)->status);
 
   // Navigate back.
   ui_test_utils::NavigateToURL(browser(),
                                GURL("http://www.example.com/path1/foo.html"));
-  EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut_id)->status);
 }
 
 // Confirm that a tab can be moved between browsers while maintaining the
@@ -1197,22 +1166,22 @@
 
   // Create a shortcut for app1.
   ash::ShelfID shortcut_id = CreateShortcut("app1");
-  EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status);
-  EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->items()[browser_index].status);
+  EXPECT_EQ(ash::STATUS_CLOSED, shelf_model()->ItemByID(shortcut_id)->status);
 
   // Activate app1 and check its item status.
-  Shelf::ActivateShelfItem(model_->ItemIndexByID(shortcut_id));
+  SelectItem(shortcut_id);
   EXPECT_EQ(2, tab_strip_model1->count());
-  EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status);
-  EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
+  EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->items()[browser_index].status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut_id)->status);
 
   // Create a new browser with blank tab.
   Browser* browser2 = CreateBrowser(profile());
   EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
   TabStripModel* tab_strip_model2 = browser2->tab_strip_model();
   EXPECT_EQ(1, tab_strip_model2->count());
-  EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status);
-  EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut_id)).status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->items()[browser_index].status);
+  EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(shortcut_id)->status);
 
   // Detach a tab at index 1 (app1) from |tab_strip_model1| and insert it as an
   // active tab at index 1 to |tab_strip_model2|.
@@ -1221,8 +1190,8 @@
                                         TabStripModel::ADD_ACTIVE);
   EXPECT_EQ(1, tab_strip_model1->count());
   EXPECT_EQ(2, tab_strip_model2->count());
-  EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status);
-  EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
+  EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->items()[browser_index].status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut_id)->status);
 
   tab_strip_model1->CloseAllTabs();
   tab_strip_model2->CloseAllTabs();
@@ -1232,9 +1201,9 @@
   TabStripModel* tab_strip = browser()->tab_strip_model();
   int tab_count = tab_strip->count();
   ash::ShelfID shortcut_id = CreateShortcut("app1");
-  Shelf::ActivateShelfItem(model_->ItemIndexByID(shortcut_id));
+  SelectItem(shortcut_id);
   EXPECT_EQ(++tab_count, tab_strip->count());
-  EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut_id)->status);
   WebContents* first_tab = tab_strip->GetActiveWebContents();
 
   // Create new tab owned by app.
@@ -1244,7 +1213,7 @@
       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
   EXPECT_EQ(++tab_count, tab_strip->count());
   // Confirm app is still active.
-  EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut_id)->status);
 
   // Create new tab not owned by app.
   ui_test_utils::NavigateToURLWithDisposition(
@@ -1252,11 +1221,11 @@
       WindowOpenDisposition::NEW_FOREGROUND_TAB, 0);
   EXPECT_EQ(++tab_count, tab_strip->count());
   // No longer active.
-  EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status);
+  EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(shortcut_id)->status);
 
   // Activating app makes first tab active again.
-  Shelf::ActivateShelfItem(model_->ItemIndexByID(shortcut_id));
-  EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
+  SelectItem(shortcut_id);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut_id)->status);
   EXPECT_EQ(tab_strip->GetActiveWebContents(), first_tab);
 }
 
@@ -1264,9 +1233,9 @@
   TabStripModel* tab_strip = browser()->tab_strip_model();
   int tab_count = tab_strip->count();
   ash::ShelfID shortcut_id = CreateShortcut("app1");
-  Shelf::ActivateShelfItem(model_->ItemIndexByID(shortcut_id));
+  SelectItem(shortcut_id);
   EXPECT_EQ(++tab_count, tab_strip->count());
-  EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut_id)->status);
   WebContents* first_tab = tab_strip->GetActiveWebContents();
 
   controller_->SetRefocusURLPatternForTest(
@@ -1278,7 +1247,7 @@
       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
   EXPECT_EQ(++tab_count, tab_strip->count());
   // Confirm app is still active.
-  EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut_id)->status);
 
   // Create new tab not owned by app.
   ui_test_utils::NavigateToURLWithDisposition(
@@ -1286,12 +1255,12 @@
       WindowOpenDisposition::NEW_FOREGROUND_TAB, 0);
   EXPECT_EQ(++tab_count, tab_strip->count());
   // No longer active.
-  EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status);
+  EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(shortcut_id)->status);
 
   // Activating app makes first tab active again, because second tab isn't
   // in its refocus url path.
-  Shelf::ActivateShelfItem(model_->ItemIndexByID(shortcut_id));
-  EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
+  SelectItem(shortcut_id);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut_id)->status);
   EXPECT_EQ(tab_strip->GetActiveWebContents(), first_tab);
 }
 
@@ -1310,14 +1279,14 @@
   EXPECT_EQ(++tab_count, tab_strip->count());
   WebContents* first_tab = tab_strip->GetActiveWebContents();
   // Confirm app is not active.
-  EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status);
+  EXPECT_EQ(ash::STATUS_CLOSED, shelf_model()->ItemByID(shortcut_id)->status);
 
   // Activating app should launch new tab, because second tab isn't
   // in its refocus url path.
-  Shelf::ActivateShelfItem(model_->ItemIndexByID(shortcut_id));
+  SelectItem(shortcut_id);
   EXPECT_EQ(++tab_count, tab_strip->count());
   WebContents* second_tab = tab_strip->GetActiveWebContents();
-  EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut_id)->status);
   EXPECT_NE(first_tab, second_tab);
   EXPECT_EQ(tab_strip->GetActiveWebContents(), second_tab);
 }
@@ -1330,14 +1299,14 @@
   EXPECT_TRUE(browser_index >= 0);
 
   // Even though we are just comming up, the browser should be active.
-  EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->items()[browser_index].status);
 
   ash::ShelfID shortcut_id = CreateShortcut("app1");
   controller_->SetRefocusURLPatternForTest(
       shortcut_id, GURL("http://www.example.com/path1/*"));
 
-  EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status);
-  EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status);
+  EXPECT_EQ(ash::STATUS_CLOSED, shelf_model()->ItemByID(shortcut_id)->status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->items()[browser_index].status);
 
   // Create new tab which would be the running app.
   ui_test_utils::NavigateToURLWithDisposition(
@@ -1346,20 +1315,20 @@
       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
 
   // There should never be two items active at the same time.
-  EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
-  EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut_id)->status);
+  EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->items()[browser_index].status);
 
   tab_strip->ActivateTabAt(0, false);
-  EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status);
-  EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status);
+  EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(shortcut_id)->status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->items()[browser_index].status);
 
   tab_strip->CloseWebContentsAt(1, TabStripModel::CLOSE_NONE);
-  EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status);
-  EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status);
+  EXPECT_EQ(ash::STATUS_CLOSED, shelf_model()->ItemByID(shortcut_id)->status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->items()[browser_index].status);
 
   browser()->window()->Deactivate();
-  EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status);
-  EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status);
+  EXPECT_EQ(ash::STATUS_CLOSED, shelf_model()->ItemByID(shortcut_id)->status);
+  EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->items()[browser_index].status);
 }
 
 // Check that the launcher activation state for a V1 application stays closed
@@ -1372,7 +1341,7 @@
   controller_->SetRefocusURLPatternForTest(
       shortcut_id, GURL("http://www.example.com/path1/*"));
 
-  EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status);
+  EXPECT_EQ(ash::STATUS_CLOSED, shelf_model()->ItemByID(shortcut_id)->status);
 
   // Create new tab which would be the running app.
   ui_test_utils::NavigateToURLWithDisposition(
@@ -1380,7 +1349,7 @@
       WindowOpenDisposition::NEW_FOREGROUND_TAB,
       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
 
-  EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(shortcut_id)->status);
   // To address the issue of crbug.com/174050, the tab we are about to close
   // has to be active.
   tab_strip->ActivateTabAt(1, false);
@@ -1389,7 +1358,7 @@
   // Close the web contents.
   tab_strip->CloseWebContentsAt(1, TabStripModel::CLOSE_NONE);
   // The status should now be set to closed.
-  EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status);
+  EXPECT_EQ(ash::STATUS_CLOSED, shelf_model()->ItemByID(shortcut_id)->status);
 }
 
 // Test that the App window could restore to its previous window state from
@@ -1489,8 +1458,6 @@
       shortcut_id, GURL("http://www.example.com/path/*"));
   std::string url = "http://www.example.com/path/bla";
 
-  int shortcut_index = model_->ItemIndexByID(shortcut_id);
-
   // Create an application handled browser tab.
   ui_test_utils::NavigateToURLWithDisposition(
       browser(), GURL(url), WindowOpenDisposition::NEW_FOREGROUND_TAB,
@@ -1511,9 +1478,9 @@
   // The active tab should still be the unnamed tab. Then we switch and reach
   // the first app and stay there.
   EXPECT_EQ(content1a, tab_strip->GetActiveWebContents());
-  Shelf::ActivateShelfItem(shortcut_index);
+  SelectItem(shortcut_id, ui::ET_KEY_RELEASED);
   EXPECT_EQ(content1, tab_strip->GetActiveWebContents());
-  Shelf::ActivateShelfItem(shortcut_index);
+  SelectItem(shortcut_id, ui::ET_KEY_RELEASED);
   EXPECT_EQ(content1, tab_strip->GetActiveWebContents());
 
   ui_test_utils::NavigateToURLWithDisposition(
@@ -1522,9 +1489,9 @@
   content::WebContents* content2 = tab_strip->GetActiveWebContents();
 
   EXPECT_EQ(content2, browser()->tab_strip_model()->GetActiveWebContents());
-  Shelf::ActivateShelfItem(shortcut_index);
+  SelectItem(shortcut_id, ui::ET_KEY_RELEASED);
   EXPECT_EQ(content1, browser()->tab_strip_model()->GetActiveWebContents());
-  Shelf::ActivateShelfItem(shortcut_index);
+  SelectItem(shortcut_id, ui::ET_KEY_RELEASED);
   EXPECT_EQ(content2, browser()->tab_strip_model()->GetActiveWebContents());
 }
 
@@ -1535,12 +1502,10 @@
   const Extension* extension1 = LoadAndLaunchPlatformApp("launch", "Launched");
   ui::BaseWindow* window1 =
       CreateAppWindow(browser()->profile(), extension1)->GetBaseWindow();
-  const ash::ShelfItem& item1 = GetLastLauncherItem();
-  ash::ShelfID app_id = item1.id;
-  int app_index = shelf_model()->ItemIndexByID(app_id);
+  const ash::ShelfItem& item = GetLastLauncherItem();
 
-  EXPECT_EQ(ash::TYPE_APP, item1.type);
-  EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
+  EXPECT_EQ(ash::TYPE_APP, item.type);
+  EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
 
   const Extension* extension2 =
       LoadAndLaunchPlatformApp("launch_2", "Launched");
@@ -1550,9 +1515,9 @@
   // By now the browser should be active. Issue Alt keystrokes several times to
   // see that we stay on that application.
   EXPECT_TRUE(window2->IsActive());
-  Shelf::ActivateShelfItem(app_index);
+  SelectItem(item.id, ui::ET_KEY_RELEASED);
   EXPECT_TRUE(window1->IsActive());
-  Shelf::ActivateShelfItem(app_index);
+  SelectItem(item.id, ui::ET_KEY_RELEASED);
   EXPECT_TRUE(window1->IsActive());
 
   ui::BaseWindow* window1a =
@@ -1560,9 +1525,9 @@
 
   EXPECT_TRUE(window1a->IsActive());
   EXPECT_FALSE(window1->IsActive());
-  Shelf::ActivateShelfItem(app_index);
+  SelectItem(item.id, ui::ET_KEY_RELEASED);
   EXPECT_TRUE(window1->IsActive());
-  Shelf::ActivateShelfItem(app_index);
+  SelectItem(item.id, ui::ET_KEY_RELEASED);
   EXPECT_TRUE(window1a->IsActive());
 }
 
@@ -1574,14 +1539,16 @@
   params.window_type = AppWindow::WINDOW_TYPE_PANEL;
   params.focused = false;
   AppWindow* window =
-      CreateAppWindowFromParams(browser()->profile(), extension, params);
+      CreateAppWindowAndRunLoop(browser()->profile(), extension, params);
   ++item_count;
   ASSERT_EQ(item_count, shelf_model()->item_count());
-  const ash::ShelfItem& item = GetLastLauncherPanelItem();
+  const ash::ShelfItem& item = GetLastLauncherItem();
   EXPECT_EQ(ash::TYPE_APP_PANEL, item.type);
   // Opening a panel does not activate it.
   EXPECT_EQ(ash::STATUS_RUNNING, item.status);
   CloseAppWindow(window);
+  // Spin a run loop so Ash's handling of the window closing syncs to Chrome.
+  base::RunLoop().RunUntilIdle();
   --item_count;
   EXPECT_EQ(item_count, shelf_model()->item_count());
 }
@@ -1595,13 +1562,13 @@
   // Create a hidden window.
   params.hidden = true;
   AppWindow* window_1 =
-      CreateAppWindowFromParams(browser()->profile(), extension, params);
+      CreateAppWindowAndRunLoop(browser()->profile(), extension, params);
   EXPECT_EQ(item_count, shelf_model()->item_count());
 
   // Create a visible window.
   params.hidden = false;
   AppWindow* window_2 =
-      CreateAppWindowFromParams(browser()->profile(), extension, params);
+      CreateAppWindowAndRunLoop(browser()->profile(), extension, params);
   ++item_count;
   EXPECT_EQ(item_count, shelf_model()->item_count());
 
@@ -1629,144 +1596,176 @@
 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, WindowAttentionStatus) {
   const Extension* extension = LoadAndLaunchPlatformApp("launch", "Launched");
   AppWindow::CreateParams params;
+  params.focused = false;
+  AppWindow* window =
+      CreateAppWindowAndRunLoop(browser()->profile(), extension, params);
+  EXPECT_TRUE(window->GetNativeWindow()->IsVisible());
+  // The window should not be active by default.
+  EXPECT_FALSE(window->GetBaseWindow()->IsActive());
+  // Confirm that a shelf item was created and is the correct state.
+  const ash::ShelfItem& item = GetLastLauncherItem();
+  EXPECT_TRUE(GetShelfItemDelegate(item.id));
+  EXPECT_EQ(ash::TYPE_APP, item.type);
+  EXPECT_EQ(ash::STATUS_RUNNING, item.status);
+
+  // App windows should go to attention state.
+  window->GetNativeWindow()->SetProperty(aura::client::kDrawAttentionKey, true);
+  EXPECT_EQ(ash::STATUS_ATTENTION, item.status);
+
+  // Click the item and confirm that the window is activated.
+  EXPECT_EQ(ash::SHELF_ACTION_WINDOW_ACTIVATED, SelectItem(item.id));
+  EXPECT_TRUE(window->GetBaseWindow()->IsActive());
+  EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
+
+  // Active windows don't show attention.
+  window->GetNativeWindow()->SetProperty(aura::client::kDrawAttentionKey, true);
+  EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
+}
+
+// Test attention states of panels.
+IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, PanelAttentionStatus) {
+  const Extension* extension = LoadAndLaunchPlatformApp("launch", "Launched");
+  AppWindow::CreateParams params;
   params.window_type = AppWindow::WINDOW_TYPE_PANEL;
   params.focused = false;
   AppWindow* panel =
-      CreateAppWindowFromParams(browser()->profile(), extension, params);
+      CreateAppWindowAndRunLoop(browser()->profile(), extension, params);
   EXPECT_TRUE(panel->GetNativeWindow()->IsVisible());
   // Panels should not be active by default.
   EXPECT_FALSE(panel->GetBaseWindow()->IsActive());
   // Confirm that a shelf item was created and is the correct state.
-  const ash::ShelfItem& item = GetLastLauncherPanelItem();
-  ash::ShelfItemDelegate* shelf_item_delegate = GetShelfItemDelegate(item.id);
-  EXPECT_TRUE(shelf_item_delegate);
+  const ash::ShelfItem& item = GetLastLauncherItem();
+  EXPECT_TRUE(GetShelfItemDelegate(item.id));
   EXPECT_EQ(ash::TYPE_APP_PANEL, item.type);
   EXPECT_EQ(ash::STATUS_RUNNING, item.status);
 
   // App windows should go to attention state.
   panel->GetNativeWindow()->SetProperty(aura::client::kDrawAttentionKey, true);
+  // Ash updates panel shelf items; spin a run loop to sync Chrome's ShelfModel.
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(ash::STATUS_ATTENTION, item.status);
 
   // Click the item and confirm that the panel is activated.
-  EXPECT_EQ(ash::SHELF_ACTION_WINDOW_ACTIVATED,
-            SelectItem(shelf_item_delegate, ui::ET_MOUSE_PRESSED));
+  EXPECT_EQ(ash::SHELF_ACTION_WINDOW_ACTIVATED, SelectItem(item.id));
+  // Ash updates panel shelf items; spin a run loop to sync Chrome's ShelfModel.
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(panel->GetBaseWindow()->IsActive());
   EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
 
   // Active windows don't show attention.
   panel->GetNativeWindow()->SetProperty(aura::client::kDrawAttentionKey, true);
+  // Ash updates panel shelf items; spin a run loop to sync Chrome's ShelfModel.
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
 }
 
 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest,
                        ShowInShelfWindowsWithWindowKeySet) {
-  ash::ShelfModel* shelf_model = ash::Shell::Get()->shelf_model();
-
   // Add a window with shelf True, close it
-  int item_count = shelf_model->item_count();
+  int item_count = shelf_model()->item_count();
   const Extension* extension = LoadAndLaunchPlatformApp("launch", "Launched");
   AppWindow::CreateParams params;
 
   params.show_in_shelf = true;
   params.window_key = "window1";
   AppWindow* window1 =
-      CreateAppWindowFromParams(browser()->profile(), extension, params);
+      CreateAppWindowAndRunLoop(browser()->profile(), extension, params);
   // There should be only 1 item added to the shelf.
-  EXPECT_EQ(item_count + 1, shelf_model->item_count());
+  EXPECT_EQ(item_count + 1, shelf_model()->item_count());
   CloseAppWindow(window1);
-  EXPECT_EQ(item_count, shelf_model->item_count());
+  EXPECT_EQ(item_count, shelf_model()->item_count());
 
   // Add a window with false, following one with true
-  item_count = shelf_model->item_count();
+  item_count = shelf_model()->item_count();
   extension = LoadAndLaunchPlatformApp("launch", "Launched");
 
   params.show_in_shelf = false;
   params.window_key = "window1";
-  window1 = CreateAppWindowFromParams(browser()->profile(), extension, params);
-  EXPECT_EQ(item_count + 1, shelf_model->item_count());
+  window1 = CreateAppWindowAndRunLoop(browser()->profile(), extension, params);
+  EXPECT_EQ(item_count + 1, shelf_model()->item_count());
   params.show_in_shelf = true;
   params.window_key = "window2";
   AppWindow* window2 =
-      CreateAppWindowFromParams(browser()->profile(), extension, params);
+      CreateAppWindowAndRunLoop(browser()->profile(), extension, params);
   // There should be 2 items added to the shelf: although window1 has
   // show_in_shelf set to false, it's the first window created so its icon must
   // show up in shelf.
-  EXPECT_EQ(item_count + 2, shelf_model->item_count());
+  EXPECT_EQ(item_count + 2, shelf_model()->item_count());
   CloseAppWindow(window1);
-  EXPECT_EQ(item_count + 1, shelf_model->item_count());
+  EXPECT_EQ(item_count + 1, shelf_model()->item_count());
   CloseAppWindow(window2);
-  EXPECT_EQ(item_count, shelf_model->item_count());
+  EXPECT_EQ(item_count, shelf_model()->item_count());
 
   // Open just one window with false
-  item_count = shelf_model->item_count();
+  item_count = shelf_model()->item_count();
   extension = LoadAndLaunchPlatformApp("launch", "Launched");
 
   params.show_in_shelf = false;
   params.window_key = "window1";
-  window1 = CreateAppWindowFromParams(browser()->profile(), extension, params);
+  window1 = CreateAppWindowAndRunLoop(browser()->profile(), extension, params);
   // There should be 1 item added to the shelf: although show_in_shelf is false,
   // this is the first window created.
-  EXPECT_EQ(item_count + 1, shelf_model->item_count());
+  EXPECT_EQ(item_count + 1, shelf_model()->item_count());
   CloseAppWindow(window1);
-  EXPECT_EQ(item_count, shelf_model->item_count());
+  EXPECT_EQ(item_count, shelf_model()->item_count());
 
   // Add a window with true, following one with false
-  item_count = shelf_model->item_count();
+  item_count = shelf_model()->item_count();
   extension = LoadAndLaunchPlatformApp("launch", "Launched");
 
   params.show_in_shelf = true;
   params.window_key = "window1";
-  window1 = CreateAppWindowFromParams(browser()->profile(), extension, params);
-  EXPECT_EQ(item_count + 1, shelf_model->item_count());  // main window
+  window1 = CreateAppWindowAndRunLoop(browser()->profile(), extension, params);
+  EXPECT_EQ(item_count + 1, shelf_model()->item_count());  // main window
   params.show_in_shelf = false;
   params.window_key = "window2";
-  window2 = CreateAppWindowFromParams(browser()->profile(), extension, params);
-  EXPECT_EQ(item_count + 2, shelf_model->item_count());
+  window2 = CreateAppWindowAndRunLoop(browser()->profile(), extension, params);
+  EXPECT_EQ(item_count + 2, shelf_model()->item_count());
   CloseAppWindow(window1);
   // There should be 1 item added to the shelf as the second window
   // is set to show_in_shelf false
-  EXPECT_EQ(item_count + 1, shelf_model->item_count());
+  EXPECT_EQ(item_count + 1, shelf_model()->item_count());
   CloseAppWindow(window2);
-  EXPECT_EQ(item_count, shelf_model->item_count());
+  EXPECT_EQ(item_count, shelf_model()->item_count());
 
   // Test closing windows in different order
-  item_count = shelf_model->item_count();
+  item_count = shelf_model()->item_count();
   extension = LoadAndLaunchPlatformApp("launch", "Launched");
 
   params.show_in_shelf = false;
   params.window_key = "window1";
-  window1 = CreateAppWindowFromParams(browser()->profile(), extension, params);
-  EXPECT_EQ(item_count + 1, shelf_model->item_count());
+  window1 = CreateAppWindowAndRunLoop(browser()->profile(), extension, params);
+  EXPECT_EQ(item_count + 1, shelf_model()->item_count());
   params.show_in_shelf = false;
   params.window_key = "window2";
-  window2 = CreateAppWindowFromParams(browser()->profile(), extension, params);
-  EXPECT_EQ(item_count + 1, shelf_model->item_count());
+  window2 = CreateAppWindowAndRunLoop(browser()->profile(), extension, params);
+  EXPECT_EQ(item_count + 1, shelf_model()->item_count());
   params.show_in_shelf = true;
   params.window_key = "window3";
   AppWindow* window3 =
-      CreateAppWindowFromParams(browser()->profile(), extension, params);
-  EXPECT_EQ(item_count + 2, shelf_model->item_count());
+      CreateAppWindowAndRunLoop(browser()->profile(), extension, params);
+  EXPECT_EQ(item_count + 2, shelf_model()->item_count());
   params.show_in_shelf = true;
   params.window_key = "window4";
   AppWindow* window4 =
-      CreateAppWindowFromParams(browser()->profile(), extension, params);
+      CreateAppWindowAndRunLoop(browser()->profile(), extension, params);
   // There should be 3 items added to the shelf.
-  EXPECT_EQ(item_count + 3, shelf_model->item_count());
+  EXPECT_EQ(item_count + 3, shelf_model()->item_count());
   // Any window close order should be valid
   CloseAppWindow(window4);
   // Closed window4 that was shown in shelf. item_count would decrease
-  EXPECT_EQ(item_count + 2, shelf_model->item_count());
+  EXPECT_EQ(item_count + 2, shelf_model()->item_count());
   CloseAppWindow(window1);
   // Closed window1 which was grouped together with window2 so item_count
   // would not decrease
-  EXPECT_EQ(item_count + 2, shelf_model->item_count());
+  EXPECT_EQ(item_count + 2, shelf_model()->item_count());
   CloseAppWindow(window3);
   // Closed window3 that was shown in shelf. item_count would decrease
-  EXPECT_EQ(item_count + 1, shelf_model->item_count());
+  EXPECT_EQ(item_count + 1, shelf_model()->item_count());
   CloseAppWindow(window2);
   // Closed window2 - there is no other window in that group and item_count
   // would decrease
-  EXPECT_EQ(item_count, shelf_model->item_count());
+  EXPECT_EQ(item_count, shelf_model()->item_count());
 }
 
 // Checks that the browser Alt "tabbing" is properly done.
@@ -1775,10 +1774,11 @@
   // Get the number of items in the browser menu.
   EXPECT_EQ(0u, chrome::GetTotalBrowserCount());
   // The first activation should create a browser at index 1 (App List @ 0).
-  Shelf::ActivateShelfItem(1);
+  const ash::ShelfID browser_id = shelf_model()->items()[1].id;
+  SelectItem(browser_id, ui::ET_KEY_RELEASED);
   EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
   // A second activation should not create a new instance.
-  Shelf::ActivateShelfItem(1);
+  SelectItem(browser_id, ui::ET_KEY_RELEASED);
   Browser* browser1 = chrome::FindLastActive();
   EXPECT_TRUE(browser1);
   Browser* browser2 = CreateBrowser(profile());
@@ -1788,9 +1788,9 @@
   EXPECT_TRUE(browser2->window()->IsActive());
 
   // Activate multiple times the switcher to see that the windows get activated.
-  Shelf::ActivateShelfItem(1);
+  SelectItem(browser_id, ui::ET_KEY_RELEASED);
   EXPECT_TRUE(browser1->window()->IsActive());
-  Shelf::ActivateShelfItem(1);
+  SelectItem(browser_id, ui::ET_KEY_RELEASED);
   EXPECT_TRUE(browser2->window()->IsActive());
 
   // Create a third browser - make sure that we do not toggle simply between
@@ -1802,13 +1802,13 @@
   EXPECT_NE(browser2->window(), browser3->window());
   EXPECT_TRUE(browser3->window()->IsActive());
 
-  Shelf::ActivateShelfItem(1);
+  SelectItem(browser_id, ui::ET_KEY_RELEASED);
   EXPECT_TRUE(browser1->window()->IsActive());
-  Shelf::ActivateShelfItem(1);
+  SelectItem(browser_id, ui::ET_KEY_RELEASED);
   EXPECT_TRUE(browser2->window()->IsActive());
-  Shelf::ActivateShelfItem(1);
+  SelectItem(browser_id, ui::ET_KEY_RELEASED);
   EXPECT_TRUE(browser3->window()->IsActive());
-  Shelf::ActivateShelfItem(1);
+  SelectItem(browser_id, ui::ET_KEY_RELEASED);
   EXPECT_TRUE(browser1->window()->IsActive());
 
   // Create another app and make sure that none of our browsers is active.
@@ -1818,7 +1818,7 @@
   EXPECT_FALSE(browser2->window()->IsActive());
 
   // After activation our browser should be active again.
-  Shelf::ActivateShelfItem(1);
+  SelectItem(browser_id, ui::ET_KEY_RELEASED);
   EXPECT_TRUE(browser1->window()->IsActive());
 }
 
@@ -1859,9 +1859,7 @@
   EXPECT_EQ(it, browser_list->end_last_active());
 
   // Now request to either activate an existing app or create a new one.
-  ash::ShelfItemDelegate* item_delegate =
-      model_->GetShelfItemDelegate(shortcut_id);
-  SelectItem(item_delegate, ui::ET_KEY_RELEASED);
+  SelectItem(shortcut_id);
 
   // Check that we have set focus on the existing application and nothing new
   // was created.
@@ -1883,7 +1881,7 @@
   AppListService* service = AppListService::Get();
 
   // There should be two items in our launcher by this time.
-  EXPECT_EQ(2, model_->item_count());
+  EXPECT_EQ(2, shelf_model()->item_count());
   EXPECT_FALSE(service->IsAppListVisible());
 
   // Open the app list menu and check that the drag and drop host was set.
@@ -1928,20 +1926,20 @@
   base::RunLoop().RunUntilIdle();
 
   // Check that a new item got created.
-  EXPECT_EQ(3, model_->item_count());
+  EXPECT_EQ(3, shelf_model()->item_count());
   EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test());
 
   // Move it where the item originally was and check that it disappears again.
   generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(),
                         bounds_grid_1.CenterPoint().y());
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(2, model_->item_count());
+  EXPECT_EQ(2, shelf_model()->item_count());
   EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test());
 
   // Dropping it should keep the launcher as it originally was.
   generator.ReleaseLeftButton();
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(2, model_->item_count());
+  EXPECT_EQ(2, shelf_model()->item_count());
   // There are a few animations which need finishing before we can continue.
   test.RunMessageLoopUntilAnimationsDone();
   // Move the mouse outside of the launcher.
@@ -1955,12 +1953,12 @@
   generator.MoveMouseTo(bounds_shelf_1.CenterPoint().x(),
                         bounds_shelf_1.CenterPoint().y());
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(3, model_->item_count());
+  EXPECT_EQ(3, shelf_model()->item_count());
   EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test());
   generator.ReleaseLeftButton();
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test());
-  EXPECT_EQ(3, model_->item_count());  // It should be still there.
+  EXPECT_EQ(3, shelf_model()->item_count());  // It should be still there.
   test.RunMessageLoopUntilAnimationsDone();
 
   // Test #3: Check that the now known item dropped into the launcher will
@@ -1971,12 +1969,12 @@
   generator.MoveMouseTo(bounds_shelf_1.CenterPoint().x(),
                         bounds_shelf_1.CenterPoint().y());
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(3, model_->item_count());  // No new item got added.
+  EXPECT_EQ(3, shelf_model()->item_count());  // No new item got added.
   EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test());
   generator.ReleaseLeftButton();
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test());
-  EXPECT_EQ(3, model_->item_count());  // And it remains that way.
+  EXPECT_EQ(3, shelf_model()->item_count());  // And it remains that way.
 
   // Test #4: Check that by pressing ESC the operation gets cancelled.
   generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(),
@@ -2015,7 +2013,7 @@
   AppListService* service = AppListService::Get();
 
   // There should be two items in our shelf by this time.
-  EXPECT_EQ(2, model_->item_count());
+  EXPECT_EQ(2, shelf_model()->item_count());
   EXPECT_FALSE(service->IsAppListVisible());
 
   // Open the app list menu and check that the drag and drop host was set.
@@ -2072,7 +2070,7 @@
   base::RunLoop().RunUntilIdle();
 
   // Check that a new item got created.
-  EXPECT_EQ(3, model_->item_count());
+  EXPECT_EQ(3, shelf_model()->item_count());
   EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test());
 
   // Move it to an empty slot on grid_view.
@@ -2081,13 +2079,13 @@
   generator.MoveMouseTo(empty_slot_rect.CenterPoint().x(),
                         empty_slot_rect.CenterPoint().y());
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(2, model_->item_count());
+  EXPECT_EQ(2, shelf_model()->item_count());
   EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test());
 
   // Dropping it should keep the shelf as it originally was.
   generator.ReleaseLeftButton();
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(2, model_->item_count());
+  EXPECT_EQ(2, shelf_model()->item_count());
 }
 
 // Do tests for removal of items from the shelf by dragging.
@@ -2100,14 +2098,14 @@
   // Create a known application and check that we have 3 items in the shelf.
   CreateShortcut("app1");
   test.RunMessageLoopUntilAnimationsDone();
-  EXPECT_EQ(3, model_->item_count());
+  EXPECT_EQ(3, shelf_model()->item_count());
 
   // Test #1: Ripping out the browser item should not change anything.
   int browser_index = GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT);
   EXPECT_LE(0, browser_index);
   RipOffItemIndex(browser_index, &generator, &test, RIP_OFF_ITEM);
   // => It should not have been removed and the location should be unchanged.
-  EXPECT_EQ(3, model_->item_count());
+  EXPECT_EQ(3, shelf_model()->item_count());
   EXPECT_EQ(browser_index, GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT));
   // Make sure that the hide state has been unset after the snap back animation
   // finished.
@@ -2120,21 +2118,21 @@
   EXPECT_LE(0, app_index);
   RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM_AND_CANCEL);
   // => It should not have been removed and the location should be unchanged.
-  ASSERT_EQ(3, model_->item_count());
+  ASSERT_EQ(3, shelf_model()->item_count());
   EXPECT_EQ(app_index, GetIndexOfShelfItemType(ash::TYPE_PINNED_APP));
 
   // Test #3: Ripping out the application and moving it back in should not
   // change anything.
   RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM_AND_RETURN);
   // => It should not have been removed and the location should be unchanged.
-  ASSERT_EQ(3, model_->item_count());
+  ASSERT_EQ(3, shelf_model()->item_count());
   // Through the operation the index might have changed.
   app_index = GetIndexOfShelfItemType(ash::TYPE_PINNED_APP);
 
   // Test #4: Ripping out the application should remove the item.
   RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM);
   // => It should not have been removed and the location should be unchanged.
-  EXPECT_EQ(2, model_->item_count());
+  EXPECT_EQ(2, shelf_model()->item_count());
   EXPECT_EQ(-1, GetIndexOfShelfItemType(ash::TYPE_PINNED_APP));
 
   // Test #5: Uninstalling an application while it is being ripped off should
@@ -2142,15 +2140,15 @@
   CreateShortcut("app2");
   test.RunMessageLoopUntilAnimationsDone();
   int app2_index = GetIndexOfShelfItemType(ash::TYPE_PINNED_APP);
-  EXPECT_EQ(3, model_->item_count());  // And it remains that way.
+  EXPECT_EQ(3, shelf_model()->item_count());  // And it remains that way.
   RipOffItemIndex(app2_index, &generator, &test,
                   RIP_OFF_ITEM_AND_DONT_RELEASE_MOUSE);
   controller_->UnpinAppWithID("app2");
   test.RunMessageLoopUntilAnimationsDone();
-  EXPECT_EQ(2, model_->item_count());  // The item should now be gone.
+  EXPECT_EQ(2, shelf_model()->item_count());  // The item should now be gone.
   generator.ReleaseLeftButton();
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(2, model_->item_count());  // And it remains that way.
+  EXPECT_EQ(2, shelf_model()->item_count());  // And it remains that way.
   EXPECT_EQ(-1, GetIndexOfShelfItemType(ash::TYPE_PINNED_APP));
 
   // Test #6: Ripping out the application when the overflow button exists.
@@ -2172,7 +2170,7 @@
   PinFakeApp(fake_app_id);
   test.RunMessageLoopUntilAnimationsDone();
 
-  int total_count = model_->item_count();
+  int total_count = shelf_model()->item_count();
   app_index = GetIndexOfShelfItemType(ash::TYPE_PINNED_APP);
   RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM);
   // When an item is ripped off from the shelf that has overflow button
@@ -2180,12 +2178,12 @@
   // suppressing any further events. If handled correctly the operation will
   // however correctly done and the item will get removed (as well as the
   // overflow button).
-  EXPECT_EQ(total_count - 1, model_->item_count());
+  EXPECT_EQ(total_count - 1, shelf_model()->item_count());
   EXPECT_TRUE(test.IsOverflowButtonVisible());
 
   // Rip off again and the overflow button should has disappeared.
   RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM);
-  EXPECT_EQ(total_count - 2, model_->item_count());
+  EXPECT_EQ(total_count - 2, shelf_model()->item_count());
   EXPECT_FALSE(test.IsOverflowButtonVisible());
 }
 
@@ -2205,18 +2203,23 @@
   const gfx::Rect bounds = button->GetBoundsInScreen();
   generator.MoveMouseTo(bounds.CenterPoint().x(), bounds.CenterPoint().y());
   generator.PressRightButton();
+  // Spin a run loop to allow Ash and Chrome to coordinate to show the menu.
+  base::RunLoop().RunUntilIdle();
   // Context menu is shown on right button press and no drag context is set.
   EXPECT_TRUE(test.shelf_view()->IsShowingMenu());
   EXPECT_FALSE(test.shelf_view()->drag_view());
   generator.ReleaseRightButton();
+  base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(test.shelf_view()->drag_view());
 
   // Press left button. Menu should close and drag context is set to |button|.
   generator.PressLeftButton();
-  EXPECT_FALSE(test.shelf_view()->IsShowingMenu());
   base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(test.shelf_view()->IsShowingMenu());
   EXPECT_EQ(test.shelf_view()->drag_view(), button);
   generator.ReleaseLeftButton();
+  // Spin a run loop to allow Ash and Chrome to coordinate to close the menu.
+  base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(test.shelf_view()->drag_view());
 }
 
@@ -2233,7 +2236,7 @@
   ash::ShelfViewTestAPI test(shelf_->GetShelfViewForTesting());
   AppListService* service = AppListService::Get();
   // There should be two items in our shelf by this time.
-  EXPECT_EQ(2, model_->item_count());
+  EXPECT_EQ(2, shelf_model()->item_count());
   EXPECT_FALSE(service->IsAppListVisible());
 
   // Open the app list menu and check that the drag and drop host was set.
@@ -2267,25 +2270,26 @@
   EXPECT_EQ(tab_count + 1, tab_strip->count());
 }
 
-// Check ash::ShelfItemDelegate of Browser Shortcut functionality.
+// Check browser shortcut item functionality.
 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTestNoDefaultBrowser,
                        BrowserShortcutLauncherItemController) {
   ash::ShelfItemDelegate* item_controller =
       controller_->GetBrowserShortcutLauncherItemController();
-  const ash::ShelfID id = item_controller->shelf_id();
-  EXPECT_FALSE(id.IsNull());
+  EXPECT_TRUE(item_controller);
+  const ash::ShelfID browser_id = item_controller->shelf_id();
+  EXPECT_EQ(extension_misc::kChromeAppId, browser_id.app_id);
 
   // Get the number of browsers.
   size_t running_browser = chrome::GetTotalBrowserCount();
   EXPECT_EQ(0u, running_browser);
-  EXPECT_FALSE(controller_->IsOpen(id));
+  EXPECT_FALSE(controller_->IsOpen(browser_id));
 
   // Activate. This creates new browser
-  SelectItem(item_controller, ui::ET_UNKNOWN);
+  SelectItem(browser_id, ui::ET_UNKNOWN);
   // New Window is created.
   running_browser = chrome::GetTotalBrowserCount();
   EXPECT_EQ(1u, running_browser);
-  EXPECT_TRUE(controller_->IsOpen(id));
+  EXPECT_TRUE(controller_->IsOpen(browser_id));
 
   // Minimize Window.
   Browser* browser = chrome::FindLastActive();
@@ -2294,10 +2298,10 @@
   EXPECT_TRUE(browser->window()->IsMinimized());
 
   // Activate again. This doesn't create new browser, it activates the window.
-  SelectItem(item_controller, ui::ET_UNKNOWN);
+  SelectItem(browser_id, ui::ET_UNKNOWN);
   running_browser = chrome::GetTotalBrowserCount();
   EXPECT_EQ(1u, running_browser);
-  EXPECT_TRUE(controller_->IsOpen(id));
+  EXPECT_TRUE(controller_->IsOpen(browser_id));
   EXPECT_FALSE(browser->window()->IsMinimized());
 }
 
@@ -2306,21 +2310,21 @@
   EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
   EXPECT_EQ(1, browser()->tab_strip_model()->count());
   EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
-  EXPECT_EQ(2, model_->item_count());
+  EXPECT_EQ(2, shelf_model()->item_count());
 
   aura::Window* window = browser()->window()->GetNativeWindow();
 
   int browser_index = GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT);
-  ash::ShelfID browser_id = model_->items()[browser_index].id;
+  ash::ShelfID browser_id = shelf_model()->items()[browser_index].id;
   ash::ShelfID id =
       ash::ShelfID::Deserialize(window->GetProperty(ash::kShelfIDKey));
   EXPECT_EQ(browser_id, id);
 
   ash::ShelfID app_id = CreateShortcut("app1");
-  EXPECT_EQ(3, model_->item_count());
+  EXPECT_EQ(3, shelf_model()->item_count());
 
   // Create and activate a new tab for "app1" and expect an application ShelfID.
-  Shelf::ActivateShelfItem(model_->ItemIndexByID(app_id));
+  SelectItem(app_id);
   EXPECT_EQ(2, browser()->tab_strip_model()->count());
   EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
   id = ash::ShelfID::Deserialize(window->GetProperty(ash::kShelfIDKey));
@@ -2349,6 +2353,8 @@
 
     ++items_added;
     ASSERT_LT(items_added, 10000);
+    // Spin a run loop so Ash can synchronize ShelfModels and update ShelfView.
+    base::RunLoop().RunUntilIdle();
   }
 
   // Now show overflow bubble.
@@ -2368,7 +2374,7 @@
   // We assume that the web store is always there (which it apparently is).
   controller_->PinAppWithID(extensions::kWebStoreAppId);
   const ash::ShelfID id(extensions::kWebStoreAppId);
-  EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(id)->status);
+  EXPECT_EQ(ash::STATUS_CLOSED, shelf_model()->ItemByID(id)->status);
 
   // Create a windowed application.
   AppLaunchParams params = CreateAppLaunchParamsUserContainer(
@@ -2376,7 +2382,7 @@
       WindowOpenDisposition::NEW_FOREGROUND_TAB, extensions::SOURCE_TEST);
   params.container = extensions::LAUNCH_CONTAINER_WINDOW;
   OpenApplication(params);
-  EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(id)->status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(id)->status);
 
   // Find the browser which holds our app.
   Browser* app_browser = NULL;
@@ -2396,23 +2402,21 @@
                                GURL("http://www.foo.com/bar.html"));
   // Make sure the navigation was entirely performed.
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(id)->status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(id)->status);
   app_browser->tab_strip_model()->CloseWebContentsAt(0,
                                                      TabStripModel::CLOSE_NONE);
   // Make sure that the app is really gone.
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(id)->status);
+  EXPECT_EQ(ash::STATUS_CLOSED, shelf_model()->ItemByID(id)->status);
 }
 
-// Checks that a opening a settings and task manager windows creates a new
-// launcher items.
+// Ensure opening settings and task manager windows create new shelf items.
 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, SettingsAndTaskManagerWindows) {
   chrome::SettingsWindowManager* settings_manager =
       chrome::SettingsWindowManager::GetInstance();
-  ash::ShelfModel* shelf_model = ash::Shell::Get()->shelf_model();
 
   // Get the number of items in the shelf and browser menu.
-  int item_count = shelf_model->item_count();
+  int item_count = shelf_model()->item_count();
   // At least App List should exist.
   ASSERT_GE(item_count, 1);
   size_t browser_count = NumberOfDetectedLauncherBrowsers(false);
@@ -2421,17 +2425,21 @@
   // number of shelf items should increase.
   settings_manager->ShowChromePageForProfile(
       browser()->profile(), chrome::GetSettingsUrl(std::string()));
+  // Spin a run loop to sync Ash's ShelfModel change for the settings window.
+  base::RunLoop().RunUntilIdle();
   Browser* settings_browser =
       settings_manager->FindBrowserForProfile(browser()->profile());
   ASSERT_TRUE(settings_browser);
   EXPECT_EQ(browser_count, NumberOfDetectedLauncherBrowsers(false));
-  EXPECT_EQ(item_count + 1, shelf_model->item_count());
+  EXPECT_EQ(item_count + 1, shelf_model()->item_count());
 
   chrome::ShowTaskManager(browser());
-  EXPECT_EQ(item_count + 2, shelf_model->item_count());
+  // Spin a run loop to sync Ash's ShelfModel change for the task manager.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(item_count + 2, shelf_model()->item_count());
 
   // Validates that all items have valid app id.
-  for (const auto& item : shelf_model->items())
+  for (const auto& item : shelf_model()->items())
     EXPECT_TRUE(crx_file::id_util::IdIsValid(item.id.app_id));
 
   // TODO(stevenjb): Test multiprofile on Chrome OS when test support is addded.
@@ -2456,9 +2464,10 @@
   const ash::ShelfID bookmark_app_shelf_id(bookmark_app->id());
 
   // The apps should be closed.
-  EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(hosted_app_shelf_id)->status);
   EXPECT_EQ(ash::STATUS_CLOSED,
-            model_->ItemByID(bookmark_app_shelf_id)->status);
+            shelf_model()->ItemByID(hosted_app_shelf_id)->status);
+  EXPECT_EQ(ash::STATUS_CLOSED,
+            shelf_model()->ItemByID(bookmark_app_shelf_id)->status);
 
   // Navigate to the app's launch URLs in two tabs.
   ui_test_utils::NavigateToURL(
@@ -2468,9 +2477,10 @@
       WindowOpenDisposition::NEW_FOREGROUND_TAB, 0);
 
   // The apps should now be running, with the last opened app active.
-  EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(hosted_app_shelf_id)->status);
+  EXPECT_EQ(ash::STATUS_RUNNING,
+            shelf_model()->ItemByID(hosted_app_shelf_id)->status);
   EXPECT_EQ(ash::STATUS_ACTIVE,
-            model_->ItemByID(bookmark_app_shelf_id)->status);
+            shelf_model()->ItemByID(bookmark_app_shelf_id)->status);
 
   // Now use the launcher controller to activate the apps.
   controller_->ActivateApp(hosted_app->id(), ash::LAUNCH_FROM_APP_LIST, 0);
@@ -2505,9 +2515,10 @@
                             extensions::LAUNCH_TYPE_WINDOW);
 
   // The apps should be closed.
-  EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(hosted_app_shelf_id)->status);
   EXPECT_EQ(ash::STATUS_CLOSED,
-            model_->ItemByID(bookmark_app_shelf_id)->status);
+            shelf_model()->ItemByID(hosted_app_shelf_id)->status);
+  EXPECT_EQ(ash::STATUS_CLOSED,
+            shelf_model()->ItemByID(bookmark_app_shelf_id)->status);
 
   // Navigate to the app's launch URLs in two tabs.
   ui_test_utils::NavigateToURL(
@@ -2517,9 +2528,10 @@
       WindowOpenDisposition::NEW_FOREGROUND_TAB, 0);
 
   // The apps should still be closed.
-  EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(hosted_app_shelf_id)->status);
   EXPECT_EQ(ash::STATUS_CLOSED,
-            model_->ItemByID(bookmark_app_shelf_id)->status);
+            shelf_model()->ItemByID(hosted_app_shelf_id)->status);
+  EXPECT_EQ(ash::STATUS_CLOSED,
+            shelf_model()->ItemByID(bookmark_app_shelf_id)->status);
 
   // Now use the launcher controller to activate the apps.
   controller_->ActivateApp(hosted_app->id(), ash::LAUNCH_FROM_APP_LIST, 0);
@@ -2529,9 +2541,10 @@
   EXPECT_EQ(3u, chrome::GetBrowserCount(browser()->profile()));
 
   // The apps should now be running, with the last opened app active.
-  EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(hosted_app_shelf_id)->status);
+  EXPECT_EQ(ash::STATUS_RUNNING,
+            shelf_model()->ItemByID(hosted_app_shelf_id)->status);
   EXPECT_EQ(ash::STATUS_ACTIVE,
-            model_->ItemByID(bookmark_app_shelf_id)->status);
+            shelf_model()->ItemByID(bookmark_app_shelf_id)->status);
 }
 
 // Test that "Close" is shown in the context menu when there are opened browsers
@@ -2556,10 +2569,11 @@
 
 // Chrome's ShelfModel should have AppList and browser items and delegates.
 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, ShelfModelInitialization) {
-  ash::ShelfModel* model = controller_->shelf_model();
-  EXPECT_EQ(2, model->item_count());
-  EXPECT_EQ(ash::kAppListId, model->items()[0].id.app_id);
-  EXPECT_TRUE(model->GetShelfItemDelegate(model->items()[0].id));
-  EXPECT_EQ(extension_misc::kChromeAppId, model->items()[1].id.app_id);
-  EXPECT_TRUE(model->GetShelfItemDelegate(model->items()[1].id));
+  EXPECT_EQ(2, shelf_model()->item_count());
+  EXPECT_EQ(ash::kAppListId, shelf_model()->items()[0].id.app_id);
+  EXPECT_TRUE(
+      shelf_model()->GetShelfItemDelegate(shelf_model()->items()[0].id));
+  EXPECT_EQ(extension_misc::kChromeAppId, shelf_model()->items()[1].id.app_id);
+  EXPECT_TRUE(
+      shelf_model()->GetShelfItemDelegate(shelf_model()->items()[1].id));
 }
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager.cc
index 55102972..913d437f 100644
--- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager.cc
+++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager.cc
@@ -20,12 +20,6 @@
 MultiUserWindowManager* g_instance = nullptr;
 }  // namespace
 
-// Caching the current multi profile mode to avoid expensive detection
-// operations.
-MultiUserWindowManager::MultiProfileMode
-    MultiUserWindowManager::multi_user_mode_ =
-        MultiUserWindowManager::MULTI_PROFILE_MODE_UNINITIALIZED;
-
 // static
 MultiUserWindowManager* MultiUserWindowManager::GetInstance() {
   return g_instance;
@@ -33,7 +27,6 @@
 
 MultiUserWindowManager* MultiUserWindowManager::CreateInstance() {
   DCHECK(!g_instance);
-  multi_user_mode_ = MULTI_PROFILE_MODE_OFF;
   ash::MultiProfileUMA::SessionMode mode =
       ash::MultiProfileUMA::SESSION_SINGLE_USER_MODE;
   // TODO(crbug.com/557406): Enable this component in Mash. The object itself
@@ -45,7 +38,6 @@
             user_manager::UserManager::Get()->GetActiveUser()->GetAccountId());
     g_instance = manager;
     manager->Init();
-    multi_user_mode_ = MULTI_PROFILE_MODE_ON;
     mode = ash::MultiProfileUMA::SESSION_SEPARATE_DESKTOP_MODE;
   }
   ash::MultiProfileUMA::RecordSessionMode(mode);
@@ -58,30 +50,24 @@
 }
 
 // static
-MultiUserWindowManager::MultiProfileMode
-MultiUserWindowManager::GetMultiProfileMode() {
-  return multi_user_mode_;
-}
-
-// static
 bool MultiUserWindowManager::ShouldShowAvatar(aura::Window* window) {
-  // Note: In case of the M-31 mode the window manager won't exist.
-  if (GetMultiProfileMode() == MULTI_PROFILE_MODE_ON) {
-    // If the window is shown on a different desktop than the user, it should
-    // have the avatar icon
-    MultiUserWindowManager* instance = GetInstance();
-    return !instance->IsWindowOnDesktopOfUser(window,
-                                              instance->GetWindowOwner(window));
-  }
-  return false;
+  // Session restore can open a window for the first user before the instance
+  // is created.
+  if (!g_instance)
+    return false;
+
+  // Show the avatar icon if the window is on a different desktop than the
+  // window's owner's desktop. The stub implementation does the right thing
+  // for single-user mode.
+  return !g_instance->IsWindowOnDesktopOfUser(
+      window, g_instance->GetWindowOwner(window));
 }
 
 // static
 void MultiUserWindowManager::DeleteInstance() {
   DCHECK(g_instance);
   delete g_instance;
-  g_instance = NULL;
-  multi_user_mode_ = MULTI_PROFILE_MODE_UNINITIALIZED;
+  g_instance = nullptr;
 }
 
 void MultiUserWindowManager::SetInstanceForTest(
@@ -89,7 +75,6 @@
   if (g_instance)
     DeleteInstance();
   g_instance = instance;
-  multi_user_mode_ = MULTI_PROFILE_MODE_ON;
 }
 
 }  // namespace chrome
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager.h b/chrome/browser/ui/ash/multi_user/multi_user_window_manager.h
index c4bdc49c2..65b0d90 100644
--- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager.h
+++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager.h
@@ -56,13 +56,6 @@
     virtual ~Observer() {}
   };
 
-  // The multi profile mode in use.
-  enum MultiProfileMode {
-    MULTI_PROFILE_MODE_UNINITIALIZED,  // Not initialized yet.
-    MULTI_PROFILE_MODE_OFF,            // Single user mode.
-    MULTI_PROFILE_MODE_ON,             // Each user has their own desktop.
-  };
-
   // Creates an instance of the MultiUserWindowManager.
   // Note: This function might fail if due to the desired mode the
   // MultiUserWindowManager is not required.
@@ -72,11 +65,6 @@
   // this will return NULL.
   static MultiUserWindowManager* GetInstance();
 
-  // Return the current multi profile mode operation. If CreateInstance was not
-  // yet called (or was already destroyed), MULTI_PROFILE_MODE_UNINITIALIZED
-  // will get returned.
-  static MultiProfileMode GetMultiProfileMode();
-
   // Whether or not the window's title should show the avatar. On chromeos,
   // this is true when the owner of the window is different from the owner of
   // the desktop.
@@ -139,10 +127,6 @@
 
  protected:
   virtual ~MultiUserWindowManager() {}
-
- private:
-  // Caching the current multi profile mode since the detection is expensive.
-  static MultiProfileMode multi_user_mode_;
 };
 
 }  // namespace chrome
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc
index 6252234..76a1118 100644
--- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc
+++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc
@@ -529,23 +529,20 @@
   WindowToEntryMap::iterator it = window_to_entry_.find(window);
   it->second->set_show_for_user(account_id);
 
-  // Show avatar icon on the teleported window.
-  if (GetMultiProfileMode() == MULTI_PROFILE_MODE_ON) {
-    // Tests could either not have a UserManager or the UserManager does not
-    // know the window owner.
-    const user_manager::User* const window_owner =
-        user_manager::UserManager::IsInitialized()
-            ? user_manager::UserManager::Get()->FindUser(owner)
-            : nullptr;
+  // Tests could either not have a UserManager or the UserManager does not
+  // know the window owner.
+  const user_manager::User* const window_owner =
+      user_manager::UserManager::IsInitialized()
+          ? user_manager::UserManager::Get()->FindUser(owner)
+          : nullptr;
 
-    const bool teleported = !IsWindowOnDesktopOfUser(window, owner);
-    if (window_owner && teleported) {
-      window->SetProperty(
-          aura::client::kAvatarIconKey,
-          new gfx::ImageSkia(GetAvatarImageForUser(window_owner)));
-    } else {
-      window->ClearProperty(aura::client::kAvatarIconKey);
-    }
+  const bool teleported = !IsWindowOnDesktopOfUser(window, owner);
+  if (window_owner && teleported) {
+    window->SetProperty(
+        aura::client::kAvatarIconKey,
+        new gfx::ImageSkia(GetAvatarImageForUser(window_owner)));
+  } else {
+    window->ClearProperty(aura::client::kAvatarIconKey);
   }
 
   // Show the window if the added user is the current one.
diff --git a/chrome/browser/ui/ash/palette_delegate_chromeos.cc b/chrome/browser/ui/ash/palette_delegate_chromeos.cc
index 527922b..326dafa 100644
--- a/chrome/browser/ui/ash/palette_delegate_chromeos.cc
+++ b/chrome/browser/ui/ash/palette_delegate_chromeos.cc
@@ -50,6 +50,10 @@
     delay_timer_.reset();
   }
 
+  void set_disable_on_failed_selection(bool disable_on_failed_selection) {
+    disable_on_failed_selection_ = disable_on_failed_selection;
+  }
+
   bool start_session_pending() const { return delay_timer_.get(); }
 
  private:
@@ -63,7 +67,15 @@
                    base::Unretained(this), rect),
         false /* not repeating */);
     delay_timer_->Reset();
+    DisableMetalayer();
+  }
 
+  void HandleFailedSelection() override {
+    if (disable_on_failed_selection_)
+      DisableMetalayer();
+  }
+
+  void DisableMetalayer() {
     DCHECK(on_selection_done_);
     // This will disable the metalayer tool, which will result in a synchronous
     // call to PaletteDelegateChromeOS::HideMetalayer.
@@ -83,6 +95,7 @@
 
   std::unique_ptr<base::Timer> delay_timer_;
   base::OnceClosure on_selection_done_;
+  bool disable_on_failed_selection_ = true;
 
   DISALLOW_COPY_AND_ASSIGN(VoiceInteractionSelectionObserver);
 };
@@ -219,7 +232,8 @@
   ash::Shell::Get()->screenshot_controller()->CancelScreenshotSession();
 }
 
-void PaletteDelegateChromeOS::ShowMetalayer(base::OnceClosure done) {
+void PaletteDelegateChromeOS::ShowMetalayer(base::OnceClosure done,
+                                            bool via_button) {
   auto* service =
       arc::ArcVoiceInteractionFrameworkService::GetForBrowserContext(profile_);
   if (!service)
@@ -231,6 +245,7 @@
         base::MakeUnique<VoiceInteractionSelectionObserver>(profile_);
   }
   highlighter_selection_observer_->set_on_selection_done(std::move(done));
+  highlighter_selection_observer_->set_disable_on_failed_selection(via_button);
   ash::Shell::Get()->highlighter_controller()->SetEnabled(true);
 }
 
diff --git a/chrome/browser/ui/ash/palette_delegate_chromeos.h b/chrome/browser/ui/ash/palette_delegate_chromeos.h
index beaba44..45bfdae1 100644
--- a/chrome/browser/ui/ash/palette_delegate_chromeos.h
+++ b/chrome/browser/ui/ash/palette_delegate_chromeos.h
@@ -43,7 +43,7 @@
   void TakeScreenshot() override;
   void TakePartialScreenshot(const base::Closure& done) override;
   void CancelPartialScreenshot() override;
-  void ShowMetalayer(base::OnceClosure done) override;
+  void ShowMetalayer(base::OnceClosure done, bool via_button) override;
   void HideMetalayer() override;
 
   // user_manager::UserManager::UserSessionStateObserver:
diff --git a/chrome/browser/ui/blocked_content/blocked_window_params.cc b/chrome/browser/ui/blocked_content/blocked_window_params.cc
index 76e753b..176ce79 100644
--- a/chrome/browser/ui/blocked_content/blocked_window_params.cc
+++ b/chrome/browser/ui/blocked_content/blocked_window_params.cc
@@ -7,6 +7,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 #include "url/gurl.h"
@@ -35,7 +36,7 @@
 chrome::NavigateParams BlockedWindowParams::CreateNavigateParams(
     content::WebContents* web_contents) const {
   GURL popup_url(target_url_);
-  web_contents->GetRenderProcessHost()->FilterURL(false, &popup_url);
+  web_contents->GetMainFrame()->GetProcess()->FilterURL(false, &popup_url);
   chrome::NavigateParams nav_params(
       Profile::FromBrowserContext(web_contents->GetBrowserContext()),
       popup_url,
diff --git a/chrome/browser/ui/blocked_content/popup_opener_tab_helper.cc b/chrome/browser/ui/blocked_content/popup_opener_tab_helper.cc
new file mode 100644
index 0000000..db29b7b
--- /dev/null
+++ b/chrome/browser/ui/blocked_content/popup_opener_tab_helper.cc
@@ -0,0 +1,83 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/blocked_content/popup_opener_tab_helper.h"
+
+#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/time/default_tick_clock.h"
+#include "chrome/browser/ui/blocked_content/scoped_visibility_tracker.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/web_contents.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+DEFINE_WEB_CONTENTS_USER_DATA_KEY(PopupOpenerTabHelper);
+
+PopupOpenerTabHelper::~PopupOpenerTabHelper() {
+  // TODO(csharrison): Add breakout metrics for when this WebContents has opened
+  // a popup in its lifetime.
+  if (visibility_tracker_) {
+    UMA_HISTOGRAM_LONG_TIMES("Tab.VisibleTimeAfterCrossOriginRedirect",
+                             visibility_tracker_->GetForegroundDuration());
+  }
+}
+
+PopupOpenerTabHelper::PopupOpenerTabHelper(content::WebContents* web_contents)
+    : content::WebContentsObserver(web_contents),
+      tick_clock_(base::MakeUnique<base::DefaultTickClock>()) {}
+
+void PopupOpenerTabHelper::DidStartNavigation(
+    content::NavigationHandle* navigation_handle) {
+  if (visibility_tracker_)
+    return;
+
+  if (navigation_handle->IsInMainFrame() && !web_contents()->IsVisible())
+    pending_background_navigations_.insert(navigation_handle);
+  // There should be at max 2 main frame navigations occurring at the same time.
+  DCHECK_LE(pending_background_navigations_.size(), 2u);
+}
+
+void PopupOpenerTabHelper::DidFinishNavigation(
+    content::NavigationHandle* navigation_handle) {
+  if (visibility_tracker_ || !navigation_handle->IsInMainFrame())
+    return;
+
+  size_t num_erased = pending_background_navigations_.erase(navigation_handle);
+  if (!num_erased || !navigation_handle->HasCommitted() ||
+      navigation_handle->IsErrorPage()) {
+    return;
+  }
+
+  // Only consider navigations without a user gesture.
+  if (navigation_handle->HasUserGesture())
+    return;
+
+  // An empty previous URL indicates this was the first load. We filter these
+  // out because we're primarily interested in sites which navigate themselves
+  // away while in the background.
+  const GURL& previous_main_frame_url = navigation_handle->GetPreviousURL();
+  if (previous_main_frame_url.is_empty())
+    return;
+
+  // Only track cross-origin navigations.
+  if (url::Origin(previous_main_frame_url)
+          .IsSameOriginWith(url::Origin(navigation_handle->GetURL()))) {
+    return;
+  }
+
+  visibility_tracker_ = base::MakeUnique<ScopedVisibilityTracker>(
+      std::move(tick_clock_), false /* is_visible */);
+  pending_background_navigations_.clear();
+}
+
+void PopupOpenerTabHelper::WasShown() {
+  if (visibility_tracker_)
+    visibility_tracker_->OnShown();
+}
+
+void PopupOpenerTabHelper::WasHidden() {
+  if (visibility_tracker_)
+    visibility_tracker_->OnHidden();
+}
diff --git a/chrome/browser/ui/blocked_content/popup_opener_tab_helper.h b/chrome/browser/ui/blocked_content/popup_opener_tab_helper.h
new file mode 100644
index 0000000..1385a70
--- /dev/null
+++ b/chrome/browser/ui/blocked_content/popup_opener_tab_helper.h
@@ -0,0 +1,64 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_BLOCKED_CONTENT_POPUP_OPENER_TAB_HELPER_H_
+#define CHROME_BROWSER_UI_BLOCKED_CONTENT_POPUP_OPENER_TAB_HELPER_H_
+
+#include <memory>
+#include <utility>
+
+#include "base/containers/flat_set.h"
+#include "base/macros.h"
+#include "base/time/tick_clock.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents_user_data.h"
+
+namespace content {
+class NavigationHandle;
+class WebContents;
+}  // namespace content
+
+class ScopedVisibilityTracker;
+
+// This class tracks WebContents for the purpose of logging metrics related to
+// popup openers.
+class PopupOpenerTabHelper
+    : public content::WebContentsObserver,
+      public content::WebContentsUserData<PopupOpenerTabHelper> {
+ public:
+  ~PopupOpenerTabHelper() override;
+
+  void set_tick_clock_for_testing(std::unique_ptr<base::TickClock> tick_clock) {
+    tick_clock_ = std::move(tick_clock);
+  }
+
+ private:
+  friend class content::WebContentsUserData<PopupOpenerTabHelper>;
+
+  explicit PopupOpenerTabHelper(content::WebContents* web_contents);
+
+  // content::WebContentsObserver:
+  void DidStartNavigation(
+      content::NavigationHandle* navigation_handle) override;
+  void DidFinishNavigation(
+      content::NavigationHandle* navigation_handle) override;
+  void WasShown() override;
+  void WasHidden() override;
+
+  // Tracks navigations we are interested in, e.g. ones which start when the
+  // WebContents is not visible.
+  base::flat_set<content::NavigationHandle*> pending_background_navigations_;
+
+  // The clock which gets passed to the |visibility_tracker_|.
+  std::unique_ptr<base::TickClock> tick_clock_;
+
+  // The |visibility_tracker| tracks the time this WebContents is in the
+  // foreground. Will be nullptr until we redirect cross-origin in the
+  // background.
+  std::unique_ptr<ScopedVisibilityTracker> visibility_tracker_;
+
+  DISALLOW_COPY_AND_ASSIGN(PopupOpenerTabHelper);
+};
+
+#endif  // CHROME_BROWSER_UI_BLOCKED_CONTENT_POPUP_OPENER_TAB_HELPER_H_
diff --git a/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc b/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc
new file mode 100644
index 0000000..12764b35
--- /dev/null
+++ b/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc
@@ -0,0 +1,146 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/blocked_content/popup_opener_tab_helper.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/test/histogram_tester.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "base/time/time.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/navigation_simulator.h"
+#include "content/public/test/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+constexpr char kTabVisibleTimeAfterRedirect[] =
+    "Tab.VisibleTimeAfterCrossOriginRedirect";
+
+class PopupOpenerTabHelperTest : public ChromeRenderViewHostTestHarness {
+ public:
+  PopupOpenerTabHelperTest() : ChromeRenderViewHostTestHarness() {}
+  ~PopupOpenerTabHelperTest() override {}
+
+  void SetUp() override {
+    ChromeRenderViewHostTestHarness::SetUp();
+    PopupOpenerTabHelper::CreateForWebContents(web_contents());
+
+    auto tick_clock = base::MakeUnique<base::SimpleTestTickClock>();
+    raw_clock_ = tick_clock.get();
+    PopupOpenerTabHelper::FromWebContents(web_contents())
+        ->set_tick_clock_for_testing(std::move(tick_clock));
+
+    EXPECT_TRUE(web_contents()->IsVisible());
+  }
+
+  void NavigateAndCommitWithoutGesture(const GURL& url) {
+    std::unique_ptr<content::NavigationSimulator> simulator =
+        content::NavigationSimulator::CreateRendererInitiated(url, main_rfh());
+    simulator->SetHasUserGesture(false);
+    simulator->Commit();
+  }
+
+  base::SimpleTestTickClock* raw_clock() { return raw_clock_; }
+
+  base::HistogramTester* histogram_tester() { return &histogram_tester_; }
+
+ private:
+  base::HistogramTester histogram_tester_;
+  base::SimpleTestTickClock* raw_clock_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(PopupOpenerTabHelperTest);
+};
+
+TEST_F(PopupOpenerTabHelperTest, BackgroundNavigation_LogsMetrics) {
+  NavigateAndCommitWithoutGesture(GURL("https://first.test/"));
+  web_contents()->WasHidden();
+  NavigateAndCommitWithoutGesture(GURL("https://example.test/"));
+
+  raw_clock()->Advance(base::TimeDelta::FromMinutes(1));
+  web_contents()->WasShown();
+  raw_clock()->Advance(base::TimeDelta::FromSeconds(1));
+
+  histogram_tester()->ExpectTotalCount(kTabVisibleTimeAfterRedirect, 0);
+  DeleteContents();
+  histogram_tester()->ExpectTotalCount(kTabVisibleTimeAfterRedirect, 1);
+  histogram_tester()->ExpectUniqueSample(
+      kTabVisibleTimeAfterRedirect,
+      base::TimeDelta::FromSeconds(1).InMilliseconds(), 1);
+}
+
+TEST_F(PopupOpenerTabHelperTest, FirstNavigation_NoLogging) {
+  web_contents()->WasHidden();
+  NavigateAndCommitWithoutGesture(GURL("https://first.test/"));
+  raw_clock()->Advance(base::TimeDelta::FromMinutes(1));
+  DeleteContents();
+  histogram_tester()->ExpectTotalCount(kTabVisibleTimeAfterRedirect, 0);
+}
+
+TEST_F(PopupOpenerTabHelperTest, VisibleNavigation_NoLogging) {
+  NavigateAndCommitWithoutGesture(GURL("https://first.test/"));
+  NavigateAndCommitWithoutGesture(GURL("https://example.test/"));
+  raw_clock()->Advance(base::TimeDelta::FromMinutes(1));
+  DeleteContents();
+  histogram_tester()->ExpectTotalCount(kTabVisibleTimeAfterRedirect, 0);
+}
+
+TEST_F(PopupOpenerTabHelperTest, AbortedNavigation_NoLogging) {
+  NavigateAndCommitWithoutGesture(GURL("https://first.test/"));
+  web_contents()->WasHidden();
+
+  std::unique_ptr<content::NavigationSimulator> simulator =
+      content::NavigationSimulator::CreateRendererInitiated(
+          GURL("https://example.test/"), main_rfh());
+  simulator->SetHasUserGesture(false);
+  simulator->Fail(net::ERR_ABORTED);
+
+  raw_clock()->Advance(base::TimeDelta::FromMinutes(1));
+  DeleteContents();
+  histogram_tester()->ExpectTotalCount(kTabVisibleTimeAfterRedirect, 0);
+}
+
+TEST_F(PopupOpenerTabHelperTest, FailedNavigation_NoLogging) {
+  NavigateAndCommitWithoutGesture(GURL("https://first.test/"));
+  web_contents()->WasHidden();
+
+  std::unique_ptr<content::NavigationSimulator> simulator =
+      content::NavigationSimulator::CreateRendererInitiated(
+          GURL("https://example.test/"), main_rfh());
+  simulator->SetHasUserGesture(false);
+  simulator->Fail(net::ERR_CONNECTION_RESET);
+
+  raw_clock()->Advance(base::TimeDelta::FromMinutes(1));
+  DeleteContents();
+  histogram_tester()->ExpectTotalCount(kTabVisibleTimeAfterRedirect, 0);
+}
+
+TEST_F(PopupOpenerTabHelperTest, SameOriginNavigation_NoLogging) {
+  NavigateAndCommitWithoutGesture(GURL("https://first.test/"));
+  web_contents()->WasHidden();
+  NavigateAndCommitWithoutGesture(GURL("https://first.test/path"));
+
+  raw_clock()->Advance(base::TimeDelta::FromMinutes(1));
+  DeleteContents();
+  histogram_tester()->ExpectTotalCount(kTabVisibleTimeAfterRedirect, 0);
+}
+
+TEST_F(PopupOpenerTabHelperTest, HasUserGesture_NoLogging) {
+  content::NavigationSimulator::NavigateAndCommitFromDocument(
+      GURL("https://first.test/"), main_rfh());
+
+  web_contents()->WasHidden();
+  std::unique_ptr<content::NavigationSimulator> simulator =
+      content::NavigationSimulator::CreateRendererInitiated(
+          GURL("https://example.test/"), main_rfh());
+  simulator->SetHasUserGesture(true);
+  simulator->Commit();
+
+  raw_clock()->Advance(base::TimeDelta::FromMinutes(1));
+  DeleteContents();
+  histogram_tester()->ExpectTotalCount(kTabVisibleTimeAfterRedirect, 0);
+}
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc
index abcee53..5fc23dc 100644
--- a/chrome/browser/ui/browser_browsertest.cc
+++ b/chrome/browser/ui/browser_browsertest.cc
@@ -604,7 +604,7 @@
   EXPECT_FALSE(js_helper->IsShowingDialogForTesting());
 
   // Make sure input events still work in the renderer process.
-  EXPECT_FALSE(contents->GetRenderProcessHost()->IgnoreInputEvents());
+  EXPECT_FALSE(contents->GetMainFrame()->GetProcess()->IgnoreInputEvents());
 }
 
 // Make sure that dialogs are closed after a renderer process dies, and that
@@ -625,7 +625,8 @@
   EXPECT_TRUE(dialog_queue->HasActiveDialog());
 
   // Crash the renderer process and ensure the dialog is gone.
-  content::RenderProcessHost* child_process = contents->GetRenderProcessHost();
+  content::RenderProcessHost* child_process =
+      contents->GetMainFrame()->GetProcess();
   content::RenderProcessHostWatcher crash_observer(
       child_process,
       content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
@@ -658,7 +659,8 @@
   EXPECT_TRUE(js_helper->IsShowingDialogForTesting());
 
   // Crash the renderer process and ensure the dialog is gone.
-  content::RenderProcessHost* child_process = contents->GetRenderProcessHost();
+  content::RenderProcessHost* child_process =
+      contents->GetMainFrame()->GetProcess();
   content::RenderProcessHostWatcher crash_observer(
       child_process,
       content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
@@ -1044,7 +1046,7 @@
   // Start with an http URL.
   ui_test_utils::NavigateToURL(browser(), http_url);
   WebContents* oldtab = browser()->tab_strip_model()->GetActiveWebContents();
-  content::RenderProcessHost* process = oldtab->GetRenderProcessHost();
+  content::RenderProcessHost* process = oldtab->GetMainFrame()->GetProcess();
 
   // Now open a tab to a blank page, set its opener to null, and redirect it
   // cross-site.
@@ -1076,7 +1078,7 @@
 
   // Popup window should not be in the opener's process.
   content::RenderProcessHost* popup_process =
-      newtab->GetRenderProcessHost();
+      newtab->GetMainFrame()->GetProcess();
   EXPECT_NE(process, popup_process);
 
   // Now open a tab to a blank page, set its opener to null, and use a
@@ -1110,7 +1112,7 @@
 
   // This popup window should also not be in the opener's process.
   content::RenderProcessHost* popup_process2 =
-      newtab2->GetRenderProcessHost();
+      newtab2->GetMainFrame()->GetProcess();
   EXPECT_NE(process, popup_process2);
 }
 
@@ -1133,7 +1135,7 @@
   // Start with an http URL.
   ui_test_utils::NavigateToURL(browser(), http_url);
   WebContents* oldtab = browser()->tab_strip_model()->GetActiveWebContents();
-  content::RenderProcessHost* process = oldtab->GetRenderProcessHost();
+  content::RenderProcessHost* process = oldtab->GetMainFrame()->GetProcess();
 
   // Now open a tab to a blank page, set its opener to null, and redirect it
   // cross-site.
@@ -1164,7 +1166,7 @@
 
   // Popup window should still be in the opener's process.
   content::RenderProcessHost* popup_process =
-      newtab->GetRenderProcessHost();
+      newtab->GetMainFrame()->GetProcess();
   EXPECT_EQ(process, popup_process);
 
   // Same thing if the current tab tries to navigate itself.
@@ -1183,7 +1185,8 @@
             oldtab->GetController().GetLastCommittedEntry()->GetURL().spec());
 
   // Original window should still be in the original process.
-  content::RenderProcessHost* new_process = newtab->GetRenderProcessHost();
+  content::RenderProcessHost* new_process =
+      newtab->GetMainFrame()->GetProcess();
   EXPECT_EQ(process, new_process);
 }
 
@@ -1887,7 +1890,7 @@
   // interstitial is deleted now.
 
   // Make sure input events still work in the renderer process.
-  EXPECT_FALSE(contents->GetRenderProcessHost()->IgnoreInputEvents());
+  EXPECT_FALSE(contents->GetMainFrame()->GetProcess()->IgnoreInputEvents());
 }
 
 
@@ -2038,14 +2041,7 @@
 }
 #endif
 
-// Disabled due to flaky timeout on Win7 Tests (dbg): https://crbug.com/753691.
-#if defined(OS_WIN) && !defined(NDEBUG)
-#define MAYBE_WindowOpenClose DISABLED_WindowOpenClose
-#else
-#define MAYBE_WindowOpenClose WindowOpenClose
-#endif
-
-IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_WindowOpenClose) {
+IN_PROC_BROWSER_TEST_F(BrowserTest, WindowOpenClose) {
   base::CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kDisablePopupBlocking);
   GURL url = ui_test_utils::GetTestUrl(
diff --git a/chrome/browser/ui/browser_navigator_browsertest.cc b/chrome/browser/ui/browser_navigator_browsertest.cc
index cdbd704..3a72fb6 100644
--- a/chrome/browser/ui/browser_navigator_browsertest.cc
+++ b/chrome/browser/ui/browser_navigator_browsertest.cc
@@ -769,7 +769,8 @@
   EXPECT_TRUE(params.target_contents->GetMainFrame()->IsRenderFrameLive());
   EXPECT_TRUE(
       params.target_contents->GetController().IsInitialBlankNavigation());
-  int renderer_id = params.target_contents->GetRenderProcessHost()->GetID();
+  int renderer_id =
+      params.target_contents->GetMainFrame()->GetProcess()->GetID();
 
   // We should have one window, with one tab of WebContents differ from
   // params.target_contents.
@@ -786,7 +787,7 @@
   EXPECT_EQ(browser()->tab_strip_model()->GetActiveWebContents(),
             params.target_contents);
   EXPECT_EQ(renderer_id,
-            params.target_contents->GetRenderProcessHost()->GetID());
+            params.target_contents->GetMainFrame()->GetProcess()->GetID());
 
   // We should have one window, with two tabs.
   EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
diff --git a/chrome/browser/ui/browser_ui_prefs.cc b/chrome/browser/ui/browser_ui_prefs.cc
index 978db35..79f4e193 100644
--- a/chrome/browser/ui/browser_ui_prefs.cc
+++ b/chrome/browser/ui/browser_ui_prefs.cc
@@ -98,8 +98,6 @@
 
   // We need to register the type of these preferences in order to query
   // them even though they're only typically controlled via policy.
-  registry->RegisterBooleanPref(prefs::kPluginsAllowOutdated, false);
-  registry->RegisterBooleanPref(prefs::kPluginsAlwaysAuthorize, false);
   registry->RegisterBooleanPref(prefs::kClearPluginLSODataEnabled, true);
   registry->RegisterBooleanPref(prefs::kHideWebStoreIcon, false);
 #if defined(OS_MACOSX)
diff --git a/chrome/browser/ui/cocoa/browser_dialogs_views_mac.cc b/chrome/browser/ui/cocoa/browser_dialogs_views_mac.cc
index dba045da..f3143175 100644
--- a/chrome/browser/ui/cocoa/browser_dialogs_views_mac.cc
+++ b/chrome/browser/ui/cocoa/browser_dialogs_views_mac.cc
@@ -20,8 +20,10 @@
 #include "chrome/browser/ui/views/importer/import_lock_dialog_view.h"
 #include "chrome/browser/ui/views/location_bar/zoom_bubble_view.h"
 #include "chrome/browser/ui/views/page_info/page_info_bubble_view.h"
+#include "chrome/browser/ui/views/safe_browsing/password_reuse_modal_warning_dialog.h"
 #include "chrome/browser/ui/views/task_manager_view.h"
 #include "chrome/browser/ui/views/update_recommended_message_box.h"
+#include "components/constrained_window/constrained_window_views.h"
 
 // This file provides definitions of desktop browser dialog-creation methods for
 // Mac where a Cocoa browser is using Views dialogs. I.e. it is included in the
@@ -140,4 +142,16 @@
   return FirstRunBubble::Show(browser);
 }
 
+void ShowPasswordReuseWarningDialog(
+    content::WebContents* web_contents,
+    safe_browsing::ChromePasswordProtectionService* service,
+    safe_browsing::OnWarningDone done_callback) {
+  safe_browsing::PasswordReuseModalWarningDialog* dialog =
+      new safe_browsing::PasswordReuseModalWarningDialog(
+          web_contents, service, std::move(done_callback));
+  constrained_window::CreateBrowserModalDialogViews(
+      dialog, web_contents->GetTopLevelNativeWindow())
+      ->Show();
+}
+
 }  // namespace chrome
diff --git a/chrome/browser/ui/cocoa/browser_dialogs_views_mac.h b/chrome/browser/ui/cocoa/browser_dialogs_views_mac.h
index 4d84d9e..3dd5d91a 100644
--- a/chrome/browser/ui/cocoa/browser_dialogs_views_mac.h
+++ b/chrome/browser/ui/cocoa/browser_dialogs_views_mac.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_UI_COCOA_BROWSER_DIALOGS_VIEWS_MAC_H_
 #define CHROME_BROWSER_UI_COCOA_BROWSER_DIALOGS_VIEWS_MAC_H_
 
+#include "chrome/browser/safe_browsing/chrome_password_protection_service.h"
 #include "ui/gfx/native_widget_types.h"
 
 class Browser;
@@ -92,6 +93,11 @@
 // Shows the first run bubble.
 void ShowFirstRunBubbleViews(Browser* browser);
 
+void ShowPasswordReuseWarningDialog(
+    content::WebContents* web_contents,
+    safe_browsing::ChromePasswordProtectionService* service,
+    safe_browsing::OnWarningDone done_callback);
+
 }  // namespace chrome
 
 #endif  // CHROME_BROWSER_UI_COCOA_BROWSER_DIALOGS_VIEWS_MAC_H_
diff --git a/chrome/browser/ui/cocoa/device_chooser_content_view_cocoa.mm b/chrome/browser/ui/cocoa/device_chooser_content_view_cocoa.mm
index f74ff11..19b2c60 100644
--- a/chrome/browser/ui/cocoa/device_chooser_content_view_cocoa.mm
+++ b/chrome/browser/ui/cocoa/device_chooser_content_view_cocoa.mm
@@ -876,9 +876,10 @@
     // Update the color of paired status.
     NSTextField* pairedStatusText = [self tableRowViewPairedStatus:rowIndex];
     if (pairedStatusText) {
-      [pairedStatusText setTextColor:(skia::SkColorToCalibratedNSColor(
-                                         isSelected ? gfx::kGoogleGreen300
-                                                    : gfx::kGoogleGreen700))];
+      [pairedStatusText
+          setTextColor:(isSelected ? [NSColor whiteColor]
+                                   : skia::SkColorToCalibratedNSColor(
+                                         gfx::kGoogleGreen700))];
     }
   }
 }
diff --git a/chrome/browser/ui/cocoa/extensions/chooser_dialog_cocoa_controller_unittest.mm b/chrome/browser/ui/cocoa/extensions/chooser_dialog_cocoa_controller_unittest.mm
index 3d6b6f7..f22de6c 100644
--- a/chrome/browser/ui/cocoa/extensions/chooser_dialog_cocoa_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/extensions/chooser_dialog_cocoa_controller_unittest.mm
@@ -483,8 +483,7 @@
   ExpectRowTextColorIs(0, [NSColor whiteColor]);
   ExpectRowTextColorIs(1, [NSColor blackColor]);
   ExpectRowTextColorIs(2, [NSColor blackColor]);
-  ExpectPairedTextColorIs(
-      0, skia::SkColorToCalibratedNSColor(gfx::kGoogleGreen300));
+  ExpectPairedTextColorIs(0, [NSColor whiteColor]);
 
   // Deselect option 0.
   [table_view_ deselectRow:0];
@@ -590,8 +589,7 @@
   ExpectRowTextColorIs(0, [NSColor blackColor]);
   ExpectRowTextColorIs(1, [NSColor blackColor]);
   ExpectRowTextColorIs(2, [NSColor whiteColor]);
-  ExpectPairedTextColorIs(
-      2, skia::SkColorToCalibratedNSColor(gfx::kGoogleGreen300));
+  ExpectPairedTextColorIs(2, [NSColor whiteColor]);
 }
 
 TEST_F(ChooserDialogCocoaControllerTest, SelectAndDeselectAnOption) {
@@ -1151,8 +1149,7 @@
   ExpectRowTextColorIs(3, [NSColor whiteColor]);
   ExpectRowTextColorIs(4, [NSColor blackColor]);
   ExpectRowTextColorIs(5, [NSColor blackColor]);
-  ExpectPairedTextColorIs(
-      0, skia::SkColorToCalibratedNSColor(gfx::kGoogleGreen300));
+  ExpectPairedTextColorIs(0, [NSColor whiteColor]);
   EXPECT_TRUE(connect_button_.enabled);
 
   // Remove option "b".
diff --git a/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller.h b/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller.h
index bea7747..7cc966b 100644
--- a/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller.h
+++ b/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller.h
@@ -60,11 +60,6 @@
   // Whether or not we are in fullscreen mode.
   BOOL inFullscreenMode_;
 
-  // Whether the menu bar is currently locked in the visible position (while
-  // the mouse is over the toolbar). AppKit counts lock/unlock calls, so it's
-  // important that locks/unlocks are balanced.
-  BOOL menubarLocked_;
-
   // Updates the fullscreen toolbar layout for changes in the menubar. This
   // object is only set when the browser is in fullscreen mode.
   base::scoped_nsobject<FullscreenMenubarTracker> menubarTracker_;
@@ -76,8 +71,9 @@
   // Manages the toolbar animations for the TOOLBAR_HIDDEN style.
   std::unique_ptr<FullscreenToolbarAnimationController> animationController_;
 
-  // Mouse tracker to track the user's interactions with the toolbar. This
-  // object is only set when the browser is in fullscreen mode.
+  // When the menu bar and toolbar are visible, creates a tracking area which
+  // is used to keep them visible until the mouse moves far enough away from
+  // them. Only set when the browser is in fullscreen mode.
   base::scoped_nsobject<FullscreenToolbarMouseTracker> mouseTracker_;
 
   // Controller for immersive fullscreen.
diff --git a/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller.mm b/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller.mm
index e832ae31..66c0ccc 100644
--- a/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller.mm
+++ b/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller.mm
@@ -17,27 +17,12 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 
-@interface NSMenu (PrivateAPI)
-- (void)_lockMenuPosition;
-- (void)_unlockMenuPosition;
-@end
-
 namespace {
 
 // Visibility fractions for the menubar and toolbar.
 const CGFloat kHideFraction = 0.0;
 const CGFloat kShowFraction = 1.0;
 
-void LockMenu() {
-  if ([NSMenu instancesRespondToSelector:@selector(_lockMenuPosition)])
-    [[NSApp mainMenu] _lockMenuPosition];
-}
-
-void UnlockMenu() {
-  if ([NSMenu instancesRespondToSelector:@selector(_unlockMenuPosition)])
-    [[NSApp mainMenu] _unlockMenuPosition];
-}
-
 }  // namespace
 
 @implementation FullscreenToolbarController
@@ -74,8 +59,7 @@
     menubarTracker_.reset([[FullscreenMenubarTracker alloc]
         initWithFullscreenToolbarController:self]);
     mouseTracker_.reset([[FullscreenToolbarMouseTracker alloc]
-        initWithFullscreenToolbarController:self
-                        animationController:animationController_.get()]);
+        initWithFullscreenToolbarController:self]);
   }
 }
 
@@ -157,7 +141,6 @@
 
   FullscreenMenubarState menubarState = [menubarTracker_ state];
   return menubarState == FullscreenMenubarState::SHOWN ||
-         [mouseTracker_ mouseInsideTrackingArea] ||
          [visibilityLockController_ isToolbarVisibilityLocked];
 }
 
@@ -184,16 +167,6 @@
 }
 
 - (void)updateToolbarLayout {
-  if ([mouseTracker_ mouseInsideTrackingArea]) {
-    if (!menubarLocked_)
-      LockMenu();
-    menubarLocked_ = YES;
-  } else {
-    if (menubarLocked_)
-      UnlockMenu();
-    menubarLocked_ = NO;
-  }
-
   [browserController_ layoutSubviews];
   animationController_->ToolbarDidUpdate();
   [mouseTracker_ updateTrackingArea];
diff --git a/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller_unittest.mm b/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller_unittest.mm
index 91756f53..e2f57d0 100644
--- a/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller_unittest.mm
@@ -19,34 +19,6 @@
 #include "ui/base/cocoa/appkit_utils.h"
 
 //////////////////////////////////////////////////////////////////
-// MockFullscreenToolbarMouseTracker
-// Mocks the mouse interactions with the toolbar.
-
-@interface MockFullscreenToolbarMouseTracker : FullscreenToolbarMouseTracker
-
-@property(nonatomic, assign) BOOL mouseInside;
-
-// Overridden to prevent a tracking area from being created.
-- (void)updateTrackingArea;
-
-- (BOOL)mouseInsideTrackingArea;
-
-@end
-
-@implementation MockFullscreenToolbarMouseTracker
-
-@synthesize mouseInside = mouseInside_;
-
-- (void)updateTrackingArea {
-}
-
-- (BOOL)mouseInsideTrackingArea {
-  return mouseInside_;
-}
-
-@end
-
-//////////////////////////////////////////////////////////////////
 // MockFullscreenMenubarTracker
 // Mocks the state of the menubar.
 
@@ -85,11 +57,6 @@
 
 @end
 
-@interface NSMenu (PrivateAPI)
-- (void)_lockMenuPosition;
-- (void)_unlockMenuPosition;
-@end
-
 #define CHECK_LAYOUT(TOOLBAR_FRACTION, MENUBAR_FRACTION)                       \
   {                                                                            \
     FullscreenToolbarLayout layout = [controller_ computeLayout];              \
@@ -124,7 +91,9 @@
     [menubar_tracker_ setMenubarProgress:0.0];
     [controller_ setMenubarTracker:menubar_tracker_];
 
-    mouse_tracker_.reset([[MockFullscreenToolbarMouseTracker alloc] init]);
+    mouse_tracker_ =
+        [OCMockObject mockForClass:[FullscreenToolbarMouseTracker class]];
+    [[mouse_tracker_ stub] updateTrackingArea];
     [controller_ setMouseTracker:mouse_tracker_];
 
     [controller_ animationController]->SetAnimationDuration(0.0);
@@ -142,15 +111,15 @@
   // A mock BrowserWindowController object.
   id bwc_;
 
+  // A mock FullscreenToolbarMouseTracker object.
+  id mouse_tracker_;
+
   // The FullscreenToolbarController object being tested.
   base::scoped_nsobject<FullscreenToolbarController> controller_;
 
   // Mocks the state of the menubar.
   base::scoped_nsobject<MockFullscreenMenubarTracker> menubar_tracker_;
 
-  // Mocks the mouse interactions with the toolbar.
-  base::scoped_nsobject<MockFullscreenToolbarMouseTracker> mouse_tracker_;
-
  private:
   DISALLOW_COPY_AND_ASSIGN(FullscreenToolbarControllerTest);
 };
@@ -238,77 +207,4 @@
   CHECK_LAYOUT(0, 0);
 }
 
-// Basic test that checks the toolbar fraction for different mouse tracking
-// values.
-TEST_F(FullscreenToolbarControllerTest, TestHiddenToolbarWithMouseTracking) {
-  CHECK_LAYOUT(0, 0);
-
-  [mouse_tracker_ setMouseInside:YES];
-  CHECK_LAYOUT(1, 0);
-
-  [menubar_tracker_ setMenubarProgress:1];
-  CHECK_LAYOUT(1, 1);
-
-  [menubar_tracker_ setMenubarProgress:0];
-  CHECK_LAYOUT(1, 0);
-
-  [mouse_tracker_ setMouseInside:NO];
-  CHECK_LAYOUT(0, 0);
-}
-
-// Test that checks the toolbar fraction with mouse tracking, menubar fraction,
-// and visibility locks.
-TEST_F(FullscreenToolbarControllerTest, TestHiddenToolbarWithMultipleFactors) {
-  FullscreenToolbarVisibilityLockController* locks =
-      [controller_ visibilityLockController];
-  base::scoped_nsobject<NSObject> owner([[NSObject alloc] init]);
-  CHECK_LAYOUT(0, 0);
-
-  // Toolbar should be shown with the menubar.
-  [menubar_tracker_ setMenubarProgress:1];
-  CHECK_LAYOUT(1, 1);
-
-  // Move the mouse to the toolbar and start hiding the menubar. Toolbar
-  // should be fully visible.
-  [mouse_tracker_ setMouseInside:YES];
-  CHECK_LAYOUT(1, 1);
-  [menubar_tracker_ setMenubarProgress:0.5];
-  CHECK_LAYOUT(1, 0.5);
-
-  // Lock the toolbar's visibility.
-  [locks lockToolbarVisibilityForOwner:owner.get() withAnimation:NO];
-  CHECK_LAYOUT(1, 0.5);
-
-  // Hide the menubar. Toolbar should be fully visible.
-  [menubar_tracker_ setMenubarProgress:0];
-  CHECK_LAYOUT(1, 0);
-
-  // Lock the toolbar's visibility. Toolbar should be fully visible.
-  [locks releaseToolbarVisibilityForOwner:owner.get() withAnimation:NO];
-  CHECK_LAYOUT(1, 0);
-
-  // Move the mouse away from the toolbar. Toolbar should hide.
-  [mouse_tracker_ setMouseInside:NO];
-  CHECK_LAYOUT(0, 0);
-
-  // Lock the toolbar and move the mouse to it.
-  [locks lockToolbarVisibilityForOwner:owner.get() withAnimation:NO];
-  [mouse_tracker_ setMouseInside:YES];
-  CHECK_LAYOUT(1, 0);
-
-  // Move the mouse away from the toolbar. Toolbar should be fully visible.
-  [mouse_tracker_ setMouseInside:NO];
-  CHECK_LAYOUT(1, 0);
-
-  // Release the toolbar. Toolbar should be hidden.
-  [locks releaseToolbarVisibilityForOwner:owner.get() withAnimation:NO];
-}
-
-// Verify that private methods used by FullscreenToolbarController still exist.
-TEST_F(FullscreenToolbarControllerTest, PrivateAPIs) {
-  EXPECT_TRUE([NSMenu instancesRespondToSelector:@selector(_lockMenuPosition)]);
-  EXPECT_TRUE(
-      [NSMenu instancesRespondToSelector:@selector(_unlockMenuPosition)]);
-}
-
 }  // namespace
diff --git a/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_mouse_tracker.h b/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_mouse_tracker.h
index 54fe6fd..a4e5929 100644
--- a/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_mouse_tracker.h
+++ b/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_mouse_tracker.h
@@ -7,17 +7,14 @@
 
 #import <Cocoa/Cocoa.h>
 
-class FullscreenToolbarAnimationController;
 @class FullscreenToolbarController;
 
 // Class that tracks mouse interactions with the fullscreen toolbar.
 @interface FullscreenToolbarMouseTracker : NSObject
 
 // Designated initializer.
-- (instancetype)
-initWithFullscreenToolbarController:(FullscreenToolbarController*)owner
-                animationController:
-                    (FullscreenToolbarAnimationController*)animationController;
+- (instancetype)initWithFullscreenToolbarController:
+    (FullscreenToolbarController*)owner;
 
 // Updates the tracking area's frame to the given toolbar frame.
 - (void)updateToolbarFrame:(NSRect)frame;
@@ -28,9 +25,6 @@
 // Removes the tracking area.
 - (void)removeTrackingArea;
 
-// Returns YES if the mouse is inside the tracking area.
-- (BOOL)mouseInsideTrackingArea;
-
 @end
 
-#endif  // CHROME_BROWSER_UI_COCOA_FULLSCREEN_FULLSCREEN_TOOLBAR_MOUSE_TRACKER_H_
\ No newline at end of file
+#endif  // CHROME_BROWSER_UI_COCOA_FULLSCREEN_FULLSCREEN_TOOLBAR_MOUSE_TRACKER_H_
diff --git a/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_mouse_tracker.mm b/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_mouse_tracker.mm
index c620b79..f604f48 100644
--- a/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_mouse_tracker.mm
+++ b/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_mouse_tracker.mm
@@ -5,9 +5,8 @@
 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_mouse_tracker.h"
 
 #include "chrome/browser/ui/cocoa/browser_window_controller.h"
-#include "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_animation_controller.h"
 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller.h"
-#include "ui/base/cocoa/appkit_utils.h"
+#include "chrome/browser/ui/cocoa/scoped_menu_bar_lock.h"
 #import "ui/base/cocoa/tracking_area.h"
 
 namespace {
@@ -29,27 +28,24 @@
   // is still on the toolbar.
   base::scoped_nsobject<CrTrackingArea> trackingArea_;
 
+  // Keeps the menu bar from hiding until the mouse exits the tracking area.
+  std::unique_ptr<ScopedMenuBarLock> menuBarLock_;
+
   // The content view for the window.
   NSView* contentView_;  // weak
 
   // The owner of this class.
   FullscreenToolbarController* owner_;  // weak
-
-  // The object managing the fullscreen toolbar's animations.
-  FullscreenToolbarAnimationController* animationController_;  // weak
 }
 
 @end
 
 @implementation FullscreenToolbarMouseTracker
 
-- (instancetype)
-initWithFullscreenToolbarController:(FullscreenToolbarController*)owner
-                animationController:
-                    (FullscreenToolbarAnimationController*)animationController {
+- (instancetype)initWithFullscreenToolbarController:
+    (FullscreenToolbarController*)owner {
   if ((self = [super init])) {
     owner_ = owner;
-    animationController_ = animationController;
   }
 
   return self;
@@ -61,9 +57,10 @@
 }
 
 - (void)updateTrackingArea {
-  // Remove the tracking area if the toolbar isn't fully shown.
-  if (!ui::IsCGFloatEqual([owner_ toolbarFraction], 1.0)) {
+  // Remove the tracking area if the toolbar and menu bar aren't both visible.
+  if ([owner_ toolbarFraction] == 0 || ![NSMenu menuBarVisible]) {
     [self removeTrackingArea];
+    menuBarLock_.reset();
     return;
   }
 
@@ -108,21 +105,12 @@
   contentView_ = nil;
 }
 
-- (BOOL)mouseInsideTrackingArea {
-  return [trackingArea_ mouseInsideTrackingAreaForView:contentView_];
-}
-
 - (void)mouseEntered:(NSEvent*)event {
-  // Empty implementation. Required for CrTrackingArea.
+  menuBarLock_.reset(new ScopedMenuBarLock());
 }
 
 - (void)mouseExited:(NSEvent*)event {
-  DCHECK_EQ([event trackingArea], trackingArea_.get());
-
-  animationController_->AnimateToolbarOutIfPossible();
-
-  [owner_ updateToolbarLayout];
-  [self removeTrackingArea];
+  menuBarLock_.reset();
 }
 
 @end
diff --git a/chrome/browser/ui/cocoa/hung_renderer_controller.mm b/chrome/browser/ui/cocoa/hung_renderer_controller.mm
index 3e221c8..ba39627 100644
--- a/chrome/browser/ui/cocoa/hung_renderer_controller.mm
+++ b/chrome/browser/ui/cocoa/hung_renderer_controller.mm
@@ -16,6 +16,7 @@
 #include "chrome/common/logging_chrome.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
@@ -156,8 +157,8 @@
 
 - (IBAction)kill:(id)sender {
   if (hungContents_) {
-    hungContents_->GetRenderProcessHost()->Shutdown(content::RESULT_CODE_HUNG,
-                                                    false);
+    hungContents_->GetMainFrame()->GetProcess()->Shutdown(
+        content::RESULT_CODE_HUNG, false);
   }
   // Cannot call performClose:, because the close button is disabled.
   [self close];
@@ -225,7 +226,8 @@
   base::scoped_nsobject<NSMutableArray> titles([[NSMutableArray alloc] init]);
   base::scoped_nsobject<NSMutableArray> favicons([[NSMutableArray alloc] init]);
   for (TabContentsIterator it; !it.done(); it.Next()) {
-    if (it->GetRenderProcessHost() == hungContents_->GetRenderProcessHost()) {
+    if (it->GetMainFrame()->GetProcess() ==
+        hungContents_->GetMainFrame()->GetProcess()) {
       base::string16 title = it->GetTitle();
       if (title.empty())
         title = CoreTabHelper::GetDefaultTitle();
@@ -245,8 +247,8 @@
 - (void)endForWebContents:(WebContents*)contents {
   DCHECK(contents);
   DCHECK(hungContents_);
-  if (hungContents_ && hungContents_->GetRenderProcessHost() ==
-      contents->GetRenderProcessHost()) {
+  if (hungContents_ && hungContents_->GetMainFrame()->GetProcess() ==
+                           contents->GetMainFrame()->GetProcess()) {
     // Cannot call performClose:, because the close button is disabled.
     [self close];
   }
diff --git a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm
index d22300e..8a7bbc8 100644
--- a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm
+++ b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm
@@ -96,11 +96,11 @@
 
 // Helper functions to get source type, or get data entities based on source
 // type.
-- (DesktopMediaID::Source)selectedSourceType;
-- (DesktopMediaID::Source)sourceTypeForBrowser:(id)browser;
-- (id)browserViewForType:(DesktopMediaID::Source)sourceType;
-- (NSMutableArray*)itemSetForType:(DesktopMediaID::Source)sourceType;
-- (NSInteger)selectedIndexForType:(DesktopMediaID::Source)sourceType;
+- (DesktopMediaID::Type)selectedSourceType;
+- (DesktopMediaID::Type)sourceTypeForBrowser:(id)browser;
+- (id)browserViewForType:(DesktopMediaID::Type)sourceType;
+- (NSMutableArray*)itemSetForType:(DesktopMediaID::Type)sourceType;
+- (NSInteger)selectedIndexForType:(DesktopMediaID::Type)sourceType;
 - (void)setTabBrowserIndex:(NSInteger)index;
 
 @end
@@ -129,18 +129,18 @@
     sourceLists_ = std::move(sourceLists);
     for (auto& sourceList : sourceLists_) {
       switch (sourceList->GetMediaListType()) {
-        case DesktopMediaID::SOURCE_NONE:
+        case DesktopMediaID::TYPE_NONE:
           NOTREACHED();
           break;
-        case DesktopMediaID::SOURCE_SCREEN:
+        case DesktopMediaID::TYPE_SCREEN:
           screenItems_.reset([[NSMutableArray alloc] init]);
           break;
-        case DesktopMediaID::SOURCE_WINDOW:
+        case DesktopMediaID::TYPE_WINDOW:
           sourceList->SetViewDialogWindowId(DesktopMediaID(
-              DesktopMediaID::SOURCE_WINDOW, [window windowNumber]));
+              DesktopMediaID::TYPE_WINDOW, [window windowNumber]));
           windowItems_.reset([[NSMutableArray alloc] init]);
           break;
-        case DesktopMediaID::SOURCE_WEB_CONTENTS:
+        case DesktopMediaID::TYPE_WEB_CONTENTS:
           tabItems_.reset([[NSMutableArray alloc] init]);
           break;
       }
@@ -237,32 +237,32 @@
 
   for (auto& sourceList : sourceLists_) {
     switch (sourceList->GetMediaListType()) {
-      case DesktopMediaID::SOURCE_NONE:
+      case DesktopMediaID::TYPE_NONE:
         NOTREACHED();
         break;
-      case DesktopMediaID::SOURCE_SCREEN:
+      case DesktopMediaID::TYPE_SCREEN:
         [sourceTypeControl_
               setLabel:l10n_util::GetNSString(
                            IDS_DESKTOP_MEDIA_PICKER_SOURCE_TYPE_SCREEN)
             forSegment:segmentIndex];
 
-        [[sourceTypeControl_ cell] setTag:DesktopMediaID::SOURCE_SCREEN
+        [[sourceTypeControl_ cell] setTag:DesktopMediaID::TYPE_SCREEN
                                forSegment:segmentIndex];
         break;
-      case DesktopMediaID::SOURCE_WINDOW:
+      case DesktopMediaID::TYPE_WINDOW:
         [sourceTypeControl_
               setLabel:l10n_util::GetNSString(
                            IDS_DESKTOP_MEDIA_PICKER_SOURCE_TYPE_WINDOW)
             forSegment:segmentIndex];
-        [[sourceTypeControl_ cell] setTag:DesktopMediaID::SOURCE_WINDOW
+        [[sourceTypeControl_ cell] setTag:DesktopMediaID::TYPE_WINDOW
                                forSegment:segmentIndex];
         break;
-      case DesktopMediaID::SOURCE_WEB_CONTENTS:
+      case DesktopMediaID::TYPE_WEB_CONTENTS:
         [sourceTypeControl_
               setLabel:l10n_util::GetNSString(
                            IDS_DESKTOP_MEDIA_PICKER_SOURCE_TYPE_TAB)
             forSegment:segmentIndex];
-        [[sourceTypeControl_ cell] setTag:DesktopMediaID::SOURCE_WEB_CONTENTS
+        [[sourceTypeControl_ cell] setTag:DesktopMediaID::TYPE_WEB_CONTENTS
                                forSegment:segmentIndex];
         break;
     }
@@ -289,11 +289,11 @@
 - (void)createSourceViewsAtOrigin:(NSPoint)origin {
   for (auto& sourceList : sourceLists_) {
     switch (sourceList->GetMediaListType()) {
-      case DesktopMediaID::SOURCE_NONE: {
+      case DesktopMediaID::TYPE_NONE: {
         NOTREACHED();
         break;
       }
-      case DesktopMediaID::SOURCE_SCREEN: {
+      case DesktopMediaID::TYPE_SCREEN: {
         const bool is_single = sourceList->GetSourceCount() <= 1;
         const CGFloat width =
             is_single ? kSingleScreenWidth : kMultipleScreenWidth;
@@ -304,13 +304,13 @@
         break;
       }
 
-      case DesktopMediaID::SOURCE_WINDOW: {
+      case DesktopMediaID::TYPE_WINDOW: {
         windowBrowser_.reset([[self
             createImageBrowserWithSize:NSMakeSize(kThumbnailWidth,
                                                   kThumbnailHeight)] retain]);
         break;
       }
-      case DesktopMediaID::SOURCE_WEB_CONTENTS: {
+      case DesktopMediaID::TYPE_WEB_CONTENTS: {
         tabBrowser_.reset([[NSTableView alloc] initWithFrame:NSZeroRect]);
         [tabBrowser_ setDelegate:self];
         [tabBrowser_ setDataSource:self];
@@ -431,23 +431,23 @@
   // the observer, and will forward notifications to this object.
   for (auto& sourceList : sourceLists_) {
     switch (sourceList->GetMediaListType()) {
-      case DesktopMediaID::SOURCE_NONE: {
+      case DesktopMediaID::TYPE_NONE: {
         NOTREACHED();
         break;
       }
-      case DesktopMediaID::SOURCE_SCREEN: {
+      case DesktopMediaID::TYPE_SCREEN: {
         sourceList->SetThumbnailSize(
             gfx::Size(kSingleScreenWidth, kSingleScreenHeight));
         sourceList->StartUpdating(bridge_.get());
         break;
       }
-      case DesktopMediaID::SOURCE_WINDOW: {
+      case DesktopMediaID::TYPE_WINDOW: {
         sourceList->SetThumbnailSize(
             gfx::Size(kThumbnailWidth, kThumbnailHeight));
         sourceList->StartUpdating(bridge_.get());
         break;
       }
-      case DesktopMediaID::SOURCE_WEB_CONTENTS: {
+      case DesktopMediaID::TYPE_WEB_CONTENTS: {
         sourceList->SetThumbnailSize(gfx::Size(kIconWidth, kRowHeight));
         sourceList->StartUpdating(bridge_.get());
         break;
@@ -464,11 +464,11 @@
     return;
   }
 
-  sourceID.set_audio_capture(![audioShareCheckbox_ isHidden] &&
-                             [audioShareCheckbox_ state] == NSOnState);
+  sourceID.audio_share = ![audioShareCheckbox_ isHidden] &&
+                         [audioShareCheckbox_ state] == NSOnState;
 
   // If the media source is an tab, activate it.
-  if (sourceID.source_type == DesktopMediaID::SOURCE_WEB_CONTENTS) {
+  if (sourceID.type == DesktopMediaID::TYPE_WEB_CONTENTS) {
     content::WebContents* tab = content::WebContents::FromRenderFrameHost(
         content::RenderFrameHost::FromID(
             sourceID.web_contents_id.render_process_id,
@@ -490,7 +490,7 @@
 }
 
 - (void)sharePressed:(id)sender {
-  DesktopMediaID::Source selectedType = [self selectedSourceType];
+  DesktopMediaID::Type selectedType = [self selectedSourceType];
   NSMutableArray* items = [self itemSetForType:selectedType];
   NSInteger selectedIndex = [self selectedIndexForType:selectedType];
   DesktopMediaPickerItem* item = [items objectAtIndex:selectedIndex];
@@ -504,14 +504,14 @@
 }
 
 - (void)typeButtonPressed:(id)sender {
-  DesktopMediaID::Source selectedType = [self selectedSourceType];
+  DesktopMediaID::Type selectedType = [self selectedSourceType];
   id browser = [self browserViewForType:selectedType];
 
   [audioShareCheckbox_
-      setHidden:selectedType != DesktopMediaID::SOURCE_WEB_CONTENTS];
+      setHidden:selectedType != DesktopMediaID::TYPE_WEB_CONTENTS];
   [imageBrowserScroll_ setDocumentView:browser];
 
-  if (selectedType == DesktopMediaID::SOURCE_WEB_CONTENTS) {
+  if (selectedType == DesktopMediaID::TYPE_WEB_CONTENTS) {
     NSInteger selectedIndex = [self selectedIndexForType:selectedType];
     [tabBrowser_ reloadData];
     [self setTabBrowserIndex:selectedIndex];
@@ -523,61 +523,61 @@
 
 #pragma mark Data Retrieve Helper
 
-- (DesktopMediaID::Source)selectedSourceType {
+- (DesktopMediaID::Type)selectedSourceType {
   NSInteger segment = [sourceTypeControl_ selectedSegment];
-  return static_cast<DesktopMediaID::Source>(
+  return static_cast<DesktopMediaID::Type>(
       [[sourceTypeControl_ cell] tagForSegment:segment]);
 }
 
-- (DesktopMediaID::Source)sourceTypeForBrowser:(id)browser {
+- (DesktopMediaID::Type)sourceTypeForBrowser:(id)browser {
   if (browser == screenBrowser_.get())
-    return DesktopMediaID::SOURCE_SCREEN;
+    return DesktopMediaID::TYPE_SCREEN;
   if (browser == windowBrowser_.get())
-    return DesktopMediaID::SOURCE_WINDOW;
-  return DesktopMediaID::SOURCE_WEB_CONTENTS;
+    return DesktopMediaID::TYPE_WINDOW;
+  return DesktopMediaID::TYPE_WEB_CONTENTS;
 }
 
-- (id)browserViewForType:(DesktopMediaID::Source)sourceType {
+- (id)browserViewForType:(DesktopMediaID::Type)sourceType {
   switch (sourceType) {
-    case DesktopMediaID::SOURCE_SCREEN:
+    case DesktopMediaID::TYPE_SCREEN:
       return screenBrowser_;
-    case DesktopMediaID::SOURCE_WINDOW:
+    case DesktopMediaID::TYPE_WINDOW:
       return windowBrowser_;
-    case DesktopMediaID::SOURCE_WEB_CONTENTS:
+    case DesktopMediaID::TYPE_WEB_CONTENTS:
       return tabBrowser_;
-    case DesktopMediaID::SOURCE_NONE:
+    case DesktopMediaID::TYPE_NONE:
       NOTREACHED();
       return nil;
   }
 }
 
-- (NSMutableArray*)itemSetForType:(DesktopMediaID::Source)sourceType {
+- (NSMutableArray*)itemSetForType:(DesktopMediaID::Type)sourceType {
   switch (sourceType) {
-    case DesktopMediaID::SOURCE_SCREEN:
+    case DesktopMediaID::TYPE_SCREEN:
       return screenItems_;
-    case DesktopMediaID::SOURCE_WINDOW:
+    case DesktopMediaID::TYPE_WINDOW:
       return windowItems_;
-    case DesktopMediaID::SOURCE_WEB_CONTENTS:
+    case DesktopMediaID::TYPE_WEB_CONTENTS:
       return tabItems_;
-    case DesktopMediaID::SOURCE_NONE:
+    case DesktopMediaID::TYPE_NONE:
       NOTREACHED();
       return nil;
   }
 }
 
-- (NSInteger)selectedIndexForType:(DesktopMediaID::Source)sourceType {
+- (NSInteger)selectedIndexForType:(DesktopMediaID::Type)sourceType {
   NSIndexSet* indexes = nil;
   switch (sourceType) {
-    case DesktopMediaID::SOURCE_SCREEN:
+    case DesktopMediaID::TYPE_SCREEN:
       indexes = [screenBrowser_ selectionIndexes];
       break;
-    case DesktopMediaID::SOURCE_WINDOW:
+    case DesktopMediaID::TYPE_WINDOW:
       indexes = [windowBrowser_ selectionIndexes];
       break;
-    case DesktopMediaID::SOURCE_WEB_CONTENTS:
+    case DesktopMediaID::TYPE_WEB_CONTENTS:
       indexes = [tabBrowser_ selectedRowIndexes];
       break;
-    case DesktopMediaID::SOURCE_NONE:
+    case DesktopMediaID::TYPE_NONE:
       NOTREACHED();
   }
 
@@ -612,13 +612,13 @@
 #pragma mark IKImageBrowserDataSource
 
 - (NSUInteger)numberOfItemsInImageBrowser:(IKImageBrowserView*)browser {
-  DesktopMediaID::Source sourceType = [self sourceTypeForBrowser:browser];
+  DesktopMediaID::Type sourceType = [self sourceTypeForBrowser:browser];
   NSMutableArray* items = [self itemSetForType:sourceType];
   return [items count];
 }
 
 - (id)imageBrowser:(IKImageBrowserView*)browser itemAtIndex:(NSUInteger)index {
-  DesktopMediaID::Source sourceType = [self sourceTypeForBrowser:browser];
+  DesktopMediaID::Type sourceType = [self sourceTypeForBrowser:browser];
   NSMutableArray* items = [self itemSetForType:sourceType];
   DesktopMediaPickerItem* item = [items objectAtIndex:index];
 
@@ -643,7 +643,7 @@
 }
 
 - (void)imageBrowserSelectionDidChange:(IKImageBrowserView*)browser {
-  DesktopMediaID::Source selectedType = [self selectedSourceType];
+  DesktopMediaID::Type selectedType = [self selectedSourceType];
   NSInteger selectedIndex = [self selectedIndexForType:selectedType];
   // Enable or disable the OK button based on whether we have a selection.
   [shareButton_ setEnabled:(selectedIndex >= 0)];
@@ -697,7 +697,7 @@
 #pragma mark DesktopMediaPickerObserver
 
 - (void)sourceAddedForList:(DesktopMediaList*)list atIndex:(int)index {
-  DesktopMediaID::Source sourceType = list->GetMediaListType();
+  DesktopMediaID::Type sourceType = list->GetMediaListType();
   NSMutableArray* items = [self itemSetForType:sourceType];
   id browser = [self browserViewForType:sourceType];
   NSInteger selectedIndex = [self selectedIndexForType:sourceType];
@@ -713,10 +713,10 @@
 
   [items insertObject:item atIndex:index];
   [browser reloadData];
-  if (sourceType == DesktopMediaID::SOURCE_WEB_CONTENTS) {
+  if (sourceType == DesktopMediaID::TYPE_WEB_CONTENTS) {
     // Memorizing selection.
     [self setTabBrowserIndex:selectedIndex];
-  } else if (sourceType == DesktopMediaID::SOURCE_SCREEN) {
+  } else if (sourceType == DesktopMediaID::TYPE_SCREEN) {
     if ([items count] == 1) {
       // Preselect the first screen source.
       [browser setSelectionIndexes:[NSIndexSet indexSetWithIndex:0]
@@ -739,11 +739,11 @@
 }
 
 - (void)sourceRemovedForList:(DesktopMediaList*)list atIndex:(int)index {
-  DesktopMediaID::Source sourceType = list->GetMediaListType();
+  DesktopMediaID::Type sourceType = list->GetMediaListType();
   NSMutableArray* items = [self itemSetForType:sourceType];
   id browser = [self browserViewForType:sourceType];
 
-  if (sourceType == DesktopMediaID::SOURCE_WEB_CONTENTS) {
+  if (sourceType == DesktopMediaID::TYPE_WEB_CONTENTS) {
     NSInteger selectedIndex = [self selectedIndexForType:sourceType];
     if (selectedIndex > index)
       --selectedIndex;
@@ -760,7 +760,7 @@
     [browser setSelectionIndexes:[NSIndexSet indexSet] byExtendingSelection:NO];
   }
   [items removeObjectAtIndex:index];
-  if (sourceType == DesktopMediaID::SOURCE_SCREEN && [items count] == 1)
+  if (sourceType == DesktopMediaID::TYPE_SCREEN && [items count] == 1)
     [browser setCellSize:NSMakeSize(kSingleScreenWidth, kSingleScreenHeight)];
   [browser reloadData];
 }
@@ -768,7 +768,7 @@
 - (void)sourceMovedForList:(DesktopMediaList*)list
                       from:(int)oldIndex
                         to:(int)newIndex {
-  DesktopMediaID::Source sourceType = list->GetMediaListType();
+  DesktopMediaID::Type sourceType = list->GetMediaListType();
   NSMutableArray* items = [self itemSetForType:sourceType];
   id browser = [self browserViewForType:sourceType];
   NSInteger selectedIndex = [self selectedIndexForType:sourceType];
@@ -785,12 +785,12 @@
   [items insertObject:item atIndex:newIndex];
   [browser reloadData];
 
-  if (sourceType == DesktopMediaID::SOURCE_WEB_CONTENTS)
+  if (sourceType == DesktopMediaID::TYPE_WEB_CONTENTS)
     [self setTabBrowserIndex:selectedIndex];
 }
 
 - (void)sourceNameChangedForList:(DesktopMediaList*)list atIndex:(int)index {
-  DesktopMediaID::Source sourceType = list->GetMediaListType();
+  DesktopMediaID::Type sourceType = list->GetMediaListType();
   NSMutableArray* items = [self itemSetForType:sourceType];
   id browser = [self browserViewForType:sourceType];
   NSInteger selectedIndex = [self selectedIndexForType:sourceType];
@@ -799,13 +799,13 @@
   const DesktopMediaList::Source& source = list->GetSource(index);
   [item setImageTitle:base::SysUTF16ToNSString(source.name)];
   [browser reloadData];
-  if (sourceType == DesktopMediaID::SOURCE_WEB_CONTENTS)
+  if (sourceType == DesktopMediaID::TYPE_WEB_CONTENTS)
     [self setTabBrowserIndex:selectedIndex];
 }
 
 - (void)sourceThumbnailChangedForList:(DesktopMediaList*)list
                               atIndex:(int)index {
-  DesktopMediaID::Source sourceType = list->GetMediaListType();
+  DesktopMediaID::Type sourceType = list->GetMediaListType();
   NSMutableArray* items = [self itemSetForType:sourceType];
   id browser = [self browserViewForType:sourceType];
   NSInteger selectedIndex = [self selectedIndexForType:sourceType];
@@ -817,7 +817,7 @@
   [item setImageRepresentation:image];
   [browser reloadData];
 
-  if (sourceType == DesktopMediaID::SOURCE_WEB_CONTENTS)
+  if (sourceType == DesktopMediaID::TYPE_WEB_CONTENTS)
     [self setTabBrowserIndex:selectedIndex];
 }
 
diff --git a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller_unittest.mm b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller_unittest.mm
index d0a5439..60d84b8 100644
--- a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller_unittest.mm
@@ -78,13 +78,13 @@
   void SetUp() override {
     CocoaTest::SetUp();
 
-    std::vector<DesktopMediaID::Source> source_types = {
-        DesktopMediaID::SOURCE_SCREEN, DesktopMediaID::SOURCE_WINDOW,
-        DesktopMediaID::SOURCE_WEB_CONTENTS};
+    std::vector<DesktopMediaID::Type> source_types = {
+        DesktopMediaID::TYPE_SCREEN, DesktopMediaID::TYPE_WINDOW,
+        DesktopMediaID::TYPE_WEB_CONTENTS};
 
-    screen_list_ = new FakeDesktopMediaList(DesktopMediaID::SOURCE_SCREEN);
-    window_list_ = new FakeDesktopMediaList(DesktopMediaID::SOURCE_WINDOW);
-    tab_list_ = new FakeDesktopMediaList(DesktopMediaID::SOURCE_WEB_CONTENTS);
+    screen_list_ = new FakeDesktopMediaList(DesktopMediaID::TYPE_SCREEN);
+    window_list_ = new FakeDesktopMediaList(DesktopMediaID::TYPE_WINDOW);
+    tab_list_ = new FakeDesktopMediaList(DesktopMediaID::TYPE_WEB_CONTENTS);
 
     std::vector<std::unique_ptr<DesktopMediaList>> source_lists;
     source_lists.push_back(std::unique_ptr<DesktopMediaList>(screen_list_));
@@ -116,7 +116,7 @@
     return callback_called_;
   }
 
-  void ChangeType(DesktopMediaID::Source sourceType) {
+  void ChangeType(DesktopMediaID::Type sourceType) {
     NSSegmentedControl* control = [controller_ sourceTypeControl];
     [control selectSegmentWithTag:sourceType];
     // [control selectSegmentWithTag] does not trigger handler, so we need to
@@ -126,17 +126,17 @@
 
   void AddWindow(int id) {
     window_list_->AddSourceByFullMediaID(
-        DesktopMediaID(DesktopMediaID::SOURCE_WINDOW, id));
+        DesktopMediaID(DesktopMediaID::TYPE_WINDOW, id));
   }
 
   void AddScreen(int id) {
     screen_list_->AddSourceByFullMediaID(
-        DesktopMediaID(DesktopMediaID::SOURCE_SCREEN, id));
+        DesktopMediaID(DesktopMediaID::TYPE_SCREEN, id));
   }
 
   void AddTab(int id) {
     tab_list_->AddSourceByFullMediaID(
-        DesktopMediaID(DesktopMediaID::SOURCE_WEB_CONTENTS, id));
+        DesktopMediaID(DesktopMediaID::TYPE_WEB_CONTENTS, id));
   }
 
  protected:
@@ -157,7 +157,7 @@
 
 TEST_F(DesktopMediaPickerControllerTest, ShowAndDismiss) {
   [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::SOURCE_SCREEN);
+  ChangeType(DesktopMediaID::TYPE_SCREEN);
 
   AddScreen(0);
   AddScreen(1);
@@ -173,7 +173,7 @@
 
 TEST_F(DesktopMediaPickerControllerTest, ClickShareScreen) {
   [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::SOURCE_SCREEN);
+  ChangeType(DesktopMediaID::TYPE_SCREEN);
 
   EXPECT_FALSE([[controller_ shareButton] isEnabled]);
   AddScreen(0);
@@ -193,7 +193,7 @@
 
 TEST_F(DesktopMediaPickerControllerTest, ClickShareWindow) {
   [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::SOURCE_WINDOW);
+  ChangeType(DesktopMediaID::TYPE_WINDOW);
   AddWindow(0);
   window_list_->SetSourceThumbnail(0);
   AddWindow(1);
@@ -214,7 +214,7 @@
 
 TEST_F(DesktopMediaPickerControllerTest, ClickShareTab) {
   [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::SOURCE_WEB_CONTENTS);
+  ChangeType(DesktopMediaID::TYPE_WEB_CONTENTS);
   AddTab(0);
   tab_list_->SetSourceThumbnail(0);
   AddTab(1);
@@ -237,7 +237,7 @@
 
 TEST_F(DesktopMediaPickerControllerTest, ClickCancel) {
   [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::SOURCE_WINDOW);
+  ChangeType(DesktopMediaID::TYPE_WINDOW);
 
   AddWindow(0);
   window_list_->SetSourceThumbnail(0);
@@ -254,7 +254,7 @@
 
 TEST_F(DesktopMediaPickerControllerTest, CloseWindow) {
   [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::SOURCE_SCREEN);
+  ChangeType(DesktopMediaID::TYPE_SCREEN);
 
   AddScreen(0);
   screen_list_->SetSourceThumbnail(0);
@@ -268,7 +268,7 @@
 
 TEST_F(DesktopMediaPickerControllerTest, UpdateThumbnail) {
   [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::SOURCE_WEB_CONTENTS);
+  ChangeType(DesktopMediaID::TYPE_WEB_CONTENTS);
 
   AddTab(0);
   tab_list_->SetSourceThumbnail(0);
@@ -285,7 +285,7 @@
 
 TEST_F(DesktopMediaPickerControllerTest, UpdateName) {
   [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::SOURCE_WINDOW);
+  ChangeType(DesktopMediaID::TYPE_WINDOW);
 
   AddWindow(0);
   window_list_->SetSourceThumbnail(0);
@@ -302,7 +302,7 @@
 
 TEST_F(DesktopMediaPickerControllerTest, RemoveSource) {
   [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::SOURCE_SCREEN);
+  ChangeType(DesktopMediaID::TYPE_SCREEN);
 
   AddScreen(0);
   AddScreen(1);
@@ -316,7 +316,7 @@
 
 TEST_F(DesktopMediaPickerControllerTest, MoveSource) {
   [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::SOURCE_WINDOW);
+  ChangeType(DesktopMediaID::TYPE_WINDOW);
 
   AddWindow(0);
   AddWindow(1);
@@ -345,26 +345,26 @@
   EXPECT_EQ(YES, [checkbox isHidden]);
 
   [checkbox setHidden:NO];
-  ChangeType(DesktopMediaID::SOURCE_WINDOW);
+  ChangeType(DesktopMediaID::TYPE_WINDOW);
   EXPECT_EQ(YES, [checkbox isHidden]);
 
   [checkbox setHidden:YES];
-  ChangeType(DesktopMediaID::SOURCE_WEB_CONTENTS);
+  ChangeType(DesktopMediaID::TYPE_WEB_CONTENTS);
   EXPECT_EQ(NO, [checkbox isHidden]);
 
   [checkbox setHidden:NO];
-  ChangeType(DesktopMediaID::SOURCE_SCREEN);
+  ChangeType(DesktopMediaID::TYPE_SCREEN);
   EXPECT_EQ(YES, [checkbox isHidden]);
 }
 
 TEST_F(DesktopMediaPickerControllerTest, TabShareWithAudio) {
   [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::SOURCE_WEB_CONTENTS);
+  ChangeType(DesktopMediaID::TYPE_WEB_CONTENTS);
 
   DesktopMediaID origin_id =
-      DesktopMediaID(DesktopMediaID::SOURCE_WEB_CONTENTS, 123);
+      DesktopMediaID(DesktopMediaID::TYPE_WEB_CONTENTS, 123);
   DesktopMediaID id_with_audio = origin_id;
-  id_with_audio.set_audio_capture(true);
+  id_with_audio.audio_share = true;
 
   tab_list_->AddSourceByFullMediaID(origin_id);
 
@@ -380,7 +380,7 @@
 
 TEST_F(DesktopMediaPickerControllerTest, TabBrowserFocusAlgorithm) {
   [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::SOURCE_WEB_CONTENTS);
+  ChangeType(DesktopMediaID::TYPE_WEB_CONTENTS);
   AddTab(0);
   AddTab(1);
   AddTab(2);
@@ -408,15 +408,15 @@
   EXPECT_EQ(1, [[items objectAtIndex:selected_index] sourceID].id);
 
   // Change source type back and forth, browser should memorize the selection.
-  ChangeType(DesktopMediaID::SOURCE_SCREEN);
-  ChangeType(DesktopMediaID::SOURCE_WEB_CONTENTS);
+  ChangeType(DesktopMediaID::TYPE_SCREEN);
+  ChangeType(DesktopMediaID::TYPE_WEB_CONTENTS);
   selected_index = [[browser selectedRowIndexes] firstIndex];
   EXPECT_EQ(1, [[items objectAtIndex:selected_index] sourceID].id);
 }
 
 TEST_F(DesktopMediaPickerControllerTest, SingleScreenNoLabel) {
   [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::SOURCE_SCREEN);
+  ChangeType(DesktopMediaID::TYPE_SCREEN);
 
   NSArray* items = [controller_ screenItems];
 
diff --git a/chrome/browser/ui/cocoa/page_info/page_info_bubble_controller.mm b/chrome/browser/ui/cocoa/page_info/page_info_bubble_controller.mm
index 478d14d..bcf3738 100644
--- a/chrome/browser/ui/cocoa/page_info/page_info_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/page_info/page_info_bubble_controller.mm
@@ -423,6 +423,13 @@
       [[FlippedView alloc] initWithFrame:[superview frame]]);
   [superview addSubview:siteSettingsSectionView];
 
+  permissionsView_ =
+      [[[FlippedView alloc] initWithFrame:[superview frame]] autorelease];
+  [siteSettingsSectionView addSubview:permissionsView_];
+
+  // The certificate section is created on demand.
+  certificateView_ = nil;
+
   // Initialize the two containers that hold the controls. The initial frames
   // are arbitrary, and will be adjusted after the controls are laid out.
   PageInfoUI::PermissionInfo info;
@@ -437,13 +444,6 @@
   [cookiesView_ setLinkTarget:self
                    withAction:@selector(showCookiesAndSiteData:)];
 
-  permissionsView_ =
-      [[[FlippedView alloc] initWithFrame:[superview frame]] autorelease];
-  [siteSettingsSectionView addSubview:permissionsView_];
-
-  // The certificate section is created on demand.
-  certificateView_ = nil;
-
   // Create the link button to view site settings. Its position will be set in
   // performLayout.
   NSString* siteSettingsButtonText =
@@ -645,7 +645,7 @@
 }
 
 - (void)layoutSecuritySection {
-  // Start the layout with the first element. Margins are handled by the caller.
+  // Margins are handled by the caller.
   CGFloat yPos = 0;
 
   [self sizeTextFieldHeightToFit:securitySummaryField_];
@@ -721,27 +721,27 @@
 }
 
 - (void)layoutSiteSettingsSection {
-  // Start the layout with the first element. Margins are handled by the caller.
-  CGFloat yPos = kSectionVerticalPadding;
+  // Margins are handled by the caller.
+  CGFloat yPos = 0;
+
+  if (permissionsPresent_) {
+    yPos = [self setYPositionOfView:permissionsView_ to:yPos] +
+           kPermissionsVerticalSpacing;
+  }
 
   if (certificateView_) {
     yPos = [self setYPositionOfView:certificateView_ to:yPos] +
            kPermissionsVerticalSpacing;
   }
 
-  yPos = [self setYPositionOfView:cookiesView_ to:yPos];
+  yPos =
+      [self setYPositionOfView:cookiesView_ to:yPos] + kSectionVerticalPadding;
 
-  if (permissionsPresent_) {
-    // Put the permission info just below the link button.
-    yPos = [self setYPositionOfView:permissionsView_ to:yPos];
-  }
-
-  yPos = [self layoutViewAtRTLStart:siteSettingsButton_
-                      withYPosition:yPos + kSectionVerticalPadding];
+  yPos = [self layoutViewAtRTLStart:siteSettingsButton_ withYPosition:yPos] +
+         kSectionVerticalPadding;
 
   // Resize the height based on contents.
-  [self setHeightOfView:siteSettingsSectionView_
-                     to:yPos + kSectionVerticalPadding];
+  [self setHeightOfView:siteSettingsSectionView_ to:yPos];
 }
 
 // Adjust the size of the window to match the size of the content, and position
@@ -922,31 +922,30 @@
       }
     }
 
-    if (PageInfoUI::ShouldShowCertificateLink()) {
-      bool isValid = (identityInfo.identity_status !=
-                      PageInfo::SITE_IDENTITY_STATUS_ERROR);
-      NSString* linkText = l10n_util::GetNSString(
-          isValid ? IDS_PAGE_INFO_CERTIFICATE_VALID_LINK
-                  : IDS_PAGE_INFO_CERTIFICATE_INVALID_LINK);
+    // Show information about the page's certificate.
+    bool isValid =
+        (identityInfo.identity_status != PageInfo::SITE_IDENTITY_STATUS_ERROR);
+    NSString* linkText = l10n_util::GetNSString(
+        isValid ? IDS_PAGE_INFO_CERTIFICATE_VALID_LINK
+                : IDS_PAGE_INFO_CERTIFICATE_INVALID_LINK);
 
-      certificateView_ =
-          [self addInspectLinkToView:siteSettingsSectionView_
-                         sectionIcon:NSImageFromImageSkia(
-                                         PageInfoUI::GetCertificateIcon())
-                        sectionTitle:l10n_util::GetStringUTF16(
-                                         IDS_PAGE_INFO_CERTIFICATE)
-                            linkText:linkText];
-      if (isValid) {
-        [certificateView_
-            setLinkToolTip:l10n_util::GetNSStringF(
-                               IDS_PAGE_INFO_CERTIFICATE_VALID_LINK_TOOLTIP,
-                               base::UTF8ToUTF16(
-                                   certificate_->issuer().GetDisplayName()))];
-      }
-
-      [certificateView_ setLinkTarget:self
-                           withAction:@selector(showCertificateInfo:)];
+    certificateView_ =
+        [self addInspectLinkToView:siteSettingsSectionView_
+                       sectionIcon:NSImageFromImageSkia(
+                                       PageInfoUI::GetCertificateIcon())
+                      sectionTitle:l10n_util::GetStringUTF16(
+                                       IDS_PAGE_INFO_CERTIFICATE)
+                          linkText:linkText];
+    if (isValid) {
+      [certificateView_
+          setLinkToolTip:l10n_util::GetNSStringF(
+                             IDS_PAGE_INFO_CERTIFICATE_VALID_LINK_TOOLTIP,
+                             base::UTF8ToUTF16(
+                                 certificate_->issuer().GetDisplayName()))];
     }
+
+    [certificateView_ setLinkTarget:self
+                         withAction:@selector(showCertificateInfo:)];
   }
   if (identityInfo.show_change_password_buttons) {
     changePasswordButton_ =
diff --git a/chrome/browser/ui/cocoa/password_reuse_warning_dialog_cocoa.mm b/chrome/browser/ui/cocoa/password_reuse_warning_dialog_cocoa.mm
index 218a1e9c..eefb25d 100644
--- a/chrome/browser/ui/cocoa/password_reuse_warning_dialog_cocoa.mm
+++ b/chrome/browser/ui/cocoa/password_reuse_warning_dialog_cocoa.mm
@@ -4,9 +4,11 @@
 
 #import "chrome/browser/ui/cocoa/password_reuse_warning_dialog_cocoa.h"
 
+#include "chrome/browser/ui/cocoa/browser_dialogs_views_mac.h"
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.h"
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window.h"
 #import "chrome/browser/ui/cocoa/password_reuse_warning_view_controller.h"
+#include "ui/base/material_design/material_design_controller.h"
 
 namespace safe_browsing {
 
@@ -16,6 +18,12 @@
     OnWarningDone done_callback) {
   DCHECK(web_contents);
 
+  if (ui::MaterialDesignController::IsSecondaryUiMaterial()) {
+    chrome::ShowPasswordReuseWarningDialog(web_contents, service,
+                                           std::move(done_callback));
+    return;
+  }
+
   // Dialog owns itself.
   new PasswordReuseWarningDialogCocoa(web_contents, service,
                                       std::move(done_callback));
diff --git a/chrome/browser/ui/cocoa/scoped_menu_bar_lock.h b/chrome/browser/ui/cocoa/scoped_menu_bar_lock.h
new file mode 100644
index 0000000..6df7feb
--- /dev/null
+++ b/chrome/browser/ui/cocoa/scoped_menu_bar_lock.h
@@ -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.
+
+#ifndef CHROME_BROWSER_UI_COCOA_SCOPED_MENU_BAR_LOCK_H_
+#define CHROME_BROWSER_UI_COCOA_SCOPED_MENU_BAR_LOCK_H_
+
+#include "base/macros.h"
+
+// ScopedMenuBarLock uses an AppKit API to lock the menu bar in its current
+// state (visible/hidden). Useful to temporarily keep the menu bar visible
+// after appearing when the user moved the mouse to the top of the screen, or
+// to temporarily prevent the menu bar from showing automatically.
+// ScopedMenuBarLock helps enforce that lock/unlock calls are balanced.
+class ScopedMenuBarLock {
+ public:
+  ScopedMenuBarLock();
+  ~ScopedMenuBarLock();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ScopedMenuBarLock);
+};
+
+#endif  // CHROME_BROWSER_UI_COCOA_SCOPED_MENU_BAR_LOCK_H_
diff --git a/chrome/browser/ui/cocoa/scoped_menu_bar_lock.mm b/chrome/browser/ui/cocoa/scoped_menu_bar_lock.mm
new file mode 100644
index 0000000..fe1da55d
--- /dev/null
+++ b/chrome/browser/ui/cocoa/scoped_menu_bar_lock.mm
@@ -0,0 +1,22 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/scoped_menu_bar_lock.h"
+
+#import <AppKit/AppKit.h>
+
+@interface NSMenu (PrivateAPI)
+- (void)_lockMenuPosition;
+- (void)_unlockMenuPosition;
+@end
+
+ScopedMenuBarLock::ScopedMenuBarLock() {
+  if ([NSMenu instancesRespondToSelector:@selector(_lockMenuPosition)])
+    [[NSApp mainMenu] _lockMenuPosition];
+}
+
+ScopedMenuBarLock::~ScopedMenuBarLock() {
+  if ([NSMenu instancesRespondToSelector:@selector(_unlockMenuPosition)])
+    [[NSApp mainMenu] _unlockMenuPosition];
+}
diff --git a/chrome/browser/ui/cocoa/scoped_menu_bar_lock_unittest.mm b/chrome/browser/ui/cocoa/scoped_menu_bar_lock_unittest.mm
new file mode 100644
index 0000000..1c0e2bf6
--- /dev/null
+++ b/chrome/browser/ui/cocoa/scoped_menu_bar_lock_unittest.mm
@@ -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.
+
+#import "chrome/browser/ui/cocoa/scoped_menu_bar_lock.h"
+
+#import <AppKit/AppKit.h>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Verify that creating and tearing down a ScopedMenuBarLock doesn't crash.
+TEST(ScopedMenuBarLockTest, CreateAndDestroy) {
+  ScopedMenuBarLock menuBarLock;
+}
+
+// Verify that the API still exists.
+TEST(ScopedMenuBarLockTest, PrivateAPIs) {
+  EXPECT_TRUE([NSMenu instancesRespondToSelector:@selector(_lockMenuPosition)]);
+  EXPECT_TRUE(
+      [NSMenu instancesRespondToSelector:@selector(_unlockMenuPosition)]);
+}
diff --git a/chrome/browser/ui/javascript_dialogs/javascript_dialog_browsertest.cc b/chrome/browser/ui/javascript_dialogs/javascript_dialog_browsertest.cc
index a84ba449..ee19db91 100644
--- a/chrome/browser/ui/javascript_dialogs/javascript_dialog_browsertest.cc
+++ b/chrome/browser/ui/javascript_dialogs/javascript_dialog_browsertest.cc
@@ -52,7 +52,8 @@
       base::UTF8ToUTF16("window.open('about:blank');"));
   content::WebContents* tab2 = new_wc_observer.GetWebContents();
   ASSERT_NE(tab1, tab2);
-  ASSERT_EQ(tab1->GetRenderProcessHost(), tab2->GetRenderProcessHost());
+  ASSERT_EQ(tab1->GetMainFrame()->GetProcess(),
+            tab2->GetMainFrame()->GetProcess());
 
   // Tab two shows a dialog.
   scoped_refptr<content::MessageLoopRunner> runner =
diff --git a/chrome/browser/ui/page_info/page_info.cc b/chrome/browser/ui/page_info/page_info.cc
index 741b297..9ca5da7 100644
--- a/chrome/browser/ui/page_info/page_info.cc
+++ b/chrome/browser/ui/page_info/page_info.cc
@@ -322,8 +322,8 @@
   Init(url, security_info);
 
   PresentSitePermissions();
-  PresentSiteData();
   PresentSiteIdentity();
+  PresentSiteData();
 
   // Every time the Page Info UI is opened a |PageInfo| object is
   // created. So this counts how ofter the Page Info UI is opened.
diff --git a/chrome/browser/ui/page_info/page_info_ui.cc b/chrome/browser/ui/page_info/page_info_ui.cc
index abed05193..d44f1136 100644
--- a/chrome/browser/ui/page_info/page_info_ui.cc
+++ b/chrome/browser/ui/page_info/page_info_ui.cc
@@ -465,12 +465,6 @@
 #endif
 
 // static
-bool PageInfoUI::ShouldShowCertificateLink() {
-  return base::CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kShowCertLink);
-}
-
-// static
 bool PageInfoUI::ContentSettingsTypeInPageInfo(ContentSettingsType type) {
   for (const PermissionsUIInfo& info : kPermissionsUIInfo) {
     if (info.type == type)
diff --git a/chrome/browser/ui/page_info/page_info_ui.h b/chrome/browser/ui/page_info/page_info_ui.h
index 3533357..85f03dff 100644
--- a/chrome/browser/ui/page_info/page_info_ui.h
+++ b/chrome/browser/ui/page_info/page_info_ui.h
@@ -197,9 +197,6 @@
   static const gfx::ImageSkia GetCertificateIcon();
 #endif
 
-  // Returns true if the Certificate Viewer link should be shown.
-  static bool ShouldShowCertificateLink();
-
   // Return true if the given ContentSettingsType is in PageInfoUI.
   static bool ContentSettingsTypeInPageInfo(ContentSettingsType type);
 
diff --git a/chrome/browser/ui/search/local_ntp_browsertest.cc b/chrome/browser/ui/search/local_ntp_browsertest.cc
index cf428cd..ebff6bfb 100644
--- a/chrome/browser/ui/search/local_ntp_browsertest.cc
+++ b/chrome/browser/ui/search/local_ntp_browsertest.cc
@@ -9,6 +9,7 @@
 
 #include "base/command_line.h"
 #include "base/i18n/base_i18n_switches.h"
+#include "base/json/string_escape.h"
 #include "base/memory/ptr_util.h"
 #include "base/optional.h"
 #include "base/strings/utf_string_conversions.h"
@@ -27,6 +28,7 @@
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
+#include "chrome/browser/search_provider_logos/logo_service_factory.h"
 #include "chrome/browser/signin/gaia_cookie_manager_service_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
@@ -44,6 +46,7 @@
 #include "components/search_engines/template_url.h"
 #include "components/search_engines/template_url_data.h"
 #include "components/search_engines/template_url_service.h"
+#include "components/search_provider_logos/logo_service.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
@@ -51,8 +54,17 @@
 #include "content/public/test/test_utils.h"
 #include "media/base/media_switches.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "ui/base/resource/resource_bundle.h"
 
+using search_provider_logos::EncodedLogo;
+using search_provider_logos::LogoCallbacks;
+using search_provider_logos::LogoCallbackReason;
+using search_provider_logos::LogoObserver;
+using search_provider_logos::LogoService;
+using testing::Eq;
+using testing::IsEmpty;
+
 namespace {
 
 content::WebContents* OpenNewTab(Browser* browser, const GURL& url) {
@@ -695,3 +707,148 @@
           GURL(chrome::kChromeUINewTabURL).GetOrigin());
   EXPECT_EQ(CONTENT_SETTING_ALLOW, mic_permission_after.content_setting);
 }
+
+// Returns configured logos.
+class FakeLogoService : public LogoService {
+ public:
+  void GetLogo(search_provider_logos::LogoCallbacks callbacks) override {
+    DCHECK(!callbacks.on_cached_decoded_logo_available);
+    DCHECK(!callbacks.on_fresh_decoded_logo_available);
+
+    if (callbacks.on_cached_encoded_logo_available) {
+      std::move(callbacks.on_cached_encoded_logo_available)
+          .Run(cached_reason, cached_logo);
+    }
+    if (callbacks.on_fresh_encoded_logo_available) {
+      std::move(callbacks.on_fresh_encoded_logo_available)
+          .Run(fresh_reason, fresh_logo);
+    }
+  }
+
+  void GetLogo(LogoObserver* observer) override { NOTREACHED(); }
+
+  LogoCallbackReason cached_reason = LogoCallbackReason::CANCELED;
+  base::Optional<EncodedLogo> cached_logo;
+  LogoCallbackReason fresh_reason = LogoCallbackReason::CANCELED;
+  base::Optional<EncodedLogo> fresh_logo;
+};
+
+class LocalNTPDoodleTest : public InProcessBrowserTest {
+ protected:
+  LocalNTPDoodleTest() {}
+
+  FakeLogoService* logo_service() {
+    return static_cast<FakeLogoService*>(
+        LogoServiceFactory::GetForProfile(browser()->profile()));
+  }
+
+  base::Optional<std::string> GetComputedStyle(content::WebContents* tab,
+                                               std::string id,
+                                               std::string css_name) {
+    std::string css_value;
+    if (instant_test_utils::GetStringFromJS(
+            tab,
+            base::StringPrintf(
+                "getComputedStyle(document.getElementById(%s))[%s]",
+                base::GetQuotedJSONString(id).c_str(),
+                base::GetQuotedJSONString(css_name).c_str()),
+            &css_value)) {
+      return css_value;
+    }
+    return base::nullopt;
+  }
+
+ private:
+  void SetUp() override {
+    feature_list_.InitWithFeatures(
+        {features::kUseGoogleLocalNtp, features::kDoodlesOnLocalNtp}, {});
+    InProcessBrowserTest::SetUp();
+  }
+
+  void SetUpInProcessBrowserTestFixture() override {
+    will_create_browser_context_services_subscription_ =
+        BrowserContextDependencyManager::GetInstance()
+            ->RegisterWillCreateBrowserContextServicesCallbackForTesting(
+                base::Bind(
+                    &LocalNTPDoodleTest::OnWillCreateBrowserContextServices,
+                    base::Unretained(this)));
+  }
+
+  static std::unique_ptr<KeyedService> CreateLogoService(
+      content::BrowserContext* context) {
+    return base::MakeUnique<FakeLogoService>();
+  }
+
+  void OnWillCreateBrowserContextServices(content::BrowserContext* context) {
+    LogoServiceFactory::GetInstance()->SetTestingFactory(
+        context, &LocalNTPDoodleTest::CreateLogoService);
+  }
+
+  base::test::ScopedFeatureList feature_list_;
+
+  std::unique_ptr<
+      base::CallbackList<void(content::BrowserContext*)>::Subscription>
+      will_create_browser_context_services_subscription_;
+};
+
+IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,
+                       ShouldBeUnchangedOnLogoFetchCancelled) {
+  logo_service()->cached_reason = LogoCallbackReason::CANCELED;
+  logo_service()->fresh_reason = LogoCallbackReason::CANCELED;
+
+  // Open a new blank tab, then go to NTP and listen for console messages.
+  content::WebContents* active_tab = OpenNewTab(browser(), GURL("about:blank"));
+  content::ConsoleObserverDelegate console_observer(active_tab, "*");
+  active_tab->SetDelegate(&console_observer);
+  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
+
+  EXPECT_THAT(GetComputedStyle(active_tab, "logo-default", "opacity"),
+              Eq<std::string>("1"));
+  EXPECT_THAT(GetComputedStyle(active_tab, "logo-doodle", "opacity"),
+              Eq<std::string>("0"));
+  EXPECT_THAT(console_observer.message(), IsEmpty());
+}
+
+IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,
+                       ShouldBeUnchangedWhenDoodleUnavailable) {
+  logo_service()->cached_reason = LogoCallbackReason::DETERMINED;
+  logo_service()->fresh_reason = LogoCallbackReason::REVALIDATED;
+
+  // Open a new blank tab, then go to NTP and listen for console messages.
+  content::WebContents* active_tab = OpenNewTab(browser(), GURL("about:blank"));
+  content::ConsoleObserverDelegate console_observer(active_tab, "*");
+  active_tab->SetDelegate(&console_observer);
+  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
+
+  EXPECT_THAT(GetComputedStyle(active_tab, "logo-default", "opacity"),
+              Eq<std::string>("1"));
+  EXPECT_THAT(GetComputedStyle(active_tab, "logo-doodle", "opacity"),
+              Eq<std::string>("0"));
+  EXPECT_THAT(console_observer.message(), IsEmpty());
+}
+
+IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldShowDoodleWhenAvailable) {
+  logo_service()->cached_reason = LogoCallbackReason::DETERMINED;
+
+  logo_service()->cached_logo = EncodedLogo();
+  std::string encoded_image = "data:image/svg+xml,<svg/>";
+  logo_service()->cached_logo->encoded_image =
+      base::RefCountedString::TakeString(&encoded_image);
+  logo_service()->cached_logo->metadata.on_click_url =
+      GURL("https://www.chromium.org");
+  logo_service()->cached_logo->metadata.alt_text = "Chromium";
+
+  logo_service()->fresh_reason = LogoCallbackReason::REVALIDATED;
+
+  // Open a new blank tab, then go to NTP and listen for console messages.
+  content::WebContents* active_tab = OpenNewTab(browser(), GURL("about:blank"));
+  content::ConsoleObserverDelegate console_observer(active_tab, "*");
+  active_tab->SetDelegate(&console_observer);
+  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
+
+  EXPECT_THAT(GetComputedStyle(active_tab, "logo-default", "opacity"),
+              Eq<std::string>("0"));
+  EXPECT_THAT(GetComputedStyle(active_tab, "logo-doodle", "opacity"),
+              Eq<std::string>("1"));
+  EXPECT_THAT(console_observer.message(), IsEmpty());
+}
diff --git a/chrome/browser/ui/search/ntp_user_data_logger.cc b/chrome/browser/ui/search/ntp_user_data_logger.cc
index ee83c405..f9c5669 100644
--- a/chrome/browser/ui/search/ntp_user_data_logger.cc
+++ b/chrome/browser/ui/search/ntp_user_data_logger.cc
@@ -215,6 +215,7 @@
 
 void NTPUserDataLogger::LogMostVisitedImpression(
     int position,
+    ntp_tiles::TileTitleSource tile_title_source,
     ntp_tiles::TileSource tile_source,
     ntp_tiles::TileVisualType tile_type) {
   if ((position >= kNumMostVisited) || impression_was_logged_[position]) {
@@ -223,13 +224,16 @@
   impression_was_logged_[position] = true;
   impression_tile_source_[position] = tile_source;
   impression_tile_type_[position] = tile_type;
+  impression_tile_title_source_[position] = tile_title_source;
 }
 
 void NTPUserDataLogger::LogMostVisitedNavigation(
     int position,
+    ntp_tiles::TileTitleSource tile_title_source,
     ntp_tiles::TileSource tile_source,
     ntp_tiles::TileVisualType tile_type) {
-  ntp_tiles::metrics::RecordTileClick(position, tile_source, tile_type);
+  ntp_tiles::metrics::RecordTileClick(position, tile_title_source, tile_source,
+                                      tile_type);
 
   // Records the action. This will be available as a time-stamped stream
   // server-side and can be used to compute time-to-long-dwell.
@@ -238,6 +242,7 @@
 
 NTPUserDataLogger::NTPUserDataLogger(content::WebContents* contents)
     : content::WebContentsObserver(contents),
+      impression_tile_title_source_(kNumMostVisited),
       impression_tile_source_(kNumMostVisited),
       impression_tile_type_(kNumMostVisited),
       has_emitted_(false),
@@ -294,9 +299,10 @@
     }
     // No URL and rappor service passed - not interested in favicon-related
     // Rappor metrics.
-    ntp_tiles::metrics::RecordTileImpression(i, impression_tile_source_[i],
-                                             impression_tile_type_[i], GURL(),
-                                             /*rappor_service=*/nullptr);
+    ntp_tiles::metrics::RecordTileImpression(
+        i, impression_tile_title_source_[i], impression_tile_source_[i],
+        impression_tile_type_[i], GURL(),
+        /*rappor_service=*/nullptr);
     ++tiles_count;
   }
   ntp_tiles::metrics::RecordPageImpression(tiles_count);
diff --git a/chrome/browser/ui/search/ntp_user_data_logger.h b/chrome/browser/ui/search/ntp_user_data_logger.h
index 60deb90..05b290d 100644
--- a/chrome/browser/ui/search/ntp_user_data_logger.h
+++ b/chrome/browser/ui/search/ntp_user_data_logger.h
@@ -8,12 +8,14 @@
 #include <stddef.h>
 
 #include <bitset>
+#include <vector>
 
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/time/time.h"
 #include "chrome/common/search/ntp_logging_events.h"
 #include "components/ntp_tiles/tile_source.h"
+#include "components/ntp_tiles/tile_title_source.h"
 #include "components/ntp_tiles/tile_visual_type.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
@@ -42,11 +44,13 @@
 
   // Logs an impression on one of the NTP tiles by a given source.
   void LogMostVisitedImpression(int position,
+                                ntp_tiles::TileTitleSource tile_title_source,
                                 ntp_tiles::TileSource tile_source,
                                 ntp_tiles::TileVisualType tile_type);
 
   // Logs a navigation on one of the NTP tiles by a given source.
   void LogMostVisitedNavigation(int position,
+                                ntp_tiles::TileTitleSource tile_title_source,
                                 ntp_tiles::TileSource tile_source,
                                 ntp_tiles::TileVisualType tile_type);
 
@@ -91,6 +95,10 @@
   // number of impressions for a source slightly out-of-sync with navigations.
   std::bitset<kNumMostVisited> impression_was_logged_;
 
+  // Stores the tile title source for each impression. Entries are only valid if
+  // the corresponding entry in |impression_was_logged_| is true.
+  std::vector<ntp_tiles::TileTitleSource> impression_tile_title_source_;
+
   // Stores the tile source for each impression. Entries are only valid if the
   // corresponding entry in |impression_was_logged_| is true.
   std::vector<ntp_tiles::TileSource> impression_tile_source_;
diff --git a/chrome/browser/ui/search/ntp_user_data_logger_unittest.cc b/chrome/browser/ui/search/ntp_user_data_logger_unittest.cc
index 0ebc8f3..b62c44ce 100644
--- a/chrome/browser/ui/search/ntp_user_data_logger_unittest.cc
+++ b/chrome/browser/ui/search/ntp_user_data_logger_unittest.cc
@@ -17,6 +17,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 using base::Bucket;
+using ntp_tiles::TileTitleSource;
 using ntp_tiles::TileSource;
 using ntp_tiles::TileVisualType;
 using testing::ElementsAre;
@@ -25,6 +26,15 @@
 
 namespace {
 
+constexpr int kUnknownTitleSource = static_cast<int>(TileTitleSource::UNKNOWN);
+constexpr int kManifestTitleSource =
+    static_cast<int>(TileTitleSource::MANIFEST);
+constexpr int kMetaTagTitleSource = static_cast<int>(TileTitleSource::META_TAG);
+constexpr int kTitleTagTitleSource =
+    static_cast<int>(TileTitleSource::TITLE_TAG);
+constexpr int kInferredTitleSource =
+    static_cast<int>(TileTitleSource::INFERRED);
+
 using Sample = base::HistogramBase::Sample;
 using Samples = std::vector<Sample>;
 
@@ -55,7 +65,8 @@
   base::TimeDelta delta = base::TimeDelta::FromMilliseconds(0);
 
   for (int i = 0; i < 8; ++i) {
-    logger.LogMostVisitedImpression(i, TileSource::SUGGESTIONS_SERVICE,
+    logger.LogMostVisitedImpression(i, TileTitleSource::UNKNOWN,
+                                    TileSource::SUGGESTIONS_SERVICE,
                                     TileVisualType::THUMBNAIL);
   }
   logger.LogEvent(NTP_ALL_TILES_LOADED, delta);
@@ -77,6 +88,7 @@
               ElementsAre(Bucket(0, 1), Bucket(8, 1)));
 }
 
+// TODO(https://crbug.com/767406): Split this test in readable units.
 TEST(NTPUserDataLoggerTest, TestLogMostVisitedImpression) {
   base::StatisticsRecorder::Initialize();
 
@@ -87,37 +99,51 @@
   base::TimeDelta delta = base::TimeDelta::FromMilliseconds(0);
 
   // Impressions increment the associated bins.
-  logger.LogMostVisitedImpression(0, TileSource::SUGGESTIONS_SERVICE,
+  logger.LogMostVisitedImpression(0, TileTitleSource::INFERRED,
+                                  TileSource::SUGGESTIONS_SERVICE,
                                   TileVisualType::THUMBNAIL);
-  logger.LogMostVisitedImpression(1, TileSource::SUGGESTIONS_SERVICE,
+  logger.LogMostVisitedImpression(1, TileTitleSource::INFERRED,
+                                  TileSource::SUGGESTIONS_SERVICE,
                                   TileVisualType::THUMBNAIL_FAILED);
-  logger.LogMostVisitedImpression(2, TileSource::SUGGESTIONS_SERVICE,
+  logger.LogMostVisitedImpression(2, TileTitleSource::INFERRED,
+                                  TileSource::SUGGESTIONS_SERVICE,
                                   TileVisualType::THUMBNAIL);
-  logger.LogMostVisitedImpression(3, TileSource::SUGGESTIONS_SERVICE,
+  logger.LogMostVisitedImpression(3, TileTitleSource::INFERRED,
+                                  TileSource::SUGGESTIONS_SERVICE,
                                   TileVisualType::THUMBNAIL);
-  logger.LogMostVisitedImpression(4, TileSource::TOP_SITES,
+  logger.LogMostVisitedImpression(4, TileTitleSource::TITLE_TAG,
+                                  TileSource::TOP_SITES,
                                   TileVisualType::THUMBNAIL);
-  logger.LogMostVisitedImpression(5, TileSource::TOP_SITES,
+  logger.LogMostVisitedImpression(5, TileTitleSource::MANIFEST,
+                                  TileSource::TOP_SITES,
                                   TileVisualType::THUMBNAIL);
-  logger.LogMostVisitedImpression(6, TileSource::TOP_SITES,
+  logger.LogMostVisitedImpression(6, TileTitleSource::TITLE_TAG,
+                                  TileSource::POPULAR,
                                   TileVisualType::THUMBNAIL);
-  logger.LogMostVisitedImpression(7, TileSource::TOP_SITES,
+  logger.LogMostVisitedImpression(7, TileTitleSource::META_TAG,
+                                  TileSource::POPULAR_BAKED_IN,
                                   TileVisualType::THUMBNAIL);
 
   // Repeated impressions for the same bins are ignored.
-  logger.LogMostVisitedImpression(0, TileSource::SUGGESTIONS_SERVICE,
+  logger.LogMostVisitedImpression(0, TileTitleSource::UNKNOWN,
+                                  TileSource::SUGGESTIONS_SERVICE,
                                   TileVisualType::THUMBNAIL_FAILED);
-  logger.LogMostVisitedImpression(1, TileSource::TOP_SITES,
+  logger.LogMostVisitedImpression(1, TileTitleSource::UNKNOWN,
+                                  TileSource::TOP_SITES,
                                   TileVisualType::THUMBNAIL_FAILED);
-  logger.LogMostVisitedImpression(2, TileSource::SUGGESTIONS_SERVICE,
+  logger.LogMostVisitedImpression(2, TileTitleSource::UNKNOWN,
+                                  TileSource::SUGGESTIONS_SERVICE,
                                   TileVisualType::THUMBNAIL);
-  logger.LogMostVisitedImpression(3, TileSource::TOP_SITES,
+  logger.LogMostVisitedImpression(3, TileTitleSource::UNKNOWN,
+                                  TileSource::TOP_SITES,
                                   TileVisualType::THUMBNAIL);
 
   // Impressions are silently ignored for tiles >= 8.
-  logger.LogMostVisitedImpression(8, TileSource::SUGGESTIONS_SERVICE,
+  logger.LogMostVisitedImpression(8, TileTitleSource::UNKNOWN,
+                                  TileSource::SUGGESTIONS_SERVICE,
                                   TileVisualType::THUMBNAIL);
-  logger.LogMostVisitedImpression(9, TileSource::TOP_SITES,
+  logger.LogMostVisitedImpression(9, TileTitleSource::UNKNOWN,
+                                  TileSource::TOP_SITES,
                                   TileVisualType::THUMBNAIL);
 
   // The actual histograms are emitted only after the ALL_TILES_LOADED event, so
@@ -136,6 +162,12 @@
               IsEmpty());
   EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.TileType.server"),
               IsEmpty());
+  EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.TileTitle"),
+              IsEmpty());
+  EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.TileTitle.client"),
+              IsEmpty());
+  EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.TileTitle.server"),
+              IsEmpty());
 
   // Send the ALL_TILES_LOADED event, this should trigger emitting histograms.
   logger.LogEvent(NTP_ALL_TILES_LOADED, delta);
@@ -149,7 +181,13 @@
       ElementsAre(Bucket(0, 1), Bucket(1, 1), Bucket(2, 1), Bucket(3, 1)));
   EXPECT_THAT(
       histogram_tester.GetAllSamples("NewTabPage.SuggestionsImpression.client"),
-      ElementsAre(Bucket(4, 1), Bucket(5, 1), Bucket(6, 1), Bucket(7, 1)));
+      ElementsAre(Bucket(4, 1), Bucket(5, 1)));
+  EXPECT_THAT(histogram_tester.GetAllSamples(
+                  "NewTabPage.SuggestionsImpression.popular_fetched"),
+              ElementsAre(Bucket(6, 1)));
+  EXPECT_THAT(histogram_tester.GetAllSamples(
+                  "NewTabPage.SuggestionsImpression.popular_baked_in"),
+              ElementsAre(Bucket(7, 1)));
   EXPECT_THAT(
       histogram_tester.GetAllSamples("NewTabPage.TileType"),
       ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL, 7),
@@ -159,20 +197,46 @@
       ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL, 3),
                   Bucket(ntp_tiles::TileVisualType::THUMBNAIL_FAILED, 1)));
   EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.TileType.client"),
-              ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL, 4)));
+              ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL, 2)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("NewTabPage.TileType.popular_fetched"),
+      ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL, 1)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("NewTabPage.TileType.popular_baked_in"),
+      ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL, 1)));
+  EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.TileTitle"),
+              ElementsAre(Bucket(kManifestTitleSource, 1),
+                          Bucket(kMetaTagTitleSource, 1),
+                          Bucket(kTitleTagTitleSource, 2),
+                          Bucket(kInferredTitleSource, 4)));
+  EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.TileTitle.server"),
+              ElementsAre(Bucket(kInferredTitleSource, 4)));
+  EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.TileTitle.client"),
+              ElementsAre(Bucket(kManifestTitleSource, 1),
+                          Bucket(kTitleTagTitleSource, 1)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("NewTabPage.TileTitle.popular_fetched"),
+      ElementsAre(Bucket(kTitleTagTitleSource, 1)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("NewTabPage.TileTitle.popular_baked_in"),
+      ElementsAre(Bucket(kMetaTagTitleSource, 1)));
 
   // After navigating away from the NTP and back, we record again.
   logger.NavigatedFromURLToURL(GURL("chrome://newtab/"),
                                GURL("http://chromium.org"));
   logger.NavigatedFromURLToURL(GURL("http://chromium.org"),
                                GURL("chrome://newtab/"));
-  logger.LogMostVisitedImpression(0, TileSource::SUGGESTIONS_SERVICE,
+  logger.LogMostVisitedImpression(0, TileTitleSource::INFERRED,
+                                  TileSource::SUGGESTIONS_SERVICE,
                                   TileVisualType::THUMBNAIL);
-  logger.LogMostVisitedImpression(1, TileSource::TOP_SITES,
+  logger.LogMostVisitedImpression(1, TileTitleSource::MANIFEST,
+                                  TileSource::POPULAR,
                                   TileVisualType::THUMBNAIL);
-  logger.LogMostVisitedImpression(2, TileSource::SUGGESTIONS_SERVICE,
+  logger.LogMostVisitedImpression(2, TileTitleSource::INFERRED,
+                                  TileSource::SUGGESTIONS_SERVICE,
                                   TileVisualType::THUMBNAIL);
-  logger.LogMostVisitedImpression(3, TileSource::TOP_SITES,
+  logger.LogMostVisitedImpression(3, TileTitleSource::MANIFEST,
+                                  TileSource::TOP_SITES,
                                   TileVisualType::THUMBNAIL_FAILED);
   logger.LogEvent(NTP_ALL_TILES_LOADED, delta);
 
@@ -185,8 +249,13 @@
       ElementsAre(Bucket(0, 2), Bucket(1, 1), Bucket(2, 2), Bucket(3, 1)));
   EXPECT_THAT(
       histogram_tester.GetAllSamples("NewTabPage.SuggestionsImpression.client"),
-      ElementsAre(Bucket(1, 1), Bucket(3, 1), Bucket(4, 1), Bucket(5, 1),
-                  Bucket(6, 1), Bucket(7, 1)));
+      ElementsAre(Bucket(3, 1), Bucket(4, 1), Bucket(5, 1)));
+  EXPECT_THAT(histogram_tester.GetAllSamples(
+                  "NewTabPage.SuggestionsImpression.popular_fetched"),
+              ElementsAre(Bucket(1, 1), Bucket(6, 1)));
+  EXPECT_THAT(histogram_tester.GetAllSamples(
+                  "NewTabPage.SuggestionsImpression.popular_baked_in"),
+              ElementsAre(Bucket(7, 1)));
   EXPECT_THAT(
       histogram_tester.GetAllSamples("NewTabPage.TileType"),
       ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL, 10),
@@ -197,10 +266,34 @@
                   Bucket(ntp_tiles::TileVisualType::THUMBNAIL_FAILED, 1)));
   EXPECT_THAT(
       histogram_tester.GetAllSamples("NewTabPage.TileType.client"),
-      ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL, 5),
+      ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL, 2),
                   Bucket(ntp_tiles::TileVisualType::THUMBNAIL_FAILED, 1)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("NewTabPage.TileType.popular_fetched"),
+      ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL, 2)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("NewTabPage.TileType.popular_baked_in"),
+      ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL, 1)));
+  EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.TileTitle"),
+              ElementsAre(Bucket(kManifestTitleSource, 3),
+                          Bucket(kMetaTagTitleSource, 1),
+                          Bucket(kTitleTagTitleSource, 2),
+                          Bucket(kInferredTitleSource, 6)));
+  EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.TileTitle.server"),
+              ElementsAre(Bucket(kInferredTitleSource, 6)));
+  EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.TileTitle.client"),
+              ElementsAre(Bucket(kManifestTitleSource, 2),
+                          Bucket(kTitleTagTitleSource, 1)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("NewTabPage.TileTitle.popular_fetched"),
+      ElementsAre(Bucket(kManifestTitleSource, 1),
+                  Bucket(kTitleTagTitleSource, 1)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("NewTabPage.TileTitle.popular_baked_in"),
+      ElementsAre(Bucket(kMetaTagTitleSource, 1)));
 }
 
+// TODO(https://crbug.com/767406): Split this test in readable units.
 TEST(NTPUserDataLoggerTest, TestLogMostVisitedNavigation) {
   base::StatisticsRecorder::Initialize();
 
@@ -208,7 +301,8 @@
 
   TestNTPUserDataLogger logger(GURL("chrome://newtab/"));
 
-  logger.LogMostVisitedNavigation(0, TileSource::SUGGESTIONS_SERVICE,
+  logger.LogMostVisitedNavigation(0, TileTitleSource::UNKNOWN,
+                                  TileSource::SUGGESTIONS_SERVICE,
                                   TileVisualType::THUMBNAIL);
   EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.MostVisited"),
               ElementsAre(Bucket(0, 1)));
@@ -225,7 +319,8 @@
       histogram_tester.GetAllSamples("NewTabPage.TileTypeClicked.client"),
       IsEmpty());
 
-  logger.LogMostVisitedNavigation(1, TileSource::SUGGESTIONS_SERVICE,
+  logger.LogMostVisitedNavigation(1, TileTitleSource::UNKNOWN,
+                                  TileSource::SUGGESTIONS_SERVICE,
                                   TileVisualType::THUMBNAIL_FAILED);
   EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.MostVisited"),
               ElementsAre(Bucket(0, 1), Bucket(1, 1)));
@@ -245,8 +340,9 @@
       histogram_tester.GetAllSamples("NewTabPage.TileTypeClicked.client"),
       IsEmpty());
 
-  logger.LogMostVisitedNavigation(2, TileSource::TOP_SITES,
-                                  TileVisualType::THUMBNAIL);
+  logger.LogMostVisitedNavigation(2, TileTitleSource::MANIFEST,
+                                  TileSource::TOP_SITES,
+                                  TileVisualType::THUMBNAIL_FAILED);
   EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.MostVisited"),
               ElementsAre(Bucket(0, 1), Bucket(1, 1), Bucket(2, 1)));
   EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.MostVisited.server"),
@@ -255,25 +351,29 @@
               ElementsAre(Bucket(2, 1)));
   EXPECT_THAT(
       histogram_tester.GetAllSamples("NewTabPage.TileTypeClicked"),
-      ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL, 2),
-                  Bucket(ntp_tiles::TileVisualType::THUMBNAIL_FAILED, 1)));
+      ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL, 1),
+                  Bucket(ntp_tiles::TileVisualType::THUMBNAIL_FAILED, 2)));
   EXPECT_THAT(
       histogram_tester.GetAllSamples("NewTabPage.TileTypeClicked.server"),
       ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL, 1),
                   Bucket(ntp_tiles::TileVisualType::THUMBNAIL_FAILED, 1)));
   EXPECT_THAT(
       histogram_tester.GetAllSamples("NewTabPage.TileTypeClicked.client"),
-      ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL, 1)));
+      ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL_FAILED, 1)));
 
-  logger.LogMostVisitedNavigation(3, TileSource::TOP_SITES,
-                                  TileVisualType::THUMBNAIL_FAILED);
+  logger.LogMostVisitedNavigation(3, TileTitleSource::META_TAG,
+                                  TileSource::POPULAR,
+                                  TileVisualType::THUMBNAIL);
   EXPECT_THAT(
       histogram_tester.GetAllSamples("NewTabPage.MostVisited"),
       ElementsAre(Bucket(0, 1), Bucket(1, 1), Bucket(2, 1), Bucket(3, 1)));
   EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.MostVisited.server"),
               ElementsAre(Bucket(0, 1), Bucket(1, 1)));
   EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.MostVisited.client"),
-              ElementsAre(Bucket(2, 1), Bucket(3, 1)));
+              ElementsAre(Bucket(2, 1)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("NewTabPage.MostVisited.popular_fetched"),
+      ElementsAre(Bucket(3, 1)));
   EXPECT_THAT(
       histogram_tester.GetAllSamples("NewTabPage.TileTypeClicked"),
       ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL, 2),
@@ -284,17 +384,36 @@
                   Bucket(ntp_tiles::TileVisualType::THUMBNAIL_FAILED, 1)));
   EXPECT_THAT(
       histogram_tester.GetAllSamples("NewTabPage.TileTypeClicked.client"),
-      ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL, 1),
-                  Bucket(ntp_tiles::TileVisualType::THUMBNAIL_FAILED, 1)));
+      ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL_FAILED, 1)));
+  EXPECT_THAT(histogram_tester.GetAllSamples(
+                  "NewTabPage.TileTypeClicked.popular_fetched"),
+              ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL, 1)));
+  EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.TileTitleClicked"),
+              ElementsAre(Bucket(kUnknownTitleSource, 2),
+                          Bucket(kManifestTitleSource, 1),
+                          Bucket(kMetaTagTitleSource, 1)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("NewTabPage.TileTitleClicked.server"),
+      ElementsAre(Bucket(kUnknownTitleSource, 2)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("NewTabPage.TileTitleClicked.client"),
+      ElementsAre(Bucket(kManifestTitleSource, 1)));
+  EXPECT_THAT(histogram_tester.GetAllSamples(
+                  "NewTabPage.TileTitleClicked.popular_fetched"),
+              ElementsAre(Bucket(kMetaTagTitleSource, 1)));
 
   // Navigations always increase.
-  logger.LogMostVisitedNavigation(0, TileSource::SUGGESTIONS_SERVICE,
+  logger.LogMostVisitedNavigation(0, TileTitleSource::UNKNOWN,
+                                  TileSource::SUGGESTIONS_SERVICE,
                                   TileVisualType::THUMBNAIL);
-  logger.LogMostVisitedNavigation(1, TileSource::TOP_SITES,
+  logger.LogMostVisitedNavigation(1, TileTitleSource::TITLE_TAG,
+                                  TileSource::TOP_SITES,
                                   TileVisualType::THUMBNAIL);
-  logger.LogMostVisitedNavigation(2, TileSource::SUGGESTIONS_SERVICE,
+  logger.LogMostVisitedNavigation(2, TileTitleSource::UNKNOWN,
+                                  TileSource::SUGGESTIONS_SERVICE,
                                   TileVisualType::THUMBNAIL);
-  logger.LogMostVisitedNavigation(3, TileSource::TOP_SITES,
+  logger.LogMostVisitedNavigation(3, TileTitleSource::MANIFEST,
+                                  TileSource::POPULAR,
                                   TileVisualType::THUMBNAIL);
   EXPECT_THAT(
       histogram_tester.GetAllSamples("NewTabPage.MostVisited"),
@@ -302,7 +421,10 @@
   EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.MostVisited.server"),
               ElementsAre(Bucket(0, 2), Bucket(1, 1), Bucket(2, 1)));
   EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.MostVisited.client"),
-              ElementsAre(Bucket(1, 1), Bucket(2, 1), Bucket(3, 2)));
+              ElementsAre(Bucket(1, 1), Bucket(2, 1)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("NewTabPage.MostVisited.popular_fetched"),
+      ElementsAre(Bucket(3, 2)));
   EXPECT_THAT(
       histogram_tester.GetAllSamples("NewTabPage.TileTypeClicked"),
       ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL, 6),
@@ -313,8 +435,27 @@
                   Bucket(ntp_tiles::TileVisualType::THUMBNAIL_FAILED, 1)));
   EXPECT_THAT(
       histogram_tester.GetAllSamples("NewTabPage.TileTypeClicked.client"),
-      ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL, 3),
+      ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL, 1),
                   Bucket(ntp_tiles::TileVisualType::THUMBNAIL_FAILED, 1)));
+  EXPECT_THAT(histogram_tester.GetAllSamples(
+                  "NewTabPage.TileTypeClicked.popular_fetched"),
+              ElementsAre(Bucket(ntp_tiles::TileVisualType::THUMBNAIL, 2)));
+  EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.TileTitleClicked"),
+              ElementsAre(Bucket(kUnknownTitleSource, 4),
+                          Bucket(kManifestTitleSource, 2),
+                          Bucket(kMetaTagTitleSource, 1),
+                          Bucket(kTitleTagTitleSource, 1)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("NewTabPage.TileTitleClicked.server"),
+      ElementsAre(Bucket(kUnknownTitleSource, 4)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("NewTabPage.TileTitleClicked.client"),
+      ElementsAre(Bucket(kManifestTitleSource, 1),
+                  Bucket(kTitleTagTitleSource, 1)));
+  EXPECT_THAT(histogram_tester.GetAllSamples(
+                  "NewTabPage.TileTitleClicked.popular_fetched"),
+              ElementsAre(Bucket(kManifestTitleSource, 1),
+                          Bucket(kMetaTagTitleSource, 1)));
 }
 
 TEST(NTPUserDataLoggerTest, TestLoadTime) {
@@ -332,7 +473,8 @@
 
   // Log a TOP_SITES impression (for the .MostVisited vs .MostLikely split in
   // the time histograms).
-  logger.LogMostVisitedImpression(0, TileSource::TOP_SITES,
+  logger.LogMostVisitedImpression(0, TileTitleSource::UNKNOWN,
+                                  TileSource::TOP_SITES,
                                   TileVisualType::THUMBNAIL);
 
   // Send the ALL_TILES_LOADED event, this should trigger emitting histograms.
@@ -377,7 +519,8 @@
 
   // This time, log a SUGGESTIONS_SERVICE impression, so the times will end up
   // in .MostLikely.
-  logger.LogMostVisitedImpression(0, TileSource::SUGGESTIONS_SERVICE,
+  logger.LogMostVisitedImpression(0, TileTitleSource::UNKNOWN,
+                                  TileSource::SUGGESTIONS_SERVICE,
                                   TileVisualType::THUMBNAIL);
 
   base::TimeDelta delta_tiles_received2 = base::TimeDelta::FromMilliseconds(50);
diff --git a/chrome/browser/ui/search/search_ipc_router.cc b/chrome/browser/ui/search/search_ipc_router.cc
index a04ef36..2ab9bc9f 100644
--- a/chrome/browser/ui/search/search_ipc_router.cc
+++ b/chrome/browser/ui/search/search_ipc_router.cc
@@ -219,6 +219,7 @@
 void SearchIPCRouter::LogMostVisitedImpression(
     int page_seq_no,
     int position,
+    ntp_tiles::TileTitleSource tile_title_source,
     ntp_tiles::TileSource tile_source,
     ntp_tiles::TileVisualType tile_type) {
   if (page_seq_no != commit_counter_)
@@ -228,12 +229,14 @@
   if (!policy_->ShouldProcessLogEvent())
     return;
 
-  delegate_->OnLogMostVisitedImpression(position, tile_source, tile_type);
+  delegate_->OnLogMostVisitedImpression(position, tile_title_source,
+                                        tile_source, tile_type);
 }
 
 void SearchIPCRouter::LogMostVisitedNavigation(
     int page_seq_no,
     int position,
+    ntp_tiles::TileTitleSource tile_title_source,
     ntp_tiles::TileSource tile_source,
     ntp_tiles::TileVisualType tile_type) {
   if (page_seq_no != commit_counter_)
@@ -243,7 +246,8 @@
   if (!policy_->ShouldProcessLogEvent())
     return;
 
-  delegate_->OnLogMostVisitedNavigation(position, tile_source, tile_type);
+  delegate_->OnLogMostVisitedNavigation(position, tile_title_source,
+                                        tile_source, tile_type);
 }
 
 void SearchIPCRouter::PasteAndOpenDropdown(int page_seq_no,
diff --git a/chrome/browser/ui/search/search_ipc_router.h b/chrome/browser/ui/search/search_ipc_router.h
index 3aa74d2..a05ae98 100644
--- a/chrome/browser/ui/search/search_ipc_router.h
+++ b/chrome/browser/ui/search/search_ipc_router.h
@@ -15,6 +15,7 @@
 #include "chrome/common/search/instant_types.h"
 #include "chrome/common/search/ntp_logging_events.h"
 #include "components/ntp_tiles/tile_source.h"
+#include "components/ntp_tiles/tile_title_source.h"
 #include "components/ntp_tiles/tile_visual_type.h"
 #include "components/omnibox/common/omnibox_focus_state.h"
 #include "content/public/browser/web_contents_binding_set.h"
@@ -58,12 +59,14 @@
     // Called to log an impression from a given provider on the New Tab Page.
     virtual void OnLogMostVisitedImpression(
         int position,
+        ntp_tiles::TileTitleSource tile_title_source,
         ntp_tiles::TileSource tile_source,
         ntp_tiles::TileVisualType tile_type) = 0;
 
     // Called to log a navigation from a given provider on the New Tab Page.
     virtual void OnLogMostVisitedNavigation(
         int position,
+        ntp_tiles::TileTitleSource tile_title_source,
         ntp_tiles::TileSource tile_source,
         ntp_tiles::TileVisualType tile_type) = 0;
 
@@ -166,10 +169,12 @@
                 base::TimeDelta time) override;
   void LogMostVisitedImpression(int page_seq_no,
                                 int position,
+                                ntp_tiles::TileTitleSource tile_title_source,
                                 ntp_tiles::TileSource tile_source,
                                 ntp_tiles::TileVisualType tile_type) override;
   void LogMostVisitedNavigation(int page_seq_no,
                                 int position,
+                                ntp_tiles::TileTitleSource tile_title_source,
                                 ntp_tiles::TileSource tile_source,
                                 ntp_tiles::TileVisualType tile_type) override;
   void PasteAndOpenDropdown(int page_seq_no,
diff --git a/chrome/browser/ui/search/search_ipc_router_unittest.cc b/chrome/browser/ui/search/search_ipc_router_unittest.cc
index 7cf59a14..466d3358 100644
--- a/chrome/browser/ui/search/search_ipc_router_unittest.cc
+++ b/chrome/browser/ui/search/search_ipc_router_unittest.cc
@@ -58,12 +58,14 @@
   MOCK_METHOD0(OnUndoAllMostVisitedDeletions, void());
   MOCK_METHOD2(OnLogEvent, void(NTPLoggingEventType event,
                                 base::TimeDelta time));
-  MOCK_METHOD3(OnLogMostVisitedImpression,
+  MOCK_METHOD4(OnLogMostVisitedImpression,
                void(int position,
+                    ntp_tiles::TileTitleSource tile_title_source,
                     ntp_tiles::TileSource tile_source,
                     ntp_tiles::TileVisualType tile_type));
-  MOCK_METHOD3(OnLogMostVisitedNavigation,
+  MOCK_METHOD4(OnLogMostVisitedNavigation,
                void(int position,
+                    ntp_tiles::TileTitleSource tile_title_source,
                     ntp_tiles::TileSource tile_source,
                     ntp_tiles::TileVisualType tile_type));
   MOCK_METHOD1(PasteIntoOmnibox, void(const base::string16&));
@@ -274,15 +276,16 @@
   NavigateAndCommitActiveTab(GURL(chrome::kChromeSearchLocalNtpUrl));
   SetupMockDelegateAndPolicy();
   MockSearchIPCRouterPolicy* policy = GetSearchIPCRouterPolicy();
-  EXPECT_CALL(
-      *mock_delegate(),
-      OnLogMostVisitedImpression(3, ntp_tiles::TileSource::SUGGESTIONS_SERVICE,
-                                 ntp_tiles::TileVisualType::THUMBNAIL))
+  EXPECT_CALL(*mock_delegate(), OnLogMostVisitedImpression(
+                                    3, ntp_tiles::TileTitleSource::UNKNOWN,
+                                    ntp_tiles::TileSource::SUGGESTIONS_SERVICE,
+                                    ntp_tiles::TileVisualType::THUMBNAIL))
       .Times(1);
   EXPECT_CALL(*policy, ShouldProcessLogEvent()).Times(1).WillOnce(Return(true));
 
   GetSearchIPCRouter().LogMostVisitedImpression(
-      GetSearchIPCRouterSeqNo(), 3, ntp_tiles::TileSource::SUGGESTIONS_SERVICE,
+      GetSearchIPCRouterSeqNo(), 3, ntp_tiles::TileTitleSource::UNKNOWN,
+      ntp_tiles::TileSource::SUGGESTIONS_SERVICE,
       ntp_tiles::TileVisualType::THUMBNAIL);
 }
 
@@ -290,15 +293,16 @@
   NavigateAndCommitActiveTab(GURL(chrome::kChromeSearchLocalNtpUrl));
   SetupMockDelegateAndPolicy();
   MockSearchIPCRouterPolicy* policy = GetSearchIPCRouterPolicy();
-  EXPECT_CALL(
-      *mock_delegate(),
-      OnLogMostVisitedNavigation(3, ntp_tiles::TileSource::SUGGESTIONS_SERVICE,
-                                 ntp_tiles::TileVisualType::THUMBNAIL))
+  EXPECT_CALL(*mock_delegate(), OnLogMostVisitedNavigation(
+                                    3, ntp_tiles::TileTitleSource::UNKNOWN,
+                                    ntp_tiles::TileSource::SUGGESTIONS_SERVICE,
+                                    ntp_tiles::TileVisualType::THUMBNAIL))
       .Times(1);
   EXPECT_CALL(*policy, ShouldProcessLogEvent()).Times(1).WillOnce(Return(true));
 
   GetSearchIPCRouter().LogMostVisitedNavigation(
-      GetSearchIPCRouterSeqNo(), 3, ntp_tiles::TileSource::SUGGESTIONS_SERVICE,
+      GetSearchIPCRouterSeqNo(), 3, ntp_tiles::TileTitleSource::UNKNOWN,
+      ntp_tiles::TileSource::SUGGESTIONS_SERVICE,
       ntp_tiles::TileVisualType::THUMBNAIL);
 }
 
diff --git a/chrome/browser/ui/search/search_tab_helper.cc b/chrome/browser/ui/search/search_tab_helper.cc
index 1915eee8..8300afc7 100644
--- a/chrome/browser/ui/search/search_tab_helper.cc
+++ b/chrome/browser/ui/search/search_tab_helper.cc
@@ -352,23 +352,27 @@
 
 void SearchTabHelper::OnLogMostVisitedImpression(
     int position,
+    ntp_tiles::TileTitleSource tile_title_source,
     ntp_tiles::TileSource tile_source,
     ntp_tiles::TileVisualType tile_type) {
 // TODO(kmadhusu): Move platform specific code from here and get rid of #ifdef.
 #if !defined(OS_ANDROID)
   NTPUserDataLogger::GetOrCreateFromWebContents(web_contents())
-      ->LogMostVisitedImpression(position, tile_source, tile_type);
+      ->LogMostVisitedImpression(position, tile_title_source, tile_source,
+                                 tile_type);
 #endif
 }
 
 void SearchTabHelper::OnLogMostVisitedNavigation(
     int position,
+    ntp_tiles::TileTitleSource tile_title_source,
     ntp_tiles::TileSource tile_source,
     ntp_tiles::TileVisualType tile_type) {
 // TODO(kmadhusu): Move platform specific code from here and get rid of #ifdef.
 #if !defined(OS_ANDROID)
   NTPUserDataLogger::GetOrCreateFromWebContents(web_contents())
-      ->LogMostVisitedNavigation(position, tile_source, tile_type);
+      ->LogMostVisitedNavigation(position, tile_title_source, tile_source,
+                                 tile_type);
 #endif
 }
 
diff --git a/chrome/browser/ui/search/search_tab_helper.h b/chrome/browser/ui/search/search_tab_helper.h
index 01bee276..67153715 100644
--- a/chrome/browser/ui/search/search_tab_helper.h
+++ b/chrome/browser/ui/search/search_tab_helper.h
@@ -16,6 +16,7 @@
 #include "chrome/common/search/instant_types.h"
 #include "chrome/common/search/ntp_logging_events.h"
 #include "components/ntp_tiles/tile_source.h"
+#include "components/ntp_tiles/tile_title_source.h"
 #include "components/ntp_tiles/tile_visual_type.h"
 #include "components/omnibox/common/omnibox_focus_state.h"
 #include "content/public/browser/reload_type.h"
@@ -104,9 +105,11 @@
   void OnUndoAllMostVisitedDeletions() override;
   void OnLogEvent(NTPLoggingEventType event, base::TimeDelta time) override;
   void OnLogMostVisitedImpression(int position,
+                                  ntp_tiles::TileTitleSource tile_title_source,
                                   ntp_tiles::TileSource tile_source,
                                   ntp_tiles::TileVisualType tile_type) override;
   void OnLogMostVisitedNavigation(int position,
+                                  ntp_tiles::TileTitleSource tile_title_source,
                                   ntp_tiles::TileSource tile_source,
                                   ntp_tiles::TileVisualType tile_type) override;
   void PasteIntoOmnibox(const base::string16& text) override;
diff --git a/chrome/browser/ui/search/search_tab_helper_unittest.cc b/chrome/browser/ui/search/search_tab_helper_unittest.cc
index caa9f80..4efe4039 100644
--- a/chrome/browser/ui/search/search_tab_helper_unittest.cc
+++ b/chrome/browser/ui/search/search_tab_helper_unittest.cc
@@ -58,12 +58,14 @@
   MOCK_METHOD0(OnUndoAllMostVisitedDeletions, void());
   MOCK_METHOD2(OnLogEvent, void(NTPLoggingEventType event,
                                 base::TimeDelta time));
-  MOCK_METHOD3(OnLogMostVisitedImpression,
+  MOCK_METHOD4(OnLogMostVisitedImpression,
                void(int position,
+                    ntp_tiles::TileTitleSource tile_title_source,
                     ntp_tiles::TileSource tile_source,
                     ntp_tiles::TileVisualType tile_type));
-  MOCK_METHOD3(OnLogMostVisitedNavigation,
+  MOCK_METHOD4(OnLogMostVisitedNavigation,
                void(int position,
+                    ntp_tiles::TileTitleSource tile_title_source,
                     ntp_tiles::TileSource tile_source,
                     ntp_tiles::TileVisualType tile_type));
   MOCK_METHOD1(PasteIntoOmnibox, void(const base::string16&));
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc
index 3473261..8862675 100644
--- a/chrome/browser/ui/tab_helpers.cc
+++ b/chrome/browser/ui/tab_helpers.cc
@@ -54,6 +54,7 @@
 #include "chrome/browser/translate/chrome_translate_client.h"
 #include "chrome/browser/ui/autofill/chrome_autofill_client.h"
 #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
+#include "chrome/browser/ui/blocked_content/popup_opener_tab_helper.h"
 #include "chrome/browser/ui/find_bar/find_tab_helper.h"
 #include "chrome/browser/ui/navigation_correction_tab_observer.h"
 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h"
@@ -222,6 +223,7 @@
   PDFPluginPlaceholderObserver::CreateForWebContents(web_contents);
   PermissionRequestManager::CreateForWebContents(web_contents);
   PopupBlockerTabHelper::CreateForWebContents(web_contents);
+  PopupOpenerTabHelper::CreateForWebContents(web_contents);
   PrefsTabHelper::CreateForWebContents(web_contents);
   prerender::PrerenderTabHelper::CreateForWebContents(web_contents);
   PreviewsInfoBarTabHelper::CreateForWebContents(web_contents);
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc
index b473e4e..f478509 100644
--- a/chrome/browser/ui/tabs/tab_strip_model.cc
+++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -8,6 +8,7 @@
 #include <map>
 #include <set>
 #include <string>
+#include <utility>
 
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
@@ -27,6 +28,7 @@
 #include "chrome/common/url_constants.h"
 #include "components/feature_engagement/features.h"
 #include "components/web_modal/web_contents_modal_dialog_manager.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -1210,7 +1212,7 @@
       if (delegate_->ShouldRunUnloadListenerBeforeClosing(closing_contents))
         continue;
       content::RenderProcessHost* process =
-          closing_contents->GetRenderProcessHost();
+          closing_contents->GetMainFrame()->GetProcess();
       ++processes[process];
     }
 
diff --git a/chrome/browser/ui/tabs/tab_strip_model_unittest.cc b/chrome/browser/ui/tabs/tab_strip_model_unittest.cc
index 84ddee06..cc06830 100644
--- a/chrome/browser/ui/tabs/tab_strip_model_unittest.cc
+++ b/chrome/browser/ui/tabs/tab_strip_model_unittest.cc
@@ -34,6 +34,7 @@
 #include "components/web_modal/web_contents_modal_dialog_manager.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -185,8 +186,8 @@
     WebContents::CreateParams create_params(
         profile(), web_contents->GetRenderViewHost()->GetSiteInstance());
     WebContents* retval = WebContents::Create(create_params);
-    EXPECT_EQ(retval->GetRenderProcessHost(),
-              web_contents->GetRenderProcessHost());
+    EXPECT_EQ(retval->GetMainFrame()->GetProcess(),
+              web_contents->GetMainFrame()->GetProcess());
     return retval;
   }
 
@@ -1885,7 +1886,7 @@
     tabstrip.CloseAllTabs();
     // On a mock RPH this checks whether we *attempted* fast shutdown.
     // A real RPH would reject our attempt since there is an unload handler.
-    EXPECT_TRUE(contents1->GetRenderProcessHost()->FastShutdownStarted());
+    EXPECT_TRUE(contents1->GetMainFrame()->GetProcess()->FastShutdownStarted());
     EXPECT_EQ(2, tabstrip.count());
 
     delegate.set_run_unload_listener(false);
@@ -1906,7 +1907,8 @@
     tabstrip.AppendWebContents(contents2, true);
 
     tabstrip.CloseWebContentsAt(1, TabStripModel::CLOSE_NONE);
-    EXPECT_FALSE(contents1->GetRenderProcessHost()->FastShutdownStarted());
+    EXPECT_FALSE(
+        contents1->GetMainFrame()->GetProcess()->FastShutdownStarted());
     EXPECT_EQ(1, tabstrip.count());
 
     tabstrip.CloseAllTabs();
diff --git a/chrome/browser/ui/views/DEPS b/chrome/browser/ui/views/DEPS
index d9217c2..49aaac4 100644
--- a/chrome/browser/ui/views/DEPS
+++ b/chrome/browser/ui/views/DEPS
@@ -3,6 +3,8 @@
  "+ash",
  "+chrome/browser/ui/views",
  "+components/constrained_window",
+ "+mash/common",
+ "+mash/quick_launch/public",
  "+services/ui/public/cpp",
  "+components/user_manager",
  "+third_party/libaddressinput",
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc
index 3fe42b0..5d708df 100644
--- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc
+++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc
@@ -397,7 +397,8 @@
       if (profiles::IsPublicSession()) {
         UpdateExclusiveAccessExitBubbleContent(
             GURL(),
-            fullscreen_types & AppWindow::FULLSCREEN_TYPE_HTML_API
+            fullscreen_types & (AppWindow::FULLSCREEN_TYPE_HTML_API |
+                                AppWindow::FULLSCREEN_TYPE_WINDOW_API)
                 ? EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_EXIT_INSTRUCTION
                 : EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE,
             ExclusiveAccessBubbleHideCallback());
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.h b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.h
index f3f93b10..ae546ea 100644
--- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.h
+++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.h
@@ -125,7 +125,7 @@
   FRIEND_TEST_ALL_PREFIXES(ChromeNativeAppWindowViewsAuraAshInteractiveTest,
                            NoImmersiveOrBubbleOutsidePublicSessionDom);
   FRIEND_TEST_ALL_PREFIXES(ChromeNativeAppWindowViewsAuraAshInteractiveTest,
-                           ImmersiveNoBubbleInsidePublicSessionWindow);
+                           ImmersiveAndBubbleInsidePublicSessionWindow);
   FRIEND_TEST_ALL_PREFIXES(ChromeNativeAppWindowViewsAuraAshInteractiveTest,
                            ImmersiveAndBubbleInsidePublicSessionDom);
   FRIEND_TEST_ALL_PREFIXES(ShapedAppWindowTargeterTest,
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash_interactive_uitest.cc b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash_interactive_uitest.cc
index 9dc78ff..a650068 100644
--- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash_interactive_uitest.cc
+++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash_interactive_uitest.cc
@@ -83,7 +83,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(ChromeNativeAppWindowViewsAuraAshInteractiveTest,
-                       ImmersiveNoBubbleInsidePublicSessionWindow) {
+                       ImmersiveAndBubbleInsidePublicSessionWindow) {
   chromeos::ScopedTestPublicSessionLoginState state;
   ExtensionTestMessageListener launched_listener("Launched", true);
   LoadAndLaunchPlatformApp("leave_fullscreen", &launched_listener);
@@ -105,7 +105,7 @@
   }
 
   EXPECT_TRUE(GetWindowAsh()->IsImmersiveModeEnabled());
-  EXPECT_FALSE(GetWindowAsh()->exclusive_access_bubble_);
+  EXPECT_TRUE(GetWindowAsh()->exclusive_access_bubble_);
 }
 
 IN_PROC_BROWSER_TEST_F(ChromeNativeAppWindowViewsAuraAshInteractiveTest,
diff --git a/chrome/browser/ui/views/autofill/password_generation_popup_view_views.cc b/chrome/browser/ui/views/autofill/password_generation_popup_view_views.cc
index 901ccb2..d8806ab 100644
--- a/chrome/browser/ui/views/autofill/password_generation_popup_view_views.cc
+++ b/chrome/browser/ui/views/autofill/password_generation_popup_view_views.cc
@@ -9,7 +9,9 @@
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/ui/autofill/password_generation_popup_controller.h"
 #include "chrome/browser/ui/autofill/popup_constants.h"
+#include "chrome/browser/ui/views/harmony/chrome_typography.h"
 #include "ui/accessibility/ax_node_data.h"
+#include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/color_palette.h"
@@ -40,11 +42,9 @@
   ~PasswordTextBox() override {}
 
   // |suggestion_text| prompts the user to select the password,
-  // |generated_password| is the generated password, and |font_list| is the font
-  // used for all text in this class.
+  // |generated_password| is the generated password.
   void Init(const base::string16& suggestion_text,
-            const base::string16& generated_password,
-            const gfx::FontList& font_list) {
+            const base::string16& generated_password) {
     views::BoxLayout* box_layout = new views::BoxLayout(
         views::BoxLayout::kVertical, gfx::Insets(12, 0), 5);
     box_layout->set_main_axis_alignment(
@@ -52,15 +52,14 @@
     SetLayoutManager(box_layout);
 
     views::Label* suggestion_label = new views::Label(
-        suggestion_text, views::Label::CustomFont{font_list.DeriveWithWeight(
-                             gfx::Font::Weight::BOLD)});
+        suggestion_text, CONTEXT_DEPRECATED_SMALL, STYLE_EMPHASIZED);
     suggestion_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
     suggestion_label->SetEnabledColor(
         PasswordGenerationPopupView::kPasswordTextColor);
     AddChildView(suggestion_label);
 
     views::Label* password_label =
-        new views::Label(generated_password, {font_list});
+        new views::Label(generated_password, CONTEXT_DEPRECATED_SMALL);
     password_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
     password_label->SetEnabledColor(
         PasswordGenerationPopupView::kPasswordTextColor);
@@ -87,11 +86,8 @@
   ~PasswordBox() override {}
 
   // |password| is the generated password, |suggestion| is the text prompting
-  // the user to select the password, and |font_list| is the font used for all
-  // the text.
-  void Init(const base::string16& password,
-            const base::string16& suggestion,
-            const gfx::FontList& font_list) {
+  // the user to select the password.
+  void Init(const base::string16& password, const base::string16& suggestion) {
     views::BoxLayout* box_layout = new views::BoxLayout(
         views::BoxLayout::kHorizontal,
         gfx::Insets(0, PasswordGenerationPopupController::kHorizontalPadding),
@@ -106,7 +102,7 @@
     AddChildView(key_image);
 
     PasswordTextBox* password_text_box = new PasswordTextBox();
-    password_text_box->Init(suggestion, password, font_list);
+    password_text_box->Init(suggestion, password);
     AddChildView(password_text_box);
   }
 
@@ -126,18 +122,19 @@
     views::Widget* parent_widget)
     : AutofillPopupBaseView(controller, parent_widget),
       password_view_(NULL),
-      font_list_(ResourceBundle::GetSharedInstance().GetFontList(
-          ResourceBundle::SmallFont)),
       controller_(controller) {
   if (controller_->display_password())
     CreatePasswordView();
 
   help_label_ = new views::StyledLabel(controller_->HelpText(), this);
-  help_label_->SetBaseFontList(font_list_);
-  help_label_->SetLineHeight(20);
-  views::StyledLabel::RangeStyleInfo default_style;
-  default_style.color = kExplanatoryTextColor;
-  help_label_->SetDefaultStyle(default_style);
+
+  // With MD, the line spacing comes from the TextContext instead and this is
+  // unnecessary.
+  if (!ui::MaterialDesignController::IsSecondaryUiMaterial())
+    help_label_->SetLineHeight(20);
+
+  help_label_->SetTextContext(CONTEXT_DEPRECATED_SMALL);
+  help_label_->SetDefaultTextStyle(STYLE_HINT);
 
   views::StyledLabel::RangeStyleInfo link_style =
       views::StyledLabel::RangeStyleInfo::CreateForLink();
@@ -166,9 +163,7 @@
     return;
 
   password_view_ = new PasswordBox();
-  password_view_->Init(controller_->password(),
-                       controller_->SuggestedText(),
-                       font_list_);
+  password_view_->Init(controller_->password(), controller_->SuggestedText());
   password_view_->SetPosition(gfx::Point());
   password_view_->SizeToPreferredSize();
   AddChildView(password_view_);
diff --git a/chrome/browser/ui/views/autofill/password_generation_popup_view_views.h b/chrome/browser/ui/views/autofill/password_generation_popup_view_views.h
index 7ff7238..0324949a 100644
--- a/chrome/browser/ui/views/autofill/password_generation_popup_view_views.h
+++ b/chrome/browser/ui/views/autofill/password_generation_popup_view_views.h
@@ -8,7 +8,6 @@
 #include "base/macros.h"
 #include "chrome/browser/ui/autofill/password_generation_popup_view.h"
 #include "chrome/browser/ui/views/autofill/autofill_popup_base_view.h"
-#include "ui/gfx/font_list.h"
 #include "ui/views/controls/styled_label_listener.h"
 
 namespace views {
@@ -58,9 +57,6 @@
   PasswordBox* password_view_;
   views::StyledLabel* help_label_;
 
-  // Fonts to use.
-  gfx::FontList font_list_;
-
   // Size of the divider between the password and the help text.
   gfx::Rect divider_bounds_;
 
diff --git a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc
index 88ea614d..f8c6d41 100644
--- a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc
+++ b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc
@@ -49,6 +49,8 @@
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/ash_config.h"
+#include "mash/common/config.h"                                   // nogncheck
+#include "mash/quick_launch/public/interfaces/constants.mojom.h"  // nogncheck
 #endif
 
 namespace {
@@ -167,6 +169,17 @@
   if (aura::Env::GetInstance()->mode() == aura::Env::Mode::LOCAL)
     return;
 
+#if defined(OS_CHROMEOS)
+  if (chromeos::GetAshConfig() == ash::Config::MASH) {
+    connection->GetConnector()->StartService(
+        service_manager::Identity(ui::mojom::kServiceName));
+    connection->GetConnector()->StartService(
+        service_manager::Identity(mash::common::GetWindowManagerServiceName()));
+    connection->GetConnector()->StartService(
+        service_manager::Identity(mash::quick_launch::mojom::kServiceName));
+  }
+#endif
+
   input_device_client_ = base::MakeUnique<ui::InputDeviceClient>();
   ui::mojom::InputDeviceServerPtr server;
   connection->GetConnector()->BindInterface(ui::mojom::kServiceName, &server);
diff --git a/chrome/browser/ui/views/content_setting_bubble_contents.cc b/chrome/browser/ui/views/content_setting_bubble_contents.cc
index 83ef7d66..a4019d8 100644
--- a/chrome/browser/ui/views/content_setting_bubble_contents.cc
+++ b/chrome/browser/ui/views/content_setting_bubble_contents.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/plugins/plugin_metadata.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/layout_constants.h"
+#include "chrome/browser/ui/views/content_setting_domain_list_view.h"
 #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/harmony/chrome_typography.h"
 #include "chrome/grit/generated_resources.h"
@@ -506,18 +507,10 @@
   for (std::vector<ContentSettingBubbleModel::DomainList>::const_iterator i(
            bubble_content.domain_lists.begin());
        i != bubble_content.domain_lists.end(); ++i) {
+    auto list_view =
+        base::MakeUnique<ContentSettingDomainListView>(i->title, i->hosts);
     layout->StartRow(0, kSingleColumnSetId);
-    views::Label* section_title = new views::Label(i->title);
-    section_title->SetMultiLine(true);
-    section_title->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    layout->AddView(section_title, 1, 1, GridLayout::FILL, GridLayout::LEADING);
-    for (std::set<std::string>::const_iterator j = i->hosts.begin();
-         j != i->hosts.end(); ++j) {
-      layout->StartRow(0, kIndentedSingleColumnSetId);
-      // TODO(tapted): Verify this when we have a mock. http://crbug.com/700196.
-      layout->AddView(new views::Label(
-          base::UTF8ToUTF16(*j), CONTEXT_BODY_TEXT_LARGE, STYLE_EMPHASIZED));
-    }
+    layout->AddView(list_view.release());
     bubble_content_empty = false;
   }
 
diff --git a/chrome/browser/ui/views/content_setting_domain_list_view.cc b/chrome/browser/ui/views/content_setting_domain_list_view.cc
new file mode 100644
index 0000000..43e8ea0
--- /dev/null
+++ b/chrome/browser/ui/views/content_setting_domain_list_view.cc
@@ -0,0 +1,29 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/content_setting_domain_list_view.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ui/views/harmony/bulleted_label_list_view.h"
+#include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
+#include "ui/gfx/canvas.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/layout/box_layout.h"
+
+ContentSettingDomainListView::ContentSettingDomainListView(
+    const base::string16& title,
+    const std::set<std::string>& domains) {
+  auto layout = std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical);
+  SetLayoutManager(layout.release());
+
+  auto title_label = std::make_unique<views::Label>(title);
+  title_label->SetMultiLine(true);
+  title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  AddChildView(title_label.release());
+
+  auto list_view = std::make_unique<BulletedLabelListView>();
+  for (const auto& domain : domains)
+    list_view->AddLabel(base::UTF8ToUTF16(domain));
+  AddChildView(list_view.release());
+}
diff --git a/chrome/browser/ui/views/content_setting_domain_list_view.h b/chrome/browser/ui/views/content_setting_domain_list_view.h
new file mode 100644
index 0000000..0c63dcc1
--- /dev/null
+++ b/chrome/browser/ui/views/content_setting_domain_list_view.h
@@ -0,0 +1,20 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_CONTENT_SETTING_DOMAIN_LIST_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_CONTENT_SETTING_DOMAIN_LIST_VIEW_H_
+
+#include "base/macros.h"
+#include "ui/views/view.h"
+
+class ContentSettingDomainListView : public views::View {
+ public:
+  ContentSettingDomainListView(const base::string16& title,
+                               const std::set<std::string>& domains);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ContentSettingDomainListView);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_CONTENT_SETTING_DOMAIN_LIST_VIEW_H_
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_list_view.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_list_view.cc
index d850b126..123d1a1 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_list_view.cc
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_list_view.cc
@@ -173,7 +173,7 @@
 
   source_view->SetName(source.name);
   source_view->SetGroup(kDesktopMediaSourceViewGroupId);
-  if (source.id.source_type == DesktopMediaID::SOURCE_WINDOW) {
+  if (source.id.type == DesktopMediaID::TYPE_WINDOW) {
     gfx::ImageSkia icon_image = GetWindowIcon(source.id);
 #if defined(USE_ASH)
     // Empty icons are used to represent default icon for aura windows. By
@@ -192,7 +192,7 @@
     parent_->OnMediaListRowsChanged();
 
   // Auto select the first screen.
-  if (index == 0 && source.id.source_type == DesktopMediaID::SOURCE_SCREEN)
+  if (index == 0 && source.id.type == DesktopMediaID::TYPE_SCREEN)
     source_view->RequestFocus();
 
   PreferredSizeChanged();
@@ -203,7 +203,7 @@
   if (!autoselect_source.empty() &&
       base::ASCIIToUTF16(autoselect_source) == source.name) {
     // Select, then accept and close the dialog when we're done adding sources.
-    parent_->SelectTab(source.id.source_type);
+    parent_->SelectTab(source.id.type);
     source_view->OnFocus();
     content::BrowserThread::PostTask(
         content::BrowserThread::UI, FROM_HERE,
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
index 8852530..9a29360 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
@@ -75,12 +75,12 @@
 
   for (auto& source_list : source_lists) {
     switch (source_list->GetMediaListType()) {
-      case DesktopMediaID::SOURCE_NONE: {
+      case DesktopMediaID::TYPE_NONE: {
         NOTREACHED();
         break;
       }
-      case DesktopMediaID::SOURCE_SCREEN: {
-        source_types_.push_back(DesktopMediaID::SOURCE_SCREEN);
+      case DesktopMediaID::TYPE_SCREEN: {
+        source_types_.push_back(DesktopMediaID::TYPE_SCREEN);
 
         const DesktopMediaSourceViewStyle kSingleScreenStyle(
             1,                                       // columns
@@ -120,8 +120,8 @@
         pane_->set_listener(this);
         break;
       }
-      case DesktopMediaID::SOURCE_WINDOW: {
-        source_types_.push_back(DesktopMediaID::SOURCE_WINDOW);
+      case DesktopMediaID::TYPE_WINDOW: {
+        source_types_.push_back(DesktopMediaID::TYPE_WINDOW);
 
         const DesktopMediaSourceViewStyle kWindowStyle(
             3,                                     // columns
@@ -149,8 +149,8 @@
         pane_->set_listener(this);
         break;
       }
-      case DesktopMediaID::SOURCE_WEB_CONTENTS: {
-        source_types_.push_back(DesktopMediaID::SOURCE_WEB_CONTENTS);
+      case DesktopMediaID::TYPE_WEB_CONTENTS: {
+        source_types_.push_back(DesktopMediaID::TYPE_WEB_CONTENTS);
 
         const DesktopMediaSourceViewStyle kTabStyle(
             1,                                     // columns
@@ -226,7 +226,7 @@
   DesktopMediaID dialog_window_id;
   if (!modal_dialog) {
     dialog_window_id = DesktopMediaID::RegisterAuraWindow(
-        DesktopMediaID::SOURCE_WINDOW, widget->GetNativeWindow());
+        DesktopMediaID::TYPE_WINDOW, widget->GetNativeWindow());
 
     // Set native window ID if the windows is outside Ash.
 #if !defined(USE_ASH)
@@ -251,20 +251,20 @@
   // Set whether the checkbox is visible based on the source type.
   if (audio_share_checkbox_) {
     switch (source_types_[index]) {
-      case DesktopMediaID::SOURCE_SCREEN:
+      case DesktopMediaID::TYPE_SCREEN:
 #if defined(USE_CRAS) || defined(OS_WIN)
         audio_share_checkbox_->SetVisible(true);
 #else
         audio_share_checkbox_->SetVisible(false);
 #endif
         break;
-      case DesktopMediaID::SOURCE_WINDOW:
+      case DesktopMediaID::TYPE_WINDOW:
         audio_share_checkbox_->SetVisible(false);
         break;
-      case DesktopMediaID::SOURCE_WEB_CONTENTS:
+      case DesktopMediaID::TYPE_WEB_CONTENTS:
         audio_share_checkbox_->SetVisible(true);
         break;
-      case DesktopMediaID::SOURCE_NONE:
+      case DesktopMediaID::TYPE_NONE:
         NOTREACHED();
         break;
     }
@@ -317,11 +317,11 @@
   // Ok button should only be enabled when a source is selected.
   DCHECK(selection);
   DesktopMediaID source = selection->source_id();
-  source.set_audio_capture(audio_share_checkbox_ &&
-                           audio_share_checkbox_->visible() &&
-                           audio_share_checkbox_->checked());
+  source.audio_share = audio_share_checkbox_ &&
+                       audio_share_checkbox_->visible() &&
+                       audio_share_checkbox_->checked();
 
-  if (source.source_type == DesktopMediaID::SOURCE_WEB_CONTENTS) {
+  if (source.type == DesktopMediaID::TYPE_WEB_CONTENTS) {
     // Activate the selected tab and bring the browser window for the selected
     // tab to the front.
     content::WebContents* tab = content::WebContents::FromRenderFrameHost(
@@ -334,7 +334,7 @@
       if (browser && browser->window())
         browser->window()->Activate();
     }
-  } else if (source.source_type == DesktopMediaID::SOURCE_WINDOW) {
+  } else if (source.type == DesktopMediaID::TYPE_WINDOW) {
 #if defined(USE_AURA)
     aura::Window* window = DesktopMediaID::GetAuraWindowById(source);
     Browser* browser = chrome::FindBrowserWithWindow(window);
@@ -367,7 +367,7 @@
 }
 
 void DesktopMediaPickerDialogView::SelectTab(
-    content::DesktopMediaID::Source source_type) {
+    content::DesktopMediaID::Type source_type) {
   for (size_t i = 0; i < source_types_.size(); i++) {
     if (source_types_[i] == source_type) {
       pane_->SelectTabAt(i);
@@ -404,7 +404,7 @@
 }
 
 int DesktopMediaPickerDialogView::GetIndexOfSourceTypeForTesting(
-    DesktopMediaID::Source source_type) const {
+    DesktopMediaID::Type source_type) const {
   for (size_t i = 0; i < source_types_.size(); i++) {
     if (source_types_[i] == source_type)
       return i;
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h
index ed0196ac..6e82b45 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h
@@ -40,7 +40,7 @@
   // Called by DesktopMediaListView.
   void OnSelectionChanged();
   void OnDoubleClick();
-  void SelectTab(content::DesktopMediaID::Source source_type);
+  void SelectTab(content::DesktopMediaID::Type source_type);
 
   // views::TabbedPaneListener overrides.
   void TabSelectedAt(int index) override;
@@ -64,7 +64,7 @@
   DesktopMediaSourceView* GetMediaSourceViewForTesting(int index) const;
   views::Checkbox* GetCheckboxForTesting() const;
   int GetIndexOfSourceTypeForTesting(
-      content::DesktopMediaID::Source source_type) const;
+      content::DesktopMediaID::Type source_type) const;
   views::TabbedPane* GetPaneForTesting() const;
 
  private:
@@ -78,7 +78,7 @@
 
   views::TabbedPane* pane_;
   std::vector<DesktopMediaListView*> list_views_;
-  std::vector<content::DesktopMediaID::Source> source_types_;
+  std::vector<content::DesktopMediaID::Type> source_types_;
 
   DISALLOW_COPY_AND_ASSIGN(DesktopMediaPickerDialogView);
 };
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_browsertest.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_browsertest.cc
index 02aada2..d07f5aff5 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_browsertest.cc
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_browsertest.cc
@@ -26,9 +26,9 @@
     gfx::NativeWindow native_window = browser()->window()->GetNativeWindow();
 
     std::vector<std::unique_ptr<DesktopMediaList>> source_lists;
-    for (auto type : {content::DesktopMediaID::SOURCE_SCREEN,
-                      content::DesktopMediaID::SOURCE_WINDOW,
-                      content::DesktopMediaID::SOURCE_WEB_CONTENTS}) {
+    for (auto type : {content::DesktopMediaID::TYPE_SCREEN,
+                      content::DesktopMediaID::TYPE_WINDOW,
+                      content::DesktopMediaID::TYPE_WEB_CONTENTS}) {
       source_lists.push_back(base::MakeUnique<FakeDesktopMediaList>(type));
     }
 
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc
index 00918a7..a152700 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc
@@ -32,9 +32,9 @@
 
 namespace views {
 
-const std::vector<DesktopMediaID::Source> kSourceTypes = {
-    DesktopMediaID::SOURCE_SCREEN, DesktopMediaID::SOURCE_WINDOW,
-    DesktopMediaID::SOURCE_WEB_CONTENTS};
+const std::vector<DesktopMediaID::Type> kSourceTypes = {
+    DesktopMediaID::TYPE_SCREEN, DesktopMediaID::TYPE_WINDOW,
+    DesktopMediaID::TYPE_WEB_CONTENTS};
 
 class DesktopMediaPickerViewsTest : public testing::Test {
  public:
@@ -72,7 +72,7 @@
     return picker_views_->GetDialogViewForTesting();
   }
 
-  bool ClickSourceTypeButton(DesktopMediaID::Source source_type) {
+  bool ClickSourceTypeButton(DesktopMediaID::Type source_type) {
     int index =
         GetPickerDialogView()->GetIndexOfSourceTypeForTesting(source_type);
 
@@ -88,7 +88,7 @@
  protected:
   content::TestBrowserThreadBundle thread_bundle_;
   views::ScopedViewsTestHelper test_helper_;
-  std::map<DesktopMediaID::Source, FakeDesktopMediaList*> media_lists_;
+  std::map<DesktopMediaID::Type, FakeDesktopMediaList*> media_lists_;
   std::unique_ptr<DesktopMediaPickerViews> picker_views_;
 };
 
@@ -107,16 +107,16 @@
 #endif
 
 TEST_F(DesktopMediaPickerViewsTest, MAYBE_DoneCallbackCalledOnOkButtonPressed) {
-  const DesktopMediaID kFakeId(DesktopMediaID::SOURCE_WINDOW, 222);
+  const DesktopMediaID kFakeId(DesktopMediaID::TYPE_WINDOW, 222);
   EXPECT_CALL(*this, OnPickerDone(kFakeId));
 
-  media_lists_[DesktopMediaID::SOURCE_WINDOW]->AddSourceByFullMediaID(kFakeId);
+  media_lists_[DesktopMediaID::TYPE_WINDOW]->AddSourceByFullMediaID(kFakeId);
   GetPickerDialogView()->GetCheckboxForTesting()->SetChecked(true);
 
   EXPECT_FALSE(
       GetPickerDialogView()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK));
 
-  EXPECT_TRUE(ClickSourceTypeButton(DesktopMediaID::SOURCE_WINDOW));
+  EXPECT_TRUE(ClickSourceTypeButton(DesktopMediaID::TYPE_WINDOW));
 
   GetPickerDialogView()->GetMediaSourceViewForTesting(0)->OnFocus();
 
@@ -145,7 +145,7 @@
 
     // By default, the first screen is selected, but not for other sharing
     // types.
-    EXPECT_EQ(source_type == DesktopMediaID::SOURCE_SCREEN,
+    EXPECT_EQ(source_type == DesktopMediaID::TYPE_SCREEN,
               source_view_0->is_selected());
     EXPECT_FALSE(source_view_1->is_selected());
 
@@ -170,12 +170,12 @@
 }
 
 TEST_F(DesktopMediaPickerViewsTest, DoneCallbackCalledOnDoubleClick) {
-  const DesktopMediaID kFakeId(DesktopMediaID::SOURCE_WEB_CONTENTS, 222);
+  const DesktopMediaID kFakeId(DesktopMediaID::TYPE_WEB_CONTENTS, 222);
   EXPECT_CALL(*this, OnPickerDone(kFakeId));
 
-  media_lists_[DesktopMediaID::SOURCE_WEB_CONTENTS]->AddSourceByFullMediaID(
+  media_lists_[DesktopMediaID::TYPE_WEB_CONTENTS]->AddSourceByFullMediaID(
       kFakeId);
-  EXPECT_TRUE(ClickSourceTypeButton(DesktopMediaID::SOURCE_WEB_CONTENTS));
+  EXPECT_TRUE(ClickSourceTypeButton(DesktopMediaID::TYPE_WEB_CONTENTS));
   GetPickerDialogView()->GetCheckboxForTesting()->SetChecked(false);
 
   ui::MouseEvent double_click(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
@@ -189,13 +189,13 @@
 }
 
 TEST_F(DesktopMediaPickerViewsTest, DoneCallbackCalledOnDoubleTap) {
-  const DesktopMediaID kFakeId(DesktopMediaID::SOURCE_SCREEN, 222);
+  const DesktopMediaID kFakeId(DesktopMediaID::TYPE_SCREEN, 222);
   EXPECT_CALL(*this, OnPickerDone(kFakeId));
 
-  EXPECT_TRUE(ClickSourceTypeButton(DesktopMediaID::SOURCE_SCREEN));
+  EXPECT_TRUE(ClickSourceTypeButton(DesktopMediaID::TYPE_SCREEN));
   GetPickerDialogView()->GetCheckboxForTesting()->SetChecked(false);
 
-  media_lists_[DesktopMediaID::SOURCE_SCREEN]->AddSourceByFullMediaID(kFakeId);
+  media_lists_[DesktopMediaID::TYPE_SCREEN]->AddSourceByFullMediaID(kFakeId);
   ui::GestureEventDetails details(ui::ET_GESTURE_TAP);
   details.set_tap_count(2);
   ui::GestureEvent double_tap(10, 10, 0, base::TimeTicks(), details);
@@ -284,35 +284,35 @@
 // Verifies the visible status of audio checkbox.
 TEST_F(DesktopMediaPickerViewsTest, AudioCheckboxState) {
   bool expect_value = false;
-  EXPECT_TRUE(ClickSourceTypeButton(DesktopMediaID::SOURCE_SCREEN));
+  EXPECT_TRUE(ClickSourceTypeButton(DesktopMediaID::TYPE_SCREEN));
 #if defined(OS_WIN) || defined(USE_CRAS)
   expect_value = true;
 #endif
   EXPECT_EQ(expect_value,
             GetPickerDialogView()->GetCheckboxForTesting()->visible());
 
-  EXPECT_TRUE(ClickSourceTypeButton(DesktopMediaID::SOURCE_WINDOW));
+  EXPECT_TRUE(ClickSourceTypeButton(DesktopMediaID::TYPE_WINDOW));
   EXPECT_FALSE(GetPickerDialogView()->GetCheckboxForTesting()->visible());
 
-  EXPECT_TRUE(ClickSourceTypeButton(DesktopMediaID::SOURCE_WEB_CONTENTS));
+  EXPECT_TRUE(ClickSourceTypeButton(DesktopMediaID::TYPE_WEB_CONTENTS));
   EXPECT_TRUE(GetPickerDialogView()->GetCheckboxForTesting()->visible());
 }
 
 // Verifies that audio share information is recorded in the ID if the checkbox
 // is checked.
 TEST_F(DesktopMediaPickerViewsTest, DoneWithAudioShare) {
-  DesktopMediaID originId(DesktopMediaID::SOURCE_WEB_CONTENTS, 222);
+  DesktopMediaID originId(DesktopMediaID::TYPE_WEB_CONTENTS, 222);
   DesktopMediaID returnId = originId;
-  returnId.set_audio_capture(true);
+  returnId.audio_share = true;
 
   // This matches the real workflow that when a source is generated in
-  // media_list, its |set_audio_capture| bit is not set. The bit is set by the
-  // picker UI if the audio checkbox is checked.
+  // media_list, its |audio_share| bit is not set. The bit is set by the picker
+  // UI if the audio checkbox is checked.
   EXPECT_CALL(*this, OnPickerDone(returnId));
-  media_lists_[DesktopMediaID::SOURCE_WEB_CONTENTS]->AddSourceByFullMediaID(
+  media_lists_[DesktopMediaID::TYPE_WEB_CONTENTS]->AddSourceByFullMediaID(
       originId);
 
-  EXPECT_TRUE(ClickSourceTypeButton(DesktopMediaID::SOURCE_WEB_CONTENTS));
+  EXPECT_TRUE(ClickSourceTypeButton(DesktopMediaID::TYPE_WEB_CONTENTS));
   GetPickerDialogView()->GetCheckboxForTesting()->SetChecked(true);
   GetPickerDialogView()->GetMediaSourceViewForTesting(0)->OnFocus();
 
diff --git a/chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_footnote_view.cc b/chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_footnote_view.cc
index 8b6bfe9..5c54b31 100644
--- a/chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_footnote_view.cc
+++ b/chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_footnote_view.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/ui/desktop_ios_promotion/desktop_ios_promotion_controller.h"
 #include "chrome/browser/ui/desktop_ios_promotion/desktop_ios_promotion_footnote_delegate.h"
 #include "chrome/browser/ui/desktop_ios_promotion/desktop_ios_promotion_util.h"
+#include "chrome/browser/ui/views/harmony/chrome_typography.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -34,13 +35,11 @@
       IDS_BOOKMARK_FOOTNOTE_DESKTOP_TO_IOS_PROMO_MESSAGE, link_text, &offset);
   SetText(promo_text);
 
-  views::StyledLabel::RangeStyleInfo link_style =
-      views::StyledLabel::RangeStyleInfo::CreateForLink();
-  link_style.font_style = gfx::Font::NORMAL;
-  AddStyleRange(gfx::Range(offset, offset + link_text.length()), link_style);
+  AddStyleRange(gfx::Range(offset, offset + link_text.length()),
+                views::StyledLabel::RangeStyleInfo::CreateForLink());
 
   views::StyledLabel::RangeStyleInfo promo_style;
-  promo_style.color = SkColorSetRGB(102, 102, 102);
+  promo_style.text_style = STYLE_SECONDARY;
   gfx::Range before_link_range(0, offset);
   if (!before_link_range.is_empty())
     AddStyleRange(before_link_range, promo_style);
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
index 261cdfe..1d34d4d 100644
--- a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
+++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
@@ -26,6 +26,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
+#include "chrome/browser/ui/views/harmony/bulleted_label_list_view.h"
 #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/harmony/chrome_typography.h"
 #include "chrome/common/extensions/extension_constants.h"
@@ -61,9 +62,6 @@
 
 namespace {
 
-// Width of the bullet column in BulletedView.
-constexpr int kBulletWidth = 20;
-
 // Size of extension icon in top left of dialog.
 constexpr int kIconSize = 64;
 
@@ -103,15 +101,6 @@
   parent->AddChildView(image_view);
 }
 
-// Creates a string for displaying |message| to the user. If it has to look
-// like a entry in a bullet point list, one is added.
-base::string16 PrepareForDisplay(const base::string16& message,
-                                 bool bullet_point) {
-  return bullet_point ? l10n_util::GetStringFUTF16(
-      IDS_EXTENSION_PERMISSION_LINE,
-      message) : message;
-}
-
 void ShowExtensionInstallDialogImpl(
     ExtensionInstallPromptShowParams* show_params,
     const ExtensionInstallPrompt::DoneCallback& done_callback,
@@ -155,26 +144,6 @@
 
 }  // namespace
 
-BulletedView::BulletedView(views::View* view) {
-  views::GridLayout* layout = views::GridLayout::CreateAndInstall(this);
-  views::ColumnSet* column_set = layout->AddColumnSet(0);
-  column_set->AddColumn(views::GridLayout::CENTER,
-                        views::GridLayout::LEADING,
-                        0,
-                        views::GridLayout::FIXED,
-                        kBulletWidth,
-                        0);
-  column_set->AddColumn(views::GridLayout::LEADING,
-                        views::GridLayout::LEADING,
-                        0,
-                        views::GridLayout::USE_PREF,
-                        0,  // No fixed width.
-                        0);
-  layout->StartRow(0, 0);
-  layout->AddView(new views::Label(PrepareForDisplay(base::string16(), true)));
-  layout->AddView(view);
-}
-
 ExtensionInstallDialogView::ExtensionInstallDialogView(
     Profile* profile,
     content::PageNavigator* navigator,
@@ -418,20 +387,15 @@
   for (size_t i = 0; i < prompt_->GetPermissionCount(perm_type); ++i) {
     layout->AddPaddingRow(0, vertical_padding);
     layout->StartRow(0, column_set_id);
-    views::Label* permission_label =
-        new views::Label(prompt_->GetPermission(i, perm_type));
 
-    permission_label->SetMultiLine(true);
-    permission_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    permission_label->SizeToFit(left_column_width - kBulletWidth);
-    layout->AddView(new BulletedView(permission_label));
+    base::string16 permission_text = prompt_->GetPermission(i, perm_type);
+    layout->AddView(new BulletedLabelListView({permission_text}));
 
     // If we have more details to provide, show them in collapsed form.
     if (!prompt_->GetPermissionsDetails(i, perm_type).empty()) {
       layout->StartRow(0, column_set_id);
       PermissionDetails details;
-      details.push_back(PrepareForDisplay(
-          prompt_->GetPermissionsDetails(i, perm_type), false));
+      details.push_back(prompt_->GetPermissionsDetails(i, perm_type));
       ExpandableContainerView* details_container =
           new ExpandableContainerView(details, left_column_width, true);
       layout->AddView(details_container);
@@ -648,8 +612,7 @@
   layout_->StartRowWithPadding(0, 0, 0,
                                ChromeLayoutProvider::Get()->GetDistanceMetric(
                                    DISTANCE_RELATED_CONTROL_VERTICAL_SMALL));
-  views::Label* detail_label =
-      new views::Label(PrepareForDisplay(detail, false));
+  views::Label* detail_label = new views::Label(detail);
   detail_label->SetMultiLine(true);
   detail_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
   layout_->AddView(detail_label);
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view.h b/chrome/browser/ui/views/extensions/extension_install_dialog_view.h
index 14e29abc..39efe0a 100644
--- a/chrome/browser/ui/views/extensions/extension_install_dialog_view.h
+++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view.h
@@ -123,15 +123,6 @@
   DISALLOW_COPY_AND_ASSIGN(ExtensionInstallDialogView);
 };
 
-// A simple view that prepends a view with a bullet with the help of a grid
-// layout.
-class BulletedView : public views::View {
- public:
-  explicit BulletedView(views::View* view);
- private:
-  DISALLOW_COPY_AND_ASSIGN(BulletedView);
-};
-
 // A view to display text with an expandable details section.
 class ExpandableContainerView : public views::View,
                                 public views::ButtonListener,
diff --git a/chrome/browser/ui/views/extensions/request_file_system_dialog_view.cc b/chrome/browser/ui/views/extensions/request_file_system_dialog_view.cc
index 813dc7a..72ffa5f7 100644
--- a/chrome/browser/ui/views/extensions/request_file_system_dialog_view.cc
+++ b/chrome/browser/ui/views/extensions/request_file_system_dialog_view.cc
@@ -11,6 +11,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
+#include "chrome/browser/ui/views/harmony/chrome_typography.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/constrained_window/constrained_window_views.h"
 #include "content/public/browser/web_contents.h"
@@ -108,7 +109,7 @@
 
   views::StyledLabel* const label = new views::StyledLabel(message, nullptr);
   views::StyledLabel::RangeStyleInfo bold_style;
-  bold_style.weight = gfx::Font::Weight::BOLD;
+  bold_style.text_style = STYLE_EMPHASIZED;
 
   DCHECK_EQ(2u, placeholder_offsets.size());
   label->AddStyleRange(gfx::Range(placeholder_offsets[0],
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 18bcb37..59e4bfd7 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
@@ -229,6 +229,7 @@
   aura::Window* window = browser()->window()->GetNativeWindow();
 
   EXPECT_FALSE(chrome::MultiUserWindowManager::ShouldShowAvatar(window));
+  EXPECT_FALSE(frame_view->profile_indicator_icon());
 
   const AccountId current_account_id =
       multi_user_util::GetAccountIdFromProfile(browser()->profile());
diff --git a/chrome/browser/ui/views/frame/system_menu_model_builder.cc b/chrome/browser/ui/views/frame/system_menu_model_builder.cc
index 29ac283..eaa2a14 100644
--- a/chrome/browser/ui/views/frame/system_menu_model_builder.cc
+++ b/chrome/browser/ui/views/frame/system_menu_model_builder.cc
@@ -144,9 +144,6 @@
 void SystemMenuModelBuilder::AppendTeleportMenu(ui::SimpleMenuModel* model) {
 #if defined(OS_CHROMEOS)
   DCHECK(browser()->window());
-  if (chrome::MultiUserWindowManager::GetMultiProfileMode() !=
-      chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_ON)
-    return;
 
   // Don't show the menu for incognito windows.
   if (browser()->profile()->IsOffTheRecord())
diff --git a/chrome/browser/ui/views/harmony/bulleted_label_list_view.cc b/chrome/browser/ui/views/harmony/bulleted_label_list_view.cc
new file mode 100644
index 0000000..2f80b01
--- /dev/null
+++ b/chrome/browser/ui/views/harmony/bulleted_label_list_view.cc
@@ -0,0 +1,81 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/harmony/bulleted_label_list_view.h"
+
+#include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
+#include "ui/gfx/canvas.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/layout/grid_layout.h"
+
+namespace {
+constexpr int kColumnSetId = 0;
+
+class BulletView : public views::View {
+ public:
+  explicit BulletView(SkColor color) : color_(color) {}
+
+  void OnPaint(gfx::Canvas* canvas) override;
+
+ private:
+  SkColor color_;
+
+  DISALLOW_COPY_AND_ASSIGN(BulletView);
+};
+
+void BulletView::OnPaint(gfx::Canvas* canvas) {
+  View::OnPaint(canvas);
+
+  SkScalar radius = std::min(height(), width()) / 8.0;
+  gfx::Point center = GetLocalBounds().CenterPoint();
+
+  SkPath path;
+  path.addCircle(center.x(), center.y(), radius);
+
+  cc::PaintFlags flags;
+  flags.setStyle(cc::PaintFlags::kStrokeAndFill_Style);
+  flags.setColor(color_);
+  flags.setAntiAlias(true);
+
+  canvas->DrawPath(path, flags);
+}
+
+}  // namespace
+
+BulletedLabelListView::BulletedLabelListView()
+    : BulletedLabelListView(std::vector<base::string16>()) {}
+
+BulletedLabelListView::BulletedLabelListView(
+    const std::vector<base::string16>& texts) {
+  constexpr auto FILL = views::GridLayout::FILL;
+  constexpr auto USE_PREF = views::GridLayout::USE_PREF;
+  constexpr auto FIXED = views::GridLayout::FIXED;
+
+  views::GridLayout* layout = views::GridLayout::CreateAndInstall(this);
+  views::ColumnSet* columns = layout->AddColumnSet(kColumnSetId);
+
+  int width = ChromeLayoutProvider::Get()->GetDistanceMetric(
+      DISTANCE_UNRELATED_CONTROL_HORIZONTAL);
+  columns->AddColumn(FILL, FILL, 0, FIXED, width, width);
+  columns->AddColumn(FILL, FILL, 1, USE_PREF, 0, 0);
+
+  for (const auto& text : texts)
+    AddLabel(text);
+}
+
+BulletedLabelListView::~BulletedLabelListView() {}
+
+void BulletedLabelListView::AddLabel(const base::string16& text) {
+  views::GridLayout* layout =
+      static_cast<views::GridLayout*>(GetLayoutManager());
+  layout->StartRow(0, kColumnSetId);
+
+  auto label = std::make_unique<views::Label>(text);
+
+  label->SetMultiLine(true);
+  label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+
+  layout->AddView(new BulletView(label->enabled_color()));
+  layout->AddView(label.release());
+}
diff --git a/chrome/browser/ui/views/harmony/bulleted_label_list_view.h b/chrome/browser/ui/views/harmony/bulleted_label_list_view.h
new file mode 100644
index 0000000..b780ae6
--- /dev/null
+++ b/chrome/browser/ui/views/harmony/bulleted_label_list_view.h
@@ -0,0 +1,23 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_HARMONY_BULLETED_LABEL_LIST_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_HARMONY_BULLETED_LABEL_LIST_VIEW_H_
+
+#include "ui/views/view.h"
+
+class BulletedLabelListView : public views::View {
+ public:
+  BulletedLabelListView();
+  explicit BulletedLabelListView(const std::vector<base::string16>& texts);
+
+  ~BulletedLabelListView() override;
+
+  void AddLabel(const base::string16& text);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BulletedLabelListView);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_HARMONY_BULLETED_LABEL_LIST_VIEW_H_
diff --git a/chrome/browser/ui/views/harmony/harmony_typography_provider.cc b/chrome/browser/ui/views/harmony/harmony_typography_provider.cc
index ab562418..0495723 100644
--- a/chrome/browser/ui/views/harmony/harmony_typography_provider.cc
+++ b/chrome/browser/ui/views/harmony/harmony_typography_provider.cc
@@ -83,6 +83,7 @@
 }  // namespace
 
 #if defined(OS_WIN)
+// static
 int HarmonyTypographyProvider::GetPlatformFontHeight(int font_context) {
   const bool direct_write_enabled =
       gfx::PlatformFontWin::IsDirectWriteEnabled();
@@ -91,7 +92,7 @@
     case CONTEXT_HEADLINE:
       return windows_10 && direct_write_enabled ? 27 : 28;
     case views::style::CONTEXT_DIALOG_TITLE:
-      return windows_10 ? 20 : 21;
+      return windows_10 || !direct_write_enabled ? 20 : 21;
     case CONTEXT_BODY_TEXT_LARGE:
       return direct_write_enabled ? 18 : 17;
     case CONTEXT_BODY_TEXT_SMALL:
diff --git a/chrome/browser/ui/views/harmony/layout_provider_unittest.cc b/chrome/browser/ui/views/harmony/layout_provider_unittest.cc
index 7883511e..879f4d0 100644
--- a/chrome/browser/ui/views/harmony/layout_provider_unittest.cc
+++ b/chrome/browser/ui/views/harmony/layout_provider_unittest.cc
@@ -40,8 +40,11 @@
  protected:
   static void SetUpTestCase() {
     // The expected case is to have DirectWrite enabled; the fallback gives
-    // different font heights. But the tests should pass either way.
-    gfx::win::MaybeInitializeDirectWrite();
+    // different font heights. However, only use DirectWrite on Windows 10 and
+    // later, since it's known to have flaky results on Windows 7. See
+    // http://crbug.com/759870.
+    if (base::win::GetVersion() >= base::win::VERSION_WIN10)
+      gfx::win::MaybeInitializeDirectWrite();
   }
 #endif
 
@@ -328,11 +331,6 @@
 // Harmony spec. This test will only run if it detects that the current machine
 // has the default OS configuration.
 TEST_F(LayoutProviderTest, ExplicitTypographyLineHeight) {
-#if defined(OS_WIN)
-  // Flaky on Windows 7. See http://crbug.com/759870.
-  if (base::win::GetVersion() == base::win::VERSION_WIN7)
-    return;
-#endif
   ui::test::MaterialDesignControllerTestAPI md_test_api(
       ui::MaterialDesignController::MATERIAL_NORMAL);
   md_test_api.SetSecondaryUiMaterial(true);
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
index 82343e9..74b9f25 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
@@ -89,32 +89,33 @@
 // General constants -----------------------------------------------------------
 
 // Bubble width constraints.
-const int kMinBubbleWidth = 320;
-const int kMaxBubbleWidth = 1000;
+constexpr int kMinBubbleWidth = 320;
+constexpr int kMaxBubbleWidth = 1000;
 
-// Security Section (BubbleHeaderView)
-// ------------------------------------------
+// Space between sections in the Page Info bubble.
+constexpr int kPageInfoVerticalSpacing = 10;
 
-// Margin and padding values for the |BubbleHeaderView|.
-const int kHeaderMarginBottom = 10;
-const int kHeaderPaddingBottom = 13;
+// Security Section (BubbleHeaderView) -----------------------------------------
 
-// Spacing between labels in the header.
-const int kHeaderLabelSpacing = 4;
+// Spacing underneath the title in the header.
+constexpr int kHeaderTitleBottomPadding = 4;
+
+// Padding for the |BubbleHeaderView|.
+constexpr int kHeaderPaddingBottom = 13;
 
 // Site Settings Section -------------------------------------------------------
 
-// Spacing above and below the cookies and certificate views.
-const int kSubViewsVerticalPadding = 6;
+// Spacing above/below the cookies and certificate views.
+constexpr int kSubViewsVerticalPadding = 3;
 
 // Spacing between a permission image and the text.
-const int kPermissionImageSpacing = 6;
+constexpr int kPermissionImageSpacing = 6;
 
-// Spacing between rows in the site settings section
-const int kPermissionsVerticalSpacing = 12;
+// Minimum spacing between the label and the menu.
+constexpr int kPermissionMenuSpacing = 16;
 
-// Spacing between the label and the menu.
-const int kPermissionMenuSpacing = 16;
+// Spacing between permission rows, plus above the site settings link.
+constexpr int kPermissionsVerticalSpacing = 12;
 
 // The default, ui::kTitleFontSizeDelta, is too large for the page info
 // bubble (e.g. +3). Use +1 to obtain a smaller font.
@@ -148,9 +149,7 @@
   column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 0,
                         views::GridLayout::USE_PREF, 0, 0);
 
-  layout->AddPaddingRow(0, kSubViewsVerticalPadding);
-
-  layout->StartRow(1, column);
+  layout->StartRowWithPadding(1, column, 0, kSubViewsVerticalPadding);
 
   views::ImageView* icon = new NonAccessibleImageView();
   icon->SetImage(image_icon);
@@ -167,9 +166,25 @@
   layout->SkipColumns(1);
 
   layout->AddView(link);
+  layout->AddPaddingRow(0, kSubViewsVerticalPadding);
   return new_view;
 }
 
+views::View* CreateSiteSettingsLink(const int side_margin,
+                                    views::LinkListener* listener) {
+  views::Link* site_settings_link = new views::Link(
+      l10n_util::GetStringUTF16(IDS_PAGE_INFO_SITE_SETTINGS_LINK));
+  site_settings_link->set_id(
+      PageInfoBubbleView::VIEW_ID_PAGE_INFO_LINK_SITE_SETTINGS);
+  site_settings_link->set_listener(listener);
+  site_settings_link->SetUnderline(false);
+  views::View* link_section = new views::View();
+  link_section->SetLayoutManager(new views::BoxLayout(
+      views::BoxLayout::kHorizontal, gfx::Insets(0, side_margin)));
+  link_section->AddChildView(site_settings_link);
+  return link_section;
+}
+
 }  // namespace
 
 // |BubbleHeaderView| is the UI element (view) that represents the header of the
@@ -263,9 +278,9 @@
 
   const int label_column_status = 1;
   AddColumnWithSideMargin(layout, side_margin, label_column_status);
-  layout->AddPaddingRow(0, kHeaderLabelSpacing);
 
-  layout->StartRow(0, label_column_status);
+  layout->StartRowWithPadding(0, label_column_status, 0,
+                              kHeaderTitleBottomPadding);
   security_details_label_ =
       new views::StyledLabel(base::string16(), styled_label_listener);
   security_details_label_->set_id(
@@ -287,7 +302,10 @@
   layout->AddView(password_reuse_button_container_, 1, 1,
                   views::GridLayout::FILL, views::GridLayout::LEADING);
 
-  layout->AddPaddingRow(1, kHeaderPaddingBottom);
+  // The spacing underneath the BubbleHeaderView should equal to
+  // |kHeaderPaddingBottom|, but subtract |kPageInfoVerticalSpacing| here since
+  // that has already been added.
+  layout->AddPaddingRow(1, kHeaderPaddingBottom - kPageInfoVerticalSpacing);
 }
 
 BubbleHeaderView::~BubbleHeaderView() {}
@@ -306,9 +324,6 @@
 
   views::StyledLabel::RangeStyleInfo link_style =
       views::StyledLabel::RangeStyleInfo::CreateForLink();
-  if (!ui::MaterialDesignController::IsSecondaryUiMaterial()) {
-    link_style.font_style |= gfx::Font::FontStyle::UNDERLINE;
-  }
   link_style.disable_line_wrapping = false;
 
   security_details_label_->AddStyleRange(details_range, link_style);
@@ -333,9 +348,6 @@
 
   views::StyledLabel::RangeStyleInfo link_style =
       views::StyledLabel::RangeStyleInfo::CreateForLink();
-  if (!ui::MaterialDesignController::IsSecondaryUiMaterial()) {
-    link_style.font_style |= gfx::Font::FontStyle::UNDERLINE;
-  }
   link_style.disable_line_wrapping = false;
 
   reset_cert_decisions_label_->AddStyleRange(link_range, link_style);
@@ -488,9 +500,7 @@
       BubbleDialogDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT),
       profile_(profile),
       header_(nullptr),
-      separator_(nullptr),
       site_settings_view_(nullptr),
-      cookie_dialog_link_(nullptr),
       permissions_view_(nullptr),
       weak_factory_(this) {
   g_shown_bubble_type = BUBBLE_PAGE_INFO;
@@ -513,28 +523,19 @@
   // below the dialog title.
   set_margins(gfx::Insets(0, 0, margins().bottom(), 0));
 
-  views::GridLayout* layout = views::GridLayout::CreateAndInstall(this);
-
-  // Use a single ColumnSet here. Otherwise the preferred width doesn't properly
-  // propagate up to the dialog width.
-  const int content_column = 0;
-  views::ColumnSet* column_set = layout->AddColumnSet(content_column);
-  column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
-                        views::GridLayout::USE_PREF, 0, 0);
+  views::BoxLayout* layout = new views::BoxLayout(
+      views::BoxLayout::kVertical, gfx::Insets(), kPageInfoVerticalSpacing);
+  SetLayoutManager(layout);
 
   header_ = new BubbleHeaderView(this, this, side_margin);
-  layout->StartRow(1, content_column);
-  layout->AddView(header_);
+  AddChildView(header_);
 
-  layout->StartRow(0, content_column);
-  separator_ = new views::Separator();
-  layout->AddView(separator_);
-
-  layout->AddPaddingRow(1, kHeaderMarginBottom);
-  layout->StartRow(1, content_column);
+  AddChildView(new views::Separator());
 
   site_settings_view_ = CreateSiteSettingsView(side_margin);
-  layout->AddView(site_settings_view_);
+  AddChildView(site_settings_view_);
+
+  AddChildView(CreateSiteSettingsLink(side_margin, this));
 
   if (!ui::MaterialDesignController::IsSecondaryUiMaterial()) {
     // In non-material, titles are inset from the dialog margin. Ensure the
@@ -644,18 +645,7 @@
     return views::View::CalculatePreferredSize();
   }
 
-  int height = 0;
-  if (header_) {
-    height += header_->GetPreferredSize().height() + kHeaderMarginBottom;
-  }
-  if (separator_) {
-    height += separator_->GetPreferredSize().height();
-  }
-
-  if (site_settings_view_) {
-    height += site_settings_view_->GetPreferredSize().height();
-  }
-
+  int height = views::View::CalculatePreferredSize().height();
   int width = kMinBubbleWidth;
   if (site_settings_view_) {
     width = std::max(width, site_settings_view_->GetPreferredSize().width());
@@ -665,6 +655,25 @@
 }
 
 void PageInfoBubbleView::SetCookieInfo(const CookieInfoList& cookie_info_list) {
+  // Create the link and icon for the Cookies section.
+  views::Link* cookie_dialog_link = new views::Link(
+      l10n_util::GetPluralStringFUTF16(IDS_PAGE_INFO_NUM_COOKIES, 0));
+  cookie_dialog_link->set_id(
+      PageInfoBubbleView::VIEW_ID_PAGE_INFO_LINK_COOKIE_DIALOG);
+  cookie_dialog_link->set_listener(this);
+  cookie_dialog_link->SetUnderline(false);
+
+  PageInfoUI::PermissionInfo info;
+  info.type = CONTENT_SETTINGS_TYPE_COOKIES;
+  info.setting = CONTENT_SETTING_ALLOW;
+  info.is_incognito =
+      Profile::FromBrowserContext(web_contents()->GetBrowserContext())
+          ->IsOffTheRecord();
+
+  const gfx::ImageSkia icon = PageInfoUI::GetPermissionIcon(info).AsImageSkia();
+  site_settings_view_->AddChildView(CreateInspectLinkSection(
+      icon, IDS_PAGE_INFO_COOKIES, cookie_dialog_link));
+
   // |cookie_info_list| should only ever have 2 items: first- and third-party
   // cookies.
   DCHECK_EQ(cookie_info_list.size(), 2u);
@@ -674,8 +683,8 @@
   }
   base::string16 label_text = l10n_util::GetPluralStringFUTF16(
       IDS_PAGE_INFO_NUM_COOKIES, total_allowed);
+  cookie_dialog_link->SetText(label_text);
 
-  cookie_dialog_link_->SetText(label_text);
   Layout();
   SizeToContents();
 }
@@ -688,9 +697,8 @@
   // will have already updated its state, so it's already reflected in the UI.
   // In addition, if a permission is set to the default setting, PageInfo
   // removes it from |permission_info_list|, but the button should remain.
-  if (permissions_view_) {
+  if (permissions_view_)
     return;
-  }
 
   permissions_view_ = new views::View();
   views::GridLayout* layout =
@@ -739,19 +747,6 @@
 
   layout->Layout(permissions_view_);
 
-  // Add site settings link.
-  views::Link* site_settings_link = new views::Link(
-      l10n_util::GetStringUTF16(IDS_PAGE_INFO_SITE_SETTINGS_LINK));
-  site_settings_link->set_id(
-      PageInfoBubbleView::VIEW_ID_PAGE_INFO_LINK_SITE_SETTINGS);
-  site_settings_link->set_listener(this);
-  views::View* link_section = new views::View();
-  const int kLinkMarginTop = 4;
-  link_section->SetLayoutManager(new views::BoxLayout(
-      views::BoxLayout::kHorizontal, gfx::Insets(kLinkMarginTop, 0)));
-  link_section->AddChildView(site_settings_link);
-  site_settings_view_->AddChildView(link_section);
-
   SizeToContents();
 }
 
@@ -770,33 +765,31 @@
       header_->AddResetDecisionsLabel();
     }
 
-    if (PageInfoUI::ShouldShowCertificateLink()) {
-      // The text of link to the Certificate Viewer varies depending on the
-      // validity of the Certificate.
-      const bool valid_identity = (identity_info.identity_status !=
-                                   PageInfo::SITE_IDENTITY_STATUS_ERROR);
-      const base::string16 link_title = l10n_util::GetStringUTF16(
-          valid_identity ? IDS_PAGE_INFO_CERTIFICATE_VALID_LINK
-                         : IDS_PAGE_INFO_CERTIFICATE_INVALID_LINK);
+    // Show information about the page's certificate.
+    // The text of link to the Certificate Viewer varies depending on the
+    // validity of the Certificate.
+    const bool valid_identity =
+        (identity_info.identity_status != PageInfo::SITE_IDENTITY_STATUS_ERROR);
+    const base::string16 link_title = l10n_util::GetStringUTF16(
+        valid_identity ? IDS_PAGE_INFO_CERTIFICATE_VALID_LINK
+                       : IDS_PAGE_INFO_CERTIFICATE_INVALID_LINK);
 
-      // Create the link to add to the Certificate Section.
-      views::Link* certificate_viewer_link = new views::Link(link_title);
-      certificate_viewer_link->set_id(
-          PageInfoBubbleView::VIEW_ID_PAGE_INFO_LINK_CERTIFICATE_VIEWER);
-      certificate_viewer_link->set_listener(this);
-      if (valid_identity) {
-        certificate_viewer_link->SetTooltipText(l10n_util::GetStringFUTF16(
-            IDS_PAGE_INFO_CERTIFICATE_VALID_LINK_TOOLTIP,
-            base::UTF8ToUTF16(certificate_->issuer().GetDisplayName())));
-      }
-
-      // Add the Certificate Section.
-      site_settings_view_->AddChildViewAt(
-          CreateInspectLinkSection(PageInfoUI::GetCertificateIcon(),
-                                   IDS_PAGE_INFO_CERTIFICATE,
-                                   certificate_viewer_link),
-          0);
+    // Create the link to add to the Certificate Section.
+    views::Link* certificate_viewer_link = new views::Link(link_title);
+    certificate_viewer_link->set_id(
+        PageInfoBubbleView::VIEW_ID_PAGE_INFO_LINK_CERTIFICATE_VIEWER);
+    certificate_viewer_link->set_listener(this);
+    certificate_viewer_link->SetUnderline(false);
+    if (valid_identity) {
+      certificate_viewer_link->SetTooltipText(l10n_util::GetStringFUTF16(
+          IDS_PAGE_INFO_CERTIFICATE_VALID_LINK_TOOLTIP,
+          base::UTF8ToUTF16(certificate_->issuer().GetDisplayName())));
     }
+
+    // Add the Certificate Section.
+    site_settings_view_->AddChildView(CreateInspectLinkSection(
+        PageInfoUI::GetCertificateIcon(), IDS_PAGE_INFO_CERTIFICATE,
+        certificate_viewer_link));
   }
 
   if (identity_info.show_change_password_buttons) {
@@ -817,25 +810,6 @@
   box_layout->set_cross_axis_alignment(
       views::BoxLayout::CROSS_AXIS_ALIGNMENT_STRETCH);
 
-  // Create the link and icon for the Certificate section.
-  cookie_dialog_link_ = new views::Link(
-      l10n_util::GetPluralStringFUTF16(IDS_PAGE_INFO_NUM_COOKIES, 0));
-  cookie_dialog_link_->set_id(
-      PageInfoBubbleView::VIEW_ID_PAGE_INFO_LINK_COOKIE_DIALOG);
-  cookie_dialog_link_->set_listener(this);
-
-  PageInfoUI::PermissionInfo info;
-  info.type = CONTENT_SETTINGS_TYPE_COOKIES;
-  info.setting = CONTENT_SETTING_ALLOW;
-  info.is_incognito =
-      Profile::FromBrowserContext(web_contents()->GetBrowserContext())
-          ->IsOffTheRecord();
-
-  const gfx::ImageSkia icon = PageInfoUI::GetPermissionIcon(info).AsImageSkia();
-  // Add the Cookies section.
-  site_settings_view->AddChildView(CreateInspectLinkSection(
-      icon, IDS_PAGE_INFO_COOKIES, cookie_dialog_link_));
-
   return site_settings_view;
 }
 
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.h b/chrome/browser/ui/views/page_info/page_info_bubble_view.h
index 21a958f..d7e9624 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view.h
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.h
@@ -172,15 +172,9 @@
   // The security summary for the current page.
   base::string16 summary_text_;
 
-  // The separator between the header and the site settings view.
-  views::Separator* separator_;
-
   // The view that contains the certificate, cookie, and permissions sections.
   views::View* site_settings_view_;
 
-  // The link that opens the "Cookies" dialog.
-  views::Link* cookie_dialog_link_;
-
   // The view that contains the "Permissions" table of the site settings view.
   views::View* permissions_view_;
 
diff --git a/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc b/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc
index 15c25ea..c6388319 100644
--- a/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc
+++ b/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc
@@ -125,8 +125,7 @@
       controller_->GetAccoutChooserTitle();
   std::unique_ptr<views::StyledLabel> title_label =
       base::MakeUnique<views::StyledLabel>(title_content.first, this);
-  title_label->SetBaseFontList(views::style::GetFont(
-      views::style::CONTEXT_DIALOG_TITLE, views::style::STYLE_PRIMARY));
+  title_label->SetTextContext(views::style::CONTEXT_DIALOG_TITLE);
   if (!title_content.second.is_empty())
     title_label->AddStyleRange(title_content.second, GetLinkStyle());
   GetBubbleFrameView()->SetTitleView(std::move(title_label));
diff --git a/chrome/browser/ui/views/passwords/auto_signin_first_run_dialog_view.cc b/chrome/browser/ui/views/passwords/auto_signin_first_run_dialog_view.cc
index ae25f93..9ca20e4 100644
--- a/chrome/browser/ui/views/passwords/auto_signin_first_run_dialog_view.cc
+++ b/chrome/browser/ui/views/passwords/auto_signin_first_run_dialog_view.cc
@@ -53,14 +53,6 @@
     controller_->OnCloseDialog();
 }
 
-void AutoSigninFirstRunDialogView::OnNativeThemeChanged(
-    const ui::NativeTheme* theme) {
-  views::StyledLabel::RangeStyleInfo default_style;
-  default_style.color =
-      views::style::GetColor(CONTEXT_BODY_TEXT_LARGE, STYLE_SECONDARY, theme);
-  text_->SetDefaultStyle(default_style);
-}
-
 bool AutoSigninFirstRunDialogView::Cancel() {
   controller_->OnAutoSigninTurnOff();
   return true;
@@ -99,9 +91,8 @@
   std::pair<base::string16, gfx::Range> text_content =
       controller_->GetAutoSigninText();
   text_ = new views::StyledLabel(text_content.first, this);
-  text_->SetBaseFontList(
-      views::style::GetFont(CONTEXT_BODY_TEXT_LARGE, STYLE_SECONDARY));
-  OnNativeThemeChanged(GetNativeTheme());
+  text_->SetTextContext(CONTEXT_BODY_TEXT_LARGE);
+  text_->SetDefaultTextStyle(STYLE_SECONDARY);
   if (!text_content.second.is_empty()) {
     text_->AddStyleRange(text_content.second,
                          views::StyledLabel::RangeStyleInfo::CreateForLink());
diff --git a/chrome/browser/ui/views/passwords/auto_signin_first_run_dialog_view.h b/chrome/browser/ui/views/passwords/auto_signin_first_run_dialog_view.h
index c79a08a2..f83b761 100644
--- a/chrome/browser/ui/views/passwords/auto_signin_first_run_dialog_view.h
+++ b/chrome/browser/ui/views/passwords/auto_signin_first_run_dialog_view.h
@@ -32,7 +32,6 @@
   base::string16 GetWindowTitle() const override;
   bool ShouldShowCloseButton() const override;
   void WindowClosing() override;
-  void OnNativeThemeChanged(const ui::NativeTheme* theme) override;
   bool Cancel() override;
   bool Accept() override;
   bool Close() override;
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
index 6475f3797..96a8d8d 100644
--- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
+++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
@@ -34,6 +34,7 @@
 #include "ui/base/ui_features.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/text_constants.h"
 #include "ui/native_theme/native_theme.h"
 #include "ui/resources/grit/ui_resources.h"
 #include "ui/views/bubble/bubble_frame_view.h"
@@ -41,6 +42,7 @@
 #include "ui/views/controls/button/image_button.h"
 #include "ui/views/controls/button/md_text_button.h"
 #include "ui/views/controls/combobox/combobox.h"
+#include "ui/views/controls/label.h"
 #include "ui/views/controls/link.h"
 #include "ui/views/controls/link_listener.h"
 #include "ui/views/controls/separator.h"
@@ -69,13 +71,14 @@
   // messages like "No passwords".
   SINGLE_VIEW_COLUMN_SET,
 
-  // | | (FILL, FILL) | | (FILL, FILL) | |
-  // Used for the credentials line of the bubble, for the pending view.
-  DOUBLE_VIEW_COLUMN_SET,
+  // | | (LEADING, FILL) | | (FILL, FILL) | |
+  // Used for the username/password line of the bubble, for the pending view.
+  DOUBLE_VIEW_COLUMN_SET_USERNAME,
+  DOUBLE_VIEW_COLUMN_SET_PASSWORD,
 
-  // | | (FILL, FILL) | | (FILL, FILL) | | (TRAILING, FILL) | |
-  // Used for the credentials line of the bubble, for the pending view.
-  // Views are username, password and the eye icon.
+  // | | (LEADING, FILL) | | (FILL, FILL) | | (TRAILING, FILL) | |
+  // Used for the password line of the bubble, for the pending view.
+  // Views are label, password and the eye icon.
   TRIPLE_VIEW_COLUMN_SET,
 
   // | | (TRAILING, CENTER) | | (TRAILING, CENTER) | |
@@ -118,16 +121,17 @@
                             full_width,
                             0);
       break;
-    case DOUBLE_VIEW_COLUMN_SET:
-      column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
-                            views::GridLayout::USE_PREF, 0, 0);
+    case DOUBLE_VIEW_COLUMN_SET_USERNAME:
+    case DOUBLE_VIEW_COLUMN_SET_PASSWORD:
+      column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL,
+                            0, views::GridLayout::USE_PREF, 0, 0);
       column_set->AddPaddingColumn(0, column_divider);
       column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
                             views::GridLayout::USE_PREF, 0, 0);
       break;
     case TRIPLE_VIEW_COLUMN_SET:
-      column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
-                            views::GridLayout::USE_PREF, 0, 0);
+      column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL,
+                            0, views::GridLayout::USE_PREF, 0, 0);
       column_set->AddPaddingColumn(0, column_divider);
       column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
                             views::GridLayout::USE_PREF, 0, 0);
@@ -265,55 +269,44 @@
 
 // Builds a credential row, adds the given elements to the layout.
 // |password_view_button| is an optional field. If it is a nullptr, a
-// DOUBLE_VIEW_COLUMN_SET will be used instead of TRIPLE_VIEW_COLUMN_SET.
-void BuildCredentialRow(views::GridLayout* layout,
-                        views::View* username_field,
-                        views::View* password_field,
-                        views::ToggleImageButton* password_view_button) {
-  ColumnSetType type =
-      password_view_button ? TRIPLE_VIEW_COLUMN_SET : DOUBLE_VIEW_COLUMN_SET;
+// DOUBLE_VIEW_COLUMN_SET_PASSWORD will be used for password row instead of
+// TRIPLE_VIEW_COLUMN_SET.
+void BuildCredentialRows(views::GridLayout* layout,
+                         views::View* username_field,
+                         views::View* password_field,
+                         views::ToggleImageButton* password_view_button) {
+  // Username row.
+  BuildColumnSet(layout, DOUBLE_VIEW_COLUMN_SET_USERNAME);
+  layout->StartRow(0, DOUBLE_VIEW_COLUMN_SET_USERNAME);
+  std::unique_ptr<views::Label> username_label(new views::Label(
+      l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_USERNAME_LABEL),
+      views::style::CONTEXT_LABEL, views::style::STYLE_PRIMARY));
+  username_label->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_RIGHT);
+  std::unique_ptr<views::Label> password_label(new views::Label(
+      l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_PASSWORD_LABEL),
+      views::style::CONTEXT_LABEL, views::style::STYLE_PRIMARY));
+  password_label->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_RIGHT);
+  int labels_width = std::max(username_label->GetPreferredSize().width(),
+                              password_label->GetPreferredSize().width());
+
+  layout->AddView(username_label.release(), 1, 1, views::GridLayout::LEADING,
+                  views::GridLayout::FILL, labels_width, 0);
+  layout->AddView(username_field, 1, 1, views::GridLayout::FILL,
+                  views::GridLayout::FILL, 0, 0);
+
+  layout->AddPaddingRow(
+      0, ChromeLayoutProvider::Get()->GetDistanceMetric(
+             views::DISTANCE_DIALOG_CONTENT_MARGIN_BOTTOM_CONTROL));
+
+  // Password row.
+  ColumnSetType type = password_view_button ? TRIPLE_VIEW_COLUMN_SET
+                                            : DOUBLE_VIEW_COLUMN_SET_PASSWORD;
   BuildColumnSet(layout, type);
   layout->StartRow(0, type);
-  // TODO(https://crbug.com/761767): Remove this workaround once the grid
-  // layout bug is fixed.
-  int username_width = username_field->GetPreferredSize().width();
-  int password_width = password_field->GetPreferredSize().width();
-  int available_width;
-  if (password_view_button) {
-    available_width = ManagePasswordsBubbleView::kDesiredBubbleWidth -
-                      2 * ChromeLayoutProvider::Get()->GetDistanceMetric(
-                              views::DISTANCE_RELATED_CONTROL_HORIZONTAL) -
-                      password_view_button->GetPreferredSize().width();
-  } else {
-    available_width = ManagePasswordsBubbleView::kDesiredBubbleWidth -
-                      ChromeLayoutProvider::Get()->GetDistanceMetric(
-                          views::DISTANCE_RELATED_CONTROL_HORIZONTAL);
-  }
-  if (username_width > available_width && password_width < available_width) {
-    // If username is long and password is short, we limit the length of the
-    // username to the available width and password gets 0.
-    layout->AddView(username_field, 1, 1, views::GridLayout::FILL,
-                    views::GridLayout::FILL, available_width, 0);
-    layout->AddView(password_field, 1, 1, views::GridLayout::FILL,
-                    views::GridLayout::FILL, 0, 0);
-  } else if (username_width < available_width &&
-             password_width > available_width) {
-    // If username is short and password is long, username keeps its
-    // preferred length, and password gets the remaining available width.
-    layout->AddView(username_field, 1, 1, views::GridLayout::FILL,
-                    views::GridLayout::FILL, username_width, 0);
-    layout->AddView(password_field, 1, 1, views::GridLayout::FILL,
-                    views::GridLayout::FILL, available_width - username_width,
-                    0);
-  } else {
-    // If both fields are long or both are short, regular implementation is
-    // kept. For long username and password, fields get equal space. For
-    // shorter ones, they share the existing space.
-    layout->AddView(username_field, 1, 1, views::GridLayout::FILL,
-                    views::GridLayout::FILL, 0, 0);
-    layout->AddView(password_field, 1, 1, views::GridLayout::FILL,
-                    views::GridLayout::FILL, 0, 0);
-  }
+  layout->AddView(password_label.release(), 1, 1, views::GridLayout::LEADING,
+                  views::GridLayout::FILL, labels_width, 0);
+  layout->AddView(password_field, 1, 1, views::GridLayout::FILL,
+                  views::GridLayout::FILL, 0, 0);
   // The eye icon is also added to the layout if it was passed.
   if (password_view_button) {
     layout->AddView(password_view_button);
@@ -521,8 +514,8 @@
   views::GridLayout* layout = views::GridLayout::CreateAndInstall(this);
   layout->set_minimum_size(gfx::Size(kDesiredBubbleWidth, 0));
 
-  BuildCredentialRow(layout, username_field_, password_field_.get(),
-                     password_view_button_);
+  BuildCredentialRows(layout, username_field_, password_field_.get(),
+                      password_view_button_);
   layout->AddPaddingRow(
       0, ChromeLayoutProvider::Get()->GetDistanceMetric(
              views::DISTANCE_DIALOG_CONTENT_MARGIN_BOTTOM_CONTROL));
@@ -712,8 +705,7 @@
 
   views::StyledLabel* confirmation =
       new views::StyledLabel(parent_->model()->save_confirmation_text(), this);
-  confirmation->SetBaseFontList(views::style::GetFont(
-      CONTEXT_DEPRECATED_SMALL, views::style::STYLE_PRIMARY));
+  confirmation->SetTextContext(CONTEXT_DEPRECATED_SMALL);
   confirmation->AddStyleRange(parent_->model()->save_confirmation_link_range(),
                               GetLinkStyle());
 
@@ -856,9 +848,9 @@
   } else {
     const autofill::PasswordForm& password_form =
         parent_->model()->pending_password();
-    BuildCredentialRow(layout, GenerateUsernameLabel(password_form).release(),
-                       GeneratePasswordLabel(password_form, false).release(),
-                       nullptr);
+    BuildCredentialRows(layout, GenerateUsernameLabel(password_form).release(),
+                        GeneratePasswordLabel(password_form, false).release(),
+                        nullptr);
   }
   layout->AddPaddingRow(
       0, layout_provider->GetDistanceMetric(
@@ -1019,8 +1011,7 @@
 void ManagePasswordsBubbleView::AddedToWidget() {
   auto title_view =
       base::MakeUnique<views::StyledLabel>(base::string16(), this);
-  title_view->SetBaseFontList(views::style::GetFont(
-      views::style::CONTEXT_DIALOG_TITLE, views::style::STYLE_PRIMARY));
+  title_view->SetTextContext(views::style::CONTEXT_DIALOG_TITLE);
   UpdateTitleText(title_view.get());
   GetBubbleFrameView()->SetTitleView(std::move(title_view));
 }
diff --git a/chrome/browser/ui/views/payments/contact_info_editor_view_controller.cc b/chrome/browser/ui/views/payments/contact_info_editor_view_controller.cc
index 030dbd74..ff870473 100644
--- a/chrome/browser/ui/views/payments/contact_info_editor_view_controller.cc
+++ b/chrome/browser/ui/views/payments/contact_info_editor_view_controller.cc
@@ -12,6 +12,7 @@
 #include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/phone_number_i18n.h"
 #include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/payments/content/payment_request_spec.h"
@@ -75,7 +76,7 @@
     return base::string16();
 
   if (type == autofill::PHONE_HOME_WHOLE_NUMBER) {
-    return data_util::GetFormattedPhoneNumberForDisplay(
+    return autofill::i18n::GetFormattedPhoneNumberForDisplay(
         *profile_to_edit_, state()->GetApplicationLocale());
   }
 
@@ -159,7 +160,7 @@
 base::string16
 ContactInfoEditorViewController::ContactInfoValidationDelegate::Format(
     const base::string16& text) {
-  return base::UTF8ToUTF16(data_util::FormatPhoneForDisplay(
+  return base::UTF8ToUTF16(autofill::i18n::FormatPhoneForDisplay(
       base::UTF16ToUTF8(text),
       autofill::AutofillCountry::CountryCodeForLocale(locale_)));
 }
diff --git a/chrome/browser/ui/views/payments/payment_request_views_util.cc b/chrome/browser/ui/views/payments/payment_request_views_util.cc
index 7428f9d..0f2dfb2 100644
--- a/chrome/browser/ui/views/payments/payment_request_views_util.cc
+++ b/chrome/browser/ui/views/payments/payment_request_views_util.cc
@@ -19,6 +19,7 @@
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/field_types.h"
+#include "components/autofill/core/browser/phone_number_i18n.h"
 #include "components/payments/core/payment_options_provider.h"
 #include "components/payments/core/payment_request_data_util.h"
 #include "components/payments/core/payments_profile_comparator.h"
@@ -128,7 +129,7 @@
       GetShippingAddressLabelFormAutofillProfile(profile, locale);
 
   base::string16 phone =
-      data_util::GetFormattedPhoneNumberForDisplay(profile, locale);
+      autofill::i18n::GetFormattedPhoneNumberForDisplay(profile, locale);
 
   return GetBaseProfileLabel(type, name, address, phone, accessible_content,
                              enabled);
@@ -314,7 +315,7 @@
 
   base::string16 phone =
       options.request_payer_phone()
-          ? data_util::GetFormattedPhoneNumberForDisplay(profile, locale)
+          ? autofill::i18n::GetFormattedPhoneNumberForDisplay(profile, locale)
           : base::string16();
 
   base::string16 email = options.request_payer_email()
diff --git a/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc b/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc
index c031679..68e7f52 100644
--- a/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc
+++ b/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc
@@ -39,6 +39,7 @@
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/color_utils.h"
@@ -959,15 +960,15 @@
       base::MakeUnique<views::StyledLabel>(data_source, this);
   data_source_label->SetBorder(views::CreateEmptyBorder(22, 0, 0, 0));
   data_source_label->set_id(static_cast<int>(DialogViewID::DATA_SOURCE_LABEL));
-
-  views::StyledLabel::RangeStyleInfo default_style;
-  default_style.color = data_source_label->GetNativeTheme()->GetSystemColor(
-      ui::NativeTheme::kColorId_LabelDisabledColor);
-  data_source_label->SetDefaultStyle(default_style);
+  data_source_label->SetDefaultTextStyle(views::style::STYLE_DISABLED);
 
   views::StyledLabel::RangeStyleInfo link_style =
       views::StyledLabel::RangeStyleInfo::CreateForLink();
-  link_style.color = gfx::kGoogleBlue700;
+
+  // This is the harmony color, so not needed when MD is default.
+  if (ui::MaterialDesignController::IsSecondaryUiMaterial())
+    link_style.override_color = gfx::kGoogleBlue700;
+
   data_source_label->AddStyleRange(
       gfx::Range(link_begin, link_begin + link_length), link_style);
   data_source_label->SizeToFit(0);
diff --git a/chrome/browser/ui/views/payments/shipping_address_editor_view_controller.cc b/chrome/browser/ui/views/payments/shipping_address_editor_view_controller.cc
index b61cea1..010e256 100644
--- a/chrome/browser/ui/views/payments/shipping_address_editor_view_controller.cc
+++ b/chrome/browser/ui/views/payments/shipping_address_editor_view_controller.cc
@@ -22,6 +22,7 @@
 #include "components/autofill/core/browser/country_combobox_model.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/phone_number_i18n.h"
 #include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/autofill/core/common/autofill_l10n_util.h"
@@ -46,7 +47,7 @@
 // Used to normalize a profile in place and synchronously from an
 // AddressNormalizer that already loaded the normalization rules.
 class SynchronousAddressNormalizerDelegate
-    : public AddressNormalizer::Delegate {
+    : public autofill::AddressNormalizer::Delegate {
  public:
   // Doesn't take ownership of |profile_to_normalize| but does modify it.
   SynchronousAddressNormalizerDelegate(
@@ -106,7 +107,7 @@
 base::string16 ShippingAddressEditorViewController::GetInitialValueForType(
     autofill::ServerFieldType type) {
   if (type == autofill::PHONE_HOME_WHOLE_NUMBER) {
-    return data_util::GetFormattedPhoneNumberForDisplay(
+    return autofill::i18n::GetFormattedPhoneNumberForDisplay(
         temporary_profile_, state()->GetApplicationLocale());
   }
 
@@ -294,7 +295,7 @@
 ShippingAddressEditorViewController::ShippingAddressValidationDelegate::Format(
     const base::string16& text) {
   if (controller_->chosen_country_index_ < controller_->countries_.size()) {
-    return base::UTF8ToUTF16(data_util::FormatPhoneForDisplay(
+    return base::UTF8ToUTF16(autofill::i18n::FormatPhoneForDisplay(
         base::UTF16ToUTF8(text),
         controller_->countries_[controller_->chosen_country_index_].first));
   } else {
diff --git a/chrome/browser/ui/views/platform_keys_certificate_selector_chromeos.cc b/chrome/browser/ui/views/platform_keys_certificate_selector_chromeos.cc
index bd7845d8..350374f 100644
--- a/chrome/browser/ui/views/platform_keys_certificate_selector_chromeos.cc
+++ b/chrome/browser/ui/views/platform_keys_certificate_selector_chromeos.cc
@@ -13,6 +13,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/browser_dialogs.h"
+#include "chrome/browser/ui/views/harmony/chrome_typography.h"
 #include "chrome/grit/generated_resources.h"
 #include "net/ssl/client_cert_identity.h"
 #include "net/ssl/ssl_private_key.h"
@@ -85,7 +86,7 @@
       new views::StyledLabel(text, nullptr /* no listener */));
 
   views::StyledLabel::RangeStyleInfo bold_style;
-  bold_style.weight = gfx::Font::Weight::BOLD;
+  bold_style.text_style = STYLE_EMPHASIZED;
   label->AddStyleRange(gfx::Range(offset, offset + name.size()), bold_style);
   CertificateSelector::InitWithText(std::move(label));
 }
diff --git a/chrome/browser/ui/views/profiles/forced_reauthentication_dialog_view.cc b/chrome/browser/ui/views/profiles/forced_reauthentication_dialog_view.cc
index 8682a31..9bbf7f7 100644
--- a/chrome/browser/ui/views/profiles/forced_reauthentication_dialog_view.cc
+++ b/chrome/browser/ui/views/profiles/forced_reauthentication_dialog_view.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
+#include "chrome/browser/ui/views/harmony/chrome_typography.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/constrained_window/constrained_window_views.h"
@@ -174,7 +175,7 @@
   prompt_label->SetDisplayedOnBackgroundColor(prompt_bar_background_color);
 
   views::StyledLabel::RangeStyleInfo bold_style;
-  bold_style.weight = gfx::Font::Weight::BOLD;
+  bold_style.text_style = STYLE_EMPHASIZED;
   prompt_label->AddStyleRange(gfx::Range(offset, offset + domain.size()),
                               bold_style);
 
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
index 7920a6a2..b95fc52 100644
--- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -39,6 +39,7 @@
 #include "chrome/browser/ui/singleton_tabs.h"
 #include "chrome/browser/ui/user_manager.h"
 #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
+#include "chrome/browser/ui/views/harmony/chrome_typography.h"
 #include "chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.h"
 #include "chrome/browser/ui/views/profiles/user_manager_view.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
@@ -433,12 +434,9 @@
     back_button_ = CreateBackButton(listener);
     *back_button = back_button_;
 
-    title_label_ = new views::Label(message);
+    title_label_ =
+        new views::Label(message, views::style::CONTEXT_DIALOG_TITLE);
     title_label_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
-    ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
-    const gfx::FontList& medium_font_list =
-        rb->GetFontList(ui::ResourceBundle::MediumFont);
-    title_label_->SetFontList(medium_font_list);
 
     AddChildView(back_button_);
     AddChildView(title_label_);
@@ -1349,12 +1347,10 @@
                                            kMenuEdgeMargin, horizontal_margin));
 
   views::Label* disclaimer = new views::Label(
-      avatar_menu_->GetSupervisedUserInformation());
+      avatar_menu_->GetSupervisedUserInformation(), CONTEXT_DEPRECATED_SMALL);
   disclaimer->SetMultiLine(true);
   disclaimer->SetAllowCharacterBreak(true);
   disclaimer->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-  ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
-  disclaimer->SetFontList(rb->GetFontList(ui::ResourceBundle::SmallFont));
   layout->StartRow(1, 0);
   layout->AddView(disclaimer);
 
@@ -1494,9 +1490,6 @@
 
   // Adds main text.
   layout->StartRowWithPadding(1, 0, 0, unrelated_vertical_spacing);
-  ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
-  const gfx::FontList& small_font_list =
-      rb->GetFontList(ui::ResourceBundle::SmallFont);
 
   if (is_primary_account) {
     std::string email = signin_ui_util::GetDisplayEmail(browser_->profile(),
@@ -1512,14 +1505,14 @@
     primary_account_removal_label->AddStyleRange(
         gfx::Range(offsets[1], offsets[1] + settings_text.size()),
         views::StyledLabel::RangeStyleInfo::CreateForLink());
-    primary_account_removal_label->SetBaseFontList(small_font_list);
+    primary_account_removal_label->SetTextContext(CONTEXT_DEPRECATED_SMALL);
     layout->AddView(primary_account_removal_label);
   } else {
     views::Label* content_label = new views::Label(
-        l10n_util::GetStringUTF16(IDS_PROFILES_ACCOUNT_REMOVAL_TEXT));
+        l10n_util::GetStringUTF16(IDS_PROFILES_ACCOUNT_REMOVAL_TEXT),
+        CONTEXT_DEPRECATED_SMALL);
     content_label->SetMultiLine(true);
     content_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    content_label->SetFontList(small_font_list);
     layout->AddView(content_label);
   }
 
@@ -1561,17 +1554,14 @@
 
   // Adds main text.
   layout->StartRowWithPadding(1, 1, 0, unrelated_vertical_spacing);
-  ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
-  const gfx::FontList& small_font_list =
-      rb->GetFontList(ui::ResourceBundle::SmallFont);
   const AvatarMenu::Item& avatar_item =
       avatar_menu_->GetItemAt(avatar_menu_->GetActiveProfileIndex());
-  views::Label* content_label = new views::Label(
-      l10n_util::GetStringFUTF16(
-          IDS_PROFILES_NOT_YOU_CONTENT_TEXT, avatar_item.name));
+  views::Label* content_label =
+      new views::Label(l10n_util::GetStringFUTF16(
+                           IDS_PROFILES_NOT_YOU_CONTENT_TEXT, avatar_item.name),
+                       CONTEXT_DEPRECATED_SMALL);
   content_label->SetMultiLine(true);
   content_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-  content_label->SetFontList(small_font_list);
   layout->AddView(content_label);
 
   // Adds "Add person" button.
diff --git a/chrome/browser/ui/views/sad_tab_view.cc b/chrome/browser/ui/views/sad_tab_view.cc
index 493763b6..31f9933 100644
--- a/chrome/browser/ui/views/sad_tab_view.cc
+++ b/chrome/browser/ui/views/sad_tab_view.cc
@@ -10,6 +10,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "chrome/app/vector_icons/vector_icons.h"
+#include "chrome/browser/ui/views/harmony/bulleted_label_list_view.h"
 #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/harmony/chrome_typography.h"
 #include "content/public/browser/web_contents.h"
@@ -32,9 +33,6 @@
 constexpr int kMaxContentWidth = 600;
 constexpr int kMinColumnWidth = 120;
 constexpr int kTitleBottomSpacing = 13;
-constexpr int kBulletBottomSpacing = 1;
-constexpr int kBulletWidth = 20;
-constexpr int kBulletPadding = 13;
 
 views::Label* CreateFormattedLabel(const base::string16& message) {
   views::Label* label =
@@ -99,33 +97,12 @@
 
   std::vector<int> bullet_string_ids = GetSubMessages();
   if (!bullet_string_ids.empty()) {
-    const int bullet_columnset_id = 1;
-    views::ColumnSet* column_set = layout->AddColumnSet(bullet_columnset_id);
-    column_set->AddPaddingColumn(1, unrelated_horizontal_spacing);
-    column_set->AddColumn(views::GridLayout::TRAILING,
-                          views::GridLayout::LEADING, 0,
-                          views::GridLayout::FIXED, kBulletWidth, 0);
-    column_set->AddPaddingColumn(0, kBulletPadding);
-    column_set->AddColumn(views::GridLayout::LEADING,
-                          views::GridLayout::LEADING, 0,
-                          views::GridLayout::USE_PREF,
-                          0,  // No fixed width.
-                          0);
-    column_set->AddPaddingColumn(1, unrelated_horizontal_spacing);
+    auto list_view = std::make_unique<BulletedLabelListView>();
+    for (const auto& id : bullet_string_ids)
+      list_view->AddLabel(l10n_util::GetStringUTF16(id));
 
-    for (int bullet_string_id : bullet_string_ids) {
-      const base::string16 bullet_character(base::WideToUTF16(L"\u2022"));
-      views::Label* bullet_label = CreateFormattedLabel(bullet_character);
-      views::Label* label =
-          CreateFormattedLabel(l10n_util::GetStringUTF16(bullet_string_id));
-
-      layout->StartRowWithPadding(0, bullet_columnset_id, 0,
-                                  kBulletBottomSpacing);
-      layout->AddView(bullet_label);
-      layout->AddView(label);
-
-      bullet_labels_.push_back(label);
-    }
+    layout->StartRow(0, column_set_id);
+    layout->AddView(list_view.release(), 2, 1);
   }
 
   action_button_ = views::MdTextButton::CreateSecondaryUiBlueButton(
@@ -186,10 +163,6 @@
   message_->SizeToFit(max_width);
   title_->SizeToFit(max_width);
 
-  // Bullet labels need to take into account the size of the bullet.
-  for (views::Label* label : bullet_labels_)
-    label->SizeToFit(max_width - kBulletWidth - kBulletPadding);
-
   View::Layout();
 }
 
diff --git a/chrome/browser/ui/views/session_crashed_bubble_view.cc b/chrome/browser/ui/views/session_crashed_bubble_view.cc
index 223d5c6..e0097d4 100644
--- a/chrome/browser/ui/views/session_crashed_bubble_view.cc
+++ b/chrome/browser/ui/views/session_crashed_bubble_view.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/ui/browser_list_observer.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/harmony/chrome_typography.h"
 #include "chrome/browser/ui/views/toolbar/app_menu_button.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
 #include "chrome/grit/chromium_strings.h"
@@ -51,9 +52,6 @@
 // Distance between checkbox and the text to the right of it.
 const int kCheckboxTextDistance = 4;
 
-// The color of the text of the sub panel to offer UMA opt-in.
-const SkColor kTextColor = SkColorSetRGB(102, 102, 102);
-
 enum SessionCrashedBubbleHistogramValue {
   SESSION_CRASHED_BUBBLE_SHOWN,
   SESSION_CRASHED_BUBBLE_ERROR,
@@ -229,13 +227,10 @@
       link_text,
       &offset);
   views::StyledLabel* uma_label = new views::StyledLabel(uma_text, this);
-  views::StyledLabel::RangeStyleInfo link_style =
-      views::StyledLabel::RangeStyleInfo::CreateForLink();
-  link_style.font_style = gfx::Font::NORMAL;
   uma_label->AddStyleRange(gfx::Range(offset, offset + link_text.length()),
-                           link_style);
+                           views::StyledLabel::RangeStyleInfo::CreateForLink());
   views::StyledLabel::RangeStyleInfo uma_style;
-  uma_style.color = kTextColor;
+  uma_style.text_style = STYLE_SECONDARY;
   gfx::Range before_link_range(0, offset);
   if (!before_link_range.is_empty())
     uma_label->AddStyleRange(before_link_range, uma_style);
diff --git a/chrome/browser/ui/views/settings_reset_prompt_dialog.cc b/chrome/browser/ui/views/settings_reset_prompt_dialog.cc
index 04f0844..cfd0bfb 100644
--- a/chrome/browser/ui/views/settings_reset_prompt_dialog.cc
+++ b/chrome/browser/ui/views/settings_reset_prompt_dialog.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
+#include "chrome/browser/ui/views/harmony/chrome_typography.h"
 #include "components/constrained_window/constrained_window_views.h"
 #include "ui/gfx/font.h"
 #include "ui/gfx/geometry/insets.h"
@@ -47,7 +48,7 @@
   views::StyledLabel* dialog_label =
       new views::StyledLabel(controller_->GetMainText(), /*listener=*/nullptr);
   views::StyledLabel::RangeStyleInfo url_style;
-  url_style.weight = gfx::Font::Weight::BOLD;
+  url_style.text_style = STYLE_EMPHASIZED;
   dialog_label->AddStyleRange(controller_->GetMainTextUrlRange(), url_style);
   AddChildView(dialog_label);
 }
diff --git a/chrome/browser/ui/views/subtle_notification_view.cc b/chrome/browser/ui/views/subtle_notification_view.cc
index f1fde2c..95e3306 100644
--- a/chrome/browser/ui/views/subtle_notification_view.cc
+++ b/chrome/browser/ui/views/subtle_notification_view.cc
@@ -152,11 +152,9 @@
   instruction_view_ =
       new InstructionView(base::string16(), kForegroundColor, kBackgroundColor);
 
-  link_ = new views::Link();
+  link_ = new views::Link(base::string16(), kInstructionTextContext);
   link_->SetFocusBehavior(FocusBehavior::NEVER);
   link_->set_listener(link_listener);
-  link_->SetFontList(
-      views::style::GetFont(kInstructionTextContext, views::style::STYLE_LINK));
   link_->SetEnabledColor(kForegroundColor);  // Override STYLE_LINK.
   link_->SetBackgroundColor(kBackgroundColor);
   link_->SetVisible(false);
diff --git a/chrome/browser/ui/views/sync/bubble_sync_promo_view.cc b/chrome/browser/ui/views/sync/bubble_sync_promo_view.cc
index 36e8012..bcaeffa 100644
--- a/chrome/browser/ui/views/sync/bubble_sync_promo_view.cc
+++ b/chrome/browser/ui/views/sync/bubble_sync_promo_view.cc
@@ -8,19 +8,13 @@
 
 #include "base/strings/string16.h"
 #include "chrome/browser/ui/sync/bubble_sync_promo_delegate.h"
+#include "chrome/browser/ui/views/harmony/chrome_typography.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/font.h"
 #include "ui/views/controls/styled_label.h"
 #include "ui/views/layout/fill_layout.h"
 
-namespace {
-
-// Color of the text of the promo.
-const SkColor kTextColor = SkColorSetRGB(102, 102, 102);
-
-}  // namespace
-
 BubbleSyncPromoView::BubbleSyncPromoView(BubbleSyncPromoDelegate* delegate,
                                          int link_text_resource_id,
                                          int message_text_resource_id)
@@ -31,13 +25,11 @@
       l10n_util::GetStringFUTF16(message_text_resource_id, link_text, &offset);
   SetText(promo_text);
 
-  views::StyledLabel::RangeStyleInfo link_style =
-      views::StyledLabel::RangeStyleInfo::CreateForLink();
-  link_style.font_style = gfx::Font::NORMAL;
-  AddStyleRange(gfx::Range(offset, offset + link_text.length()), link_style);
+  AddStyleRange(gfx::Range(offset, offset + link_text.length()),
+                views::StyledLabel::RangeStyleInfo::CreateForLink());
 
   views::StyledLabel::RangeStyleInfo promo_style;
-  promo_style.color = kTextColor;
+  promo_style.text_style = STYLE_SECONDARY;
   gfx::Range before_link_range(0, offset);
   if (!before_link_range.is_empty())
     AddStyleRange(before_link_range, promo_style);
diff --git a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
index 09346b7..00482758 100644
--- a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
+++ b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
+#include "chrome/browser/ui/views/harmony/chrome_typography.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/constrained_window/constrained_window_views.h"
@@ -169,7 +170,7 @@
   prompt_label->SetDisplayedOnBackgroundColor(kPromptBarBackgroundColor);
 
   views::StyledLabel::RangeStyleInfo bold_style;
-  bold_style.weight = gfx::Font::Weight::BOLD;
+  bold_style.text_style = STYLE_EMPHASIZED;
   prompt_label->AddStyleRange(
       gfx::Range(offset, offset + domain.size()), bold_style);
 
diff --git a/chrome/browser/ui/webui/app_launcher_page_ui.cc b/chrome/browser/ui/webui/app_launcher_page_ui.cc
index e5d3e53d..a186130c 100644
--- a/chrome/browser/ui/webui/app_launcher_page_ui.cc
+++ b/chrome/browser/ui/webui/app_launcher_page_ui.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/webui/app_launcher_page_ui.h"
 
+#include <memory>
 #include <string>
 
 #include "base/memory/ptr_util.h"
@@ -22,6 +23,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
@@ -109,7 +111,7 @@
 
   content::WebContents* web_contents = wc_getter.Run();
   content::RenderProcessHost* render_host =
-      web_contents ? web_contents->GetRenderProcessHost() : nullptr;
+      web_contents ? web_contents->GetMainFrame()->GetProcess() : nullptr;
   NTPResourceCache::WindowType win_type = NTPResourceCache::GetWindowType(
       profile_, render_host);
   scoped_refptr<base::RefCountedMemory> html_bytes(
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
index 8c2c588..83f882e 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -362,25 +362,8 @@
 
   params.SetString("gaiaUrl", GaiaUrls::GetInstance()->gaia_url().spec());
 
-  if (use_easy_bootstrap_) {
-    params.SetBoolean("useEafe", true);
-    // Easy login overrides.
-    std::string eafe_url = "https://easylogin.corp.google.com/";
-    base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-    if (command_line->HasSwitch(switches::kEafeUrl))
-      eafe_url = command_line->GetSwitchValueASCII(switches::kEafeUrl);
-    std::string eafe_path = "planters/cbaudioChrome";
-    if (command_line->HasSwitch(switches::kEafePath))
-      eafe_path = command_line->GetSwitchValueASCII(switches::kEafePath);
-
-    params.SetString("gaiaUrl", eafe_url);
-    params.SetString("gaiaPath", eafe_path);
-  }
-
-  // Easy bootstrap is not v2-compatible
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kCrosGaiaApiV1) ||
-      use_easy_bootstrap_) {
+          switches::kCrosGaiaApiV1)) {
     params.SetString("chromeOSApiVersion", "1");
   } else {
     // This enables GLIF MM UI for the online Gaia screen by default.
@@ -489,16 +472,12 @@
   AddCallback("completeLogin", &GaiaScreenHandler::HandleCompleteLogin);
   AddCallback("completeAuthentication",
               &GaiaScreenHandler::HandleCompleteAuthentication);
-  AddCallback("completeAuthenticationAuthCodeOnly",
-              &GaiaScreenHandler::HandleCompleteAuthenticationAuthCodeOnly);
   AddCallback("usingSAMLAPI", &GaiaScreenHandler::HandleUsingSAMLAPI);
   AddCallback("scrapedPasswordCount",
               &GaiaScreenHandler::HandleScrapedPasswordCount);
   AddCallback("scrapedPasswordVerificationFailed",
               &GaiaScreenHandler::HandleScrapedPasswordVerificationFailed);
   AddCallback("loginWebuiReady", &GaiaScreenHandler::HandleGaiaUIReady);
-  AddCallback("toggleEasyBootstrap",
-              &GaiaScreenHandler::HandleToggleEasyBootstrap);
   AddCallback("identifierEntered", &GaiaScreenHandler::HandleIdentifierEntered);
   AddCallback("updateOfflineLogin",
               &GaiaScreenHandler::set_offline_login_is_active);
@@ -681,17 +660,6 @@
   Delegate()->CompleteLogin(user_context);
 }
 
-void GaiaScreenHandler::HandleCompleteAuthenticationAuthCodeOnly(
-    const std::string& auth_code) {
-  if (!Delegate())
-    return;
-
-  UserContext user_context;
-  user_context.SetAuthFlow(UserContext::AUTH_FLOW_EASY_BOOTSTRAP);
-  user_context.SetAuthCode(auth_code);
-  Delegate()->CompleteLogin(user_context);
-}
-
 void GaiaScreenHandler::HandleCompleteLogin(const std::string& gaia_id,
                                             const std::string& typed_email,
                                             const std::string& password,
@@ -717,11 +685,6 @@
   RecordSAMLScrapingVerificationResultInHistogram(false);
 }
 
-void GaiaScreenHandler::HandleToggleEasyBootstrap() {
-  use_easy_bootstrap_ = !use_easy_bootstrap_;
-  LoadAuthExtension(true /* force */, false /* offline */);
-}
-
 void GaiaScreenHandler::HandleGaiaUIReady() {
   VLOG(1) << "Gaia is loaded";
 
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
index b4a5a226..2cda506d 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
@@ -95,7 +95,6 @@
                                     const std::string& auth_code,
                                     bool using_saml,
                                     const std::string& gaps_cookie);
-  void HandleCompleteAuthenticationAuthCodeOnly(const std::string& auth_code);
   void HandleCompleteLogin(const std::string& gaia_id,
                            const std::string& typed_email,
                            const std::string& password,
@@ -112,8 +111,6 @@
 
   void HandleGaiaUIReady();
 
-  void HandleToggleEasyBootstrap();
-
   void HandleIdentifierEntered(const std::string& account_identifier);
 
   void HandleAuthExtensionLoaded();
@@ -248,9 +245,6 @@
   std::string test_pass_;
   bool test_expects_complete_login_ = false;
 
-  // True if Easy bootstrap is enabled.
-  bool use_easy_bootstrap_ = false;
-
   // True if proxy doesn't allow access to google.com/generate_204.
   NetworkPortalDetector::CaptivePortalStatus captive_portal_status_ =
       NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE;
diff --git a/chrome/browser/ui/webui/chromeos/login/supervised_user_creation_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/supervised_user_creation_screen_handler.cc
index 6bb1525..a6db11fe 100644
--- a/chrome/browser/ui/webui/chromeos/login/supervised_user_creation_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/supervised_user_creation_screen_handler.cc
@@ -155,11 +155,6 @@
   // It should be removed by issue 251179.
   builder->Add("takePhoto", IDS_OPTIONS_CHANGE_PICTURE_TAKE_PHOTO);
   builder->Add("discardPhoto", IDS_OPTIONS_CHANGE_PICTURE_DISCARD_PHOTO);
-  builder->Add("flipPhoto", IDS_OPTIONS_CHANGE_PICTURE_FLIP_PHOTO);
-  builder->Add("photoFlippedAccessibleText",
-               IDS_OPTIONS_PHOTO_FLIP_ACCESSIBLE_TEXT);
-  builder->Add("photoFlippedBackAccessibleText",
-               IDS_OPTIONS_PHOTO_FLIPBACK_ACCESSIBLE_TEXT);
   builder->Add("photoCaptureAccessibleText",
                IDS_OPTIONS_PHOTO_CAPTURE_ACCESSIBLE_TEXT);
   builder->Add("photoDiscardAccessibleText",
diff --git a/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc
index 8f34f6a7..381c59b 100644
--- a/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc
@@ -94,7 +94,7 @@
                IDS_USER_IMAGE_SCREEN_DESCRIPTION);
   builder->Add("takePhoto", IDS_OPTIONS_CHANGE_PICTURE_TAKE_PHOTO);
   builder->Add("discardPhoto", IDS_OPTIONS_CHANGE_PICTURE_DISCARD_PHOTO);
-  builder->Add("flipPhoto", IDS_OPTIONS_CHANGE_PICTURE_FLIP_PHOTO);
+  builder->Add("switchMode", IDS_OPTIONS_CHANGE_PICTURE_SWITCH_MODE);
   builder->Add("profilePhoto", IDS_IMAGE_SCREEN_PROFILE_PHOTO);
   builder->Add("profilePhotoLoading",
                IDS_IMAGE_SCREEN_PROFILE_LOADING_PHOTO);
diff --git a/chrome/browser/ui/webui/devtools_ui.cc b/chrome/browser/ui/webui/devtools_ui.cc
index 5ae56ba58..54c2a5d5 100644
--- a/chrome/browser/ui/webui/devtools_ui.cc
+++ b/chrome/browser/ui/webui/devtools_ui.cc
@@ -150,6 +150,14 @@
     return;
   }
 
+  // Serve empty page.
+  std::string empty_path_prefix(chrome::kChromeUIDevToolsBlankPath);
+  if (base::StartsWith(path, empty_path_prefix,
+                       base::CompareCase::INSENSITIVE_ASCII)) {
+    callback.Run(new base::RefCountedStaticMemory());
+    return;
+  }
+
   // Serve request from remote location.
   std::string remote_path_prefix(chrome::kChromeUIDevToolsRemotePath);
   remote_path_prefix += "/";
diff --git a/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chrome/browser/ui/webui/extensions/extensions_ui.cc
index 009d70ab..5fc251c7 100644
--- a/chrome/browser/ui/webui/extensions/extensions_ui.cc
+++ b/chrome/browser/ui/webui/extensions/extensions_ui.cc
@@ -108,9 +108,12 @@
   source->SetJsonPath("strings.js");
 
   // Add common strings.
-  source->AddLocalizedString("close", IDS_CLOSE);
-  source->AddLocalizedString("ok", IDS_OK);
+  source->AddLocalizedString("add", IDS_ADD);
   source->AddLocalizedString("cancel", IDS_CANCEL);
+  source->AddLocalizedString("close", IDS_CLOSE);
+  source->AddLocalizedString("confirm", IDS_CONFIRM);
+  source->AddLocalizedString("done", IDS_DONE);
+  source->AddLocalizedString("ok", IDS_OK);
 
   // Add extension-specific strings.
   source->AddLocalizedString("title",
@@ -253,6 +256,32 @@
                              IDS_EXTENSIONS_VIEW_INACTIVE);
   source->AddLocalizedString("viewIframe",
                              IDS_EXTENSIONS_VIEW_IFRAME);
+#if defined(OS_CHROMEOS)
+  source->AddLocalizedString("manageKioskApp",
+                             IDS_MD_EXTENSIONS_MANAGE_KIOSK_APP);
+  source->AddLocalizedString("kioskAddApp", IDS_MD_EXTENSIONS_KIOSK_ADD_APP);
+  source->AddLocalizedString("kioskAddAppHint",
+                             IDS_MD_EXTENSIONS_KIOSK_ADD_APP_HINT);
+  source->AddLocalizedString("kioskEnableAutoLaunch",
+                             IDS_MD_EXTENSIONS_KIOSK_ENABLE_AUTO_LAUNCH);
+  source->AddLocalizedString("kioskDisableAutoLaunch",
+                             IDS_MD_EXTENSIONS_KIOSK_DISABLE_AUTO_LAUNCH);
+  source->AddLocalizedString("kioskAutoLaunch",
+                             IDS_MD_EXTENSIONS_KIOSK_AUTO_LAUNCH);
+  source->AddLocalizedString("kioskInvalidApp",
+                             IDS_MD_EXTENSIONS_KIOSK_INVALID_APP);
+  source->AddLocalizedString(
+      "kioskDisableBailout",
+      IDS_MD_EXTENSIONS_KIOSK_DISABLE_BAILOUT_SHORTCUT_LABEL);
+  source->AddLocalizedString(
+      "kioskDisableBailoutWarningTitle",
+      IDS_MD_EXTENSIONS_KIOSK_DISABLE_BAILOUT_SHORTCUT_WARNING_TITLE);
+  source->AddString(
+      "kioskDisableBailoutWarningBody",
+      l10n_util::GetStringFUTF16(
+          IDS_MD_EXTENSIONS_KIOSK_DISABLE_BAILOUT_SHORTCUT_WARNING_BODY,
+          l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_OS_NAME)));
+#endif
   source->AddString(
       "getMoreExtensionsUrl",
       base::ASCIIToUTF16(
@@ -280,6 +309,15 @@
                           IDR_MD_EXTENSIONS_KEYBOARD_SHORTCUTS_HTML);
   source->AddResourcePath("keyboard_shortcuts.js",
                           IDR_MD_EXTENSIONS_KEYBOARD_SHORTCUTS_JS);
+#if defined(OS_CHROMEOS)
+  source->AddResourcePath("kiosk_browser_proxy.html",
+                          IDR_MD_EXTENSIONS_KIOSK_BROWSER_PROXY_HTML);
+  source->AddResourcePath("kiosk_browser_proxy.js",
+                          IDR_MD_EXTENSIONS_KIOSK_BROWSER_PROXY_JS);
+  source->AddResourcePath("kiosk_dialog.html",
+                          IDR_MD_EXTENSIONS_KIOSK_DIALOG_HTML);
+  source->AddResourcePath("kiosk_dialog.js", IDR_MD_EXTENSIONS_KIOSK_DIALOG_JS);
+#endif
   source->AddResourcePath("manager.html", IDR_MD_EXTENSIONS_MANAGER_HTML);
   source->AddResourcePath("manager.js", IDR_MD_EXTENSIONS_MANAGER_JS);
   source->AddResourcePath("icons.html", IDR_MD_EXTENSIONS_ICONS_HTML);
@@ -380,18 +418,18 @@
     web_ui->AddMessageHandler(std::move(install_extension_handler));
     install_handler->GetLocalizedValues(source);
 
-#if defined(OS_CHROMEOS)
-    auto kiosk_app_handler = base::MakeUnique<chromeos::KioskAppsHandler>(
-        chromeos::OwnerSettingsServiceChromeOSFactory::GetForBrowserContext(
-            profile));
-    chromeos::KioskAppsHandler* kiosk_handler = kiosk_app_handler.get();
-    web_ui->AddMessageHandler(std::move(kiosk_app_handler));
-    kiosk_handler->GetLocalizedValues(source);
-#endif
-
     web_ui->AddMessageHandler(base::MakeUnique<MetricsHandler>());
   }
 
+#if defined(OS_CHROMEOS)
+  auto kiosk_app_handler = base::MakeUnique<chromeos::KioskAppsHandler>(
+      chromeos::OwnerSettingsServiceChromeOSFactory::GetForBrowserContext(
+          profile));
+  chromeos::KioskAppsHandler* kiosk_handler = kiosk_app_handler.get();
+  web_ui->AddMessageHandler(std::move(kiosk_app_handler));
+  kiosk_handler->GetLocalizedValues(source);
+#endif
+
   // Need to allow <object> elements so that the <extensionoptions> browser
   // plugin can be loaded within chrome://extensions.
   source->OverrideContentSecurityPolicyObjectSrc("object-src 'self';");
diff --git a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
index 9567b08b..97e6fa5 100644
--- a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
+++ b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/webui/interstitials/interstitial_ui.h"
 
+#include <memory>
+
 #include "base/atomic_sequence_num.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
@@ -283,9 +285,9 @@
   resource.is_subframe = false;
   resource.threat_type = threat_type;
   resource.web_contents_getter =
-      security_interstitials::UnsafeResource::
-          GetWebContentsGetter(web_contents->GetRenderProcessHost()->GetID(),
-                               web_contents->GetMainFrame()->GetRoutingID());
+      security_interstitials::UnsafeResource::GetWebContentsGetter(
+          web_contents->GetMainFrame()->GetProcess()->GetID(),
+          web_contents->GetMainFrame()->GetRoutingID());
   resource.threat_source = g_browser_process->safe_browsing_service()
                                ->database_manager()
                                ->GetThreatSource();
@@ -332,7 +334,7 @@
   resource.threat_type = threat_type;
   resource.web_contents_getter =
       security_interstitials::UnsafeResource::GetWebContentsGetter(
-          web_contents->GetRenderProcessHost()->GetID(),
+          web_contents->GetMainFrame()->GetProcess()->GetID(),
           web_contents->GetMainFrame()->GetRoutingID());
   resource.threat_source = g_browser_process->safe_browsing_service()
                                ->database_manager()
@@ -393,7 +395,7 @@
 }
 #endif
 
-} //  namespace
+}  //  namespace
 
 InterstitialUI::InterstitialUI(content::WebUI* web_ui)
     : WebUIController(web_ui) {
diff --git a/chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom b/chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom
index 5937eb9..484839b6 100644
--- a/chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom
+++ b/chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom
@@ -4,8 +4,14 @@
 
 module mojom;
 
+struct PreviewsStatus {
+  // The human readable description of the status that will be displayed on
+  // chrome://interventions-internals.
+  string description;
+  bool enabled;
+};
+
 interface InterventionsInternalsPageHandler {
-  // Send a message showing if previews is enabled or disabled.
-  // Returns true if previews is enabled, and false otherwise.
-  GetPreviewsEnabled() => (bool enabled);
+  // Returns a map of previews modes statuses.
+  GetPreviewsEnabled() => (map<string, PreviewsStatus> statuses);
 };
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 e6614d7..c9b37b2 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
@@ -4,8 +4,24 @@
 
 #include "chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.h"
 
+#include <unordered_map>
+
 #include "components/previews/core/previews_experiments.h"
 
+namespace {
+
+// Key for status mapping.
+const char kAmpRedirectionPreviews[] = "ampPreviews";
+const char kClientLoFiPreviews[] = "clientLoFiPreviews";
+const char kOfflinePreviews[] = "offlinePreviews";
+
+// Description for statuses.
+const char kAmpRedirectionDescription[] = "AMP Previews";
+const char kClientLoFiDescription[] = "Client LoFi Previews";
+const char kOfflineDesciption[] = "Offline Previews";
+
+}  // namespace
+
 InterventionsInternalsPageHandler::InterventionsInternalsPageHandler(
     mojom::InterventionsInternalsPageHandlerRequest request)
     : binding_(this, std::move(request)) {}
@@ -14,9 +30,22 @@
 
 void InterventionsInternalsPageHandler::GetPreviewsEnabled(
     GetPreviewsEnabledCallback callback) {
-  // TODO(thanhdle): change enable to a dictionary with all previews mode
-  // status.
-  bool enabled = previews::params::IsOfflinePreviewsEnabled();
+  std::unordered_map<std::string, mojom::PreviewsStatusPtr> statuses;
 
-  std::move(callback).Run(enabled);
+  auto amp_status = mojom::PreviewsStatus::New();
+  amp_status->description = kAmpRedirectionDescription;
+  amp_status->enabled = previews::params::IsAMPRedirectionPreviewEnabled();
+  statuses[kAmpRedirectionPreviews] = std::move(amp_status);
+
+  auto client_lofi_status = mojom::PreviewsStatus::New();
+  client_lofi_status->description = kClientLoFiDescription;
+  client_lofi_status->enabled = previews::params::IsClientLoFiEnabled();
+  statuses[kClientLoFiPreviews] = std::move(client_lofi_status);
+
+  auto offline_status = mojom::PreviewsStatus::New();
+  offline_status->description = kOfflineDesciption;
+  offline_status->enabled = previews::params::IsOfflinePreviewsEnabled();
+  statuses[kOfflinePreviews] = std::move(offline_status);
+
+  std::move(callback).Run(std::move(statuses));
 }
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
new file mode 100644
index 0000000..8e8efe3d
--- /dev/null
+++ b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc
@@ -0,0 +1,146 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.h"
+
+#include <unordered_map>
+
+#include "base/macros.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/scoped_task_environment.h"
+#include "chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom.h"
+#include "components/previews/core/previews_features.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+// The key for the mapping for the enabled/disabled status map.
+constexpr char kAMPRedirectionPreviews[] = "ampPreviews";
+constexpr char kClientLoFiPreviews[] = "clientLoFiPreviews";
+constexpr char kOfflinePreviews[] = "offlinePreviews";
+
+// Description for statuses.
+constexpr char kAmpRedirectionDescription[] = "AMP Previews";
+constexpr char kClientLoFiDescription[] = "Client LoFi Previews";
+constexpr char kOfflineDesciption[] = "Offline Previews";
+
+std::unordered_map<std::string, mojom::PreviewsStatusPtr> passedInParams;
+
+void MockGetPreviewsEnabledCallback(
+    std::unordered_map<std::string, mojom::PreviewsStatusPtr> params) {
+  passedInParams = std::move(params);
+}
+
+}  // namespace
+
+class InterventionsInternalsPageHandlerTest : public testing::Test {
+ public:
+  InterventionsInternalsPageHandlerTest()
+      : scoped_task_environment_(
+            base::test::ScopedTaskEnvironment::MainThreadType::IO) {}
+
+  ~InterventionsInternalsPageHandlerTest() override {}
+
+  void SetUp() override {
+    scoped_task_environment_.RunUntilIdle();
+
+    request = mojo::MakeRequest(&pageHandlerPtr);
+    pageHandler.reset(
+        new InterventionsInternalsPageHandler(std::move(request)));
+
+    scoped_feature_list_ = base::MakeUnique<base::test::ScopedFeatureList>();
+  }
+
+ protected:
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  mojom::InterventionsInternalsPageHandlerPtr pageHandlerPtr;
+  mojom::InterventionsInternalsPageHandlerRequest request;
+  std::unique_ptr<InterventionsInternalsPageHandler> pageHandler;
+  std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_;
+};
+
+TEST_F(InterventionsInternalsPageHandlerTest, CorrectSizeOfPassingParameters) {
+  pageHandler->GetPreviewsEnabled(
+      base::BindOnce(&MockGetPreviewsEnabledCallback));
+
+  constexpr size_t expected = 3;
+  EXPECT_EQ(expected, passedInParams.size());
+}
+
+TEST_F(InterventionsInternalsPageHandlerTest, AMPRedirectionDisabled) {
+  // Init with kAMPRedirection disabled.
+  scoped_feature_list_->InitWithFeatures({},
+                                         {previews::features::kAMPRedirection});
+
+  pageHandler->GetPreviewsEnabled(
+      base::BindOnce(&MockGetPreviewsEnabledCallback));
+  auto amp_redirection = passedInParams.find(kAMPRedirectionPreviews);
+  ASSERT_NE(passedInParams.end(), amp_redirection);
+  EXPECT_EQ(kAmpRedirectionDescription, amp_redirection->second->description);
+  EXPECT_FALSE(amp_redirection->second->enabled);
+}
+
+TEST_F(InterventionsInternalsPageHandlerTest, AMPRedirectionEnabled) {
+  // Init with kAMPRedirection enabled.
+  scoped_feature_list_->InitWithFeatures({previews::features::kAMPRedirection},
+                                         {});
+
+  pageHandler->GetPreviewsEnabled(
+      base::BindOnce(&MockGetPreviewsEnabledCallback));
+  auto amp_redirection = passedInParams.find(kAMPRedirectionPreviews);
+  ASSERT_NE(passedInParams.end(), amp_redirection);
+  EXPECT_EQ(kAmpRedirectionDescription, amp_redirection->second->description);
+  EXPECT_TRUE(amp_redirection->second->enabled);
+}
+
+TEST_F(InterventionsInternalsPageHandlerTest, ClientLoFiDisabled) {
+  // Init with kClientLoFi disabled.
+  scoped_feature_list_->InitWithFeatures({}, {previews::features::kClientLoFi});
+
+  pageHandler->GetPreviewsEnabled(
+      base::BindOnce(&MockGetPreviewsEnabledCallback));
+  auto client_lofi = passedInParams.find(kClientLoFiPreviews);
+  ASSERT_NE(passedInParams.end(), client_lofi);
+  EXPECT_EQ(kClientLoFiDescription, client_lofi->second->description);
+  EXPECT_FALSE(client_lofi->second->enabled);
+}
+
+TEST_F(InterventionsInternalsPageHandlerTest, ClientLoFiEnabled) {
+  // Init with kClientLoFi enabled.
+  scoped_feature_list_->InitWithFeatures({previews::features::kClientLoFi}, {});
+
+  pageHandler->GetPreviewsEnabled(
+      base::BindOnce(&MockGetPreviewsEnabledCallback));
+  auto client_lofi = passedInParams.find(kClientLoFiPreviews);
+  ASSERT_NE(passedInParams.end(), client_lofi);
+  EXPECT_EQ(kClientLoFiDescription, client_lofi->second->description);
+  EXPECT_TRUE(client_lofi->second->enabled);
+}
+
+TEST_F(InterventionsInternalsPageHandlerTest, OfflinePreviewsDisabled) {
+  // Init with kOfflinePreviews disabled.
+  scoped_feature_list_->InitWithFeatures(
+      {}, {previews::features::kOfflinePreviews});
+
+  pageHandler->GetPreviewsEnabled(
+      base::BindOnce(&MockGetPreviewsEnabledCallback));
+  auto offline_previews = passedInParams.find(kOfflinePreviews);
+  ASSERT_NE(passedInParams.end(), offline_previews);
+  EXPECT_EQ(kOfflineDesciption, offline_previews->second->description);
+  EXPECT_FALSE(offline_previews->second->enabled);
+}
+
+TEST_F(InterventionsInternalsPageHandlerTest, OfflinePreviewsEnabled) {
+  // Init with kOfflinePreviews enabled.
+  scoped_feature_list_->InitWithFeatures({previews::features::kOfflinePreviews},
+                                         {});
+
+  pageHandler->GetPreviewsEnabled(
+      base::BindOnce(&MockGetPreviewsEnabledCallback));
+  auto offline_previews = passedInParams.find(kOfflinePreviews);
+  ASSERT_NE(passedInParams.end(), offline_previews);
+  EXPECT_TRUE(offline_previews->second);
+  EXPECT_EQ(kOfflineDesciption, offline_previews->second->description);
+  EXPECT_TRUE(offline_previews->second->enabled);
+}
diff --git a/chrome/browser/ui/webui/ntp/new_tab_ui.cc b/chrome/browser/ui/webui/ntp/new_tab_ui.cc
index fbd429bc..02aed5c 100644
--- a/chrome/browser/ui/webui/ntp/new_tab_ui.cc
+++ b/chrome/browser/ui/webui/ntp/new_tab_ui.cc
@@ -24,6 +24,7 @@
 #include "components/prefs/pref_service.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
@@ -169,7 +170,7 @@
 
   content::WebContents* web_contents = wc_getter.Run();
   content::RenderProcessHost* render_host =
-      web_contents ? web_contents->GetRenderProcessHost() : nullptr;
+      web_contents ? web_contents->GetMainFrame()->GetProcess() : nullptr;
   NTPResourceCache::WindowType win_type = NTPResourceCache::GetWindowType(
       profile_, render_host);
   scoped_refptr<base::RefCountedMemory> html_bytes(
diff --git a/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc b/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc
index 5869704..ca0065e9 100644
--- a/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc
@@ -11,8 +11,10 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/values.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/webui/policy_tool_ui_handler.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -32,6 +34,9 @@
   void SetUp() override;
 
   base::FilePath GetSessionsDir();
+  base::FilePath::StringType GetDefaultSessionName();
+  base::FilePath::StringType GetSessionExtension();
+  base::FilePath GetSessionPath(const base::FilePath::StringType& session_name);
 
   void LoadSession(const std::string& session_name);
 
@@ -48,7 +53,22 @@
   base::FilePath profile_dir;
   EXPECT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &profile_dir));
   return profile_dir.AppendASCII(TestingProfile::kTestUserProfileDir)
-      .Append(FILE_PATH_LITERAL("Policy sessions"));
+      .Append(PolicyToolUIHandler::kPolicyToolSessionsDir);
+}
+
+base::FilePath::StringType PolicyToolUITest::GetDefaultSessionName() {
+  return PolicyToolUIHandler::kPolicyToolDefaultSessionName;
+}
+
+base::FilePath::StringType PolicyToolUITest::GetSessionExtension() {
+  return PolicyToolUIHandler::kPolicyToolSessionExtension;
+}
+
+base::FilePath PolicyToolUITest::GetSessionPath(
+    const base::FilePath::StringType& session_name) {
+  return GetSessionsDir()
+      .Append(session_name)
+      .AddExtension(GetSessionExtension());
 }
 
 PolicyToolUITest::PolicyToolUITest() {}
@@ -116,38 +136,31 @@
 }
 
 IN_PROC_BROWSER_TEST_F(PolicyToolUITest, CreatingSessionFiles) {
-  base::ThreadRestrictions::ScopedAllowIO allow_io;
+  base::ScopedAllowBlockingForTesting allow_blocking;
   // Check that the directory is not created yet.
   EXPECT_FALSE(PathExists(GetSessionsDir()));
 
   ui_test_utils::NavigateToURL(browser(), GURL("chrome://policy-tool"));
 
-  const base::FilePath default_session_path =
-      GetSessionsDir().Append(FILE_PATH_LITERAL("policy.json"));
   // Check that the default session file was created.
-  EXPECT_TRUE(PathExists(default_session_path));
+  EXPECT_TRUE(PathExists(GetSessionPath(GetDefaultSessionName())));
 
   // Check that when moving to a different session the corresponding file is
   // created.
   LoadSession("test_creating_sessions");
-
-  const base::FilePath test_session_path =
-      GetSessionsDir().Append(FILE_PATH_LITERAL("test_creating_sessions.json"));
-  EXPECT_TRUE(PathExists(test_session_path));
+  EXPECT_TRUE(
+      PathExists(GetSessionPath(FILE_PATH_LITERAL("test_creating_sessions"))));
 
   // Check that unicode characters are valid for the session name.
   LoadSession("сессия");
-
-  const base::FilePath russian_session_path =
-      GetSessionsDir().Append(FILE_PATH_LITERAL("сессия.json"));
-  EXPECT_TRUE(PathExists(russian_session_path));
+  EXPECT_TRUE(PathExists(GetSessionPath(FILE_PATH_LITERAL("сессия"))));
 }
 
 IN_PROC_BROWSER_TEST_F(PolicyToolUITest, ImportingSession) {
   ui_test_utils::NavigateToURL(browser(), GURL("chrome://policy-tool"));
 
   // Set up policy values and put them in the session file.
-  base::ThreadRestrictions::ScopedAllowIO allow_io;
+  base::ScopedAllowBlockingForTesting allow_blocking;
   base::DictionaryValue test_policies;
   // Add a known chrome policy.
   test_policies.SetString("chromePolicies.AllowDinosaurEasterEgg.value",
@@ -158,9 +171,8 @@
   std::string json;
   base::JSONWriter::WriteWithOptions(
       test_policies, base::JSONWriter::Options::OPTIONS_PRETTY_PRINT, &json);
-  base::WriteFile(
-      GetSessionsDir().Append(FILE_PATH_LITERAL("test_session.json")),
-      json.c_str(), json.size());
+  base::WriteFile(GetSessionPath(FILE_PATH_LITERAL("test_session")),
+                  json.c_str(), json.size());
 
   // Import the created session and wait until all the tasks are finished.
   LoadSession("test_session");
@@ -198,11 +210,10 @@
   EXPECT_EQ(expected, *values);
 
   // Check if the session file is correct.
-  base::ThreadRestrictions::ScopedAllowIO allow_io;
+  base::ScopedAllowBlockingForTesting allow_blocking;
   std::string file_contents;
-  base::ReadFileToString(
-      GetSessionsDir().Append(FILE_PATH_LITERAL("policy.json")),
-      &file_contents);
+  base::ReadFileToString(GetSessionPath(GetDefaultSessionName()),
+                         &file_contents);
   values = base::JSONReader::Read(file_contents);
   expected.SetDictionary("extensionPolicies",
                          base::MakeUnique<base::DictionaryValue>());
@@ -230,18 +241,72 @@
 
 IN_PROC_BROWSER_TEST_F(PolicyToolUITest, InvalidJson) {
   ui_test_utils::NavigateToURL(browser(), GURL("chrome://policy-tool"));
-  base::ThreadRestrictions::ScopedAllowIO allow_io;
-  base::WriteFile(
-      GetSessionsDir().Append(FILE_PATH_LITERAL("test_session.json")), "{", 1);
+  base::ScopedAllowBlockingForTesting allow_blocking;
+  base::WriteFile(GetSessionPath(FILE_PATH_LITERAL("test_session")), "{", 1);
   LoadSessionAndWaitForAlert("test_session");
 }
 
 IN_PROC_BROWSER_TEST_F(PolicyToolUITest, UnableToCreateDirectoryOrFile) {
   ui_test_utils::NavigateToURL(browser(), GURL("chrome://policy-tool"));
-  base::ThreadRestrictions::ScopedAllowIO allow_io;
+  base::ScopedAllowBlockingForTesting allow_blocking;
   base::DeleteFile(GetSessionsDir(), true);
   base::File not_directory(GetSessionsDir(), base::File::Flags::FLAG_CREATE |
                                                  base::File::Flags::FLAG_WRITE);
   not_directory.Close();
   LoadSessionAndWaitForAlert("test_session");
 }
+
+IN_PROC_BROWSER_TEST_F(PolicyToolUITest, DefaultSession) {
+  // Navigate to the tool to make sure the sessions directory is created.
+  ui_test_utils::NavigateToURL(browser(), GURL("chrome://policy-tool"));
+
+  // Check that if there are no sessions, a session with default name is
+  // created.
+  base::ScopedAllowBlockingForTesting allow_blocking;
+  EXPECT_TRUE(base::PathExists(GetSessionPath(GetDefaultSessionName())));
+
+  // Create a session file and load it.
+  base::DictionaryValue expected;
+  expected.SetString("chromePolicies.SessionName.value", "session");
+  std::string file_contents;
+  base::JSONWriter::Write(expected, &file_contents);
+
+  base::WriteFile(GetSessionPath(FILE_PATH_LITERAL("session")),
+                  file_contents.c_str(), file_contents.size());
+  LoadSession("session");
+  std::unique_ptr<base::DictionaryValue> values = ExtractPolicyValues(false);
+  EXPECT_EQ(expected, *values);
+
+  // Open the tool in a new tab and check that it loads the newly created
+  // session (which is the last used session) and not the default session.
+  chrome::NewTab(browser());
+  ui_test_utils::NavigateToURL(browser(), GURL("chrome://policy-tool"));
+  values = ExtractPolicyValues(false);
+  EXPECT_EQ(expected, *values);
+}
+
+IN_PROC_BROWSER_TEST_F(PolicyToolUITest, MultipleSessionsChoice) {
+  base::ScopedAllowBlockingForTesting allow_blocking;
+  base::CreateDirectory(GetSessionsDir());
+  // Create 5 session files with different last access times and contents.
+  base::DictionaryValue contents;
+  base::Time initial_time = base::Time::Now();
+  for (int i = 0; i < 5; ++i) {
+    contents.SetPath({"chromePolicies", "SessionId", "value"},
+                     base::Value(base::IntToString(i)));
+    base::FilePath::StringType session_name =
+        base::FilePath::FromUTF8Unsafe(base::IntToString(i)).value();
+    std::string stringified_contents;
+    base::JSONWriter::Write(contents, &stringified_contents);
+    base::WriteFile(GetSessionPath(session_name), stringified_contents.c_str(),
+                    stringified_contents.size());
+    base::Time current_time = initial_time + base::TimeDelta::FromSeconds(i);
+    base::TouchFile(GetSessionPath(session_name), current_time, current_time);
+  }
+
+  // Load the page. This should load the last session.
+  ui_test_utils::NavigateToURL(browser(), GURL("chrome://policy-tool"));
+  std::unique_ptr<base::DictionaryValue> page_contents =
+      ExtractPolicyValues(false);
+  EXPECT_EQ(contents, *page_contents);
+}
diff --git a/chrome/browser/ui/webui/policy_tool_ui_handler.cc b/chrome/browser/ui/webui/policy_tool_ui_handler.cc
index ae609a2..d5d8e32 100644
--- a/chrome/browser/ui/webui/policy_tool_ui_handler.cc
+++ b/chrome/browser/ui/webui/policy_tool_ui_handler.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/webui/policy_tool_ui_handler.h"
 
+#include "base/files/file_enumerator.h"
 #include "base/files/file_util.h"
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
@@ -12,17 +13,28 @@
 #include "build/build_config.h"
 #include "chrome/browser/profiles/profile.h"
 
+// static
+const base::FilePath::CharType PolicyToolUIHandler::kPolicyToolSessionsDir[] =
+    FILE_PATH_LITERAL("Policy sessions");
+
+// static
+const base::FilePath::CharType
+    PolicyToolUIHandler::kPolicyToolDefaultSessionName[] =
+        FILE_PATH_LITERAL("policy");
+
+// static
+const base::FilePath::CharType
+    PolicyToolUIHandler::kPolicyToolSessionExtension[] =
+        FILE_PATH_LITERAL("json");
+
 PolicyToolUIHandler::PolicyToolUIHandler() : callback_weak_ptr_factory_(this) {}
 
 PolicyToolUIHandler::~PolicyToolUIHandler() {}
 
 void PolicyToolUIHandler::RegisterMessages() {
   // Set directory for storing sessions.
-  sessions_dir_ = Profile::FromWebUI(web_ui())->GetPath().Append(
-      FILE_PATH_LITERAL("Policy sessions"));
-  // Set current session name.
-  // TODO(urusant): do so in a smarter way, e.g. choose the last edited session.
-  session_name_ = FILE_PATH_LITERAL("policy");
+  sessions_dir_ =
+      Profile::FromWebUI(web_ui())->GetPath().Append(kPolicyToolSessionsDir);
 
   web_ui()->RegisterMessageCallback(
       "initialized", base::Bind(&PolicyToolUIHandler::HandleInitializedAdmin,
@@ -44,6 +56,45 @@
   return sessions_dir_.Append(name).AddExtension(FILE_PATH_LITERAL("json"));
 }
 
+base::ListValue PolicyToolUIHandler::GetSessionsList() {
+  base::FilePath::StringType sessions_pattern =
+      FILE_PATH_LITERAL("*.") +
+      base::FilePath::StringType(kPolicyToolSessionExtension);
+  base::FileEnumerator enumerator(sessions_dir_, /*recursive=*/false,
+                                  base::FileEnumerator::FILES,
+                                  sessions_pattern);
+  // A vector of session names and their last access times.
+  using Session = std::pair<base::Time, base::FilePath::StringType>;
+  std::vector<Session> sessions;
+  for (base::FilePath name = enumerator.Next(); !name.empty();
+       name = enumerator.Next()) {
+    base::File::Info info;
+    base::GetFileInfo(name, &info);
+    sessions.push_back(
+        {info.last_accessed, name.BaseName().RemoveExtension().value()});
+  }
+  // Sort the sessions by the the time of last access in decreasing order.
+  std::sort(sessions.begin(), sessions.end(), std::greater<Session>());
+
+  // Convert sessions to the list containing only names.
+  base::ListValue session_names;
+  for (const Session& session : sessions)
+    session_names.GetList().push_back(base::Value(session.second));
+  return session_names;
+}
+
+void PolicyToolUIHandler::SetDefaultSessionName() {
+  base::ListValue sessions = GetSessionsList();
+  if (sessions.empty()) {
+    // If there are no sessions, fallback to the default session name.
+    session_name_ = kPolicyToolDefaultSessionName;
+  } else {
+    session_name_ =
+        base::FilePath::FromUTF8Unsafe(sessions.GetList()[0].GetString())
+            .value();
+  }
+}
+
 std::string PolicyToolUIHandler::ReadOrCreateFileCallback() {
   // Create sessions directory, if it doesn't exist yet.
   // If unable to create a directory, just silently return a dictionary
@@ -53,7 +104,12 @@
   if (!base::CreateDirectory(sessions_dir_))
     return "{\"logged\": false}";
 
+  // Initialize session name if it is not initialized yet.
+  if (session_name_.empty())
+    SetDefaultSessionName();
+
   const base::FilePath session_path = GetSessionPath(session_name_);
+
   // Check if the file for the current session already exists. If not, create it
   // and put an empty dictionary in it.
   base::File session_file(session_path, base::File::Flags::FLAG_CREATE |
@@ -76,6 +132,12 @@
   // Read file contents.
   std::string contents;
   base::ReadFileToString(session_path, &contents);
+
+  // Touch the file to remember the last session.
+  base::File::Info info;
+  base::GetFileInfo(session_path, &info);
+  base::TouchFile(session_path, base::Time::Now(), info.last_modified);
+
   return contents;
 }
 
@@ -132,12 +194,8 @@
 
 void PolicyToolUIHandler::HandleLoadSession(const base::ListValue* args) {
   DCHECK_EQ(1U, args->GetSize());
-#if defined(OS_WIN)
   base::FilePath::StringType new_session_name =
-      base::UTF8ToUTF16(args->GetList()[0].GetString());
-#else
-  base::FilePath::StringType new_session_name = args->GetList()[0].GetString();
-#endif
+      base::FilePath::FromUTF8Unsafe(args->GetList()[0].GetString()).value();
   if (!IsValidSessionName(new_session_name)) {
     ShowErrorMessageToUser("errorInvalidSessionName");
     return;
diff --git a/chrome/browser/ui/webui/policy_tool_ui_handler.h b/chrome/browser/ui/webui/policy_tool_ui_handler.h
index deb4f23..316a6e5f 100644
--- a/chrome/browser/ui/webui/policy_tool_ui_handler.h
+++ b/chrome/browser/ui/webui/policy_tool_ui_handler.h
@@ -18,6 +18,11 @@
   void OnJavascriptDisallowed() override;
 
  private:
+  friend class PolicyToolUITest;
+
+  static const base::FilePath::CharType kPolicyToolSessionsDir[];
+  static const base::FilePath::CharType kPolicyToolDefaultSessionName[];
+  static const base::FilePath::CharType kPolicyToolSessionExtension[];
   // Reads the current session file (based on the session_name_) and sends the
   // contents to the UI.
   void ImportFile();
@@ -37,6 +42,12 @@
 
   base::FilePath GetSessionPath(const base::FilePath::StringType& name) const;
 
+  // Returns the current list of all sessions sorted by last access time in
+  // decreasing order.
+  base::ListValue GetSessionsList();
+
+  void SetDefaultSessionName();
+
   base::FilePath sessions_dir_;
   base::FilePath::StringType session_name_;
 
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 9868df8..7a9a4ec 100644
--- a/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc
@@ -34,6 +34,7 @@
 #include "extensions/common/permissions/usb_device_permission.h"
 #include "extensions/common/permissions/usb_device_permission_data.h"
 #include "extensions/common/value_builder.h"
+#include "printing/print_job_constants.h"
 #include "printing/pwg_raster_settings.h"
 
 using device::UsbDevice;
@@ -306,8 +307,9 @@
     const PrinterHandler::GetCapabilityCallback& callback,
     const base::DictionaryValue& capability) {
   std::unique_ptr<base::DictionaryValue> capabilities =
-      base::DictionaryValue::From(
-          std::make_unique<base::Value>(capability.Clone()));
+      std::make_unique<base::DictionaryValue>();
+  if (!capability.empty())  // empty capability -> empty return dictionary
+    capabilities->SetPath({printing::kSettingCapabilities}, capability.Clone());
   callback.Run(std::move(capabilities));
 }
 
diff --git a/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc b/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc
index 08f2cb58..f37e6c4f 100644
--- a/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc
+++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc
@@ -40,6 +40,7 @@
 #include "extensions/common/extension.h"
 #include "extensions/common/value_builder.h"
 #include "printing/pdf_render_settings.h"
+#include "printing/print_job_constants.h"
 #include "printing/pwg_raster_settings.h"
 #include "printing/units.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -214,7 +215,15 @@
                       std::unique_ptr<base::DictionaryValue>* capability_out,
                       std::unique_ptr<base::DictionaryValue> capability) {
   ++(*call_count);
-  *capability_out = std::move(capability);
+  const base::Value* capabilities = nullptr;
+  if (capability) {
+    capabilities = capability->FindPathOfType({printing::kSettingCapabilities},
+                                              base::Value::Type::DICTIONARY);
+  }
+  *capability_out =
+      capabilities ? base::DictionaryValue::From(
+                         std::make_unique<base::Value>(capabilities->Clone()))
+                   : nullptr;
 }
 
 // Used as a callback to StartPrint in tests.
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 eea235a..2204cb3 100644
--- a/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc
@@ -25,12 +25,12 @@
 #include "chrome/browser/printing/print_preview_dialog_controller.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/chrome_select_file_policy.h"
-#include "chrome/browser/ui/webui/print_preview/printer_capabilities.h"
 #include "chrome/browser/ui/webui/print_preview/sticky_settings.h"
 #include "chrome/common/chrome_switches.h"
 #include "components/cloud_devices/common/printer_description.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/web_contents.h"
+#include "printing/print_job_constants.h"
 #include "printing/printing_context.h"
 #include "printing/units.h"
 #include "ui/gfx/geometry/size.h"
@@ -162,9 +162,9 @@
     const std::string& destination_id,
     const GetCapabilityCallback& callback) {
   auto printer_info = base::MakeUnique<base::DictionaryValue>();
-  printer_info->SetString(printing::kPrinterId, destination_id);
+  printer_info->SetString(printing::kSettingDeviceName, destination_id);
   printer_info->Set(
-      printing::kPrinterCapabilities,
+      printing::kSettingCapabilities,
       GetPdfCapabilities(g_browser_process->GetApplicationLocale()));
   callback.Run(std::move(printer_info));
 }
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 73e4f9b..4d4d1de7 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -44,7 +44,6 @@
 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
 #include "chrome/browser/ui/webui/print_preview/pdf_printer_handler.h"
 #include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
-#include "chrome/browser/ui/webui/print_preview/printer_capabilities.h"
 #include "chrome/browser/ui/webui/print_preview/printer_handler.h"
 #include "chrome/browser/ui/webui/print_preview/sticky_settings.h"
 #include "chrome/common/chrome_switches.h"
@@ -725,9 +724,9 @@
 
     PrinterType type = PrinterType::kPdfPrinter;
     if (print_with_extension)
-      type = PrinterType::kPrivetPrinter;
-    else if (print_with_privet)
       type = PrinterType::kExtensionPrinter;
+    else if (print_with_privet)
+      type = PrinterType::kPrivetPrinter;
     PrinterHandler* handler = GetPrinterHandler(type);
     handler->StartPrint(destination_id, capabilities, title, print_ticket,
                         gfx::Size(width, height), data,
@@ -1044,10 +1043,10 @@
     const std::string& callback_id,
     std::unique_ptr<base::DictionaryValue> settings_info) {
   // Check that |settings_info| is valid.
-  if (settings_info && !settings_info->empty()) {
+  if (settings_info &&
+      settings_info->FindKeyOfType(printing::kSettingCapabilities,
+                                   base::Value::Type::DICTIONARY)) {
     VLOG(1) << "Get printer capabilities finished";
-    DCHECK(settings_info->FindKeyOfType(printing::kPrinterCapabilities,
-                                        base::Value::Type::DICTIONARY));
     ResolveJavascriptCallback(base::Value(callback_id), *settings_info);
     return;
   }
@@ -1065,7 +1064,7 @@
   auto caps_value = base::MakeUnique<base::Value>();
   auto caps = base::MakeUnique<base::DictionaryValue>();
   if (destination_info &&
-      destination_info->Remove(printing::kPrinterCapabilities, &caps_value) &&
+      destination_info->Remove(printing::kSettingCapabilities, &caps_value) &&
       caps_value->IsType(base::Value::Type::DICTIONARY)) {
     caps = base::DictionaryValue::From(std::move(caps_value));
   } else {
@@ -1357,7 +1356,7 @@
 
 void PrintPreviewHandler::BadMessageReceived() {
   bad_message::ReceivedBadMessage(
-      GetInitiator()->GetRenderProcessHost(),
+      GetInitiator()->GetMainFrame()->GetProcess(),
       bad_message::BadMessageReason::PPH_EXTRA_PREVIEW_MESSAGE);
 }
 
diff --git a/chrome/browser/ui/webui/print_preview/printer_capabilities.cc b/chrome/browser/ui/webui/print_preview/printer_capabilities.cc
index a63b3877..e3f0fab 100644
--- a/chrome/browser/ui/webui/print_preview/printer_capabilities.cc
+++ b/chrome/browser/ui/webui/print_preview/printer_capabilities.cc
@@ -31,8 +31,7 @@
 
 namespace printing {
 
-const char kPrinterId[] = "printerId";
-const char kPrinterCapabilities[] = "capabilities";
+const char kPrinter[] = "printer";
 
 namespace {
 
@@ -152,7 +151,7 @@
   const std::string& printer_description = printer_name_description.second;
 
   auto printer_info = base::MakeUnique<base::DictionaryValue>();
-  printer_info->SetString(kPrinterId, device_name);
+  printer_info->SetString(kSettingDeviceName, device_name);
   printer_info->SetString(kSettingPrinterName, printer_name);
   printer_info->SetString(kSettingPrinterDescription, printer_description);
   printer_info->SetBoolean(
@@ -160,10 +159,13 @@
       base::ContainsKey(basic_info.options, kCUPSEnterprisePrinter) &&
           basic_info.options.at(kCUPSEnterprisePrinter) == kValueTrue);
 
-  printer_info->Set(kPrinterCapabilities,
-                    GetPrinterCapabilitiesOnBlockingPoolThread(device_name));
+  auto printer_info_capabilities = std::make_unique<base::DictionaryValue>();
+  printer_info_capabilities->SetDictionary(kPrinter, std::move(printer_info));
+  printer_info_capabilities->Set(
+      kSettingCapabilities,
+      GetPrinterCapabilitiesOnBlockingPoolThread(device_name));
 
-  return printer_info;
+  return printer_info_capabilities;
 }
 
 void ConvertPrinterListForCallback(
diff --git a/chrome/browser/ui/webui/print_preview/printer_capabilities.h b/chrome/browser/ui/webui/print_preview/printer_capabilities.h
index 9cedc07..e8bb93e 100644
--- a/chrome/browser/ui/webui/print_preview/printer_capabilities.h
+++ b/chrome/browser/ui/webui/print_preview/printer_capabilities.h
@@ -17,10 +17,6 @@
 
 struct PrinterBasicInfo;
 
-// Printer capability setting keys.
-extern const char kPrinterId[];
-extern const char kPrinterCapabilities[];
-
 // Extracts the printer display name and description from the
 // appropriate fields in |printer| for the platform.
 std::pair<std::string, std::string> GetPrinterNameAndDescription(
diff --git a/chrome/browser/ui/webui/print_preview/printer_handler.h b/chrome/browser/ui/webui/print_preview/printer_handler.h
index 06c2d2c..2f9eb01 100644
--- a/chrome/browser/ui/webui/print_preview/printer_handler.h
+++ b/chrome/browser/ui/webui/print_preview/printer_handler.h
@@ -45,6 +45,15 @@
   using AddedPrintersCallback =
       base::Callback<void(const base::ListValue& printers)>;
   using GetPrintersDoneCallback = base::Closure;
+  // |capability| should contain a CDD with key printing::kSettingCapabilities.
+  // It may also contain other information about the printer in a dictionary
+  // with key printing::kPrinter.
+  // If |capability| is null, empty, or does not contain a dictionary with key
+  // printing::kSettingCapabilities, this indicates a failure to retrieve
+  // capabilities.
+  // If the dictionary with key printing::kSettingCapabilities is
+  // empty, this indicates capabilities were retrieved but the printer does
+  // not support any of the capability fields in a CDD.
   using GetCapabilityCallback =
       base::Callback<void(std::unique_ptr<base::DictionaryValue> capability)>;
   using PrintCallback =
diff --git a/chrome/browser/ui/webui/settings/change_password_handler.cc b/chrome/browser/ui/webui/settings/change_password_handler.cc
index 72b389c..c4c7199 100644
--- a/chrome/browser/ui/webui/settings/change_password_handler.cc
+++ b/chrome/browser/ui/webui/settings/change_password_handler.cc
@@ -46,14 +46,13 @@
 }
 
 void ChangePasswordHandler::OnGaiaPasswordChanged() {
-  CallJavascriptFunction("cr.webUIListenerCallback",
-                         base::Value("change-password-on-dismiss"));
+  FireWebUIListener("change-password-on-dismiss");
 }
 
 void ChangePasswordHandler::OnMarkingSiteAsLegitimate(const GURL& url) {
-  if (service_->unhandled_password_reuses().empty()) {
-    CallJavascriptFunction("cr.webUIListenerCallback",
-                           base::Value("change-password-on-dismiss"));
+  if (!ChromePasswordProtectionService::ShouldShowChangePasswordSettingUI(
+          profile_)) {
+    FireWebUIListener("change-password-on-dismiss");
   }
 }
 
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 37cabdc..1cb3eb8 100644
--- a/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc
@@ -181,8 +181,10 @@
     NOTREACHED();
   DCHECK_EQ("image/png", mime_type);
 
+  // Use |raw_data| as image but first verify that it can be decoded.
   user_photo_ = gfx::ImageSkia();
-  user_photo_data_url_ = image_url;
+  std::vector<unsigned char> photo_data(raw_data.begin(), raw_data.end());
+  user_photo_data_ = base::RefCountedBytes::TakeVector(&photo_data);
 
   ImageDecoder::Cancel(this);
   ImageDecoder::Start(this, raw_data);
@@ -207,7 +209,17 @@
     case user_manager::User::USER_IMAGE_EXTERNAL: {
       // User has image from camera/file, record it and add to the image list.
       previous_image_ = user->GetImage();
-      SendOldImage(webui::GetBitmapDataUrl(*previous_image_.bitmap()), -1);
+      previous_image_format_ = user->image_format();
+      if (previous_image_format_ == user_manager::UserImage::FORMAT_PNG &&
+          user->has_image_bytes()) {
+        previous_image_bytes_ = user->image_bytes();
+        SendOldImage(webui::GetPngDataUrl(previous_image_bytes_->front(),
+                                          previous_image_bytes_->size()),
+                     -1);
+      } else {
+        previous_image_bytes_ = nullptr;
+        SendOldImage(webui::GetBitmapDataUrl(*previous_image_.bitmap()), -1);
+      }
       break;
     }
     case user_manager::User::USER_IMAGE_PROFILE: {
@@ -225,6 +237,8 @@
         // User has an old default image, so present it in the same manner as a
         // previous image from file.
         previous_image_ = user->GetImage();
+        previous_image_bytes_ = nullptr;
+        previous_image_format_ = user_manager::UserImage::FORMAT_UNKNOWN;
         SendOldImage(
             default_user_image::GetDefaultImageUrl(previous_image_index_),
             previous_image_index_);
@@ -278,10 +292,11 @@
   if (image_type == "old") {
     // Previous image (from camera or manually uploaded) re-selected.
     DCHECK(!previous_image_.isNull());
-    user_image_manager->SaveUserImage(
-        user_manager::UserImage::CreateAndEncode(
-            previous_image_,
-            user_manager::UserImage::FORMAT_JPEG));
+    std::unique_ptr<user_manager::UserImage> user_image =
+        base::MakeUnique<user_manager::UserImage>(
+            previous_image_, previous_image_bytes_, previous_image_format_);
+    user_image->MarkAsSafe();
+    user_image_manager->SaveUserImage(std::move(user_image));
 
     UMA_HISTOGRAM_EXACT_LINEAR("UserImage.ChangeChoice",
                                default_user_image::kHistogramImageOld,
@@ -306,7 +321,7 @@
       waiting_for_camera_photo = true;
       VLOG(1) << "Still waiting for camera image to decode";
     } else {
-      SetImageFromCamera(user_photo_);
+      SetImageFromCamera(user_photo_, user_photo_data_.get());
     }
   } else if (image_type == "profile") {
     // Profile image selected. Could be previous (old) user image.
@@ -349,11 +364,16 @@
   VLOG(1) << "Selected image from file";
 }
 
-void ChangePictureHandler::SetImageFromCamera(const gfx::ImageSkia& photo) {
+void ChangePictureHandler::SetImageFromCamera(
+    const gfx::ImageSkia& photo,
+    base::RefCountedBytes* photo_bytes) {
+  std::unique_ptr<user_manager::UserImage> user_image =
+      base::MakeUnique<user_manager::UserImage>(
+          photo, photo_bytes, user_manager::UserImage::FORMAT_PNG);
+  user_image->MarkAsSafe();
   ChromeUserManager::Get()
       ->GetUserImageManager(GetUser()->GetAccountId())
-      ->SaveUserImage(user_manager::UserImage::CreateAndEncode(
-          photo, user_manager::UserImage::FORMAT_JPEG));
+      ->SaveUserImage(std::move(user_image));
   UMA_HISTOGRAM_EXACT_LINEAR("UserImage.ChangeChoice",
                              default_user_image::kHistogramImageFromCamera,
                              default_user_image::kHistogramImagesCount);
@@ -390,7 +410,7 @@
 
 void ChangePictureHandler::OnImageDecoded(const SkBitmap& decoded_image) {
   user_photo_ = gfx::ImageSkia::CreateFrom1xBitmap(decoded_image);
-  SetImageFromCamera(user_photo_);
+  SetImageFromCamera(user_photo_, user_photo_data_.get());
 }
 
 void ChangePictureHandler::OnDecodeImageFailed() {
diff --git a/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h b/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h
index 77586cf..ab0e183 100644
--- a/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h
@@ -104,7 +104,8 @@
                                  const gfx::ImageSkia& profile_image) override;
 
   // Sets user image to photo taken from camera.
-  void SetImageFromCamera(const gfx::ImageSkia& photo);
+  void SetImageFromCamera(const gfx::ImageSkia& photo,
+                          base::RefCountedBytes* image_bytes);
 
   // Returns handle to browser window or NULL if it can't be found.
   gfx::NativeWindow GetBrowserWindow() const;
@@ -121,6 +122,9 @@
 
   // Previous user image from camera/file and its data URL.
   gfx::ImageSkia previous_image_;
+  scoped_refptr<base::RefCountedBytes> previous_image_bytes_;
+  user_manager::UserImage::ImageFormat previous_image_format_ =
+      user_manager::UserImage::FORMAT_UNKNOWN;
 
   // Index of the previous user image.
   int previous_image_index_;
@@ -128,8 +132,8 @@
   // Last user photo, if taken.
   gfx::ImageSkia user_photo_;
 
-  // Data URL for |user_photo_|.
-  std::string user_photo_data_url_;
+  // Data for |user_photo_|.
+  scoped_refptr<base::RefCountedBytes> user_photo_data_;
 
   ScopedObserver<user_manager::UserManager, ChangePictureHandler>
       user_manager_observer_;
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 d046f21..69b4aef7 100644
--- a/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc
@@ -48,7 +48,7 @@
   auto* service =
       arc::ArcVoiceInteractionFrameworkService::GetForBrowserContext(profile_);
   if (service)
-    service->SetVoiceInteractionEnabled(enabled);
+    service->SetVoiceInteractionEnabled(enabled, base::BindOnce([](bool) {}));
 }
 
 void GoogleAssistantHandler::HandleSetGoogleAssistantContextEnabled(
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 0d22074..4de822e 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
@@ -1292,17 +1292,16 @@
     {"changePicturePageDescription", IDS_SETTINGS_CHANGE_PICTURE_DIALOG_TEXT},
     {"takePhoto", IDS_SETTINGS_CHANGE_PICTURE_TAKE_PHOTO},
     {"discardPhoto", IDS_SETTINGS_CHANGE_PICTURE_DISCARD_PHOTO},
-    {"flipPhoto", IDS_SETTINGS_CHANGE_PICTURE_FLIP_PHOTO},
+    {"switchMode", IDS_SETTINGS_CHANGE_PICTURE_SWITCH_MODE},
     {"chooseFile", IDS_SETTINGS_CHANGE_PICTURE_CHOOSE_FILE},
     {"profilePhoto", IDS_SETTINGS_CHANGE_PICTURE_PROFILE_PHOTO},
     {"oldPhoto", IDS_SETTINGS_CHANGE_PICTURE_OLD_PHOTO},
     {"previewAltText", IDS_SETTINGS_CHANGE_PICTURE_PREVIEW_ALT},
     {"authorCreditText", IDS_SETTINGS_CHANGE_PICTURE_AUTHOR_CREDIT_TEXT},
-    {"photoFlippedAccessibleText", IDS_SETTINGS_PHOTO_FLIP_ACCESSIBLE_TEXT},
-    {"photoFlippedBackAccessibleText",
-     IDS_SETTINGS_PHOTO_FLIPBACK_ACCESSIBLE_TEXT},
     {"photoCaptureAccessibleText", IDS_SETTINGS_PHOTO_CAPTURE_ACCESSIBLE_TEXT},
     {"photoDiscardAccessibleText", IDS_SETTINGS_PHOTO_DISCARD_ACCESSIBLE_TEXT},
+    {"photoModeAccessibleText", IDS_SETTINGS_PHOTO_MODE_ACCESSIBLE_TEXT},
+    {"videoModeAccessibleText", IDS_SETTINGS_VIDEO_MODE_ACCESSIBLE_TEXT},
 #else   // !defined(OS_CHROMEOS)
     {"domainManagedProfile", IDS_SETTINGS_PEOPLE_DOMAIN_MANAGED_PROFILE},
     {"editPerson", IDS_SETTINGS_EDIT_PERSON},
@@ -1603,12 +1602,18 @@
 }
 
 void AddSearchStrings(content::WebUIDataSource* html_source, Profile* profile) {
+#if defined(OS_CHROMEOS)
+  const bool is_user_primary =
+      chromeos::ProfileHelper::Get()->GetUserByProfile(profile) ==
+      user_manager::UserManager::Get()->GetPrimaryUser();
+#endif
+
   LocalizedString localized_strings[] = {
 #if defined(OS_CHROMEOS)
-    {"searchPageTitle",
-     !profile->IsSupervised() && chromeos::switches::IsVoiceInteractionEnabled()
-         ? IDS_SETTINGS_SEARCH_AND_ASSISTANT
-         : IDS_SETTINGS_SEARCH},
+    {"searchPageTitle", !profile->IsSupervised() && is_user_primary &&
+                                chromeos::switches::IsVoiceInteractionEnabled()
+                            ? IDS_SETTINGS_SEARCH_AND_ASSISTANT
+                            : IDS_SETTINGS_SEARCH},
 #else
     {"searchPageTitle", IDS_SETTINGS_SEARCH},
 #endif
@@ -1645,8 +1650,9 @@
       base::ASCIIToUTF16(chrome::kOmniboxLearnMoreURL));
   html_source->AddString("searchExplanation", search_explanation_text);
 #if defined(OS_CHROMEOS)
-  html_source->AddBoolean("enableVoiceInteraction",
-                          chromeos::switches::IsVoiceInteractionEnabled());
+  html_source->AddBoolean(
+      "enableVoiceInteraction",
+      chromeos::switches::IsVoiceInteractionEnabled() && is_user_primary);
 #endif
 }
 
@@ -1859,6 +1865,7 @@
      IDS_SETTINGS_SITE_SETTINGS_COOKIES_ALLOW_SITES_RECOMMENDED},
     {"siteSettingsAllow", IDS_SETTINGS_SITE_SETTINGS_ALLOW},
     {"siteSettingsBlock", IDS_SETTINGS_SITE_SETTINGS_BLOCK},
+    {"siteSettingsBlockSound", IDS_SETTINGS_SITE_SETTINGS_BLOCK_SOUND},
     {"siteSettingsSessionOnly", IDS_SETTINGS_SITE_SETTINGS_SESSION_ONLY},
     {"siteSettingsAllowed", IDS_SETTINGS_SITE_SETTINGS_ALLOWED},
     {"siteSettingsAllowedRecommended",
diff --git a/chrome/browser/ui/webui/settings_utils_linux.cc b/chrome/browser/ui/webui/settings_utils_linux.cc
index 26a72ee..6caf7414 100644
--- a/chrome/browser/ui/webui/settings_utils_linux.cc
+++ b/chrome/browser/ui/webui/settings_utils_linux.cc
@@ -16,6 +16,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/tab_contents/tab_util.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
@@ -140,7 +141,7 @@
   base::PostTaskWithTraits(
       FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()},
       base::BindOnce(&DetectAndStartProxyConfigUtil,
-                     web_contents->GetRenderProcessHost()->GetID(),
+                     web_contents->GetRenderViewHost()->GetProcess()->GetID(),
                      web_contents->GetRenderViewHost()->GetRoutingID()));
 }
 
diff --git a/chrome/browser/ui/webui/signin/inline_login_ui_browsertest.cc b/chrome/browser/ui/webui/signin/inline_login_ui_browsertest.cc
index 61c0d0e..2b976b7 100644
--- a/chrome/browser/ui/webui/signin/inline_login_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/signin/inline_login_ui_browsertest.cc
@@ -103,7 +103,7 @@
       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
   content::WebContents* contents =
       browser->tab_strip_model()->GetActiveWebContents();
-  content::RenderProcessHost* process = contents->GetRenderProcessHost();
+  content::RenderProcessHost* process = contents->GetMainFrame()->GetProcess();
   return ContentInfo(contents, process->GetID(),
                      process->GetStoragePartition());
 }
@@ -348,7 +348,7 @@
   ASSERT_EQ(1u, set.size());
   content::WebContents* webview_contents = *set.begin();
   content::RenderProcessHost* process =
-      webview_contents->GetRenderProcessHost();
+      webview_contents->GetMainFrame()->GetProcess();
   ASSERT_NE(info.pid, process->GetID());
   ASSERT_NE(info.storage_partition, process->GetStoragePartition());
 }
diff --git a/chrome/browser/ui/webui/webui_browsertest.cc b/chrome/browser/ui/webui/webui_browsertest.cc
index dbbee1d..70289d0 100644
--- a/chrome/browser/ui/webui/webui_browsertest.cc
+++ b/chrome/browser/ui/webui/webui_browsertest.cc
@@ -12,6 +12,7 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/child_process_security_policy.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_ui_message_handler.h"
 #include "content/public/common/content_switches.h"
@@ -44,7 +45,7 @@
   ui_test_utils::NavigateToURL(browser(), web_ui_url);
   EXPECT_TRUE(
       content::ChildProcessSecurityPolicy::GetInstance()->HasWebUIBindings(
-          web_contents->GetRenderProcessHost()->GetID()));
+          web_contents->GetMainFrame()->GetProcess()->GetID()));
 
   // Capture the SiteInstance before navigating for later comparison.
   scoped_refptr<content::SiteInstance> orig_site_instance(
@@ -60,7 +61,7 @@
   EXPECT_NE(orig_site_instance, web_contents->GetSiteInstance());
   EXPECT_TRUE(
       content::ChildProcessSecurityPolicy::GetInstance()->HasWebUIBindings(
-          web_contents->GetRenderProcessHost()->GetID()));
+          web_contents->GetMainFrame()->GetProcess()->GetID()));
 }
 
 IN_PROC_BROWSER_TEST_F(WebUIImplBrowserTest, InPageNavigationsAndReload) {
diff --git a/chrome/browser/ui/window_sizer/window_sizer_ash_uitest.cc b/chrome/browser/ui/window_sizer/window_sizer_ash_uitest.cc
index 4850564..eaf3940 100644
--- a/chrome/browser/ui/window_sizer/window_sizer_ash_uitest.cc
+++ b/chrome/browser/ui/window_sizer/window_sizer_ash_uitest.cc
@@ -69,6 +69,8 @@
   center.Offset(- origin.x(), - origin.y());
   generator.MoveMouseTo(center);
   generator.ClickLeftButton();
+  // Spin a run loop so Ash can notify Chrome of item selection for handling.
+  base::RunLoop().RunUntilIdle();
 }
 
 }  // namespace
diff --git a/chrome/browser/vr/BUILD.gn b/chrome/browser/vr/BUILD.gn
index 420ca259..b0d176bd 100644
--- a/chrome/browser/vr/BUILD.gn
+++ b/chrome/browser/vr/BUILD.gn
@@ -5,6 +5,7 @@
 import("//chrome/common/features.gni")
 import("//device/vr/features/features.gni")
 import("//testing/test.gni")
+import("//tools/grit/repack.gni")
 
 if (is_android) {
   import("//build/config/android/rules.gni")
@@ -55,10 +56,6 @@
     "elements/invisible_hit_target.h",
     "elements/linear_layout.cc",
     "elements/linear_layout.h",
-    "elements/loading_indicator.cc",
-    "elements/loading_indicator.h",
-    "elements/loading_indicator_texture.cc",
-    "elements/loading_indicator_texture.h",
     "elements/rect.cc",
     "elements/rect.h",
     "elements/render_text_wrapper.cc",
@@ -103,6 +100,7 @@
     "gltf_asset.h",
     "gltf_parser.cc",
     "gltf_parser.h",
+    "model/model.h",
     "target_property.h",
     "toolbar_helper.cc",
     "toolbar_helper.h",
@@ -174,15 +172,21 @@
     "test/constants.h",
     "test/fake_ui_element_renderer.cc",
     "test/fake_ui_element_renderer.h",
+    "test/gl_test_environment.cc",
+    "test/gl_test_environment.h",
+    "test/gl_test_environment_unittest.cc",
     "test/mock_browser_interface.cc",
     "test/mock_browser_interface.h",
     "test/mock_content_input_delegate.cc",
     "test/mock_content_input_delegate.h",
     "test/paths.cc",
     "test/paths.h",
+    "test/ui_pixel_test.cc",
+    "test/ui_pixel_test.h",
     "test/ui_scene_manager_test.cc",
     "test/ui_scene_manager_test.h",
     "ui_input_manager_unittest.cc",
+    "ui_pixeltest.cc",
     "ui_scene_manager_unittest.cc",
     "ui_scene_unittest.cc",
     "vr_gl_util_unittest.cc",
@@ -190,8 +194,8 @@
 
   deps = [
     ":vr_common",
+    ":vr_test_pak",
     "//base/test:test_support",
-    "//components:components_tests_pak",
     "//components/security_state/core",
     "//components/toolbar:vector_icons",
     "//skia",
@@ -201,6 +205,7 @@
     "//ui/gfx:test_support",
     "//ui/gfx/geometry",
     "//ui/gl",
+    "//ui/gl:test_support",
   ]
 
   if (is_android) {
@@ -209,6 +214,24 @@
 
   data = [
     "test/data/",
-    "$root_out_dir/components_tests_resources.pak",
+    "$root_out_dir/vr_test.pak",
+  ]
+}
+
+repack("vr_test_pak") {
+  sources = [
+    "$root_gen_dir/chrome/generated_resources_en-US.pak",
+    "$root_gen_dir/chrome/vr_shell_resources.pak",
+    "$root_gen_dir/components/components_resources.pak",
+    "$root_gen_dir/components/strings/components_strings_en-US.pak",
+  ]
+
+  output = "$root_out_dir/vr_test.pak"
+
+  deps = [
+    "//chrome/app:generated_resources",
+    "//chrome/browser/resources:vr_shell_resources",
+    "//components/resources:components_resources",
+    "//components/strings",
   ]
 }
diff --git a/chrome/browser/vr/elements/loading_indicator.cc b/chrome/browser/vr/elements/loading_indicator.cc
deleted file mode 100644
index b1814a5..0000000
--- a/chrome/browser/vr/elements/loading_indicator.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/vr/elements/loading_indicator.h"
-
-#include "base/memory/ptr_util.h"
-#include "chrome/browser/vr/elements/loading_indicator_texture.h"
-
-namespace vr {
-
-LoadingIndicator::LoadingIndicator(int preferred_width)
-    : TexturedElement(preferred_width),
-      texture_(base::MakeUnique<LoadingIndicatorTexture>()) {
-  SetVisible(false);
-}
-
-LoadingIndicator::~LoadingIndicator() = default;
-
-UiTexture* LoadingIndicator::GetTexture() const {
-  return texture_.get();
-}
-
-void LoadingIndicator::SetVisible(bool visible) {
-  if (visible_ == visible)
-    return;
-  visible_ = visible;
-  UpdateOpacity();
-}
-
-void LoadingIndicator::SetLoading(bool loading) {
-  if (loading_ == loading)
-    return;
-  loading_ = loading;
-  texture_->SetLoading(loading);
-  texture_->SetLoadProgress(0);
-  UpdateOpacity();
-}
-
-void LoadingIndicator::SetLoadProgress(float progress) {
-  texture_->SetLoadProgress(progress);
-}
-
-void LoadingIndicator::UpdateOpacity() {
-  SetOpacity((visible_ && loading_) ? opacity_when_visible() : 0);
-}
-
-}  // namespace vr
diff --git a/chrome/browser/vr/elements/loading_indicator.h b/chrome/browser/vr/elements/loading_indicator.h
deleted file mode 100644
index d72ca4a..0000000
--- a/chrome/browser/vr/elements/loading_indicator.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 CHROME_BROWSER_VR_ELEMENTS_LOADING_INDICATOR_H_
-#define CHROME_BROWSER_VR_ELEMENTS_LOADING_INDICATOR_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "chrome/browser/vr/elements/textured_element.h"
-
-namespace vr {
-
-class LoadingIndicatorTexture;
-
-class LoadingIndicator : public TexturedElement {
- public:
-  explicit LoadingIndicator(int preferred_width);
-  ~LoadingIndicator() override;
-
-  void SetVisible(bool visible) override;
-  void SetLoading(bool loading);
-  void SetLoadProgress(float progress);
-
- private:
-  UiTexture* GetTexture() const override;
-  std::unique_ptr<LoadingIndicatorTexture> texture_;
-
-  void UpdateOpacity();
-
-  bool visible_ = false;
-  bool loading_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(LoadingIndicator);
-};
-
-}  // namespace vr
-
-#endif  // CHROME_BROWSER_VR_ELEMENTS_LOADING_INDICATOR_H_
diff --git a/chrome/browser/vr/elements/loading_indicator_texture.cc b/chrome/browser/vr/elements/loading_indicator_texture.cc
deleted file mode 100644
index 84527437..0000000
--- a/chrome/browser/vr/elements/loading_indicator_texture.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/vr/elements/loading_indicator_texture.h"
-
-#include "base/logging.h"
-#include "cc/paint/skia_paint_canvas.h"
-#include "third_party/skia/include/core/SkCanvas.h"
-
-namespace vr {
-
-namespace {
-
-static constexpr float kWidth = 0.24;
-static constexpr float kHeight = 0.008;
-
-}  // namespace
-
-LoadingIndicatorTexture::LoadingIndicatorTexture() = default;
-
-LoadingIndicatorTexture::~LoadingIndicatorTexture() = default;
-
-gfx::Size LoadingIndicatorTexture::GetPreferredTextureSize(
-    int maximum_width) const {
-  return gfx::Size(maximum_width, maximum_width * kHeight / kWidth);
-}
-
-gfx::SizeF LoadingIndicatorTexture::GetDrawnSize() const {
-  return size_;
-}
-
-void LoadingIndicatorTexture::SetLoading(bool loading) {
-  if (loading_ != loading) {
-    loading_ = loading;
-    set_dirty();
-  }
-}
-
-void LoadingIndicatorTexture::SetLoadProgress(float progress) {
-  DCHECK_GE(progress, 0.0f);
-  DCHECK_LE(progress, 1.0f);
-  if (progress_ != progress) {
-    progress_ = progress;
-    set_dirty();
-  }
-}
-
-void LoadingIndicatorTexture::Draw(SkCanvas* canvas,
-                                   const gfx::Size& texture_size) {
-  size_.set_height(texture_size.height());
-  size_.set_width(texture_size.width());
-
-  canvas->save();
-  canvas->scale(size_.width() / kWidth, size_.width() / kWidth);
-
-  SkPaint paint;
-  paint.setColor(color_scheme().loading_indicator_background);
-  canvas->drawRoundRect({0, 0, kWidth, kHeight}, kHeight / 2, kHeight / 2,
-                        paint);
-
-  if (loading_) {
-    paint.setColor(color_scheme().loading_indicator_foreground);
-    float progress_width = kHeight + (kWidth - kHeight) * progress_;
-    canvas->drawRoundRect({0, 0, progress_width, kHeight}, kHeight / 2,
-                          kHeight / 2, paint);
-  }
-
-  canvas->restore();
-}
-
-}  // namespace vr
diff --git a/chrome/browser/vr/elements/loading_indicator_texture.h b/chrome/browser/vr/elements/loading_indicator_texture.h
deleted file mode 100644
index 39302e4..0000000
--- a/chrome/browser/vr/elements/loading_indicator_texture.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VR_ELEMENTS_LOADING_INDICATOR_TEXTURE_H_
-#define CHROME_BROWSER_VR_ELEMENTS_LOADING_INDICATOR_TEXTURE_H_
-
-#include "chrome/browser/vr/elements/ui_texture.h"
-#include "ui/gfx/geometry/size.h"
-
-class SkCanvas;
-
-namespace vr {
-
-class LoadingIndicatorTexture : public UiTexture {
- public:
-  LoadingIndicatorTexture();
-  ~LoadingIndicatorTexture() override;
-  gfx::Size GetPreferredTextureSize(int width) const override;
-  gfx::SizeF GetDrawnSize() const override;
-
-  void SetLoading(bool loading);
-  void SetLoadProgress(float progress);
-
- private:
-  void Draw(SkCanvas* canvas, const gfx::Size& texture_size) override;
-  gfx::SizeF size_;
-  bool loading_ = false;
-  float progress_ = 0;
-};
-
-}  // namespace vr
-
-#endif  // CHROME_BROWSER_VR_ELEMENTS_LOADING_INDICATOR_TEXTURE_H_
diff --git a/chrome/browser/vr/elements/ui_element.cc b/chrome/browser/vr/elements/ui_element.cc
index 9e37a9c..35a1972 100644
--- a/chrome/browser/vr/elements/ui_element.cc
+++ b/chrome/browser/vr/elements/ui_element.cc
@@ -207,6 +207,10 @@
   DCHECK_NE(old_size, children_.size());
 }
 
+void UiElement::AddBinding(std::unique_ptr<BindingBase> binding) {
+  bindings_.push_back(std::move(binding));
+}
+
 gfx::Point3F UiElement::GetCenter() const {
   gfx::Point3F center;
   world_space_transform_.TransformPoint(&center);
diff --git a/chrome/browser/vr/elements/ui_element.h b/chrome/browser/vr/elements/ui_element.h
index 9441991b..be388686 100644
--- a/chrome/browser/vr/elements/ui_element.h
+++ b/chrome/browser/vr/elements/ui_element.h
@@ -14,6 +14,7 @@
 #include "cc/animation/transform_operations.h"
 #include "chrome/browser/vr/animation_player.h"
 #include "chrome/browser/vr/color_scheme.h"
+#include "chrome/browser/vr/databinding/binding_base.h"
 #include "chrome/browser/vr/elements/draw_phase.h"
 #include "chrome/browser/vr/elements/ui_element_iterator.h"
 #include "chrome/browser/vr/elements/ui_element_name.h"
@@ -195,6 +196,11 @@
   UiElement* parent() { return parent_; }
   const UiElement* parent() const { return parent_; }
 
+  void AddBinding(std::unique_ptr<BindingBase> binding);
+  const std::vector<std::unique_ptr<BindingBase>>& bindings() {
+    return bindings_;
+  }
+
   gfx::Point3F GetCenter() const;
   gfx::Vector3dF GetNormal() const;
 
@@ -345,6 +351,8 @@
   UiElement* parent_ = nullptr;
   std::vector<std::unique_ptr<UiElement>> children_;
 
+  std::vector<std::unique_ptr<BindingBase>> bindings_;
+
   DISALLOW_COPY_AND_ASSIGN(UiElement);
 };
 
diff --git a/chrome/browser/vr/model/model.h b/chrome/browser/vr/model/model.h
new file mode 100644
index 0000000..50955e7
--- /dev/null
+++ b/chrome/browser/vr/model/model.h
@@ -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.
+
+#ifndef CHROME_BROWSER_VR_MODEL_MODEL_H_
+#define CHROME_BROWSER_VR_MODEL_MODEL_H_
+
+namespace vr {
+
+struct Model {
+  bool loading = false;
+  float load_progress = 0.0f;
+};
+
+}  // namespace vr
+
+#endif  // CHROME_BROWSER_VR_MODEL_MODEL_H_
diff --git a/chrome/browser/vr/run_all_unittests.cc b/chrome/browser/vr/run_all_unittests.cc
index 9cfe7d8..8995188 100644
--- a/chrome/browser/vr/run_all_unittests.cc
+++ b/chrome/browser/vr/run_all_unittests.cc
@@ -30,7 +30,7 @@
     PathService::Get(base::DIR_MODULE, &pak_path);
 #endif
     ui::ResourceBundle::InitSharedInstanceWithPakPath(
-        pak_path.AppendASCII("components_tests_resources.pak"));
+        pak_path.AppendASCII("vr_test.pak"));
   }
 
   void Shutdown() override {
diff --git a/chrome/browser/vr/test/gl_test_environment.cc b/chrome/browser/vr/test/gl_test_environment.cc
new file mode 100644
index 0000000..f319724
--- /dev/null
+++ b/chrome/browser/vr/test/gl_test_environment.cc
@@ -0,0 +1,56 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/vr/test/gl_test_environment.h"
+
+#include "ui/gl/test/gl_image_test_template.h"
+#include "ui/gl/test/gl_surface_test_support.h"
+
+namespace vr {
+
+GlTestEnvironment::GlTestEnvironment(const gfx::Size frame_buffer_size) {
+  // Setup offscreen GL context.
+  gl::GLImageTestSupport::InitializeGL();
+  surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size());
+  context_ = gl::init::CreateGLContext(nullptr, surface_.get(),
+                                       gl::GLContextAttribs());
+  context_->MakeCurrent(surface_.get());
+
+  if (gl::GLContext::GetCurrent()->GetVersionInfo()->IsAtLeastGL(3, 3)) {
+    // To avoid glGetVertexAttribiv(0, ...) failing.
+    glGenVertexArraysOES(1, &vao_);
+    glBindVertexArrayOES(vao_);
+  }
+
+  frame_buffer_ = gl::GLTestHelper::SetupFramebuffer(
+      frame_buffer_size.width(), frame_buffer_size.height());
+  glBindFramebufferEXT(GL_FRAMEBUFFER, frame_buffer_);
+
+  // Create depth buffer.
+  glGenRenderbuffersEXT(1, &depth_render_buffer_);
+  glBindRenderbufferEXT(GL_RENDERBUFFER, depth_render_buffer_);
+  glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
+                           frame_buffer_size.width(),
+                           frame_buffer_size.height());
+  glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+                               GL_RENDERBUFFER, depth_render_buffer_);
+  glBindRenderbufferEXT(GL_RENDERBUFFER, 0);
+}
+
+GlTestEnvironment::~GlTestEnvironment() {
+  glDeleteFramebuffersEXT(1, &frame_buffer_);
+  if (vao_) {
+    glDeleteVertexArraysOES(1, &vao_);
+  }
+  context_->ReleaseCurrent(surface_.get());
+  context_ = nullptr;
+  surface_ = nullptr;
+  gl::GLImageTestSupport::CleanupGL();
+}
+
+GLuint GlTestEnvironment::GetFrameBufferForTesting() {
+  return frame_buffer_;
+}
+
+}  // namespace vr
diff --git a/chrome/browser/vr/test/gl_test_environment.h b/chrome/browser/vr/test/gl_test_environment.h
new file mode 100644
index 0000000..474e3b3b
--- /dev/null
+++ b/chrome/browser/vr/test/gl_test_environment.h
@@ -0,0 +1,32 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_VR_TEST_GL_TEST_ENVIRONMENT_H_
+#define CHROME_BROWSER_VR_TEST_GL_TEST_ENVIRONMENT_H_
+
+#include "ui/gfx/geometry/size.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_surface.h"
+
+namespace vr {
+
+class GlTestEnvironment {
+ public:
+  explicit GlTestEnvironment(const gfx::Size frame_buffer_size);
+  ~GlTestEnvironment();
+
+  GLuint GetFrameBufferForTesting();
+
+ private:
+  scoped_refptr<gl::GLSurface> surface_;
+  scoped_refptr<gl::GLContext> context_;
+  GLuint vao_ = 0;
+  GLuint frame_buffer_ = 0;
+  GLuint depth_render_buffer_ = 0;
+};
+
+}  // namespace vr
+
+#endif  // CHROME_BROWSER_VR_TEST_GL_TEST_ENVIRONMENT_H_
diff --git a/chrome/browser/vr/test/gl_test_environment_unittest.cc b/chrome/browser/vr/test/gl_test_environment_unittest.cc
new file mode 100644
index 0000000..322e876
--- /dev/null
+++ b/chrome/browser/vr/test/gl_test_environment_unittest.cc
@@ -0,0 +1,19 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/vr/test/gl_test_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gl/gl_bindings.h"
+
+namespace vr {
+
+TEST(GlTestEnvironmentTest, InitializeAndCleanup) {
+  GlTestEnvironment gl_test_environment(gfx::Size(100, 100));
+  EXPECT_NE(gl_test_environment.GetFrameBufferForTesting(), 0u);
+  EXPECT_EQ(glGetError(), (GLenum)GL_NO_ERROR);
+  // We just test that clean up doesn't crash.
+}
+
+}  // namespace vr
diff --git a/chrome/browser/vr/test/ui_pixel_test.cc b/chrome/browser/vr/test/ui_pixel_test.cc
new file mode 100644
index 0000000..9ef0452
--- /dev/null
+++ b/chrome/browser/vr/test/ui_pixel_test.cc
@@ -0,0 +1,161 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/vr/test/ui_pixel_test.h"
+
+#include "base/memory/ptr_util.h"
+#include "chrome/browser/vr/browser_ui_interface.h"
+#include "chrome/browser/vr/ui_browser_interface.h"
+#include "chrome/browser/vr/ui_input_manager.h"
+#include "chrome/browser/vr/ui_renderer.h"
+#include "chrome/browser/vr/ui_scene.h"
+#include "third_party/WebKit/public/platform/WebGestureEvent.h"
+#include "third_party/skia/include/core/SkImageEncoder.h"
+#include "third_party/skia/include/core/SkStream.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/test/gl_image_test_template.h"
+
+namespace vr {
+
+namespace {
+
+// Resolution of Pixel Phone for one eye.
+static const gfx::Size kPixelHalfScreen(960, 1080);
+
+}  // namespace
+
+UiPixelTest::UiPixelTest() : frame_buffer_size_(kPixelHalfScreen) {}
+
+UiPixelTest::~UiPixelTest() = default;
+
+void UiPixelTest::SetUp() {
+  gl_test_environment_ =
+      base::MakeUnique<GlTestEnvironment>(frame_buffer_size_);
+
+  // Make content texture.
+  content_texture_ = gl::GLTestHelper::CreateTexture(GL_TEXTURE_2D);
+  // TODO(tiborg): Make GL_TEXTURE_EXTERNAL_OES texture for content and fill it
+  // with fake content.
+  ASSERT_EQ(glGetError(), (GLenum)GL_NO_ERROR);
+
+  browser_ = base::MakeUnique<MockBrowserInterface>();
+  content_input_delegate_ = base::MakeUnique<MockContentInputDelegate>();
+}
+
+void UiPixelTest::TearDown() {
+  ui_.reset();
+  glDeleteTextures(1, &content_texture_);
+  gl_test_environment_.reset();
+}
+
+void UiPixelTest::MakeUi(const UiInitialState& ui_initial_state,
+                         const ToolbarState& toolbar_state) {
+  ui_ = base::MakeUnique<Ui>(browser_.get(), content_input_delegate_.get(),
+                             ui_initial_state);
+  ui_->OnGlInitialized(content_texture_);
+  ui_->GetBrowserUiWeakPtr()->SetToolbarState(toolbar_state);
+}
+
+void UiPixelTest::DrawUi(const gfx::Vector3dF& laser_direction,
+                         const gfx::Point3F& laser_origin,
+                         UiInputManager::ButtonState button_state,
+                         float controller_opacity,
+                         const gfx::Transform& controller_transform,
+                         const gfx::Transform& view_matrix,
+                         const gfx::Transform& proj_matrix) {
+  ControllerInfo controller_info;
+  controller_info.transform = controller_transform;
+  controller_info.opacity = controller_opacity;
+  controller_info.laser_origin = laser_origin;
+  controller_info.touchpad_button_state = button_state;
+  controller_info.app_button_state = UiInputManager::ButtonState::UP;
+  controller_info.home_button_state = UiInputManager::ButtonState::UP;
+  RenderInfo render_info;
+  render_info.head_pose = view_matrix;
+  render_info.left_eye_info.view_matrix = view_matrix;
+  render_info.left_eye_info.proj_matrix = proj_matrix;
+  render_info.left_eye_info.view_proj_matrix = proj_matrix * view_matrix;
+  render_info.right_eye_info = render_info.left_eye_info;
+  render_info.surface_texture_size = frame_buffer_size_;
+  render_info.left_eye_info.viewport = {0, 0, frame_buffer_size_.width(),
+                                        frame_buffer_size_.height()};
+  render_info.right_eye_info.viewport = {0, 0, 0, 0};
+
+  GestureList gesture_list;
+  ui_->scene()->OnBeginFrame(
+      base::TimeTicks(),
+      gfx::Vector3dF(-render_info.head_pose.matrix().get(2, 0),
+                     -render_info.head_pose.matrix().get(2, 1),
+                     -render_info.head_pose.matrix().get(2, 2)));
+  ui_->input_manager()->HandleInput(
+      gfx::Vector3dF(0.0f, 0.0f, -1.0f), controller_info.laser_origin,
+      controller_info.touchpad_button_state, &gesture_list,
+      &controller_info.target_point, &controller_info.reticle_render_target);
+
+  ui_->scene()->PrepareToDraw();
+  ui_->ui_renderer()->Draw(render_info, controller_info);
+
+  // We produce GL errors while rendering. Clear them all so that we can check
+  // for errors of subsequent calls.
+  // TODO(768905): Fix producing errors while rendering.
+  while (glGetError() != GL_NO_ERROR) {
+  }
+}
+
+std::unique_ptr<SkBitmap> UiPixelTest::SaveCurrentFrameBufferToSkBitmap() {
+  // Read pixels from frame buffer.
+  uint32_t* pixels =
+      new uint32_t[frame_buffer_size_.width() * frame_buffer_size_.height()];
+  glReadPixels(0, 0, frame_buffer_size_.width(), frame_buffer_size_.height(),
+               GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+  if (glGetError() != GL_NO_ERROR) {
+    return nullptr;
+  }
+
+  // Flip image vertically since SkBitmap expects the pixels in a different
+  // order.
+  for (int stride = 0; stride < frame_buffer_size_.height() / 2; stride++) {
+    for (int strideOffset = 0; strideOffset < frame_buffer_size_.width();
+         strideOffset++) {
+      size_t topPixelIndex = frame_buffer_size_.width() * stride + strideOffset;
+      size_t bottomPixelIndex = (frame_buffer_size_.height() - stride - 1) *
+                                    frame_buffer_size_.width() +
+                                strideOffset;
+      pixels[topPixelIndex] ^= pixels[bottomPixelIndex];
+      pixels[bottomPixelIndex] ^= pixels[topPixelIndex];
+      pixels[topPixelIndex] ^= pixels[bottomPixelIndex];
+    }
+  }
+
+  // Create bitmap with pixels.
+  std::unique_ptr<SkBitmap> bitmap = base::MakeUnique<SkBitmap>();
+  if (!bitmap->installPixels(SkImageInfo::MakeN32(frame_buffer_size_.width(),
+                                                  frame_buffer_size_.height(),
+                                                  kOpaque_SkAlphaType),
+                             pixels,
+                             sizeof(uint32_t) * frame_buffer_size_.width(),
+                             [](void* pixels, void* context) {
+                               delete[] static_cast<uint32_t*>(pixels);
+                             },
+                             nullptr)) {
+    return nullptr;
+  }
+
+  return bitmap;
+}
+
+bool UiPixelTest::SaveSkBitmapToPng(const SkBitmap& bitmap,
+                                    const std::string& filename) {
+  SkFILEWStream stream(filename.c_str());
+  if (!stream.isValid()) {
+    return false;
+  }
+  if (!SkEncodeImage(&stream, bitmap, SkEncodedImageFormat::kPNG, 100)) {
+    return false;
+  }
+  return true;
+}
+
+}  // namespace vr
diff --git a/chrome/browser/vr/test/ui_pixel_test.h b/chrome/browser/vr/test/ui_pixel_test.h
new file mode 100644
index 0000000..9fb6214
--- /dev/null
+++ b/chrome/browser/vr/test/ui_pixel_test.h
@@ -0,0 +1,52 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_VR_TEST_UI_PIXEL_TEST_H_
+#define CHROME_BROWSER_VR_TEST_UI_PIXEL_TEST_H_
+
+#include "chrome/browser/vr/test/gl_test_environment.h"
+#include "chrome/browser/vr/test/mock_browser_interface.h"
+#include "chrome/browser/vr/test/mock_content_input_delegate.h"
+#include "chrome/browser/vr/toolbar_state.h"
+#include "chrome/browser/vr/ui.h"
+#include "chrome/browser/vr/ui_input_manager.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/transform.h"
+
+namespace vr {
+
+class UiPixelTest : public testing::Test {
+ public:
+  UiPixelTest();
+  ~UiPixelTest() override;
+  void SetUp() override;
+  void TearDown() override;
+
+ protected:
+  void MakeUi(const UiInitialState& ui_initial_state,
+              const ToolbarState& toolbar_state);
+  void DrawUi(const gfx::Vector3dF& laser_direction,
+              const gfx::Point3F& laser_origin,
+              UiInputManager::ButtonState button_state,
+              float controller_opacity,
+              const gfx::Transform& controller_transform,
+              const gfx::Transform& view_matrix,
+              const gfx::Transform& proj_matrix);
+  std::unique_ptr<SkBitmap> SaveCurrentFrameBufferToSkBitmap();
+  bool SaveSkBitmapToPng(const SkBitmap& bitmap, const std::string& filename);
+
+ private:
+  std::unique_ptr<GlTestEnvironment> gl_test_environment_;
+  std::unique_ptr<MockBrowserInterface> browser_;
+  std::unique_ptr<MockContentInputDelegate> content_input_delegate_;
+  GLuint content_texture_ = 0;
+  gfx::Size frame_buffer_size_;
+  std::unique_ptr<Ui> ui_;
+};
+
+}  // namespace vr
+
+#endif  // CHROME_BROWSER_VR_TEST_UI_PIXEL_TEST_H_
diff --git a/chrome/browser/vr/test/ui_scene_manager_test.cc b/chrome/browser/vr/test/ui_scene_manager_test.cc
index a5143aa..e7ea78a7 100644
--- a/chrome/browser/vr/test/ui_scene_manager_test.cc
+++ b/chrome/browser/vr/test/ui_scene_manager_test.cc
@@ -6,6 +6,7 @@
 
 #include "base/memory/ptr_util.h"
 #include "chrome/browser/vr/elements/rect.h"
+#include "chrome/browser/vr/model/model.h"
 #include "chrome/browser/vr/test/constants.h"
 #include "chrome/browser/vr/test/fake_ui_element_renderer.h"
 #include "chrome/browser/vr/ui.h"
@@ -39,24 +40,28 @@
 
 void UiSceneManagerTest::MakeManager(InCct in_cct, InWebVr in_web_vr) {
   scene_ = base::MakeUnique<UiScene>();
+  model_ = base::MakeUnique<Model>();
 
   UiInitialState ui_initial_state;
   ui_initial_state.in_cct = in_cct;
   ui_initial_state.in_web_vr = in_web_vr;
   ui_initial_state.web_vr_autopresentation_expected = false;
-  manager_ = base::MakeUnique<UiSceneManager>(
-      browser_.get(), scene_.get(), &content_input_delegate_, ui_initial_state);
+  manager_ = base::MakeUnique<UiSceneManager>(browser_.get(), scene_.get(),
+                                              &content_input_delegate_,
+                                              model_.get(), ui_initial_state);
 }
 
 void UiSceneManagerTest::MakeAutoPresentedManager() {
   scene_ = base::MakeUnique<UiScene>();
+  model_ = base::MakeUnique<Model>();
 
   UiInitialState ui_initial_state;
   ui_initial_state.in_cct = false;
   ui_initial_state.in_web_vr = false;
   ui_initial_state.web_vr_autopresentation_expected = true;
-  manager_ = base::MakeUnique<UiSceneManager>(
-      browser_.get(), scene_.get(), &content_input_delegate_, ui_initial_state);
+  manager_ = base::MakeUnique<UiSceneManager>(browser_.get(), scene_.get(),
+                                              &content_input_delegate_,
+                                              model_.get(), ui_initial_state);
 }
 
 bool UiSceneManagerTest::IsVisible(UiElementName name) const {
diff --git a/chrome/browser/vr/test/ui_scene_manager_test.h b/chrome/browser/vr/test/ui_scene_manager_test.h
index 4fe65f83..182761c 100644
--- a/chrome/browser/vr/test/ui_scene_manager_test.h
+++ b/chrome/browser/vr/test/ui_scene_manager_test.h
@@ -20,6 +20,7 @@
 class UiElement;
 class UiScene;
 class UiSceneManager;
+struct Model;
 
 class UiSceneManagerTest : public testing::Test {
  public:
@@ -78,6 +79,7 @@
   base::MessageLoop message_loop_;
   std::unique_ptr<MockBrowserInterface> browser_;
   std::unique_ptr<UiScene> scene_;
+  std::unique_ptr<Model> model_;
   std::unique_ptr<UiSceneManager> manager_;
   MockContentInputDelegate content_input_delegate_;
   base::TimeTicks current_time_;
diff --git a/chrome/browser/vr/testapp/BUILD.gn b/chrome/browser/vr/testapp/BUILD.gn
new file mode 100644
index 0000000..536c8dd
--- /dev/null
+++ b/chrome/browser/vr/testapp/BUILD.gn
@@ -0,0 +1,38 @@
+# 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("//tools/grit/repack.gni")
+
+executable("vr_testapp") {
+  sources = [
+    "gl_renderer.cc",
+    "gl_renderer.h",
+    "vr_test_context.cc",
+    "vr_test_context.h",
+    "vr_testapp.cc",
+  ]
+
+  deps = [
+    "//base",
+    "//build/config:exe_and_shlib_deps",
+    "//chrome/browser/resources:vr_shell_resources",
+    "//chrome/browser/vr:vr_common",
+    "//chrome/browser/vr:vr_test_pak",
+    "//components:components_tests_pak",
+    "//components/security_state/core",
+    "//components/toolbar:vector_icons",
+    "//components/tracing:startup_tracing",
+    "//skia",
+    "//ui/accessibility:ax_gen",
+    "//ui/display/types",
+    "//ui/events",
+    "//ui/events:dom_keycode_converter",
+    "//ui/events/ozone:events_ozone_layout",
+    "//ui/gfx/geometry",
+    "//ui/gl",
+    "//ui/gl/init",
+    "//ui/ozone",
+    "//ui/platform_window",
+  ]
+}
diff --git a/chrome/browser/vr/testapp/DEPS b/chrome/browser/vr/testapp/DEPS
new file mode 100644
index 0000000..6e8c1d6
--- /dev/null
+++ b/chrome/browser/vr/testapp/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+  "+ui/ozone",
+  "+ui/events/ozone",
+]
diff --git a/chrome/browser/vr/testapp/gl_renderer.cc b/chrome/browser/vr/testapp/gl_renderer.cc
new file mode 100644
index 0000000..7608fff8
--- /dev/null
+++ b/chrome/browser/vr/testapp/gl_renderer.cc
@@ -0,0 +1,56 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/vr/testapp/gl_renderer.h"
+
+#include "base/threading/thread_task_runner_handle.h"
+#include "chrome/browser/vr/testapp/vr_test_context.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_surface.h"
+#include "ui/gl/init/gl_factory.h"
+
+namespace vr {
+
+GlRenderer::GlRenderer(const scoped_refptr<gl::GLSurface>& surface,
+                       const gfx::Size& size,
+                       vr::VrTestContext* vr)
+    : surface_(surface), size_(size), vr_(vr), weak_ptr_factory_(this) {}
+
+GlRenderer::~GlRenderer() {}
+
+bool GlRenderer::Initialize() {
+  context_ = gl::init::CreateGLContext(nullptr, surface_.get(),
+                                       gl::GLContextAttribs());
+  if (!context_.get()) {
+    LOG(ERROR) << "Failed to create GL context";
+    return false;
+  }
+
+  surface_->Resize(size_, 1.f, gl::GLSurface::ColorSpace::UNSPECIFIED, true);
+
+  if (!context_->MakeCurrent(surface_.get())) {
+    LOG(ERROR) << "Failed to make GL context current";
+    return false;
+  }
+
+  vr_->OnGlInitialized(size_);
+
+  PostRenderFrameTask(gfx::SwapResult::SWAP_ACK);
+  return true;
+}
+
+void GlRenderer::RenderFrame() {
+  context_->MakeCurrent(surface_.get());
+  vr_->DrawFrame();
+  PostRenderFrameTask(surface_->SwapBuffers());
+}
+
+void GlRenderer::PostRenderFrameTask(gfx::SwapResult result) {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::Bind(&GlRenderer::RenderFrame, weak_ptr_factory_.GetWeakPtr()));
+}
+
+}  // namespace vr
diff --git a/chrome/browser/vr/testapp/gl_renderer.h b/chrome/browser/vr/testapp/gl_renderer.h
new file mode 100644
index 0000000..f84d697
--- /dev/null
+++ b/chrome/browser/vr/testapp/gl_renderer.h
@@ -0,0 +1,49 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_VR_TESTAPP_GL_RENDERER_H_
+#define CHROME_BROWSER_VR_TESTAPP_GL_RENDERER_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/swap_result.h"
+
+namespace gl {
+class GLContext;
+class GLSurface;
+}  // namespace gl
+
+namespace vr {
+
+class VrTestContext;
+
+// This class manages an OpenGL context and initiates per-frame rendering.
+class GlRenderer {
+ public:
+  GlRenderer(const scoped_refptr<gl::GLSurface>& surface,
+             const gfx::Size& size,
+             vr::VrTestContext* vr);
+
+  virtual ~GlRenderer();
+
+  bool Initialize();
+  void RenderFrame();
+  void PostRenderFrameTask(gfx::SwapResult result);
+
+ private:
+  scoped_refptr<gl::GLSurface> surface_;
+  gfx::Size size_;
+  vr::VrTestContext* vr_;
+  scoped_refptr<gl::GLContext> context_;
+
+  base::WeakPtrFactory<GlRenderer> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(GlRenderer);
+};
+
+}  // namespace vr
+
+#endif  // CHROME_BROWSER_VR_TESTAPP_GL_RENDERER_H_
diff --git a/chrome/browser/vr/testapp/vr_test_context.cc b/chrome/browser/vr/testapp/vr_test_context.cc
new file mode 100644
index 0000000..2f5d8a9b
--- /dev/null
+++ b/chrome/browser/vr/testapp/vr_test_context.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 "chrome/browser/vr/testapp/vr_test_context.h"
+
+#include "base/i18n/icu_util.h"
+#include "base/memory/ptr_util.h"
+#include "base/path_service.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/vr/toolbar_state.h"
+#include "chrome/browser/vr/ui.h"
+#include "chrome/browser/vr/ui_input_manager.h"
+#include "chrome/browser/vr/ui_interface.h"
+#include "chrome/browser/vr/ui_renderer.h"
+#include "chrome/browser/vr/ui_scene.h"
+#include "chrome/browser/vr/ui_scene_manager.h"
+#include "chrome/browser/vr/vr_shell_renderer.h"
+#include "components/security_state/core/security_state.h"
+#include "components/toolbar/vector_icons.h"
+#include "third_party/WebKit/public/platform/WebGestureEvent.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/events/event.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/gfx/font_list.h"
+
+namespace vr {
+
+namespace {
+
+constexpr float kDefaultViewScale = 1.4f;
+constexpr float kMousePaneWidth = 5.0f;
+constexpr float kMousePaneDepth = 2.0f;
+
+}  // namespace
+
+VrTestContext::VrTestContext()
+    : ui_(base::MakeUnique<Ui>(this, this, UiInitialState())),
+      controller_info_(base::MakeUnique<ControllerInfo>()) {
+  controller_info_->reticle_render_target = nullptr;
+
+  base::FilePath pak_path;
+  PathService::Get(base::DIR_MODULE, &pak_path);
+  ui::ResourceBundle::InitSharedInstanceWithPakPath(
+      pak_path.AppendASCII("vr_test.pak"));
+
+  base::i18n::InitializeICU();
+
+  GURL gurl("https://dangerous.com/dir/file.html");
+  ToolbarState state(gurl, security_state::SecurityLevel::DANGEROUS,
+                     &toolbar::kHttpsInvalidIcon,
+                     base::UTF8ToUTF16("Not secure"), true, false);
+  ui_->SetToolbarState(state);
+  ui_->SetHistoryButtonsEnabled(true, true);
+  ui_->SetLoading(true);
+  ui_->SetLoadProgress(0.4);
+  ui_->SetVideoCapturingIndicator(true);
+  ui_->SetScreenCapturingIndicator(true);
+  ui_->SetAudioCapturingIndicator(true);
+  ui_->SetBluetoothConnectedIndicator(true);
+  ui_->SetLocationAccessIndicator(true);
+}
+
+VrTestContext::~VrTestContext() = default;
+
+void VrTestContext::DrawFrame() {
+  base::TimeTicks current_time = base::TimeTicks::Now();
+
+  const gfx::Transform proj_matrix(kDefaultViewScale, 0, 0, 0, 0,
+                                   kDefaultViewScale, 0, 0, 0, 0, -1, 0, 0, 0,
+                                   -1, 0);
+  const gfx::Transform head_pose;
+  RenderInfo render_info;
+  render_info.head_pose = head_pose;
+  render_info.surface_texture_size = window_size_;
+  render_info.left_eye_info.viewport = gfx::Rect(window_size_);
+  render_info.left_eye_info.view_matrix = head_pose;
+  render_info.left_eye_info.proj_matrix = proj_matrix;
+  render_info.left_eye_info.view_proj_matrix = proj_matrix * head_pose;
+
+  // Update the render position of all UI elements (including desktop).
+  ui_->scene()->OnBeginFrame(current_time, gfx::Vector3dF(0.f, 0.f, -1.0f));
+  ui_->scene()->PrepareToDraw();
+  ui_->OnProjMatrixChanged(render_info.left_eye_info.proj_matrix);
+  ui_->ui_renderer()->Draw(render_info, *controller_info_);
+
+  // TODO(cjgrant): Render viewport-aware elements.
+}
+
+void VrTestContext::HandleInput(ui::Event* event) {
+  if (event->IsKeyEvent()) {
+    const ui::KeyEvent* key_event = event->AsKeyEvent();
+    if (key_event->code() == ui::DomCode::US_F) {
+      ui_->SetFullscreen(true);
+    }
+    return;
+  }
+
+  if (!event->IsMouseEvent()) {
+    return;
+  }
+
+  // Synthesize a controller direction based on mouse position in the window.
+  const ui::MouseEvent* mouse_event = event->AsMouseEvent();
+  gfx::Point3F laser_origin{0.5, -0.5, 0};
+  gfx::Point3F target_point = {
+      kMousePaneWidth * (mouse_event->x() / window_size_.width() - 0.5),
+      kMousePaneWidth * window_size_.height() / window_size_.width() *
+          (-mouse_event->y() / window_size_.height() + 0.5),
+      -kMousePaneDepth};
+  gfx::Vector3dF controller_direction = target_point - laser_origin;
+  controller_info_->laser_origin = laser_origin;
+  controller_info_->reticle_render_target = nullptr;
+
+  GestureList gesture_list;
+  ui_->input_manager()->HandleInput(
+      controller_direction, controller_info_->laser_origin,
+      controller_info_->touchpad_button_state, &gesture_list,
+      &controller_info_->target_point,
+      &controller_info_->reticle_render_target);
+}
+
+void VrTestContext::OnGlInitialized(const gfx::Size& window_size) {
+  window_size_ = window_size;
+  ui_->OnGlInitialized(0);
+}
+
+void VrTestContext::OnContentEnter(const gfx::PointF& normalized_hit_point) {}
+
+void VrTestContext::OnContentLeave() {}
+
+void VrTestContext::OnContentMove(const gfx::PointF& normalized_hit_point) {}
+
+void VrTestContext::OnContentDown(const gfx::PointF& normalized_hit_point) {}
+
+void VrTestContext::OnContentUp(const gfx::PointF& normalized_hit_point) {}
+
+void VrTestContext::OnContentFlingStart(
+    std::unique_ptr<blink::WebGestureEvent> gesture,
+    const gfx::PointF& normalized_hit_point) {}
+
+void VrTestContext::OnContentFlingCancel(
+    std::unique_ptr<blink::WebGestureEvent> gesture,
+    const gfx::PointF& normalized_hit_point) {}
+
+void VrTestContext::OnContentScrollBegin(
+    std::unique_ptr<blink::WebGestureEvent> gesture,
+    const gfx::PointF& normalized_hit_point) {}
+
+void VrTestContext::OnContentScrollUpdate(
+    std::unique_ptr<blink::WebGestureEvent> gesture,
+    const gfx::PointF& normalized_hit_point) {}
+
+void VrTestContext::OnContentScrollEnd(
+    std::unique_ptr<blink::WebGestureEvent> gesture,
+    const gfx::PointF& normalized_hit_point) {}
+
+void VrTestContext::ExitPresent() {}
+void VrTestContext::ExitFullscreen() {}
+void VrTestContext::NavigateBack() {}
+void VrTestContext::ExitCct() {}
+void VrTestContext::OnUnsupportedMode(vr::UiUnsupportedMode mode) {}
+void VrTestContext::OnExitVrPromptResult(vr::UiUnsupportedMode reason,
+                                         vr::ExitVrPromptChoice choice) {}
+void VrTestContext::OnContentScreenBoundsChanged(const gfx::SizeF& bounds) {}
+
+}  // namespace vr
diff --git a/chrome/browser/vr/testapp/vr_test_context.h b/chrome/browser/vr/testapp/vr_test_context.h
new file mode 100644
index 0000000..93fd2fe
--- /dev/null
+++ b/chrome/browser/vr/testapp/vr_test_context.h
@@ -0,0 +1,74 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_VR_TESTAPP_VR_TEST_CONTEXT_H_
+#define CHROME_BROWSER_VR_TESTAPP_VR_TEST_CONTEXT_H_
+
+#include "base/macros.h"
+
+#include <cstdint>
+
+#include "chrome/browser/vr/content_input_delegate.h"
+#include "chrome/browser/vr/ui_browser_interface.h"
+
+namespace ui {
+class Event;
+}
+
+namespace vr {
+
+struct ControllerInfo;
+class Ui;
+
+// This class provides a home for the VR UI in a testapp context, and
+// manipulates the UI according to user input.
+class VrTestContext : public vr::ContentInputDelegate,
+                      public vr::UiBrowserInterface {
+ public:
+  VrTestContext();
+  ~VrTestContext() override;
+
+  void OnGlInitialized(const gfx::Size& window_size);
+  void DrawFrame();
+  void HandleInput(ui::Event* event);
+
+  // vr::ContentInputDelegate.
+  void OnContentEnter(const gfx::PointF& normalized_hit_point) override;
+  void OnContentLeave() override;
+  void OnContentMove(const gfx::PointF& normalized_hit_point) override;
+  void OnContentDown(const gfx::PointF& normalized_hit_point) override;
+  void OnContentUp(const gfx::PointF& normalized_hit_point) override;
+  void OnContentFlingStart(std::unique_ptr<blink::WebGestureEvent> gesture,
+                           const gfx::PointF& normalized_hit_point) override;
+  void OnContentFlingCancel(std::unique_ptr<blink::WebGestureEvent> gesture,
+                            const gfx::PointF& normalized_hit_point) override;
+  void OnContentScrollBegin(std::unique_ptr<blink::WebGestureEvent> gesture,
+                            const gfx::PointF& normalized_hit_point) override;
+  void OnContentScrollUpdate(std::unique_ptr<blink::WebGestureEvent> gesture,
+                             const gfx::PointF& normalized_hit_point) override;
+  void OnContentScrollEnd(std::unique_ptr<blink::WebGestureEvent> gesture,
+                          const gfx::PointF& normalized_hit_point) override;
+
+  // vr::UiBrowserInterface implementation (UI calling to VrShell).
+  void ExitPresent() override;
+  void ExitFullscreen() override;
+  void NavigateBack() override;
+  void ExitCct() override;
+  void OnUnsupportedMode(vr::UiUnsupportedMode mode) override;
+  void OnExitVrPromptResult(vr::UiUnsupportedMode reason,
+                            vr::ExitVrPromptChoice choice) override;
+  void OnContentScreenBoundsChanged(const gfx::SizeF& bounds) override;
+
+ private:
+  std::unique_ptr<Ui> ui_;
+  gfx::Size window_size_;
+
+  std::unique_ptr<ControllerInfo> controller_info_;
+
+  DISALLOW_COPY_AND_ASSIGN(VrTestContext);
+};
+
+}  // namespace vr
+
+#endif  // CHROME_BROWSER_VR_TESTAPP_VR_TEST_CONTEXT_H_
diff --git a/chrome/browser/vr/testapp/vr_testapp.cc b/chrome/browser/vr/testapp/vr_testapp.cc
new file mode 100644
index 0000000..9d88737
--- /dev/null
+++ b/chrome/browser/vr/testapp/vr_testapp.cc
@@ -0,0 +1,300 @@
+// 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 <utility>
+
+#include "base/at_exit.h"
+#include "base/command_line.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 "chrome/browser/vr/testapp/gl_renderer.h"
+#include "chrome/browser/vr/testapp/vr_test_context.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/public/ozone_gpu_test_helper.h"
+#include "ui/ozone/public/ozone_platform.h"
+#include "ui/platform_window/platform_window.h"
+#include "ui/platform_window/platform_window_delegate.h"
+
+// This file is a shameless rip-off of ui/ozone's demo application. Ozone lets
+// us spin up a window and collect input without dealing with Linux platform
+// specifics.
+
+class AppWindow;
+
+class RendererFactory {
+ public:
+  RendererFactory();
+  ~RendererFactory();
+
+  bool Initialize();
+  std::unique_ptr<vr::GlRenderer> CreateRenderer(gfx::AcceleratedWidget widget,
+                                                 const gfx::Size& size,
+                                                 vr::VrTestContext* vr);
+
+ private:
+  // 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(AppWindow* window);
+  void RemoveWindow(AppWindow* 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<AppWindow>> 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 AppWindow : public ui::PlatformWindowDelegate {
+ public:
+  AppWindow(WindowManager* window_manager,
+            RendererFactory* renderer_factory,
+            const gfx::Rect& bounds)
+      : window_manager_(window_manager),
+        renderer_factory_(renderer_factory),
+        vr_(base::MakeUnique<vr::VrTestContext>()),
+        weak_ptr_factory_(this) {
+    platform_window_ =
+        ui::OzonePlatform::GetInstance()->CreatePlatformWindow(this, bounds);
+    platform_window_->Show();
+  }
+  ~AppWindow() override {}
+
+  gfx::AcceleratedWidget GetAcceleratedWidget() {
+    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(&AppWindow::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();
+    else
+      vr_->HandleInput(event);
+  }
+  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(), vr_.get());
+    renderer_->Initialize();
+  }
+
+  WindowManager* window_manager_;      // Not owned.
+  RendererFactory* renderer_factory_;  // Not owned.
+
+  std::unique_ptr<vr::VrTestContext> vr_;
+  std::unique_ptr<vr::GlRenderer> renderer_;
+
+  // Window-related state.
+  std::unique_ptr<ui::PlatformWindow> platform_window_;
+  gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget;
+
+  base::WeakPtrFactory<AppWindow> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(AppWindow);
+};
+
+RendererFactory::RendererFactory() {}
+
+RendererFactory::~RendererFactory() {}
+
+bool RendererFactory::Initialize() {
+  ui::OzonePlatform::InitParams params;
+  params.single_process = true;
+  ui::OzonePlatform::InitializeForGPU(params);
+
+  if (gl::init::InitializeGLOneOff() &&
+      gpu_helper_.Initialize(base::ThreadTaskRunnerHandle::Get())) {
+    return true;
+  }
+  return false;
+}
+
+std::unique_ptr<vr::GlRenderer> RendererFactory::CreateRenderer(
+    gfx::AcceleratedWidget widget,
+    const gfx::Size& size,
+    vr::VrTestContext* vr) {
+  scoped_refptr<gl::GLSurface> surface = gl::init::CreateViewGLSurface(widget);
+  if (!surface) {
+    LOG(FATAL) << "Failed to create GL surface";
+    return nullptr;
+  }
+  return base::MakeUnique<vr::GlRenderer>(surface, size, vr);
+}
+
+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";
+  }
+
+  DCHECK(delegate_);
+  delegate_->AddObserver(this);
+  delegate_->Initialize();
+  OnConfigurationChanged();
+}
+
+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<AppWindow> window(
+        new AppWindow(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;
+
+  base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+      switches::kUseGL, gl::kGLImplementationEGLName);
+
+  // Build UI thread message loop. This is used by platform
+  // implementations for event polling & running background tasks.
+  base::MessageLoopForUI message_loop;
+  base::TaskScheduler::CreateAndStartWithDefaultParams("VrUiViewer");
+
+  ui::OzonePlatform::InitParams params;
+  params.single_process = true;
+  ui::OzonePlatform::InitializeForUI(params);
+  ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine()
+      ->SetCurrentLayoutByName("us");
+
+  base::RunLoop run_loop;
+
+  WindowManager window_manager(run_loop.QuitClosure());
+
+  run_loop.Run();
+
+  return 0;
+}
diff --git a/chrome/browser/vr/ui.cc b/chrome/browser/vr/ui.cc
index 32b2f838..fef9b05 100644
--- a/chrome/browser/vr/ui.cc
+++ b/chrome/browser/vr/ui.cc
@@ -6,6 +6,7 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "chrome/browser/vr/model/model.h"
 #include "chrome/browser/vr/ui_input_manager.h"
 #include "chrome/browser/vr/ui_interface.h"
 #include "chrome/browser/vr/ui_renderer.h"
@@ -19,28 +20,111 @@
        ContentInputDelegate* content_input_delegate,
        const vr::UiInitialState& ui_initial_state)
     : scene_(base::MakeUnique<vr::UiScene>()),
+      model_(base::MakeUnique<vr::Model>()),
       scene_manager_(
           base::MakeUnique<vr::UiSceneManager>(browser,
                                                scene_.get(),
                                                content_input_delegate,
-                                               ui_initial_state)) {}
+                                               model_.get(),
+                                               ui_initial_state)),
+      input_manager_(base::MakeUnique<vr::UiInputManager>(scene_.get())),
+      weak_ptr_factory_(this) {}
 
 Ui::~Ui() = default;
 
-UiInterface* Ui::ui() {
-  return scene_manager_.get();
+base::WeakPtr<vr::BrowserUiInterface> Ui::GetBrowserUiWeakPtr() {
+  return weak_ptr_factory_.GetWeakPtr();
 }
 
-base::WeakPtr<vr::BrowserUiInterface> Ui::GetBrowserUiWeakPtr() {
-  return scene_manager_->GetWeakPtr();
+void Ui::SetWebVrMode(bool enabled, bool show_toast) {
+  scene_manager_->SetWebVrMode(enabled, show_toast);
+}
+
+void Ui::SetFullscreen(bool enabled) {
+  scene_manager_->SetFullscreen(enabled);
+}
+
+void Ui::SetToolbarState(const ToolbarState& state) {
+  scene_manager_->SetToolbarState(state);
+}
+
+void Ui::SetIncognito(bool enabled) {
+  scene_manager_->SetIncognito(enabled);
+}
+
+void Ui::SetWebVrSecureOrigin(bool secure) {
+  scene_manager_->SetWebVrSecureOrigin(secure);
+}
+
+void Ui::SetLoading(bool loading) {
+  model_->loading = loading;
+}
+
+void Ui::SetLoadProgress(float progress) {
+  model_->load_progress = progress;
+}
+
+void Ui::SetIsExiting() {
+  scene_manager_->SetIsExiting();
+}
+
+void Ui::SetHistoryButtonsEnabled(bool can_go_back, bool can_go_forward) {
+  scene_manager_->SetHistoryButtonsEnabled(can_go_back, can_go_forward);
+}
+
+void Ui::SetVideoCapturingIndicator(bool enabled) {
+  scene_manager_->SetVideoCapturingIndicator(enabled);
+}
+
+void Ui::SetScreenCapturingIndicator(bool enabled) {
+  scene_manager_->SetScreenCapturingIndicator(enabled);
+}
+
+void Ui::SetAudioCapturingIndicator(bool enabled) {
+  scene_manager_->SetAudioCapturingIndicator(enabled);
+}
+
+void Ui::SetBluetoothConnectedIndicator(bool enabled) {
+  scene_manager_->SetBluetoothConnectedIndicator(enabled);
+}
+
+void Ui::SetLocationAccessIndicator(bool enabled) {
+  scene_manager_->SetLocationAccessIndicator(enabled);
+}
+
+void Ui::SetExitVrPromptEnabled(bool enabled, UiUnsupportedMode reason) {
+  scene_manager_->SetExitVrPromptEnabled(enabled, reason);
+}
+
+bool Ui::ShouldRenderWebVr() {
+  return scene_manager_->ShouldRenderWebVr();
 }
 
 void Ui::OnGlInitialized(unsigned int content_texture_id) {
-  ui()->OnGlInitialized(content_texture_id);
-  input_manager_ = base::MakeUnique<vr::UiInputManager>(scene_.get());
   vr_shell_renderer_ = base::MakeUnique<vr::VrShellRenderer>();
   ui_renderer_ =
       base::MakeUnique<vr::UiRenderer>(scene_.get(), vr_shell_renderer_.get());
+  scene_manager_->OnGlInitialized(content_texture_id);
+}
+
+void Ui::OnAppButtonClicked() {
+  scene_manager_->OnAppButtonClicked();
+}
+
+void Ui::OnAppButtonGesturePerformed(UiInterface::Direction direction) {
+  scene_manager_->OnAppButtonGesturePerformed(direction);
+}
+
+void Ui::OnProjMatrixChanged(const gfx::Transform& proj_matrix) {
+  scene_manager_->OnProjMatrixChanged(proj_matrix);
+}
+
+void Ui::OnWebVrFrameAvailable() {
+  scene_manager_->OnWebVrFrameAvailable();
+}
+
+void Ui::OnWebVrTimedOut() {
+  scene_manager_->OnWebVrTimedOut();
 }
 
 }  // namespace vr
diff --git a/chrome/browser/vr/ui.h b/chrome/browser/vr/ui.h
index ec0a3d7..abbbf9a 100644
--- a/chrome/browser/vr/ui.h
+++ b/chrome/browser/vr/ui.h
@@ -9,6 +9,7 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "chrome/browser/vr/browser_ui_interface.h"
 #include "chrome/browser/vr/ui_interface.h"
 
 namespace vr {
@@ -20,6 +21,7 @@
 class UiScene;
 class UiSceneManager;
 class VrShellRenderer;
+struct Model;
 }  // namespace vr
 
 namespace vr {
@@ -32,18 +34,12 @@
 
 // This class manages all GLThread owned objects and GL rendering for VrShell.
 // It is not threadsafe and must only be used on the GL thread.
-class Ui {
+class Ui : public BrowserUiInterface, public UiInterface {
  public:
   Ui(UiBrowserInterface* browser,
      ContentInputDelegate* content_input_delegate,
      const vr::UiInitialState& ui_initial_state);
-  virtual ~Ui();
-
-  base::WeakPtr<vr::BrowserUiInterface> GetBrowserUiWeakPtr();
-
-  void OnGlInitialized(unsigned int content_texture_id);
-
-  UiInterface* ui();
+  ~Ui() override;
 
   // TODO(crbug.com/767957): Refactor to hide these behind the UI interface.
   UiScene* scene() { return scene_.get(); }
@@ -51,14 +47,45 @@
   UiRenderer* ui_renderer() { return ui_renderer_.get(); }
   UiInputManager* input_manager() { return input_manager_.get(); }
 
+  base::WeakPtr<vr::BrowserUiInterface> GetBrowserUiWeakPtr();
+
+  // BrowserUiInterface
+  void SetWebVrMode(bool enabled, bool show_toast) override;
+  void SetFullscreen(bool enabled) override;
+  void SetToolbarState(const ToolbarState& state) override;
+  void SetIncognito(bool enabled) override;
+  void SetWebVrSecureOrigin(bool secure) override;
+  void SetLoading(bool loading) override;
+  void SetLoadProgress(float progress) override;
+  void SetIsExiting() override;
+  void SetHistoryButtonsEnabled(bool can_go_back, bool can_go_forward) override;
+  void SetVideoCapturingIndicator(bool enabled) override;
+  void SetScreenCapturingIndicator(bool enabled) override;
+  void SetAudioCapturingIndicator(bool enabled) override;
+  void SetBluetoothConnectedIndicator(bool enabled) override;
+  void SetLocationAccessIndicator(bool enabled) override;
+  void SetExitVrPromptEnabled(bool enabled, UiUnsupportedMode reason) override;
+
+  // UiInterface
+  bool ShouldRenderWebVr() override;
+  void OnGlInitialized(unsigned int content_texture_id) override;
+  void OnAppButtonClicked() override;
+  void OnAppButtonGesturePerformed(UiInterface::Direction direction) override;
+  void OnProjMatrixChanged(const gfx::Transform& proj_matrix) override;
+  void OnWebVrFrameAvailable() override;
+  void OnWebVrTimedOut() override;
+
  private:
   // This state may be further abstracted into a SkiaUi object.
   std::unique_ptr<vr::UiScene> scene_;
+  std::unique_ptr<vr::Model> model_;
   std::unique_ptr<vr::UiSceneManager> scene_manager_;
   std::unique_ptr<vr::VrShellRenderer> vr_shell_renderer_;
   std::unique_ptr<vr::UiInputManager> input_manager_;
   std::unique_ptr<vr::UiRenderer> ui_renderer_;
 
+  base::WeakPtrFactory<Ui> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(Ui);
 };
 
diff --git a/chrome/browser/vr/ui_interface.h b/chrome/browser/vr/ui_interface.h
index 158a4f4..9f882e2 100644
--- a/chrome/browser/vr/ui_interface.h
+++ b/chrome/browser/vr/ui_interface.h
@@ -11,8 +11,6 @@
 
 namespace vr {
 
-class UiScene;
-
 // This is the platform-specific interface to the VR UI.
 class UiInterface {
  public:
@@ -26,8 +24,6 @@
 
   virtual ~UiInterface() {}
 
-  virtual UiScene* scene() = 0;
-
   virtual bool ShouldRenderWebVr() = 0;
 
   virtual void OnGlInitialized(unsigned int content_texture_id) = 0;
diff --git a/chrome/browser/vr/ui_pixeltest.cc b/chrome/browser/vr/ui_pixeltest.cc
new file mode 100644
index 0000000..1c93b843
--- /dev/null
+++ b/chrome/browser/vr/ui_pixeltest.cc
@@ -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.
+
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/vr/test/constants.h"
+#include "chrome/browser/vr/test/ui_pixel_test.h"
+#include "chrome/browser/vr/toolbar_state.h"
+#include "components/toolbar/vector_icons.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace vr {
+
+namespace {
+
+static const gfx::Transform kIdentity;
+
+}  // namespace
+
+TEST_F(UiPixelTest, DrawVrBrowsingMode) {
+  // Set up scene.
+  UiInitialState ui_initial_state;
+  ui_initial_state.in_cct = false;
+  ui_initial_state.in_web_vr = false;
+  ui_initial_state.web_vr_autopresentation_expected = false;
+  MakeUi(ui_initial_state,
+         ToolbarState(GURL("https://example.com"), security_state::SECURE,
+                      &toolbar::kHttpsValidIcon, base::UTF8ToUTF16("Secure"),
+                      true, false));
+
+  // Draw UI.
+  DrawUi(gfx::Vector3dF(0.0f, 0.0f, -1.0f), gfx::Point3F(0.5f, -0.5f, 0.0f),
+         UiInputManager::ButtonState::UP, 1.0f, kIdentity, kIdentity,
+         kProjMatrix);
+
+  // Read pixels into SkBitmap.
+  auto bitmap = SaveCurrentFrameBufferToSkBitmap();
+  EXPECT_TRUE(bitmap);
+}
+
+}  // namespace vr
diff --git a/chrome/browser/vr/ui_renderer.h b/chrome/browser/vr/ui_renderer.h
index 0bde2cbd..cf3962ef 100644
--- a/chrome/browser/vr/ui_renderer.h
+++ b/chrome/browser/vr/ui_renderer.h
@@ -20,12 +20,12 @@
 struct ControllerInfo {
   gfx::Point3F target_point;
   gfx::Point3F laser_origin;
-  UiInputManager::ButtonState touchpad_button_state;
-  UiInputManager::ButtonState app_button_state;
-  UiInputManager::ButtonState home_button_state;
+  UiInputManager::ButtonState touchpad_button_state = UiInputManager::UP;
+  UiInputManager::ButtonState app_button_state = UiInputManager::UP;
+  UiInputManager::ButtonState home_button_state = UiInputManager::UP;
   gfx::Transform transform;
-  float opacity;
-  UiElement* reticle_render_target;
+  float opacity = 1.0f;
+  UiElement* reticle_render_target = nullptr;
 };
 
 // Provides information for rendering such as the viewport and view/projection
diff --git a/chrome/browser/vr/ui_scene.cc b/chrome/browser/vr/ui_scene.cc
index 1fff097..e046a40 100644
--- a/chrome/browser/vr/ui_scene.cc
+++ b/chrome/browser/vr/ui_scene.cc
@@ -10,6 +10,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/time/time.h"
 #include "base/values.h"
+#include "chrome/browser/vr/databinding/binding_base.h"
 #include "chrome/browser/vr/elements/draw_phase.h"
 #include "chrome/browser/vr/elements/ui_element.h"
 #include "ui/gfx/transform.h"
@@ -66,6 +67,12 @@
   }
 
   for (auto& element : *root_element_) {
+    for (auto& binding : element.bindings()) {
+      binding->Update();
+    }
+  }
+
+  for (auto& element : *root_element_) {
     element.LayOutChildren();
     element.AdjustRotationForHeadPose(look_at);
   }
diff --git a/chrome/browser/vr/ui_scene_manager.cc b/chrome/browser/vr/ui_scene_manager.cc
index d34836be..aa3c4e8 100644
--- a/chrome/browser/vr/ui_scene_manager.cc
+++ b/chrome/browser/vr/ui_scene_manager.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/memory/ptr_util.h"
+#include "chrome/browser/vr/databinding/binding.h"
 #include "chrome/browser/vr/elements/button.h"
 #include "chrome/browser/vr/elements/close_button_texture.h"
 #include "chrome/browser/vr/elements/content_element.h"
@@ -18,7 +19,6 @@
 #include "chrome/browser/vr/elements/grid.h"
 #include "chrome/browser/vr/elements/invisible_hit_target.h"
 #include "chrome/browser/vr/elements/linear_layout.h"
-#include "chrome/browser/vr/elements/loading_indicator.h"
 #include "chrome/browser/vr/elements/rect.h"
 #include "chrome/browser/vr/elements/system_indicator.h"
 #include "chrome/browser/vr/elements/text.h"
@@ -30,6 +30,7 @@
 #include "chrome/browser/vr/elements/url_bar.h"
 #include "chrome/browser/vr/elements/viewport_aware_root.h"
 #include "chrome/browser/vr/elements/webvr_url_toast.h"
+#include "chrome/browser/vr/model/model.h"
 #include "chrome/browser/vr/target_property.h"
 #include "chrome/browser/vr/ui.h"
 #include "chrome/browser/vr/ui_browser_interface.h"
@@ -42,12 +43,30 @@
 
 namespace vr {
 
+namespace {
+
+template <typename P>
+void BindColor(UiSceneManager* model, Rect* rect, P p) {
+  rect->AddBinding(base::MakeUnique<Binding<SkColor>>(
+      base::Bind([](UiSceneManager* m, P p) { return (m->color_scheme()).*p; },
+                 base::Unretained(model), p),
+      base::Bind(
+          [](Rect* r, const SkColor& c) {
+            r->SetCenterColor(c);
+            r->SetEdgeColor(c);
+          },
+          base::Unretained(rect))));
+}
+
+}  // namespace
+
 using TargetProperty::BOUNDS;
 using TargetProperty::TRANSFORM;
 
 UiSceneManager::UiSceneManager(UiBrowserInterface* browser,
                                UiScene* scene,
                                ContentInputDelegate* content_input_delegate,
+                               Model* model,
                                const UiInitialState& ui_initial_state)
     : browser_(browser),
       scene_(scene),
@@ -56,8 +75,7 @@
       started_for_autopresentation_(
           ui_initial_state.web_vr_autopresentation_expected),
       showing_web_vr_splash_screen_(
-          ui_initial_state.web_vr_autopresentation_expected),
-      weak_ptr_factory_(this) {
+          ui_initial_state.web_vr_autopresentation_expected) {
   Create2dBrowsingSubtreeRoots();
   CreateWebVrRoot();
   CreateBackground();
@@ -65,7 +83,7 @@
   CreateContentQuad(content_input_delegate);
   CreateSecurityWarnings();
   CreateSystemIndicators();
-  CreateUrlBar();
+  CreateUrlBar(model);
   CreateWebVrUrlToast();
   CreateCloseButton();
   CreateScreenDimmer();
@@ -397,8 +415,7 @@
   scene_->AddUiElement(k2dBrowsingRoot, std::move(element));
 }
 
-void UiSceneManager::CreateUrlBar() {
-  // TODO(cjgrant): Incorporate final size and position.
+void UiSceneManager::CreateUrlBar(Model* model) {
   auto url_bar = base::MakeUnique<UrlBar>(
       512,
       base::Bind(&UiSceneManager::OnBackButtonClicked, base::Unretained(this)),
@@ -414,16 +431,39 @@
   control_elements_.push_back(url_bar.get());
   scene_->AddUiElement(k2dBrowsingForeground, std::move(url_bar));
 
-  auto indicator = base::MakeUnique<LoadingIndicator>(256);
-  indicator->set_name(kLoadingIndicator);
-  indicator->set_draw_phase(kPhaseForeground);
-  indicator->SetTranslate(0, kLoadingIndicatorVerticalOffset,
-                          kLoadingIndicatorDepthOffset);
-  indicator->SetSize(kLoadingIndicatorWidth, kLoadingIndicatorHeight);
-  indicator->set_y_anchoring(YAnchoring::YTOP);
-  loading_indicator_ = indicator.get();
-  control_elements_.push_back(indicator.get());
-  scene_->AddUiElement(kUrlBar, std::move(indicator));
+  auto indicator_bg = base::MakeUnique<Rect>();
+  indicator_bg->set_name(kLoadingIndicator);
+  indicator_bg->set_draw_phase(kPhaseForeground);
+  indicator_bg->SetTranslate(0, kLoadingIndicatorVerticalOffset,
+                             kLoadingIndicatorDepthOffset);
+  indicator_bg->SetSize(kLoadingIndicatorWidth, kLoadingIndicatorHeight);
+  indicator_bg->set_y_anchoring(YAnchoring::YTOP);
+  indicator_bg->SetTransitionedProperties({OPACITY});
+  indicator_bg->set_corner_radius(kLoadingIndicatorHeight * 0.5f);
+  indicator_bg->AddBinding(VR_BIND_FUNC(bool, Model, model, loading, Rect,
+                                        indicator_bg.get(), SetVisible));
+  BindColor(this, indicator_bg.get(),
+            &ColorScheme::loading_indicator_background);
+
+  scene_->AddUiElement(kUrlBar, std::move(indicator_bg));
+
+  auto indicator_fg = base::MakeUnique<Rect>();
+  indicator_fg->set_draw_phase(kPhaseForeground);
+  indicator_fg->set_x_anchoring(XLEFT);
+  indicator_fg->set_corner_radius(kLoadingIndicatorHeight * 0.5f);
+  indicator_fg->set_hit_testable(false);
+  BindColor(this, indicator_fg.get(),
+            &ColorScheme::loading_indicator_foreground);
+  indicator_fg->AddBinding(base::MakeUnique<Binding<float>>(
+      base::Bind([](Model* m) { return m->load_progress; },
+                 base::Unretained(model)),
+      base::Bind(
+          [](Rect* r, const float& value) {
+            r->SetSize(kLoadingIndicatorWidth * value, kLoadingIndicatorHeight);
+            r->SetTranslate(r->size().width() * 0.5f, 0.0f, 0.001f);
+          },
+          base::Unretained(indicator_fg.get()))));
+  scene_->AddUiElement(kLoadingIndicator, std::move(indicator_fg));
 }
 
 TransientElement* UiSceneManager::AddTransientParent(UiElementName name,
@@ -544,10 +584,6 @@
                        std::move(element));
 }
 
-base::WeakPtr<UiSceneManager> UiSceneManager::GetWeakPtr() {
-  return weak_ptr_factory_.GetWeakPtr();
-}
-
 void UiSceneManager::SetWebVrMode(bool web_vr, bool show_toast) {
   if (web_vr_mode_ == web_vr && web_vr_show_toast_ == show_toast) {
     return;
@@ -772,10 +808,6 @@
   ConfigureScene();
 }
 
-UiScene* UiSceneManager::scene() {
-  return scene_;
-}
-
 bool UiSceneManager::ShouldRenderWebVr() {
   return scene_->web_vr_rendering_enabled();
 }
@@ -886,11 +918,11 @@
 }
 
 void UiSceneManager::SetLoading(bool loading) {
-  loading_indicator_->SetLoading(loading);
+  NOTREACHED();
 }
 
 void UiSceneManager::SetLoadProgress(float progress) {
-  loading_indicator_->SetLoadProgress(progress);
+  NOTREACHED();
 }
 
 void UiSceneManager::SetIsExiting() {
diff --git a/chrome/browser/vr/ui_scene_manager.h b/chrome/browser/vr/ui_scene_manager.h
index 0168ad7..8d408ad 100644
--- a/chrome/browser/vr/ui_scene_manager.h
+++ b/chrome/browser/vr/ui_scene_manager.h
@@ -7,7 +7,6 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
-#include "base/memory/weak_ptr.h"
 #include "base/values.h"
 #include "chrome/browser/vr/browser_ui_interface.h"
 #include "chrome/browser/vr/color_scheme.h"
@@ -21,7 +20,6 @@
 class ContentElement;
 class ContentInputDelegate;
 class Grid;
-class LoadingIndicator;
 class Rect;
 class TransientElement;
 class WebVrUrlToast;
@@ -30,6 +28,7 @@
 class UiScene;
 class UrlBar;
 class ExitPrompt;
+struct Model;
 struct UiInitialState;
 
 // The scene manager creates and maintains a UiElement hierarchy.
@@ -55,7 +54,6 @@
 //           kScreenCaptureIndicator
 //           kLocationAccessIndicator
 //           kBluetoothConnectedIndicator
-//           kLoadingIndicator
 //       kExitPrompt
 //         kExitPromptBackplane
 //       kExclusiveScreenToastTransientParent
@@ -90,19 +88,16 @@
   UiSceneManager(UiBrowserInterface* browser,
                  UiScene* scene,
                  ContentInputDelegate* content_input_delegate,
+                 Model* model,
                  const UiInitialState& ui_initial_state);
   ~UiSceneManager() override;
 
-  base::WeakPtr<UiSceneManager> GetWeakPtr();
-
   // UiBrowserInterface.
-  void SetWebVrMode(bool web_vr, bool show_toast) override;
   void SetFullscreen(bool fullscreen) override;
   void SetIncognito(bool incognito) override;
   void SetToolbarState(const ToolbarState& state) override;
   void SetWebVrSecureOrigin(bool secure) override;
-  void SetLoading(bool loading) override;
-  void SetLoadProgress(float progress) override;
+  void SetWebVrMode(bool web_vr, bool show_toast) override;
   void SetIsExiting() override;
   void SetVideoCapturingIndicator(bool enabled) override;
   void SetScreenCapturingIndicator(bool enabled) override;
@@ -111,8 +106,13 @@
   void SetBluetoothConnectedIndicator(bool enabled) override;
   void SetHistoryButtonsEnabled(bool can_go_back, bool can_go_forward) override;
 
+  // TODO(vollick): once we have migrated to a model, these methods can be
+  // removed. They will be left here for now as BrowserUiInterface is an
+  // abstract base class. The Set.. methods above are all on the chopping block.
+  void SetLoading(bool loading) override;
+  void SetLoadProgress(float progress) override;
+
   // UiInterface.
-  UiScene* scene() override;
   bool ShouldRenderWebVr() override;
   void OnGlInitialized(unsigned int content_texture_id) override;
   void OnAppButtonClicked() override;
@@ -127,6 +127,9 @@
   void OnSecurityIconClickedForTesting();
   void OnExitPromptChoiceForTesting(bool chose_exit);
 
+  // TODO(vollick): this should move to the model.
+  const ColorScheme& color_scheme() const;
+
  private:
   void Create2dBrowsingSubtreeRoots();
   void CreateWebVrRoot();
@@ -138,7 +141,7 @@
   void CreateUnderDevelopmentNotice();
   void CreateBackground();
   void CreateViewportAwareRoot();
-  void CreateUrlBar();
+  void CreateUrlBar(Model* model);
   void CreateWebVrUrlToast();
   void CreateCloseButton();
   void CreateExitPrompt();
@@ -156,7 +159,6 @@
   void OnCloseButtonClicked();
   void OnUnsupportedMode(UiUnsupportedMode mode);
   ColorScheme::Mode mode() const;
-  const ColorScheme& color_scheme() const;
 
   TransientElement* AddTransientParent(UiElementName name,
                                        UiElementName parent_name,
@@ -189,7 +191,6 @@
   UrlBar* url_bar_ = nullptr;
   TransientElement* webvr_url_toast_transient_parent_ = nullptr;
   WebVrUrlToast* webvr_url_toast_ = nullptr;
-  LoadingIndicator* loading_indicator_ = nullptr;
 
   std::vector<UiElement*> system_indicators_;
 
@@ -221,8 +222,6 @@
   gfx::SizeF last_content_screen_bounds_;
   float last_content_aspect_ratio_ = 0.0f;
 
-  base::WeakPtrFactory<UiSceneManager> weak_ptr_factory_;
-
   DISALLOW_COPY_AND_ASSIGN(UiSceneManager);
 };
 
diff --git a/chrome/browser/vr/ui_scene_manager_unittest.cc b/chrome/browser/vr/ui_scene_manager_unittest.cc
index e9cea79..55b8abd 100644
--- a/chrome/browser/vr/ui_scene_manager_unittest.cc
+++ b/chrome/browser/vr/ui_scene_manager_unittest.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/vr/elements/content_element.h"
 #include "chrome/browser/vr/elements/ui_element.h"
 #include "chrome/browser/vr/elements/ui_element_name.h"
+#include "chrome/browser/vr/model/model.h"
 #include "chrome/browser/vr/target_property.h"
 #include "chrome/browser/vr/test/animation_utils.h"
 #include "chrome/browser/vr/test/constants.h"
@@ -28,19 +29,19 @@
 using TargetProperty::OPACITY;
 
 namespace {
-std::set<UiElementName> kFloorCeilingBackgroundElements = {
+const std::set<UiElementName> kFloorCeilingBackgroundElements = {
     kBackgroundFront, kBackgroundLeft,   kBackgroundBack, kBackgroundRight,
     kBackgroundTop,   kBackgroundBottom, kCeiling,        kFloor};
-std::set<UiElementName> kElementsVisibleInBrowsing = {
+const std::set<UiElementName> kElementsVisibleInBrowsing = {
     kBackgroundFront, kBackgroundLeft, kBackgroundBack,
     kBackgroundRight, kBackgroundTop,  kBackgroundBottom,
     kCeiling,         kFloor,          kContentQuad,
     kBackplane,       kUrlBar,         kUnderDevelopmentNotice};
-std::set<UiElementName> kElementsVisibleWithExitPrompt = {
+const std::set<UiElementName> kElementsVisibleWithExitPrompt = {
     kBackgroundFront, kBackgroundLeft,     kBackgroundBack, kBackgroundRight,
     kBackgroundTop,   kBackgroundBottom,   kCeiling,        kFloor,
     kExitPrompt,      kExitPromptBackplane};
-std::set<UiElementName> kHitTestableElements = {
+const std::set<UiElementName> kHitTestableElements = {
     kFloor,
     kCeiling,
     kBackplane,
@@ -56,7 +57,7 @@
     kLoadingIndicator,
     kCloseButton,
 };
-std::set<UiElementName> kElementsVisibleWithExitWarning = {
+const std::set<UiElementName> kElementsVisibleWithExitWarning = {
     kScreenDimmer, kExitWarning,
 };
 
@@ -643,6 +644,21 @@
   CheckRendererOpacityRecursive(&scene_->root_element());
 }
 
+TEST_F(UiSceneManagerTest, LoadingIndicatorBindings) {
+  MakeManager(kNotInCct, kNotInWebVr);
+  model_->loading = true;
+  model_->load_progress = 0.5f;
+  AnimateBy(MsToDelta(200));
+  EXPECT_TRUE(VerifyVisibility({kLoadingIndicator}, true));
+  UiElement* loading_indicator = scene_->GetUiElementByName(kLoadingIndicator);
+  UiElement* loading_indicator_fg = loading_indicator->children().back().get();
+  EXPECT_FLOAT_EQ(loading_indicator->size().width() * 0.5f,
+                  loading_indicator_fg->size().width());
+  float tx =
+      loading_indicator_fg->GetTargetTransform().Apply().matrix().get(0, 3);
+  EXPECT_FLOAT_EQ(loading_indicator->size().width() * 0.25f, tx);
+}
+
 TEST_F(UiSceneManagerTest, ExitWarning) {
   MakeManager(kNotInCct, kNotInWebVr);
   manager_->SetIsExiting();
diff --git a/chrome/browser/vr/vr_shell_renderer.cc b/chrome/browser/vr/vr_shell_renderer.cc
index b9dd7559..16b4b0e7 100644
--- a/chrome/browser/vr/vr_shell_renderer.cc
+++ b/chrome/browser/vr/vr_shell_renderer.cc
@@ -1101,6 +1101,11 @@
     float opacity,
     gfx::SizeF element_size,
     float corner_radius) {
+  // TODO(vollick): handle drawing this degenerate situation crbug.com/768922
+  if (corner_radius * 2.0 > element_size.width() ||
+      corner_radius * 2.0 > element_size.height()) {
+    return;
+  }
   TexturedQuadRenderer* renderer = texture_location == kTextureLocationExternal
                                        ? GetExternalTexturedQuadRenderer()
                                        : GetTexturedQuadRenderer();
diff --git a/chrome/chrome_watcher/chrome_watcher_main.cc b/chrome/chrome_watcher/chrome_watcher_main.cc
index 51796f7..da878d96 100644
--- a/chrome/chrome_watcher/chrome_watcher_main.cc
+++ b/chrome/chrome_watcher/chrome_watcher_main.cc
@@ -140,10 +140,11 @@
 #endif  // NDEBUG
 }
 
-base::FilePath GetLogFileName() {
-  std::string filename;
-  std::unique_ptr<base::Environment> env(base::Environment::Create());
-  if (env->GetVar(env_vars::kLogFileName, &filename) && !filename.empty())
+base::FilePath GetLogFileName(const base::CommandLine& command_line) {
+  std::string filename = command_line.GetSwitchValueASCII(switches::kLogFile);
+  if (filename.empty())
+    base::Environment::Create()->GetVar(env_vars::kLogFileName, &filename);
+  if (!filename.empty())
     return base::FilePath::FromUTF8Unsafe(filename);
 
   const base::FilePath log_filename(FILE_PATH_LITERAL("chrome_debug.log"));
@@ -173,7 +174,7 @@
   // Don't resolve the log path unless we need to. Otherwise we leave an open
   // ALPC handle after sandbox lockdown on Windows.
   if ((logging_dest & LOG_TO_FILE) != 0) {
-    log_path = GetLogFileName();
+    log_path = GetLogFileName(command_line);
 
   } else {
     log_locking_state = DONT_LOCK_LOG_FILE;
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index 06d20421..81e5011d 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -6,6 +6,7 @@
 import("//build/util/process_version.gni")
 import("//chrome/common/features.gni")
 import("//chrome/process_version_rc_template.gni")  # For branding_file_path.
+import("//components/nacl/features.gni")
 import("//extensions/features/features.gni")
 import("//media/media_options.gni")
 import("//mojo/public/tools/bindings/mojom.gni")
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index f7d2558e..c983b67 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -61,6 +61,16 @@
 const base::Feature kAssetDownloadSuggestionsFeature{
     "NTPAssetDownloadSuggestions", base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Enables the built-in DNS resolver.
+const base::Feature kAsyncDns {
+  "AsyncDns",
+#if defined(OS_CHROMEOS) || defined(OS_MACOSX)
+      base::FEATURE_ENABLED_BY_DEFAULT
+#else
+      base::FEATURE_DISABLED_BY_DEFAULT
+#endif
+};
+
 #if defined(OS_WIN) || defined(OS_MACOSX)
 // Enables automatic tab discarding, when the system is in low memory state.
 const base::Feature kAutomaticTabDiscarding{"AutomaticTabDiscarding",
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index 210dd01..8e50094 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -40,6 +40,8 @@
 
 extern const base::Feature kAssetDownloadSuggestionsFeature;
 
+extern const base::Feature kAsyncDns;
+
 #if defined(OS_WIN) || defined(OS_MACOSX)
 extern const base::Feature kAutomaticTabDiscarding;
 #endif  // defined(OS_WIN) || defined(OS_MACOSX)
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index ae499c47..eebabf5 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -257,6 +257,10 @@
 const char kDisableSearchGeolocationDisclosure[] =
     "disable-search-geolocation-disclosure";
 
+// If set processes created to host a service will not load resources.
+const char kDisableServiceProcessResourceLoading[] =
+    "disable-service-process-resource-loading";
+
 // Disables Web Notification custom layouts.
 const char kDisableWebNotificationCustomLayouts[] =
     "disable-web-notification-custom-layouts";
@@ -648,9 +652,6 @@
 // If true the app list will be shown.
 const char kShowAppList[]                   = "show-app-list";
 
-// If true the Certificate link will be shown in Page Info for HTTPS pages.
-const char kShowCertLink[] = "show-cert-link";
-
 // Does not show an infobar when an extension attaches to a page using
 // chrome.debugger page. Required to attach to extension background pages.
 const char kSilentDebuggerExtensionAPI[]    = "silent-debugger-extension-api";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 20019fd..669c17e2 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -19,7 +19,7 @@
 
 namespace base {
 class CommandLine;
-};
+}
 
 namespace switches {
 
@@ -89,6 +89,7 @@
 extern const char kDisablePromptOnRepost[];
 extern const char kDisablePushApiBackgroundMode[];
 extern const char kDisableSearchGeolocationDisclosure[];
+extern const char kDisableServiceProcessResourceLoading[];
 extern const char kDisableWebNotificationCustomLayouts[];
 extern const char kDisableZeroBrowsersOpenForTests[];
 extern const char kDiskCacheDir[];
@@ -190,7 +191,6 @@
 extern const char kRestoreLastSession[];
 extern const char kSavePageAsMHTML[];
 extern const char kShowAppList[];
-extern const char kShowCertLink[];
 extern const char kSilentDebuggerExtensionAPI[];
 extern const char kSilentLaunch[];
 extern const char kSimulateCriticalUpdate[];
diff --git a/chrome/common/extensions/api/common_extension_api_unittest.cc b/chrome/common/extensions/api/common_extension_api_unittest.cc
index 92c658b..e5ad5e2 100644
--- a/chrome/common/extensions/api/common_extension_api_unittest.cc
+++ b/chrome/common/extensions/api/common_extension_api_unittest.cc
@@ -769,10 +769,10 @@
     EXPECT_TRUE(feature->whitelist().empty());
     EXPECT_TRUE(feature->extension_types().empty());
 
-    EXPECT_EQ(SimpleFeature::UNSPECIFIED_LOCATION, feature->location());
+    EXPECT_FALSE(feature->location());
     EXPECT_TRUE(feature->platforms().empty());
-    EXPECT_EQ(0, feature->min_manifest_version());
-    EXPECT_EQ(0, feature->max_manifest_version());
+    EXPECT_FALSE(feature->min_manifest_version());
+    EXPECT_FALSE(feature->max_manifest_version());
   }
 }
 
diff --git a/chrome/common/extensions/chrome_extensions_client.cc b/chrome/common/extensions/chrome_extensions_client.cc
index 7b06dcdf..b65abdf 100644
--- a/chrome/common/extensions/chrome_extensions_client.cc
+++ b/chrome/common/extensions/chrome_extensions_client.cc
@@ -259,8 +259,9 @@
 base::StringPiece ChromeExtensionsClient::GetAPISchema(
     const std::string& name) const {
   // Test from most common to least common.
-  if (api::ChromeGeneratedSchemas::IsGenerated(name))
-    return api::ChromeGeneratedSchemas::Get(name);
+  base::StringPiece chrome_schema = api::ChromeGeneratedSchemas::Get(name);
+  if (!chrome_schema.empty())
+    return chrome_schema;
 
   return api::GeneratedSchemas::Get(name);
 }
diff --git a/chrome/common/instant_struct_traits.h b/chrome/common/instant_struct_traits.h
index 39a3f25..e3d6eb5 100644
--- a/chrome/common/instant_struct_traits.h
+++ b/chrome/common/instant_struct_traits.h
@@ -6,6 +6,7 @@
 #include "chrome/common/search/instant_types.h"
 #include "chrome/common/search/ntp_logging_events.h"
 #include "components/ntp_tiles/tile_source.h"
+#include "components/ntp_tiles/tile_title_source.h"
 #include "components/ntp_tiles/tile_visual_type.h"
 #include "components/omnibox/common/omnibox_focus_state.h"
 #include "ipc/ipc_message_macros.h"
@@ -17,6 +18,9 @@
 
 IPC_ENUM_TRAITS_MAX_VALUE(NTPLoggingEventType, NTP_EVENT_TYPE_LAST)
 
+IPC_ENUM_TRAITS_MAX_VALUE(ntp_tiles::TileTitleSource,
+                          ntp_tiles::TileTitleSource::LAST)
+
 IPC_ENUM_TRAITS_MAX_VALUE(ntp_tiles::TileSource, ntp_tiles::TileSource::LAST)
 
 IPC_ENUM_TRAITS_MAX_VALUE(ntp_tiles::TileVisualType, ntp_tiles::TILE_TYPE_MAX)
diff --git a/chrome/common/logging_chrome.cc b/chrome/common/logging_chrome.cc
index 8899916..af1889b 100644
--- a/chrome/common/logging_chrome.cc
+++ b/chrome/common/logging_chrome.cc
@@ -252,7 +252,8 @@
 }
 
 base::FilePath GetSessionLogFile(const base::CommandLine& command_line) {
-  return GetSessionLogDir(command_line).Append(GetLogFileName().BaseName());
+  return GetSessionLogDir(command_line)
+      .Append(GetLogFileName(command_line).BaseName());
 }
 
 #endif  // OS_CHROMEOS
@@ -271,7 +272,7 @@
   // Don't resolve the log path unless we need to. Otherwise we leave an open
   // ALPC handle after sandbox lockdown on Windows.
   if ((logging_dest & LOG_TO_FILE) != 0) {
-    log_path = GetLogFileName();
+    log_path = GetLogFileName(command_line);
 
 #if defined(OS_CHROMEOS)
     // For BWSI (Incognito) logins, we want to put the logs in the user
@@ -387,10 +388,11 @@
   chrome_logging_redirected_ = false;
 }
 
-base::FilePath GetLogFileName() {
-  std::string filename;
-  std::unique_ptr<base::Environment> env(base::Environment::Create());
-  if (env->GetVar(env_vars::kLogFileName, &filename) && !filename.empty())
+base::FilePath GetLogFileName(const base::CommandLine& command_line) {
+  std::string filename = command_line.GetSwitchValueASCII(switches::kLogFile);
+  if (filename.empty())
+    base::Environment::Create()->GetVar(env_vars::kLogFileName, &filename);
+  if (!filename.empty())
     return base::FilePath::FromUTF8Unsafe(filename);
 
   const base::FilePath log_filename(FILE_PATH_LITERAL("chrome_debug.log"));
diff --git a/chrome/common/logging_chrome.h b/chrome/common/logging_chrome.h
index 0b00997..9b0d208 100644
--- a/chrome/common/logging_chrome.h
+++ b/chrome/common/logging_chrome.h
@@ -55,7 +55,7 @@
 void CleanupChromeLogging();
 
 // Returns the fully-qualified name of the log file.
-base::FilePath GetLogFileName();
+base::FilePath GetLogFileName(const base::CommandLine& command_line);
 
 // Returns true when error/assertion dialogs are not to be shown, false
 // otherwise.
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 60b4cdea..56d8bca 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -991,6 +991,11 @@
 // be always allowed or not.
 const char kPluginsAlwaysAuthorize[] = "plugins.always_authorize";
 
+// Boolean that indicates whether all Flash content (including cross-origin and
+// small content) is allowed to run when it is explicitly allowed via content
+// settings.
+const char kRunAllFlashInAllowMode[] = "plugins.run_all_flash_in_allow_mode";
+
 #if BUILDFLAG(ENABLE_PLUGINS)
 // Dictionary holding plugins metadata.
 const char kPluginsMetadata[] = "plugins.metadata";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index ba46a16..1eb4035 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -329,6 +329,7 @@
 #endif
 extern const char kPluginsAllowOutdated[];
 extern const char kPluginsAlwaysAuthorize[];
+extern const char kRunAllFlashInAllowMode[];
 #if BUILDFLAG(ENABLE_PLUGINS)
 extern const char kPluginsMetadata[];
 extern const char kPluginsResourceCacheUpdate[];
diff --git a/chrome/common/search.mojom b/chrome/common/search.mojom
index 96b95e8..43b46b6 100644
--- a/chrome/common/search.mojom
+++ b/chrome/common/search.mojom
@@ -15,6 +15,9 @@
 enum OmniboxFocusState;
 
 [Native]
+enum TileTitleSource;
+
+[Native]
 enum TileSource;
 
 [Native]
@@ -56,12 +59,14 @@
   // Logs an impression on one of the Most Visited tile on the InstantExtended
   // New Tab Page.
   LogMostVisitedImpression(int32 page_seq_no, int32 position,
+                           TileTitleSource tile_title_source,
                            TileSource tile_source,
                            TileVisualType tile_type);
 
   // Logs a navigation on one of the Most Visited tile on the InstantExtended
   // New Tab Page.
   LogMostVisitedNavigation(int32 page_seq_no, int32 position,
+                           TileTitleSource tile_title_source,
                            TileSource tile_source,
                            TileVisualType tile_type);
 
diff --git a/chrome/common/search.typemap b/chrome/common/search.typemap
index 020a4316..45ed315f 100644
--- a/chrome/common/search.typemap
+++ b/chrome/common/search.typemap
@@ -6,6 +6,7 @@
 public_headers = [
   "//chrome/common/search/instant_types.h",
   "//chrome/common/search/ntp_logging_events.h",
+  "//components/ntp_tiles/tile_title_source.h",
   "//components/ntp_tiles/tile_source.h",
   "//components/ntp_tiles/tile_visual_type.h",
   "//components/omnibox/common/omnibox_focus_state.h",
@@ -17,6 +18,7 @@
 ]
 type_mappings = [
   "chrome.mojom.NTPLoggingEventType=::NTPLoggingEventType",
+  "chrome.mojom.TileTitleSource=::ntp_tiles::TileTitleSource",
   "chrome.mojom.TileSource=::ntp_tiles::TileSource",
   "chrome.mojom.TileVisualType=::ntp_tiles::TileVisualType",
   "chrome.mojom.OmniboxFocusState=::OmniboxFocusState",
diff --git a/chrome/common/search/instant_types.cc b/chrome/common/search/instant_types.cc
index 85c1b711..b4256732 100644
--- a/chrome/common/search/instant_types.cc
+++ b/chrome/common/search/instant_types.cc
@@ -58,7 +58,8 @@
 }
 
 InstantMostVisitedItem::InstantMostVisitedItem()
-    : source(ntp_tiles::TileSource::TOP_SITES) {}
+    : title_source(ntp_tiles::TileTitleSource::UNKNOWN),
+      source(ntp_tiles::TileSource::TOP_SITES) {}
 
 InstantMostVisitedItem::InstantMostVisitedItem(
     const InstantMostVisitedItem& other) = default;
diff --git a/chrome/common/search/instant_types.h b/chrome/common/search/instant_types.h
index b21c7238..c9f9088 100644
--- a/chrome/common/search/instant_types.h
+++ b/chrome/common/search/instant_types.h
@@ -12,6 +12,7 @@
 
 #include "base/strings/string16.h"
 #include "components/ntp_tiles/tile_source.h"
+#include "components/ntp_tiles/tile_title_source.h"
 #include "url/gurl.h"
 
 // ID used by Instant code to refer to objects (e.g. Autocomplete results, Most
@@ -127,6 +128,9 @@
   // The external URL of the favicon associated with this page.
   GURL favicon;
 
+  // The source of the item's |title|.
+  ntp_tiles::TileTitleSource title_source;
+
   // The source of the item, e.g. server-side or client-side.
   ntp_tiles::TileSource source;
 };
diff --git a/chrome/common/service_process_util_mac_unittest.mm b/chrome/common/service_process_util_mac_unittest.mm
index c4eaff8..db20296 100644
--- a/chrome/common/service_process_util_mac_unittest.mm
+++ b/chrome/common/service_process_util_mac_unittest.mm
@@ -23,17 +23,6 @@
 #include "chrome/common/mac/mock_launchd.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-// Once Chrome no longer supports OSX 10.7, everything within this
-// preprocessor block can be removed.
-#if !defined(MAC_OS_X_VERSION_10_8) || \
-    MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8
-@interface NSFileManager (Chrome)
-- (BOOL)trashItemAtURL:(NSURL*)url
-      resultingItemURL:(NSURL* __nullable* __nullable)outResultingURL
-                 error:(NSError**)error;
-@end
-#endif
-
 class ServiceProcessStateFileManipulationTest : public ::testing::Test {
  public:
   void TrashFunc(const base::FilePath& src) {
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index a33c377..949dd94 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -188,6 +188,7 @@
 const char kChromeUIDeviceLogHost[] = "device-log";
 const char kChromeUIDevicesHost[] = "devices";
 const char kChromeUIDevToolsHost[] = "devtools";
+const char kChromeUIDevToolsBlankPath[] = "blank";
 const char kChromeUIDevToolsBundledPath[] = "bundled";
 const char kChromeUIDevToolsCustomPath[] = "custom";
 const char kChromeUIDevToolsRemotePath[] = "remote";
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h
index 02ef861..cc30c1d 100644
--- a/chrome/common/url_constants.h
+++ b/chrome/common/url_constants.h
@@ -176,9 +176,10 @@
 extern const char kChromeUIDeviceLogHost[];
 extern const char kChromeUIDevicesHost[];
 extern const char kChromeUIDevToolsHost[];
+extern const char kChromeUIDevToolsBlankPath[];
 extern const char kChromeUIDevToolsBundledPath[];
-extern const char kChromeUIDevToolsRemotePath[];
 extern const char kChromeUIDevToolsCustomPath[];
+extern const char kChromeUIDevToolsRemotePath[];
 extern const char kChromeUIDNSHost[];
 extern const char kChromeUIDomainReliabilityInternalsHost[];
 extern const char kChromeUIDownloadsHost[];
diff --git a/chrome/installer/linux/BUILD.gn b/chrome/installer/linux/BUILD.gn
index af7487ed..ca0178e3 100644
--- a/chrome/installer/linux/BUILD.gn
+++ b/chrome/installer/linux/BUILD.gn
@@ -10,6 +10,7 @@
 import("//build/util/process_version.gni")
 import("//build/util/version.gni")
 import("//chrome/process_version_rc_template.gni")  # For branding_file_path.
+import("//components/nacl/features.gni")
 
 if (current_cpu == "x86" || current_cpu == "x64") {
   import("//media/cdm/ppapi/cdm_paths.gni")
diff --git a/chrome/installer/linux/common/installer.include b/chrome/installer/linux/common/installer.include
index 20349270..b53e4eb 100644
--- a/chrome/installer/linux/common/installer.include
+++ b/chrome/installer/linux/common/installer.include
@@ -126,11 +126,12 @@
 stage_install_common() {
   log_cmd echo "Staging common install files in '${STAGEDIR}'..."
 
-  # TODO(mmoss) This assumes we built the static binaries. To support shared
-  # builds, we probably want an install target in scons so it can give us all
-  # the right files. See also:
-  # http://code.google.com/p/chromium/issues/detail?id=4451
-  #
+  # Note: Changes here may also need to be applied to ChromeOS's
+  # chromite/lib/chrome_util.py.
+
+  # Note: This only supports static binaries and does not work when the GN
+  # is_component_build flag is true.
+
   # app
   STRIPPEDFILE="${BUILDDIR}/${PROGNAME}.stripped"
   install -m 755 "${STRIPPEDFILE}" "${STAGEDIR}/${INSTALLDIR}/${PROGNAME}"
@@ -149,16 +150,14 @@
     install -m 644 "${BUILDDIR}/ui_resources_100_percent.pak" "${STAGEDIR}/${INSTALLDIR}/"
   fi
 
-  # ICU data file; only necessary when icu_use_data_file_flag is set to 1
-  # in build/common.gypi.
+  # ICU data file; Necessary when the GN icu_use_data_file flag is true.
   install -m 644 "${BUILDDIR}/icudtl.dat" "${STAGEDIR}/${INSTALLDIR}/"
 
-  # V8 snapshot files; only necessary when v8_use_external_startup_data is
-  # set to 1 in build/common.gypi.
-  if [ -f "${BUILDDIR}/natives_blob.bin" ]; then
-    install -m 644 "${BUILDDIR}/natives_blob.bin" "${STAGEDIR}/${INSTALLDIR}/"
-    install -m 644 "${BUILDDIR}/snapshot_blob.bin" "${STAGEDIR}/${INSTALLDIR}/"
-  fi
+  # V8 snapshot files; Necessary when the GN v8_use_external_startup_data flag
+  # is true.
+  install -m 644 "${BUILDDIR}/natives_blob.bin" "${STAGEDIR}/${INSTALLDIR}/"
+  install -m 644 "${BUILDDIR}/snapshot_blob.bin" "${STAGEDIR}/${INSTALLDIR}/"
+
   # V8 context snapshot file; it will replace V8's snapshot_blob.bin
   # TODO(peria): Remove snapshot_blob.bin when dependencies are resolved.
   if [ -f "${BUILDDIR}/v8_context_snapshot.bin" ]; then
@@ -167,7 +166,9 @@
 
   # sandbox
   # Rename sandbox binary with hyphen instead of underscore because that's what
-  # the code looks for, but the build targets can't use hyphens (scons bug?)
+  # the code looks for. Originally, the SCons build system may have had a bug
+  # where it did not support hyphens, so this is stuck as is to avoid breaking
+  # anyone who expects the build artifact to have the underscore.
   install -m 4755 -s "${BUILDDIR}/${PROGNAME}_sandbox" \
     "${STAGEDIR}/${INSTALLDIR}/${PROGNAME}-sandbox"
 
@@ -215,7 +216,6 @@
     install -m ${SHLIB_PERMS} -s "${BUILDDIR}/lib/libc++.so" "${STAGEDIR}/${INSTALLDIR}/lib/"
   fi
 
-
   # nacl_helper and nacl_helper_bootstrap
   # Don't use "-s" (strip) because this runs binutils "strip", which
   # mangles the special ELF program headers of nacl_helper_bootstrap.
diff --git a/chrome/installer/mac/app/Unpacker.m b/chrome/installer/mac/app/Unpacker.m
index 02ff012..5d45520 100644
--- a/chrome/installer/mac/app/Unpacker.m
+++ b/chrome/installer/mac/app/Unpacker.m
@@ -146,9 +146,6 @@
 - (void)didFinishEjectingDisk:(DADiskRef)disk
                 withDissenter:(DADissenterRef)dissenter {
   DASessionSetDispatchQueue(session_, NULL);
-#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8
-  dispatch_release(unpack_dq_);
-#endif
   CFRelease(session_);
   NSError* error = nil;
   if (dissenter) {
@@ -167,4 +164,4 @@
   }
 }
 
-@end
\ No newline at end of file
+@end
diff --git a/chrome/installer/mini_installer/BUILD.gn b/chrome/installer/mini_installer/BUILD.gn
index d8249e6..cc3782f 100644
--- a/chrome/installer/mini_installer/BUILD.gn
+++ b/chrome/installer/mini_installer/BUILD.gn
@@ -7,6 +7,7 @@
 import("//build/config/ui.gni")
 import("//chrome/process_version_rc_template.gni")
 import("//chrome/test/mini_installer/mini_installer_test.gni")
+import("//components/nacl/features.gni")
 import("//third_party/icu/config.gni")
 import("//ui/base/ui_features.gni")
 import("//v8/gni/v8.gni")
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc
index fd5749f..5dba7a4b 100644
--- a/chrome/installer/util/shell_util.cc
+++ b/chrome/installer/util/shell_util.cc
@@ -2082,7 +2082,7 @@
 
   // Windows 8 does not permit making a browser default just like that.
   // This process needs to be routed through the system's UI. Use
-  // ShowMakeChromeDefaultProocolClientSystemUI instead (below).
+  // ShowMakeChromeDefaultProtocolClientSystemUI instead (below).
   if (!CanMakeChromeDefaultUnattended())
     return false;
 
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn
index d3a748f..f211e816 100644
--- a/chrome/renderer/BUILD.gn
+++ b/chrome/renderer/BUILD.gn
@@ -4,6 +4,7 @@
 
 import("//build/config/features.gni")
 import("//chrome/common/features.gni")
+import("//components/nacl/features.gni")
 import("//components/spellcheck/spellcheck_build_features.gni")
 import("//extensions/features/features.gni")
 import("//media/media_options.gni")
diff --git a/chrome/renderer/extensions/automation_internal_custom_bindings.cc b/chrome/renderer/extensions/automation_internal_custom_bindings.cc
index 271c113..b55224f 100644
--- a/chrome/renderer/extensions/automation_internal_custom_bindings.cc
+++ b/chrome/renderer/extensions/automation_internal_custom_bindings.cc
@@ -1004,10 +1004,8 @@
   gin::DataObjectBuilder state(isolate);
   uint32_t state_pos = 0, state_shifter = node->data().state;
   while (state_shifter) {
-    if (state_pos != ui::AX_STATE_OFFSCREEN) {
-      if (state_shifter & 1)
-        state.Set(ToString(static_cast<ui::AXState>(state_pos)), true);
-    }
+    if (state_shifter & 1)
+      state.Set(ToString(static_cast<ui::AXState>(state_pos)), true);
     state_shifter = state_shifter >> 1;
     state_pos++;
   }
@@ -1022,12 +1020,12 @@
        focused_cache == cache && focused_node == node) ||
       cache->tree.data().focus_id == node->id();
   if (focused)
-    state.Set("focused", true);
+    state.Set(ToString(api::automation::STATE_TYPE_FOCUSED), true);
 
   bool offscreen = false;
   ComputeGlobalNodeBounds(cache, node, gfx::RectF(), &offscreen);
   if (offscreen)
-    state.Set(ToString(ui::AX_STATE_OFFSCREEN), true);
+    state.Set(ToString(api::automation::STATE_TYPE_OFFSCREEN), true);
 
   args.GetReturnValue().Set(state.Build());
 }
diff --git a/chrome/renderer/resources/extensions/searchbox_api.js b/chrome/renderer/resources/extensions/searchbox_api.js
index 8d639bfb..6691bc02 100644
--- a/chrome/renderer/resources/extensions/searchbox_api.js
+++ b/chrome/renderer/resources/extensions/searchbox_api.js
@@ -117,14 +117,18 @@
 
       // This method is restricted to chrome-search://most-visited pages by
       // checking the invoking context's origin in searchbox_extension.cc.
-      this.logMostVisitedImpression = function(position, tileSource, tileType) {
-        LogMostVisitedImpression(position, tileSource, tileType);
+      this.logMostVisitedImpression = function(position, tileTitleSource,
+                                               tileSource, tileType) {
+        LogMostVisitedImpression(position, tileTitleSource, tileSource,
+                                 tileType);
       };
 
       // This method is restricted to chrome-search://most-visited pages by
       // checking the invoking context's origin in searchbox_extension.cc.
-      this.logMostVisitedNavigation = function(position, tileSource, tileType) {
-        LogMostVisitedNavigation(position, tileSource, tileType);
+      this.logMostVisitedNavigation = function(position, tileTitleSource,
+                                               tileSource, tileType) {
+        LogMostVisitedNavigation(position, tileTitleSource, tileSource,
+                                 tileType);
       };
 
       this.undoAllMostVisitedDeletions = function() {
diff --git a/chrome/renderer/searchbox/searchbox.cc b/chrome/renderer/searchbox/searchbox.cc
index 33f027e2..9df5e12 100644
--- a/chrome/renderer/searchbox/searchbox.cc
+++ b/chrome/renderer/searchbox/searchbox.cc
@@ -243,18 +243,22 @@
   embedded_search_service_->LogEvent(page_seq_no_, event, delta);
 }
 
-void SearchBox::LogMostVisitedImpression(int position,
-                                         ntp_tiles::TileSource tile_source,
-                                         ntp_tiles::TileVisualType tile_type) {
-  embedded_search_service_->LogMostVisitedImpression(page_seq_no_, position,
-                                                     tile_source, tile_type);
+void SearchBox::LogMostVisitedImpression(
+    int position,
+    ntp_tiles::TileTitleSource tile_title_source,
+    ntp_tiles::TileSource tile_source,
+    ntp_tiles::TileVisualType tile_type) {
+  embedded_search_service_->LogMostVisitedImpression(
+      page_seq_no_, position, tile_title_source, tile_source, tile_type);
 }
 
-void SearchBox::LogMostVisitedNavigation(int position,
-                                         ntp_tiles::TileSource tile_source,
-                                         ntp_tiles::TileVisualType tile_type) {
-  embedded_search_service_->LogMostVisitedNavigation(page_seq_no_, position,
-                                                     tile_source, tile_type);
+void SearchBox::LogMostVisitedNavigation(
+    int position,
+    ntp_tiles::TileTitleSource tile_title_source,
+    ntp_tiles::TileSource tile_source,
+    ntp_tiles::TileVisualType tile_type) {
+  embedded_search_service_->LogMostVisitedNavigation(
+      page_seq_no_, position, tile_title_source, tile_source, tile_type);
 }
 
 void SearchBox::CheckIsUserSignedInToChromeAs(const base::string16& identity) {
diff --git a/chrome/renderer/searchbox/searchbox.h b/chrome/renderer/searchbox/searchbox.h
index 21b1490..a840b82 100644
--- a/chrome/renderer/searchbox/searchbox.h
+++ b/chrome/renderer/searchbox/searchbox.h
@@ -15,6 +15,7 @@
 #include "chrome/common/search/ntp_logging_events.h"
 #include "chrome/renderer/instant_restricted_id_cache.h"
 #include "components/ntp_tiles/tile_source.h"
+#include "components/ntp_tiles/tile_title_source.h"
 #include "components/ntp_tiles/tile_visual_type.h"
 #include "components/omnibox/common/omnibox_focus_state.h"
 #include "content/public/renderer/render_frame_observer.h"
@@ -53,11 +54,13 @@
 
   // Sends LogMostVisitedImpression to the browser.
   void LogMostVisitedImpression(int position,
+                                ntp_tiles::TileTitleSource tile_title_source,
                                 ntp_tiles::TileSource tile_source,
                                 ntp_tiles::TileVisualType tile_type);
 
   // Sends LogMostVisitedNavigation to the browser.
   void LogMostVisitedNavigation(int position,
+                                ntp_tiles::TileTitleSource tile_title_source,
                                 ntp_tiles::TileSource tile_source,
                                 ntp_tiles::TileVisualType tile_type);
 
diff --git a/chrome/renderer/searchbox/searchbox_extension.cc b/chrome/renderer/searchbox/searchbox_extension.cc
index 67d7d74..8c36394 100644
--- a/chrome/renderer/searchbox/searchbox_extension.cc
+++ b/chrome/renderer/searchbox/searchbox_extension.cc
@@ -167,6 +167,8 @@
              UTF8ToV8String(isolate, mv_item.favicon.spec()));
   }
 
+  obj->Set(v8::String::NewFromUtf8(isolate, "tileTitleSource"),
+           v8::Integer::New(isolate, static_cast<int>(mv_item.title_source)));
   obj->Set(v8::String::NewFromUtf8(isolate, "tileSource"),
            v8::Integer::New(isolate, static_cast<int>(mv_item.source)));
   obj->Set(v8::String::NewFromUtf8(isolate, "title"),
@@ -862,23 +864,27 @@
   if (!render_frame)
     return;
 
-  if (args.Length() < 3 || !args[0]->IsNumber() || !args[1]->IsNumber() ||
-      !args[2]->IsNumber()) {
+  if (args.Length() < 4 || !args[0]->IsNumber() || !args[1]->IsNumber() ||
+      !args[2]->IsNumber() || !args[3]->IsNumber()) {
     ThrowInvalidParameters(args);
     return;
   }
 
   DVLOG(1) << render_frame << " LogMostVisitedImpression";
 
-  if (args[1]->Uint32Value() <= static_cast<int>(ntp_tiles::TileSource::LAST) &&
-      args[2]->Uint32Value() <= ntp_tiles::TileVisualType::TILE_TYPE_MAX) {
+  if (args[1]->Uint32Value() <=
+          static_cast<int>(ntp_tiles::TileTitleSource::LAST) &&
+      args[2]->Uint32Value() <= static_cast<int>(ntp_tiles::TileSource::LAST) &&
+      args[3]->Uint32Value() <= ntp_tiles::TileVisualType::TILE_TYPE_MAX) {
+    auto tile_title_source =
+        static_cast<ntp_tiles::TileTitleSource>(args[1]->Uint32Value());
     auto tile_source =
-        static_cast<ntp_tiles::TileSource>(args[1]->Uint32Value());
+        static_cast<ntp_tiles::TileSource>(args[2]->Uint32Value());
     auto tile_type =
-        static_cast<ntp_tiles::TileVisualType>(args[2]->Uint32Value());
+        static_cast<ntp_tiles::TileVisualType>(args[3]->Uint32Value());
     SearchBox::Get(render_frame)
-        ->LogMostVisitedImpression(args[0]->IntegerValue(), tile_source,
-                                   tile_type);
+        ->LogMostVisitedImpression(args[0]->IntegerValue(), tile_title_source,
+                                   tile_source, tile_type);
   }
 }
 
@@ -890,22 +896,27 @@
   if (!render_frame)
     return;
 
-  if (args.Length() < 2 || !args[0]->IsNumber() || !args[1]->IsNumber()) {
+  if (args.Length() < 4 || !args[0]->IsNumber() || !args[1]->IsNumber() ||
+      !args[2]->IsNumber() || !args[3]->IsNumber()) {
     ThrowInvalidParameters(args);
     return;
   }
 
   DVLOG(1) << render_frame << " LogMostVisitedNavigation";
 
-  if (args[1]->Uint32Value() <= static_cast<int>(ntp_tiles::TileSource::LAST) &&
-      args[2]->Uint32Value() <= ntp_tiles::TileVisualType::TILE_TYPE_MAX) {
+  if (args[1]->Uint32Value() <=
+          static_cast<int>(ntp_tiles::TileTitleSource::LAST) &&
+      args[2]->Uint32Value() <= static_cast<int>(ntp_tiles::TileSource::LAST) &&
+      args[3]->Uint32Value() <= ntp_tiles::TileVisualType::TILE_TYPE_MAX) {
+    auto tile_title_source =
+        static_cast<ntp_tiles::TileTitleSource>(args[1]->Uint32Value());
     auto tile_source =
-        static_cast<ntp_tiles::TileSource>(args[1]->Uint32Value());
+        static_cast<ntp_tiles::TileSource>(args[2]->Uint32Value());
     auto tile_type =
-        static_cast<ntp_tiles::TileVisualType>(args[2]->Uint32Value());
+        static_cast<ntp_tiles::TileVisualType>(args[3]->Uint32Value());
     SearchBox::Get(render_frame)
-        ->LogMostVisitedNavigation(args[0]->IntegerValue(), tile_source,
-                                   tile_type);
+        ->LogMostVisitedNavigation(args[0]->IntegerValue(), tile_title_source,
+                                   tile_source, tile_type);
   }
 }
 
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 04637dd..78c3e3af 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -10,6 +10,7 @@
 import("//chrome/common/features.gni")
 import("//chrome/chrome_repack_locales.gni")
 import("//components/feature_engagement/features.gni")
+import("//components/nacl/features.gni")
 import("//components/offline_pages/features/features.gni")
 import("//components/os_crypt/features.gni")
 import("//components/signin/features.gni")
@@ -1073,8 +1074,6 @@
       "base/browser_tests_main_chromeos.cc",
       "base/mash_browser_tests_main.cc",
       "base/mash_browser_tests_main.h",
-      "base/mojo_test_connector.cc",
-      "base/mojo_test_connector.h",
     ]
 
     deps += [
@@ -1082,12 +1081,6 @@
       "//mash/session/public/interfaces:constants",
       "//services/service_manager/background:lib",
     ]
-
-    data_deps = [
-      ":mash_browser_tests_catalog_copy",
-      ":mus_browser_tests_catalog_copy",
-      "//mash/session",
-    ]
   } else {
     sources += [ "base/browser_tests_main.cc" ]
   }
@@ -1951,6 +1944,7 @@
         "../browser/extensions/extension_management_test_util.cc",
         "../browser/extensions/extension_management_test_util.h",
         "../browser/extensions/extension_messages_apitest.cc",
+        "../browser/extensions/extension_modules_apitest.cc",
         "../browser/extensions/extension_override_apitest.cc",
         "../browser/extensions/extension_request_limiting_throttle_browsertest.cc",
         "../browser/extensions/extension_resource_request_policy_apitest.cc",
@@ -2231,7 +2225,6 @@
         "../browser/chromeos/login/bluetooth_host_pairing_browsertest.cc",
         "../browser/chromeos/login/crash_restore_browsertest.cc",
         "../browser/chromeos/login/demo_mode/demo_app_launcher_browsertest.cc",
-        "../browser/chromeos/login/easy_unlock/bootstrap_browsertest.cc",
         "../browser/chromeos/login/enable_debugging_browsertest.cc",
         "../browser/chromeos/login/enrollment/enrollment_screen_browsertest.cc",
         "../browser/chromeos/login/enrollment/mock_auto_enrollment_check_screen.cc",
@@ -3407,6 +3400,7 @@
     "../browser/ui/tests/ui_gfx_image_unittest.cc",
     "../browser/ui/tests/ui_gfx_image_unittest.mm",
     "../browser/ui/webui/fileicon_source_unittest.cc",
+    "../browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc",
     "../browser/ui/webui/local_state/local_state_ui_unittest.cc",
     "../browser/ui/webui/log_web_ui_url_unittest.cc",
     "../browser/update_client/chrome_update_query_params_delegate_unittest.cc",
@@ -3730,6 +3724,7 @@
 
       # The autofill popup is implemented in mostly native code on Android.
       "../browser/ui/autofill/autofill_popup_controller_unittest.cc",
+      "../browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc",
       "../browser/ui/blocked_content/scoped_visibility_tracker_unittest.cc",
       "../browser/ui/bookmarks/bookmark_context_menu_controller_unittest.cc",
       "../browser/ui/bookmarks/bookmark_unittest.cc",
@@ -4761,6 +4756,7 @@
         "../browser/ui/cocoa/profiles/profile_chooser_controller_unittest.mm",
         "../browser/ui/cocoa/profiles/profile_menu_controller_unittest.mm",
         "../browser/ui/cocoa/profiles/user_manager_mac_unittest.mm",
+        "../browser/ui/cocoa/scoped_menu_bar_lock_unittest.mm",
         "../browser/ui/cocoa/screen_capture_notification_ui_cocoa_unittest.mm",
         "../browser/ui/cocoa/spinner_view_unittest.mm",
         "../browser/ui/cocoa/sprite_view_unittest.mm",
@@ -5234,73 +5230,6 @@
   }
 }
 
-if (is_chromeos && enable_package_mash_services) {
-  group("mash_browser_tests") {
-    testonly = true
-    data_deps = [
-      ":browser_tests",
-    ]
-  }
-
-  service_manifest("mash_browser_tests_manifest") {
-    name = "mash_browser_tests"
-    source = "base/mash_browser_tests_manifest.json"
-  }
-
-  catalog("mash_browser_tests_catalog") {
-    testonly = true
-    embedded_services = [ ":mash_browser_tests_manifest" ]
-    catalog_deps = [ "//chrome/app/mash:catalog" ]
-  }
-
-  copy("mash_browser_tests_catalog_copy") {
-    testonly = true
-    sources = get_target_outputs(":mash_browser_tests_catalog")
-    outputs = [
-      "${root_out_dir}/mash_browser_tests_catalog.json",
-    ]
-    deps = [
-      ":mash_browser_tests_catalog",
-    ]
-  }
-
-  group("mus_browser_tests_run") {
-    testonly = true
-    deps = [
-      ":mus_browser_tests",
-    ]
-  }
-
-  group("mus_browser_tests") {
-    testonly = true
-    data_deps = [
-      ":browser_tests",
-    ]
-  }
-
-  service_manifest("mus_browser_tests_manifest") {
-    name = "mus_browser_tests"
-    source = "base/mus_browser_tests_manifest.json"
-  }
-
-  catalog("mus_browser_tests_catalog") {
-    testonly = true
-    embedded_services = [ ":mus_browser_tests_manifest" ]
-    catalog_deps = [ "//chrome/app/mash:catalog_mus" ]
-  }
-
-  copy("mus_browser_tests_catalog_copy") {
-    testonly = true
-    sources = get_target_outputs(":mus_browser_tests_catalog")
-    outputs = [
-      "${root_out_dir}/mus_browser_tests_catalog.json",
-    ]
-    deps = [
-      ":mus_browser_tests_catalog",
-    ]
-  }
-}
-
 if (is_win) {
   loadable_module("conflicts_dll") {
     testonly = true
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/suggestions/ContentSuggestionsTestUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/suggestions/ContentSuggestionsTestUtils.java
index 175b3b5..4532d73 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/suggestions/ContentSuggestionsTestUtils.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/suggestions/ContentSuggestionsTestUtils.java
@@ -25,8 +25,8 @@
     public static SnippetArticle createDummySuggestion(
             @CategoryInt int category, String suffix, boolean isVideoSuggestion) {
         return new SnippetArticle(category, "https://site.com/url" + suffix, "title" + suffix,
-                "pub" + suffix, "txt" + suffix, "https://site.com/url" + suffix, 0, 0, 0,
-                isVideoSuggestion, /* thumbnailDominantColor = */ null);
+                "pub" + suffix, "https://site.com/url" + suffix, 0, 0, 0, isVideoSuggestion,
+                /* thumbnailDominantColor = */ null);
     }
 
     public static SnippetArticle createDummySuggestion(@CategoryInt int category) {
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/suggestions/FakeMostVisitedSites.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/suggestions/FakeMostVisitedSites.java
index 6cb69e07..9aecd60f 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/suggestions/FakeMostVisitedSites.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/suggestions/FakeMostVisitedSites.java
@@ -9,6 +9,7 @@
 import org.chromium.chrome.browser.suggestions.SiteSuggestion;
 import org.chromium.chrome.browser.suggestions.TileSectionType;
 import org.chromium.chrome.browser.suggestions.TileSource;
+import org.chromium.chrome.browser.suggestions.TileTitleSource;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -52,12 +53,12 @@
     }
 
     @Override
-    public void recordTileImpression(int index, int type, int source, String url) {
+    public void recordTileImpression(int index, int type, int titleSource, int source, String url) {
         // Metrics are stubbed out.
     }
 
     @Override
-    public void recordOpenedMostVisitedItem(int index, int tileType, int source) {
+    public void recordOpenedMostVisitedItem(int index, int tileType, int titleSource, int source) {
         //  Metrics are stubbed out.
     }
 
@@ -113,8 +114,8 @@
     }
 
     public static SiteSuggestion createSiteSuggestion(String title, String url) {
-        return new SiteSuggestion(
-                title, url, "", TileSource.TOP_SITES, TileSectionType.PERSONALIZED);
+        return new SiteSuggestion(title, url, "", TileTitleSource.TITLE_TAG, TileSource.TOP_SITES,
+                TileSectionType.PERSONALIZED);
     }
 
     private void notifyTileSuggestionsAvailable() {
diff --git a/chrome/test/base/OWNERS b/chrome/test/base/OWNERS
index 7278c1e..b1c274e1 100644
--- a/chrome/test/base/OWNERS
+++ b/chrome/test/base/OWNERS
@@ -1,9 +1,3 @@
 per-file js2gtest.*=dtseng@chromium.org
 
 per-file *tracing*=file://base/trace_event/OWNERS
-
-per-file mash_browser_tests_manifest.json=set noparent
-per-file mash_browser_tests_manifest.json=file://ipc/SECURITY_OWNERS
-
-per-file mus_browser_tests_manifest.json=set noparent
-per-file mus_browser_tests_manifest.json=file://ipc/SECURITY_OWNERS
diff --git a/chrome/test/base/mash_browser_tests_main.cc b/chrome/test/base/mash_browser_tests_main.cc
index 344d2c3..143fedd 100644
--- a/chrome/test/base/mash_browser_tests_main.cc
+++ b/chrome/test/base/mash_browser_tests_main.cc
@@ -2,204 +2,59 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <algorithm>
-
-#include "base/at_exit.h"
 #include "base/command_line.h"
-#include "base/debug/debugger.h"
-#include "base/debug/stack_trace.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/i18n/icu_util.h"
-#include "base/json/json_reader.h"
-#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
-#include "base/path_service.h"
-#include "base/process/launch.h"
-#include "base/run_loop.h"
-#include "base/sys_info.h"
-#include "base/task_scheduler/task_scheduler.h"
-#include "base/test/launcher/test_launcher.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/values.h"
-#include "chrome/app/mash/embedded_services.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/chrome_test_launcher.h"
 #include "chrome/test/base/chrome_test_suite.h"
-#include "chrome/test/base/mojo_test_connector.h"
 #include "content/public/app/content_main.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/common/content_switches.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/test/test_launcher.h"
-#include "mash/session/public/interfaces/constants.mojom.h"
-#include "services/service_manager/public/cpp/connector.h"
-#include "services/service_manager/public/cpp/service.h"
-#include "services/service_manager/public/cpp/service_context.h"
-#include "services/service_manager/public/cpp/service_runner.h"
-#include "services/service_manager/public/cpp/standalone_service/standalone_service.h"
-#include "services/service_manager/runner/common/switches.h"
-#include "services/service_manager/runner/init.h"
-#include "services/ui/common/switches.h"
 #include "ui/aura/env.h"
 
 namespace {
 
-const base::FilePath::CharType kMashCatalogFilename[] =
-    FILE_PATH_LITERAL("mash_browser_tests_catalog.json");
-const base::FilePath::CharType kMusCatalogFilename[] =
-    FILE_PATH_LITERAL("mus_browser_tests_catalog.json");
+// Enumeration of the possible chrome-ash configurations.
+enum class AshConfig {
+  // Aura is backed by mus, but chrome and ash are still in the same process.
+  MUS,
 
-// ChromeTestLauncherDelegate implementation used for '--mus' (ash runs in
-// process with chrome).
+  // Aura is backed by mus and chrome and ash are in separate processes. In
+  // this mode chrome code can only use ash code in ash/public/cpp.
+  MASH,
+};
+
 class MusTestLauncherDelegate : public ChromeTestLauncherDelegate {
  public:
   explicit MusTestLauncherDelegate(ChromeTestSuiteRunner* runner)
-      : ChromeTestLauncherDelegate(runner) {}
+      : ChromeTestLauncherDelegate(runner),
+        config_(
+            base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kMash)
+                ? AshConfig::MASH
+                : AshConfig::MUS) {}
+
   ~MusTestLauncherDelegate() override {}
 
  private:
   // ChromeTestLauncherDelegate:
   int RunTestSuite(int argc, char** argv) override {
     content::GetContentMainParams()->env_mode = aura::Env::Mode::MUS;
-    content::GetContentMainParams()->create_discardable_memory = true;
+    content::GetContentMainParams()->create_discardable_memory =
+        (config_ == AshConfig::MUS);
     return ChromeTestLauncherDelegate::RunTestSuite(argc, argv);
   }
 
+  AshConfig config_;
+
   DISALLOW_COPY_AND_ASSIGN(MusTestLauncherDelegate);
 };
 
-class MashTestSuite : public ChromeTestSuite {
- public:
-  MashTestSuite(int argc, char** argv) : ChromeTestSuite(argc, argv) {}
-
-  void SetMojoTestConnector(std::unique_ptr<MojoTestConnector> connector) {
-    mojo_test_connector_ = std::move(connector);
-  }
-
-  MojoTestConnector* mojo_test_connector() {
-    return mojo_test_connector_.get();
-  }
-
- private:
-  // ChromeTestSuite:
-  void Shutdown() override {
-    mojo_test_connector_.reset();
-    ChromeTestSuite::Shutdown();
-  }
-
-  std::unique_ptr<MojoTestConnector> mojo_test_connector_;
-
-  DISALLOW_COPY_AND_ASSIGN(MashTestSuite);
-};
-
-// Used to setup the command line for passing a mojo channel to tests.
-class MashTestLauncherDelegate : public ChromeTestLauncherDelegate {
- public:
-  MashTestLauncherDelegate() : ChromeTestLauncherDelegate(nullptr) {
-    base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-    config_ = command_line->HasSwitch("run-in-mash")
-                  ? MojoTestConnector::Config::MASH
-                  : MojoTestConnector::Config::MUS;
-  }
-  ~MashTestLauncherDelegate() override {}
-
-  MojoTestConnector* GetMojoTestConnectorForSingleProcess() {
-    // This is only called for single process tests, in which case we need
-    // the TestSuite to own the MojoTestConnector.
-    DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
-        content::kSingleProcessTestsFlag));
-    DCHECK(test_suite_);
-    test_suite_->SetMojoTestConnector(
-        base::MakeUnique<MojoTestConnector>(ReadCatalogManifest(), config_));
-    return test_suite_->mojo_test_connector();
-  }
-
- private:
-  // ChromeTestLauncherDelegate:
-  int RunTestSuite(int argc, char** argv) override {
-    test_suite_.reset(new MashTestSuite(argc, argv));
-    content::GetContentMainParams()->env_mode = aura::Env::Mode::MUS;
-    content::GetContentMainParams()->create_discardable_memory =
-        (config_ == MojoTestConnector::Config::MUS);
-    const int result = test_suite_->Run();
-    test_suite_.reset();
-    return result;
-  }
-
-  std::unique_ptr<content::TestState> PreRunTest(
-      base::CommandLine* command_line,
-      base::TestLauncher::LaunchOptions* test_launch_options) override {
-    if (!mojo_test_connector_) {
-      mojo_test_connector_ =
-          base::MakeUnique<MojoTestConnector>(ReadCatalogManifest(), config_);
-      mojo_test_connector_->Init();
-    }
-    return mojo_test_connector_->PrepareForTest(command_line,
-                                                test_launch_options);
-  }
-
-  void OnDoneRunningTests() override {
-    // We have to shutdown this state here, while an AtExitManager is still
-    // valid.
-    mojo_test_connector_.reset();
-  }
-
-  std::unique_ptr<base::Value> ReadCatalogManifest() {
-    std::string catalog_contents;
-    base::FilePath exe_path;
-    base::PathService::Get(base::DIR_EXE, &exe_path);
-    base::FilePath catalog_path = exe_path.Append(
-        config_ == MojoTestConnector::Config::MASH ? kMashCatalogFilename
-                                                   : kMusCatalogFilename);
-    bool result = base::ReadFileToString(catalog_path, &catalog_contents);
-    DCHECK(result);
-    std::unique_ptr<base::Value> manifest_value =
-        base::JSONReader::Read(catalog_contents);
-    DCHECK(manifest_value);
-    return manifest_value;
-  }
-
-  MojoTestConnector::Config config_;
-
-  std::unique_ptr<MashTestSuite> test_suite_;
-  std::unique_ptr<MojoTestConnector> mojo_test_connector_;
-
-  DISALLOW_COPY_AND_ASSIGN(MashTestLauncherDelegate);
-};
-
-std::unique_ptr<content::ServiceManagerConnection>
-    CreateServiceManagerConnection(MashTestLauncherDelegate* delegate) {
-  delegate->GetMojoTestConnectorForSingleProcess()->Init();
-  std::unique_ptr<content::ServiceManagerConnection> connection(
-      content::ServiceManagerConnection::Create(
-          delegate->GetMojoTestConnectorForSingleProcess()
-              ->InitBackgroundServiceManager(),
-          base::ThreadTaskRunnerHandle::Get()));
-  connection->Start();
-  connection->GetConnector()->StartService(mash::session::mojom::kServiceName);
-  return connection;
-}
-
-void StartEmbeddedService(service_manager::mojom::ServiceRequest request) {
-  // The UI service requires this to be TYPE_UI, so we just always use TYPE_UI
-  // for now.
-  base::MessageLoop message_loop(base::MessageLoop::TYPE_UI);
-  base::RunLoop run_loop;
-  service_manager::ServiceContext context(
-      CreateEmbeddedMashService(
-          base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-              service_manager::switches::kServiceName)),
-      std::move(request));
-  context.SetQuitClosure(run_loop.QuitClosure());
-  run_loop.Run();
-}
-
 }  // namespace
 
 bool RunMashBrowserTests(int argc, char** argv, int* exit_code) {
   base::CommandLine::Init(argc, argv);
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  if (!command_line->HasSwitch("run-in-mash") &&
+  if (!command_line->HasSwitch(switches::kMash) &&
       !command_line->HasSwitch(switches::kMus)) {
     // Currently launching content_package_services via the browser_tests binary
     // will lead to a nested test suite, trying to run all tests again. However
@@ -218,57 +73,12 @@
     return false;
   }
 
-  if (command_line->HasSwitch(MojoTestConnector::kMashApp)) {
-#if defined(OS_LINUX)
-    base::AtExitManager exit_manager;
-#endif
-    base::i18n::InitializeICU();
-
-#if !defined(OFFICIAL_BUILD)
-    base::debug::EnableInProcessStackDumping();
-#endif
-
-    base::TaskScheduler::CreateAndStartWithDefaultParams("StandaloneService");
-
-    command_line->AppendSwitch(ui::switches::kUseTestConfig);
-    service_manager::RunStandaloneService(base::Bind(&StartEmbeddedService));
-    *exit_code = 0;
-
-    base::TaskScheduler::GetInstance()->Shutdown();
-
-    return true;
-  }
-
   size_t parallel_jobs = base::NumParallelJobs();
-  std::unique_ptr<ChromeTestSuiteRunner> chrome_test_suite_runner;
-  std::unique_ptr<MusTestLauncherDelegate> mus_test_launcher_delegate;
-  std::unique_ptr<MashTestLauncherDelegate> mash_test_launcher_delegate;
-  ChromeTestLauncherDelegate* test_launcher_delegate = nullptr;
-  if (command_line->HasSwitch(switches::kMus)) {
-    chrome_test_suite_runner = base::MakeUnique<ChromeTestSuiteRunner>();
-    mus_test_launcher_delegate = base::MakeUnique<MusTestLauncherDelegate>(
-        chrome_test_suite_runner.get());
-    test_launcher_delegate = mus_test_launcher_delegate.get();
-  } else {
-    if (parallel_jobs > 1U)
-      parallel_jobs /= 2U;
-    mash_test_launcher_delegate = base::MakeUnique<MashTestLauncherDelegate>();
-    test_launcher_delegate = mash_test_launcher_delegate.get();
-  }
-
-  // --single_process and no service pipe token indicate we were run directly
-  // from the command line. In this case we have to start up
-  // ServiceManagerConnection as though we were embedded.
-  content::ServiceManagerConnection::Factory service_manager_connection_factory;
-  if (command_line->HasSwitch(content::kSingleProcessTestsFlag) &&
-      !command_line->HasSwitch(service_manager::switches::kServicePipeToken) &&
-      mash_test_launcher_delegate) {
-    service_manager_connection_factory = base::Bind(
-        &CreateServiceManagerConnection, mash_test_launcher_delegate.get());
-    content::ServiceManagerConnection::SetFactoryForTest(
-        &service_manager_connection_factory);
-  }
+  ChromeTestSuiteRunner chrome_test_suite_runner;
+  MusTestLauncherDelegate test_launcher_delegate(&chrome_test_suite_runner);
+  if (command_line->HasSwitch(switches::kMash) && parallel_jobs > 1U)
+    parallel_jobs /= 2U;
   *exit_code =
-      LaunchChromeTests(parallel_jobs, test_launcher_delegate, argc, argv);
+      LaunchChromeTests(parallel_jobs, &test_launcher_delegate, argc, argv);
   return true;
 }
diff --git a/chrome/test/base/mash_browser_tests_manifest.json b/chrome/test/base/mash_browser_tests_manifest.json
deleted file mode 100644
index e6bfadd..0000000
--- a/chrome/test/base/mash_browser_tests_manifest.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "name": "mash_browser_tests",
-  "display_name": "Mash Browser Tests",
-  "interface_provider_specs": {
-    "service_manager:connector": {
-      "requires": { "*": [ "app" ] }
-    }
-  }
-}
diff --git a/chrome/test/base/mojo_test_connector.cc b/chrome/test/base/mojo_test_connector.cc
deleted file mode 100644
index 8cd656b5..0000000
--- a/chrome/test/base/mojo_test_connector.cc
+++ /dev/null
@@ -1,270 +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/test/base/mojo_test_connector.h"
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/command_line.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread.h"
-#include "chrome/common/chrome_switches.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/service_names.mojom.h"
-#include "content/public/test/test_launcher.h"
-#include "mash/session/public/interfaces/constants.mojom.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/outgoing_broker_client_invitation.h"
-#include "mojo/edk/embedder/platform_channel_pair.h"
-#include "mojo/edk/embedder/scoped_ipc_support.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
-#include "services/catalog/store.h"
-#include "services/service_manager/background/background_service_manager.h"
-#include "services/service_manager/public/cpp/connector.h"
-#include "services/service_manager/public/cpp/service.h"
-#include "services/service_manager/public/cpp/service_context.h"
-#include "services/service_manager/runner/common/client_util.h"
-#include "services/service_manager/runner/common/switches.h"
-#include "services/service_manager/runner/host/service_process_launcher.h"
-#include "services/service_manager/service_manager.h"
-#include "services/service_manager/switches.h"
-
-namespace {
-
-const char kMashTestRunnerName[] = "mash_browser_tests";
-const char kMusTestRunnerName[] = "mus_browser_tests";
-
-// State created per test to register a client process with the background
-// service manager.
-class MojoTestState : public content::TestState {
- public:
-  MojoTestState(MojoTestConnector* connector,
-                base::CommandLine* command_line,
-                base::TestLauncher::LaunchOptions* test_launch_options,
-                MojoTestConnector::Config config)
-      : connector_(connector),
-        background_service_manager_(nullptr),
-        platform_channel_(base::MakeUnique<mojo::edk::PlatformChannelPair>()),
-        main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
-        config_(config),
-        weak_factory_(this) {
-    command_line->AppendSwitch(MojoTestConnector::kTestSwitch);
-    command_line->AppendSwitchASCII(switches::kMusConfig,
-                                    config_ == MojoTestConnector::Config::MASH
-                                        ? switches::kMash
-                                        : switches::kMus);
-
-#if defined(OS_WIN)
-    platform_channel_->PrepareToPassClientHandleToChildProcess(
-        command_line, &test_launch_options->handles_to_inherit);
-#elif defined(OS_POSIX)
-    platform_channel_->PrepareToPassClientHandleToChildProcess(
-        command_line, &test_launch_options->fds_to_remap);
-#else
-#error "Unsupported"
-#endif
-
-    // Create the pipe token, as it must be passed to children processes via the
-    // command line.
-    service_ = service_manager::PassServiceRequestOnCommandLine(
-        &broker_client_invitation_, command_line);
-  }
-
-  ~MojoTestState() override {}
-
- private:
-  // content::TestState:
-  void ChildProcessLaunched(base::ProcessHandle handle,
-                            base::ProcessId pid) override {
-    platform_channel_->ChildProcessLaunched();
-    broker_client_invitation_.Send(
-        handle,
-        mojo::edk::ConnectionParams(mojo::edk::TransportProtocol::kLegacy,
-                                    platform_channel_->PassServerHandle()));
-
-    main_task_runner_->PostTask(FROM_HERE,
-                                base::Bind(&MojoTestState::SetupService,
-                                           weak_factory_.GetWeakPtr(), pid));
-  }
-
-  // Called on the main thread only.
-  // This registers the services needed for the test. This is not done until
-  // after ChildProcessLaunched as previous test runs will tear down existing
-  // connections.
-  void SetupService(base::ProcessId pid) {
-    service_manager::mojom::ServicePtr service;
-    auto request = mojo::MakeRequest(&service);
-
-    // BackgroundServiceManager must be created after mojo::edk::Init() as it
-    // attempts to create mojo pipes for the provided catalog on a separate
-    // thread.
-    background_service_manager_ =
-        connector_->CreateBackgroundServiceManager(std::move(service));
-    background_service_manager_->RegisterService(
-        service_manager::Identity(content::mojom::kPackagedServicesServiceName,
-                                  service_manager::mojom::kRootUserID),
-        std::move(service_), mojo::MakeRequest(&pid_receiver_));
-
-    DCHECK(pid_receiver_.is_bound());
-    pid_receiver_->SetPID(pid);
-    pid_receiver_.reset();
-
-    if (config_ == MojoTestConnector::Config::MASH) {
-      background_service_manager_->StartService(
-          service_manager::Identity(mash::session::mojom::kServiceName,
-                                    service_manager::mojom::kRootUserID));
-    }
-  }
-
-  mojo::edk::OutgoingBrokerClientInvitation broker_client_invitation_;
-  MojoTestConnector* connector_;
-  std::unique_ptr<service_manager::BackgroundServiceManager>
-      background_service_manager_;
-
-  // The ServicePtr must be created before child process launch so that the pipe
-  // can be set on the command line. It is held until SetupService is called at
-  // which point |background_service_manager_| takes over ownership.
-  service_manager::mojom::ServicePtr service_;
-
-  std::unique_ptr<mojo::edk::PlatformChannelPair> platform_channel_;
-  service_manager::mojom::PIDReceiverPtr pid_receiver_;
-  const scoped_refptr<base::TaskRunner> main_task_runner_;
-
-  const MojoTestConnector::Config config_;
-
-  base::WeakPtrFactory<MojoTestState> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(MojoTestState);
-};
-
-// The name in the manifest results in getting exe:mash_browser_tests used,
-// remap that to browser_tests.
-void RemoveMashFromBrowserTests(base::CommandLine* command_line) {
-  base::FilePath exe_path(command_line->GetProgram());
-#if defined(OS_WIN)
-  exe_path = exe_path.DirName().Append(FILE_PATH_LITERAL("browser_tests.exe"));
-#else
-  exe_path = exe_path.DirName().Append(FILE_PATH_LITERAL("browser_tests"));
-#endif
-  command_line->SetProgram(exe_path);
-}
-
-}  // namespace
-
-// ServiceProcessLauncherDelegate that makes exe:mash_browser_tests to
-// exe:browser_tests and removes '--run-in-mash'.
-class MojoTestConnector::ServiceProcessLauncherDelegateImpl
-    : public service_manager::ServiceProcessLauncherDelegate {
- public:
-  explicit ServiceProcessLauncherDelegateImpl(
-      const std::string& test_runner_name)
-      : test_runner_name_(test_runner_name) {}
-  ~ServiceProcessLauncherDelegateImpl() override {}
-
- private:
-  // service_manager::ServiceProcessLauncherDelegate:
-  void AdjustCommandLineArgumentsForTarget(
-      const service_manager::Identity& target,
-      base::CommandLine* command_line) override {
-    if (target.name() != content::mojom::kPackagedServicesServiceName) {
-      if (target.name() == test_runner_name_) {
-        RemoveMashFromBrowserTests(command_line);
-        command_line->SetProgram(
-            base::CommandLine::ForCurrentProcess()->GetProgram());
-      }
-      command_line->AppendSwitch(MojoTestConnector::kMashApp);
-      return;
-    }
-
-    base::CommandLine::StringVector argv(command_line->argv());
-    auto iter =
-        std::find(argv.begin(), argv.end(), FILE_PATH_LITERAL("--run-in-mash"));
-    if (iter != argv.end())
-      argv.erase(iter);
-    *command_line = base::CommandLine(argv);
-  }
-
-  const std::string test_runner_name_;
-
-  DISALLOW_COPY_AND_ASSIGN(ServiceProcessLauncherDelegateImpl);
-};
-
-// static
-const char MojoTestConnector::kTestSwitch[] = "is_test";
-// static
-const char MojoTestConnector::kMashApp[] = "mash-app";
-
-MojoTestConnector::MojoTestConnector(
-    std::unique_ptr<base::Value> catalog_contents,
-    Config config)
-    : config_(config),
-      service_process_launcher_delegate_(new ServiceProcessLauncherDelegateImpl(
-          config == MojoTestConnector::Config::MASH ? kMashTestRunnerName
-                                                    : kMusTestRunnerName)),
-      background_service_manager_(nullptr),
-      catalog_contents_(std::move(catalog_contents)) {}
-
-void MojoTestConnector::Init() {
-  // In single-process test mode, browser code will initialize the EDK and IPC.
-  // Otherwise we ensure it's initialized here.
-  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
-          content::kSingleProcessTestsFlag)) {
-    mojo::edk::Init();
-    ipc_thread_ = base::MakeUnique<base::Thread>("IPC thread");
-    ipc_thread_->StartWithOptions(base::Thread::Options(
-        base::MessageLoop::TYPE_IO, 0));
-    ipc_support_ = base::MakeUnique<mojo::edk::ScopedIPCSupport>(
-        ipc_thread_->task_runner(),
-        mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST);
-  }
-}
-
-service_manager::mojom::ServiceRequest
-MojoTestConnector::InitBackgroundServiceManager() {
-  service_manager::mojom::ServicePtr service;
-  auto request = mojo::MakeRequest(&service);
-  background_service_manager_ =
-      CreateBackgroundServiceManager(std::move(service));
-  return request;
-}
-
-std::unique_ptr<service_manager::BackgroundServiceManager>
-MojoTestConnector::CreateBackgroundServiceManager(
-    service_manager::mojom::ServicePtr service) {
-  // BackgroundServiceManager must be created after mojo::edk::Init() as it
-  // attempts to create mojo pipes for the provided catalog on a separate
-  // thread.
-  std::unique_ptr<service_manager::BackgroundServiceManager>
-      background_service_manager =
-          base::MakeUnique<service_manager::BackgroundServiceManager>(
-              service_process_launcher_delegate_.get(),
-              catalog_contents_->CreateDeepCopy());
-  background_service_manager->RegisterService(
-      service_manager::Identity(config_ == MojoTestConnector::Config::MASH
-                                    ? kMashTestRunnerName
-                                    : kMusTestRunnerName,
-                                service_manager::mojom::kRootUserID),
-      std::move(service), nullptr);
-
-  return background_service_manager;
-}
-
-MojoTestConnector::~MojoTestConnector() {}
-
-std::unique_ptr<content::TestState> MojoTestConnector::PrepareForTest(
-    base::CommandLine* command_line,
-    base::TestLauncher::LaunchOptions* test_launch_options) {
-  return base::MakeUnique<MojoTestState>(this, command_line,
-                                         test_launch_options, config_);
-}
-
-void MojoTestConnector::StartService(const std::string& service_name) {
-  background_service_manager_->StartService(service_manager::Identity(
-      service_name, service_manager::mojom::kRootUserID));
-}
diff --git a/chrome/test/base/mojo_test_connector.h b/chrome/test/base/mojo_test_connector.h
deleted file mode 100644
index cf5f6b88..0000000
--- a/chrome/test/base/mojo_test_connector.h
+++ /dev/null
@@ -1,97 +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 CHROME_TEST_BASE_MOJO_TEST_CONNECTOR_H_
-#define CHROME_TEST_BASE_MOJO_TEST_CONNECTOR_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/process/process_handle.h"
-#include "base/test/launcher/test_launcher.h"
-#include "services/service_manager/background/background_service_manager.h"
-#include "services/service_manager/public/interfaces/service.mojom.h"
-
-namespace base {
-class CommandLine;
-class Thread;
-class Value;
-}
-
-namespace mojo {
-namespace edk {
-class ScopedIPCSupport;
-}
-}
-
-namespace content {
-class TestState;
-}
-
-// MojoTestConnector is responsible for providing the necessary wiring for
-// test processes to get a mojo channel passed to them.  To use this class
-// call PrepareForTest() prior to launching each test. It is expected
-// PrepareForTest() is called from content::TestLauncherDelegate::PreRunTest().
-class MojoTestConnector {
- public:
-  // Switch added to command line of each test.
-  static const char kTestSwitch[];
-
-  // Command line switch added to all apps that are expected to be provided by
-  // browser_tests.
-  static const char kMashApp[];
-
-  // Enumeration of the possible chrome-ash configurations supported by this
-  // test.
-  enum class Config {
-    // Aura is backed by mus, but chrome and ash are still in the same process.
-    MUS,
-
-    // Aura is backed by mus and chrome and ash are in separate processes. In
-    // this mode chrome code can only use ash code in ash/public/cpp.
-    MASH,
-  };
-
-  MojoTestConnector(std::unique_ptr<base::Value> catalog_contents,
-                    Config config);
-  ~MojoTestConnector();
-
-  service_manager::BackgroundServiceManager* background_service_manager() {
-    return background_service_manager_.get();
-  }
-
-  // Initializes the Mojo environment, and IPC thread.
-  void Init();
-
-  // Initializes the background thread the ServiceManager runs on.
-  service_manager::mojom::ServiceRequest InitBackgroundServiceManager();
-
-  std::unique_ptr<service_manager::BackgroundServiceManager>
-  CreateBackgroundServiceManager(service_manager::mojom::ServicePtr service);
-
-  std::unique_ptr<content::TestState> PrepareForTest(
-      base::CommandLine* command_line,
-      base::TestLauncher::LaunchOptions* test_launch_options);
-
-  void StartService(const std::string& service_name);
-
- private:
-  class ServiceProcessLauncherDelegateImpl;
-
-  const Config config_;
-
-  std::unique_ptr<ServiceProcessLauncherDelegateImpl>
-      service_process_launcher_delegate_;
-  std::unique_ptr<service_manager::BackgroundServiceManager>
-      background_service_manager_;
-
-  std::unique_ptr<base::Thread> ipc_thread_;
-  std::unique_ptr<mojo::edk::ScopedIPCSupport> ipc_support_;
-
-  std::unique_ptr<base::Value> catalog_contents_;
-
-  DISALLOW_COPY_AND_ASSIGN(MojoTestConnector);
-};
-
-#endif  // CHROME_TEST_BASE_MOJO_TEST_CONNECTOR_H_
diff --git a/chrome/test/base/mus_browser_tests_manifest.json b/chrome/test/base/mus_browser_tests_manifest.json
deleted file mode 100644
index 46c027e..0000000
--- a/chrome/test/base/mus_browser_tests_manifest.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "name": "mus_browser_tests",
-  "display_name": "Mus Browser Tests",
-  "interface_provider_specs": {
-    "service_manager:connector": {
-      "requires": { "*": [ "app" ] }
-    }
-  }
-}
diff --git a/chrome/test/base/ui_test_utils.cc b/chrome/test/base/ui_test_utils.cc
index 3214d5bb..0904f08 100644
--- a/chrome/test/base/ui_test_utils.cc
+++ b/chrome/test/base/ui_test_utils.cc
@@ -430,8 +430,10 @@
   *value_size = -1;
   if (url.is_valid() && contents) {
     scoped_refptr<net::URLRequestContextGetter> context_getter =
-        contents->GetRenderProcessHost()->GetStoragePartition()->
-            GetURLRequestContext();
+        contents->GetMainFrame()
+            ->GetProcess()
+            ->GetStoragePartition()
+            ->GetURLRequestContext();
     base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
                               base::WaitableEvent::InitialState::NOT_SIGNALED);
     CHECK(content::BrowserThread::PostTask(
diff --git a/chrome/test/chromedriver/net/net_util_unittest.cc b/chrome/test/chromedriver/net/net_util_unittest.cc
index 91ae6e2..6c59439 100644
--- a/chrome/test/chromedriver/net/net_util_unittest.cc
+++ b/chrome/test/chromedriver/net/net_util_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/threading/thread.h"
 #include "chrome/test/chromedriver/net/url_request_context_getter.h"
 #include "net/base/ip_endpoint.h"
@@ -33,7 +34,9 @@
  public:
   FetchUrlTest()
       : io_thread_("io"),
-        response_(kSendHello) {
+        response_(kSendHello),
+        scoped_task_environment_(
+            base::test::ScopedTaskEnvironment::MainThreadType::IO) {
     base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
     CHECK(io_thread_.StartWithOptions(options));
     context_getter_ = new URLRequestContextGetter(io_thread_.task_runner());
@@ -108,6 +111,7 @@
   std::unique_ptr<net::HttpServer> server_;
   scoped_refptr<URLRequestContextGetter> context_getter_;
   std::string server_url_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
 };
 
 }  // namespace
diff --git a/chrome/test/chromedriver/server/http_handler.cc b/chrome/test/chromedriver/server/http_handler.cc
index 786be4a..2e5af11 100644
--- a/chrome/test/chromedriver/server/http_handler.cc
+++ b/chrome/test/chromedriver/server/http_handler.cc
@@ -702,40 +702,83 @@
     case kOk:
       response.reset(new net::HttpServerResponseInfo(net::HTTP_OK));
       break;
-    case kNoSuchFrame:
-    case kStaleElementReference:
-    case kElementNotVisible:
-    case kInvalidElementState:
-    case kNoSuchWindow:
-    case kInvalidCookieDomain:
-    case kInvalidSelector:
-    case kXPathLookupError:
-    case kNoAlertOpen:
-    case kInvalidArgument:
+    // error codes
     case kElementNotInteractable:
-    case kNoSuchExecutionContext:
       response.reset(new net::HttpServerResponseInfo(net::HTTP_BAD_REQUEST));
       break;
-    case kNoSuchSession:
-    case kNoSuchElement:
-    case kUnknownCommand:
+    case kInvalidArgument:
+      response.reset(new net::HttpServerResponseInfo(net::HTTP_BAD_REQUEST));
+      break;
+    case kInvalidCookieDomain:
+      response.reset(new net::HttpServerResponseInfo(net::HTTP_BAD_REQUEST));
+      break;
+    case kInvalidElementState:
+      response.reset(new net::HttpServerResponseInfo(net::HTTP_BAD_REQUEST));
+      break;
+    case kInvalidSelector:
+      response.reset(new net::HttpServerResponseInfo(net::HTTP_BAD_REQUEST));
+      break;
+    case kJavaScriptError:
+      response.reset(new net::HttpServerResponseInfo(net::HTTP_BAD_REQUEST));
+      break;
     case kNoSuchCookie:
       response.reset(new net::HttpServerResponseInfo(net::HTTP_NOT_FOUND));
       break;
-    case kTimeout:
+    case kNoSuchElement:
+      response.reset(new net::HttpServerResponseInfo(net::HTTP_NOT_FOUND));
+      break;
+    case kNoSuchFrame:
+      response.reset(new net::HttpServerResponseInfo(net::HTTP_NOT_FOUND));
+      break;
+    case kNoSuchWindow:
+      response.reset(new net::HttpServerResponseInfo(net::HTTP_NOT_FOUND));
+      break;
     case kScriptTimeout:
       response.reset(
           new net::HttpServerResponseInfo(net::HTTP_REQUEST_TIMEOUT));
       break;
-    case kUnknownError:
-    case kUnableToSetCookie:
-    case kJavaScriptError:
-    case kUnexpectedAlertOpen:
     case kSessionNotCreatedException:
+      response.reset(
+          new net::HttpServerResponseInfo(net::HTTP_INTERNAL_SERVER_ERROR));
+      break;
+    case kStaleElementReference:
+      response.reset(new net::HttpServerResponseInfo(net::HTTP_NOT_FOUND));
+      break;
+    case kTimeout:
+      response.reset(
+          new net::HttpServerResponseInfo(net::HTTP_REQUEST_TIMEOUT));
+      break;
+    case kUnableToSetCookie:
+      response.reset(
+          new net::HttpServerResponseInfo(net::HTTP_INTERNAL_SERVER_ERROR));
+      break;
+    case kUnexpectedAlertOpen:
+      response.reset(
+          new net::HttpServerResponseInfo(net::HTTP_INTERNAL_SERVER_ERROR));
+      break;
+    case kUnknownCommand:
+      response.reset(new net::HttpServerResponseInfo(net::HTTP_NOT_FOUND));
+      break;
+    case kUnknownError:
+      response.reset(
+          new net::HttpServerResponseInfo(net::HTTP_INTERNAL_SERVER_ERROR));
+      break;
+    case kUnsupportedOperation:
+      response.reset(
+          new net::HttpServerResponseInfo(net::HTTP_INTERNAL_SERVER_ERROR));
+      break;
+
+    // TODO(kereliuk): evaluate the usage of these as they relate to the spec
+    case kElementNotVisible:
+    case kXPathLookupError:
+    case kNoAlertOpen:
+    case kNoSuchExecutionContext:
+      response.reset(new net::HttpServerResponseInfo(net::HTTP_BAD_REQUEST));
+      break;
+    case kNoSuchSession:
     case kChromeNotReachable:
     case kDisconnected:
     case kForbidden:
-    case kUnsupportedOperation:
     case kTabCrashed:
       response.reset(
           new net::HttpServerResponseInfo(net::HTTP_INTERNAL_SERVER_ERROR));
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-content_suggestion_placeholder.Nexus_5-19.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-content_suggestion_placeholder.Nexus_5-19.png
new file mode 100644
index 0000000..7875d28
--- /dev/null
+++ b/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-content_suggestion_placeholder.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-signin_promo.Nexus_5-19.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-signin_promo.Nexus_5-19.png
index 887697d..a6248db 100644
--- a/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-signin_promo.Nexus_5-19.png
+++ b/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-signin_promo.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.signin_promo.Nexus_5-19.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.signin_promo.Nexus_5-19.png
index c4fd9a7..fa84d75 100644
--- a/chrome/test/data/android/render_tests/ArticleSnippetsTest.signin_promo.Nexus_5-19.png
+++ b/chrome/test/data/android/render_tests/ArticleSnippetsTest.signin_promo.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/chromeos/app_mode/virtual_keyboard/key.pem b/chrome/test/data/chromeos/app_mode/virtual_keyboard/key.pem
new file mode 100644
index 0000000..b1300babd
--- /dev/null
+++ b/chrome/test/data/chromeos/app_mode/virtual_keyboard/key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC+GEsI8mDjBCNS
+LonR4nrVuKMoj6DdikcQo2NK1Bt9sVS9AYGleCJ9pkcAX4XDzUPeUPc9nseA3uz9
+00hXkq0devyW+sWN8cTqzDOEIhQ9U+lQrjD8jM6Nfzj73gdS3WsDWh7C5N+p7Mtp
+6uUOoDiYHSVrrzcbGG89q2InxOBGTS4QE9rt5j7p4dUsknQFDik/lcE9rqulAdIx
+Bl9xC6qd16kqC2he7OCUM/g7O7yRE8G4TDVc+tbAcQd65TtoWkWKvnu1s7nd4DvE
+y+bH/41NBsNCVp943qYbcW5ByQdVsPxWzy9Q1Fx0ovUM52mKpTOdpAtv4Thj9kg/
+e//KHHBxAgMBAAECggEACvRp8JJNOI/uvCfv688+Lm5VQrtiNRoopcIQsQl/qxLq
+0/iQANnnPO/15ATdN88us9NdKCksDJZsOGVyZA+RF+OURlwdweQWqcRKTLlNCsq4
+5ZwgORGhPqDABy3ApMsbRWZuYuNfK1L41voBKMJdeJCnbSj8Bzz1fiuP/MQ4+3wS
+LkIs3pSK4Ppdnn2Hl9razBHUTHCGzTphZilG6YM/rvqzUAgWsrYDoPf4m5hh9+ij
+UV+NH5AMJeEzlbBVo1LjWwudqVoBvxRcnMJUOHwd1as3hV3RlM5hLM2w3720RoVd
+opBHkM+kZOR7jx+pHbRSfU6WgVDKU5JqhWDueERM8QKBgQDpKue9uzMI2OQs+UF7
+/APK06/kLMa80eMbx8uJ8z9KA+WJ6bHqyVdoHYkQfe+MXBFMff8j+xj8mzsw+M0n
+GaF/eCuauO4OBkpOmLSKfGXoIt7Uc5pzsnmC1RJFIsz2Sxmi4Nvxy8KZqutyd9nf
+mZyLAJLChDLwWgvidhE61T7B6QKBgQDQtaHYPsnR1KWzqmJd1iOOkdBinVBNd3Kn
+QjnC6odPWh5uthzPH8Mq0bGPS32Htll+OaYm8lVfzTzsdd1bYmThQhMgo1IlKwlM
+HHz4BdQWI8w+RxP0JoOkOEyCG6QZkRjoB8qYdjGfO7yHgZnmx5sF8TK29McQPt8n
+/9mjk6ndSQKBgQCi4hwdiKZwKcPMPxul1zl2+UZIaZcz1JOIlpvzdH/j3rD9FMn7
+MEflLazQXol3TeGvw9z2b7TW0kIZRdVa2Sbeez5KyaFTHsXN/hMxIxG1hpaPZ2qg
+JC+KW/p1XYg9Dd2M0PQVB7ibzLDJuDv1XcPjvrTHOb6z9NOUkdIbfVhn8QKBgQC9
+nIYRA9ou+9YeyCjdv3JGUErVjL4r4t0S/6OiZZfQi7siMekyc1TITgHWgWrmJNBh
+UNaWg4r0om07FkmogFfOHk1qVXaHtfWYZDlUy1bHVnZ0Dfce1O67/zni6mHHqH7M
+Lmfs41Rpqce6BBBiDe3VFDBS70b6h2QN3u9HIRwtoQKBgAS4ny7Qs860FK4lp+DX
+/PqqNkd7jLWR9sJTsm68YZzG+11PcHXN7z8qJOzLt2TncqGb0JLSLPRqno3RCw0t
+65cnWIYd9jKls9wpqgGPL4fxhO+c5aSG23yXKDyQA4RMEWLtHhprVcMoh6JRkzDW
+v6QkZrlC+emRlRhUfDDJjmaO
+-----END PRIVATE KEY-----
diff --git a/chrome/test/data/chromeos/app_mode/virtual_keyboard/src/background.js b/chrome/test/data/chromeos/app_mode/virtual_keyboard/src/background.js
new file mode 100644
index 0000000..c7a17f7e
--- /dev/null
+++ b/chrome/test/data/chromeos/app_mode/virtual_keyboard/src/background.js
@@ -0,0 +1,137 @@
+// 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.
+
+/**
+ * The packed extension resides in
+ * ../webstore/downloads/fmmbbdiapbcicajbpkpkdbcgidgppada.crx .
+ * Update it too whenever this file is updated.
+ * See https://developer.chrome.com/extensions/packaging#packaging for how to
+ * package.
+ */
+
+chrome.test.runTests([
+  function virtualKeyboardAllRestrict() {
+    chrome.virtualKeyboard.restrictFeatures(
+        {
+          autoCompleteEnabled: false,
+          autoCorrectEnabled: false,
+          spellCheckEnabled: false,
+          voiceInputEnabled: false,
+          handwritingEnabled: false
+        },
+        chrome.test.callbackPass(function(update) {
+          chrome.test.assertEq(
+              {
+                autoCompleteEnabled: false,
+                autoCorrectEnabled: false,
+                spellCheckEnabled: false,
+                voiceInputEnabled: false,
+                handwritingEnabled: false
+              },
+              update);
+
+          chrome.virtualKeyboardPrivate.getKeyboardConfig(
+              chrome.test.callbackPass(function(config) {
+                chrome.test.assertTrue(
+                    config.features.includes('autocomplete-disabled'));
+                chrome.test.assertTrue(
+                    config.features.includes('autocorrect-disabled'));
+                chrome.test.assertTrue(
+                    config.features.includes('spellcheck-disabled'));
+                chrome.test.assertTrue(
+                    config.features.includes('voiceinput-disabled'));
+                chrome.test.assertTrue(
+                    config.features.includes('handwriting-disabled'));
+              }));
+        }));
+  },
+  function virtualKeyboardAllEnable() {
+    chrome.virtualKeyboard.restrictFeatures(
+        {
+          autoCompleteEnabled: true,
+          autoCorrectEnabled: true,
+          spellCheckEnabled: true,
+          voiceInputEnabled: true,
+          handwritingEnabled: true
+        },
+        chrome.test.callbackPass(function(update) {
+          chrome.test.assertEq(
+              {
+                autoCompleteEnabled: true,
+                autoCorrectEnabled: true,
+                spellCheckEnabled: true,
+                voiceInputEnabled: true,
+                handwritingEnabled: true
+              },
+              update);
+          chrome.virtualKeyboardPrivate.getKeyboardConfig(
+              chrome.test.callbackPass(function(config) {
+                chrome.test.assertTrue(
+                    config.features.includes('autocomplete-enabled'));
+                chrome.test.assertTrue(
+                    config.features.includes('autocorrect-enabled'));
+                chrome.test.assertTrue(
+                    config.features.includes('spellcheck-enabled'));
+                chrome.test.assertTrue(
+                    config.features.includes('voiceinput-enabled'));
+                chrome.test.assertTrue(
+                    config.features.includes('handwriting-enabled'));
+              }));
+        }));
+  },
+  function virtualKeyboardPartialRestrict() {
+    chrome.virtualKeyboard.restrictFeatures(
+        {
+          autoCompleteEnabled: false,
+          autoCorrectEnabled: true,
+          spellCheckEnabled: false,
+          voiceInputEnabled: true,
+          // handwritingEnabled is omitted; the current config should be used.
+        },
+        chrome.test.callbackPass(function(update) {
+          chrome.test.assertEq(
+              {
+                autoCompleteEnabled: false,
+                spellCheckEnabled: false,
+              },
+              update);
+          chrome.virtualKeyboardPrivate.getKeyboardConfig(
+              chrome.test.callbackPass(function(config) {
+                chrome.test.assertTrue(
+                    config.features.includes('autocomplete-disabled'));
+                chrome.test.assertTrue(
+                    config.features.includes('autocorrect-enabled'));
+                chrome.test.assertTrue(
+                    config.features.includes('spellcheck-disabled'));
+                chrome.test.assertTrue(
+                    config.features.includes('voiceinput-enabled'));
+                chrome.test.assertTrue(
+                    config.features.includes('handwriting-enabled'));
+              }));
+        }));
+  },
+  function virtualKeyboardOnConfigChanged() {
+    chrome.test.listenOnce(
+        chrome.virtualKeyboardPrivate.onKeyboardConfigChanged,
+        function(config) {
+          chrome.test.assertTrue(!!config);
+          // The callback parameter should be the same as the return value of
+          // |getKeyboardConfig|
+          chrome.virtualKeyboardPrivate.getKeyboardConfig(
+              chrome.test.callbackPass(function(config2) {
+                chrome.test.assertEq(config, config2);
+              }));
+        });
+
+    chrome.virtualKeyboard.restrictFeatures(
+        {
+          autoCompleteEnabled: true,
+          autoCorrectEnabled: true,
+          spellCheckEnabled: false,
+          voiceInputEnabled: true,
+          handwritingEnabled: false
+        },
+        chrome.test.callbackPass());
+  },
+]);
diff --git a/chrome/test/data/chromeos/app_mode/virtual_keyboard/src/manifest.json b/chrome/test/data/chromeos/app_mode/virtual_keyboard/src/manifest.json
new file mode 100644
index 0000000..c3d9bed
--- /dev/null
+++ b/chrome/test/data/chromeos/app_mode/virtual_keyboard/src/manifest.json
@@ -0,0 +1,16 @@
+{
+  "name": "chrome.virtualKeyboard test kiosk app in the kiosk session.",
+  "version": "0.1",
+  "description": "Tests chrome.virtualKeyboard in kiosk apps running in the kiosk session. Extension ID: fmmbbdiapbcicajbpkpkdbcgidgppada",
+  "app": {
+    "background": {
+      "scripts": ["background.js"]
+    }
+  },
+  "kiosk_only": true,
+  "kiosk_enabled": true,
+  "permissions": [
+    "virtualKeyboard",
+    "virtualKeyboardPrivate"
+  ]
+}
diff --git a/chrome/test/data/chromeos/app_mode/webstore/downloads/fmmbbdiapbcicajbpkpkdbcgidgppada.crx b/chrome/test/data/chromeos/app_mode/webstore/downloads/fmmbbdiapbcicajbpkpkdbcgidgppada.crx
new file mode 100644
index 0000000..944679d2
--- /dev/null
+++ b/chrome/test/data/chromeos/app_mode/webstore/downloads/fmmbbdiapbcicajbpkpkdbcgidgppada.crx
Binary files differ
diff --git a/chrome/test/data/chromeos/oobe_webui_browsertest.js b/chrome/test/data/chromeos/oobe_webui_browsertest.js
index dcbe7a9..23e6d92 100644
--- a/chrome/test/data/chromeos/oobe_webui_browsertest.js
+++ b/chrome/test/data/chromeos/oobe_webui_browsertest.js
@@ -98,7 +98,6 @@
       '#user-image-grid',
       '#discard-photo',
       '#take-photo',
-      '#flip-photo',
     ];
 
     // Enable when failure is resolved.
diff --git a/chrome/test/data/devtools/dom_warnings_page.html b/chrome/test/data/devtools/dom_warnings_page.html
new file mode 100644
index 0000000..6b82025
--- /dev/null
+++ b/chrome/test/data/devtools/dom_warnings_page.html
@@ -0,0 +1,4 @@
+<form>
+  <input id="dup" type="text" autocomplete="username">
+  <input id="dup" type="password" autocomplete="current-password">
+</form>
\ No newline at end of file
diff --git a/chrome/test/data/extensions/api_test/messaging/large_messages/background.js b/chrome/test/data/extensions/api_test/messaging/large_messages/background.js
new file mode 100644
index 0000000..8fb5956
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/messaging/large_messages/background.js
@@ -0,0 +1,14 @@
+// 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.
+
+try {
+  // Passing super-large messages should be prevented by the renderer.
+  var tooLarge = 1024 * 1024 * 128;
+  chrome.runtime.sendMessage('a'.repeat(tooLarge));
+  chrome.test.notifyFail();
+} catch (e) {
+  chrome.test.assertEq("Message length exceeded maximum allowed length.",
+                       e.message);
+  chrome.test.notifyPass();
+}
diff --git a/chrome/test/data/extensions/api_test/messaging/large_messages/manifest.json b/chrome/test/data/extensions/api_test/messaging/large_messages/manifest.json
new file mode 100644
index 0000000..d295100
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/messaging/large_messages/manifest.json
@@ -0,0 +1,7 @@
+{
+  "name": "Pass large messages",
+  "description": "Pass obscenely large messages",
+  "background": {"scripts": ["background.js"]},
+  "manifest_version": 2,
+  "version": "0.1"
+}
diff --git a/chrome/test/data/extensions/api_test/modules/background.html b/chrome/test/data/extensions/api_test/modules/background.html
new file mode 100644
index 0000000..526bea5
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/modules/background.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<html>
+  <script src="background.js" type="module"></script>
+</html>
diff --git a/chrome/test/data/extensions/api_test/modules/background.js b/chrome/test/data/extensions/api_test/modules/background.js
new file mode 100644
index 0000000..d4aaab68
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/modules/background.js
@@ -0,0 +1,10 @@
+// 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.
+
+// TODO(devlin): Sadly, there's no good way of checking that the import
+// succeeds, so in the failure case the test just times out, rather than
+// giving a useful error.
+import {pass} from '/module.js';
+
+pass();
diff --git a/chrome/test/data/extensions/api_test/modules/manifest.json b/chrome/test/data/extensions/api_test/modules/manifest.json
new file mode 100644
index 0000000..fd0001b
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/modules/manifest.json
@@ -0,0 +1,6 @@
+{
+  "name": "modules test",
+  "manifest_version": 2,
+  "background": { "page": "background.html" },
+  "version": "0.1"
+}
diff --git a/chrome/test/data/extensions/api_test/modules/module.js b/chrome/test/data/extensions/api_test/modules/module.js
new file mode 100644
index 0000000..919d17b
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/modules/module.js
@@ -0,0 +1,7 @@
+// 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.
+
+export function pass() {
+  chrome.test.notifyPass();
+}
diff --git a/chrome/test/data/extensions/api_test/webrtc_from_web_accessible_resource/content_script.js b/chrome/test/data/extensions/api_test/webrtc_from_web_accessible_resource/content_script.js
index 77780336..6fad383 100644
--- a/chrome/test/data/extensions/api_test/webrtc_from_web_accessible_resource/content_script.js
+++ b/chrome/test/data/extensions/api_test/webrtc_from_web_accessible_resource/content_script.js
@@ -5,4 +5,5 @@
 var iframe = document.createElement('iframe');
 iframe.src = chrome.runtime.getURL(
     'iframe_content.html' + document.location.search);
+iframe.allow = 'microphone';
 document.body.appendChild(iframe);
diff --git a/chrome/test/data/geolocation/iframe_controller.js b/chrome/test/data/geolocation/iframe_controller.js
index a36a3b62..e314e8d 100644
--- a/chrome/test/data/geolocation/iframe_controller.js
+++ b/chrome/test/data/geolocation/iframe_controller.js
@@ -12,6 +12,7 @@
 function addIFrame(iframe_id, iframe_src) {
   var id = 'iframe_' + iframe_id;
   var iframe = document.getElementById(id);
+  iframe.allow = 'geolocation';
   if (iframe_src) {
     iframe.src = iframe_src;
   } else {
diff --git a/chrome/test/data/local_ntp/local_ntp_browsertest.html b/chrome/test/data/local_ntp/local_ntp_browsertest.html
index dcd5a40..a513ad17 100644
--- a/chrome/test/data/local_ntp/local_ntp_browsertest.html
+++ b/chrome/test/data/local_ntp/local_ntp_browsertest.html
@@ -18,10 +18,20 @@
         <div id="logo">
           <!-- The logo that is displayed in the absence of a doodle. -->
           <div id="logo-default" title="Google"></div>
+          <!-- Logo displayed on light themes. Doesn't fade. -->
+          <div id="logo-dark" title="Google"></div>
+          <!-- A doodle, if any: its link and image. -->
           <div id="logo-doodle">
             <a id="logo-doodle-link">
               <img id="logo-doodle-image"></img>
             </a>
+            <!-- A spinner, visible on dark-themed NTPs, prompting the doodle -->
+            <div id="logo-doodle-notifier">
+              <div class="outer ball0"><div class="inner"></div></div>
+              <div class="outer ball1"><div class="inner"></div></div>
+              <div class="outer ball2"><div class="inner"></div></div>
+              <div class="outer ball3"><div class="inner"></div></div>
+            </div>
           </div>
         </div>
         <div id="fakebox">
diff --git a/chrome/test/data/local_ntp/voice_speech_browsertest.js b/chrome/test/data/local_ntp/voice_speech_browsertest.js
index 89b1590..b1edfb85 100644
--- a/chrome/test/data/local_ntp/voice_speech_browsertest.js
+++ b/chrome/test/data/local_ntp/voice_speech_browsertest.js
@@ -754,6 +754,81 @@
 
 
 /**
+ * Tests showing the proper error when there is no network connectivity.
+ */
+test.speech.testNetworkError = function() {
+  test.speech.initSpeech();
+  speech.start();
+  speech.recognition_.onerror({error: 'network'});
+
+  assertFalse(speech.isRecognizing());
+  assertEquals(1, test.speech.recognitionActiveCount);
+  assertEquals(1, test.speech.viewActiveCount);
+  assertEquals(RecognitionError.NETWORK, test.speech.viewState.error);
+
+  test.speech.clock.advanceTime(7999);
+  assertEquals(1, test.speech.viewActiveCount);
+
+  test.speech.clock.advanceTime(1);
+  test.speech.clock.pendingTimeouts.shift().callback();
+  test.speech.validateInactive();
+};
+
+
+/**
+ * Tests showing the proper error when there is no network connectivity, after
+ * interim results have been received.
+ */
+test.speech.testNetworkErrorAfterInterimResults = function() {
+  test.speech.initSpeech();
+
+  const lowConfidenceText = 'low';
+  const highConfidenceText = 'high';
+  const viewText = highConfidenceText + lowConfidenceText;
+  const responseEvent =
+      test.speech.createInterimResponse(lowConfidenceText, highConfidenceText);
+
+  speech.start();
+  speech.recognition_.onresult(responseEvent);
+  speech.recognition_.onerror({error: 'network'});
+
+  assertFalse(speech.isRecognizing());
+  assertEquals(1, test.speech.recognitionActiveCount);
+  assertEquals(1, test.speech.viewActiveCount);
+  assertEquals(RecognitionError.NETWORK, test.speech.viewState.error);
+
+  test.speech.clock.advanceTime(7999);
+  assertEquals(1, test.speech.viewActiveCount);
+
+  test.speech.clock.advanceTime(1);
+  test.speech.clock.pendingTimeouts.shift().callback();
+  test.speech.validateInactive();
+};
+
+
+/**
+ * Tests showing the proper error when microphone permission is denied.
+ */
+test.speech.testPermissionError = function() {
+  test.speech.initSpeech();
+  speech.start();
+  speech.recognition_.onerror({error: 'not-allowed'});
+
+  assertFalse(speech.isRecognizing());
+  assertEquals(1, test.speech.recognitionActiveCount);
+  assertEquals(1, test.speech.viewActiveCount);
+  assertEquals(RecognitionError.NOT_ALLOWED, test.speech.viewState.error);
+
+  test.speech.clock.advanceTime(7999);
+  assertEquals(1, test.speech.viewActiveCount);
+
+  test.speech.clock.advanceTime(1);
+  test.speech.clock.pendingTimeouts.shift().callback();
+  test.speech.validateInactive();
+};
+
+
+/**
  * Tests that if no interactions occurs for some time during speech recognition,
  * the current high confidence speech results are submitted for search.
  */
diff --git a/chrome/test/data/nacl/BUILD.gn b/chrome/test/data/nacl/BUILD.gn
index 4a46affe..ed8057c9 100644
--- a/chrome/test/data/nacl/BUILD.gn
+++ b/chrome/test/data/nacl/BUILD.gn
@@ -5,6 +5,7 @@
 import("//build/config/compiler/compiler.gni")
 import("//build/config/features.gni")
 import("//build/config/nacl/config.gni")
+import("//components/nacl/features.gni")
 import("//ppapi/native_client/nacl_test_data.gni")
 
 group("nacl") {
diff --git a/chrome/test/data/plugin_power_saver/run_all_flash.html b/chrome/test/data/plugin_power_saver/run_all_flash.html
new file mode 100644
index 0000000..6369f83ca
--- /dev/null
+++ b/chrome/test/data/plugin_power_saver/run_all_flash.html
@@ -0,0 +1,4 @@
+<object id='small' type='application/x-shockwave-flash' width='16'
+    height='16'></object>
+<object id='cross_origin' data='http://otherorigin.com/fake.swf'
+    type='application/x-shockwave-flash' width='400' height='100'></object>
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index ed5d3bd..469a9a5f 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -1657,6 +1657,14 @@
     ]
   },
 
+  "RunAllFlashInAllowMode": {
+    "os": ["win", "linux", "mac", "chromeos"],
+    "test_policy": { "RunAllFlashInAllowMode": true },
+    "pref_mappings": [
+      { "pref": "plugins.run_all_flash_in_allow_mode" }
+    ]
+  },
+
   "BookmarkBarEnabled": {
     "os": ["win", "linux", "mac", "chromeos"],
     "can_be_recommended": true,
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index 73ba31e..fce8c81 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -104,6 +104,8 @@
     "webui_resource_async_browsertest.js",
   ]
 
+  extra_js_files = [ "//chrome/browser/resources/md_downloads/constants.js" ]
+
   if (is_chromeos) {
     sources += [
       "settings/easy_unlock_browsertest_chromeos.js",
diff --git a/chrome/test/data/webui/extensions/extension_item_test.js b/chrome/test/data/webui/extensions/extension_item_test.js
index da13a36e..7f7f3a5 100644
--- a/chrome/test/data/webui/extensions/extension_item_test.js
+++ b/chrome/test/data/webui/extensions/extension_item_test.js
@@ -110,10 +110,21 @@
       testNormalElementsAreVisible(item);
       testDeveloperElementsAreVisible(item);
 
+      // Developer reload button should be visible only for enabled unpacked
+      // extensions.
       extension_test_util.testVisible(item, '#dev-reload-button', false);
+
       item.set('data.location', chrome.developerPrivate.Location.UNPACKED);
       Polymer.dom.flush();
       extension_test_util.testVisible(item, '#dev-reload-button', true);
+
+      item.set('data.state', chrome.developerPrivate.ExtensionState.DISABLED);
+      Polymer.dom.flush();
+      extension_test_util.testVisible(item, '#dev-reload-button', false);
+
+      item.set('data.state', chrome.developerPrivate.ExtensionState.TERMINATED);
+      Polymer.dom.flush();
+      extension_test_util.testVisible(item, '#dev-reload-button', false);
     });
 
     /** Tests that the delegate methods are correctly called. */
diff --git a/chrome/test/data/webui/interventions_internals_browsertest.js b/chrome/test/data/webui/interventions_internals_browsertest.js
index 9ce8cee..649774e 100644
--- a/chrome/test/data/webui/interventions_internals_browsertest.js
+++ b/chrome/test/data/webui/interventions_internals_browsertest.js
@@ -7,7 +7,7 @@
  */
 
 /** @const {string} Path to source root. */
-var ROOT_PATH = '../../../../';
+let ROOT_PATH = '../../../../';
 
 /**
  * Test fixture for InterventionsInternals WebUI testing.
@@ -46,23 +46,23 @@
       constructor() {
         super(['getPreviewsEnabled']);
 
-        /** @private {boolean} */
-        this.previewsEnabled_ = false;
+        /** @private {!Map} */
+        this.statuses_ = new Map();
       }
 
       /**
-       * Change the behavior of the PageHandler for testing purposes.
-       * @param {boolean} The new status for previews.
+       * Setup testing map.
+       * @param {!Map} map The testing status map.
        */
-      setPreviewsEnabled(enabled) {
-        this.previewsEnabled_ = enabled;
+      setTestingMap(map) {
+        this.statuses_ = map;
       }
 
-      /** @override */
+      /** @override **/
       getPreviewsEnabled() {
         this.methodCalled('getPreviewsEnabled');
         return Promise.resolve({
-          enabled: this.previewsEnabled_,
+          statuses: this.statuses_,
         });
       }
     }
@@ -75,42 +75,39 @@
   },
 };
 
-TEST_F('InterventionsInternalsUITest', 'PreviewStatusEnabledTest', function() {
+TEST_F('InterventionsInternalsUITest', 'DisplayCorrectStatuses', function() {
   let setupFnResolver = this.setupFnResolver;
 
-  test('EnabledStatusTest', function() {
+  test('DisplayCorrectStatuses', () => {
     // Setup testPageHandler behavior.
-    window.testPageHandler.setPreviewsEnabled(true);
-    setupFnResolver.resolve();
+    let testMap = new Map();
+    testMap.set('params1', {
+      description: 'Params 1',
+      enabled: true,
+    });
+    testMap.set('params2', {
+      description: 'Params 2',
+      enabled: false,
+    });
+    testMap.set('params3', {
+      description: 'Param 3',
+      enabled: false,
+    });
+
+    window.testPageHandler.setTestingMap(testMap);
+    this.setupFnResolver.resolve();
 
     return setupFnResolver.promise
-        .then(function() {
+        .then(() => {
           return window.testPageHandler.whenCalled('getPreviewsEnabled');
         })
-        .then(function() {
-          let message = document.querySelector('#offlinePreviews');
-          expectEquals('OfflinePreviews: Enabled', message.textContent);
-        });
-  });
-
-  mocha.run();
-});
-
-TEST_F('InterventionsInternalsUITest', 'PreviewStatusDisabledTest', function() {
-  let setupFnResolver = this.setupFnResolver;
-
-  test('DisabledStatusTest', function() {
-    // Setup testPageHandler behavior.
-    window.testPageHandler.setPreviewsEnabled(false);
-    setupFnResolver.resolve();
-
-    return setupFnResolver.promise
-        .then(function() {
-          return window.testPageHandler.whenCalled('getPreviewsEnabled');
-        })
-        .then(function() {
-          let message = document.querySelector('#offlinePreviews');
-          expectEquals('OfflinePreviews: Disabled', message.textContent);
+        .then(() => {
+          testMap.forEach((value, key) => {
+            let expected = value.description + ': ' +
+                (value.enabled ? 'Enabled' : 'Disabled');
+            let actual = document.querySelector('#' + key).textContent;
+            expectEquals(expected, actual);
+          });
         });
   });
 
diff --git a/chrome/test/data/webui/md_downloads/downloads_browsertest.js b/chrome/test/data/webui/md_downloads/downloads_browsertest.js
index 31203b8a..d4f8ffeee 100644
--- a/chrome/test/data/webui/md_downloads/downloads_browsertest.js
+++ b/chrome/test/data/webui/md_downloads/downloads_browsertest.js
@@ -56,9 +56,9 @@
  * @constructor
  * @extends {DownloadsTest}
  */
-function DownloadsLayoutTest() {}
+function DownloadsManagerTest() {}
 
-DownloadsLayoutTest.prototype = {
+DownloadsManagerTest.prototype = {
   __proto__: DownloadsTest.prototype,
 
   /** @override */
@@ -66,11 +66,13 @@
 
   /** @override */
   extraLibraries: DownloadsTest.prototype.extraLibraries.concat([
-    'layout_tests.js',
+    ROOT_PATH + 'ui/webui/resources/js/cr.js',
+    ROOT_PATH + 'chrome/browser/resources/md_downloads/constants.js',
+    'manager_tests.js',
   ]),
 };
 
-TEST_F('DownloadsLayoutTest', 'All', function() {
+TEST_F('DownloadsManagerTest', 'All', function() {
   mocha.run();
 });
 
diff --git a/chrome/test/data/webui/md_downloads/layout_tests.js b/chrome/test/data/webui/md_downloads/layout_tests.js
deleted file mode 100644
index 7af4dac..0000000
--- a/chrome/test/data/webui/md_downloads/layout_tests.js
+++ /dev/null
@@ -1,29 +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.
-
-suite('layout tests', function() {
-  /** @type {!downloads.Manager} */
-  let manager;
-
-  setup(function() {
-    PolymerTest.clearBody();
-    manager = document.createElement('downloads-manager');
-    document.body.appendChild(manager);
-    assertEquals(manager, downloads.Manager.get());
-  });
-
-  test('long URLs ellide', function() {
-    downloads.Manager.insertItems(0, [{
-      file_name: 'file name',
-      state: downloads.States.COMPLETE,
-      url: 'a'.repeat(1000),
-    }]);
-
-    Polymer.dom.flush();
-
-    const item = manager.$$('downloads-item');
-    assertLT(item.$$('#url').offsetWidth, item.offsetWidth);
-    assertEquals(300, item.$$('#url').textContent.length);
-  });
-});
diff --git a/chrome/test/data/webui/md_downloads/manager_tests.js b/chrome/test/data/webui/md_downloads/manager_tests.js
new file mode 100644
index 0000000..c1e89b3
--- /dev/null
+++ b/chrome/test/data/webui/md_downloads/manager_tests.js
@@ -0,0 +1,89 @@
+// 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.
+
+suite('manager tests', function() {
+  const DOWNLOAD_DATA_TEMPLATE = Object.freeze({
+    by_ext_id: '',
+    by_ext_name: '',
+    danger_type: downloads.DangerType.NOT_DANGEROUS,
+    date_string: '',
+    file_externally_removed: false,
+    file_path: '/some/file/path',
+    file_name: 'download 1',
+    file_url: 'file:///some/file/path',
+    id: '',
+    last_reason_text: '',
+    otr: false,
+    percent: 100,
+    progress_status_text: '',
+    resume: false,
+    return: false,
+    since_string: 'Today',
+    started: Date.now() - 10000,
+    state: downloads.States.COMPLETE,
+    total: -1,
+    url: 'http://permission.site',
+  });
+
+  /** @type {!downloads.Manager} */
+  let manager;
+
+  setup(function() {
+    PolymerTest.clearBody();
+    manager = document.createElement('downloads-manager');
+    document.body.appendChild(manager);
+    assertEquals(manager, downloads.Manager.get());
+  });
+
+  test('long URLs ellide', function() {
+    downloads.Manager.insertItems(0, [{
+                                    file_name: 'file name',
+                                    state: downloads.States.COMPLETE,
+                                    url: 'a'.repeat(1000),
+                                  }]);
+    Polymer.dom.flush();
+
+    const item = manager.$$('downloads-item');
+    assertLT(item.$$('#url').offsetWidth, item.offsetWidth);
+    assertEquals(300, item.$$('#url').textContent.length);
+  });
+
+  test('inserting items at beginning render dates correctly', function() {
+    const dateQuery = '* /deep/ h3[id=date]:not(:empty)';
+    const countDates = () => manager.querySelectorAll(dateQuery).length;
+
+    let download1 = Object.assign({}, DOWNLOAD_DATA_TEMPLATE);
+    let download2 = Object.assign({}, DOWNLOAD_DATA_TEMPLATE);
+
+    downloads.Manager.insertItems(0, [download1, download2]);
+    Polymer.dom.flush();
+    assertEquals(1, countDates());
+
+    downloads.Manager.removeItem(0);
+    Polymer.dom.flush();
+    assertEquals(1, countDates());
+
+    downloads.Manager.insertItems(0, [download1]);
+    Polymer.dom.flush();
+    assertEquals(1, countDates());
+  });
+
+  test('update', function() {
+    let dangerousDownload = Object.assign({}, DOWNLOAD_DATA_TEMPLATE, {
+      danger_type: downloads.DangerType.DANGEROUS_FILE,
+      state: downloads.States.DANGEROUS,
+    });
+    downloads.Manager.insertItems(0, [dangerousDownload]);
+    Polymer.dom.flush();
+    assertTrue(!!manager.$$('downloads-item').$$('.dangerous'));
+
+    let safeDownload = Object.assign({}, dangerousDownload, {
+      danger_type: downloads.DangerType.NOT_DANGEROUS,
+      state: downloads.States.COMPLETE,
+    });
+    downloads.Manager.updateItem(0, safeDownload);
+    Polymer.dom.flush();
+    assertFalse(!!manager.$$('downloads-item').$$('.dangerous'));
+  });
+});
diff --git a/chrome/test/data/webui/print_preview/native_layer_stub.js b/chrome/test/data/webui/print_preview/native_layer_stub.js
index 28643bc..95e3b51 100644
--- a/chrome/test/data/webui/print_preview/native_layer_stub.js
+++ b/chrome/test/data/webui/print_preview/native_layer_stub.js
@@ -33,7 +33,7 @@
 
       /**
        * @private {!Map<string,
-       *                !Promise<!print_preview.PrinterCapabilitiesResponse>}
+       *                !Promise<!print_preview.CapabilitiesResponse>}
        *     A map from destination IDs to the responses to be sent when
        *     |getPrinterCapabilities| is called for the ID.
        */
@@ -115,8 +115,8 @@
     }
 
     /** @override */
-    getPrinterCapabilities(printerId) {
-      this.methodCalled('getPrinterCapabilities', printerId);
+    getPrinterCapabilities(printerId, type) {
+      this.methodCalled('getPrinterCapabilities', printerId, type);
       return this.localDestinationCapabilities_.get(printerId);
     }
 
@@ -179,14 +179,14 @@
     }
 
     /**
-     * @param {!print_preview.PrinterCapabilitiesResponse} response The
+     * @param {!print_preview.CapabilitiesResponse} response The
      *     response to send for the destination whose ID is in the response.
      * @param {boolean?} opt_reject Whether to reject the callback for this
      *     destination. Defaults to false (will resolve callback) if not
      *     provided.
      */
     setLocalDestinationCapabilities(response, opt_reject) {
-      this.localDestinationCapabilities_.set(response.printerId,
+      this.localDestinationCapabilities_.set(response.printer.deviceName,
           opt_reject ? Promise.reject() : Promise.resolve(response));
     }
 
diff --git a/chrome/test/data/webui/print_preview/print_preview_destination_search_test.js b/chrome/test/data/webui/print_preview/print_preview_destination_search_test.js
index 39d5125..5629c51 100644
--- a/chrome/test/data/webui/print_preview/print_preview_destination_search_test.js
+++ b/chrome/test/data/webui/print_preview/print_preview_destination_search_test.js
@@ -140,10 +140,12 @@
     test('ResolutionFails', function() {
       var destId = "001122DEADBEEF";
       if (cr.isChromeOS) {
-        nativeLayer_.setSetupPrinterResponse(true, { printerId: destId,
-                                                     success: false,});
+        nativeLayer_.setSetupPrinterResponse(true, {printerId: destId,
+                                                    success: false,});
       } else {
-        nativeLayer_.setLocalDestinationCapabilities({printerId: destId,
+        nativeLayer_.setLocalDestinationCapabilities({printer: {
+                                                          deviceName: destId,
+                                                      },
                                                       capabilities: getCaps()},
                                                      true);
       }
@@ -165,7 +167,9 @@
       if (cr.isChromeOS)
         nativeLayer_.setSetupPrinterResponse(false, response);
       else
-        nativeLayer_.setLocalDestinationCapabilities({printerId: destId,
+        nativeLayer_.setLocalDestinationCapabilities({printer: {
+                                                          deviceName: destId,
+                                                      },
                                                       capabilities: getCaps()});
 
       var waiter = waitForEvent(
diff --git a/chrome/test/data/webui/print_preview/print_preview_tests.js b/chrome/test/data/webui/print_preview/print_preview_tests.js
index b328f7a..a7666917 100644
--- a/chrome/test/data/webui/print_preview/print_preview_tests.js
+++ b/chrome/test/data/webui/print_preview/print_preview_tests.js
@@ -103,8 +103,10 @@
    */
   function getCddTemplate(printerId, opt_printerName) {
     return {
-      printerId: printerId,
-      printerName: opt_printerName || '',
+      printer: {
+        deviceName: printerId,
+        printerName: opt_printerName || '',
+      },
       capabilities: {
         version: '1.0',
         printer: {
@@ -151,7 +153,9 @@
    */
   function getPdfPrinter() {
     return {
-      printerId: 'Save as PDF',
+      printer: {
+        deviceName: 'Save as PDF',
+      },
       capabilities: {
         version: '1.0',
         printer: {
@@ -1343,7 +1347,7 @@
           function(args) {
             // Sanity check some printing argument values.
             var printTicketStore = args.printTicketStore;
-            expectEquals(barDevice.printerId, args.destination.id);
+            expectEquals(barDevice.printer.deviceName, args.destination.id);
             expectEquals(
                 getDefaultOrientation(barDevice) == 'LANDSCAPE',
                 printTicketStore.landscape.getValue());
@@ -1431,11 +1435,11 @@
       // local printer. See crbug.com/741341 and crbug.com/741528
       test('MacOpenPDFInPreview', function() {
         var device = getPdfPrinter();
-        initialSettings.systemDefaultDestinationId_ = device.printerId;
+        initialSettings.systemDefaultDestinationId_ = device.printer.deviceName;
         return setupSettingsAndDestinationsWithCapabilities(device).
             then(function() {
               assertEquals(
-                device.printerId,
+                device.printer.deviceName,
                 printPreview.destinationStore_.selectedDestination.id);
               return nativeLayer.whenCalled('getPreview');
             }).then(function() {
@@ -1465,7 +1469,7 @@
       // print ticket is invalid.
       test('MacOpenPDFInPreviewBadPrintTicket', function() {
         var device = getPdfPrinter();
-        initialSettings.systemDefaultDestinationId_ = device.printerId;
+        initialSettings.systemDefaultDestinationId_ = device.printer.deviceName;
         return Promise.all([
           setupSettingsAndDestinationsWithCapabilities(device),
           nativeLayer.whenCalled('getPreview')
diff --git a/chrome/test/data/webui/settings/appearance_page_test.js b/chrome/test/data/webui/settings/appearance_page_test.js
index 22029e8..f87cf8cb 100644
--- a/chrome/test/data/webui/settings/appearance_page_test.js
+++ b/chrome/test/data/webui/settings/appearance_page_test.js
@@ -149,10 +149,18 @@
 
   if (cr.isChromeOS) {
     test('wallpaperManager', function() {
-      var button = appearancePage.$.wallpaperButton;
-      assertTrue(!!button);
-      MockInteractions.tap(button);
-      return appearanceBrowserProxy.whenCalled('openWallpaperManager');
+      appearanceBrowserProxy.setIsWallpaperPolicyControlled(false);
+      // TODO(dschuyler): This should notice the policy change without needing
+      // the page to be recreated.
+      createAppearancePage();
+      return appearanceBrowserProxy.whenCalled('isWallpaperPolicyControlled')
+          .then(() => {
+            var button = appearancePage.$.wallpaperButton;
+            assertTrue(!!button);
+            assertFalse(button.disabled);
+            MockInteractions.tap(button);
+            return appearanceBrowserProxy.whenCalled('openWallpaperManager');
+          });
     });
 
     test('wallpaperSettingVisible', function() {
@@ -173,7 +181,7 @@
           .then(function() {
             Polymer.dom.flush();
             assertFalse(appearancePage.$$('#wallpaperPolicyIndicator').hidden);
-            assertTrue(appearancePage.$$('#showWallpaperManager').disabled);
+            assertTrue(appearancePage.$$('#wallpaperButton').disabled);
           });
     });
   } else {
diff --git a/chrome/utility/BUILD.gn b/chrome/utility/BUILD.gn
index 5cba26a..d3726b9 100644
--- a/chrome/utility/BUILD.gn
+++ b/chrome/utility/BUILD.gn
@@ -5,6 +5,7 @@
 import("//build/config/crypto.gni")
 import("//build/config/features.gni")
 import("//build/config/sysroot.gni")
+import("//chrome/common/features.gni")
 import("//extensions/features/features.gni")
 import("//printing/features/features.gni")
 import("//services/service_manager/public/service_manifest.gni")
@@ -144,6 +145,34 @@
     }
   }
 
+  if (enable_package_mash_services) {
+    sources += [
+      "mash_service_factory.cc",
+      "mash_service_factory.h",
+    ]
+    deps += [
+      "//mash/quick_launch:lib",
+      "//mash/quick_launch/public/interfaces",
+      "//services/ui:lib",
+      "//services/ui/public/interfaces",
+    ]
+
+    if (is_linux) {
+      deps += [
+        "//components/font_service:lib",
+        "//components/font_service/public/interfaces",
+      ]
+    }
+  }
+
+  if (is_chromeos) {
+    deps += [
+      "//ash/autoclick/mus:lib",
+      "//ash/mus:lib",
+      "//ash/touch_hud/mus:lib",
+    ]
+  }
+
   if (use_nss_certs) {
     sources += [
       "importer/nss_decryptor_system_nss.cc",
diff --git a/chrome/utility/DEPS b/chrome/utility/DEPS
index 99f7b8b6..eccb81c 100644
--- a/chrome/utility/DEPS
+++ b/chrome/utility/DEPS
@@ -2,6 +2,7 @@
   "+chrome/grit",
   "+chrome/installer/util",
   "+chrome/profiling",
+  "+components/font_service/font_service_app.h",
   "+components/payments/content/utility",
   "+components/printing/service/public/cpp",
   "+components/printing/service/public/interfaces",
@@ -15,7 +16,24 @@
   "+media",
   "+services/service_manager/embedder",
   "+services/service_manager/public/cpp",
+  "+services/ui/public",
+  "+services/ui/service.h",
   "+skia/ext",
   "+third_party/libxml",
   "+third_party/zlib/google",
 ]
+
+specific_include_rules = {
+  "mash_service_factory.cc": [
+    "+ash/mus/window_manager_application.h",
+    "+ash/autoclick/mus/autoclick_application.h",
+    "+ash/public/interfaces",
+    "+ash/touch_hud/mus/touch_hud_application.h",
+    "+components/font_service/font_service_app.h",
+    "+components/font_service/public/interfaces",
+    "+mash/quick_launch/public",
+    "+mash/quick_launch/quick_launch.h",
+    "+services/ui/public",
+    "+services/ui/service.h",
+  ]
+}
diff --git a/chrome/utility/chrome_content_utility_client.cc b/chrome/utility/chrome_content_utility_client.cc
index f7f002cf..c07194f 100644
--- a/chrome/utility/chrome_content_utility_client.cc
+++ b/chrome/utility/chrome_content_utility_client.cc
@@ -57,6 +57,10 @@
 #include "chrome/utility/extensions/extensions_handler.h"
 #endif
 
+#if BUILDFLAG(ENABLE_PACKAGE_MASH_SERVICES)
+#include "chrome/utility/mash_service_factory.h"
+#endif
+
 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
 #include "chrome/common/printing/pdf_to_pwg_raster_converter.mojom.h"
 #include "chrome/utility/printing/pdf_to_pwg_raster_converter_service.h"
@@ -359,6 +363,10 @@
   services->emplace(chrome::mojom::kProfileImportServiceName,
                     profile_import_info);
 #endif
+
+#if BUILDFLAG(ENABLE_PACKAGE_MASH_SERVICES)
+  RegisterMashServices(services);
+#endif
 }
 
 void ChromeContentUtilityClient::RegisterNetworkBinders(
diff --git a/chrome/utility/cloud_print/pwg_encoder.cc b/chrome/utility/cloud_print/pwg_encoder.cc
index 0af1c88..c2e1648 100644
--- a/chrome/utility/cloud_print/pwg_encoder.cc
+++ b/chrome/utility/cloud_print/pwg_encoder.cc
@@ -93,9 +93,9 @@
   base::WriteBigEndian<uint32_t>(header + kHeaderCupsDuplex,
                                  pwg_header_info.duplex ? 1 : 0);
   base::WriteBigEndian<uint32_t>(header + kHeaderCupsHwResolutionHorizontal,
-                                 pwg_header_info.dpi);
+                                 pwg_header_info.dpi.width());
   base::WriteBigEndian<uint32_t>(header + kHeaderCupsHwResolutionVertical,
-                                 pwg_header_info.dpi);
+                                 pwg_header_info.dpi.height());
   base::WriteBigEndian<uint32_t>(header + kHeaderCupsTumble,
                                  pwg_header_info.tumble ? 1 : 0);
   base::WriteBigEndian<uint32_t>(header + kHeaderCupsWidth,
diff --git a/chrome/utility/cloud_print/pwg_encoder.h b/chrome/utility/cloud_print/pwg_encoder.h
index dc27d236..5cd8bf4 100644
--- a/chrome/utility/cloud_print/pwg_encoder.h
+++ b/chrome/utility/cloud_print/pwg_encoder.h
@@ -10,6 +10,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "ui/gfx/geometry/size.h"
 
 namespace cloud_print {
 
@@ -17,7 +18,7 @@
 
 struct PwgHeaderInfo {
   PwgHeaderInfo()
-      : dpi(300),
+      : dpi(300, 300),
         total_pages(1),
         flipx(false),
         flipy(false),
@@ -25,7 +26,7 @@
         duplex(false),
         tumble(false) {}
   enum ColorSpace { SGRAY = 18, SRGB = 19 };
-  uint32_t dpi;
+  gfx::Size dpi;
   uint32_t total_pages;
   bool flipx;
   bool flipy;
diff --git a/chrome/utility/cloud_print/pwg_encoder_unittest.cc b/chrome/utility/cloud_print/pwg_encoder_unittest.cc
index 127934c..50d191b 100644
--- a/chrome/utility/cloud_print/pwg_encoder_unittest.cc
+++ b/chrome/utility/cloud_print/pwg_encoder_unittest.cc
@@ -58,7 +58,7 @@
   // Encode in color by default.
   std::unique_ptr<BitmapImage> image = MakeSampleBitmap();
   PwgHeaderInfo header_info;
-  header_info.dpi = kRasterDPI;
+  header_info.dpi = gfx::Size(kRasterDPI, kRasterDPI);
 
   std::string output = PwgEncoder::GetDocumentHeader();
   output += PwgEncoder::EncodePage(*image, header_info);
diff --git a/chrome/utility/mash_service_factory.cc b/chrome/utility/mash_service_factory.cc
new file mode 100644
index 0000000..6cc1763
--- /dev/null
+++ b/chrome/utility/mash_service_factory.cc
@@ -0,0 +1,87 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/utility/mash_service_factory.h"
+
+#include "base/memory/ptr_util.h"
+#include "build/build_config.h"
+#include "mash/quick_launch/public/interfaces/constants.mojom.h"
+#include "mash/quick_launch/quick_launch.h"
+#include "services/ui/public/interfaces/constants.mojom.h"
+#include "services/ui/service.h"
+
+#if defined(OS_CHROMEOS)
+#include "ash/autoclick/mus/autoclick_application.h"  // nogncheck
+#include "ash/mus/window_manager_application.h"       // nogncheck
+#include "ash/public/interfaces/constants.mojom.h"    // nogncheck
+#include "ash/touch_hud/mus/touch_hud_application.h"  // nogncheck
+#endif                                                // defined(OS_CHROMEOS)
+
+#if defined(OS_LINUX) && !defined(OS_ANDROID)
+#include "components/font_service/font_service_app.h"
+#include "components/font_service/public/interfaces/constants.mojom.h"
+#endif  // defined(OS_LINUX) && !defined(OS_ANDROID)
+
+namespace {
+
+using ServiceFactoryFunction = std::unique_ptr<service_manager::Service>();
+
+void RegisterMashService(
+    content::ContentUtilityClient::StaticServiceMap* services,
+    const std::string& name,
+    ServiceFactoryFunction factory_function) {
+  service_manager::EmbeddedServiceInfo service_info;
+  service_info.factory = base::Bind(factory_function);
+  services->emplace(name, service_info);
+}
+
+std::unique_ptr<service_manager::Service> CreateUiService() {
+  return base::MakeUnique<ui::Service>();
+}
+
+#if defined(OS_CHROMEOS)
+std::unique_ptr<service_manager::Service> CreateAshService() {
+  const bool show_primary_host_on_connect = true;
+  return base::MakeUnique<ash::mus::WindowManagerApplication>(
+      show_primary_host_on_connect);
+}
+
+std::unique_ptr<service_manager::Service> CreateAccessibilityAutoclick() {
+  return base::MakeUnique<ash::autoclick::AutoclickApplication>();
+}
+
+std::unique_ptr<service_manager::Service> CreateQuickLaunch() {
+  return base::MakeUnique<mash::quick_launch::QuickLaunch>();
+}
+
+std::unique_ptr<service_manager::Service> CreateTouchHud() {
+  return base::MakeUnique<ash::touch_hud::TouchHudApplication>();
+}
+#endif
+
+#if defined(OS_LINUX) && !defined(OS_ANDROID)
+std::unique_ptr<service_manager::Service> CreateFontService() {
+  return base::MakeUnique<font_service::FontServiceApp>();
+}
+
+#endif  // defined(OS_LINUX) && !defined(OS_ANDROID)
+
+}  // namespace
+
+void RegisterMashServices(
+    content::ContentUtilityClient::StaticServiceMap* services) {
+  RegisterMashService(services, ui::mojom::kServiceName, &CreateUiService);
+  RegisterMashService(services, mash::quick_launch::mojom::kServiceName,
+                      &CreateQuickLaunch);
+#if defined(OS_CHROMEOS)
+  RegisterMashService(services, ash::mojom::kServiceName, &CreateAshService);
+  RegisterMashService(services, "accessibility_autoclick",
+                      &CreateAccessibilityAutoclick);
+  RegisterMashService(services, "touch_hud", &CreateTouchHud);
+#endif
+#if defined(OS_LINUX) && !defined(OS_ANDROID)
+  RegisterMashService(services, font_service::mojom::kServiceName,
+                      &CreateFontService);
+#endif  // defined(OS_LINUX) && !defined(OS_ANDROID)
+}
diff --git a/chrome/utility/mash_service_factory.h b/chrome/utility/mash_service_factory.h
new file mode 100644
index 0000000..5ed5ae69
--- /dev/null
+++ b/chrome/utility/mash_service_factory.h
@@ -0,0 +1,14 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_UTILITY_MASH_SERVICE_FACTORY_H_
+#define CHROME_UTILITY_MASH_SERVICE_FACTORY_H_
+
+#include "content/public/utility/content_utility_client.h"
+
+// Registers the services provided by mash.
+void RegisterMashServices(
+    content::ContentUtilityClient::StaticServiceMap* services);
+
+#endif  // CHROME_UTILITY_MASH_SERVICE_FACTORY_H_
diff --git a/chrome/utility/printing/pdf_to_pwg_raster_converter_impl.cc b/chrome/utility/printing/pdf_to_pwg_raster_converter_impl.cc
index e721f46..c2bcf2d 100644
--- a/chrome/utility/printing/pdf_to_pwg_raster_converter_impl.cc
+++ b/chrome/utility/printing/pdf_to_pwg_raster_converter_impl.cc
@@ -56,7 +56,7 @@
     }
 
     cloud_print::PwgHeaderInfo header_info;
-    header_info.dpi = settings.dpi;
+    header_info.dpi = gfx::Size(settings.dpi, settings.dpi);
     header_info.total_pages = total_page_count;
 
     // Transform odd pages.
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index ef3395aa..5f73e3f 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -48,6 +48,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/certificate_request_result_type.h"
 #include "content/public/browser/client_certificate_delegate.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/resource_dispatcher_host.h"
 #include "content/public/browser/storage_partition.h"
@@ -476,7 +477,7 @@
       base::BindOnce(
           &CastContentBrowserClient::SelectClientCertificateOnIOThread,
           base::Unretained(this), requesting_url,
-          web_contents->GetRenderProcessHost()->GetID(),
+          web_contents->GetMainFrame()->GetProcess()->GetID(),
           base::SequencedTaskRunnerHandle::Get(),
           base::Bind(
               &content::ClientCertificateDelegate::ContinueWithCertificate,
diff --git a/chromecast/media/cma/backend/alsa/stream_mixer_alsa.cc b/chromecast/media/cma/backend/alsa/stream_mixer_alsa.cc
index 48b28af..452b156 100644
--- a/chromecast/media/cma/backend/alsa/stream_mixer_alsa.cc
+++ b/chromecast/media/cma/backend/alsa/stream_mixer_alsa.cc
@@ -85,7 +85,7 @@
 
 // The minimum amount of data that we allow in the ALSA buffer before starting
 // to skip inputs with no available data.
-const int kMinBufferedDataMs = 8;
+const int kMinBufferedDataMs = 20;
 
 // A list of supported sample rates.
 // TODO(jyw): move this up into chromecast/public for 1) documentation and
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc
index 3e499c1b..15823a3 100644
--- a/chromeos/chromeos_switches.cc
+++ b/chromeos/chromeos_switches.cc
@@ -238,12 +238,6 @@
 // Disables wake on wifi features.
 const char kDisableWakeOnWifi[] = "disable-wake-on-wifi";
 
-// EAFE path to use for Easy bootstrapping.
-const char kEafePath[] = "eafe-path";
-
-// EAFE URL to use for Easy bootstrapping.
-const char kEafeUrl[] = "eafe-url";
-
 // Enables the Android Wallpapers App as the default app on Chrome OS.
 const char kEnableAndroidWallpapersApp[] = "enable-android-wallpapers-app";
 
diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h
index c66167b..ca8436e 100644
--- a/chromeos/chromeos_switches.h
+++ b/chromeos/chromeos_switches.h
@@ -75,8 +75,6 @@
     kDisableSystemTimezoneAutomaticDetectionPolicy[];
 CHROMEOS_EXPORT extern const char kDisableVolumeAdjustSound[];
 CHROMEOS_EXPORT extern const char kDisableWakeOnWifi[];
-CHROMEOS_EXPORT extern const char kEafePath[];
-CHROMEOS_EXPORT extern const char kEafeUrl[];
 CHROMEOS_EXPORT extern const char kEnableAndroidWallpapersApp[];
 CHROMEOS_EXPORT extern const char kEnableArc[];
 CHROMEOS_EXPORT extern const char kEnableArcOOBEOptIn[];
diff --git a/chromeos/cryptohome/async_method_caller.cc b/chromeos/cryptohome/async_method_caller.cc
index 42481d4..797d31c 100644
--- a/chromeos/cryptohome/async_method_caller.cc
+++ b/chromeos/cryptohome/async_method_caller.cc
@@ -282,44 +282,46 @@
     data_callback_map_.erase(it);
   }
   // Registers a callback which is called when the result for AsyncXXX is ready.
-  void RegisterAsyncCallback(
-      Callback callback, const char* error, int async_id) {
-    if (async_id == chromeos::CryptohomeClient::kNotReadyAsyncId) {
+  void RegisterAsyncCallback(Callback callback,
+                             const char* error,
+                             base::Optional<int> async_id) {
+    if (!async_id.has_value()) {
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE, base::Bind(callback,
-                                false,  // return status
-                                cryptohome::MOUNT_ERROR_FATAL));
+          FROM_HERE, base::BindOnce(callback,
+                                    false,  // return status
+                                    cryptohome::MOUNT_ERROR_FATAL));
       return;
     }
 
-    if (async_id == 0) {
+    if (async_id.value() == 0) {
       LOG(ERROR) << error;
       return;
     }
-    VLOG(1) << "Adding handler for " << async_id;
-    DCHECK_EQ(callback_map_.count(async_id), 0U);
-    DCHECK_EQ(data_callback_map_.count(async_id), 0U);
-    callback_map_[async_id] = CallbackElement(callback);
+    VLOG(1) << "Adding handler for " << async_id.value();
+    DCHECK_EQ(callback_map_.count(async_id.value()), 0U);
+    DCHECK_EQ(data_callback_map_.count(async_id.value()), 0U);
+    callback_map_[async_id.value()] = CallbackElement(callback);
   }
 
   // Registers a callback which is called when the result for AsyncXXX is ready.
-  void RegisterAsyncDataCallback(
-      DataCallback callback, const char* error, int async_id) {
-    if (async_id == chromeos::CryptohomeClient::kNotReadyAsyncId) {
+  void RegisterAsyncDataCallback(DataCallback callback,
+                                 const char* error,
+                                 base::Optional<int> async_id) {
+    if (!async_id.has_value()) {
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE, base::Bind(callback,
-                                false,  // return status
-                                std::string()));
+          FROM_HERE, base::BindOnce(callback,
+                                    false,  // return status
+                                    std::string()));
       return;
     }
-    if (async_id == 0) {
+    if (async_id.value() == 0) {
       LOG(ERROR) << error;
       return;
     }
-    VLOG(1) << "Adding handler for " << async_id;
-    DCHECK_EQ(callback_map_.count(async_id), 0U);
-    DCHECK_EQ(data_callback_map_.count(async_id), 0U);
-    data_callback_map_[async_id] = DataCallbackElement(callback);
+    VLOG(1) << "Adding handler for " << async_id.value();
+    DCHECK_EQ(callback_map_.count(async_id.value()), 0U);
+    DCHECK_EQ(data_callback_map_.count(async_id.value()), 0U);
+    data_callback_map_[async_id.value()] = DataCallbackElement(callback);
   }
 
   CallbackMap callback_map_;
diff --git a/chromeos/dbus/cryptohome_client.cc b/chromeos/dbus/cryptohome_client.cc
index fabae14..c49cefa5 100644
--- a/chromeos/dbus/cryptohome_client.cc
+++ b/chromeos/dbus/cryptohome_client.cc
@@ -29,9 +29,6 @@
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
 namespace chromeos {
-
-const int CryptohomeClient::kNotReadyAsyncId = -1;
-
 namespace {
 
 // This suffix is appended to cryptohome_id to get hash in stub implementation:
@@ -101,7 +98,7 @@
   // CryptohomeClient override.
   void AsyncCheckKey(const cryptohome::Identification& cryptohome_id,
                      const std::string& key,
-                     const AsyncMethodCallback& callback) override {
+                     AsyncMethodCallback callback) override {
     dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
                                  cryptohome::kCryptohomeAsyncCheckKey);
     dbus::MessageWriter writer(&method_call);
@@ -110,14 +107,14 @@
     proxy_->CallMethod(
         &method_call, kTpmDBusTimeoutMs,
         base::BindOnce(&CryptohomeClientImpl::OnAsyncMethodCall,
-                       weak_ptr_factory_.GetWeakPtr(), callback));
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   // CryptohomeClient override.
   void AsyncMigrateKey(const cryptohome::Identification& cryptohome_id,
                        const std::string& from_key,
                        const std::string& to_key,
-                       const AsyncMethodCallback& callback) override {
+                       AsyncMethodCallback callback) override {
     dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
                                  cryptohome::kCryptohomeAsyncMigrateKey);
     dbus::MessageWriter writer(&method_call);
@@ -127,12 +124,12 @@
     proxy_->CallMethod(
         &method_call, kTpmDBusTimeoutMs,
         base::BindOnce(&CryptohomeClientImpl::OnAsyncMethodCall,
-                       weak_ptr_factory_.GetWeakPtr(), callback));
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   // CryptohomeClient override.
   void AsyncRemove(const cryptohome::Identification& cryptohome_id,
-                   const AsyncMethodCallback& callback) override {
+                   AsyncMethodCallback callback) override {
     dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
                                  cryptohome::kCryptohomeAsyncRemove);
     dbus::MessageWriter writer(&method_call);
@@ -140,7 +137,7 @@
     proxy_->CallMethod(
         &method_call, kTpmDBusTimeoutMs,
         base::BindOnce(&CryptohomeClientImpl::OnAsyncMethodCall,
-                       weak_ptr_factory_.GetWeakPtr(), callback));
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   // CryptohomeClient override.
@@ -227,7 +224,7 @@
   void AsyncMount(const cryptohome::Identification& cryptohome_id,
                   const std::string& key,
                   int flags,
-                  const AsyncMethodCallback& callback) override {
+                  AsyncMethodCallback callback) override {
     dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
                                  cryptohome::kCryptohomeAsyncMount);
     dbus::MessageWriter writer(&method_call);
@@ -240,14 +237,14 @@
     proxy_->CallMethod(
         &method_call, kTpmDBusTimeoutMs,
         base::BindOnce(&CryptohomeClientImpl::OnAsyncMethodCall,
-                       weak_ptr_factory_.GetWeakPtr(), callback));
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   // CryptohomeClient override.
   void AsyncAddKey(const cryptohome::Identification& cryptohome_id,
                    const std::string& key,
                    const std::string& new_key,
-                   const AsyncMethodCallback& callback) override {
+                   AsyncMethodCallback callback) override {
     dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
                                  cryptohome::kCryptohomeAsyncAddKey);
     dbus::MessageWriter writer(&method_call);
@@ -257,23 +254,23 @@
     proxy_->CallMethod(
         &method_call, kTpmDBusTimeoutMs,
         base::BindOnce(&CryptohomeClientImpl::OnAsyncMethodCall,
-                       weak_ptr_factory_.GetWeakPtr(), callback));
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   // CryptohomeClient override.
-  void AsyncMountGuest(const AsyncMethodCallback& callback) override {
+  void AsyncMountGuest(AsyncMethodCallback callback) override {
     dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
                                  cryptohome::kCryptohomeAsyncMountGuest);
     proxy_->CallMethod(
         &method_call, kTpmDBusTimeoutMs,
         base::BindOnce(&CryptohomeClientImpl::OnAsyncMethodCall,
-                       weak_ptr_factory_.GetWeakPtr(), callback));
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   // CryptohomeClient override.
   void AsyncMountPublic(const cryptohome::Identification& public_mount_id,
                         int flags,
-                        const AsyncMethodCallback& callback) override {
+                        AsyncMethodCallback callback) override {
     dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
                                  cryptohome::kCryptohomeAsyncMountPublic);
     dbus::MessageWriter writer(&method_call);
@@ -283,7 +280,7 @@
     proxy_->CallMethod(
         &method_call, kTpmDBusTimeoutMs,
         base::BindOnce(&CryptohomeClientImpl::OnAsyncMethodCall,
-                       weak_ptr_factory_.GetWeakPtr(), callback));
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   // CryptohomeClient override.
@@ -490,7 +487,7 @@
   // CryptohomeClient override.
   void AsyncTpmAttestationCreateEnrollRequest(
       attestation::PrivacyCAType pca_type,
-      const AsyncMethodCallback& callback) override {
+      AsyncMethodCallback callback) override {
     dbus::MethodCall method_call(
         cryptohome::kCryptohomeInterface,
         cryptohome::kCryptohomeAsyncTpmAttestationCreateEnrollRequest);
@@ -499,13 +496,13 @@
     proxy_->CallMethod(
         &method_call, kTpmDBusTimeoutMs,
         base::BindOnce(&CryptohomeClientImpl::OnAsyncMethodCall,
-                       weak_ptr_factory_.GetWeakPtr(), callback));
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   // CryptohomeClient override.
   void AsyncTpmAttestationEnroll(attestation::PrivacyCAType pca_type,
                                  const std::string& pca_response,
-                                 const AsyncMethodCallback& callback) override {
+                                 AsyncMethodCallback callback) override {
     dbus::MethodCall method_call(
         cryptohome::kCryptohomeInterface,
         cryptohome::kCryptohomeAsyncTpmAttestationEnroll);
@@ -517,7 +514,7 @@
     proxy_->CallMethod(
         &method_call, kTpmDBusTimeoutMs,
         base::BindOnce(&CryptohomeClientImpl::OnAsyncMethodCall,
-                       weak_ptr_factory_.GetWeakPtr(), callback));
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   // CryptohomeClient override.
@@ -526,7 +523,7 @@
       attestation::AttestationCertificateProfile certificate_profile,
       const cryptohome::Identification& cryptohome_id,
       const std::string& request_origin,
-      const AsyncMethodCallback& callback) override {
+      AsyncMethodCallback callback) override {
     dbus::MethodCall method_call(
         cryptohome::kCryptohomeInterface,
         cryptohome::kCryptohomeAsyncTpmAttestationCreateCertRequest);
@@ -538,7 +535,7 @@
     proxy_->CallMethod(
         &method_call, kTpmDBusTimeoutMs,
         base::BindOnce(&CryptohomeClientImpl::OnAsyncMethodCall,
-                       weak_ptr_factory_.GetWeakPtr(), callback));
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   // CryptohomeClient override.
@@ -547,7 +544,7 @@
       attestation::AttestationKeyType key_type,
       const cryptohome::Identification& cryptohome_id,
       const std::string& key_name,
-      const AsyncMethodCallback& callback) override {
+      AsyncMethodCallback callback) override {
     dbus::MethodCall method_call(
         cryptohome::kCryptohomeInterface,
         cryptohome::kCryptohomeAsyncTpmAttestationFinishCertRequest);
@@ -562,7 +559,7 @@
     proxy_->CallMethod(
         &method_call, kTpmDBusTimeoutMs,
         base::BindOnce(&CryptohomeClientImpl::OnAsyncMethodCall,
-                       weak_ptr_factory_.GetWeakPtr(), callback));
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   // CryptohomeClient override.
@@ -627,7 +624,7 @@
       attestation::AttestationKeyType key_type,
       const cryptohome::Identification& cryptohome_id,
       const std::string& key_name,
-      const AsyncMethodCallback& callback) override {
+      AsyncMethodCallback callback) override {
     dbus::MethodCall method_call(
         cryptohome::kCryptohomeInterface,
         cryptohome::kCryptohomeTpmAttestationRegisterKey);
@@ -639,7 +636,7 @@
     proxy_->CallMethod(
         &method_call, kTpmDBusTimeoutMs,
         base::BindOnce(&CryptohomeClientImpl::OnAsyncMethodCall,
-                       weak_ptr_factory_.GetWeakPtr(), callback));
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   // CryptohomeClient override.
@@ -651,7 +648,7 @@
       const std::string& device_id,
       attestation::AttestationChallengeOptions options,
       const std::string& challenge,
-      const AsyncMethodCallback& callback) override {
+      AsyncMethodCallback callback) override {
     dbus::MethodCall method_call(
         cryptohome::kCryptohomeInterface,
         cryptohome::kCryptohomeTpmAttestationSignEnterpriseChallenge);
@@ -671,7 +668,7 @@
     proxy_->CallMethod(
         &method_call, kTpmDBusTimeoutMs,
         base::BindOnce(&CryptohomeClientImpl::OnAsyncMethodCall,
-                       weak_ptr_factory_.GetWeakPtr(), callback));
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   // CryptohomeClient override.
@@ -680,7 +677,7 @@
       const cryptohome::Identification& cryptohome_id,
       const std::string& key_name,
       const std::string& challenge,
-      const AsyncMethodCallback& callback) override {
+      AsyncMethodCallback callback) override {
     dbus::MethodCall method_call(
         cryptohome::kCryptohomeInterface,
         cryptohome::kCryptohomeTpmAttestationSignSimpleChallenge);
@@ -694,7 +691,7 @@
     proxy_->CallMethod(
         &method_call, kTpmDBusTimeoutMs,
         base::BindOnce(&CryptohomeClientImpl::OnAsyncMethodCall,
-                       weak_ptr_factory_.GetWeakPtr(), callback));
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   // CryptohomeClient override.
@@ -1006,19 +1003,20 @@
 
  private:
   // Handles the result of AsyncXXX methods.
-  void OnAsyncMethodCall(const AsyncMethodCallback& callback,
+  void OnAsyncMethodCall(AsyncMethodCallback callback,
                          dbus::Response* response) {
     if (!response) {
-      callback.Run(kNotReadyAsyncId);
+      std::move(callback).Run(base::nullopt);
       return;
     }
     dbus::MessageReader reader(response);
     int async_id = 0;
     if (!reader.PopInt32(&async_id)) {
       LOG(ERROR) << "Invalid response: " << response->ToString();
+      std::move(callback).Run(base::nullopt);
       return;
     }
-    callback.Run(async_id);
+    std::move(callback).Run(async_id);
   }
 
   // Handles the result of GetSystemSalt().
diff --git a/chromeos/dbus/cryptohome_client.h b/chromeos/dbus/cryptohome_client.h
index 652ac9b..1d712b4 100644
--- a/chromeos/dbus/cryptohome_client.h
+++ b/chromeos/dbus/cryptohome_client.h
@@ -46,10 +46,6 @@
 // initializes the DBusThreadManager instance.
 class CHROMEOS_EXPORT CryptohomeClient : public DBusClient {
  public:
-  // Constant that will be passed to AsyncMethodCallback to indicate that
-  // cryptohome is not ready yet.
-  static const int kNotReadyAsyncId;
-
   // A callback to handle AsyncCallStatus signals.
   typedef base::Callback<void(int async_id,
                               bool return_status,
@@ -60,8 +56,13 @@
                               bool return_status,
                               const std::string& data)>
       AsyncCallStatusWithDataHandler;
-  // A callback to handle responses of AsyncXXX methods.
-  typedef base::Callback<void(int async_id)> AsyncMethodCallback;
+
+  // Callback for the methods initiate asynchronous operations.
+  // On success (i.e. the asynchronous operation is started), an |async_id|
+  // is returned, so the user code can identify the corresponding singal
+  // handler invocation later.
+  using AsyncMethodCallback = DBusMethodCallback<int /* async_id */>;
+
   // A callback for GetSystemSalt().
   typedef base::Callback<void(DBusMethodCallStatus call_status,
                               const std::vector<uint8_t>& system_salt)>
@@ -154,19 +155,19 @@
   // succeeds.
   virtual void AsyncCheckKey(const cryptohome::Identification& cryptohome_id,
                              const std::string& key,
-                             const AsyncMethodCallback& callback) = 0;
+                             AsyncMethodCallback callback) = 0;
 
   // Calls AsyncMigrateKey method.  |callback| is called after the method call
   // succeeds.
   virtual void AsyncMigrateKey(const cryptohome::Identification& cryptohome_id,
                                const std::string& from_key,
                                const std::string& to_key,
-                               const AsyncMethodCallback& callback) = 0;
+                               AsyncMethodCallback callback) = 0;
 
   // Calls AsyncRemove method.  |callback| is called after the method call
   // succeeds.
   virtual void AsyncRemove(const cryptohome::Identification& cryptohome_id,
-                           const AsyncMethodCallback& callback) = 0;
+                           AsyncMethodCallback callback) = 0;
 
   // Calls RenameCryptohome method. |callback| is called after the method
   // call succeeds.
@@ -206,7 +207,7 @@
   virtual void AsyncMount(const cryptohome::Identification& cryptohome_id,
                           const std::string& key,
                           int flags,
-                          const AsyncMethodCallback& callback) = 0;
+                          AsyncMethodCallback callback) = 0;
 
   // Calls the AsyncAddKey method to asynchronously add another |new_key| for
   // |username|, using |key| to unlock it first.
@@ -214,11 +215,11 @@
   virtual void AsyncAddKey(const cryptohome::Identification& cryptohome_id,
                            const std::string& key,
                            const std::string& new_key,
-                           const AsyncMethodCallback& callback) = 0;
+                           AsyncMethodCallback callback) = 0;
 
   // Calls AsyncMountGuest method.  |callback| is called after the method call
   // succeeds.
-  virtual void AsyncMountGuest(const AsyncMethodCallback& callback) = 0;
+  virtual void AsyncMountGuest(AsyncMethodCallback callback) = 0;
 
   // Calls the AsyncMount method to asynchronously mount the cryptohome for
   // |public_mount_id|. For supported |flags|, see the documentation of
@@ -227,7 +228,7 @@
   virtual void AsyncMountPublic(
       const cryptohome::Identification& public_mount_id,
       int flags,
-      const AsyncMethodCallback& callback) = 0;
+      AsyncMethodCallback callback) = 0;
 
   // Calls TpmIsReady method.
   virtual void TpmIsReady(DBusMethodCallback<bool> callback) = 0;
@@ -332,7 +333,7 @@
   // AsyncTpmAttestationEnroll.
   virtual void AsyncTpmAttestationCreateEnrollRequest(
       chromeos::attestation::PrivacyCAType pca_type,
-      const AsyncMethodCallback& callback) = 0;
+      AsyncMethodCallback callback) = 0;
 
   // Asynchronously finishes an attestation enrollment operation.  The callback
   // will be called when the dbus call completes.  When the operation completes,
@@ -342,7 +343,7 @@
   virtual void AsyncTpmAttestationEnroll(
       chromeos::attestation::PrivacyCAType pca_type,
       const std::string& pca_response,
-      const AsyncMethodCallback& callback) = 0;
+      AsyncMethodCallback callback) = 0;
 
   // Asynchronously creates an attestation certificate request according to
   // |certificate_profile|.  Some profiles require that the |cryptohome_id| of
@@ -359,7 +360,7 @@
       attestation::AttestationCertificateProfile certificate_profile,
       const cryptohome::Identification& cryptohome_id,
       const std::string& request_origin,
-      const AsyncMethodCallback& callback) = 0;
+      AsyncMethodCallback callback) = 0;
 
   // Asynchronously finishes a certificate request operation.  The callback will
   // be called when the dbus call completes.  When the operation completes, the
@@ -375,7 +376,7 @@
       attestation::AttestationKeyType key_type,
       const cryptohome::Identification& cryptohome_id,
       const std::string& key_name,
-      const AsyncMethodCallback& callback) = 0;
+      AsyncMethodCallback callback) = 0;
 
   // Checks if an attestation key already exists.  If the key specified by
   // |key_type| and |key_name| exists, then the result sent to the callback will
@@ -420,7 +421,7 @@
       attestation::AttestationKeyType key_type,
       const cryptohome::Identification& cryptohome_id,
       const std::string& key_name,
-      const AsyncMethodCallback& callback) = 0;
+      AsyncMethodCallback callback) = 0;
 
   // Asynchronously signs an enterprise challenge with the key specified by
   // |key_type| and |key_name|.  |domain| and |device_id| will be included in
@@ -438,7 +439,7 @@
       const std::string& device_id,
       attestation::AttestationChallengeOptions options,
       const std::string& challenge,
-      const AsyncMethodCallback& callback) = 0;
+      AsyncMethodCallback callback) = 0;
 
   // Asynchronously signs a simple challenge with the key specified by
   // |key_type| and |key_name|.  |challenge| can be any set of arbitrary bytes.
@@ -453,7 +454,7 @@
       const cryptohome::Identification& cryptohome_id,
       const std::string& key_name,
       const std::string& challenge,
-      const AsyncMethodCallback& callback) = 0;
+      AsyncMethodCallback callback) = 0;
 
   // Gets the payload associated with the key specified by |key_type| and
   // |key_name|.  The |callback| will be called when the operation completes.
diff --git a/chromeos/dbus/fake_cryptohome_client.cc b/chromeos/dbus/fake_cryptohome_client.cc
index 266f22b..9ccb5722 100644
--- a/chromeos/dbus/fake_cryptohome_client.cc
+++ b/chromeos/dbus/fake_cryptohome_client.cc
@@ -102,22 +102,22 @@
 void FakeCryptohomeClient::AsyncCheckKey(
     const cryptohome::Identification& cryptohome_id,
     const std::string& key,
-    const AsyncMethodCallback& callback) {
-  ReturnAsyncMethodResult(callback);
+    AsyncMethodCallback callback) {
+  ReturnAsyncMethodResult(std::move(callback));
 }
 
 void FakeCryptohomeClient::AsyncMigrateKey(
     const cryptohome::Identification& cryptohome_id,
     const std::string& from_key,
     const std::string& to_key,
-    const AsyncMethodCallback& callback) {
-  ReturnAsyncMethodResult(callback);
+    AsyncMethodCallback callback) {
+  ReturnAsyncMethodResult(std::move(callback));
 }
 
 void FakeCryptohomeClient::AsyncRemove(
     const cryptohome::Identification& cryptohome_id,
-    const AsyncMethodCallback& callback) {
-  ReturnAsyncMethodResult(callback);
+    AsyncMethodCallback callback) {
+  ReturnAsyncMethodResult(std::move(callback));
 }
 
 void FakeCryptohomeClient::RenameCryptohome(
@@ -167,28 +167,27 @@
     const cryptohome::Identification& cryptohome_id,
     const std::string& key,
     int flags,
-    const AsyncMethodCallback& callback) {
-  ReturnAsyncMethodResult(callback);
+    AsyncMethodCallback callback) {
+  ReturnAsyncMethodResult(std::move(callback));
 }
 
 void FakeCryptohomeClient::AsyncAddKey(
     const cryptohome::Identification& cryptohome_id,
     const std::string& key,
     const std::string& new_key,
-    const AsyncMethodCallback& callback) {
-  ReturnAsyncMethodResult(callback);
+    AsyncMethodCallback callback) {
+  ReturnAsyncMethodResult(std::move(callback));
 }
 
-void FakeCryptohomeClient::AsyncMountGuest(
-    const AsyncMethodCallback& callback) {
-  ReturnAsyncMethodResult(callback);
+void FakeCryptohomeClient::AsyncMountGuest(AsyncMethodCallback callback) {
+  ReturnAsyncMethodResult(std::move(callback));
 }
 
 void FakeCryptohomeClient::AsyncMountPublic(
     const cryptohome::Identification& public_mount_id,
     int flags,
-    const AsyncMethodCallback& callback) {
-  ReturnAsyncMethodResult(callback);
+    AsyncMethodCallback callback) {
+  ReturnAsyncMethodResult(std::move(callback));
 }
 
 void FakeCryptohomeClient::TpmIsReady(DBusMethodCallback<bool> callback) {
@@ -392,15 +391,15 @@
 
 void FakeCryptohomeClient::AsyncTpmAttestationCreateEnrollRequest(
     chromeos::attestation::PrivacyCAType pca_type,
-    const AsyncMethodCallback& callback) {
-  ReturnAsyncMethodData(callback, std::string());
+    AsyncMethodCallback callback) {
+  ReturnAsyncMethodData(std::move(callback), std::string());
 }
 
 void FakeCryptohomeClient::AsyncTpmAttestationEnroll(
     chromeos::attestation::PrivacyCAType pca_type,
     const std::string& pca_response,
-    const AsyncMethodCallback& callback) {
-  ReturnAsyncMethodResult(callback);
+    AsyncMethodCallback callback) {
+  ReturnAsyncMethodResult(std::move(callback));
 }
 
 void FakeCryptohomeClient::AsyncTpmAttestationCreateCertRequest(
@@ -408,8 +407,8 @@
     attestation::AttestationCertificateProfile certificate_profile,
     const cryptohome::Identification& cryptohome_id,
     const std::string& request_origin,
-    const AsyncMethodCallback& callback) {
-  ReturnAsyncMethodData(callback, std::string());
+    AsyncMethodCallback callback) {
+  ReturnAsyncMethodData(std::move(callback), std::string());
 }
 
 void FakeCryptohomeClient::AsyncTpmAttestationFinishCertRequest(
@@ -417,8 +416,8 @@
     attestation::AttestationKeyType key_type,
     const cryptohome::Identification& cryptohome_id,
     const std::string& key_name,
-    const AsyncMethodCallback& callback) {
-  ReturnAsyncMethodData(callback, std::string());
+    AsyncMethodCallback callback) {
+  ReturnAsyncMethodData(std::move(callback), std::string());
 }
 
 void FakeCryptohomeClient::TpmAttestationDoesKeyExist(
@@ -493,8 +492,8 @@
     attestation::AttestationKeyType key_type,
     const cryptohome::Identification& cryptohome_id,
     const std::string& key_name,
-    const AsyncMethodCallback& callback) {
-  ReturnAsyncMethodData(callback, std::string());
+    AsyncMethodCallback callback) {
+  ReturnAsyncMethodData(std::move(callback), std::string());
 }
 
 void FakeCryptohomeClient::TpmAttestationSignEnterpriseChallenge(
@@ -505,8 +504,8 @@
     const std::string& device_id,
     attestation::AttestationChallengeOptions options,
     const std::string& challenge,
-    const AsyncMethodCallback& callback) {
-  ReturnAsyncMethodData(callback, std::string());
+    AsyncMethodCallback callback) {
+  ReturnAsyncMethodData(std::move(callback), std::string());
 }
 
 void FakeCryptohomeClient::TpmAttestationSignSimpleChallenge(
@@ -514,11 +513,11 @@
     const cryptohome::Identification& cryptohome_id,
     const std::string& key_name,
     const std::string& challenge,
-    const AsyncMethodCallback& callback) {
+    AsyncMethodCallback callback) {
   chromeos::attestation::SignedData signed_data;
   signed_data.set_data(challenge + kTwentyBytesNonce);
   signed_data.set_signature(kSignature);
-  ReturnAsyncMethodData(callback, signed_data.SerializeAsString());
+  ReturnAsyncMethodData(std::move(callback), signed_data.SerializeAsString());
 }
 
 void FakeCryptohomeClient::TpmAttestationGetKeyPayload(
@@ -754,41 +753,41 @@
 }
 
 void FakeCryptohomeClient::ReturnAsyncMethodResult(
-    const AsyncMethodCallback& callback) {
+    AsyncMethodCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
-      base::Bind(&FakeCryptohomeClient::ReturnAsyncMethodResultInternal,
-                 weak_ptr_factory_.GetWeakPtr(), callback));
+      base::BindOnce(&FakeCryptohomeClient::ReturnAsyncMethodResultInternal,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
-void FakeCryptohomeClient::ReturnAsyncMethodData(
-    const AsyncMethodCallback& callback,
-    const std::string& data) {
+void FakeCryptohomeClient::ReturnAsyncMethodData(AsyncMethodCallback callback,
+                                                 const std::string& data) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
-      base::Bind(&FakeCryptohomeClient::ReturnAsyncMethodDataInternal,
-                 weak_ptr_factory_.GetWeakPtr(), callback, data));
+      base::BindOnce(&FakeCryptohomeClient::ReturnAsyncMethodDataInternal,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback),
+                     data));
 }
 
 void FakeCryptohomeClient::ReturnAsyncMethodResultInternal(
-    const AsyncMethodCallback& callback) {
-  callback.Run(async_call_id_);
+    AsyncMethodCallback callback) {
+  std::move(callback).Run(async_call_id_);
   if (!async_call_status_handler_.is_null()) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(async_call_status_handler_, async_call_id_, true,
-                              cryptohome::MOUNT_ERROR_NONE));
+        FROM_HERE, base::BindOnce(async_call_status_handler_, async_call_id_,
+                                  true, cryptohome::MOUNT_ERROR_NONE));
   }
   ++async_call_id_;
 }
 
 void FakeCryptohomeClient::ReturnAsyncMethodDataInternal(
-    const AsyncMethodCallback& callback,
+    AsyncMethodCallback callback,
     const std::string& data) {
-  callback.Run(async_call_id_);
+  std::move(callback).Run(async_call_id_);
   if (!async_call_status_data_handler_.is_null()) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(async_call_status_data_handler_, async_call_id_,
-                              true, data));
+        FROM_HERE, base::BindOnce(async_call_status_data_handler_,
+                                  async_call_id_, true, data));
   }
   ++async_call_id_;
 }
diff --git a/chromeos/dbus/fake_cryptohome_client.h b/chromeos/dbus/fake_cryptohome_client.h
index d66ad81c8..c94a254 100644
--- a/chromeos/dbus/fake_cryptohome_client.h
+++ b/chromeos/dbus/fake_cryptohome_client.h
@@ -39,13 +39,13 @@
   void Unmount(DBusMethodCallback<bool> callback) override;
   void AsyncCheckKey(const cryptohome::Identification& cryptohome_id,
                      const std::string& key,
-                     const AsyncMethodCallback& callback) override;
+                     AsyncMethodCallback callback) override;
   void AsyncMigrateKey(const cryptohome::Identification& cryptohome_id,
                        const std::string& from_key,
                        const std::string& to_key,
-                       const AsyncMethodCallback& callback) override;
+                       AsyncMethodCallback callback) override;
   void AsyncRemove(const cryptohome::Identification& cryptohome_id,
-                   const AsyncMethodCallback& callback) override;
+                   AsyncMethodCallback callback) override;
   void RenameCryptohome(const cryptohome::Identification& cryptohome_id_from,
                         const cryptohome::Identification& cryptohome_id_to,
                         const ProtobufMethodCallback& callback) override;
@@ -59,15 +59,15 @@
   void AsyncMount(const cryptohome::Identification& cryptohome_id,
                   const std::string& key,
                   int flags,
-                  const AsyncMethodCallback& callback) override;
+                  AsyncMethodCallback callback) override;
   void AsyncAddKey(const cryptohome::Identification& cryptohome_id,
                    const std::string& key,
                    const std::string& new_key,
-                   const AsyncMethodCallback& callback) override;
-  void AsyncMountGuest(const AsyncMethodCallback& callback) override;
+                   AsyncMethodCallback callback) override;
+  void AsyncMountGuest(AsyncMethodCallback callback) override;
   void AsyncMountPublic(const cryptohome::Identification& public_mount_id,
                         int flags,
-                        const AsyncMethodCallback& callback) override;
+                        AsyncMethodCallback callback) override;
   void TpmIsReady(DBusMethodCallback<bool> callback) override;
   void TpmIsEnabled(DBusMethodCallback<bool> callback) override;
   bool CallTpmIsEnabledAndBlock(bool* enabled) override;
@@ -99,22 +99,22 @@
   void TpmAttestationIsEnrolled(DBusMethodCallback<bool> callback) override;
   void AsyncTpmAttestationCreateEnrollRequest(
       chromeos::attestation::PrivacyCAType pca_type,
-      const AsyncMethodCallback& callback) override;
+      AsyncMethodCallback callback) override;
   void AsyncTpmAttestationEnroll(chromeos::attestation::PrivacyCAType pca_type,
                                  const std::string& pca_response,
-                                 const AsyncMethodCallback& callback) override;
+                                 AsyncMethodCallback callback) override;
   void AsyncTpmAttestationCreateCertRequest(
       chromeos::attestation::PrivacyCAType pca_type,
       attestation::AttestationCertificateProfile certificate_profile,
       const cryptohome::Identification& cryptohome_id,
       const std::string& request_origin,
-      const AsyncMethodCallback& callback) override;
+      AsyncMethodCallback callback) override;
   void AsyncTpmAttestationFinishCertRequest(
       const std::string& pca_response,
       attestation::AttestationKeyType key_type,
       const cryptohome::Identification& cryptohome_id,
       const std::string& key_name,
-      const AsyncMethodCallback& callback) override;
+      AsyncMethodCallback callback) override;
   void TpmAttestationDoesKeyExist(
       attestation::AttestationKeyType key_type,
       const cryptohome::Identification& cryptohome_id,
@@ -134,7 +134,7 @@
       attestation::AttestationKeyType key_type,
       const cryptohome::Identification& cryptohome_id,
       const std::string& key_name,
-      const AsyncMethodCallback& callback) override;
+      AsyncMethodCallback callback) override;
   void TpmAttestationSignEnterpriseChallenge(
       attestation::AttestationKeyType key_type,
       const cryptohome::Identification& cryptohome_id,
@@ -143,13 +143,13 @@
       const std::string& device_id,
       attestation::AttestationChallengeOptions options,
       const std::string& challenge,
-      const AsyncMethodCallback& callback) override;
+      AsyncMethodCallback callback) override;
   void TpmAttestationSignSimpleChallenge(
       attestation::AttestationKeyType key_type,
       const cryptohome::Identification& cryptohome_id,
       const std::string& key_name,
       const std::string& challenge,
-      const AsyncMethodCallback& callback) override;
+      AsyncMethodCallback callback) override;
   void TpmAttestationGetKeyPayload(
       attestation::AttestationKeyType key_type,
       const cryptohome::Identification& cryptohome_id,
@@ -272,17 +272,17 @@
       const ProtobufMethodCallback& callback);
 
   // Posts tasks which return fake results to the UI thread.
-  void ReturnAsyncMethodResult(const AsyncMethodCallback& callback);
+  void ReturnAsyncMethodResult(AsyncMethodCallback callback);
 
   // Posts tasks which return fake data to the UI thread.
-  void ReturnAsyncMethodData(const AsyncMethodCallback& callback,
+  void ReturnAsyncMethodData(AsyncMethodCallback callback,
                              const std::string& data);
 
   // This method is used to implement ReturnAsyncMethodResult without data.
-  void ReturnAsyncMethodResultInternal(const AsyncMethodCallback& callback);
+  void ReturnAsyncMethodResultInternal(AsyncMethodCallback callback);
 
   // This method is used to implement ReturnAsyncMethodResult with data.
-  void ReturnAsyncMethodDataInternal(const AsyncMethodCallback& callback,
+  void ReturnAsyncMethodDataInternal(AsyncMethodCallback callback,
                                      const std::string& data);
 
   // This method is used to implement MigrateToDircrypto with simulated progress
diff --git a/chromeos/dbus/fake_cryptohome_client_unittest.cc b/chromeos/dbus/fake_cryptohome_client_unittest.cc
index a151790..8ddd1d0 100644
--- a/chromeos/dbus/fake_cryptohome_client_unittest.cc
+++ b/chromeos/dbus/fake_cryptohome_client_unittest.cc
@@ -23,9 +23,6 @@
 class FakeCryptohomeClientTest : public ::testing::Test {
  public:
   FakeCryptohomeClientTest() : weak_ptr_factory_(this) {
-    async_method_callback_ =
-        base::Bind(&FakeCryptohomeClientTest::MockHandleAsyncMethodCallback,
-                   weak_ptr_factory_.GetWeakPtr());
     fake_cryptohome_client_.SetAsyncCallStatusHandlers(
         base::Bind(
             &FakeCryptohomeClientTest::MockHandleAsyncMethodResultResponse,
@@ -34,7 +31,6 @@
                    weak_ptr_factory_.GetWeakPtr()));
   }
 
-  MOCK_METHOD1(MockHandleAsyncMethodCallback, void(int));
   MOCK_METHOD3(MockHandleAsyncMethodResultResponse, void(int, bool, int));
   MOCK_METHOD3(MockHandleAsyncMethodDataResponse,
                void(int, bool, const std::string&));
@@ -43,7 +39,6 @@
   base::test::ScopedTaskEnvironment scoped_task_environment_;
 
   FakeCryptohomeClient fake_cryptohome_client_;
-  CryptohomeClient::AsyncMethodCallback async_method_callback_;
 
   base::WeakPtrFactory<FakeCryptohomeClientTest> weak_ptr_factory_;
 
@@ -54,18 +49,20 @@
 TEST_F(FakeCryptohomeClientTest, SignSimpleChallenge) {
   const std::string challenge{"challenge"};
 
-  EXPECT_CALL(*this, MockHandleAsyncMethodCallback(_));
-
   std::string return_data;
   EXPECT_CALL(*this, MockHandleAsyncMethodDataResponse(_, true, _))
       .WillOnce(SaveArg<2>(&return_data));
 
   cryptohome::Identification cryptohome_id;
+  bool called = false;
   fake_cryptohome_client_.TpmAttestationSignSimpleChallenge(
       attestation::AttestationKeyType::KEY_DEVICE, cryptohome_id, "key_name",
-      challenge, async_method_callback_);
-
+      challenge,
+      base::BindOnce(
+          [](bool* called, base::Optional<int> async_id) { *called = true; },
+          &called));
   base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(called);
 
   chromeos::attestation::SignedData signed_data;
   ASSERT_TRUE(signed_data.ParseFromString(return_data));
diff --git a/chromeos/login/auth/user_context.h b/chromeos/login/auth/user_context.h
index 88cb42d..ef5175d 100644
--- a/chromeos/login/auth/user_context.h
+++ b/chromeos/login/auth/user_context.h
@@ -33,8 +33,6 @@
     AUTH_FLOW_OFFLINE,
     // Offline authentication using and Easy unlock device (e.g. a phone).
     AUTH_FLOW_EASY_UNLOCK,
-    // Easy bootstrap flow.
-    AUTH_FLOW_EASY_BOOTSTRAP,
     // Authentication against Active Directory server.
     AUTH_FLOW_ACTIVE_DIRECTORY,
   };
diff --git a/chromeos/printing/printer_configuration.cc b/chromeos/printing/printer_configuration.cc
index 76e1265..359cf284 100644
--- a/chromeos/printing/printer_configuration.cc
+++ b/chromeos/printing/printer_configuration.cc
@@ -8,9 +8,45 @@
 
 #include "base/guid.h"
 #include "base/strings/string_piece.h"
+#include "base/strings/string_util.h"
+#include "net/base/ip_endpoint.h"
+#include "url/url_constants.h"
 
 namespace chromeos {
 
+namespace {
+
+// Returns the index of the first character representing the hostname in |uri|.
+// Returns npos if the start of the hostname is not found.
+//
+// We should use GURL to do this except that uri could start with ipp:// which
+// is not a standard url scheme (according to GURL).
+size_t HostnameStart(base::StringPiece uri) {
+  size_t scheme_separator_start = uri.find(url::kStandardSchemeSeparator);
+  if (scheme_separator_start == base::StringPiece::npos) {
+    return base::StringPiece::npos;
+  }
+  return scheme_separator_start + strlen(url::kStandardSchemeSeparator);
+}
+
+base::StringPiece HostAndPort(base::StringPiece uri) {
+  size_t hostname_start = HostnameStart(uri);
+  if (hostname_start == base::StringPiece::npos) {
+    return "";
+  }
+
+  size_t hostname_end = uri.find("/", hostname_start);
+  if (hostname_end == base::StringPiece::npos) {
+    // No trailing slash.  Use end of string.
+    hostname_end = uri.size();
+  }
+
+  CHECK_GT(hostname_end, hostname_start);
+  return uri.substr(hostname_start, hostname_end - hostname_start);
+}
+
+}  // namespace
+
 Printer::Printer() : source_(SRC_USER_PREFS) {
   id_ = base::GenerateGUID();
 }
@@ -30,6 +66,34 @@
   return ppd_reference_.autoconf;
 }
 
+bool Printer::RequiresIpResolution() const {
+  return effective_uri_.empty() &&
+         base::StartsWith(id_, "zeroconf-", base::CompareCase::SENSITIVE);
+}
+
+net::HostPortPair Printer::GetHostAndPort() const {
+  if (uri_.empty()) {
+    return net::HostPortPair();
+  }
+
+  return net::HostPortPair::FromString(HostAndPort(uri_).as_string());
+}
+
+std::string Printer::ReplaceHostAndPort(const net::IPEndPoint& ip) const {
+  if (uri_.empty()) {
+    return "";
+  }
+
+  size_t hostname_start = HostnameStart(uri_);
+  if (hostname_start == base::StringPiece::npos) {
+    return "";
+  }
+  size_t host_port_len = HostAndPort(uri_).length();
+  return base::JoinString({uri_.substr(0, hostname_start), ip.ToString(),
+                           uri_.substr(hostname_start + host_port_len)},
+                          "");
+}
+
 Printer::PrinterProtocol Printer::GetProtocol() const {
   const base::StringPiece uri(uri_);
 
diff --git a/chromeos/printing/printer_configuration.h b/chromeos/printing/printer_configuration.h
index 270ec01..ad6399f9 100644
--- a/chromeos/printing/printer_configuration.h
+++ b/chromeos/printing/printer_configuration.h
@@ -11,6 +11,11 @@
 #include "base/macros.h"
 #include "base/time/time.h"
 #include "chromeos/chromeos_export.h"
+#include "net/base/host_port_pair.h"
+
+namespace net {
+class IPEndPoint;
+}  // namespace net
 
 namespace chromeos {
 
@@ -126,6 +131,18 @@
   // |uri_|.
   bool IsIppEverywhere() const;
 
+  // Returns true if |effective_uri_| needs to be computed before the pritner
+  // can be installed.
+  bool RequiresIpResolution() const;
+
+  // Returns the hostname and port for |uri_|.  Assumes that the uri is
+  // well formed.  Returns an empty string if |uri_| is not set.
+  net::HostPortPair GetHostAndPort() const;
+
+  // Returns the |uri_| with the host and port replaced with |ip|.  Returns an
+  // empty string if |uri_| is empty.
+  std::string ReplaceHostAndPort(const net::IPEndPoint& ip) const;
+
   // Returns the printer protocol the printer is configured with.
   Printer::PrinterProtocol GetProtocol() const;
 
diff --git a/components/BUILD.gn b/components/BUILD.gn
index fedaff5..1992989 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -5,6 +5,7 @@
 import("//build/config/chrome_build.gni")
 import("//build/config/features.gni")
 import("//build/config/ui.gni")
+import("//components/nacl/features.gni")
 import("//printing/features/features.gni")
 import("//rlz/features/features.gni")
 import("//testing/test.gni")
diff --git a/components/arc/arc_service_manager.cc b/components/arc/arc_service_manager.cc
index b4832063..a529142 100644
--- a/components/arc/arc_service_manager.cc
+++ b/components/arc/arc_service_manager.cc
@@ -5,7 +5,6 @@
 #include "components/arc/arc_service_manager.h"
 
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_session.h"
 #include "components/arc/arc_session_runner.h"
@@ -19,7 +18,7 @@
 }  // namespace
 
 ArcServiceManager::ArcServiceManager()
-    : arc_bridge_service_(base::MakeUnique<ArcBridgeService>()) {
+    : arc_bridge_service_(std::make_unique<ArcBridgeService>()) {
   DCHECK(!g_arc_service_manager);
   g_arc_service_manager = this;
 }
diff --git a/components/arc/arc_session.cc b/components/arc/arc_session.cc
index ef73499f..9a7b6dc 100644
--- a/components/arc/arc_session.cc
+++ b/components/arc/arc_session.cc
@@ -15,7 +15,6 @@
 #include "base/files/file_util.h"
 #include "base/location.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/sys_info.h"
 #include "base/task_scheduler/post_task.h"
@@ -511,7 +510,7 @@
   mojom::ArcBridgeInstancePtr instance;
   instance.Bind(mojo::InterfacePtrInfo<mojom::ArcBridgeInstance>(
       std::move(server_pipe), 0u));
-  arc_bridge_host_ = base::MakeUnique<ArcBridgeHostImpl>(arc_bridge_service_,
+  arc_bridge_host_ = std::make_unique<ArcBridgeHostImpl>(arc_bridge_service_,
                                                          std::move(instance));
 
   VLOG(0) << "ARC ready.";
@@ -699,7 +698,7 @@
 // static
 std::unique_ptr<ArcSession> ArcSession::Create(
     ArcBridgeService* arc_bridge_service) {
-  return base::MakeUnique<ArcSessionImpl>(arc_bridge_service);
+  return std::make_unique<ArcSessionImpl>(arc_bridge_service);
 }
 
 }  // namespace arc
diff --git a/components/arc/arc_session_runner_unittest.cc b/components/arc/arc_session_runner_unittest.cc
index 7e93589..5fb89f8b 100644
--- a/components/arc/arc_session_runner_unittest.cc
+++ b/components/arc/arc_session_runner_unittest.cc
@@ -9,7 +9,6 @@
 #include "base/bind_helpers.h"
 #include "base/callback_helpers.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/test/scoped_task_environment.h"
@@ -45,7 +44,7 @@
 
   void SetUp() override {
     chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        base::MakeUnique<chromeos::FakeSessionManagerClient>());
+        std::make_unique<chromeos::FakeSessionManagerClient>());
     chromeos::DBusThreadManager::Initialize();
 
     stop_reason_ = ArcStopReason::SHUTDOWN;
@@ -55,7 +54,7 @@
 
     // We inject FakeArcSession here so we do not need task_runner.
     arc_session_runner_ =
-        base::MakeUnique<ArcSessionRunner>(base::Bind(FakeArcSession::Create));
+        std::make_unique<ArcSessionRunner>(base::Bind(FakeArcSession::Create));
     arc_session_runner_->AddObserver(this);
   }
 
@@ -89,19 +88,19 @@
   void ResetArcSessionFactory(
       const ArcSessionRunner::ArcSessionFactory& factory) {
     arc_session_runner_->RemoveObserver(this);
-    arc_session_runner_ = base::MakeUnique<ArcSessionRunner>(factory);
+    arc_session_runner_ = std::make_unique<ArcSessionRunner>(factory);
     arc_session_runner_->AddObserver(this);
   }
 
   static std::unique_ptr<ArcSession> CreateSuspendedArcSession() {
-    auto arc_session = base::MakeUnique<FakeArcSession>();
+    auto arc_session = std::make_unique<FakeArcSession>();
     arc_session->SuspendBoot();
     return std::move(arc_session);
   }
 
   static std::unique_ptr<ArcSession> CreateBootFailureArcSession(
       ArcStopReason reason) {
-    auto arc_session = base::MakeUnique<FakeArcSession>();
+    auto arc_session = std::make_unique<FakeArcSession>();
     arc_session->EnableBootFailureEmulation(reason);
     return std::move(arc_session);
   }
diff --git a/components/arc/bitmap/OWNERS b/components/arc/bitmap/OWNERS
index bb65116..ef5cf84 100644
--- a/components/arc/bitmap/OWNERS
+++ b/components/arc/bitmap/OWNERS
@@ -1,2 +1,3 @@
 per-file *_struct_traits*.*=set noparent
 per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *_struct_traits*.*=file://components/arc/common/ARC_SECURITY_OWNERS
diff --git a/components/arc/bluetooth/OWNERS b/components/arc/bluetooth/OWNERS
index 2ec6129..40f6a3e 100644
--- a/components/arc/bluetooth/OWNERS
+++ b/components/arc/bluetooth/OWNERS
@@ -1,4 +1,7 @@
 per-file *_type_converter*.*=set noparent
 per-file *_type_converter*.*=file://ipc/SECURITY_OWNERS
+per-file *_type_converter*.*=file://components/arc/common/ARC_SECURITY_OWNERS
+
 per-file *_struct_traits*.*=set noparent
 per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *_struct_traits*.*=file://components/arc/common/ARC_SECURITY_OWNERS
diff --git a/components/arc/bluetooth/bluetooth_struct_traits.cc b/components/arc/bluetooth/bluetooth_struct_traits.cc
index c09ac04..f778315 100644
--- a/components/arc/bluetooth/bluetooth_struct_traits.cc
+++ b/components/arc/bluetooth/bluetooth_struct_traits.cc
@@ -4,12 +4,12 @@
 
 #include "components/arc/bluetooth/bluetooth_struct_traits.h"
 
+#include <initializer_list>
 #include <map>
 #include <string>
 #include <utility>
 #include <vector>
 
-#include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
@@ -43,7 +43,7 @@
   ~ServiceUUIDEntry() override {}
 
   void AddTo(device::BluetoothAdvertisement::Data* data) override {
-    auto string_uuids = base::MakeUnique<std::vector<std::string>>();
+    auto string_uuids = std::make_unique<std::vector<std::string>>();
     for (const auto& uuid : service_uuids) {
       string_uuids->emplace_back(uuid.value());
     }
@@ -59,9 +59,10 @@
 
   void AddTo(device::BluetoothAdvertisement::Data* data) override {
     std::string string_uuid = base::StringPrintf("%04x", service_uuid);
+    using MapType = std::map<std::string, std::vector<uint8_t>>;
     data->set_service_data(
-        base::WrapUnique(new std::map<std::string, std::vector<uint8_t>>{
-            {string_uuid, service_data}}));
+        std::make_unique<MapType, std::initializer_list<MapType::value_type>>(
+            {{string_uuid, service_data}}));
   }
 };
 
@@ -72,8 +73,10 @@
   ~ManufacturerDataEntry() override {}
 
   void AddTo(device::BluetoothAdvertisement::Data* data) override {
-    data->set_manufacturer_data(base::WrapUnique(
-        new std::map<uint16_t, std::vector<uint8_t>>{{company_id_code, blob}}));
+    using MapType = std::map<uint16_t, std::vector<uint8_t>>;
+    data->set_manufacturer_data(
+        std::make_unique<MapType, std::initializer_list<MapType::value_type>>(
+            {{company_id_code, blob}}));
   }
 };
 
@@ -166,7 +169,7 @@
     switch (data.tag()) {
       case arc::mojom::BluetoothAdvertisingDataDataView::Tag::SERVICE_UUIDS: {
         std::unique_ptr<ServiceUUIDEntry> service_uuids =
-            base::MakeUnique<ServiceUUIDEntry>();
+            std::make_unique<ServiceUUIDEntry>();
         if (!data.ReadServiceUuids(&service_uuids->service_uuids))
           return false;
         *output = std::move(service_uuids);
@@ -174,7 +177,7 @@
       }
       case arc::mojom::BluetoothAdvertisingDataDataView::Tag::SERVICE_DATA: {
         std::unique_ptr<ServiceDataEntry> service_data =
-            base::MakeUnique<ServiceDataEntry>();
+            std::make_unique<ServiceDataEntry>();
         if (!data.ReadServiceData(service_data.get()))
           return false;
         *output = std::move(service_data);
@@ -183,7 +186,7 @@
       case arc::mojom::BluetoothAdvertisingDataDataView::Tag::
           MANUFACTURER_DATA: {
         std::unique_ptr<ManufacturerDataEntry> manufacturer_data =
-            base::MakeUnique<ManufacturerDataEntry>();
+            std::make_unique<ManufacturerDataEntry>();
         // We get manufacturer data as a big blob. The first two bytes
         // should be a company identifier code and the rest is manufacturer-
         // specific.
@@ -207,7 +210,7 @@
         // device::BluetoothAdvertisement::AdvertisementData, so data we
         // don't know how to handle yet will be dropped but won't cause a
         // failure to deserialize.
-        *output = base::MakeUnique<AdvertisementEntry>();
+        *output = std::make_unique<AdvertisementEntry>();
         break;
       }
     }
@@ -223,7 +226,7 @@
   device::BluetoothAdvertisement::AdvertisementType adv_type;
   if (!advertisement.ReadType(&adv_type))
     return false;
-  auto data = base::MakeUnique<device::BluetoothAdvertisement::Data>(adv_type);
+  auto data = std::make_unique<device::BluetoothAdvertisement::Data>(adv_type);
 
   std::vector<std::unique_ptr<AdvertisementEntry>> adv_entries;
   if (!advertisement.ReadData(&adv_entries))
diff --git a/components/arc/bluetooth/bluetooth_type_converters.cc b/components/arc/bluetooth/bluetooth_type_converters.cc
index d614997..0da98fa6 100644
--- a/components/arc/bluetooth/bluetooth_type_converters.cc
+++ b/components/arc/bluetooth/bluetooth_type_converters.cc
@@ -10,7 +10,6 @@
 #include <string>
 #include <vector>
 
-#include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
@@ -125,7 +124,7 @@
 
   switch (result->type) {
     case bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE:
-      result->value.Append(base::MakeUnique<base::Value>());
+      result->value.Append(std::make_unique<base::Value>());
       break;
     case bluez::BluetoothServiceAttributeValueBlueZ::UINT:
     case bluez::BluetoothServiceAttributeValueBlueZ::INT:
@@ -140,7 +139,7 @@
       if (depth + 1 >= arc::kBluetoothSDPMaxDepth) {
         result->type = bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE;
         result->type_size = 0;
-        result->value.Append(base::MakeUnique<base::Value>());
+        result->value.Append(std::make_unique<base::Value>());
         return result;
       }
       for (const auto& child : attr_bluez.sequence()) {
@@ -175,7 +174,7 @@
       if (attr->value.GetSize() != 1) {
         return bluez::BluetoothServiceAttributeValueBlueZ(
             bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE, 0,
-            base::MakeUnique<base::Value>());
+            std::make_unique<base::Value>());
       }
 
       std::unique_ptr<base::Value> value;
@@ -188,10 +187,10 @@
       if (depth + 1 >= arc::kBluetoothSDPMaxDepth || attr->sequence.empty()) {
         return bluez::BluetoothServiceAttributeValueBlueZ(
             bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE, 0,
-            base::MakeUnique<base::Value>());
+            std::make_unique<base::Value>());
       }
 
-      auto bluez_sequence = base::MakeUnique<
+      auto bluez_sequence = std::make_unique<
           bluez::BluetoothServiceAttributeValueBlueZ::Sequence>();
       for (const auto& child : attr->sequence) {
         bluez_sequence->push_back(Convert(child, depth + 1));
@@ -205,7 +204,7 @@
   }
   return bluez::BluetoothServiceAttributeValueBlueZ(
       bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE, 0,
-      base::MakeUnique<base::Value>());
+      std::make_unique<base::Value>());
 }
 
 // static
diff --git a/components/arc/bluetooth/bluetooth_type_converters_unittest.cc b/components/arc/bluetooth/bluetooth_type_converters_unittest.cc
index 45c0106c..ba8f562 100644
--- a/components/arc/bluetooth/bluetooth_type_converters_unittest.cc
+++ b/components/arc/bluetooth/bluetooth_type_converters_unittest.cc
@@ -9,7 +9,6 @@
 #include <string>
 #include <vector>
 
-#include "base/memory/ptr_util.h"
 #include "base/values.h"
 #include "device/bluetooth/bluetooth_gatt_service.h"
 #include "device/bluetooth/bluetooth_uuid.h"
@@ -114,7 +113,7 @@
   nulltypeAttributeMojo->type =
       bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE;
   nulltypeAttributeMojo->type_size = 0;
-  nulltypeAttributeMojo->value.Append(base::MakeUnique<base::Value>());
+  nulltypeAttributeMojo->value.Append(std::make_unique<base::Value>());
 
   auto nulltypeAttributeBlueZ =
       nulltypeAttributeMojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
@@ -287,7 +286,7 @@
   auto sequenceNoData = arc::mojom::BluetoothSdpAttribute::New();
   sequenceNoData->type = bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE;
   sequenceNoData->type_size = 0;
-  sequenceNoData->value.Append(base::MakeUnique<base::Value>());
+  sequenceNoData->value.Append(std::make_unique<base::Value>());
 
   auto sequenceNoDataBlueZ =
       sequenceNoData.To<bluez::BluetoothServiceAttributeValueBlueZ>();
@@ -329,7 +328,7 @@
   int valueUint16AsInt;
   auto uintAttributeBlueZ = bluez::BluetoothServiceAttributeValueBlueZ(
       bluez::BluetoothServiceAttributeValueBlueZ::UINT, sizeof(valueUint16),
-      base::MakeUnique<base::Value>(static_cast<int>(valueUint16)));
+      std::make_unique<base::Value>(static_cast<int>(valueUint16)));
 
   auto uintAttributeMojo =
       ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(uintAttributeBlueZ);
@@ -345,7 +344,7 @@
   bool actualBool = true;
   auto boolAttributeBlueZ = bluez::BluetoothServiceAttributeValueBlueZ(
       bluez::BluetoothServiceAttributeValueBlueZ::BOOL, sizeof(bool),
-      base::MakeUnique<base::Value>(valueBool));
+      std::make_unique<base::Value>(valueBool));
 
   auto boolAttributeMojo =
       ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(boolAttributeBlueZ);
@@ -362,7 +361,7 @@
   std::string actualUUID;
   auto uuidAttributeBlueZ = bluez::BluetoothServiceAttributeValueBlueZ(
       bluez::BluetoothServiceAttributeValueBlueZ::UUID, sizeof(uint16_t),
-      base::MakeUnique<base::Value>(valueUUID));
+      std::make_unique<base::Value>(valueUUID));
 
   auto uuidAttributeMojo =
       ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(uuidAttributeBlueZ);
@@ -379,7 +378,7 @@
   std::string actualString;
   auto stringAttributeBlueZ = bluez::BluetoothServiceAttributeValueBlueZ(
       bluez::BluetoothServiceAttributeValueBlueZ::STRING, valueString.length(),
-      base::MakeUnique<base::Value>(valueString));
+      std::make_unique<base::Value>(valueString));
 
   auto stringAttributeMojo =
       ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(stringAttributeBlueZ);
@@ -400,10 +399,10 @@
       sequence(new bluez::BluetoothServiceAttributeValueBlueZ::Sequence());
   sequence->push_back(bluez::BluetoothServiceAttributeValueBlueZ(
       bluez::BluetoothServiceAttributeValueBlueZ::UUID, sizeof(uint16_t),
-      base::MakeUnique<base::Value>(l2capUUID)));
+      std::make_unique<base::Value>(l2capUUID)));
   sequence->push_back(bluez::BluetoothServiceAttributeValueBlueZ(
       bluez::BluetoothServiceAttributeValueBlueZ::UINT, sizeof(uint16_t),
-      base::MakeUnique<base::Value>(l2capChannel)));
+      std::make_unique<base::Value>(l2capChannel)));
 
   auto sequenceBlueZ =
       bluez::BluetoothServiceAttributeValueBlueZ(std::move(sequence));
diff --git a/components/arc/common/voice_interaction_framework.mojom b/components/arc/common/voice_interaction_framework.mojom
index d1c3201..f40540b 100644
--- a/components/arc/common/voice_interaction_framework.mojom
+++ b/components/arc/common/voice_interaction_framework.mojom
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// Next MinVersion: 12
+// Next MinVersion: 13
 
 module arc.mojom;
 
@@ -53,7 +53,8 @@
 };
 
 // Connects with Android system server.
-// Next method ID: 10
+// Next method ID: 11
+// Deprecated method ID: 4
 interface VoiceInteractionFrameworkInstance {
   Init@0(VoiceInteractionFrameworkHost host_ptr);
 
@@ -72,8 +73,8 @@
   // Shows/hides the metalayer in the container.
   [MinVersion=1] SetMetalayerVisibility@3([MinVersion=2] bool visible);
 
-  // Turns on / off voice interaction in container.
-  [MinVersion=4] SetVoiceInteractionEnabled@4(bool enable);
+  // Turns on / off voice interaction and ack the setting.
+  [MinVersion=12] SetVoiceInteractionEnabled@10(bool enable) => ();
 
   // Turns on / off context for voice interaction in container. This function
   // controls whether screenshot and view hierarchy information should be sent
diff --git a/components/arc/file_system/OWNERS b/components/arc/file_system/OWNERS
index bb65116..ef5cf84 100644
--- a/components/arc/file_system/OWNERS
+++ b/components/arc/file_system/OWNERS
@@ -1,2 +1,3 @@
 per-file *_struct_traits*.*=set noparent
 per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *_struct_traits*.*=file://components/arc/common/ARC_SECURITY_OWNERS
diff --git a/components/arc/ime/OWNERS b/components/arc/ime/OWNERS
index bb65116..ef5cf84 100644
--- a/components/arc/ime/OWNERS
+++ b/components/arc/ime/OWNERS
@@ -1,2 +1,3 @@
 per-file *_struct_traits*.*=set noparent
 per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *_struct_traits*.*=file://components/arc/common/ARC_SECURITY_OWNERS
diff --git a/components/arc/ime/arc_ime_service_unittest.cc b/components/arc/ime/arc_ime_service_unittest.cc
index 5a35fe79..a5acb8e 100644
--- a/components/arc/ime/arc_ime_service_unittest.cc
+++ b/components/arc/ime/arc_ime_service_unittest.cc
@@ -145,13 +145,13 @@
 
  private:
   void SetUp() override {
-    arc_bridge_service_ = base::MakeUnique<ArcBridgeService>();
+    arc_bridge_service_ = std::make_unique<ArcBridgeService>();
     instance_ =
-        base::MakeUnique<ArcImeService>(nullptr, arc_bridge_service_.get());
+        std::make_unique<ArcImeService>(nullptr, arc_bridge_service_.get());
     fake_arc_ime_bridge_ = new FakeArcImeBridge();
     instance_->SetImeBridgeForTesting(base::WrapUnique(fake_arc_ime_bridge_));
 
-    fake_input_method_ = base::MakeUnique<FakeInputMethod>();
+    fake_input_method_ = std::make_unique<FakeInputMethod>();
     instance_->SetInputMethodForTesting(fake_input_method_.get());
 
     fake_window_delegate_ = new FakeArcWindowDelegate();
diff --git a/components/arc/intent_helper/OWNERS b/components/arc/intent_helper/OWNERS
index bb65116..ef5cf84 100644
--- a/components/arc/intent_helper/OWNERS
+++ b/components/arc/intent_helper/OWNERS
@@ -1,2 +1,3 @@
 per-file *_struct_traits*.*=set noparent
 per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *_struct_traits*.*=file://components/arc/common/ARC_SECURITY_OWNERS
diff --git a/components/arc/intent_helper/activity_icon_loader.cc b/components/arc/intent_helper/activity_icon_loader.cc
index 54c431864..fa2502d 100644
--- a/components/arc/intent_helper/activity_icon_loader.cc
+++ b/components/arc/intent_helper/activity_icon_loader.cc
@@ -11,13 +11,13 @@
 
 #include "base/base64.h"
 #include "base/bind.h"
-#include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/task_scheduler/post_task.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service_manager.h"
 #include "components/arc/arc_util.h"
 #include "ui/base/layout.h"
+#include "ui/gfx/codec/png_codec.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/image/image_skia_operations.h"
 
@@ -79,9 +79,28 @@
   return instance;
 }
 
+// Encodes the |image| as PNG data considering scale factor, and returns it as
+// data: URL.
+scoped_refptr<base::RefCountedData<GURL>> GeneratePNGDataUrl(
+    const gfx::ImageSkia& image,
+    ui::ScaleFactor scale_factor) {
+  float scale = ui::GetScaleForScaleFactor(scale_factor);
+  std::vector<unsigned char> output;
+  gfx::PNGCodec::EncodeBGRASkBitmap(image.GetRepresentation(scale).sk_bitmap(),
+                                    false /* discard_transparency */, &output);
+  std::string encoded;
+  base::Base64Encode(
+      base::StringPiece(reinterpret_cast<const char*>(output.data()),
+                        output.size()),
+      &encoded);
+  return base::WrapRefCounted(
+      new base::RefCountedData<GURL>(GURL(kPngDataUrlPrefix + encoded)));
+}
+
 std::unique_ptr<ActivityIconLoader::ActivityToIconsMap> ResizeAndEncodeIcons(
-    std::vector<mojom::ActivityIconPtr> icons) {
-  auto result = base::MakeUnique<ActivityIconLoader::ActivityToIconsMap>();
+    std::vector<mojom::ActivityIconPtr> icons,
+    ui::ScaleFactor scale_factor) {
+  auto result = std::make_unique<ActivityIconLoader::ActivityToIconsMap>();
   for (size_t i = 0; i < icons.size(); ++i) {
     static const size_t kBytesPerPixel = 4;
     const mojom::ActivityIconPtr& icon = icons.at(i);
@@ -110,23 +129,14 @@
     gfx::Image icon16(icon_small);
     gfx::Image icon20(icon_large);
 
-    // Encode the icon as PNG data, and then as data: URL.
-    scoped_refptr<base::RefCountedMemory> img = icon16.As1xPNGBytes();
-    if (!img)
-      continue;
-    std::string encoded;
-    base::Base64Encode(base::StringPiece(img->front_as<char>(), img->size()),
-                       &encoded);
-    scoped_refptr<base::RefCountedData<GURL>> dataurl(
-        new base::RefCountedData<GURL>(GURL(kPngDataUrlPrefix + encoded)));
-
     const std::string activity_name = icon->activity->activity_name.has_value()
                                           ? (*icon->activity->activity_name)
                                           : std::string();
-    result->insert(
-        std::make_pair(ActivityIconLoader::ActivityName(
-                           icon->activity->package_name, activity_name),
-                       ActivityIconLoader::Icons(icon16, icon20, dataurl)));
+    result->insert(std::make_pair(
+        ActivityIconLoader::ActivityName(icon->activity->package_name,
+                                         activity_name),
+        ActivityIconLoader::Icons(
+            icon16, icon20, GeneratePNGDataUrl(icon_small, scale_factor))));
   }
 
   return result;
@@ -214,7 +224,7 @@
 void ActivityIconLoader::OnIconsResizedForTesting(
     const OnIconsReadyCallback& cb,
     std::unique_ptr<ActivityToIconsMap> result) {
-  OnIconsResized(base::MakeUnique<ActivityToIconsMap>(), cb, std::move(result));
+  OnIconsResized(std::make_unique<ActivityToIconsMap>(), cb, std::move(result));
 }
 
 void ActivityIconLoader::AddCacheEntryForTesting(const ActivityName& activity) {
@@ -241,7 +251,8 @@
     std::vector<mojom::ActivityIconPtr> icons) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   base::PostTaskAndReplyWithResult(
-      FROM_HERE, base::Bind(&ResizeAndEncodeIcons, base::Passed(&icons)),
+      FROM_HERE,
+      base::Bind(&ResizeAndEncodeIcons, base::Passed(&icons), scale_factor_),
       base::Bind(&ActivityIconLoader::OnIconsResized,
                  weak_ptr_factory_.GetWeakPtr(), base::Passed(&cached_result),
                  cb));
diff --git a/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc b/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc
index 5fdf49a..0964fe9 100644
--- a/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc
+++ b/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc
@@ -4,9 +4,9 @@
 
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
 
+#include <memory>
 #include <utility>
 
-#include "base/memory/ptr_util.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/common/intent_helper.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -32,8 +32,8 @@
 
  private:
   void SetUp() override {
-    arc_bridge_service_ = base::MakeUnique<ArcBridgeService>();
-    instance_ = base::MakeUnique<ArcIntentHelperBridge>(
+    arc_bridge_service_ = std::make_unique<ArcBridgeService>();
+    instance_ = std::make_unique<ArcIntentHelperBridge>(
         nullptr /* context */, arc_bridge_service_.get());
   }
 
@@ -151,7 +151,7 @@
   };
 
   // Observer should be called when intent filter is updated.
-  auto observer = base::MakeUnique<FakeObserver>();
+  auto observer = std::make_unique<FakeObserver>();
   instance_->AddObserver(observer.get());
   EXPECT_FALSE(observer->IsUpdated());
   instance_->OnIntentFiltersUpdated(std::vector<IntentFilter>());
diff --git a/components/arc/test/fake_app_instance.cc b/components/arc/test/fake_app_instance.cc
index db8a8597..ac44769 100644
--- a/components/arc/test/fake_app_instance.cc
+++ b/components/arc/test/fake_app_instance.cc
@@ -12,7 +12,6 @@
 
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
-#include "base/memory/ptr_util.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
@@ -63,14 +62,14 @@
 void FakeAppInstance::LaunchApp(const std::string& package_name,
                                 const std::string& activity,
                                 int64_t display_id) {
-  launch_requests_.push_back(base::MakeUnique<Request>(package_name, activity));
+  launch_requests_.push_back(std::make_unique<Request>(package_name, activity));
 }
 
 void FakeAppInstance::RequestAppIcon(const std::string& package_name,
                                      const std::string& activity,
                                      mojom::ScaleFactor scale_factor) {
   icon_requests_.push_back(
-      base::MakeUnique<IconRequest>(package_name, activity, scale_factor));
+      std::make_unique<IconRequest>(package_name, activity, scale_factor));
 }
 
 void FakeAppInstance::SendRefreshAppList(
@@ -352,7 +351,7 @@
                                   arc::mojom::ScaleFactor scale_factor,
                                   RequestIconCallback callback) {
   shortcut_icon_requests_.push_back(
-      base::MakeUnique<ShortcutIconRequest>(icon_resource_id, scale_factor));
+      std::make_unique<ShortcutIconRequest>(icon_resource_id, scale_factor));
 
   std::string png_data_as_string;
   if (GetFakeIcon(scale_factor, &png_data_as_string)) {
diff --git a/components/arc/test/fake_arc_session.cc b/components/arc/test/fake_arc_session.cc
index 4ee5854..1e58c1f 100644
--- a/components/arc/test/fake_arc_session.cc
+++ b/components/arc/test/fake_arc_session.cc
@@ -78,7 +78,7 @@
 
 // static
 std::unique_ptr<ArcSession> FakeArcSession::Create() {
-  return base::MakeUnique<FakeArcSession>();
+  return std::make_unique<FakeArcSession>();
 }
 
 }  // namespace arc
diff --git a/components/arc/test/fake_bluetooth_instance.cc b/components/arc/test/fake_bluetooth_instance.cc
index cca29c94..a9e1cd7 100644
--- a/components/arc/test/fake_bluetooth_instance.cc
+++ b/components/arc/test/fake_bluetooth_instance.cc
@@ -4,7 +4,6 @@
 
 #include <utility>
 
-#include "base/memory/ptr_util.h"
 #include "components/arc/test/fake_bluetooth_instance.h"
 
 namespace arc {
@@ -60,7 +59,7 @@
     mojom::BluetoothAddressPtr addr,
     int32_t rssi,
     std::vector<mojom::BluetoothAdvertisingDataPtr> adv_data) {
-  le_device_found_data_.push_back(base::MakeUnique<LEDeviceFoundData>(
+  le_device_found_data_.push_back(std::make_unique<LEDeviceFoundData>(
       std::move(addr), rssi, std::move(adv_data)));
 }
 
@@ -80,7 +79,7 @@
     mojom::BluetoothAddressPtr remote_addr,
     std::vector<mojom::BluetoothGattDBElementPtr> db) {
   gatt_db_result_.push_back(
-      base::MakeUnique<GattDBResult>(std::move(remote_addr), std::move(db)));
+      std::make_unique<GattDBResult>(std::move(remote_addr), std::move(db)));
 }
 
 void FakeBluetoothInstance::OnServicesRemoved(
diff --git a/components/arc/test/fake_voice_interaction_framework_instance.cc b/components/arc/test/fake_voice_interaction_framework_instance.cc
index 45f48bf8..a3016f16 100644
--- a/components/arc/test/fake_voice_interaction_framework_instance.cc
+++ b/components/arc/test/fake_voice_interaction_framework_instance.cc
@@ -32,7 +32,10 @@
     bool visible) {}
 
 void FakeVoiceInteractionFrameworkInstance::SetVoiceInteractionEnabled(
-    bool enable) {}
+    bool enable,
+    SetVoiceInteractionEnabledCallback callback) {
+  std::move(callback).Run();
+}
 
 void FakeVoiceInteractionFrameworkInstance::SetVoiceInteractionContextEnabled(
     bool enable) {}
diff --git a/components/arc/test/fake_voice_interaction_framework_instance.h b/components/arc/test/fake_voice_interaction_framework_instance.h
index c31a522..39167bb48 100644
--- a/components/arc/test/fake_voice_interaction_framework_instance.h
+++ b/components/arc/test/fake_voice_interaction_framework_instance.h
@@ -23,7 +23,9 @@
   void ToggleVoiceInteractionSession(bool homescreen_is_active) override;
   void StartVoiceInteractionSessionForRegion(const gfx::Rect& region) override;
   void SetMetalayerVisibility(bool visible) override;
-  void SetVoiceInteractionEnabled(bool enable) override;
+  void SetVoiceInteractionEnabled(
+      bool enable,
+      SetVoiceInteractionEnabledCallback callback) override;
   void SetVoiceInteractionContextEnabled(bool enable) override;
   void StartVoiceInteractionSetupWizard() override;
   void ShowVoiceInteractionSettings() override;
diff --git a/components/arc/video_accelerator/OWNERS b/components/arc/video_accelerator/OWNERS
index bb65116..ef5cf84 100644
--- a/components/arc/video_accelerator/OWNERS
+++ b/components/arc/video_accelerator/OWNERS
@@ -1,2 +1,3 @@
 per-file *_struct_traits*.*=set noparent
 per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *_struct_traits*.*=file://components/arc/common/ARC_SECURITY_OWNERS
diff --git a/components/arc/voice_interaction/OWNERS b/components/arc/voice_interaction/OWNERS
index bb65116..ef5cf84 100644
--- a/components/arc/voice_interaction/OWNERS
+++ b/components/arc/voice_interaction/OWNERS
@@ -1,2 +1,3 @@
 per-file *_struct_traits*.*=set noparent
 per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *_struct_traits*.*=file://components/arc/common/ARC_SECURITY_OWNERS
diff --git a/components/autofill/content/renderer/BUILD.gn b/components/autofill/content/renderer/BUILD.gn
index 431e75e..8231879 100644
--- a/components/autofill/content/renderer/BUILD.gn
+++ b/components/autofill/content/renderer/BUILD.gn
@@ -17,6 +17,8 @@
     "page_click_listener.h",
     "page_click_tracker.cc",
     "page_click_tracker.h",
+    "page_passwords_analyser.cc",
+    "page_passwords_analyser.h",
     "password_autofill_agent.cc",
     "password_autofill_agent.h",
     "password_form_conversion_utils.cc",
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc
index bf662aa..31d27cb 100644
--- a/components/autofill/content/renderer/form_autofill_util.cc
+++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -261,16 +261,6 @@
   return node_text;
 }
 
-// Returns the aggregated values of the descendants of |element| that are
-// non-empty text nodes.  This is a faster alternative to |innerText()| for
-// performance critical operations.  It does a full depth-first search so can be
-// used when the structure is not directly known.  However, unlike with
-// |innerText()|, the search depth and breadth are limited to a fixed threshold.
-// Whitespace is trimmed from text accumulated at descendant nodes.
-base::string16 FindChildText(const WebNode& node) {
-  return FindChildTextWithIgnoreList(node, std::set<WebNode>());
-}
-
 // Shared function for InferLabelFromPrevious() and InferLabelFromNext().
 base::string16 InferLabelFromSibling(const WebFormControlElement& element,
                                      bool forward) {
@@ -1808,5 +1798,9 @@
   input_element->SetSelectionRange(selection_start, suggestion.length());
 }
 
+base::string16 FindChildText(const WebNode& node) {
+  return FindChildTextWithIgnoreList(node, std::set<WebNode>());
+}
+
 }  // namespace form_util
 }  // namespace autofill
diff --git a/components/autofill/content/renderer/form_autofill_util.h b/components/autofill/content/renderer/form_autofill_util.h
index eac0abc..38378c3 100644
--- a/components/autofill/content/renderer/form_autofill_util.h
+++ b/components/autofill/content/renderer/form_autofill_util.h
@@ -270,6 +270,14 @@
                        const base::string16& user_input,
                        blink::WebFormControlElement* input_element);
 
+// Returns the aggregated values of the descendants of |element| that are
+// non-empty text nodes.  This is a faster alternative to |innerText()| for
+// performance critical operations.  It does a full depth-first search so can be
+// used when the structure is not directly known.  However, unlike with
+// |innerText()|, the search depth and breadth are limited to a fixed threshold.
+// Whitespace is trimmed from text accumulated at descendant nodes.
+base::string16 FindChildText(const blink::WebNode& node);
+
 }  // namespace form_util
 }  // namespace autofill
 
diff --git a/components/autofill/content/renderer/page_passwords_analyser.cc b/components/autofill/content/renderer/page_passwords_analyser.cc
new file mode 100644
index 0000000..9801dc1
--- /dev/null
+++ b/components/autofill/content/renderer/page_passwords_analyser.cc
@@ -0,0 +1,466 @@
+// 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/autofill/content/renderer/page_passwords_analyser.h"
+
+#include <stack>
+
+#include "base/lazy_instance.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/content/renderer/form_autofill_util.h"
+#include "components/autofill/content/renderer/password_form_conversion_utils.h"
+#include "third_party/WebKit/public/web/WebConsoleMessage.h"
+#include "third_party/WebKit/public/web/WebDocument.h"
+#include "third_party/WebKit/public/web/WebElement.h"
+#include "third_party/WebKit/public/web/WebElementCollection.h"
+#include "third_party/WebKit/public/web/WebFormControlElement.h"
+#include "third_party/WebKit/public/web/WebLabelElement.h"
+#include "third_party/WebKit/public/web/WebNode.h"
+#include "third_party/re2/src/re2/re2.h"
+
+namespace autofill {
+
+namespace {
+
+const char* kTypeAttributes[] = {"text", "email", "tel", "password"};
+const char* kTypeTextAttributes[] = {"text", "email", "tel"};
+
+using ConsoleLevel = blink::WebConsoleMessage::Level;
+
+// ConsoleLogger provides a convenient interface for logging messages to the
+// DevTools console, both in terms of wrapping and formatting console messages
+// along with their parameters, and in ordering messages so that higher-priority
+// warnings are displayed first.
+class ConsoleLogger {
+ public:
+  static const ConsoleLevel kError = blink::WebConsoleMessage::kLevelError;
+  static const ConsoleLevel kWarning = blink::WebConsoleMessage::kLevelWarning;
+  static const ConsoleLevel kVerbose = blink::WebConsoleMessage::kLevelVerbose;
+
+  ConsoleLogger(blink::WebLocalFrame* frame) : frame_(frame) {}
+
+  void Send(const std::string& message,
+            ConsoleLevel level,
+            const blink::WebNode& node) {
+    Send(message, level, std::vector<blink::WebNode>{node});
+  }
+
+  void Send(const std::string& message,
+            ConsoleLevel level,
+            const std::vector<blink::WebNode>& nodes) {
+    node_buffer_[level].push_back(Entry{message, nodes});
+  }
+
+  void Flush() {
+    for (ConsoleLevel level : {kError, kWarning, kVerbose}) {
+      for (Entry& entry : node_buffer_[level]) {
+        std::string parameter_string;
+        for (unsigned i = 0; i < entry.nodes.size(); ++i)
+          parameter_string += "%o";
+        frame_->AddMessageToConsole(blink::WebConsoleMessage(
+            level,
+            blink::WebString::FromUTF8("[DOM] " + entry.message +
+                                       parameter_string),
+            std::move(entry.nodes)));
+      }
+    }
+    node_buffer_.clear();
+  }
+
+ private:
+  struct Entry {
+    const std::string message;
+    const std::vector<blink::WebNode> nodes;
+  };
+
+  blink::WebLocalFrame* frame_;
+  // Though ConsoleLogger provides buffering, it is intended to be simply over
+  // the course of a single analysis, for ordering purposes.
+  std::map<ConsoleLevel, std::vector<Entry>> node_buffer_;
+};
+
+// A simple wrapper that provides some extra data about nodes
+// during the DOM traversal (e.g. whether it lies within a <form>
+// element, which is necessary for some of the warnings).
+struct TraversalInfo {
+  const blink::WebNode node;
+  const bool in_form;
+};
+
+// Collects the important elements in a form that are
+// relevant to the Password Manager, which consists of the text and password
+// inputs in a form, as well as their ordering.
+struct FormInputCollection {
+  blink::WebFormElement form;
+  std::vector<blink::WebFormControlElement> inputs;
+  std::vector<size_t> text_inputs;
+  std::vector<size_t> password_inputs;
+  std::string signature;
+
+  // The signature of a form is a string of 'T's and 'P's, representing
+  // username and password fields respectively. This is used to quickly match
+  // against well-known <input> patterns to guess what kind of form we are
+  // dealing with, and provide intelligent autocomplete suggestions.
+  void AddInput(const blink::WebFormControlElement& input) {
+    std::string type(
+        input.HasAttribute("type") ? input.GetAttribute("type").Utf8() : "");
+    signature += type != "password" ? 'T' : 'P';
+    if (type != "password")
+      text_inputs.push_back(inputs.size());
+    else
+      password_inputs.push_back(inputs.size());
+    inputs.push_back(input);
+  }
+};
+
+#define DECLARE_LAZY_MATCHER(NAME, PATTERN)                                   \
+  struct LabelPatternLazyInstanceTraits_##NAME                                \
+      : public base::internal::DestructorAtExitLazyInstanceTraits<re2::RE2> { \
+    static re2::RE2* New(void* instance) {                                    \
+      return CreateMatcher(instance, PATTERN);                                \
+    }                                                                         \
+  };                                                                          \
+  base::LazyInstance<re2::RE2, LabelPatternLazyInstanceTraits_##NAME> NAME =  \
+      LAZY_INSTANCE_INITIALIZER;
+
+DECLARE_LAZY_MATCHER(ignored_characters_matcher, R"(\W)");
+DECLARE_LAZY_MATCHER(username_matcher, R"(user(name)?|login)");
+DECLARE_LAZY_MATCHER(email_matcher, R"(email(address)?)");
+DECLARE_LAZY_MATCHER(telephone_matcher, R"((mobile)?(telephone)?(number|no))");
+
+#undef DECLARE_LAZY_MATCHER
+
+// Represents a common <label> content text-pattern that indicates
+// something of the purpose of an element (for example: that it is a username
+// field).
+struct InputHint {
+  const re2::RE2* regex;
+  std::string tokens;
+  size_t match;
+
+  InputHint(const re2::RE2* regex) : regex(regex), match(std::string::npos) {}
+
+  InputHint(const re2::RE2* regex, const std::string tokens)
+      : InputHint(regex) {
+    this->tokens = " " + tokens;
+  }
+
+  void MatchLabel(std::string& label_content, size_t index) {
+    if (re2::RE2::FullMatch(label_content, *regex))
+      match = index;
+  }
+};
+
+// Multiple semantic forms may be contained within a single <form> element,
+// which causes confusion to the Password Manager, which acts under the
+// assumption each <form> element corresponds to a single form.
+// |FormIsTooComplex| uses a simple heuristic to guess whether a form may
+// contain too many inputs to be considered a single form.
+bool FormIsTooComplex(const std::string& signature) {
+  unsigned kind_changes = 0;
+  unsigned password_count = 0;
+  for (const char kind : signature) {
+    if (kind == (kind_changes & 1 ? 'T' : 'P'))
+      ++kind_changes;
+    password_count += kind == 'P';
+  }
+  return kind_changes >= 3 || password_count > 3;
+}
+
+// Stores an element's id in |ids| for duplicity-checking.
+void TrackElementId(
+    const blink::WebElement& element,
+    std::map<std::string, std::vector<blink::WebNode>>* nodes_for_id) {
+  if (element.HasAttribute("id")) {
+    std::string id_attr = element.GetAttribute("id").Utf8();
+    (*nodes_for_id)[id_attr].push_back(element);
+  }
+}
+
+// We don't want to re-analyse the same nodes each time the method is
+// called. This technically means some warnings might be overlooked (for
+// example if an invalid attribute is added), but these cases are assumed
+// to be rare, and are ignored for the sake of simplicity.
+// The id of |node| will additionally be added to the corresponding |ids| set.
+bool TrackElementIfUntracked(
+    const blink::WebElement& node,
+    std::set<blink::WebNode>* skip_nodes,
+    std::map<std::string, std::vector<blink::WebNode>>* nodes_for_id) {
+  if (skip_nodes->count(node))
+    return true;
+  skip_nodes->insert(node);
+  // If we don't skip the node, we want to make sure its id is tracked.
+  TrackElementId(node, nodes_for_id);
+  return false;
+}
+
+// Error and warning messages regarding the DOM structure: missing <form> tags,
+// duplicate ids, etc. Returns a list of the forms found in the DOM for further
+// analysis.
+std::vector<FormInputCollection> ExtractFormsForAnalysis(
+    const blink::WebDocument& document,
+    std::set<blink::WebNode>* skip_nodes,
+    ConsoleLogger* console_logger) {
+  std::vector<FormInputCollection> form_input_collections;
+
+  // Keep track of inputs that are inside <form> elements to find the complement
+  // for warnings afterwards.
+  std::set<blink::WebFormControlElement> inputs_with_forms;
+  std::map<std::string, std::vector<blink::WebNode>> nodes_for_id;
+
+  blink::WebVector<blink::WebFormElement> forms;
+  document.Forms(forms);
+  for (const blink::WebFormElement& form : forms) {
+    form_input_collections.push_back(FormInputCollection{form});
+    // Collect all the inputs in the form.
+    blink::WebVector<blink::WebFormControlElement> form_control_elements;
+    form.GetFormControlElements(form_control_elements);
+    for (const blink::WebFormControlElement& input : form_control_elements) {
+      if (TrackElementIfUntracked(input, skip_nodes, &nodes_for_id))
+        continue;
+      // We are only interested in a subset of input elements -- those likely
+      // to be username or password fields.
+      if (input.TagName() == "INPUT" &&
+          (!input.HasAttribute("type") ||
+           std::find(std::begin(kTypeAttributes), std::end(kTypeAttributes),
+                     input.GetAttribute("type").Utf8()) !=
+               std::end(kTypeAttributes))) {
+        form_input_collections.back().AddInput(input);
+        inputs_with_forms.insert(input);
+      }
+    }
+
+    TrackElementIfUntracked(form, skip_nodes, &nodes_for_id);
+  }
+
+  // Check for password fields that are not contained inside forms.
+  auto password_inputs = document.QuerySelectorAll("input[type=\"password\"]");
+  for (unsigned i = 0; i < password_inputs.size(); ++i) {
+    if (TrackElementIfUntracked(password_inputs[i], skip_nodes, &nodes_for_id))
+      continue;
+    // Any password fields inside <form> elements will have been skipped,
+    // leaving just those without associated forms.
+    console_logger->Send("Password field is not contained in a form:",
+                         ConsoleLogger::kVerbose, password_inputs[i]);
+  }
+  // Check for input fields that are not contained inside forms, to make sure
+  // their id attributes don't conflict with other fields also not contained
+  // inside forms.
+  std::string selector = "input:not([type])";
+  for (const char* text_type : kTypeTextAttributes)
+    selector += ", input[type=\"" + std::string(text_type) + "\"]";
+  auto text_inputs =
+      document.QuerySelectorAll(blink::WebString::FromUTF8(selector));
+  for (const blink::WebElement& text_input : text_inputs)
+    TrackElementIfUntracked(text_input, skip_nodes, &nodes_for_id);
+
+  // Warn against elements sharing an id attribute. Duplicate id attributes both
+  // are against the HTML specification and can cause issues with password
+  // saving/filling, as the Password Manager makes the assumption that ids may
+  // be used as a unique identifier for nodes.
+  for (const auto& pair : nodes_for_id) {
+    const std::string& id_attr = pair.first;
+    const std::vector<blink::WebNode>& nodes = pair.second;
+    if (nodes.size() <= 1)
+      continue;
+    if (!id_attr.empty()) {
+      console_logger->Send(
+          base::StringPrintf("Found %zu elements with non-unique id #%s:",
+                             nodes.size(), id_attr.c_str()),
+          ConsoleLogger::kError, nodes);
+    } else {
+      console_logger->Send("The id attribute must be unique and non-empty:",
+                           ConsoleLogger::kError, nodes);
+    }
+  }
+
+  return form_input_collections;
+}
+
+// The username field is the most difficult field to identify, as there
+// are often many other textual fields in a form, and it is not always
+// possible to work out which one is the username. Here, we find any
+// <label> elements pointing to the input fields, and check their content.
+// Labels containing text such as "Username:" or "Email address:" are
+// likely to indicate the desired field, and will be prioritised over
+// other fields.
+void InferUsernameField(
+    const blink::WebFormElement& form,
+    const std::vector<blink::WebFormControlElement>& inputs,
+    size_t username_field_guess,
+    std::map<size_t, std::string>* autocomplete_suggestions) {
+  blink::WebElementCollection labels(form.GetElementsByHTMLTagName("label"));
+  DCHECK(!labels.IsNull());
+
+  std::vector<InputHint> input_hints;
+  std::string username_field_guess_tokens;
+
+  input_hints.push_back(InputHint(username_matcher.Pointer()));
+  input_hints.push_back(InputHint(email_matcher.Pointer(), "email"));
+  input_hints.push_back(InputHint(telephone_matcher.Pointer(), "tel"));
+
+  for (blink::WebElement item = labels.FirstItem(); !item.IsNull();
+       item = labels.NextItem()) {
+    blink::WebLabelElement label(item.To<blink::WebLabelElement>());
+    blink::WebElement control(label.CorrespondingControl());
+    if (!control.IsNull() && control.IsFormControlElement()) {
+      blink::WebFormControlElement form_control(
+          control.To<blink::WebFormControlElement>());
+      auto found = std::find(inputs.begin(), inputs.end(), form_control);
+      if (found != inputs.end()) {
+        std::string label_content(
+            base::UTF16ToUTF8(form_util::FindChildText(label)));
+        // Reduce to plain-text, as labels often contain extra punctuation.
+        re2::RE2::GlobalReplace(&label_content,
+                                ignored_characters_matcher.Get(), "");
+        for (InputHint& input_hint : input_hints)
+          input_hint.MatchLabel(label_content, found - inputs.begin());
+      }
+    }
+  }
+
+  for (InputHint& input_hint : input_hints) {
+    if (input_hint.match != std::string::npos) {
+      username_field_guess = input_hint.match;
+      username_field_guess_tokens = input_hint.tokens;
+      break;
+    }
+  }
+
+  (*autocomplete_suggestions)[username_field_guess] =
+      "username" + username_field_guess_tokens;
+}
+
+// Infer what kind of form a form corresponds to (e.g. a
+// registration, log-in or password reset form), based on the structure of
+// the form.
+void GuessAutocompleteAttributesForPasswordFields(
+    const std::vector<size_t>& password_inputs,
+    bool has_text_field,
+    std::map<size_t, std::string>* autocomplete_suggestions) {
+  size_t password_count = password_inputs.size();
+  switch (password_count) {
+    case 3:
+      (*autocomplete_suggestions)[password_inputs[0]] = "current-password";
+    // Fall-through here to match the last two password fields.
+    case 2:
+      (*autocomplete_suggestions)[password_inputs[password_count - 2]] =
+          "new-password";
+      (*autocomplete_suggestions)[password_inputs[password_count - 1]] =
+          "new-password";
+      break;
+    case 1:
+      (*autocomplete_suggestions)[password_inputs[password_count - 1]] =
+          has_text_field ? "current-password" : "new-password";
+      break;
+  }
+}
+
+// Error and warning messages specific to an individual form (for example,
+// autocomplete attributes, or missing username fields, etc.).
+void AnalyseForm(const FormInputCollection& form_input_collection,
+                 ConsoleLogger* console_logger) {
+  const blink::WebFormElement& form = form_input_collection.form;
+  const std::vector<blink::WebFormControlElement>& inputs =
+      form_input_collection.inputs;
+  const std::vector<size_t>& text_inputs = form_input_collection.text_inputs;
+  const std::vector<size_t>& password_inputs =
+      form_input_collection.password_inputs;
+  const std::string& signature = form_input_collection.signature;
+
+  // We're only interested in forms that contain password fields.
+  if (password_inputs.empty())
+    return;
+
+  // If a username field is not first, or if there is no username field,
+  // flag it as an issue.
+  bool has_text_field = !text_inputs.empty();
+  size_t username_field_guess =
+      0;  // Give it a default value to keep the compiler happy.
+  if (!has_text_field || text_inputs[0] > password_inputs[0]) {
+    // There is no formal requirement to have associated username fields for
+    // every password field, but providing one ensures that the Password
+    // Manager associates the correct account name with the password (for
+    // example in password reset forms).
+    console_logger->Send(
+        "Password forms should have (optionally hidden) "
+        "username fields for accessibility:",
+        ConsoleLogger::kVerbose, form);
+  } else {
+    // By default (if the other heuristics fail), the first text field
+    // preceding a password field will be considered the username field.
+    for (username_field_guess = password_inputs[0] - 1;;
+         --username_field_guess) {
+      if (signature[username_field_guess] == 'T')
+        break;
+    }
+  }
+
+  if (FormIsTooComplex(signature)) {
+    console_logger->Send(
+        "Multiple forms should be contained in their own "
+        "form elements; break up complex forms into ones that represent a "
+        "single action:",
+        ConsoleLogger::kVerbose, form);
+    return;
+  }
+
+  // The autocomplete attribute provides valuable hints to the Password
+  // Manager as to the semantic structure of a form. Rather than simply point
+  // out that an autocomplete attribute would be useful, we try to suggest the
+  // intended value of the autocomplete attribute in order to save time for
+  // the developer.
+  std::map<size_t, std::string> autocomplete_suggestions;
+  if (has_text_field && text_inputs[0] < password_inputs[0])
+    InferUsernameField(form, inputs, username_field_guess,
+                       &autocomplete_suggestions);
+
+  GuessAutocompleteAttributesForPasswordFields(password_inputs, has_text_field,
+                                               &autocomplete_suggestions);
+
+  // For each input element that is not annotated with an autocomplete
+  // attribute, if we have a guess for what function the input serves, log
+  // a warning, suggesting that the inferred attribute value should be added.
+  for (size_t i = 0; i < inputs.size(); ++i) {
+    if (autocomplete_suggestions.count(i) &&
+        !inputs[i].HasAttribute("autocomplete"))
+      console_logger->Send(
+          "Input elements should have autocomplete "
+          "attributes (suggested: \"" +
+              autocomplete_suggestions[i] + "\"):",
+          ConsoleLogger::kVerbose, inputs[i]);
+  }
+}
+
+}  // namespace
+
+// Out-of-line definitions to keep [chromium-style] happy.
+PagePasswordsAnalyser::PagePasswordsAnalyser() {}
+
+PagePasswordsAnalyser::~PagePasswordsAnalyser() {}
+
+void PagePasswordsAnalyser::Reset() {
+  skip_nodes_.clear();
+}
+
+void PagePasswordsAnalyser::AnalyseDocumentDOM(blink::WebLocalFrame* frame) {
+  DCHECK(frame);
+  ConsoleLogger console_logger(frame);
+
+  blink::WebDocument document(frame->GetDocument());
+  // Extract all the forms from the DOM, and provide relevant warnings.
+  std::vector<FormInputCollection> forms(
+      ExtractFormsForAnalysis(document, &skip_nodes_, &console_logger));
+
+  // Analyse each form in turn, for example with respect to autocomplete
+  // attributes.
+  for (const FormInputCollection& form_input_collection : forms)
+    AnalyseForm(form_input_collection, &console_logger);
+
+  // Finally, send all the warnings and errors to the console.
+  console_logger.Flush();
+}
+
+}  // namespace autofill
\ No newline at end of file
diff --git a/components/autofill/content/renderer/page_passwords_analyser.h b/components/autofill/content/renderer/page_passwords_analyser.h
new file mode 100644
index 0000000..cdaceab
--- /dev/null
+++ b/components/autofill/content/renderer/page_passwords_analyser.h
@@ -0,0 +1,44 @@
+// 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_AUTOFILL_CONTENT_RENDERER_PAGE_PASSWORDS_ANALYSER_H_
+#define COMPONENTS_AUTOFILL_CONTENT_RENDERER_PAGE_PASSWORDS_ANALYSER_H_
+
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
+
+namespace autofill {
+
+// This class provides feedback to web developers about the password forms on
+// their webpages, in order to increase the accessibility of web forms to the
+// Password Manager. This is achieved by crawling the DOM whenever new forms are
+// added to the page and checking for common mistakes, or ways in which the form
+// could be improved (for example, with autocomplete attributes). See
+// |AnalyseDocumentDOM| for more specific information about these warnings.
+class PagePasswordsAnalyser {
+ public:
+  PagePasswordsAnalyser();
+
+  ~PagePasswordsAnalyser();
+
+  // Clear the set of nodes that have already been analysed, so that they will
+  // be analysed again next time |AnalyseDocumentDOM| is called. This is called
+  // upon page load, for instance.
+  void Reset();
+
+  // |AnalyseDocumentDOM| traverses the DOM, logging potential issues in the
+  // DevTools console. Errors are logged for those issues that conflict with the
+  // HTML specification. Warnings are logged for issues that cause problems with
+  // identification of fields on the web-page for the Password Manager.
+  void AnalyseDocumentDOM(blink::WebLocalFrame* frame);
+
+  std::set<blink::WebNode> skip_nodes_;
+  // This is true when new DOM content is available since the last time
+  // the page was analysed, meaning the page needs to be reanalysed.
+  bool page_dirty_;
+};
+
+}  // namespace autofill
+
+#endif
+   // COMPONENTS_AUTOFILL_CONTENT_RENDERER_PAGE_PASSWORDS_ANALYSER_H_
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc
index 39b17a40..2608d2f 100644
--- a/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -1309,6 +1309,14 @@
       GetPasswordManagerDriver()->PasswordFormsParsed(password_forms);
     }
   }
+
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+  // Provide warnings about the accessibility of password forms on the page.
+  if (!password_forms.empty() &&
+      (frame->GetDocument().Url().ProtocolIs(url::kHttpScheme) ||
+       frame->GetDocument().Url().ProtocolIs(url::kHttpsScheme)))
+    page_passwords_analyser_.AnalyseDocumentDOM(frame);
+#endif
 }
 
 void PasswordAutofillAgent::DidFinishDocumentLoad() {
@@ -1814,6 +1822,9 @@
   sent_request_to_store_ = false;
   checked_safe_browsing_reputation_ = false;
   blacklisted_form_found_ = false;
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+  page_passwords_analyser_.Reset();
+#endif
 }
 
 void PasswordAutofillAgent::ClearPreview(
diff --git a/components/autofill/content/renderer/password_autofill_agent.h b/components/autofill/content/renderer/password_autofill_agent.h
index f34bd69a..82aa6ee 100644
--- a/components/autofill/content/renderer/password_autofill_agent.h
+++ b/components/autofill/content/renderer/password_autofill_agent.h
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/macros.h"
+#include "build/build_config.h"
 #include "components/autofill/content/common/autofill_agent.mojom.h"
 #include "components/autofill/content/common/autofill_driver.mojom.h"
 #include "components/autofill/content/renderer/autofill_agent.h"
@@ -25,6 +26,10 @@
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "third_party/WebKit/public/web/WebInputElement.h"
 
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#include "components/autofill/content/renderer/page_passwords_analyser.h"
+#endif
+
 namespace blink {
 class WebFormElementObserver;
 class WebInputElement;
@@ -317,6 +322,10 @@
 
   AutofillAgent* autofill_agent_;  // Weak reference.
 
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+  PagePasswordsAnalyser page_passwords_analyser_;
+#endif
+
   mojom::PasswordManagerDriverPtr password_manager_driver_;
 
   mojo::Binding<mojom::PasswordAutofillAgent> binding_;
diff --git a/components/autofill/content/renderer/password_form_conversion_utils.cc b/components/autofill/content/renderer/password_form_conversion_utils.cc
index 151eae7..4850ad8f 100644
--- a/components/autofill/content/renderer/password_form_conversion_utils.cc
+++ b/components/autofill/content/renderer/password_form_conversion_utils.cc
@@ -100,16 +100,6 @@
 const char kAutocompleteNewPassword[] = "new-password";
 const char kAutocompleteCreditCardPrefix[] = "cc-";
 
-re2::RE2* CreateMatcher(void* instance, const char* pattern) {
-  re2::RE2::Options options;
-  options.set_case_sensitive(false);
-  // Use placement new to initialize the instance in the preallocated space.
-  // The "(instance)" is very important to force POD type initialization.
-  re2::RE2* matcher = new (instance) re2::RE2(pattern, options);
-  DCHECK(matcher->ok());
-  return matcher;
-}
-
 struct LoginAndSignupLazyInstanceTraits
     : public base::internal::DestructorAtExitLazyInstanceTraits<re2::RE2> {
   static re2::RE2* New(void* instance) {
@@ -664,6 +654,16 @@
 
 }  // namespace
 
+re2::RE2* CreateMatcher(void* instance, const char* pattern) {
+  re2::RE2::Options options;
+  options.set_case_sensitive(false);
+  // Use placement new to initialize the instance in the preallocated space.
+  // The "(instance)" is very important to force POD type initialization.
+  re2::RE2* matcher = new (instance) re2::RE2(pattern, options);
+  DCHECK(matcher->ok());
+  return matcher;
+}
+
 bool IsGaiaReauthenticationForm(const blink::WebFormElement& form) {
   if (GURL(form.GetDocument().Url()).GetOrigin() !=
       GaiaUrls::GetInstance()->gaia_url().GetOrigin()) {
diff --git a/components/autofill/content/renderer/password_form_conversion_utils.h b/components/autofill/content/renderer/password_form_conversion_utils.h
index a039eaf..339d105 100644
--- a/components/autofill/content/renderer/password_form_conversion_utils.h
+++ b/components/autofill/content/renderer/password_form_conversion_utils.h
@@ -24,10 +24,17 @@
 class WebLocalFrame;
 }
 
+namespace re2 {
+class RE2;
+}
+
 namespace autofill {
 
 struct PasswordForm;
 
+// The caller of this function is responsible for deleting the returned object.
+re2::RE2* CreateMatcher(void* instance, const char* pattern);
+
 // Tests whether the given form is a GAIA reauthentication form.
 bool IsGaiaReauthenticationForm(const blink::WebFormElement& form);
 
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn
index 65bf484..0cf8f69 100644
--- a/components/autofill/core/browser/BUILD.gn
+++ b/components/autofill/core/browser/BUILD.gn
@@ -14,6 +14,9 @@
     "address_field.h",
     "address_i18n.cc",
     "address_i18n.h",
+    "address_normalizer.h",
+    "address_normalizer_impl.cc",
+    "address_normalizer_impl.h",
     "address_rewriter.cc",
     "address_rewriter.h",
     "address_rewriter_rules.cc",
@@ -250,6 +253,8 @@
     "data_driven_test.cc",
     "data_driven_test.h",
     "suggestion_test_helpers.h",
+    "test_address_normalizer.cc",
+    "test_address_normalizer.h",
     "test_autofill_client.cc",
     "test_autofill_client.h",
     "test_autofill_clock.cc",
@@ -326,6 +331,7 @@
     "address_combobox_model_unittest.cc",
     "address_field_unittest.cc",
     "address_i18n_unittest.cc",
+    "address_normalizer_impl_unittest.cc",
     "address_rewriter_unittest.cc",
     "address_unittest.cc",
     "address_validation_util_unittest.cc",
diff --git a/components/autofill/core/browser/address_normalizer.h b/components/autofill/core/browser/address_normalizer.h
new file mode 100644
index 0000000..dd4ce5ec
--- /dev/null
+++ b/components/autofill/core/browser/address_normalizer.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 COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZER_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZER_H_
+
+#include <string>
+
+#include "third_party/libaddressinput/chromium/chrome_address_validator.h"
+
+namespace autofill {
+
+class AutofillProfile;
+
+// A class used to normalize addresses.
+class AddressNormalizer : public autofill::LoadRulesListener {
+ public:
+  // The interface for the normalization delegates.
+  class Delegate {
+   public:
+    virtual void OnAddressNormalized(
+        const AutofillProfile& normalized_profile) = 0;
+
+    virtual void OnCouldNotNormalize(const AutofillProfile& profile) = 0;
+
+   protected:
+    virtual ~Delegate() {}
+  };
+
+  // The interface for the normalization request.
+  class Request {
+   public:
+    virtual void OnRulesLoaded(bool success) = 0;
+    virtual ~Request() {}
+  };
+
+  // Start loading the validation rules for the specified |region_code|.
+  virtual void LoadRulesForRegion(const std::string& region_code) = 0;
+
+  // Returns whether the rules for the specified |region_code| have finished
+  // loading.
+  virtual bool AreRulesLoadedForRegion(const std::string& region_code) = 0;
+
+  // Starts the normalization of the |profile| based on the |region_code|. The
+  // normalized profile will be returned to the |requester| possibly
+  // asynchronously. If the normalization is not completed in |timeout_seconds|
+  // the requester will be informed and the request cancelled. This value should
+  // be greater or equal to 0, for which it means that the normalization should
+  // happen synchronously, or not at all if the rules are not already loaded.
+  // Will start loading the rules for the |region_code| if they had not started
+  // loading.
+  virtual void StartAddressNormalization(const AutofillProfile& profile,
+                                         const std::string& region_code,
+                                         int timeout_seconds,
+                                         Delegate* requester) = 0;
+};
+
+}  // namespace autofill
+
+#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZER_H_
diff --git a/components/autofill/core/browser/address_normalizer_impl.cc b/components/autofill/core/browser/address_normalizer_impl.cc
new file mode 100644
index 0000000..00fb2487
--- /dev/null
+++ b/components/autofill/core/browser/address_normalizer_impl.cc
@@ -0,0 +1,186 @@
+// 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/autofill/core/browser/address_normalizer_impl.h"
+
+#include <stddef.h>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/cancelable_callback.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "base/time/time.h"
+#include "components/autofill/core/browser/address_i18n.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/phone_number_i18n.h"
+#include "third_party/libaddressinput/chromium/chrome_address_validator.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/source.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h"
+
+namespace autofill {
+namespace {
+
+using ::i18n::addressinput::Source;
+using ::i18n::addressinput::Storage;
+
+class AddressNormalizationRequest : public AddressNormalizer::Request {
+ public:
+  // The |delegate| and |address_validator| need to outlive this Request.
+  AddressNormalizationRequest(const AutofillProfile& profile,
+                              const std::string& region_code,
+                              int timeout_seconds,
+                              AddressNormalizer::Delegate* delegate,
+                              AddressValidator* address_validator)
+      : profile_(profile),
+        region_code_(region_code),
+        delegate_(delegate),
+        address_validator_(address_validator),
+        has_responded_(false),
+        on_timeout_(base::Bind(&AddressNormalizationRequest::OnRulesLoaded,
+                               base::Unretained(this),
+                               false)) {
+    base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
+        FROM_HERE, on_timeout_.callback(),
+        base::TimeDelta::FromSeconds(timeout_seconds));
+  }
+
+  ~AddressNormalizationRequest() override {}
+
+  void OnRulesLoaded(bool success) override {
+    on_timeout_.Cancel();
+
+    // Check if the timeout happened before the rules were loaded.
+    if (has_responded_)
+      return;
+    has_responded_ = true;
+
+    // In either case, format the phone number.
+    FormatPhoneNumberForResponse();
+
+    if (!success) {
+      delegate_->OnCouldNotNormalize(profile_);
+      return;
+    }
+
+    // The rules should be loaded.
+    DCHECK(address_validator_->AreRulesLoadedForRegion(region_code_));
+
+    // Create the AddressData from the profile.
+    ::i18n::addressinput::AddressData address_data =
+        *autofill::i18n::CreateAddressDataFromAutofillProfile(profile_,
+                                                              region_code_);
+
+    // Normalize the address.
+    if (address_validator_ &&
+        address_validator_->NormalizeAddress(&address_data)) {
+      profile_.SetRawInfo(ADDRESS_HOME_STATE,
+                          base::UTF8ToUTF16(address_data.administrative_area));
+      profile_.SetRawInfo(ADDRESS_HOME_CITY,
+                          base::UTF8ToUTF16(address_data.locality));
+      profile_.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY,
+                          base::UTF8ToUTF16(address_data.dependent_locality));
+    }
+
+    delegate_->OnAddressNormalized(profile_);
+  }
+
+ private:
+  // Tries to format the phone number to the E.164 format to send in the Payment
+  // Response, as defined in the Payment Request spec. Keeps the original
+  // if it cannot be formatted. More info at:
+  // https://w3c.github.io/browser-payment-api/#paymentrequest-updated-algorithm
+  void FormatPhoneNumberForResponse() {
+    const std::string original_number = base::UTF16ToUTF8(
+        profile_.GetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER), region_code_));
+
+    std::string formatted_number =
+        autofill::i18n::FormatPhoneForResponse(original_number, region_code_);
+
+    profile_.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
+                        base::UTF8ToUTF16(formatted_number));
+  }
+
+  AutofillProfile profile_;
+  std::string region_code_;
+  AddressNormalizer::Delegate* delegate_;
+  AddressValidator* address_validator_;
+
+  bool has_responded_;
+  base::CancelableCallback<void()> on_timeout_;
+
+  DISALLOW_COPY_AND_ASSIGN(AddressNormalizationRequest);
+};
+
+}  // namespace
+
+AddressNormalizerImpl::AddressNormalizerImpl(std::unique_ptr<Source> source,
+                                             std::unique_ptr<Storage> storage)
+    : address_validator_(std::move(source), std::move(storage), this) {}
+
+AddressNormalizerImpl::~AddressNormalizerImpl() {}
+
+void AddressNormalizerImpl::LoadRulesForRegion(const std::string& region_code) {
+  address_validator_.LoadRules(region_code);
+}
+
+bool AddressNormalizerImpl::AreRulesLoadedForRegion(
+    const std::string& region_code) {
+  return address_validator_.AreRulesLoadedForRegion(region_code);
+}
+
+void AddressNormalizerImpl::StartAddressNormalization(
+    const AutofillProfile& profile,
+    const std::string& region_code,
+    int timeout_seconds,
+    AddressNormalizer::Delegate* requester) {
+  DCHECK_GE(timeout_seconds, 0);
+
+  std::unique_ptr<AddressNormalizationRequest> request(
+      base::MakeUnique<AddressNormalizationRequest>(profile, region_code,
+                                                    timeout_seconds, requester,
+                                                    &address_validator_));
+
+  // Check if the rules are already loaded.
+  if (AreRulesLoadedForRegion(region_code)) {
+    request->OnRulesLoaded(true);
+  } else {
+    // Setup the variables so the profile gets normalized when the rules have
+    // finished loading.
+    auto it = pending_normalization_.find(region_code);
+    if (it == pending_normalization_.end()) {
+      // If no entry exists yet, create the entry and assign it to |it|.
+      it = pending_normalization_
+               .insert(std::make_pair(region_code,
+                                      std::vector<std::unique_ptr<Request>>()))
+               .first;
+    }
+
+    it->second.push_back(std::move(request));
+
+    // Start loading the rules for that region. If the rules were already in the
+    // process of being loaded, this call will do nothing.
+    LoadRulesForRegion(region_code);
+  }
+}
+
+void AddressNormalizerImpl::OnAddressValidationRulesLoaded(
+    const std::string& region_code,
+    bool success) {
+  // Check if an address normalization is pending.
+  auto it = pending_normalization_.find(region_code);
+  if (it != pending_normalization_.end()) {
+    for (size_t i = 0; i < it->second.size(); ++i) {
+      it->second[i]->OnRulesLoaded(success);
+    }
+    pending_normalization_.erase(it);
+  }
+}
+
+}  // namespace autofill
diff --git a/components/autofill/core/browser/address_normalizer_impl.h b/components/autofill/core/browser/address_normalizer_impl.h
new file mode 100644
index 0000000..27ace767
--- /dev/null
+++ b/components/autofill/core/browser/address_normalizer_impl.h
@@ -0,0 +1,60 @@
+// 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_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZER_IMPL_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZER_IMPL_H_
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "components/autofill/core/browser/address_normalizer.h"
+
+namespace i18n {
+namespace addressinput {
+class Source;
+class Storage;
+}  // namespace addressinput
+}  // namespace i18n
+
+namespace autofill {
+
+class AutofillProfile;
+
+// A class used to normalize addresses.
+class AddressNormalizerImpl : public AddressNormalizer {
+ public:
+  AddressNormalizerImpl(std::unique_ptr<::i18n::addressinput::Source> source,
+                        std::unique_ptr<::i18n::addressinput::Storage> storage);
+  ~AddressNormalizerImpl() override;
+
+  // AddressNormalizer implementation.
+  void LoadRulesForRegion(const std::string& region_code) override;
+  bool AreRulesLoadedForRegion(const std::string& region_code) override;
+  void StartAddressNormalization(const AutofillProfile& profile,
+                                 const std::string& region_code,
+                                 int timeout_seconds,
+                                 Delegate* requester) override;
+
+ private:
+  // Called when the validation rules for the |region_code| have finished
+  // loading. Implementation of the LoadRulesListener interface.
+  void OnAddressValidationRulesLoaded(const std::string& region_code,
+                                      bool success) override;
+
+  // Map associating a region code to pending normalizations.
+  std::map<std::string, std::vector<std::unique_ptr<Request>>>
+      pending_normalization_;
+
+  // The address validator used to normalize addresses.
+  AddressValidator address_validator_;
+
+  DISALLOW_COPY_AND_ASSIGN(AddressNormalizerImpl);
+};
+
+}  // namespace autofill
+
+#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZER_IMPL_H_
diff --git a/components/autofill/core/browser/address_normalizer_impl_unittest.cc b/components/autofill/core/browser/address_normalizer_impl_unittest.cc
new file mode 100644
index 0000000..7ec31ca
--- /dev/null
+++ b/components/autofill/core/browser/address_normalizer_impl_unittest.cc
@@ -0,0 +1,245 @@
+// 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/autofill/core/browser/address_normalizer_impl.h"
+
+#include <utility>
+
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_task_environment.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/null_storage.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/source.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h"
+#include "third_party/libaddressinput/src/cpp/test/testdata_source.h"
+
+namespace autofill {
+namespace {
+
+using ::i18n::addressinput::NullStorage;
+using ::i18n::addressinput::Source;
+using ::i18n::addressinput::Storage;
+using ::i18n::addressinput::TestdataSource;
+
+const char kLocale[] = "US";
+
+// The requester of normalization for this test.
+class NormalizationDelegate : public AddressNormalizer::Delegate {
+ public:
+  NormalizationDelegate()
+      : normalized_called_(false), not_normalized_called_(false) {}
+
+  ~NormalizationDelegate() override {}
+
+  void OnAddressNormalized(const AutofillProfile& profile) override {
+    normalized_called_ = true;
+    profile_ = profile;
+  }
+
+  void OnCouldNotNormalize(const AutofillProfile& profile) override {
+    not_normalized_called_ = true;
+    profile_ = profile;
+  }
+
+  bool normalized_called() const { return normalized_called_; }
+
+  bool not_normalized_called() const { return not_normalized_called_; }
+
+  const AutofillProfile& profile() const { return profile_; }
+
+ private:
+  bool normalized_called_;
+  bool not_normalized_called_;
+  AutofillProfile profile_;
+
+  DISALLOW_COPY_AND_ASSIGN(NormalizationDelegate);
+};
+
+// Used to load region rules for this test.
+class ChromiumTestdataSource : public TestdataSource {
+ public:
+  ChromiumTestdataSource() : TestdataSource(true) {}
+
+  ~ChromiumTestdataSource() override {}
+
+  // For this test, only load the rules for the kLocale.
+  void Get(const std::string& key, const Callback& data_ready) const override {
+    data_ready(
+        true, key,
+        new std::string("{\"data/US\": "
+                        "{\"id\":\"data/US\",\"key\":\"US\",\"name\":\"UNITED "
+                        "STATES\",\"lang\":\"en\",\"languages\":\"en\"}}"));
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ChromiumTestdataSource);
+};
+
+// A test subclass of the AddressNormalizerImpl. Used to simulate rules not
+// being loaded.
+class TestAddressNormalizer : public AddressNormalizerImpl {
+ public:
+  TestAddressNormalizer(std::unique_ptr<::i18n::addressinput::Source> source,
+                        std::unique_ptr<::i18n::addressinput::Storage> storage)
+      : AddressNormalizerImpl(std::move(source), std::move(storage)),
+        should_load_rules_(true) {}
+
+  ~TestAddressNormalizer() override {}
+
+  void ShouldLoadRules(bool should_load_rules) {
+    should_load_rules_ = should_load_rules;
+  }
+
+  void LoadRulesForRegion(const std::string& region_code) override {
+    if (should_load_rules_) {
+      AddressNormalizerImpl::LoadRulesForRegion(region_code);
+    }
+  }
+
+ private:
+  bool should_load_rules_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestAddressNormalizer);
+};
+
+}  // namespace
+
+class AddressNormalizerTest : public testing::Test {
+ protected:
+  AddressNormalizerTest()
+      : normalizer_(new TestAddressNormalizer(
+            std::unique_ptr<Source>(new ChromiumTestdataSource),
+            std::unique_ptr<Storage>(new NullStorage))) {}
+
+  ~AddressNormalizerTest() override {}
+
+  const std::unique_ptr<TestAddressNormalizer> normalizer_;
+
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AddressNormalizerTest);
+};
+
+// Tests that rules are not loaded by default.
+TEST_F(AddressNormalizerTest, AreRulesLoadedForRegion_NotLoaded) {
+  EXPECT_FALSE(normalizer_->AreRulesLoadedForRegion(kLocale));
+}
+
+// Tests that the rules are loaded correctly.
+TEST_F(AddressNormalizerTest, AreRulesLoadedForRegion_Loaded) {
+  normalizer_->LoadRulesForRegion(kLocale);
+  EXPECT_TRUE(normalizer_->AreRulesLoadedForRegion(kLocale));
+}
+
+// Tests that if the rules are loaded before the normalization is started, the
+// normalized profile will be returned to the delegate synchronously.
+TEST_F(AddressNormalizerTest, StartNormalization_RulesLoaded) {
+  NormalizationDelegate delegate;
+  AutofillProfile profile;
+
+  // Load the rules.
+  normalizer_->LoadRulesForRegion(kLocale);
+  EXPECT_TRUE(normalizer_->AreRulesLoadedForRegion(kLocale));
+
+  // Start the normalization.
+  normalizer_->StartAddressNormalization(profile, kLocale, 0, &delegate);
+
+  // Since the rules are already loaded, the address should be normalized
+  // synchronously.
+  EXPECT_TRUE(delegate.normalized_called());
+  EXPECT_FALSE(delegate.not_normalized_called());
+}
+
+// Tests that if the rules are not loaded before the normalization and cannot be
+// loaded after, the address will not be normalized and the delegate will be
+// notified.
+TEST_F(AddressNormalizerTest, StartNormalization_RulesNotLoaded_WillNotLoad) {
+  NormalizationDelegate delegate;
+  AutofillProfile profile;
+
+  // Make sure the rules will not be loaded in the StartAddressNormalization
+  // call.
+  normalizer_->ShouldLoadRules(false);
+
+  // Start the normalization.
+  normalizer_->StartAddressNormalization(profile, kLocale, 0, &delegate);
+
+  // Let the timeout execute.
+  scoped_task_environment_.RunUntilIdle();
+
+  // Since the rules are never loaded and the timeout is 0, the delegate should
+  // get notified that the address could not be normalized.
+  EXPECT_FALSE(delegate.normalized_called());
+  EXPECT_TRUE(delegate.not_normalized_called());
+}
+
+// Tests that if the rules are not loaded before the call to
+// StartAddressNormalization, they will be loaded in the call.
+TEST_F(AddressNormalizerTest, StartNormalization_RulesNotLoaded_WillLoad) {
+  NormalizationDelegate delegate;
+  AutofillProfile profile;
+
+  // Start the normalization.
+  normalizer_->StartAddressNormalization(profile, kLocale, 0, &delegate);
+
+  // Even if the rules are not loaded before the call to
+  // StartAddressNormalization, they should get loaded in the call. Since our
+  // test source is synchronous, the normalization will happen synchronously
+  // too.
+  EXPECT_TRUE(normalizer_->AreRulesLoadedForRegion(kLocale));
+  EXPECT_TRUE(delegate.normalized_called());
+  EXPECT_FALSE(delegate.not_normalized_called());
+}
+
+// Tests that the phone number is formatted when the address is normalized.
+TEST_F(AddressNormalizerTest, FormatPhone_AddressNormalized) {
+  NormalizationDelegate delegate;
+  AutofillProfile profile;
+  profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
+                     base::UTF8ToUTF16("(515) 123-1234"));
+
+  // Load the rules.
+  normalizer_->LoadRulesForRegion(kLocale);
+  EXPECT_TRUE(normalizer_->AreRulesLoadedForRegion(kLocale));
+
+  // Start the normalization.
+  normalizer_->StartAddressNormalization(profile, kLocale, 0, &delegate);
+
+  // Make sure the address was normalized.
+  EXPECT_TRUE(delegate.normalized_called());
+
+  // Expect that the phone number was formatted.
+  EXPECT_EQ("+15151231234", base::UTF16ToUTF8(delegate.profile().GetRawInfo(
+                                PHONE_HOME_WHOLE_NUMBER)));
+}
+
+// Tests that the phone number is formatted even when the address is not
+// normalized.
+TEST_F(AddressNormalizerTest, FormatPhone_AddressNotNormalized) {
+  NormalizationDelegate delegate;
+  AutofillProfile profile;
+  profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
+                     base::UTF8ToUTF16("515-123-1234"));
+
+  // Make sure the rules will not be loaded in the StartAddressNormalization
+  // call.
+  normalizer_->ShouldLoadRules(false);
+
+  // Start the normalization.
+  normalizer_->StartAddressNormalization(profile, kLocale, 0, &delegate);
+
+  // Let the timeout execute.
+  scoped_task_environment_.RunUntilIdle();
+
+  // Make sure the address was not normalized.
+  EXPECT_TRUE(delegate.not_normalized_called());
+
+  // Expect that the phone number was formatted.
+  EXPECT_EQ("+15151231234", base::UTF16ToUTF8(delegate.profile().GetRawInfo(
+                                PHONE_HOME_WHOLE_NUMBER)));
+}
+
+}  // namespace autofill
diff --git a/components/autofill/core/browser/autofill_data_util.cc b/components/autofill/core/browser/autofill_data_util.cc
index 784409dd0..7e0f53b 100644
--- a/components/autofill/core/browser/autofill_data_util.cc
+++ b/components/autofill/core/browser/autofill_data_util.cc
@@ -12,6 +12,8 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/autofill_country.h"
+#include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/grit/components_scaled_resources.h"
@@ -442,5 +444,14 @@
   return IsValidCountryCode(base::UTF16ToUTF8(country_code));
 }
 
+std::string GetCountryCodeWithFallback(const autofill::AutofillProfile* profile,
+                                       const std::string& app_locale) {
+  std::string country_code =
+      base::UTF16ToUTF8(profile->GetRawInfo(autofill::ADDRESS_HOME_COUNTRY));
+  if (!IsValidCountryCode(country_code))
+    country_code = AutofillCountry::CountryCodeForLocale(app_locale);
+  return country_code;
+}
+
 }  // namespace data_util
 }  // namespace autofill
diff --git a/components/autofill/core/browser/autofill_data_util.h b/components/autofill/core/browser/autofill_data_util.h
index 2e3d6fc..74c972e 100644
--- a/components/autofill/core/browser/autofill_data_util.h
+++ b/components/autofill/core/browser/autofill_data_util.h
@@ -9,9 +9,11 @@
 
 #include "base/strings/string16.h"
 #include "base/strings/string_piece_forward.h"
-#include "components/autofill/core/browser/autofill_profile.h"
 
 namespace autofill {
+
+class AutofillProfile;
+
 namespace data_util {
 
 struct NameParts {
@@ -66,6 +68,12 @@
 bool IsValidCountryCode(const std::string& country_code);
 bool IsValidCountryCode(const base::string16& country_code);
 
+// Returns a country code to be used when validating this profile. If the
+// profile has a valid country code set, it is returned. If not, a country code
+// associated with |app_locale| is used as a fallback.
+std::string GetCountryCodeWithFallback(const autofill::AutofillProfile* profile,
+                                       const std::string& app_locale);
+
 }  // namespace data_util
 }  // namespace autofill
 
diff --git a/components/autofill/core/browser/autofill_data_util_unittest.cc b/components/autofill/core/browser/autofill_data_util_unittest.cc
index 1a66f8e..d2de515 100644
--- a/components/autofill/core/browser/autofill_data_util_unittest.cc
+++ b/components/autofill/core/browser/autofill_data_util_unittest.cc
@@ -5,6 +5,7 @@
 #include "components/autofill/core/browser/autofill_data_util.h"
 
 #include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc
index 415fec0b..e216bcb 100644
--- a/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -5411,8 +5411,6 @@
   credit_card_form.fields[3].value = ASCIIToUTF16("2017");
   credit_card_form.fields[4].value = ASCIIToUTF16("123");
 
-  base::HistogramTester histogram_tester;
-
   // Confirm upload happened and the new UI flag was sent in the request.
   EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
   FormSubmitted(credit_card_form);
@@ -5446,9 +5444,7 @@
   credit_card_form.fields[3].value = ASCIIToUTF16("2017");
   credit_card_form.fields[4].value = ASCIIToUTF16("123");
 
-  base::HistogramTester histogram_tester;
-
-  // Confirm upload happened and the new UI flag was sent in the request.
+  // Confirm upload happened and the new UI flag was not sent in the request.
   EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
   FormSubmitted(credit_card_form);
   EXPECT_TRUE(autofill_manager_->credit_card_was_uploaded());
@@ -5481,8 +5477,6 @@
   credit_card_form.fields[3].value = ASCIIToUTF16("2017");
   credit_card_form.fields[4].value = ASCIIToUTF16("123");
 
-  base::HistogramTester histogram_tester;
-
   // Confirm upload happened and the show Google logo flag was sent in the
   // request.
   EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
@@ -5517,9 +5511,7 @@
   credit_card_form.fields[3].value = ASCIIToUTF16("2017");
   credit_card_form.fields[4].value = ASCIIToUTF16("123");
 
-  base::HistogramTester histogram_tester;
-
-  // Confirm upload happened and the show Google logo flag was sent in the
+  // Confirm upload happened and the show Google logo flag was not sent in the
   // request.
   EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
   FormSubmitted(credit_card_form);
diff --git a/components/autofill/core/browser/phone_number_i18n.cc b/components/autofill/core/browser/phone_number_i18n.cc
index 66fe9faa..63954a0 100644
--- a/components/autofill/core/browser/phone_number_i18n.cc
+++ b/components/autofill/core/browser/phone_number_i18n.cc
@@ -11,15 +11,34 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/autofill/core/browser/autofill_country.h"
+#include "components/autofill/core/browser/autofill_data_util.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/validation.h"
 #include "third_party/libphonenumber/phonenumber_api.h"
 
-using i18n::phonenumbers::PhoneNumber;
-using i18n::phonenumbers::PhoneNumberUtil;
-
 namespace autofill {
 
 namespace {
 
+using ::i18n::phonenumbers::PhoneNumberUtil;
+
+// Formats the |phone_number| to the specified |format|. Returns the original
+// number if the operation is not possible.
+std::string FormatPhoneNumber(const std::string& phone_number,
+                              const std::string& country_code,
+                              PhoneNumberUtil::PhoneNumberFormat format) {
+  ::i18n::phonenumbers::PhoneNumber parsed_number;
+  PhoneNumberUtil* phone_number_util = PhoneNumberUtil::GetInstance();
+  if (phone_number_util->Parse(phone_number, country_code, &parsed_number) !=
+      PhoneNumberUtil::NO_PARSING_ERROR) {
+    return phone_number;
+  }
+
+  std::string formatted_number;
+  phone_number_util->Format(parsed_number, format, &formatted_number);
+  return formatted_number;
+}
+
 std::string SanitizeRegion(const std::string& region,
                            const std::string& app_locale) {
   if (region.length() == 2)
@@ -29,7 +48,7 @@
 }
 
 // Returns true if |phone_number| is valid.
-bool IsValidPhoneNumber(const PhoneNumber& phone_number) {
+bool IsValidPhoneNumber(const ::i18n::phonenumbers::PhoneNumber& phone_number) {
   PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance();
   if (!phone_util->IsPossibleNumber(phone_number))
     return false;
@@ -52,7 +71,7 @@
 // whether to format in the national or in the international format, is passed
 // in explicitly, as |number| might have an implicit country code set, even
 // though the original input lacked a country code.
-void FormatValidatedNumber(const PhoneNumber& number,
+void FormatValidatedNumber(const ::i18n::phonenumbers::PhoneNumber& number,
                            const base::string16& country_code,
                            base::string16* formatted_number,
                            base::string16* normalized_number) {
@@ -101,11 +120,11 @@
                       base::string16* city_code,
                       base::string16* number,
                       std::string* inferred_region,
-                      PhoneNumber* i18n_number) {
+                      ::i18n::phonenumbers::PhoneNumber* i18n_number) {
   country_code->clear();
   city_code->clear();
   number->clear();
-  *i18n_number = PhoneNumber();
+  *i18n_number = ::i18n::phonenumbers::PhoneNumber();
 
   std::string number_text(base::UTF16ToUTF8(value));
 
@@ -150,7 +169,8 @@
   // Check if parsed number has a country code that was not inferred from the
   // region.
   if (i18n_number->has_country_code() &&
-      i18n_number->country_code_source() != PhoneNumber::FROM_DEFAULT_COUNTRY) {
+      i18n_number->country_code_source() !=
+          ::i18n::phonenumbers::PhoneNumber::FROM_DEFAULT_COUNTRY) {
     *country_code = base::UTF8ToUTF16(
         base::IntToString(i18n_number->country_code()));
   }
@@ -166,7 +186,7 @@
   DCHECK_EQ(2u, region.size());
   base::string16 country_code, unused_city_code, unused_number;
   std::string unused_region;
-  PhoneNumber phone_number;
+  ::i18n::phonenumbers::PhoneNumber phone_number;
   if (!ParsePhoneNumber(value, region, &country_code, &unused_city_code,
                         &unused_number, &unused_region, &phone_number)) {
     return base::string16();  // Parsing failed - do not store phone.
@@ -187,7 +207,7 @@
 
   base::string16 unused_country_code, unused_city_code, unused_number;
   std::string unused_region;
-  PhoneNumber phone_number;
+  ::i18n::phonenumbers::PhoneNumber phone_number;
   if (!ParsePhoneNumber(country_code + city_code + number, region,
                         &unused_country_code, &unused_city_code, &unused_number,
                         &unused_region, &phone_number)) {
@@ -208,14 +228,14 @@
   PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance();
 
   // Parse phone numbers based on the region
-  PhoneNumber i18n_number1;
+  ::i18n::phonenumbers::PhoneNumber i18n_number1;
   if (phone_util->Parse(
           base::UTF16ToUTF8(number_a), region.c_str(), &i18n_number1) !=
               PhoneNumberUtil::NO_PARSING_ERROR) {
     return false;
   }
 
-  PhoneNumber i18n_number2;
+  ::i18n::phonenumbers::PhoneNumber i18n_number2;
   if (phone_util->Parse(
           base::UTF16ToUTF8(number_b), region.c_str(), &i18n_number2) !=
               PhoneNumberUtil::NO_PARSING_ERROR) {
@@ -237,6 +257,45 @@
   return false;
 }
 
+base::string16 GetFormattedPhoneNumberForDisplay(const AutofillProfile& profile,
+                                                 const std::string& locale) {
+  // Since the "+" is removed for some country's phone numbers, try to add a "+"
+  // and see if it is a valid phone number for a country.
+  // Having two "+" in front of a number has no effect on the formatted number.
+  // The reason for this is international phone numbers for another country. For
+  // example, without adding a "+", the US number 1-415-123-1234 for an AU
+  // address would be wrongly formatted as +61 1-415-123-1234 which is invalid.
+  std::string phone = base::UTF16ToUTF8(
+      profile.GetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER), locale));
+  std::string tentative_intl_phone = "+" + phone;
+
+  // Always favor the tentative international phone number if it's determined as
+  // being a valid number.
+  if (IsValidPhoneNumber(
+          base::UTF8ToUTF16(tentative_intl_phone),
+          autofill::data_util::GetCountryCodeWithFallback(&profile, locale))) {
+    return base::UTF8ToUTF16(FormatPhoneForDisplay(
+        tentative_intl_phone,
+        autofill::data_util::GetCountryCodeWithFallback(&profile, locale)));
+  }
+
+  return base::UTF8ToUTF16(FormatPhoneForDisplay(
+      phone,
+      autofill::data_util::GetCountryCodeWithFallback(&profile, locale)));
+}
+
+std::string FormatPhoneForDisplay(const std::string& phone_number,
+                                  const std::string& country_code) {
+  return FormatPhoneNumber(phone_number, country_code,
+                           PhoneNumberUtil::PhoneNumberFormat::INTERNATIONAL);
+}
+
+std::string FormatPhoneForResponse(const std::string& phone_number,
+                                   const std::string& country_code) {
+  return FormatPhoneNumber(phone_number, country_code,
+                           PhoneNumberUtil::PhoneNumberFormat::E164);
+}
+
 PhoneObject::PhoneObject(const base::string16& number,
                          const std::string& region) {
   DCHECK_EQ(2u, region.size());
@@ -246,7 +305,8 @@
   // [ http://crbug.com/100845 ].  Once the bug is fixed, add a DCHECK here to
   // verify.
 
-  std::unique_ptr<PhoneNumber> i18n_number(new PhoneNumber);
+  std::unique_ptr<::i18n::phonenumbers::PhoneNumber> i18n_number(
+      new ::i18n::phonenumbers::PhoneNumber);
   if (ParsePhoneNumber(number, region, &country_code_, &city_code_, &number_,
                        &region_, i18n_number.get())) {
     // The phone number was successfully parsed, so store the parsed version.
@@ -298,7 +358,8 @@
   region_ = other.region_;
 
   if (other.i18n_number_.get())
-    i18n_number_.reset(new PhoneNumber(*other.i18n_number_));
+    i18n_number_.reset(
+        new ::i18n::phonenumbers::PhoneNumber(*other.i18n_number_));
   else
     i18n_number_.reset();
 
diff --git a/components/autofill/core/browser/phone_number_i18n.h b/components/autofill/core/browser/phone_number_i18n.h
index 26e2a1b..5baa44a 100644
--- a/components/autofill/core/browser/phone_number_i18n.h
+++ b/components/autofill/core/browser/phone_number_i18n.h
@@ -20,6 +20,8 @@
 
 namespace autofill {
 
+class AutofillProfile;
+
 // Utilities to process, normalize and compare international phone numbers.
 namespace i18n {
 
@@ -68,6 +70,24 @@
                        const std::string& region,
                        const std::string& app_locale);
 
+// Returns the phone number from the given |profile| formatted for display.
+base::string16 GetFormattedPhoneNumberForDisplay(const AutofillProfile& profile,
+                                                 const std::string& locale);
+
+// Formats the given number |phone_number| to
+// i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat::INTERNATIONAL format
+// by using i18n::phonenumbers::PhoneNumberUtil::Format.
+std::string FormatPhoneForDisplay(const std::string& phone_number,
+                                  const std::string& country_code);
+
+// Formats the given number |phone_number| to
+// i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat::E164 format by using
+// i18n::phonenumbers::PhoneNumberUtil::Format, as defined in the Payment
+// Request spec
+// (https://w3c.github.io/browser-payment-api/#paymentrequest-updated-algorithm)
+std::string FormatPhoneForResponse(const std::string& phone_number,
+                                   const std::string& country_code);
+
 // The cached phone number, does parsing only once, improves performance.
 class PhoneObject {
  public:
diff --git a/components/autofill/core/browser/phone_number_i18n_unittest.cc b/components/autofill/core/browser/phone_number_i18n_unittest.cc
index 17a2431..ac791074 100644
--- a/components/autofill/core/browser/phone_number_i18n_unittest.cc
+++ b/components/autofill/core/browser/phone_number_i18n_unittest.cc
@@ -2,13 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "components/autofill/core/browser/phone_number_i18n.h"
+
 #include <stddef.h>
 
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/browser/phone_number_i18n.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/field_types.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/libphonenumber/phonenumber_api.h"
 
@@ -272,4 +274,189 @@
                                  "en-US"));
 }
 
+// Tests that the phone numbers are correctly formatted for the Payment
+// Response.
+TEST(PhoneNumberUtilTest, FormatPhoneForResponse) {
+  EXPECT_EQ("+15151231234",
+            i18n::FormatPhoneForResponse("(515) 123-1234", "US"));
+  EXPECT_EQ("+15151231234",
+            i18n::FormatPhoneForResponse("(1) 515-123-1234", "US"));
+  EXPECT_EQ("+33142685300",
+            i18n::FormatPhoneForResponse("1 42 68 53 00", "FR"));
+}
+
+// Tests that the phone numbers are correctly formatted to display to the user.
+TEST(PhoneNumberUtilTest, FormatPhoneForDisplay) {
+  EXPECT_EQ("+1 515-123-1234", i18n::FormatPhoneForDisplay("5151231234", "US"));
+  EXPECT_EQ("+33 1 42 68 53 00",
+            i18n::FormatPhoneForDisplay("142685300", "FR"));
+}
+
+// Test for the GetFormattedPhoneNumberForDisplay method.
+struct PhoneNumberFormatCase {
+  PhoneNumberFormatCase(const char* phone,
+                        const char* country,
+                        const char* expected_format,
+                        const char* locale = "")
+      : phone(phone),
+        country(country),
+        expected_format(expected_format),
+        locale(locale) {}
+
+  const char* phone;
+  const char* country;
+  const char* expected_format;
+  const char* locale;
+};
+
+class GetFormattedPhoneNumberForDisplayTest
+    : public testing::TestWithParam<PhoneNumberFormatCase> {};
+
+TEST_P(GetFormattedPhoneNumberForDisplayTest,
+       GetFormattedPhoneNumberForDisplay) {
+  AutofillProfile profile;
+  profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
+                     base::UTF8ToUTF16(GetParam().phone));
+  profile.SetRawInfo(ADDRESS_HOME_COUNTRY,
+                     base::UTF8ToUTF16(GetParam().country));
+  EXPECT_EQ(GetParam().expected_format,
+            base::UTF16ToUTF8(i18n::GetFormattedPhoneNumberForDisplay(
+                profile, GetParam().locale)));
+}
+
+INSTANTIATE_TEST_CASE_P(
+    GetFormattedPhoneNumberForDisplay,
+    GetFormattedPhoneNumberForDisplayTest,
+    testing::Values(
+        //////////////////////////
+        // US phone in US.
+        //////////////////////////
+        // Formatted phone numbers.
+        PhoneNumberFormatCase("+1 415-555-5555", "US", "+1 415-555-5555"),
+        PhoneNumberFormatCase("1 415-555-5555", "US", "+1 415-555-5555"),
+        PhoneNumberFormatCase("415-555-5555", "US", "+1 415-555-5555"),
+        // Raw phone numbers.
+        PhoneNumberFormatCase("+14155555555", "US", "+1 415-555-5555"),
+        PhoneNumberFormatCase("14155555555", "US", "+1 415-555-5555"),
+        PhoneNumberFormatCase("4155555555", "US", "+1 415-555-5555"),
+
+        //////////////////////////
+        // US phone in CA.
+        //////////////////////////
+        // Formatted phone numbers.
+        PhoneNumberFormatCase("+1 415-555-5555", "CA", "+1 415-555-5555"),
+        PhoneNumberFormatCase("1 415-555-5555", "CA", "+1 415-555-5555"),
+        PhoneNumberFormatCase("415-555-5555", "CA", "+1 415-555-5555"),
+        // Raw phone numbers.
+        PhoneNumberFormatCase("+14155555555", "CA", "+1 415-555-5555"),
+        PhoneNumberFormatCase("14155555555", "CA", "+1 415-555-5555"),
+        PhoneNumberFormatCase("4155555555", "CA", "+1 415-555-5555"),
+
+        //////////////////////////
+        // US phone in AU.
+        //////////////////////////
+        // A US phone with the country code is correctly formatted as an US
+        // number.
+        PhoneNumberFormatCase("+1 415-555-5555", "AU", "+1 415-555-5555"),
+        PhoneNumberFormatCase("1 415-555-5555", "AU", "+1 415-555-5555"),
+        // Without a country code, the phone is formatted for the profile's
+        // country, even if it's invalid.
+        PhoneNumberFormatCase("415-555-5555", "AU", "+61 4155555555"),
+
+        //////////////////////////
+        // US phone in MX.
+        //////////////////////////
+        // A US phone with the country code is correctly formatted as an US
+        // number.
+        PhoneNumberFormatCase("+1 415-555-5555", "MX", "+1 415-555-5555"),
+        // "+52 1 415 555 5555" is a valid number for Mexico,
+        PhoneNumberFormatCase("1 415-555-5555", "MX", "+52 1 415 555 5555"),
+        // Without a country code, the phone is formatted for the profile's
+        // country.
+        PhoneNumberFormatCase("415-555-5555", "MX", "+52 415 555 5555"),
+
+        //////////////////////////
+        // AU phone in AU.
+        //////////////////////////
+        // Formatted phone numbers.
+        PhoneNumberFormatCase("+61 2 9374 4000", "AU", "+61 2 9374 4000"),
+        PhoneNumberFormatCase("61 2 9374 4000", "AU", "+61 2 9374 4000"),
+        PhoneNumberFormatCase("02 9374 4000", "AU", "+61 2 9374 4000"),
+        PhoneNumberFormatCase("2 9374 4000", "AU", "+61 2 9374 4000"),
+        // Raw phone numbers.
+        PhoneNumberFormatCase("+61293744000", "AU", "+61 2 9374 4000"),
+        PhoneNumberFormatCase("61293744000", "AU", "+61 2 9374 4000"),
+        PhoneNumberFormatCase("0293744000", "AU", "+61 2 9374 4000"),
+        PhoneNumberFormatCase("293744000", "AU", "+61 2 9374 4000"),
+
+        //////////////////////////
+        // AU phone in US.
+        //////////////////////////
+        // An AU phone with the country code is correctly formatted as an AU
+        // number.
+        PhoneNumberFormatCase("+61 2 9374 4000", "US", "+61 2 9374 4000"),
+        PhoneNumberFormatCase("61 2 9374 4000", "US", "+61 2 9374 4000"),
+        // Without a country code, the phone is formatted for the profile's
+        // country.
+        // This local AU number fits the length of a US number, so it's
+        // formatted for US.
+        PhoneNumberFormatCase("02 9374 4000", "US", "+1 029-374-4000"),
+        // This local AU number is formatted as an US number, even if it's
+        // invlaid.
+        PhoneNumberFormatCase("2 9374 4000", "US", "+1 293744000"),
+
+        //////////////////////////
+        // MX phone in MX.
+        //////////////////////////
+        // Formatted phone numbers.
+        PhoneNumberFormatCase("+52 55 5342 8400", "MX", "+52 55 5342 8400"),
+        PhoneNumberFormatCase("52 55 5342 8400", "MX", "+52 55 5342 8400"),
+        PhoneNumberFormatCase("55 5342 8400", "MX", "+52 55 5342 8400"),
+        // Raw phone numbers.
+        PhoneNumberFormatCase("+525553428400", "MX", "+52 55 5342 8400"),
+        PhoneNumberFormatCase("525553428400", "MX", "+52 55 5342 8400"),
+        PhoneNumberFormatCase("5553428400", "MX", "+52 55 5342 8400"),
+
+        //////////////////////////
+        // MX phone in US.
+        //////////////////////////
+        // A MX phone with the country code is correctly formatted as a MX
+        // number.
+        PhoneNumberFormatCase("+52 55 5342 8400", "US", "+52 55 5342 8400"),
+        PhoneNumberFormatCase("52 55 5342 8400", "US", "+52 55 5342 8400"),
+        // This local MX number fits the length of a US number, so it's
+        // formatted for US.
+        PhoneNumberFormatCase("55 5342 8400", "US", "+1 555-342-8400")));
+
+INSTANTIATE_TEST_CASE_P(
+    GetFormattedPhoneNumberForDisplay_EdgeCases,
+    GetFormattedPhoneNumberForDisplayTest,
+    testing::Values(
+        //////////////////////////
+        // No country.
+        //////////////////////////
+        // Fallback to locale if no country is set.
+        PhoneNumberFormatCase("52 55 5342 8400",
+                              "",
+                              "+52 55 5342 8400",
+                              "es_MX"),
+        PhoneNumberFormatCase("55 5342 8400", "", "+52 55 5342 8400", "es_MX"),
+        PhoneNumberFormatCase("55 5342 8400", "", "+1 555-342-8400", "en_US"),
+        PhoneNumberFormatCase("61 2 9374 4000", "", "+61 2 9374 4000", "en_AU"),
+        PhoneNumberFormatCase("02 9374 4000", "", "+61 2 9374 4000", "en_AU"),
+
+        //////////////////////////
+        // No country or locale.
+        //////////////////////////
+        // Format according to the country code.
+        PhoneNumberFormatCase("61 2 9374 4000", "", "+61 2 9374 4000"),
+        PhoneNumberFormatCase("52 55 5342 8400", "", "+52 55 5342 8400"),
+        PhoneNumberFormatCase("1 415 555 5555", "", "+1 415-555-5555"),
+        // If no country code is found, formats for US.
+        PhoneNumberFormatCase("02 9374 4000", "", "+1 029-374-4000"),
+        PhoneNumberFormatCase("2 9374 4000", "", "+1 293744000"),
+        PhoneNumberFormatCase("55 5342 8400", "", "+1 555-342-8400"),
+        PhoneNumberFormatCase("52 55 5342 8400", "", "+52 55 5342 8400"),
+        PhoneNumberFormatCase("415-555-5555", "", "+1 415-555-5555")));
+
 }  // namespace autofill
diff --git a/components/autofill/core/browser/test_address_normalizer.cc b/components/autofill/core/browser/test_address_normalizer.cc
new file mode 100644
index 0000000..1ec6324
--- /dev/null
+++ b/components/autofill/core/browser/test_address_normalizer.cc
@@ -0,0 +1,38 @@
+// 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/autofill/core/browser/test_address_normalizer.h"
+
+namespace autofill {
+
+bool TestAddressNormalizer::AreRulesLoadedForRegion(
+    const std::string& region_code) {
+  return true;
+}
+
+void TestAddressNormalizer::StartAddressNormalization(
+    const AutofillProfile& profile,
+    const std::string& region_code,
+    int timeout_seconds,
+    AddressNormalizer::Delegate* requester) {
+  if (instantaneous_normalization_) {
+    requester->OnAddressNormalized(profile);
+    return;
+  }
+
+  // Setup the necessary variables for the delayed normalization.
+  profile_ = profile;
+  requester_ = requester;
+}
+
+void TestAddressNormalizer::DelayNormalization() {
+  instantaneous_normalization_ = false;
+}
+
+void TestAddressNormalizer::CompleteAddressNormalization() {
+  DCHECK(instantaneous_normalization_ == false);
+  requester_->OnAddressNormalized(profile_);
+}
+
+}  // namespace autofill
diff --git a/components/autofill/core/browser/test_address_normalizer.h b/components/autofill/core/browser/test_address_normalizer.h
new file mode 100644
index 0000000..d9dbbd8
--- /dev/null
+++ b/components/autofill/core/browser/test_address_normalizer.h
@@ -0,0 +1,47 @@
+// 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_AUTOFILL_CORE_BROWSER_TEST_ADDRESS_NORMALIZER_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_ADDRESS_NORMALIZER_H_
+
+#include <string>
+
+#include "components/autofill/core/browser/address_normalizer.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+
+namespace autofill {
+
+// A simpler version of the address normalizer to be used in tests. Can be set
+// to normalize instantaneously or to wait for a call.
+class TestAddressNormalizer : public AddressNormalizer {
+ public:
+  TestAddressNormalizer() {}
+
+  void LoadRulesForRegion(const std::string& region_code) override {}
+
+  bool AreRulesLoadedForRegion(const std::string& region_code) override;
+
+  void StartAddressNormalization(
+      const AutofillProfile& profile,
+      const std::string& region_code,
+      int timeout_seconds,
+      AddressNormalizer::Delegate* requester) override;
+
+  void OnAddressValidationRulesLoaded(const std::string& region_code,
+                                      bool success) override {}
+
+  void DelayNormalization();
+
+  void CompleteAddressNormalization();
+
+ private:
+  AutofillProfile profile_;
+  AddressNormalizer::Delegate* requester_;
+
+  bool instantaneous_normalization_ = true;
+};
+
+}  // namespace autofill
+
+#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_ADDRESS_NORMALIZER_H_
diff --git a/components/content_settings/core/browser/content_settings_default_provider.cc b/components/content_settings/core/browser/content_settings_default_provider.cc
index 8636b48b..b2e8daf 100644
--- a/components/content_settings/core/browser/content_settings_default_provider.cc
+++ b/components/content_settings/core/browser/content_settings_default_provider.cc
@@ -193,6 +193,10 @@
                             IntToContentSetting(prefs_->GetInteger(
                                 GetPrefName(CONTENT_SETTINGS_TYPE_ADS))),
                             CONTENT_SETTING_NUM_SETTINGS);
+  UMA_HISTOGRAM_ENUMERATION("ContentSettings.DefaultSoundSetting",
+                            IntToContentSetting(prefs_->GetInteger(
+                                GetPrefName(CONTENT_SETTINGS_TYPE_SOUND))),
+                            CONTENT_SETTING_NUM_SETTINGS);
 #endif
   pref_change_registrar_.Init(prefs_);
   PrefChangeRegistrar::NamedChangeCallback callback = base::Bind(
diff --git a/components/crash/core/common/objc_zombie.mm b/components/crash/core/common/objc_zombie.mm
index ceb308f..244fecf 100644
--- a/components/crash/core/common/objc_zombie.mm
+++ b/components/crash/core/common/objc_zombie.mm
@@ -21,12 +21,6 @@
 #include "build/build_config.h"
 #include "components/crash/core/common/crash_keys.h"
 
-#if !defined(OS_IOS) && (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_6)
-// Apparently objc/runtime.h doesn't define this with the 10.6 SDK yet.
-// The docs say it exists since 10.6 however.
-OBJC_EXPORT void *objc_destructInstance(id obj);
-#endif
-
 // Deallocated objects are re-classed as |CrZombie|.  No superclass
 // because then the class would have to override many/most of the
 // inherited methods (|NSObject| is like a category magnet!).
diff --git a/components/cronet/PRESUBMIT.py b/components/cronet/PRESUBMIT.py
index 7c553d7..3265877c 100644
--- a/components/cronet/PRESUBMIT.py
+++ b/components/cronet/PRESUBMIT.py
@@ -8,6 +8,8 @@
 for more details about the presubmit API built into depot_tools.
 """
 
+import os
+
 def _PyLintChecks(input_api, output_api):
   pylint_checks = input_api.canned_checks.GetPylint(input_api, output_api,
           extra_paths_list=_GetPathsToPrepend(input_api), pylintrc='pylintrc')
@@ -73,6 +75,26 @@
       input_api, output_api, '.', [ r'^.+_unittest\.py$'])
 
 
+def _ChangeAffectsCronetForAndroid(change):
+  """ Returns |true| if the change may affect Cronet for Android. """
+
+  for affected_file in change.AffectedFiles():
+    path = affected_file.LocalPath()
+    if not path.startswith(os.path.join('components', 'cronet', 'ios')):
+      return True
+  return False
+
+
+def _ChangeAffectsCronetForIos(change):
+  """ Returns |true| if the change may affect Cronet for iOS. """
+
+  for affected_file in change.AffectedFiles():
+    path = affected_file.LocalPath()
+    if not path.startswith(os.path.join('components', 'cronet', 'android')):
+      return True
+  return False
+
+
 def CheckChangeOnUpload(input_api, output_api):
   results = []
   results.extend(_PyLintChecks(input_api, output_api))
@@ -91,9 +113,12 @@
   This hook adds an extra try bot to the CL description in order to run Cronet
   tests in addition to CQ try bots.
   """
+
+  try_bots = []
+  if _ChangeAffectsCronetForAndroid(change):
+    try_bots.append('master.tryserver.chromium.android:android_cronet_tester')
+  if _ChangeAffectsCronetForIos(change):
+    try_bots.append('master.tryserver.chromium.mac:ios-simulator-cronet')
+
   return output_api.EnsureCQIncludeTrybotsAreAdded(
-    cl,
-    [
-      'master.tryserver.chromium.android:android_cronet_tester',
-    ],
-    'Automatically added Cronet trybot to run tests on CQ.')
+    cl, try_bots, 'Automatically added Cronet trybots to run tests on CQ.')
diff --git a/components/download/content/internal/download_driver_impl.cc b/components/download/content/internal/download_driver_impl.cc
index db06cab9..2f598a9 100644
--- a/components/download/content/internal/download_driver_impl.cc
+++ b/components/download/content/internal/download_driver_impl.cc
@@ -91,6 +91,7 @@
          entry.response_headers->response_code() == net::HTTP_PARTIAL_CONTENT);
     entry.can_resume &= entry.response_headers->HasStrongValidators();
   }
+  entry.url_chain = item->GetUrlChain();
   return entry;
 }
 
diff --git a/components/download/content/internal/download_driver_impl_unittest.cc b/components/download/content/internal/download_driver_impl_unittest.cc
index bbc0169..9f465ca 100644
--- a/components/download/content/internal/download_driver_impl_unittest.cc
+++ b/components/download/content/internal/download_driver_impl_unittest.cc
@@ -15,6 +15,7 @@
 #include "content/public/test/fake_download_item.h"
 #include "content/public/test/mock_download_manager.h"
 #include "net/http/http_response_headers.h"
+#include "net/http/http_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -189,4 +190,26 @@
   EXPECT_NE(guids.end(), guids.find(item1.GetGuid()));
 }
 
+TEST_F(DownloadDriverImplTest, TestCreateDriverEntry) {
+  using DownloadState = content::DownloadItem::DownloadState;
+  content::FakeDownloadItem item;
+  const std::string kGuid("dummy guid");
+  const std::vector<GURL> kUrls = {GURL("http://www.example.com/foo.html"),
+                                   GURL("http://www.example.com/bar.html")};
+  scoped_refptr<net::HttpResponseHeaders> headers =
+      new net::HttpResponseHeaders("HTTP/1.1 201\n");
+
+  item.SetGuid(kGuid);
+  item.SetUrlChain(kUrls);
+  item.SetState(DownloadState::IN_PROGRESS);
+  item.SetResponseHeaders(headers);
+
+  DriverEntry entry = driver_->CreateDriverEntry(&item);
+
+  EXPECT_EQ(kGuid, entry.guid);
+  EXPECT_EQ(kUrls, entry.url_chain);
+  EXPECT_EQ(DriverEntry::State::IN_PROGRESS, entry.state);
+  EXPECT_EQ(headers, entry.response_headers);
+}
+
 }  // namespace download
diff --git a/components/download/internal/proto/entry.proto b/components/download/internal/proto/entry.proto
index 964176db..1591647 100644
--- a/components/download/internal/proto/entry.proto
+++ b/components/download/internal/proto/entry.proto
@@ -19,7 +19,8 @@
   TEST_2 = 2;
   TEST_3 = 3;
   OFFLINE_PAGE_PREFETCH = 4;
-  BOUNDARY = 5;
+  BACKGROUND_FETCH = 5;
+  BOUNDARY = 6;
 }
 
 // Stores the request params, internal state, metrics and metadata associated
diff --git a/components/download/internal/proto_conversions.cc b/components/download/internal/proto_conversions.cc
index 7badbc2..db28637 100644
--- a/components/download/internal/proto_conversions.cc
+++ b/components/download/internal/proto_conversions.cc
@@ -64,6 +64,8 @@
       return protodb::DownloadClient::TEST_3;
     case DownloadClient::OFFLINE_PAGE_PREFETCH:
       return protodb::DownloadClient::OFFLINE_PAGE_PREFETCH;
+    case DownloadClient::BACKGROUND_FETCH:
+      return protodb::DownloadClient::BACKGROUND_FETCH;
     case DownloadClient::BOUNDARY:
       return protodb::DownloadClient::BOUNDARY;
   }
@@ -85,6 +87,8 @@
       return DownloadClient::TEST_3;
     case protodb::DownloadClient::OFFLINE_PAGE_PREFETCH:
       return DownloadClient::OFFLINE_PAGE_PREFETCH;
+    case protodb::DownloadClient::BACKGROUND_FETCH:
+      return DownloadClient::BACKGROUND_FETCH;
     case protodb::DownloadClient::BOUNDARY:
       return DownloadClient::BOUNDARY;
   }
diff --git a/components/download/internal/stats.cc b/components/download/internal/stats.cc
index f6db72a..2c4f8b0 100644
--- a/components/download/internal/stats.cc
+++ b/components/download/internal/stats.cc
@@ -87,6 +87,8 @@
       return "__Test__";
     case DownloadClient::OFFLINE_PAGE_PREFETCH:
       return "OfflinePage";
+    case DownloadClient::BACKGROUND_FETCH:
+      return "BackgroundFetch";
     case DownloadClient::BOUNDARY:
       NOTREACHED();
       break;
diff --git a/components/download/public/clients.h b/components/download/public/clients.h
index 3939aea..8706f648 100644
--- a/components/download/public/clients.h
+++ b/components/download/public/clients.h
@@ -32,7 +32,9 @@
 
   OFFLINE_PAGE_PREFETCH = 1,
 
-  BOUNDARY = 2,
+  BACKGROUND_FETCH = 2,
+
+  BOUNDARY = 3,
 };
 
 using DownloadClientMap = std::map<DownloadClient, std::unique_ptr<Client>>;
diff --git a/components/error_page/common/localized_error.cc b/components/error_page/common/localized_error.cc
index aed848b..771de280 100644
--- a/components/error_page/common/localized_error.cc
+++ b/components/error_page/common/localized_error.cc
@@ -388,6 +388,14 @@
     },
 };
 
+const LocalizedErrorMap generic_4xx_5xx_error = {
+    0,
+    IDS_ERRORPAGES_HEADING_PAGE_NOT_WORKING,
+    IDS_ERRORPAGES_SUMMARY_CONTACT_SITE_OWNER,
+    SUGGEST_NONE,
+    SHOW_BUTTON_RELOAD,
+};
+
 const LocalizedErrorMap dns_probe_error_options[] = {
   {error_page::DNS_PROBE_POSSIBLE,
    IDS_ERRORPAGES_HEADING_NOT_AVAILABLE,
@@ -452,9 +460,12 @@
                                arraysize(net_error_options),
                                error_code);
   } else if (error_domain == Error::kHttpErrorDomain) {
-    return FindErrorMapInArray(http_error_options,
-                               arraysize(http_error_options),
-                               error_code);
+    const LocalizedErrorMap* map = FindErrorMapInArray(
+        http_error_options, arraysize(http_error_options), error_code);
+    // Handle miscellaneous 400/500 errors.
+    return !map && error_code >= 400 && error_code < 600
+               ? &generic_4xx_5xx_error
+               : map;
   } else if (error_domain == Error::kDnsProbeErrorDomain) {
     const LocalizedErrorMap* map =
         FindErrorMapInArray(dns_probe_error_options,
@@ -916,10 +927,6 @@
   summary->SetString(
       "msg", l10n_util::GetStringUTF16(options.summary_resource_id));
 
-  // Add a DNS definition string.
-  summary->SetString("dnsDefinition",
-      l10n_util::GetStringUTF16(IDS_ERRORPAGES_SUMMARY_DNS_DEFINITION));
-
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
 
   // Check if easter egg should be disabled.
diff --git a/components/error_page_strings.grdp b/components/error_page_strings.grdp
index 73459a2..8d5feb1 100644
--- a/components/error_page_strings.grdp
+++ b/components/error_page_strings.grdp
@@ -150,11 +150,8 @@
   <message name="IDS_ERRORPAGES_SUMMARY_CONNECTION_REFUSED" desc="Summary in the error page when we try and connect to a server, but the server doesn't let us.">
     <ph name="HOST_NAME">&lt;strong jscontent="hostName"&gt;&lt;/strong&gt;<ex>www.whatever.com</ex></ph> refused to connect.
   </message>
-  <message name="IDS_ERRORPAGES_SUMMARY_NAME_NOT_RESOLVED" desc="Summary in the error page when a dns look up fails. The 'abbr' tag is HTML mark up used to indicate that 'DNS address' is an abbreviation.">
-    <ph name="HOST_NAME">&lt;strong jscontent="hostName"&gt;&lt;/strong&gt;<ex>www.whatever.com</ex></ph>’s server <ph name="BEGIN_ABBR">&lt;abbr jsvalues="title:dnsDefinition"&gt;</ph>DNS address<ph name="END_ABBR">&lt;/abbr&gt;</ph> could not be found.
-  </message>
-  <message name="IDS_ERRORPAGES_SUMMARY_DNS_DEFINITION" desc="Definition of DNS that appears when hovering over the abbreviation">
-    DNS is the network service that translates a website’s name to its Internet address.
+  <message name="IDS_ERRORPAGES_SUMMARY_NAME_NOT_RESOLVED" desc="Summary in the error page when a dns look up fails.">
+    <ph name="HOST_NAME">&lt;strong jscontent="hostName"&gt;&lt;/strong&gt;<ex>www.whatever.com</ex></ph>’s server IP address could not be found.
   </message>
   <message name="IDS_ERRORPAGES_SUMMARY_ICANN_NAME_COLLISION" desc="Summary in the error page when a dns look up fails due to having contained 127.0.53.53.">
     This site on the company, organization or school intranet has the same URL as an external website.
@@ -221,7 +218,9 @@
   <message name="IDS_ERRORPAGES_HEADING_PAGE_NOT_WORKING" desc="Heading in the error page for HTTP 5xx errors, which are considered to be server side errors. Also used for bad responses.">
     This page isn’t working
   </message>
-
+  <message name="IDS_ERRORPAGES_SUMMARY_CONTACT_SITE_OWNER" desc="Generic suggestion for when the server returns a HTTP 4xx or 5xx error asking users to contact the site owner.">
+    If the problem continues, contact the site owner.
+  </message>
   <message name="IDS_ERRORPAGES_SUMMARY_WEBSITE_CANNOT_HANDLE_REQUEST" desc="Summary in the error page when the server returns a 501 or 505.">
     <ph name="HOST_NAME">&lt;strong jscontent="hostName"&gt;&lt;/strong&gt;<ex>www.whatever.com</ex></ph> is currently unable to handle this request.
   </message>
diff --git a/components/exo/keyboard.cc b/components/exo/keyboard.cc
index 35b827ce..9d348e0 100644
--- a/components/exo/keyboard.cc
+++ b/components/exo/keyboard.cc
@@ -24,6 +24,16 @@
 // Delay until a key state change expected to be acknowledged is expired.
 const int kExpirationDelayForPendingKeyAcksMs = 1000;
 
+// The accelerator keys reserved to be processed by chrome.
+const struct {
+  ui::KeyboardCode keycode;
+  int modifiers;
+} kReservedAccelerators[] = {
+    {ui::VKEY_SPACE, ui::EF_CONTROL_DOWN},
+    {ui::VKEY_SPACE, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN},
+    {ui::VKEY_F13, ui::EF_NONE},
+    {ui::VKEY_I, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN}};
+
 bool ProcessAccelerator(Surface* surface, const ui::KeyEvent* event) {
   views::Widget* widget =
       views::Widget::GetTopLevelWidgetForNativeView(surface->window());
@@ -100,6 +110,16 @@
   return false;
 }
 
+bool IsReservedAccelerator(const ui::KeyEvent* event) {
+  for (const auto& accelerator : kReservedAccelerators) {
+    if (event->flags() == accelerator.modifiers &&
+        event->key_code() == accelerator.keycode) {
+      return true;
+    }
+  }
+  return false;
+}
+
 }  // namespace
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -111,7 +131,7 @@
           kExpirationDelayForPendingKeyAcksMs)),
       weak_ptr_factory_(this) {
   auto* helper = WMHelper::GetInstance();
-  helper->AddPostTargetHandler(this);
+  AddEventHandler();
   helper->AddFocusObserver(this);
   helper->AddTabletModeObserver(this);
   helper->AddInputDeviceEventObserver(this);
@@ -124,8 +144,8 @@
   if (focus_)
     focus_->RemoveSurfaceObserver(this);
   auto* helper = WMHelper::GetInstance();
+  RemoveEventHandler();
   helper->RemoveFocusObserver(this);
-  helper->RemovePostTargetHandler(this);
   helper->RemoveTabletModeObserver(this);
   helper->RemoveInputDeviceEventObserver(this);
 }
@@ -153,7 +173,9 @@
 }
 
 void Keyboard::SetNeedKeyboardKeyAcks(bool need_acks) {
+  RemoveEventHandler();
   are_keyboard_key_acks_needed_ = need_acks;
+  AddEventHandler();
 }
 
 bool Keyboard::AreKeyboardKeyAcksNeeded() const {
@@ -174,15 +196,6 @@
 // ui::EventHandler overrides:
 
 void Keyboard::OnKeyEvent(ui::KeyEvent* event) {
-  // Pass accelerators to ShellSurfaceWidget before passing it to the delegate
-  // if ack key event is not needed.
-  if (!are_keyboard_key_acks_needed_) {
-    if (focus_ && ProcessAccelerator(focus_, event)) {
-      event->StopPropagation();
-      return;
-    }
-  }
-
   // These modifiers reflect what Wayland is aware of.  For example,
   // EF_SCROLL_LOCK_ON is missing because Wayland doesn't support scroll lock.
   const int kModifierMask = ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN |
@@ -206,7 +219,7 @@
       auto it =
           std::find(pressed_keys_.begin(), pressed_keys_.end(), event->code());
       if (it == pressed_keys_.end()) {
-        if (focus_ && !consumed_by_ime) {
+        if (focus_ && !consumed_by_ime && !IsReservedAccelerator(event)) {
           uint32_t serial = delegate_->OnKeyboardKey(event->time_stamp(),
                                                      event->code(), true);
           if (are_keyboard_key_acks_needed_) {
@@ -214,6 +227,7 @@
                 {serial,
                  {*event, base::TimeTicks::Now() +
                               expiration_delay_for_pending_key_acks_}});
+            event->SetHandled();
           }
         }
 
@@ -224,7 +238,7 @@
       auto it =
           std::find(pressed_keys_.begin(), pressed_keys_.end(), event->code());
       if (it != pressed_keys_.end()) {
-        if (focus_ && !consumed_by_ime) {
+        if (focus_ && !consumed_by_ime && !IsReservedAccelerator(event)) {
           uint32_t serial = delegate_->OnKeyboardKey(event->time_stamp(),
                                                      event->code(), false);
           if (are_keyboard_key_acks_needed_) {
@@ -232,6 +246,7 @@
                 {serial,
                  {*event, base::TimeTicks::Now() +
                               expiration_delay_for_pending_key_acks_}});
+            event->SetHandled();
           }
         }
 
@@ -365,4 +380,20 @@
       delay);
 }
 
+void Keyboard::AddEventHandler() {
+  auto* helper = WMHelper::GetInstance();
+  if (are_keyboard_key_acks_needed_)
+    helper->AddPreTargetHandler(this);
+  else
+    helper->AddPostTargetHandler(this);
+}
+
+void Keyboard::RemoveEventHandler() {
+  auto* helper = WMHelper::GetInstance();
+  if (are_keyboard_key_acks_needed_)
+    helper->RemovePreTargetHandler(this);
+  else
+    helper->RemovePostTargetHandler(this);
+}
+
 }  // namespace exo
diff --git a/components/exo/keyboard.h b/components/exo/keyboard.h
index 8b9d95b..c70795a 100644
--- a/components/exo/keyboard.h
+++ b/components/exo/keyboard.h
@@ -79,6 +79,14 @@
   // Schedule next call of ProcessExpiredPendingKeyAcks after |delay|
   void ScheduleProcessExpiredPendingKeyAcks(base::TimeDelta delay);
 
+  // Adds/Removes pre or post event handler depending on if key acks are needed.
+  // If key acks are needed, pre target handler will be added because this class
+  // wants to dispatch keys before they are consumed by Chrome. Otherwise, post
+  // target handler will be added because all accelerators should be handled by
+  // Chrome before they are dispatched by this class.
+  void AddEventHandler();
+  void RemoveEventHandler();
+
   // The delegate instance that all events except for events about device
   // configuration are dispatched to.
   KeyboardDelegate* const delegate_;
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc
index 506fee9e..15da1b1 100644
--- a/components/exo/shell_surface.cc
+++ b/components/exo/shell_surface.cc
@@ -63,25 +63,15 @@
 // fullscreen or pinned state.
 constexpr int kMaximizedOrFullscreenOrPinnedLockTimeoutMs = 100;
 
-// This is a struct for accelerator keys.
-struct Accelerator {
+// The accelerator keys used to close ShellSurfaces.
+const struct {
   ui::KeyboardCode keycode;
   int modifiers;
-};
-
-// The accelerator keys used to close ShellSurfaces.
-const Accelerator kCloseWindowAccelerators[] = {
+} kCloseWindowAccelerators[] = {
     {ui::VKEY_W, ui::EF_CONTROL_DOWN},
     {ui::VKEY_W, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN},
     {ui::VKEY_F4, ui::EF_ALT_DOWN}};
 
-// The accelerator keys reserved to be processed by the focus manager.
-const Accelerator kReservedAccelerators[] = {
-    {ui::VKEY_SPACE, ui::EF_CONTROL_DOWN},
-    {ui::VKEY_SPACE, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN},
-    {ui::VKEY_F13, ui::EF_NONE},
-    {ui::VKEY_I, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN}};
-
 class CustomFrameView : public views::NonClientFrameView {
  public:
   explicit CustomFrameView(views::Widget* widget) : widget_(widget) {}
@@ -206,18 +196,10 @@
   // Overridden from views::Widget
   void Close() override { shell_surface_->Close(); }
   void OnKeyEvent(ui::KeyEvent* event) override {
-    // TODO(hidehiko): Handle ESC + SHIFT + COMMAND accelerator key
-    // to escape pinned mode.
-    for (const auto& entry : kReservedAccelerators) {
-      // Handle only reserved accelerators.
-      if (event->flags() == entry.modifiers &&
-          event->key_code() == entry.keycode) {
-        if (GetFocusManager()->ProcessAccelerator(ui::Accelerator(*event)))
-          event->StopPropagation();
-      }
-    }
-    // Do not call Widget::OnKeyEvent that eats focus management keys (like the
-    // tab key) as well.
+    // Handle only accelerators. Do not call Widget::OnKeyEvent that eats focus
+    // management keys (like the tab key) as well.
+    if (GetFocusManager()->ProcessAccelerator(ui::Accelerator(*event)))
+      event->SetHandled();
   }
 
  private:
diff --git a/components/exo/wayland/BUILD.gn b/components/exo/wayland/BUILD.gn
index ef835a23..f381fd8 100644
--- a/components/exo/wayland/BUILD.gn
+++ b/components/exo/wayland/BUILD.gn
@@ -112,7 +112,13 @@
   ]
 }
 
-source_set("client_lib") {
+config("client_support_config") {
+  if (ozone_platform_gbm) {
+    defines = [ "USE_GBM" ]
+  }
+}
+
+source_set("client_support") {
   sources = [
     "clients/client_base.cc",
     "clients/client_base.h",
@@ -139,12 +145,11 @@
       ":libdrm",
       "//ui/gl:gl_config",
     ]
-    defines = [ "OZONE_PLATFORM_GBM" ]
-    deps += [
-      "//third_party/minigbm",
-      "//ui/ozone",
-    ]
+    deps += [ "//ui/ozone" ]
+    public_deps += [ "//third_party/minigbm" ]
   }
+
+  public_configs = [ ":client_support_config" ]
 }
 
 executable("wayland_rects_client") {
@@ -153,7 +158,7 @@
   ]
 
   deps = [
-    ":client_lib",
+    ":client_support",
     "//base",
     "//build/config:exe_and_shlib_deps",
     "//skia",
@@ -169,7 +174,7 @@
       ":libdrm",
       "//ui/gl:gl_config",
     ]
-    defines = [ "OZONE_PLATFORM_GBM" ]
+    defines = [ "USE_GBM" ]
     deps += [ "//third_party/minigbm" ]
   }
 }
@@ -181,7 +186,7 @@
   ]
 
   deps = [
-    ":client_lib",
+    ":client_support",
     "//base",
     "//skia",
     "//third_party/wayland:wayland_client",
@@ -196,8 +201,6 @@
       ":libdrm",
       "//ui/gl:gl_config",
     ]
-    defines = [ "OZONE_PLATFORM_GBM" ]
-    deps += [ "//third_party/minigbm" ]
   }
 }
 
@@ -206,7 +209,7 @@
     "clients/simple_main.cc",
   ]
   deps = [
-    ":client_lib",
+    ":client_support",
     ":simple",
     "//base",
     "//build/config:exe_and_shlib_deps",
@@ -219,7 +222,7 @@
   ]
 
   deps = [
-    ":client_lib",
+    ":client_support",
     "//base",
     "//build/config:exe_and_shlib_deps",
     "//skia",
@@ -251,7 +254,7 @@
   ]
 
   deps = [
-    ":client_lib",
+    ":client_support",
     ":simple",
     ":wayland",
     "//ash:test_support_without_content",
@@ -276,18 +279,6 @@
     "//ash/resources:ash_test_resources_100_percent",
     "//ash/resources:ash_test_resources_200_percent",
   ]
-
-  if (ozone_platform_gbm) {
-    configs += [
-      "//components/exo/wayland:libdrm",
-      "//ui/gl:gl_config",
-    ]
-    defines = [ "OZONE_PLATFORM_GBM" ]
-    deps += [
-      "//third_party/minigbm",
-      "//ui/ozone",
-    ]
-  }
 }
 
 if (ozone_platform_gbm) {
@@ -297,7 +288,7 @@
     ]
 
     deps = [
-      ":client_lib",
+      ":client_support",
       "//base",
       "//skia",
       "//third_party/wayland:wayland_client",
@@ -310,7 +301,6 @@
       ":libdrm",
       "//ui/gl:gl_config",
     ]
-    defines = [ "OZONE_PLATFORM_GBM" ]
     deps += [ "//third_party/minigbm" ]
   }
 }
diff --git a/components/exo/wayland/clients/client_base.cc b/components/exo/wayland/clients/client_base.cc
index 9586167..091dedc8 100644
--- a/components/exo/wayland/clients/client_base.cc
+++ b/components/exo/wayland/clients/client_base.cc
@@ -34,7 +34,7 @@
 #include "ui/gl/gl_surface_egl.h"
 #include "ui/gl/init/gl_factory.h"
 
-#if defined(OZONE_PLATFORM_GBM)
+#if defined(USE_GBM)
 #include <drm_fourcc.h>
 #include <gbm.h>
 #include <xf86drm.h>
@@ -72,12 +72,12 @@
 // Buffer format.
 const int32_t kShmFormat = WL_SHM_FORMAT_ARGB8888;
 const SkColorType kColorType = kBGRA_8888_SkColorType;
-#if defined(OZONE_PLATFORM_GBM)
+#if defined(USE_GBM)
 const GrPixelConfig kGrPixelConfig = kBGRA_8888_GrPixelConfig;
 #endif
 const size_t kBytesPerPixel = 4;
 
-#if defined(OZONE_PLATFORM_GBM)
+#if defined(USE_GBM)
 // DRI render node path template.
 const char kDriRenderNodeTemplate[] = "/dev/dri/renderD%u";
 #endif
@@ -125,7 +125,7 @@
   buffer->busy = false;
 }
 
-#if defined(OZONE_PLATFORM_GBM)
+#if defined(USE_GBM)
 const GrGLInterface* GrGLCreateNativeInterface() {
   return GrGLAssembleInterface(nullptr, [](void* ctx, const char name[]) {
     return eglGetProcAddress(name);
@@ -143,7 +143,7 @@
 // ClientBase::InitParams, public:
 
 ClientBase::InitParams::InitParams() {
-#if defined(OZONE_PLATFORM_GBM)
+#if defined(USE_GBM)
   drm_format = DRM_FORMAT_ABGR8888;
   bo_usage = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING | GBM_BO_USE_TEXTURING;
 #endif
@@ -273,7 +273,7 @@
     return false;
   }
 
-#if defined(OZONE_PLATFORM_GBM)
+#if defined(USE_GBM)
   sk_sp<const GrGLInterface> native_interface;
   if (params.use_drm) {
     // Number of files to look for when discovering DRM devices.
@@ -462,7 +462,7 @@
     int32_t drm_format,
     int32_t bo_usage) {
   std::unique_ptr<Buffer> buffer;
-#if defined(OZONE_PLATFORM_GBM)
+#if defined(USE_GBM)
   if (device_) {
     buffer = std::make_unique<Buffer>();
     buffer->bo.reset(gbm_bo_create(device_.get(), size.width(), size.height(),
diff --git a/components/exo/wayland/clients/client_base.h b/components/exo/wayland/clients/client_base.h
index 74135ce6..8b525f3f2 100644
--- a/components/exo/wayland/clients/client_base.h
+++ b/components/exo/wayland/clients/client_base.h
@@ -18,6 +18,10 @@
 #include "ui/gl/gl_surface.h"
 #include "ui/gl/scoped_make_current.h"
 
+#if defined(USE_GBM)
+#include <gbm.h>
+#endif
+
 namespace base {
 class CommandLine;
 class MessageLoopForUI;
@@ -69,7 +73,7 @@
 
     std::unique_ptr<wl_buffer> buffer;
     bool busy = false;
-#if defined(OZONE_PLATFORM_GBM)
+#if defined(USE_GBM)
     std::unique_ptr<gbm_bo> bo;
     std::unique_ptr<ScopedEglImage> egl_image;
     std::unique_ptr<ScopedEglSync> egl_sync;
@@ -104,7 +108,7 @@
   std::unique_ptr<wl_surface> surface_;
   std::unique_ptr<wl_shell_surface> shell_surface_;
   Globals globals_;
-#if defined(OZONE_PLATFORM_GBM)
+#if defined(USE_GBM)
   std::unique_ptr<base::MessageLoopForUI> ui_loop_;
   base::ScopedFD drm_fd_;
   std::unique_ptr<gbm_device> device_;
diff --git a/components/exo/wayland/clients/client_helper.cc b/components/exo/wayland/clients/client_helper.cc
index 33b3301..8d648968 100644
--- a/components/exo/wayland/clients/client_helper.cc
+++ b/components/exo/wayland/clients/client_helper.cc
@@ -12,7 +12,7 @@
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_enums.h"
 
-#if defined(OZONE_PLATFORM_GBM)
+#if defined(USE_GBM)
 #include <gbm.h>
 #endif
 
@@ -48,7 +48,7 @@
 DEFAULT_DELETER(zwp_linux_buffer_params_v1, zwp_linux_buffer_params_v1_destroy)
 DEFAULT_DELETER(zwp_linux_dmabuf_v1, zwp_linux_dmabuf_v1_destroy)
 
-#if defined(OZONE_PLATFORM_GBM)
+#if defined(USE_GBM)
 DEFAULT_DELETER(gbm_bo, gbm_bo_destroy)
 DEFAULT_DELETER(gbm_device, gbm_device_destroy)
 #endif
@@ -57,7 +57,7 @@
 namespace wayland {
 namespace clients {
 
-#if defined(OZONE_PLATFORM_GBM)
+#if defined(USE_GBM)
 GLuint DeleteTextureTraits::InvalidValue() {
   return 0;
 }
diff --git a/components/exo/wayland/clients/client_helper.h b/components/exo/wayland/clients/client_helper.h
index 4ed8743a..80049c5 100644
--- a/components/exo/wayland/clients/client_helper.h
+++ b/components/exo/wayland/clients/client_helper.h
@@ -15,7 +15,7 @@
 #include "base/scoped_generic.h"
 #include "components/exo/wayland/aura-shell-client-protocol.h"
 
-#if defined(OZONE_PLATFORM_GBM)
+#if defined(USE_GBM)
 #include <gbm.h>
 #endif
 
@@ -50,7 +50,7 @@
 DEFAULT_DELETER_FDECL(zwp_linux_buffer_params_v1)
 DEFAULT_DELETER_FDECL(zwp_linux_dmabuf_v1)
 
-#if defined(OZONE_PLATFORM_GBM)
+#if defined(USE_GBM)
 DEFAULT_DELETER_FDECL(gbm_bo)
 DEFAULT_DELETER_FDECL(gbm_device)
 #endif
@@ -59,7 +59,7 @@
 namespace wayland {
 namespace clients {
 
-#if defined(OZONE_PLATFORM_GBM)
+#if defined(USE_GBM)
 struct DeleteTextureTraits {
   static unsigned InvalidValue();
   static void Free(unsigned texture);
diff --git a/components/exo/wayland/clients/rects.cc b/components/exo/wayland/clients/rects.cc
index 4071936..954bcca 100644
--- a/components/exo/wayland/clients/rects.cc
+++ b/components/exo/wayland/clients/rects.cc
@@ -390,7 +390,7 @@
       if (gr_context) {
         gr_context->flush();
 
-#if defined(OZONE_PLATFORM_GBM)
+#if defined(USE_GBM)
         if (egl_sync_type_) {
           buffer->egl_sync.reset(new ScopedEglSync(eglCreateSyncKHR(
               eglGetCurrentDisplay(), egl_sync_type_, nullptr)));
@@ -423,7 +423,7 @@
                         surface_size_.height());
       wl_surface_attach(surface, frame->buffer->buffer.get(), 0, 0);
 
-#if defined(OZONE_PLATFORM_GBM)
+#if defined(USE_GBM)
       if (frame->buffer->egl_sync) {
         eglClientWaitSyncKHR(eglGetCurrentDisplay(),
                              frame->buffer->egl_sync->get(),
diff --git a/components/exo/wayland/clients/test/wayland_client_test.h b/components/exo/wayland/clients/test/wayland_client_test.h
index 449d87e1..ba58cffc 100644
--- a/components/exo/wayland/clients/test/wayland_client_test.h
+++ b/components/exo/wayland/clients/test/wayland_client_test.h
@@ -5,6 +5,8 @@
 #ifndef COMPONENT_EXO_WAYLAND_CLIENTS_TEST_WAYLAND_CLIENT_TEST_H_
 #define COMPONENT_EXO_WAYLAND_CLIENTS_TEST_WAYLAND_CLIENT_TEST_H_
 
+#include <memory>
+
 #include "base/macros.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/components/font_service/manifest.json b/components/font_service/manifest.json
index adc052b..2fd8207 100644
--- a/components/font_service/manifest.json
+++ b/components/font_service/manifest.json
@@ -1,6 +1,7 @@
 {
   "name": "font_service",
   "display_name": "Font Service",
+  "sandbox_type": "none",
   "interface_provider_specs": {
     "service_manager:connector": {
       "provides": {
diff --git a/components/font_service/public/interfaces/BUILD.gn b/components/font_service/public/interfaces/BUILD.gn
index 12efaaf..7e06c372 100644
--- a/components/font_service/public/interfaces/BUILD.gn
+++ b/components/font_service/public/interfaces/BUILD.gn
@@ -6,6 +6,7 @@
 
 mojom("interfaces") {
   sources = [
+    "constants.mojom",
     "font_service.mojom",
   ]
 
diff --git a/components/font_service/public/interfaces/constants.mojom b/components/font_service/public/interfaces/constants.mojom
new file mode 100644
index 0000000..0875747
--- /dev/null
+++ b/components/font_service/public/interfaces/constants.mojom
@@ -0,0 +1,7 @@
+// 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 font_service.mojom;
+
+const string kServiceName = "font_service";
diff --git a/components/metrics/call_stack_profile_metrics_provider.cc b/components/metrics/call_stack_profile_metrics_provider.cc
index cf859488..9e34470 100644
--- a/components/metrics/call_stack_profile_metrics_provider.cc
+++ b/components/metrics/call_stack_profile_metrics_provider.cc
@@ -469,10 +469,16 @@
       return UI_THREAD;
     case CallStackProfileParams::FILE_THREAD:
       return FILE_THREAD;
+    case CallStackProfileParams::FILE_USER_BLOCKING_THREAD:
+      return FILE_USER_BLOCKING_THREAD;
     case CallStackProfileParams::PROCESS_LAUNCHER_THREAD:
       return PROCESS_LAUNCHER_THREAD;
+    case CallStackProfileParams::CACHE_THREAD:
+      return CACHE_THREAD;
     case CallStackProfileParams::IO_THREAD:
       return IO_THREAD;
+    case CallStackProfileParams::DB_THREAD:
+      return DB_THREAD;
     case CallStackProfileParams::GPU_MAIN_THREAD:
       return GPU_MAIN_THREAD;
     case CallStackProfileParams::RENDER_THREAD:
diff --git a/components/metrics/call_stack_profile_params.h b/components/metrics/call_stack_profile_params.h
index c16e6ac..fad2116 100644
--- a/components/metrics/call_stack_profile_params.h
+++ b/components/metrics/call_stack_profile_params.h
@@ -31,8 +31,11 @@
     // Browser process threads, some of which occur in other processes as well.
     UI_THREAD,
     FILE_THREAD,
+    FILE_USER_BLOCKING_THREAD,
     PROCESS_LAUNCHER_THREAD,
+    CACHE_THREAD,
     IO_THREAD,
+    DB_THREAD,
 
     // GPU process thread.
     GPU_MAIN_THREAD,
diff --git a/components/metrics/file_metrics_provider.cc b/components/metrics/file_metrics_provider.cc
index 4ed7053..619cba7 100644
--- a/components/metrics/file_metrics_provider.cc
+++ b/components/metrics/file_metrics_provider.cc
@@ -5,6 +5,7 @@
 #include "components/metrics/file_metrics_provider.h"
 
 #include "base/command_line.h"
+#include "base/containers/flat_map.h"
 #include "base/files/file.h"
 #include "base/files/file_enumerator.h"
 #include "base/files/file_util.h"
@@ -114,8 +115,23 @@
 // This structure stores all the information about the sources being monitored
 // and their current reporting state.
 struct FileMetricsProvider::SourceInfo {
-  SourceInfo(SourceType source_type, SourceAssociation source_association)
-      : type(source_type), association(source_association) {}
+  SourceInfo(const Params& params)
+      : type(params.type),
+        association(params.association),
+        prefs_key(params.prefs_key),
+        filter(params.filter) {
+    switch (type) {
+      case SOURCE_HISTOGRAMS_ACTIVE_FILE:
+        DCHECK(prefs_key.empty());
+      // fall through
+      case SOURCE_HISTOGRAMS_ATOMIC_FILE:
+        path = params.path;
+        break;
+      case SOURCE_HISTOGRAMS_ATOMIC_DIR:
+        directory = params.path;
+        break;
+    }
+  }
   ~SourceInfo() {}
 
   // How to access this source (file/dir, atomic/active).
@@ -135,6 +151,9 @@
   // Name used inside prefs to persistent metadata.
   std::string prefs_key;
 
+  // The filter callback for determining what to do with found files.
+  FilterCallback filter;
+
   // The last-seen time of this source to detect change.
   base::Time last_seen;
 
@@ -149,6 +168,14 @@
   DISALLOW_COPY_AND_ASSIGN(SourceInfo);
 };
 
+FileMetricsProvider::Params::Params(const base::FilePath& path,
+                                    SourceType type,
+                                    SourceAssociation association,
+                                    base::StringPiece prefs_key)
+    : path(path), type(type), association(association), prefs_key(prefs_key) {}
+
+FileMetricsProvider::Params::~Params() {}
+
 FileMetricsProvider::FileMetricsProvider(PrefService* local_state)
     : task_runner_(CreateBackgroundTaskRunner()),
       pref_service_(local_state),
@@ -159,39 +186,23 @@
 
 FileMetricsProvider::~FileMetricsProvider() {}
 
-void FileMetricsProvider::RegisterSource(const base::FilePath& path,
-                                         SourceType type,
-                                         SourceAssociation source_association,
-                                         const base::StringPiece prefs_key) {
+void FileMetricsProvider::RegisterSource(const Params& params) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Ensure that kSourceOptions has been filled for this type.
-  DCHECK_GT(arraysize(kSourceOptions), static_cast<size_t>(type));
+  DCHECK_GT(arraysize(kSourceOptions), static_cast<size_t>(params.type));
 
-  std::unique_ptr<SourceInfo> source(new SourceInfo(type, source_association));
-  source->prefs_key = prefs_key.as_string();
-
-  switch (source->type) {
-    case SOURCE_HISTOGRAMS_ACTIVE_FILE:
-      DCHECK(prefs_key.empty());
-    // fall through
-    case SOURCE_HISTOGRAMS_ATOMIC_FILE:
-      source->path = path;
-      break;
-    case SOURCE_HISTOGRAMS_ATOMIC_DIR:
-      source->directory = path;
-      break;
-  }
+  std::unique_ptr<SourceInfo> source(new SourceInfo(params));
 
   // |prefs_key| may be empty if the caller does not wish to persist the
   // state across instances of the program.
-  if (pref_service_ && !prefs_key.empty()) {
+  if (pref_service_ && !params.prefs_key.empty()) {
     source->last_seen = base::Time::FromInternalValue(
         pref_service_->GetInt64(metrics::prefs::kMetricsLastSeenPrefix +
                                 source->prefs_key));
   }
 
-  switch (source_association) {
+  switch (params.association) {
     case ASSOCIATE_CURRENT_RUN:
     case ASSOCIATE_INTERNAL_PROFILE:
       sources_to_check_.push_back(std::move(source));
@@ -214,21 +225,26 @@
 // static
 void FileMetricsProvider::SetTaskRunnerForTesting(
     const scoped_refptr<base::TaskRunner>& task_runner) {
-  DCHECK(!g_task_runner_for_testing);
+  DCHECK(!g_task_runner_for_testing || !task_runner);
   g_task_runner_for_testing = task_runner.get();
 }
 
 // static
+void FileMetricsProvider::RecordAccessResult(AccessResult result) {
+  UMA_HISTOGRAM_ENUMERATION("UMA.FileMetricsProvider.AccessResult", result,
+                            ACCESS_RESULT_MAX);
+}
+
+// static
 bool FileMetricsProvider::LocateNextFileInDirectory(SourceInfo* source) {
   DCHECK_EQ(SOURCE_HISTOGRAMS_ATOMIC_DIR, source->type);
   DCHECK(!source->directory.empty());
 
-  // Open the directory and find all the files, remembering the oldest that
-  // has not been read. They can be removed and/or ignored if they're older
-  // than the last-check time.
-  base::Time oldest_file_time = base::Time::Now();
-  base::FilePath oldest_file_path;
+  // Open the directory and find all the files, remembering the last-modified
+  // time of each.
+  base::flat_map<base::Time, base::FilePath> found_files;
   base::FilePath file_path;
+  base::Time now_time = base::Time::Now();
   int file_count = 0;
   int delete_count = 0;
   base::FileEnumerator file_iter(source->directory, /*recursive=*/false,
@@ -258,11 +274,9 @@
     // Process real files.
     base::Time modified = file_info.GetLastModifiedTime();
     if (modified > source->last_seen) {
-      // This file hasn't been read. Remember it if it is older than others.
-      if (modified < oldest_file_time) {
-        oldest_file_path = std::move(file_path);
-        oldest_file_time = modified;
-      }
+      // This file hasn't been read. Remember it (unless it's from the future).
+      if (modified <= now_time)
+        found_files.emplace(modified, std::move(file_path));
       ++file_count;
     } else {
       // This file has been read. Try to delete it. Ignore any errors because
@@ -280,14 +294,22 @@
   UMA_HISTOGRAM_COUNTS_100("UMA.FileMetricsProvider.DeletedFiles",
                            delete_count);
 
-  // Stop now if there are no files to read.
-  if (oldest_file_path.empty())
-    return false;
+  // Filter files from the front until one is found for processing.
+  while (!found_files.empty()) {
+    base::FilePath& path = found_files.begin()->second;
+    AccessResult result = HandleFilterSource(source, path);
+    if (result == ACCESS_RESULT_SUCCESS) {
+      source->path = std::move(path);
+      return true;
+    }
 
-  // Set the active file to be the oldest modified file that has not yet
-  // been read.
-  source->path = std::move(oldest_file_path);
-  return true;
+    // Record the result. Success will be recorded by the caller.
+    RecordAccessResult(result);
+    found_files.erase(found_files.begin());
+  }
+
+  // No files to read.
+  return false;
 }
 
 // static
@@ -325,8 +347,7 @@
     // Some results are not reported in order to keep the dashboard clean.
     if (result != ACCESS_RESULT_DOESNT_EXIST &&
         result != ACCESS_RESULT_NOT_MODIFIED) {
-      UMA_HISTOGRAM_ENUMERATION(
-          "UMA.FileMetricsProvider.AccessResult", result, ACCESS_RESULT_MAX);
+      RecordAccessResult(result);
     }
 
     // Metrics associated with internal profiles have to be fetched directly
@@ -371,6 +392,13 @@
   if (source->last_seen >= info.last_modified)
     return ACCESS_RESULT_NOT_MODIFIED;
 
+  // Non-directory files still need to be filtered.
+  if (source->directory.empty()) {
+    AccessResult result = HandleFilterSource(source, source->path);
+    if (result != ACCESS_RESULT_SUCCESS)
+      return result;
+  }
+
   // A new file of metrics has been found.
   base::File file(source->path, kSourceOptions[source->type].file_open_flags);
   if (!file.IsValid())
@@ -458,6 +486,48 @@
            << source->path.value();
 }
 
+FileMetricsProvider::AccessResult FileMetricsProvider::HandleFilterSource(
+    SourceInfo* source,
+    const base::FilePath& path) {
+  if (!source->filter)
+    return ACCESS_RESULT_SUCCESS;
+
+  // Alternatively, pass a Params object to the filter like what was originally
+  // used to configure the source.
+  // Params params(path, source->type, source->association, source->prefs_key);
+  switch (source->filter.Run(path)) {
+    case FILTER_PROCESS_FILE:
+      // Process the file.
+      return ACCESS_RESULT_SUCCESS;
+
+    case FILTER_TRY_LATER: {
+      // Touch the file with the current timestamp making it (presumably) the
+      // newest file in the directory.
+      base::Time now = base::Time::Now();
+      base::TouchFile(path, /*accessed=*/now, /*modified=*/now);
+      return ACCESS_RESULT_FILTER_TRY_LATER;
+    }
+
+    case FILTER_SKIP_FILE:
+      switch (source->type) {
+        case SOURCE_HISTOGRAMS_ATOMIC_FILE:
+        case SOURCE_HISTOGRAMS_ATOMIC_DIR:
+          // Only "atomic" files are deleted (best-effort).
+          DeleteFileWhenPossible(path);
+          break;
+        case SOURCE_HISTOGRAMS_ACTIVE_FILE:
+          // File will presumably get modified elsewhere and thus tried again.
+          break;
+      }
+      return ACCESS_RESULT_FILTER_SKIP_FILE;
+  }
+
+  // Code never gets here but some compilers don't realize that and so complain
+  // that "not all control paths return a value".
+  NOTREACHED();
+  return ACCESS_RESULT_SUCCESS;
+}
+
 void FileMetricsProvider::ScheduleSourcesCheck() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (sources_to_check_.empty())
diff --git a/components/metrics/file_metrics_provider.h b/components/metrics/file_metrics_provider.h
index 0581e99..ba14892 100644
--- a/components/metrics/file_metrics_provider.h
+++ b/components/metrics/file_metrics_provider.h
@@ -9,7 +9,7 @@
 #include <memory>
 #include <string>
 
-#include "base/callback.h"
+#include "base/callback_forward.h"
 #include "base/files/file_path.h"
 #include "base/gtest_prod_util.h"
 #include "base/memory/weak_ptr.h"
@@ -34,6 +34,8 @@
 class FileMetricsProvider : public MetricsProvider,
                             public base::StatisticsRecorder::HistogramProvider {
  public:
+  struct Params;
+
   enum SourceType {
     // "Atomic" files are a collection of histograms that are written
     // completely in a single atomic operation (typically a write followed
@@ -97,6 +99,51 @@
     ASSOCIATE_INTERNAL_PROFILE_OR_PREVIOUS_RUN,
   };
 
+  enum FilterAction {
+    // Process this file normally.
+    FILTER_PROCESS_FILE,
+
+    // Try again. This could happen within milliseconds or minutes but no other
+    // files from the same source will get processed in between. The process
+    // must have permission to "touch" the file and alter its last-modified
+    // time because files are always processed in order of those stamps.
+    FILTER_TRY_LATER,
+
+    // Skip this file. This file will not be processed until it has changed
+    // (i.e. had its last-modifided time updated). If it is "atomic", an
+    // attempt will be made to delete it.
+    FILTER_SKIP_FILE,
+  };
+
+  // A "filter" can be defined to determine what to do on a per-file basis.
+  // This is called only after a file has been found to be the next one to
+  // be processed so it's okay if filter calls are relatively expensive.
+  // Calls are made on a background thread of low-priority and capable of
+  // doing I/O.
+  using FilterCallback =
+      base::RepeatingCallback<FilterAction(const base::FilePath& path)>;
+
+  // Parameters for RegisterSource, defined as a structure to allow new
+  // ones to be added (with default values) that doesn't require changes
+  // to all call sites.
+  struct Params {
+    Params(const base::FilePath& path,
+           SourceType type,
+           SourceAssociation association,
+           base::StringPiece prefs_key = base::StringPiece());
+
+    ~Params();
+
+    // The standard parameters, set during construction.
+    const base::FilePath path;
+    const SourceType type;
+    const SourceAssociation association;
+    const base::StringPiece prefs_key;
+
+    // Other parameters that can be set after construction.
+    FilterCallback filter;
+  };
+
   explicit FileMetricsProvider(PrefService* local_state);
   ~FileMetricsProvider() override;
 
@@ -107,10 +154,7 @@
   // necessary keys in advance. Set |prefs_key| empty (nullptr will work) if
   // no persistence is required. ACTIVE files shouldn't have a pref key as
   // they update internal state about what has been previously sent.
-  void RegisterSource(const base::FilePath& path,
-                      SourceType type,
-                      SourceAssociation source_association,
-                      const base::StringPiece prefs_key);
+  void RegisterSource(const Params& params);
 
   // Registers all necessary preferences for maintaining persistent state
   // about a monitored file across process restarts. The |prefs_key| is
@@ -151,6 +195,12 @@
     // File contents were internally deleted.
     ACCESS_RESULT_MEMORY_DELETED,
 
+    // File is scheduled to be tried again later.
+    ACCESS_RESULT_FILTER_TRY_LATER,
+
+    // The file was skipped according to filtering rules.
+    ACCESS_RESULT_FILTER_SKIP_FILE,
+
     ACCESS_RESULT_MAX
   };
 
@@ -159,6 +209,9 @@
   struct SourceInfo;
   using SourceInfoList = std::list<std::unique_ptr<SourceInfo>>;
 
+  // Records an access result in a histogram.
+  static void RecordAccessResult(AccessResult result);
+
   // Looks for the next file to read within a directory. Returns true if a
   // file was found. This is part of CheckAndMapNewMetricSourcesOnTaskRunner
   // and so runs on an thread capable of I/O. The |source| structure will
@@ -183,6 +236,10 @@
       base::HistogramSnapshotManager* snapshot_manager,
       SourceInfo* source);
 
+  // Calls source filter (if any) and returns the desired action.
+  static AccessResult HandleFilterSource(SourceInfo* source,
+                                         const base::FilePath& path);
+
   // Creates a task to check all monitored sources for updates.
   void ScheduleSourcesCheck();
 
diff --git a/components/metrics/file_metrics_provider_unittest.cc b/components/metrics/file_metrics_provider_unittest.cc
index b208198..5072064 100644
--- a/components/metrics/file_metrics_provider_unittest.cc
+++ b/components/metrics/file_metrics_provider_unittest.cc
@@ -79,6 +79,8 @@
   ~FileMetricsProviderTest() override {
     // Clear out any final remaining tasks.
     task_runner_->RunUntilIdle();
+    FileMetricsProvider::SetTaskRunnerForTesting(nullptr);
+    DCHECK_EQ(0U, filter_actions_remaining_);
     // If a global histogram allocator exists at this point then it likely
     // acquired histograms that will continue to point to the released
     // memory and potentially cause use-after-free memory corruption.
@@ -204,9 +206,25 @@
     return created_histograms_[index];
   }
 
+  void SetFilterActions(FileMetricsProvider::Params* params,
+                        const FileMetricsProvider::FilterAction* actions,
+                        size_t count) {
+    filter_actions_ = actions;
+    filter_actions_remaining_ = count;
+    params->filter = base::Bind(&FileMetricsProviderTest::FilterSourcePath,
+                                base::Unretained(this));
+  }
+
   const bool create_large_files_;
 
  private:
+  FileMetricsProvider::FilterAction FilterSourcePath(
+      const base::FilePath& path) {
+    DCHECK_LT(0U, filter_actions_remaining_);
+    --filter_actions_remaining_;
+    return *filter_actions_++;
+  }
+
   scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
   base::ThreadTaskRunnerHandle thread_task_runner_handle_;
 
@@ -216,6 +234,9 @@
   std::unique_ptr<FileMetricsProvider> provider_;
   base::HistogramBase* created_histograms_[kMaxCreateHistograms];
 
+  const FileMetricsProvider::FilterAction* filter_actions_ = nullptr;
+  size_t filter_actions_remaining_ = 0;
+
   DISALLOW_COPY_AND_ASSIGN(FileMetricsProviderTest);
 };
 
@@ -235,10 +256,9 @@
   base::TouchFile(metrics_file(), metrics_time, metrics_time);
 
   // Register the file and allow the "checker" task to run.
-  provider()->RegisterSource(metrics_file(),
-                             FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_FILE,
-                             FileMetricsProvider::ASSOCIATE_CURRENT_RUN,
-                             kMetricsName);
+  provider()->RegisterSource(FileMetricsProvider::Params(
+      metrics_file(), FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_FILE,
+      FileMetricsProvider::ASSOCIATE_CURRENT_RUN, kMetricsName));
 
   // Record embedded snapshots via snapshot-manager.
   OnDidCreateMetricsLog();
@@ -274,6 +294,75 @@
   EXPECT_FALSE(base::PathExists(metrics_file()));
 }
 
+TEST_P(FileMetricsProviderTest, FilterDelaysFile) {
+  ASSERT_FALSE(PathExists(metrics_file()));
+
+  base::Time now_time = base::Time::Now();
+  base::Time metrics_time = now_time - base::TimeDelta::FromMinutes(5);
+  std::unique_ptr<base::PersistentHistogramAllocator> histogram_allocator =
+      CreateMetricsFileWithHistograms(2);
+  ASSERT_TRUE(PathExists(metrics_file()));
+  base::TouchFile(metrics_file(), metrics_time, metrics_time);
+  base::File::Info fileinfo;
+  ASSERT_TRUE(base::GetFileInfo(metrics_file(), &fileinfo));
+  EXPECT_GT(base::Time::Now(), fileinfo.last_modified);
+
+  // Register the file and allow the "checker" task to run.
+  FileMetricsProvider::Params params(
+      metrics_file(), FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_FILE,
+      FileMetricsProvider::ASSOCIATE_CURRENT_RUN, kMetricsName);
+  const FileMetricsProvider::FilterAction actions[] = {
+      FileMetricsProvider::FILTER_TRY_LATER,
+      FileMetricsProvider::FILTER_PROCESS_FILE};
+  SetFilterActions(&params, actions, arraysize(actions));
+  provider()->RegisterSource(params);
+
+  // Processing the file should touch it but yield no results. File timestamp
+  // accuracy is limited so compare the touched time to a couple seconds past.
+  OnDidCreateMetricsLog();
+  RunTasks();
+  EXPECT_EQ(0U, GetSnapshotHistogramCount());
+  EXPECT_TRUE(base::PathExists(metrics_file()));
+  ASSERT_TRUE(base::GetFileInfo(metrics_file(), &fileinfo));
+  EXPECT_LT(metrics_time, fileinfo.last_modified);
+  EXPECT_LE(now_time - base::TimeDelta::FromSeconds(2), fileinfo.last_modified);
+
+  // Second full run on the same file should process the file.
+  OnDidCreateMetricsLog();
+  RunTasks();
+  EXPECT_EQ(2U, GetSnapshotHistogramCount());
+  EXPECT_FALSE(base::PathExists(metrics_file()));
+}
+
+TEST_P(FileMetricsProviderTest, FilterSkipsFile) {
+  ASSERT_FALSE(PathExists(metrics_file()));
+
+  base::Time now_time = base::Time::Now();
+  base::Time metrics_time = now_time - base::TimeDelta::FromMinutes(5);
+  std::unique_ptr<base::PersistentHistogramAllocator> histogram_allocator =
+      CreateMetricsFileWithHistograms(2);
+  ASSERT_TRUE(PathExists(metrics_file()));
+  base::TouchFile(metrics_file(), metrics_time, metrics_time);
+  base::File::Info fileinfo;
+  ASSERT_TRUE(base::GetFileInfo(metrics_file(), &fileinfo));
+  EXPECT_GT(base::Time::Now(), fileinfo.last_modified);
+
+  // Register the file and allow the "checker" task to run.
+  FileMetricsProvider::Params params(
+      metrics_file(), FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_FILE,
+      FileMetricsProvider::ASSOCIATE_CURRENT_RUN, kMetricsName);
+  const FileMetricsProvider::FilterAction actions[] = {
+      FileMetricsProvider::FILTER_SKIP_FILE};
+  SetFilterActions(&params, actions, arraysize(actions));
+  provider()->RegisterSource(params);
+
+  // Processing the file should delete it.
+  OnDidCreateMetricsLog();
+  RunTasks();
+  EXPECT_EQ(0U, GetSnapshotHistogramCount());
+  EXPECT_FALSE(base::PathExists(metrics_file()));
+}
+
 TEST_P(FileMetricsProviderTest, AccessDirectory) {
   ASSERT_FALSE(PathExists(metrics_file()));
 
@@ -335,10 +424,10 @@
   base::GlobalHistogramAllocator::ReleaseForTesting();
 
   // Register the file and allow the "checker" task to run.
-  provider()->RegisterSource(metrics_files.GetPath(),
-                             FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_DIR,
-                             FileMetricsProvider::ASSOCIATE_CURRENT_RUN,
-                             kMetricsName);
+  provider()->RegisterSource(FileMetricsProvider::Params(
+      metrics_files.GetPath(),
+      FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_DIR,
+      FileMetricsProvider::ASSOCIATE_CURRENT_RUN, kMetricsName));
 
   // Files could come out in the order: a1, c2, d4, b3. They are recognizeable
   // by the number of histograms contained within each.
@@ -361,6 +450,89 @@
   EXPECT_TRUE(base::PathExists(metrics_files.GetPath().AppendASCII("baz")));
 }
 
+TEST_P(FileMetricsProviderTest, AccessFilteredDirectory) {
+  ASSERT_FALSE(PathExists(metrics_file()));
+
+  // Get this first so it isn't created inside the persistent allocator.
+  base::GlobalHistogramAllocator::GetCreateHistogramResultHistogram();
+
+  base::GlobalHistogramAllocator::CreateWithLocalMemory(64 << 10, 0,
+                                                        kMetricsName);
+  base::GlobalHistogramAllocator* allocator =
+      base::GlobalHistogramAllocator::Get();
+  base::HistogramBase* histogram;
+
+  // Create files starting with a timestamp a few minutes back.
+  base::Time base_time = base::Time::Now() - base::TimeDelta::FromMinutes(10);
+
+  // Create some files in an odd order. The files are "touched" back in time to
+  // ensure that each file has a later timestamp on disk than the previous one.
+  base::ScopedTempDir metrics_files;
+  EXPECT_TRUE(metrics_files.CreateUniqueTempDir());
+
+  histogram = base::Histogram::FactoryGet("h1", 1, 100, 10, 0);
+  histogram->Add(1);
+  WriteMetricsFileAtTime(metrics_files.GetPath().AppendASCII("a1.pma"),
+                         allocator,
+                         base_time + base::TimeDelta::FromMinutes(1));
+
+  histogram = base::Histogram::FactoryGet("h2", 1, 100, 10, 0);
+  histogram->Add(2);
+  WriteMetricsFileAtTime(metrics_files.GetPath().AppendASCII("c2.pma"),
+                         allocator,
+                         base_time + base::TimeDelta::FromMinutes(2));
+
+  histogram = base::Histogram::FactoryGet("h3", 1, 100, 10, 0);
+  histogram->Add(3);
+  WriteMetricsFileAtTime(metrics_files.GetPath().AppendASCII("b3.pma"),
+                         allocator,
+                         base_time + base::TimeDelta::FromMinutes(3));
+
+  histogram = base::Histogram::FactoryGet("h4", 1, 100, 10, 0);
+  histogram->Add(3);
+  WriteMetricsFileAtTime(metrics_files.GetPath().AppendASCII("d4.pma"),
+                         allocator,
+                         base_time + base::TimeDelta::FromMinutes(4));
+
+  base::TouchFile(metrics_files.GetPath().AppendASCII("b3.pma"),
+                  base_time + base::TimeDelta::FromMinutes(5),
+                  base_time + base::TimeDelta::FromMinutes(5));
+
+  // The global allocator has to be detached here so that no metrics created
+  // by code called below get stored in it as that would make for potential
+  // use-after-free operations if that code is called again.
+  base::GlobalHistogramAllocator::ReleaseForTesting();
+
+  // Register the file and allow the "checker" task to run.
+  FileMetricsProvider::Params params(
+      metrics_files.GetPath(),
+      FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_DIR,
+      FileMetricsProvider::ASSOCIATE_CURRENT_RUN, kMetricsName);
+  const FileMetricsProvider::FilterAction actions[] = {
+      FileMetricsProvider::FILTER_PROCESS_FILE,   // a1
+      FileMetricsProvider::FILTER_TRY_LATER,      // c2
+      FileMetricsProvider::FILTER_SKIP_FILE,      // d4
+      FileMetricsProvider::FILTER_PROCESS_FILE,   // b3
+      FileMetricsProvider::FILTER_PROCESS_FILE};  // c2 (again)
+  SetFilterActions(&params, actions, arraysize(actions));
+  provider()->RegisterSource(params);
+
+  // Files could come out in the order: a1, b3, c2. They are recognizeable
+  // by the number of histograms contained within each.
+  const uint32_t expect_order[] = {1, 3, 2, 0};
+  for (size_t i = 0; i < arraysize(expect_order); ++i) {
+    // Record embedded snapshots via snapshot-manager.
+    OnDidCreateMetricsLog();
+    RunTasks();
+    EXPECT_EQ(expect_order[i], GetSnapshotHistogramCount()) << i;
+  }
+
+  EXPECT_FALSE(base::PathExists(metrics_files.GetPath().AppendASCII("a1.pma")));
+  EXPECT_FALSE(base::PathExists(metrics_files.GetPath().AppendASCII("c2.pma")));
+  EXPECT_FALSE(base::PathExists(metrics_files.GetPath().AppendASCII("b3.pma")));
+  EXPECT_FALSE(base::PathExists(metrics_files.GetPath().AppendASCII("d4.pma")));
+}
+
 TEST_P(FileMetricsProviderTest, AccessReadWriteMetrics) {
   // Create a global histogram allocator that maps to a file.
   ASSERT_FALSE(PathExists(metrics_file()));
@@ -379,9 +551,9 @@
       base::GlobalHistogramAllocator::ReleaseForTesting();
 
   // Register the file and allow the "checker" task to run.
-  provider()->RegisterSource(
+  provider()->RegisterSource(FileMetricsProvider::Params(
       metrics_file(), FileMetricsProvider::SOURCE_HISTOGRAMS_ACTIVE_FILE,
-      FileMetricsProvider::ASSOCIATE_CURRENT_RUN, nullptr);
+      FileMetricsProvider::ASSOCIATE_CURRENT_RUN));
 
   // Record embedded snapshots via snapshot-manager.
   OnDidCreateMetricsLog();
@@ -412,10 +584,9 @@
 
   // Register the file and allow the "checker" task to run.
   ASSERT_TRUE(PathExists(metrics_file()));
-  provider()->RegisterSource(metrics_file(),
-                             FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_FILE,
-                             FileMetricsProvider::ASSOCIATE_PREVIOUS_RUN,
-                             kMetricsName);
+  provider()->RegisterSource(FileMetricsProvider::Params(
+      metrics_file(), FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_FILE,
+      FileMetricsProvider::ASSOCIATE_PREVIOUS_RUN, kMetricsName));
 
   // Record embedded snapshots via snapshot-manager.
   ASSERT_TRUE(HasPreviousSessionData());
@@ -448,9 +619,9 @@
 
   // Register the file and allow the "checker" task to run.
   ASSERT_TRUE(PathExists(metrics_file()));
-  provider()->RegisterSource(
+  provider()->RegisterSource(FileMetricsProvider::Params(
       metrics_file(), FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_FILE,
-      FileMetricsProvider::ASSOCIATE_INTERNAL_PROFILE, kMetricsName);
+      FileMetricsProvider::ASSOCIATE_INTERNAL_PROFILE, kMetricsName));
 
   // Record embedded snapshots via snapshot-manager.
   OnDidCreateMetricsLog();
@@ -486,9 +657,9 @@
 
   // Register the file and allow the "checker" task to run.
   ASSERT_TRUE(PathExists(metrics_file()));
-  provider()->RegisterSource(
+  provider()->RegisterSource(FileMetricsProvider::Params(
       metrics_file(), FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_FILE,
-      FileMetricsProvider::ASSOCIATE_INTERNAL_PROFILE, kMetricsName);
+      FileMetricsProvider::ASSOCIATE_INTERNAL_PROFILE, kMetricsName));
 
   // Record embedded snapshots via snapshot-manager.
   OnDidCreateMetricsLog();
@@ -516,10 +687,10 @@
 
   // Register the file and allow the "checker" task to run.
   ASSERT_TRUE(PathExists(metrics_file()));
-  provider()->RegisterSource(
+  provider()->RegisterSource(FileMetricsProvider::Params(
       metrics_file(), FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_FILE,
       FileMetricsProvider::ASSOCIATE_INTERNAL_PROFILE_OR_PREVIOUS_RUN,
-      kMetricsName);
+      kMetricsName));
 
   // Record embedded snapshots via snapshot-manager.
   ASSERT_TRUE(HasPreviousSessionData());
@@ -557,10 +728,10 @@
 
   // Register the file and allow the "checker" task to run.
   ASSERT_TRUE(PathExists(metrics_file()));
-  provider()->RegisterSource(
+  provider()->RegisterSource(FileMetricsProvider::Params(
       metrics_file(), FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_FILE,
       FileMetricsProvider::ASSOCIATE_INTERNAL_PROFILE_OR_PREVIOUS_RUN,
-      kMetricsName);
+      kMetricsName));
 
   // Record embedded snapshots via snapshot-manager.
   EXPECT_FALSE(HasPreviousSessionData());
@@ -613,9 +784,9 @@
   }
 
   // Register the file and allow the "checker" task to run.
-  provider()->RegisterSource(
+  provider()->RegisterSource(FileMetricsProvider::Params(
       temp_dir(), FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_DIR,
-      FileMetricsProvider::ASSOCIATE_INTERNAL_PROFILE, "");
+      FileMetricsProvider::ASSOCIATE_INTERNAL_PROFILE));
 
   OnDidCreateMetricsLog();
   RunTasks();
diff --git a/components/metrics/metrics_reporting_default_state.cc b/components/metrics/metrics_reporting_default_state.cc
index f3e4133..a166600b 100644
--- a/components/metrics/metrics_reporting_default_state.cc
+++ b/components/metrics/metrics_reporting_default_state.cc
@@ -22,6 +22,12 @@
   local_state->SetInteger(prefs::kMetricsDefaultOptIn, default_state);
 }
 
+void ForceRecordMetricsReportingDefaultState(
+    PrefService* local_state,
+    EnableMetricsDefault default_state) {
+  local_state->SetInteger(prefs::kMetricsDefaultOptIn, default_state);
+}
+
 EnableMetricsDefault GetMetricsReportingDefaultState(PrefService* local_state) {
   return static_cast<EnableMetricsDefault>(
       local_state->GetInteger(prefs::kMetricsDefaultOptIn));
diff --git a/components/metrics/metrics_reporting_default_state.h b/components/metrics/metrics_reporting_default_state.h
index 80f05cd..ad81e99c 100644
--- a/components/metrics/metrics_reporting_default_state.h
+++ b/components/metrics/metrics_reporting_default_state.h
@@ -34,6 +34,11 @@
 void RecordMetricsReportingDefaultState(PrefService* local_state,
                                         EnableMetricsDefault default_state);
 
+// Same as above, but does not verify the current state is UNKNOWN.
+void ForceRecordMetricsReportingDefaultState(
+    PrefService* local_state,
+    EnableMetricsDefault default_state);
+
 // Gets information about the default value for the enable metrics reporting
 // checkbox shown during first-run.
 EnableMetricsDefault GetMetricsReportingDefaultState(PrefService* local_state);
diff --git a/components/metrics/proto/BUILD.gn b/components/metrics/proto/BUILD.gn
index e30b0f4..0041cdcd8 100644
--- a/components/metrics/proto/BUILD.gn
+++ b/components/metrics/proto/BUILD.gn
@@ -10,6 +10,7 @@
     "cast_logs.proto",
     "chrome_user_metrics_extension.proto",
     "execution_context.proto",
+    "extension_install.proto",
     "histogram_event.proto",
     "memory_leak_report.proto",
     "omnibox_event.proto",
diff --git a/components/metrics/proto/execution_context.proto b/components/metrics/proto/execution_context.proto
index 9a32fa4..64dfa6e 100644
--- a/components/metrics/proto/execution_context.proto
+++ b/components/metrics/proto/execution_context.proto
@@ -34,11 +34,11 @@
   // some of which occur in other processes as well.
   UI_THREAD = 1;
   FILE_THREAD = 2;
-  FILE_USER_BLOCKING_THREAD = 3;  // Deprecated.
+  FILE_USER_BLOCKING_THREAD = 3;
   PROCESS_LAUNCHER_THREAD = 4;
-  CACHE_THREAD = 5;  // Deprecated.
+  CACHE_THREAD = 5;
   IO_THREAD = 6;
-  DB_THREAD = 7;  // Deprecated.
+  DB_THREAD = 7;
 
   // GPU process thread.
   GPU_MAIN_THREAD = 8;
diff --git a/components/metrics/proto/extension_install.proto b/components/metrics/proto/extension_install.proto
new file mode 100644
index 0000000..07498c20
--- /dev/null
+++ b/components/metrics/proto/extension_install.proto
@@ -0,0 +1,173 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Stores information about an extension installed on a user's machine.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+option java_outer_classname = "ExtensionInstallProtos";
+option java_package = "org.chromium.components.metrics";
+
+package metrics;
+
+// Next tag: 16.
+message ExtensionInstallProto {
+  // The type of extension item this is.
+  enum Type {
+    UNKNOWN_TYPE = 0;         // Unknown (hopefully never used)
+    EXTENSION = 1;            // A browser extension
+    THEME = 2;                // A browser theme
+    USER_SCRIPT = 3;          // An extension converted from a user script
+    HOSTED_APP = 4;           // A hosted app
+    LEGACY_PACKAGED_APP = 5;  // A (deprecated) v1 packaged app
+    PLATFORM_APP = 6;         // A platform app
+    SHARED_MODULE = 7;        // A shared module
+  }
+  optional Type type = 1;
+
+  // The source of the extension.
+  enum InstallLocation {
+    UNKNOWN_LOCATION = 0;  // Unknown (hopefully never used)
+    INTERNAL = 1;  // A crx file from the internal Extensions directory; most
+                   // webstore-installed extensions fall into this category.
+    EXTERNAL_PREF = 2;  // A crx file from an external directory (via prefs).
+    EXTERNAL_REGISTRY = 3;  // A crx file from an external directory (via the
+                            // Windows registry)
+    UNPACKED = 4;   // An unpacked extension loaded from chrome://extensions.
+    COMPONENT = 5;  // An internal component extension.
+    EXTERNAL_PREF_DOWNLOAD = 6;    // A crx file from an external directory (via
+                                   // prefs), downloaded from an update URL.
+    EXTERNAL_POLICY_DOWNLOAD = 7;  // A crx file from an external directory (via
+                                   // admin policies), downloaded from an update
+                                   // URL.
+    COMMAND_LINE = 8;  // Loaded from the commandline (e.g. --load-extension).
+    EXTERNAL_POLICY = 9;  // A crx file from an external directory (via admin
+                          // policies), cached locally and installed from the
+                          // cache.
+    EXTERNAL_COMPONENT = 10;  // A component extension that was downloaded
+                              // externally via an update url.
+  }
+  optional InstallLocation install_location = 2;
+
+  // The manifest version in the extension. Note: this refers to the
+  // Chrome-required versioning of the manifest, not the extension version.
+  // Currently, it is always 1 or 2.
+  optional int32 manifest_version = 3;
+
+  // The associated UI action in the extension. Each extension can have at most
+  // one type of action.
+  enum ActionType {
+    NO_ACTION = 0;
+    BROWSER_ACTION = 1;
+    PAGE_ACTION = 2;
+    SYSTEM_INDICATOR = 3;
+  }
+  optional ActionType action_type = 4;
+
+  // If the extension has been granted file access.
+  optional bool has_file_access = 5;
+
+  // If the extension has been granted permission to run in incognito contexts.
+  optional bool has_incognito_access = 6;
+
+  // If the extension originated from the Chrome Web Store according to the
+  // prefs.
+  // This differs from install_location, which specifies from where the location
+  // on the user’s machine from where the install originated, but not whether
+  // the extension is hosted in the store. For instance, sideloaded extensions
+  // that are specified via ID in the registry are downloaded from the store.
+  optional bool is_from_store = 7;
+
+  // If the extension automatically updates from the Chrome Web Store.
+  optional bool updates_from_store = 8;
+
+  // If the extension is a bookmark app that was generated from a web page. This
+  // is distinct from install_location above, which specifies from where on the
+  // user’s machine the install originated.
+  optional bool is_from_bookmark = 9;
+
+  // If the extension was created from a user script. This is distinct from
+  // install_location above, which specifies from where on the user’s machine
+  // the install originated.
+  optional bool is_converted_from_user_script = 10;
+
+  // If the extension was installed by default when the profile was created.
+  // These extensions are specified by Chrome.
+  optional bool is_default_installed = 11;
+
+  // If the extension was installed by an OEM. This differs from
+  // "is_default_installed", since these extensions are specified by the OEM
+  // rather than by Chrome. These are specified in a file that is created as
+  // part of the creation of the Chrome image, and can be specific to different
+  // OEMs.
+  optional bool is_oem_installed = 12;
+
+  // The type of background page this extension has. Each extension can have at
+  // most one type of background presence.
+  enum BackgroundScriptType {
+    NO_BACKGROUND_SCRIPT = 0;        // The extension has no background page.
+    PERSISTENT_BACKGROUND_PAGE = 1;  // The extension has a persistent
+                                     // background page.
+    EVENT_PAGE = 2;                  // The extension has a (lazy) event page.
+  }
+  optional BackgroundScriptType background_script_type = 13;
+
+  // The reasons an extension may be disabled.
+  enum DisableReason {
+    USER_ACTION = 0;              // The user disabled the extension.
+    PERMISSIONS_INCREASE = 1;     // The extension increased permissions.
+    RELOAD = 2;                   // The extension is reloading.
+    UNSUPPORTED_REQUIREMENT = 3;  // The extension has requirements that weren't
+                                  // met (e.g. graphics capabilities).
+    SIDELOAD_WIPEOUT = 4;         // The extension was disabled in the sideload
+                                  // wipeout.
+    UNKNOWN_FROM_SYNC = 5;        // The extension was disabled by sync.
+    NOT_VERIFIED = 6;             // The extension couldn't be verified.
+    GREYLIST = 7;                 // The extension was found on the greylist.
+    CORRUPTED = 8;  // The extension install was corrupted according to content
+                    // verification.
+    REMOTE_INSTALL = 9;  // The extension was installed remotely and hasn't been
+                         // enabled.
+    EXTERNAL_EXTENSION = 10;  // The extension was sideloaded and hasn't been
+                              // enabled.
+    UPDATE_REQUIRED_BY_POLICY = 11;    // Policy requires an unmet minimum
+                                       // version.
+    CUSTODIAN_APPROVAL_REQUIRED = 12;  // The extension is pending custodian
+                                       // approval for a supervised user.
+    BLOCKED_BY_POLICY = 13;  // The extension is disabled because it's blocked
+                             // by enterprise policy.
+  }
+  // Any DisableReasons in effect for the extension. An empty list means the
+  // extension is not disabled. Note that an extension that is not disabled may
+  // nonetheless not be running, e.g., terminated because the extension process
+  // was killed.
+  repeated DisableReason disable_reasons = 14;
+
+  // The state of the extension in the safe browsing blacklist.
+  // The numeric values here match the values of the respective enum in
+  // ClientCRXListInfoResponse proto.
+  enum BlacklistState {
+    // The extension is not in the blacklist.
+    NOT_BLACKLISTED = 0;
+    // The extension is malware.
+    BLACKLISTED_MALWARE = 1;
+    // The extension has a serious security vulnerability.
+    BLACKLISTED_SECURITY_VULNERABILITY = 2;
+    // The extension violated CWS policy.
+    BLACKLISTED_CWS_POLICY_VIOLATION = 3;
+    // The extension is considered potentially unwanted.
+    BLACKLISTED_POTENTIALLY_UNWANTED = 4;
+    // Used when we couldn't connect to server, e.g. when offline.
+    BLACKLISTED_UNKNOWN = 5;
+  }
+  optional BlacklistState blacklist_state = 15;
+
+  // Whether the extension was installed in the current sampling period. This
+  // is useful if trying to use extension installation in conjunction with other
+  // metrics (e.g. page load). Since some of the metrics from this period will
+  // have the extension installed and others won't, these records can be
+  // discarded for that analysis.
+  optional bool installed_in_this_sample_period = 16;
+}
diff --git a/components/metrics/proto/system_profile.proto b/components/metrics/proto/system_profile.proto
index 3ae0b0d..3039d61e 100644
--- a/components/metrics/proto/system_profile.proto
+++ b/components/metrics/proto/system_profile.proto
@@ -13,7 +13,9 @@
 
 package metrics;
 
-// Next tag: 24
+import "extension_install.proto";
+
+// Next tag: 26
 message SystemProfileProto {
   // The time when the client was compiled/linked, in seconds since the epoch.
   optional int64 build_timestamp = 1;
@@ -944,4 +946,9 @@
     optional fixed32 omaha_fingerprint = 3;
   }
   repeated ChromeComponent chrome_component = 24;
+
+  // Information about the user's installed extensions. This will include
+  // extensions from all fully-initialized profiles. If a single extension is
+  // installed in multiple profiles, it will be recorded multiple times.
+  repeated ExtensionInstallProto extension_install = 25;
 }
diff --git a/components/metrics/public/cpp/call_stack_profile_struct_traits.h b/components/metrics/public/cpp/call_stack_profile_struct_traits.h
index 47860c4d..6a3af7cf 100644
--- a/components/metrics/public/cpp/call_stack_profile_struct_traits.h
+++ b/components/metrics/public/cpp/call_stack_profile_struct_traits.h
@@ -232,10 +232,16 @@
         return metrics::mojom::Thread::UI_THREAD;
       case metrics::CallStackProfileParams::Thread::FILE_THREAD:
         return metrics::mojom::Thread::FILE_THREAD;
+      case metrics::CallStackProfileParams::Thread::FILE_USER_BLOCKING_THREAD:
+        return metrics::mojom::Thread::FILE_USER_BLOCKING_THREAD;
       case metrics::CallStackProfileParams::Thread::PROCESS_LAUNCHER_THREAD:
         return metrics::mojom::Thread::PROCESS_LAUNCHER_THREAD;
+      case metrics::CallStackProfileParams::Thread::CACHE_THREAD:
+        return metrics::mojom::Thread::CACHE_THREAD;
       case metrics::CallStackProfileParams::Thread::IO_THREAD:
         return metrics::mojom::Thread::IO_THREAD;
+      case metrics::CallStackProfileParams::Thread::DB_THREAD:
+        return metrics::mojom::Thread::DB_THREAD;
       case metrics::CallStackProfileParams::Thread::GPU_MAIN_THREAD:
         return metrics::mojom::Thread::GPU_MAIN_THREAD;
       case metrics::CallStackProfileParams::Thread::RENDER_THREAD:
@@ -259,12 +265,22 @@
       case metrics::mojom::Thread::FILE_THREAD:
         *out = metrics::CallStackProfileParams::Thread::FILE_THREAD;
         return true;
+      case metrics::mojom::Thread::FILE_USER_BLOCKING_THREAD:
+        *out =
+            metrics::CallStackProfileParams::Thread::FILE_USER_BLOCKING_THREAD;
+        return true;
       case metrics::mojom::Thread::PROCESS_LAUNCHER_THREAD:
         *out = metrics::CallStackProfileParams::Thread::PROCESS_LAUNCHER_THREAD;
         return true;
+      case metrics::mojom::Thread::CACHE_THREAD:
+        *out = metrics::CallStackProfileParams::Thread::CACHE_THREAD;
+        return true;
       case metrics::mojom::Thread::IO_THREAD:
         *out = metrics::CallStackProfileParams::Thread::IO_THREAD;
         return true;
+      case metrics::mojom::Thread::DB_THREAD:
+        *out = metrics::CallStackProfileParams::Thread::DB_THREAD;
+        return true;
       case metrics::mojom::Thread::GPU_MAIN_THREAD:
         *out = metrics::CallStackProfileParams::Thread::GPU_MAIN_THREAD;
         return true;
diff --git a/components/metrics/public/cpp/call_stack_profile_struct_traits_unittest.cc b/components/metrics/public/cpp/call_stack_profile_struct_traits_unittest.cc
index 3d697d4..b6802d3 100644
--- a/components/metrics/public/cpp/call_stack_profile_struct_traits_unittest.cc
+++ b/components/metrics/public/cpp/call_stack_profile_struct_traits_unittest.cc
@@ -309,12 +309,21 @@
   EXPECT_TRUE(proxy_->BounceThread(Thread::FILE_THREAD, &out));
   EXPECT_EQ(Thread::FILE_THREAD, out);
 
+  EXPECT_TRUE(proxy_->BounceThread(Thread::FILE_USER_BLOCKING_THREAD, &out));
+  EXPECT_EQ(Thread::FILE_USER_BLOCKING_THREAD, out);
+
   EXPECT_TRUE(proxy_->BounceThread(Thread::PROCESS_LAUNCHER_THREAD, &out));
   EXPECT_EQ(Thread::PROCESS_LAUNCHER_THREAD, out);
 
+  EXPECT_TRUE(proxy_->BounceThread(Thread::CACHE_THREAD, &out));
+  EXPECT_EQ(Thread::CACHE_THREAD, out);
+
   EXPECT_TRUE(proxy_->BounceThread(Thread::IO_THREAD, &out));
   EXPECT_EQ(Thread::IO_THREAD, out);
 
+  EXPECT_TRUE(proxy_->BounceThread(Thread::DB_THREAD, &out));
+  EXPECT_EQ(Thread::DB_THREAD, out);
+
   EXPECT_TRUE(proxy_->BounceThread(Thread::GPU_MAIN_THREAD, &out));
   EXPECT_EQ(Thread::GPU_MAIN_THREAD, out);
 
diff --git a/components/metrics/public/interfaces/call_stack_profile_collector.mojom b/components/metrics/public/interfaces/call_stack_profile_collector.mojom
index 66fbb42f..3573f90 100644
--- a/components/metrics/public/interfaces/call_stack_profile_collector.mojom
+++ b/components/metrics/public/interfaces/call_stack_profile_collector.mojom
@@ -49,8 +49,11 @@
 
   UI_THREAD,
   FILE_THREAD,
+  FILE_USER_BLOCKING_THREAD,
   PROCESS_LAUNCHER_THREAD,
+  CACHE_THREAD,
   IO_THREAD,
+  DB_THREAD,
 
   GPU_MAIN_THREAD,
 
diff --git a/components/metrics_services_manager/metrics_services_manager.cc b/components/metrics_services_manager/metrics_services_manager.cc
index 0bd70581..559e806 100644
--- a/components/metrics_services_manager/metrics_services_manager.cc
+++ b/components/metrics_services_manager/metrics_services_manager.cc
@@ -21,7 +21,10 @@
 
 MetricsServicesManager::MetricsServicesManager(
     std::unique_ptr<MetricsServicesManagerClient> client)
-    : client_(std::move(client)), may_upload_(false), may_record_(false) {
+    : client_(std::move(client)),
+      may_upload_(false),
+      may_record_(false),
+      consent_given_(false) {
   DCHECK(client_);
 }
 
@@ -81,10 +84,12 @@
 }
 
 void MetricsServicesManager::UpdatePermissions(bool current_may_record,
+                                               bool current_consent_given,
                                                bool current_may_upload) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  // If the user has opted out of metrics, delete local UKM state.
-  if (may_record_ && !current_may_record) {
+  // If the user has opted out of metrics, delete local UKM state. We Only check
+  // consent for UKM.
+  if (consent_given_ && !current_consent_given) {
     ukm::UkmService* ukm = GetUkmService();
     if (ukm) {
       ukm->Purge();
@@ -93,10 +98,9 @@
   }
 
   // Stash the current permissions so that we can update the RapporServiceImpl
-  // correctly when the Rappor preference changes.  The metrics recording
-  // preference partially determines the initial rappor setting, and also
-  // controls whether FINE metrics are sent.
+  // correctly when the Rappor preference changes.
   may_record_ = current_may_record;
+  consent_given_ = current_consent_given;
   may_upload_ = current_may_upload;
   UpdateRunningServices();
 }
@@ -138,7 +142,8 @@
       client_->IsMetricsReportingForceEnabled() ||
       metrics_service_client_->IsHistorySyncEnabledOnAllProfiles();
   bool is_incognito = client_->IsIncognitoSessionActive();
-  if (may_record_ && sync_enabled & !is_incognito) {
+
+  if (consent_given_ && sync_enabled & !is_incognito) {
     ukm->EnableRecording();
     if (may_upload_)
       ukm->EnableReporting();
@@ -151,9 +156,13 @@
 }
 
 void MetricsServicesManager::UpdateUploadPermissions(bool may_upload) {
-  UpdatePermissions((client_->IsMetricsReportingForceEnabled() ||
-                     client_->IsMetricsReportingEnabled()),
-                    client_->IsMetricsReportingForceEnabled() || may_upload);
+  if (client_->IsMetricsReportingForceEnabled()) {
+    UpdatePermissions(true, true, true);
+    return;
+  }
+
+  UpdatePermissions(client_->IsMetricsReportingEnabled(),
+                    client_->IsMetricsConsentGiven(), may_upload);
 }
 
 }  // namespace metrics_services_manager
diff --git a/components/metrics_services_manager/metrics_services_manager.h b/components/metrics_services_manager/metrics_services_manager.h
index 6880845..3837823 100644
--- a/components/metrics_services_manager/metrics_services_manager.h
+++ b/components/metrics_services_manager/metrics_services_manager.h
@@ -77,10 +77,6 @@
   // renderer process exits unexpectedly.
   void OnRendererProcessCrash();
 
-  // Update the managed services when permissions for recording/uploading
-  // metrics change.
-  void UpdatePermissions(bool current_may_record, bool current_may_upload);
-
   // Update the managed services when permissions for uploading metrics change.
   void UpdateUploadPermissions(bool may_upload);
 
@@ -101,6 +97,12 @@
   // Update the state of UkmService to match current permissions.
   void UpdateUkmService();
 
+  // Update the managed services when permissions for recording/uploading
+  // metrics change.
+  void UpdatePermissions(bool current_may_record,
+                         bool current_consent_given,
+                         bool current_may_upload);
+
   // The client passed in from the embedder.
   std::unique_ptr<MetricsServicesManagerClient> client_;
 
@@ -113,6 +115,9 @@
   // The current metrics recording setting.
   bool may_record_;
 
+  // The current metrics setting reflecting if consent was given.
+  bool consent_given_;
+
   // The MetricsServiceClient. Owns the MetricsService.
   std::unique_ptr<metrics::MetricsServiceClient> metrics_service_client_;
 
diff --git a/components/metrics_services_manager/metrics_services_manager_client.h b/components/metrics_services_manager/metrics_services_manager_client.h
index 351fc67..e806067 100644
--- a/components/metrics_services_manager/metrics_services_manager_client.h
+++ b/components/metrics_services_manager/metrics_services_manager_client.h
@@ -51,6 +51,9 @@
   // Returns whether metrics reporting is enabled.
   virtual bool IsMetricsReportingEnabled() = 0;
 
+  // Returns whether metrics consent is given.
+  virtual bool IsMetricsConsentGiven() = 0;
+
   // Returns whether there are any Incognito browsers/tabs open.
   virtual bool IsIncognitoSessionActive() = 0;
 
diff --git a/components/nacl/broker/BUILD.gn b/components/nacl/broker/BUILD.gn
index 925060a..e86f972 100644
--- a/components/nacl/broker/BUILD.gn
+++ b/components/nacl/broker/BUILD.gn
@@ -2,8 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/features.gni")
 import("//build/config/compiler/compiler.gni")
+import("//components/nacl/features.gni")
 import("//services/service_manager/public/service_manifest.gni")
 
 # This file builds nacl64.exe, which is a 64-bit x86 Windows executable
diff --git a/components/nacl/browser/BUILD.gn b/components/nacl/browser/BUILD.gn
index 08e4a05..a10c599 100644
--- a/components/nacl/browser/BUILD.gn
+++ b/components/nacl/browser/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/features.gni")
+import("//components/nacl/features.gni")
 
 assert(enable_nacl)
 
diff --git a/components/nacl/common/BUILD.gn b/components/nacl/common/BUILD.gn
index 8840bf9..bc165635 100644
--- a/components/nacl/common/BUILD.gn
+++ b/components/nacl/common/BUILD.gn
@@ -3,7 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/buildflag_header.gni")
-import("//build/config/features.gni")
+import("//components/nacl/features.gni")
 import("//mojo/public/tools/bindings/mojom.gni")
 
 if (enable_nacl) {
diff --git a/components/nacl/features.gni b/components/nacl/features.gni
new file mode 100644
index 0000000..de172b4d
--- /dev/null
+++ b/components/nacl/features.gni
@@ -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.
+
+import("//build/config/chromecast_build.gni")
+
+declare_args() {
+  # Enables Native Client support.
+  # Temporarily disable nacl on arm64 linux to get rid of compilation errors.
+  # TODO: When mipsel-nacl-clang is available, drop the exclusion.
+  enable_nacl = !is_ios && !is_android && !is_fuchsia && !is_chromecast &&
+                current_cpu != "mipsel" && current_cpu != "mips64el" &&
+                !(is_linux && target_cpu == "arm64")
+
+  # Non-SFI is not yet supported on mipsel
+  enable_nacl_nonsfi = current_cpu != "mipsel" && current_cpu != "mips64el"
+}
diff --git a/components/nacl/loader/BUILD.gn b/components/nacl/loader/BUILD.gn
index 974939b..db67c535 100644
--- a/components/nacl/loader/BUILD.gn
+++ b/components/nacl/loader/BUILD.gn
@@ -2,8 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/features.gni")
 import("//build/config/nacl/config.gni")
+import("//components/nacl/features.gni")
 import("//services/service_manager/public/service_manifest.gni")
 import("//testing/test.gni")
 
diff --git a/components/nacl/loader/sandbox_linux/BUILD.gn b/components/nacl/loader/sandbox_linux/BUILD.gn
index 96dc1dbd..f3a0f4d4 100644
--- a/components/nacl/loader/sandbox_linux/BUILD.gn
+++ b/components/nacl/loader/sandbox_linux/BUILD.gn
@@ -2,8 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/features.gni")
 import("//build/config/ui.gni")
+import("//components/nacl/features.gni")
 
 assert(is_linux)
 assert(enable_nacl)
diff --git a/components/nacl/renderer/BUILD.gn b/components/nacl/renderer/BUILD.gn
index 065ca4f..1b41d6b9 100644
--- a/components/nacl/renderer/BUILD.gn
+++ b/components/nacl/renderer/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/features.gni")
+import("//components/nacl/features.gni")
 
 assert(enable_nacl)
 
diff --git a/components/navigation_metrics/navigation_metrics.cc b/components/navigation_metrics/navigation_metrics.cc
index f63b6c4..cf36265 100644
--- a/components/navigation_metrics/navigation_metrics.cc
+++ b/components/navigation_metrics/navigation_metrics.cc
@@ -60,6 +60,14 @@
 static_assert(arraysize(kSchemeNames) == SCHEME_MAX,
               "kSchemeNames should have SCHEME_MAX elements");
 
+Scheme GetScheme(const GURL& url) {
+  for (int i = 1; i < SCHEME_MAX; ++i) {
+    if (url.SchemeIs(kSchemeNames[i]))
+      return static_cast<Scheme>(i);
+  }
+  return SCHEME_UNKNOWN;
+}
+
 }  // namespace
 
 namespace navigation_metrics {
@@ -67,14 +75,7 @@
 void RecordMainFrameNavigation(const GURL& url,
                                bool is_same_document,
                                bool is_off_the_record) {
-  Scheme scheme = SCHEME_UNKNOWN;
-  for (int i = 1; i < SCHEME_MAX; ++i) {
-    if (url.SchemeIs(kSchemeNames[i])) {
-      scheme = static_cast<Scheme>(i);
-      break;
-    }
-  }
-
+  Scheme scheme = GetScheme(url);
   UMA_HISTOGRAM_ENUMERATION("Navigation.MainFrameScheme", scheme, SCHEME_MAX);
   if (!is_same_document) {
     UMA_HISTOGRAM_ENUMERATION("Navigation.MainFrameSchemeDifferentPage", scheme,
@@ -91,4 +92,9 @@
   }
 }
 
+void RecordOmniboxURLNavigation(const GURL& url) {
+  UMA_HISTOGRAM_ENUMERATION("Omnibox.URLNavigationScheme", GetScheme(url),
+                            SCHEME_MAX);
+}
+
 }  // namespace navigation_metrics
diff --git a/components/navigation_metrics/navigation_metrics.h b/components/navigation_metrics/navigation_metrics.h
index 1475d6e18..3552798 100644
--- a/components/navigation_metrics/navigation_metrics.h
+++ b/components/navigation_metrics/navigation_metrics.h
@@ -13,6 +13,8 @@
                                bool is_same_document,
                                bool is_off_the_record);
 
+void RecordOmniboxURLNavigation(const GURL& url);
+
 }  // namespace navigation_metrics
 
 #endif  // COMPONENTS_NAVIGATION_METRICS_NAVIGATION_METRICS_H_
diff --git a/components/network_session_configurator/browser/network_session_configurator.cc b/components/network_session_configurator/browser/network_session_configurator.cc
index 960d52b6..2b35e17 100644
--- a/components/network_session_configurator/browser/network_session_configurator.cc
+++ b/components/network_session_configurator/browser/network_session_configurator.cc
@@ -201,6 +201,13 @@
       GetVariationParam(quic_trial_params, "estimate_initial_rtt"), "true");
 }
 
+bool ShouldQuicConnectUsingDefaultNetwork(
+    const VariationParameters& quic_trial_params) {
+  return base::LowerCaseEqualsASCII(
+      GetVariationParam(quic_trial_params, "connect_using_default_network"),
+      "true");
+}
+
 bool ShouldQuicMigrateSessionsOnNetworkChange(
     const VariationParameters& quic_trial_params) {
   return base::LowerCaseEqualsASCII(
@@ -282,6 +289,8 @@
         ShouldQuicRaceCertVerification(quic_trial_params);
     params->quic_estimate_initial_rtt =
         ShouldQuicEstimateInitialRtt(quic_trial_params);
+    params->quic_connect_using_default_network =
+        ShouldQuicConnectUsingDefaultNetwork(quic_trial_params);
     params->quic_migrate_sessions_on_network_change =
         ShouldQuicMigrateSessionsOnNetworkChange(quic_trial_params);
     params->quic_migrate_sessions_early =
diff --git a/components/network_session_configurator/browser/network_session_configurator_unittest.cc b/components/network_session_configurator/browser/network_session_configurator_unittest.cc
index f6e3dbf..74720bd 100644
--- a/components/network_session_configurator/browser/network_session_configurator_unittest.cc
+++ b/components/network_session_configurator/browser/network_session_configurator_unittest.cc
@@ -96,6 +96,7 @@
   EXPECT_EQ(net::kPingTimeoutSecs, params_.quic_reduced_ping_timeout_seconds);
   EXPECT_FALSE(params_.quic_race_cert_verification);
   EXPECT_FALSE(params_.quic_estimate_initial_rtt);
+  EXPECT_FALSE(params_.quic_connect_using_default_network);
   EXPECT_FALSE(params_.quic_migrate_sessions_on_network_change);
   EXPECT_FALSE(params_.quic_migrate_sessions_early);
   EXPECT_FALSE(params_.quic_allow_server_migration);
@@ -225,6 +226,18 @@
 }
 
 TEST_F(NetworkSessionConfiguratorTest,
+       QuicConnectUsingDefaultNetworkFromFieldTrialParams) {
+  std::map<std::string, std::string> field_trial_params;
+  field_trial_params["connect_using_default_network"] = "true";
+  variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params);
+  base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled");
+
+  ParseFieldTrials();
+
+  EXPECT_TRUE(params_.quic_connect_using_default_network);
+}
+
+TEST_F(NetworkSessionConfiguratorTest,
        QuicMigrateSessionsOnNetworkChangeFromFieldTrialParams) {
   std::map<std::string, std::string> field_trial_params;
   field_trial_params["migrate_sessions_on_network_change"] = "true";
diff --git a/components/ntp_snippets/BUILD.gn b/components/ntp_snippets/BUILD.gn
index 5e95e66e..95f1484 100644
--- a/components/ntp_snippets/BUILD.gn
+++ b/components/ntp_snippets/BUILD.gn
@@ -48,6 +48,8 @@
     "contextual/contextual_content_suggestions_service.h",
     "contextual/contextual_json_request.cc",
     "contextual/contextual_json_request.h",
+    "contextual/contextual_suggestion.cc",
+    "contextual/contextual_suggestion.h",
     "contextual/contextual_suggestions_fetcher.h",
     "contextual/contextual_suggestions_fetcher_impl.cc",
     "contextual/contextual_suggestions_fetcher_impl.h",
diff --git a/components/ntp_snippets/breaking_news/breaking_news_suggestions_provider.cc b/components/ntp_snippets/breaking_news/breaking_news_suggestions_provider.cc
deleted file mode 100644
index 57a3d276..0000000
--- a/components/ntp_snippets/breaking_news/breaking_news_suggestions_provider.cc
+++ /dev/null
@@ -1,143 +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/ntp_snippets/breaking_news/breaking_news_suggestions_provider.h"
-
-#include "base/bind.h"
-#include "base/time/clock.h"
-#include "components/ntp_snippets/breaking_news/breaking_news_listener.h"
-#include "components/ntp_snippets/category.h"
-#include "components/ntp_snippets/pref_names.h"
-#include "components/ntp_snippets/remote/json_to_categories.h"
-#include "components/strings/grit/components_strings.h"
-
-namespace ntp_snippets {
-
-BreakingNewsSuggestionsProvider::BreakingNewsSuggestionsProvider(
-    ContentSuggestionsProvider::Observer* observer,
-    std::unique_ptr<BreakingNewsListener> breaking_news_raw_data_provider,
-    std::unique_ptr<base::Clock> clock,
-    std::unique_ptr<RemoteSuggestionsDatabase> database)
-    : ContentSuggestionsProvider(observer),
-      breaking_news_raw_data_provider_(
-          std::move(breaking_news_raw_data_provider)),
-      clock_(std::move(clock)),
-      database_(std::move(database)),
-      provided_category_(
-          Category::FromKnownCategory(KnownCategories::BREAKING_NEWS)),
-      category_status_(CategoryStatus::INITIALIZING) {
-  database_->SetErrorCallback(
-      base::Bind(&BreakingNewsSuggestionsProvider::OnDatabaseError,
-                 base::Unretained(this)));
-  database_->LoadSnippets(
-      base::Bind(&BreakingNewsSuggestionsProvider::OnDatabaseLoaded,
-                 base::Unretained(this)));
-  // Unretained because |this| owns |breaking_news_listener_|.
-  breaking_news_raw_data_provider_->StartListening(
-      base::Bind(&BreakingNewsSuggestionsProvider::OnNewRemoteSuggestion,
-                 base::Unretained(this)));
-}
-
-BreakingNewsSuggestionsProvider::~BreakingNewsSuggestionsProvider() {
-  breaking_news_raw_data_provider_->StopListening();
-}
-
-void BreakingNewsSuggestionsProvider::OnNewRemoteSuggestion(
-    std::unique_ptr<RemoteSuggestion> remote_suggestion) {
-  std::vector<std::unique_ptr<RemoteSuggestion>> suggestions;
-  suggestions.push_back(std::move(remote_suggestion));
-  if (database_->IsInitialized()) {
-    database_->SaveSnippets(suggestions);
-  } else {
-    // TODO(mamir): Check how often a breaking news is received before DB is
-    // initialized.
-    LOG(WARNING) << "Cannot store breaking news, database is not initialized.";
-  }
-  NotifyNewSuggestions(std::move(suggestions));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Private methods
-
-CategoryStatus BreakingNewsSuggestionsProvider::GetCategoryStatus(
-    Category category) {
-  DCHECK_EQ(category, provided_category_);
-  return category_status_;
-}
-
-CategoryInfo BreakingNewsSuggestionsProvider::GetCategoryInfo(
-    Category category) {
-  // TODO(mamir): needs to be corrected, just a placeholer
-  return CategoryInfo(base::string16(),
-                      ContentSuggestionsCardLayout::MINIMAL_CARD,
-                      ContentSuggestionsAdditionalAction::VIEW_ALL,
-                      /*show_if_empty=*/false, base::string16());
-}
-
-void BreakingNewsSuggestionsProvider::DismissSuggestion(
-    const ContentSuggestion::ID& suggestion_id) {
-  // TODO(mamir): implement.
-}
-
-void BreakingNewsSuggestionsProvider::FetchSuggestionImage(
-    const ContentSuggestion::ID& suggestion_id,
-    ImageFetchedCallback callback) {
-  // TODO(mamir): implement.
-}
-
-void BreakingNewsSuggestionsProvider::Fetch(
-    const Category& category,
-    const std::set<std::string>& known_suggestion_ids,
-    FetchDoneCallback callback) {
-  // TODO(jkrcal): Make Fetch method optional.
-}
-
-void BreakingNewsSuggestionsProvider::ClearHistory(
-    base::Time begin,
-    base::Time end,
-    const base::Callback<bool(const GURL& url)>& filter) {
-  observer()->OnNewSuggestions(this, provided_category_,
-                               std::vector<ContentSuggestion>());
-}
-
-void BreakingNewsSuggestionsProvider::ClearCachedSuggestions(
-    Category category) {
-  DCHECK_EQ(category, provided_category_);
-  // TODO(mamir): clear the cached suggestions.
-}
-
-void BreakingNewsSuggestionsProvider::GetDismissedSuggestionsForDebugging(
-    Category category,
-    DismissedSuggestionsCallback callback) {
-  // TODO(mamir): implement.
-}
-
-void BreakingNewsSuggestionsProvider::ClearDismissedSuggestionsForDebugging(
-    Category category) {
-  // TODO(mamir): implement.
-}
-
-void BreakingNewsSuggestionsProvider::OnDatabaseLoaded(
-    std::vector<std::unique_ptr<RemoteSuggestion>> suggestions) {
-  // TODO(mamir): check and update DB status.
-  NotifyNewSuggestions(std::move(suggestions));
-}
-
-void BreakingNewsSuggestionsProvider::OnDatabaseError() {
-  // TODO(mamir): implement.
-}
-
-void BreakingNewsSuggestionsProvider::NotifyNewSuggestions(
-    std::vector<std::unique_ptr<RemoteSuggestion>> suggestions) {
-  std::vector<ContentSuggestion> result;
-  for (const std::unique_ptr<RemoteSuggestion>& suggestion : suggestions) {
-    result.emplace_back(suggestion->ToContentSuggestion(provided_category_));
-  }
-
-  DVLOG(1) << "NotifyNewSuggestions(): " << result.size()
-           << " items in category " << provided_category_;
-  observer()->OnNewSuggestions(this, provided_category_, std::move(result));
-}
-
-}  // namespace ntp_snippets
diff --git a/components/ntp_snippets/breaking_news/breaking_news_suggestions_provider.h b/components/ntp_snippets/breaking_news/breaking_news_suggestions_provider.h
deleted file mode 100644
index d0b6b21e..0000000
--- a/components/ntp_snippets/breaking_news/breaking_news_suggestions_provider.h
+++ /dev/null
@@ -1,85 +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_NTP_SNIPPETS_BREAKING_NEWS_BREAKING_NEWS_SUGGESTIONS_PROVIDER_H_
-#define COMPONENTS_NTP_SNIPPETS_BREAKING_NEWS_BREAKING_NEWS_SUGGESTIONS_PROVIDER_H_
-
-#include "components/ntp_snippets/category.h"
-#include "components/ntp_snippets/content_suggestions_provider.h"
-#include "components/ntp_snippets/remote/json_to_categories.h"
-#include "components/ntp_snippets/remote/remote_suggestions_database.h"
-#include "components/prefs/pref_registry_simple.h"
-
-namespace ntp_snippets {
-class BreakingNewsListener;
-}
-
-namespace base {
-class Clock;
-}
-
-namespace ntp_snippets {
-
-// Receives breaking news suggestions asynchronously via BreakingNewsListener,
-// stores them and provides them as content suggestions.
-// This class is final because it does things in its constructor which make it
-// unsafe to derive from it.
-class BreakingNewsSuggestionsProvider final
-    : public ContentSuggestionsProvider {
- public:
-  BreakingNewsSuggestionsProvider(
-      ContentSuggestionsProvider::Observer* observer,
-      std::unique_ptr<BreakingNewsListener> breaking_news_raw_data_provider,
-      std::unique_ptr<base::Clock> clock,
-      std::unique_ptr<RemoteSuggestionsDatabase> database);
-  ~BreakingNewsSuggestionsProvider() override;
-
-  // ContentSuggestionsProvider implementation.
-  CategoryStatus GetCategoryStatus(Category category) override;
-  CategoryInfo GetCategoryInfo(Category category) override;
-  void DismissSuggestion(const ContentSuggestion::ID& suggestion_id) override;
-  void FetchSuggestionImage(const ContentSuggestion::ID& suggestion_id,
-                            ImageFetchedCallback callback) override;
-  void Fetch(const Category& category,
-             const std::set<std::string>& known_suggestion_ids,
-             FetchDoneCallback callback) override;
-  void ClearHistory(
-      base::Time begin,
-      base::Time end,
-      const base::Callback<bool(const GURL& url)>& filter) override;
-  void ClearCachedSuggestions(Category category) override;
-  void GetDismissedSuggestionsForDebugging(
-      Category category,
-      DismissedSuggestionsCallback callback) override;
-  void ClearDismissedSuggestionsForDebugging(Category category) override;
-
- private:
-  // Callback called from the breaking news listener when new content has been
-  // pushed from the server.
-  void OnNewRemoteSuggestion(
-      std::unique_ptr<RemoteSuggestion> remote_suggestion);
-
-  // Callbacks for the RemoteSuggestionsDatabase.
-  void OnDatabaseLoaded(
-      std::vector<std::unique_ptr<RemoteSuggestion>> suggestions);
-  void OnDatabaseError();
-
-  void NotifyNewSuggestions(
-      std::vector<std::unique_ptr<RemoteSuggestion>> suggestions);
-
-  std::unique_ptr<BreakingNewsListener> breaking_news_raw_data_provider_;
-  std::unique_ptr<base::Clock> clock_;
-
-  // The database for persisting suggestions.
-  std::unique_ptr<RemoteSuggestionsDatabase> database_;
-
-  const Category provided_category_;
-  CategoryStatus category_status_;
-
-  DISALLOW_COPY_AND_ASSIGN(BreakingNewsSuggestionsProvider);
-};
-
-}  // namespace ntp_snippets
-
-#endif  // COMPONENTS_NTP_SNIPPETS_BREAKING_NEWS_BREAKING_NEWS_SUGGESTIONS_PROVIDER_H_
diff --git a/components/ntp_snippets/contextual/contextual_content_suggestions_service.cc b/components/ntp_snippets/contextual/contextual_content_suggestions_service.cc
index 4094976..dd12e915 100644
--- a/components/ntp_snippets/contextual/contextual_content_suggestions_service.cc
+++ b/components/ntp_snippets/contextual/contextual_content_suggestions_service.cc
@@ -66,10 +66,9 @@
     ContextualSuggestionsFetcher::OptionalSuggestions fetched_suggestions) {
   std::vector<ContentSuggestion> suggestions;
   if (fetched_suggestions.has_value()) {
-    for (const std::unique_ptr<RemoteSuggestion>& suggestion :
+    for (const std::unique_ptr<ContextualSuggestion>& suggestion :
          fetched_suggestions.value()) {
-      suggestions.emplace_back(suggestion->ToContentSuggestion(
-          Category::FromKnownCategory(KnownCategories::CONTEXTUAL)));
+      suggestions.emplace_back(suggestion->ToContentSuggestion());
       ContentSuggestion::ID id = suggestions.back().id();
       GURL image_url = suggestion->salient_image_url();
       image_url_by_id_[id.id_within_category()] = image_url;
diff --git a/components/ntp_snippets/contextual/contextual_content_suggestions_service_unittest.cc b/components/ntp_snippets/contextual/contextual_content_suggestions_service_unittest.cc
index 40e34c2..1305a8d9 100644
--- a/components/ntp_snippets/contextual/contextual_content_suggestions_service_unittest.cc
+++ b/components/ntp_snippets/contextual/contextual_content_suggestions_service_unittest.cc
@@ -17,11 +17,10 @@
 #include "components/image_fetcher/core/image_fetcher_impl.h"
 #include "components/ntp_snippets/category_info.h"
 #include "components/ntp_snippets/content_suggestion.h"
+#include "components/ntp_snippets/contextual/contextual_suggestion.h"
 #include "components/ntp_snippets/contextual/contextual_suggestions_fetcher.h"
 #include "components/ntp_snippets/remote/cached_image_fetcher.h"
 #include "components/ntp_snippets/remote/json_to_categories.h"
-#include "components/ntp_snippets/remote/remote_suggestion.h"
-#include "components/ntp_snippets/remote/remote_suggestion_builder.h"
 #include "components/ntp_snippets/remote/remote_suggestions_database.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
@@ -149,14 +148,12 @@
   MockFetchContextualSuggestionsCallback mock_suggestions_callback;
   const std::string kValidFromUrl = "http://some.url";
   const std::string kToUrl = "http://another.url";
-  ContextualSuggestionsFetcher::OptionalSuggestions remote_suggestions =
-      RemoteSuggestion::PtrVector();
-  remote_suggestions->push_back(test::RemoteSuggestionBuilder()
-                                    .AddId(kToUrl)
-                                    .SetUrl(kToUrl)
-                                    .SetAmpUrl(kToUrl)
-                                    .Build());
-  fetcher()->SetFakeResponse(Status::Success(), std::move(remote_suggestions));
+  ContextualSuggestionsFetcher::OptionalSuggestions contextual_suggestions =
+      ContextualSuggestion::PtrVector();
+  contextual_suggestions->push_back(
+      ContextualSuggestion::CreateForTesting(kToUrl, ""));
+  fetcher()->SetFakeResponse(Status::Success(),
+                             std::move(contextual_suggestions));
   EXPECT_CALL(mock_suggestions_callback,
               Run(Property(&Status::IsSuccess, true), GURL(kValidFromUrl),
                   Pointee(ElementsAre(AllOf(
@@ -174,7 +171,8 @@
        ShouldRunCallbackOnEmptyResults) {
   MockFetchContextualSuggestionsCallback mock_suggestions_callback;
   const std::string kEmpty;
-  fetcher()->SetFakeResponse(Status::Success(), RemoteSuggestion::PtrVector());
+  fetcher()->SetFakeResponse(Status::Success(),
+                             ContextualSuggestion::PtrVector());
   EXPECT_CALL(mock_suggestions_callback, Run(Property(&Status::IsSuccess, true),
                                              GURL(kEmpty), Pointee(IsEmpty())));
   source()->FetchContextualSuggestions(
@@ -186,7 +184,7 @@
   MockFetchContextualSuggestionsCallback mock_suggestions_callback;
   const std::string kEmpty;
   fetcher()->SetFakeResponse(Status(StatusCode::TEMPORARY_ERROR, ""),
-                             RemoteSuggestion::PtrVector());
+                             ContextualSuggestion::PtrVector());
   EXPECT_CALL(mock_suggestions_callback,
               Run(Property(&Status::IsSuccess, false), GURL(kEmpty),
                   Pointee(IsEmpty())));
@@ -215,15 +213,12 @@
   const std::string kValidFromUrl = "http://some.url";
   const std::string kToUrl = "http://another.url";
   const std::string kValidImageUrl = "http://some.url/image.png";
-  ContextualSuggestionsFetcher::OptionalSuggestions remote_suggestions =
-      RemoteSuggestion::PtrVector();
-  remote_suggestions->push_back(test::RemoteSuggestionBuilder()
-                                    .AddId(kToUrl)
-                                    .SetUrl(kToUrl)
-                                    .SetAmpUrl(kToUrl)
-                                    .SetImageUrl(kValidImageUrl)
-                                    .Build());
-  fetcher()->SetFakeResponse(Status::Success(), std::move(remote_suggestions));
+  ContextualSuggestionsFetcher::OptionalSuggestions contextual_suggestions =
+      ContextualSuggestion::PtrVector();
+  contextual_suggestions->push_back(
+      ContextualSuggestion::CreateForTesting(kToUrl, kValidImageUrl));
+  fetcher()->SetFakeResponse(Status::Success(),
+                             std::move(contextual_suggestions));
   MockFetchContextualSuggestionsCallback mock_suggestions_callback;
   std::vector<ContentSuggestion> suggestions;
   EXPECT_CALL(mock_suggestions_callback, Run(_, _, _))
diff --git a/components/ntp_snippets/contextual/contextual_suggestion.cc b/components/ntp_snippets/contextual/contextual_suggestion.cc
new file mode 100644
index 0000000..546d7f1
--- /dev/null
+++ b/components/ntp_snippets/contextual/contextual_suggestion.cc
@@ -0,0 +1,94 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/ntp_snippets/contextual/contextual_suggestion.h"
+
+#include "base/memory/ptr_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "components/ntp_snippets/category.h"
+
+namespace {
+
+// dict.Get() specialization for base::Time values
+bool GetTimeValue(const base::DictionaryValue& dict,
+                  const std::string& key,
+                  base::Time* time) {
+  // TODO(gaschler): Replace all usages of GetString(key, &str) by
+  // FindKey(key)->GetString().
+  std::string time_value;
+  return dict.GetString(key, &time_value) &&
+         base::Time::FromString(time_value.c_str(), time);
+}
+
+// dict.Get() specialization for GURL values
+bool GetURLValue(const base::DictionaryValue& dict,
+                 const std::string& key,
+                 GURL* url) {
+  std::string spec;
+  if (!dict.GetString(key, &spec)) {
+    return false;
+  }
+  *url = GURL(spec);
+  return url->is_valid();
+}
+
+}  // namespace
+
+namespace ntp_snippets {
+
+ContextualSuggestion::ContextualSuggestion(const std::string& id) : id_(id) {}
+
+ContextualSuggestion::~ContextualSuggestion() = default;
+
+// static
+std::unique_ptr<ContextualSuggestion>
+ContextualSuggestion::CreateFromDictionary(const base::DictionaryValue& dict) {
+  std::string id;
+  if (!dict.GetString("url", &id) || id.empty()) {
+    return nullptr;
+  }
+  auto suggestion = MakeUnique(id);
+  GetURLValue(dict, "url", &suggestion->url_);
+  if (!dict.GetString("title", &suggestion->title_)) {
+    dict.GetString("source", &suggestion->title_);
+  }
+  dict.GetString("snippet", &suggestion->snippet_);
+  GetTimeValue(dict, "creationTime", &suggestion->publish_date_);
+  GetURLValue(dict, "imageUrl", &suggestion->salient_image_url_);
+  if (!dict.GetString("attribution", &suggestion->publisher_name_)) {
+    dict.GetString("source", &suggestion->publisher_name_);
+  }
+  return suggestion;
+}
+
+ContentSuggestion ContextualSuggestion::ToContentSuggestion() const {
+  ContentSuggestion suggestion(
+      Category::FromKnownCategory(KnownCategories::CONTEXTUAL), id_, url_);
+  suggestion.set_title(base::UTF8ToUTF16(title_));
+  suggestion.set_snippet_text(base::UTF8ToUTF16(snippet_));
+  suggestion.set_publish_date(publish_date_);
+  suggestion.set_publisher_name(base::UTF8ToUTF16(publisher_name_));
+  return suggestion;
+}
+
+// static
+std::unique_ptr<ContextualSuggestion> ContextualSuggestion::CreateForTesting(
+    const std::string& to_url,
+    const std::string& image_url) {
+  auto suggestion = MakeUnique({to_url});
+  suggestion->url_ = GURL(to_url);
+  suggestion->salient_image_url_ = GURL(image_url);
+  return suggestion;
+}
+
+// static
+std::unique_ptr<ContextualSuggestion> ContextualSuggestion::MakeUnique(
+    const std::string& id) {
+  return base::WrapUnique(new ContextualSuggestion(id));
+}
+
+}  // namespace ntp_snippets
diff --git a/components/ntp_snippets/contextual/contextual_suggestion.h b/components/ntp_snippets/contextual/contextual_suggestion.h
new file mode 100644
index 0000000..a7a9472
--- /dev/null
+++ b/components/ntp_snippets/contextual/contextual_suggestion.h
@@ -0,0 +1,81 @@
+// 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_NTP_SNIPPETS_CONTEXTUAL_CONTEXTUAL_SUGGESTION_H_
+#define COMPONENTS_NTP_SNIPPETS_CONTEXTUAL_CONTEXTUAL_SUGGESTION_H_
+
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/optional.h"
+#include "base/time/time.h"
+#include "components/ntp_snippets/content_suggestion.h"
+#include "url/gurl.h"
+
+namespace base {
+class DictionaryValue;
+}  // namespace base
+
+namespace ntp_snippets {
+
+class ContextualSuggestion {
+ public:
+  using PtrVector = std::vector<std::unique_ptr<ContextualSuggestion>>;
+
+  ~ContextualSuggestion();
+
+  // Creates a ContextualSuggestion from a dictionary. Returns a null pointer if
+  // the dictionary doesn't correspond to a valid suggestion.
+  static std::unique_ptr<ContextualSuggestion> CreateFromDictionary(
+      const base::DictionaryValue& dict);
+
+  // Converts to general content suggestion form.
+  ContentSuggestion ToContentSuggestion() const;
+
+  // The ID for identifying the suggestion.
+  const std::string& id() const { return id_; }
+
+  // Title of the suggestion.
+  const std::string& title() const { return title_; }
+
+  // The main URL pointing to the content web page.
+  const GURL& url() const { return url_; }
+
+  // The name of the content's publisher.
+  const std::string& publisher_name() const { return publisher_name_; }
+
+  // Summary or relevant extract from the content.
+  const std::string& snippet() const { return snippet_; }
+
+  // Link to an image representative of the content. Do not fetch directly,
+  // but through the service, which uses caching, to avoid multiple
+  // network requests.
+  const GURL& salient_image_url() const { return salient_image_url_; }
+
+  static std::unique_ptr<ContextualSuggestion> CreateForTesting(
+      const std::string& to_url,
+      const std::string& image_url);
+
+ private:
+  ContextualSuggestion(const std::string& id);
+
+  // base::MakeUnique doesn't work if the ctor is private.
+  static std::unique_ptr<ContextualSuggestion> MakeUnique(
+      const std::string& id);
+
+  std::string id_;
+  std::string title_;
+  GURL url_;
+  std::string publisher_name_;
+  GURL salient_image_url_;
+  std::string snippet_;
+  base::Time publish_date_;
+};
+
+}  // namespace ntp_snippets
+
+#endif  // COMPONENTS_NTP_SNIPPETS_CONTEXTUAL_CONTEXTUAL_SUGGESTION_H_
diff --git a/components/ntp_snippets/contextual/contextual_suggestions_fetcher.h b/components/ntp_snippets/contextual/contextual_suggestions_fetcher.h
index fb5794f..ea40806 100644
--- a/components/ntp_snippets/contextual/contextual_suggestions_fetcher.h
+++ b/components/ntp_snippets/contextual/contextual_suggestions_fetcher.h
@@ -13,7 +13,7 @@
 #include "base/optional.h"
 #include "components/ntp_snippets/category.h"
 #include "components/ntp_snippets/category_info.h"
-#include "components/ntp_snippets/remote/remote_suggestion.h"
+#include "components/ntp_snippets/contextual/contextual_suggestion.h"
 #include "components/ntp_snippets/status.h"
 
 namespace ntp_snippets {
@@ -21,7 +21,7 @@
 // Fetches contextual suggestions from the server.
 class ContextualSuggestionsFetcher {
  public:
-  using OptionalSuggestions = base::Optional<RemoteSuggestion::PtrVector>;
+  using OptionalSuggestions = base::Optional<ContextualSuggestion::PtrVector>;
 
   // If fetching fails, the optional will be empty.
   using SuggestionsAvailableCallback =
diff --git a/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.cc b/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.cc
index dcf9d84..dfbbc8f 100644
--- a/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.cc
+++ b/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.cc
@@ -89,18 +89,20 @@
 // |suggestions|. Returns true on success, false if anything went wrong.
 bool AddSuggestionsFromListValue(bool content_suggestions_api,
                                  const base::ListValue& list,
-                                 RemoteSuggestion::PtrVector* suggestions) {
+                                 ContextualSuggestion::PtrVector* suggestions) {
   for (const auto& value : list) {
     const base::DictionaryValue* dict = nullptr;
     if (!value.GetAsDictionary(&dict)) {
       return false;
     }
 
-    std::string s;
-    dict->GetAsString(&s);
-    DVLOG(1) << "AddSuggestionsFromListValue " << s;
-    std::unique_ptr<RemoteSuggestion> suggestion =
-        RemoteSuggestion::CreateFromContextualSuggestionsDictionary(*dict);
+    if (DLOG_IS_ON(INFO)) {
+      std::string s;
+      dict->GetAsString(&s);
+      DVLOG(1) << "AddSuggestionsFromListValue " << s;
+    }
+    std::unique_ptr<ContextualSuggestion> suggestion =
+        ContextualSuggestion::CreateFromDictionary(*dict);
     suggestions->push_back(std::move(suggestion));
   }
   return true;
@@ -242,7 +244,7 @@
     return;
   }
 
-  OptionalSuggestions optional_suggestions = RemoteSuggestion::PtrVector();
+  OptionalSuggestions optional_suggestions = ContextualSuggestion::PtrVector();
   if (!JsonToSuggestions(*result, &optional_suggestions.value())) {
     DLOG(WARNING) << "Received invalid suggestions: " << last_fetch_json_;
     FetchFinished(OptionalSuggestions(), std::move(callback),
@@ -272,7 +274,7 @@
 
 bool ContextualSuggestionsFetcherImpl::JsonToSuggestions(
     const base::Value& parsed,
-    RemoteSuggestion::PtrVector* suggestions) {
+    ContextualSuggestion::PtrVector* suggestions) {
   const base::DictionaryValue* top_dict = nullptr;
   if (!parsed.GetAsDictionary(&top_dict)) {
     return false;
diff --git a/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.h b/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.h
index 4f7098b..e430c6b5 100644
--- a/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.h
+++ b/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.h
@@ -16,8 +16,8 @@
 #include "components/ntp_snippets/category.h"
 #include "components/ntp_snippets/category_info.h"
 #include "components/ntp_snippets/contextual/contextual_json_request.h"
+#include "components/ntp_snippets/contextual/contextual_suggestion.h"
 #include "components/ntp_snippets/contextual/contextual_suggestions_fetcher.h"
-#include "components/ntp_snippets/remote/remote_suggestion.h"
 #include "components/ntp_snippets/status.h"
 #include "net/url_request/url_request_context_getter.h"
 
@@ -71,7 +71,7 @@
                      const std::string& error_details);
 
   bool JsonToSuggestions(const base::Value& parsed,
-                         RemoteSuggestion::PtrVector* suggestions);
+                         ContextualSuggestion::PtrVector* suggestions);
 
   // Authentication for signed-in users.
   SigninManagerBase* signin_manager_;
diff --git a/components/ntp_tiles/BUILD.gn b/components/ntp_tiles/BUILD.gn
index 300d475..847cc74 100644
--- a/components/ntp_tiles/BUILD.gn
+++ b/components/ntp_tiles/BUILD.gn
@@ -32,6 +32,7 @@
     "switches.cc",
     "switches.h",
     "tile_source.h",
+    "tile_title_source.h",
     "tile_visual_type.h",
     "webui/ntp_tiles_internals_message_handler.cc",
     "webui/ntp_tiles_internals_message_handler.h",
@@ -114,6 +115,7 @@
     sources = [
       "section_type.h",
       "tile_source.h",
+      "tile_title_source.h",
       "tile_visual_type.h",
     ]
   }
diff --git a/components/ntp_tiles/icon_cacher_impl_unittest.cc b/components/ntp_tiles/icon_cacher_impl_unittest.cc
index 929923ef..7b32685 100644
--- a/components/ntp_tiles/icon_cacher_impl_unittest.cc
+++ b/components/ntp_tiles/icon_cacher_impl_unittest.cc
@@ -193,7 +193,8 @@
               GURL("http://url.google/"),
               GURL("http://url.google/icon.png"),
               GURL("http://url.google/favicon.ico"),
-              GURL()),  // thumbnail, unused
+              GURL(),                     // thumbnail, unused
+              TileTitleSource::UNKNOWN),  // title_source, unused
         image_fetcher_(new ::testing::StrictMock<MockImageFetcher>),
         image_decoder_(new ::testing::StrictMock<MockImageDecoder>) {}
 
diff --git a/components/ntp_tiles/metrics.cc b/components/ntp_tiles/metrics.cc
index bcd9f4a..977c33910 100644
--- a/components/ntp_tiles/metrics.cc
+++ b/components/ntp_tiles/metrics.cc
@@ -20,6 +20,8 @@
 // Maximum number of tiles to record in histograms.
 const int kMaxNumTiles = 12;
 
+const int kLastTitleSource = static_cast<int>(TileTitleSource::LAST);
+
 // Identifiers for the various tile sources.
 const char kHistogramClientName[] = "client";
 const char kHistogramServerName[] = "server";
@@ -93,6 +95,7 @@
 }
 
 void RecordTileImpression(int index,
+                          TileTitleSource title_source,
                           TileSource source,
                           TileVisualType type,
                           const GURL& url,
@@ -105,6 +108,14 @@
       "NewTabPage.SuggestionsImpression.%s", source_name.c_str());
   LogHistogramEvent(impression_histogram, index, kMaxNumTiles);
 
+  UMA_HISTOGRAM_ENUMERATION("NewTabPage.TileTitle",
+                            static_cast<int>(title_source),
+                            kLastTitleSource + 1);
+  std::string title_source_histogram = base::StringPrintf(
+      "NewTabPage.TileTitle.%s", GetSourceHistogramName(source).c_str());
+  LogHistogramEvent(title_source_histogram, static_cast<int>(title_source),
+                    kLastTitleSource + 1);
+
   if (type > LAST_RECORDED_TILE_TYPE) {
     return;
   }
@@ -130,7 +141,10 @@
   }
 }
 
-void RecordTileClick(int index, TileSource source, TileVisualType tile_type) {
+void RecordTileClick(int index,
+                     TileTitleSource title_source,
+                     TileSource source,
+                     TileVisualType tile_type) {
   UMA_HISTOGRAM_ENUMERATION("NewTabPage.MostVisited", index, kMaxNumTiles);
 
   std::string histogram = base::StringPrintf(
@@ -144,14 +158,22 @@
     LogHistogramEvent(tile_type_histogram, index, kMaxNumTiles);
   }
 
+  UMA_HISTOGRAM_ENUMERATION("NewTabPage.TileTitleClicked",
+                            static_cast<int>(title_source),
+                            kLastTitleSource + 1);
+  std::string name_histogram = base::StringPrintf(
+      "NewTabPage.TileTitleClicked.%s", GetSourceHistogramName(source).c_str());
+  LogHistogramEvent(name_histogram, static_cast<int>(title_source),
+                    kLastTitleSource + 1);
+
   if (tile_type <= LAST_RECORDED_TILE_TYPE) {
     UMA_HISTOGRAM_ENUMERATION("NewTabPage.TileTypeClicked", tile_type,
                               LAST_RECORDED_TILE_TYPE + 1);
 
-    std::string histogram =
+    std::string type_histogram =
         base::StringPrintf("NewTabPage.TileTypeClicked.%s",
                            GetSourceHistogramName(source).c_str());
-    LogHistogramEvent(histogram, tile_type, LAST_RECORDED_TILE_TYPE + 1);
+    LogHistogramEvent(type_histogram, tile_type, LAST_RECORDED_TILE_TYPE + 1);
   }
 }
 
diff --git a/components/ntp_tiles/metrics.h b/components/ntp_tiles/metrics.h
index eb0bf2d2..543b72aa 100644
--- a/components/ntp_tiles/metrics.h
+++ b/components/ntp_tiles/metrics.h
@@ -9,6 +9,8 @@
 #include <vector>
 
 #include "components/ntp_tiles/ntp_tile.h"
+#include "components/ntp_tiles/tile_source.h"
+#include "components/ntp_tiles/tile_title_source.h"
 #include "components/ntp_tiles/tile_visual_type.h"
 #include "url/gurl.h"
 
@@ -26,13 +28,17 @@
 // should be called only after the visual |type| of the tile has been
 // determined. If |rappor_service| is null, no rappor metrics will be reported.
 void RecordTileImpression(int index,
+                          TileTitleSource tile_source,
                           TileSource source,
                           TileVisualType type,
                           const GURL& url,
                           rappor::RapporService* rappor_service);
 
 // Records a click on a tile.
-void RecordTileClick(int index, TileSource source, TileVisualType tile_type);
+void RecordTileClick(int index,
+                     TileTitleSource tile_source,
+                     TileSource source,
+                     TileVisualType tile_type);
 
 }  // namespace metrics
 }  // namespace ntp_tiles
diff --git a/components/ntp_tiles/metrics_unittest.cc b/components/ntp_tiles/metrics_unittest.cc
index cba9de5..c8dcdd3a 100644
--- a/components/ntp_tiles/metrics_unittest.cc
+++ b/components/ntp_tiles/metrics_unittest.cc
@@ -19,6 +19,15 @@
 namespace metrics {
 namespace {
 
+constexpr int kUnknownTitleSource = static_cast<int>(TileTitleSource::UNKNOWN);
+constexpr int kManifestTitleSource =
+    static_cast<int>(TileTitleSource::MANIFEST);
+constexpr int kMetaTagTitleSource = static_cast<int>(TileTitleSource::META_TAG);
+constexpr int kTitleTagTitleSource =
+    static_cast<int>(TileTitleSource::TITLE_TAG);
+constexpr int kInferredTitleSource =
+    static_cast<int>(TileTitleSource::INFERRED);
+
 using testing::ElementsAre;
 using testing::IsEmpty;
 
@@ -32,22 +41,24 @@
 TEST(RecordTileImpressionTest, ShouldRecordUmaForIcons) {
   base::HistogramTester histogram_tester;
 
-  RecordTileImpression(0, TileSource::TOP_SITES, ICON_REAL, GURL(),
+  RecordTileImpression(0, TileTitleSource::UNKNOWN, TileSource::TOP_SITES,
+                       ICON_REAL, GURL(), /*rappor_service=*/nullptr);
+  RecordTileImpression(1, TileTitleSource::UNKNOWN, TileSource::TOP_SITES,
+                       ICON_REAL, GURL(), /*rappor_service=*/nullptr);
+  RecordTileImpression(2, TileTitleSource::UNKNOWN, TileSource::TOP_SITES,
+                       ICON_REAL, GURL(), /*rappor_service=*/nullptr);
+  RecordTileImpression(3, TileTitleSource::UNKNOWN, TileSource::TOP_SITES,
+                       ICON_COLOR, GURL(), /*rappor_service=*/nullptr);
+  RecordTileImpression(4, TileTitleSource::UNKNOWN, TileSource::TOP_SITES,
+                       ICON_COLOR, GURL(), /*rappor_service=*/nullptr);
+  RecordTileImpression(5, TileTitleSource::UNKNOWN,
+                       TileSource::SUGGESTIONS_SERVICE, ICON_REAL, GURL(),
                        /*rappor_service=*/nullptr);
-  RecordTileImpression(1, TileSource::TOP_SITES, ICON_REAL, GURL(),
+  RecordTileImpression(6, TileTitleSource::UNKNOWN,
+                       TileSource::SUGGESTIONS_SERVICE, ICON_DEFAULT, GURL(),
                        /*rappor_service=*/nullptr);
-  RecordTileImpression(2, TileSource::TOP_SITES, ICON_REAL, GURL(),
-                       /*rappor_service=*/nullptr);
-  RecordTileImpression(3, TileSource::TOP_SITES, ICON_COLOR, GURL(),
-                       /*rappor_service=*/nullptr);
-  RecordTileImpression(4, TileSource::TOP_SITES, ICON_COLOR, GURL(),
-                       /*rappor_service=*/nullptr);
-  RecordTileImpression(5, TileSource::SUGGESTIONS_SERVICE, ICON_REAL, GURL(),
-                       /*rappor_service=*/nullptr);
-  RecordTileImpression(6, TileSource::SUGGESTIONS_SERVICE, ICON_DEFAULT, GURL(),
-                       /*rappor_service=*/nullptr);
-  RecordTileImpression(7, TileSource::POPULAR, ICON_COLOR, GURL(),
-                       /*rappor_service=*/nullptr);
+  RecordTileImpression(7, TileTitleSource::TITLE_TAG, TileSource::POPULAR,
+                       ICON_COLOR, GURL(), /*rappor_service=*/nullptr);
 
   EXPECT_THAT(
       histogram_tester.GetAllSamples("NewTabPage.SuggestionsImpression"),
@@ -106,12 +117,13 @@
 TEST(RecordTileImpressionTest, ShouldRecordUmaForThumbnails) {
   base::HistogramTester histogram_tester;
 
-  RecordTileImpression(0, TileSource::TOP_SITES, THUMBNAIL_FAILED, GURL(),
+  RecordTileImpression(0, TileTitleSource::UNKNOWN, TileSource::TOP_SITES,
+                       THUMBNAIL_FAILED, GURL(), /*rappor_service=*/nullptr);
+  RecordTileImpression(1, TileTitleSource::UNKNOWN,
+                       TileSource::SUGGESTIONS_SERVICE, THUMBNAIL, GURL(),
                        /*rappor_service=*/nullptr);
-  RecordTileImpression(1, TileSource::SUGGESTIONS_SERVICE, THUMBNAIL, GURL(),
-                       /*rappor_service=*/nullptr);
-  RecordTileImpression(2, TileSource::POPULAR, THUMBNAIL, GURL(),
-                       /*rappor_service=*/nullptr);
+  RecordTileImpression(2, TileTitleSource::TITLE_TAG, TileSource::POPULAR,
+                       THUMBNAIL, GURL(), /*rappor_service=*/nullptr);
 
   EXPECT_THAT(
       histogram_tester.GetAllSamples("NewTabPage.SuggestionsImpression"),
@@ -148,9 +160,48 @@
               IsEmpty());
 }
 
+TEST(RecordTileImpressionTest, ShouldRecordImpressionsForTileTitleSource) {
+  base::HistogramTester histogram_tester;
+  RecordTileImpression(0, TileTitleSource::UNKNOWN, TileSource::TOP_SITES,
+                       ICON_REAL, GURL(), /*rappor_service=*/nullptr);
+  RecordTileImpression(1, TileTitleSource::INFERRED,
+                       TileSource::SUGGESTIONS_SERVICE, ICON_REAL, GURL(),
+                       /*rappor_service=*/nullptr);
+  RecordTileImpression(2, TileTitleSource::TITLE_TAG, TileSource::POPULAR,
+                       ICON_REAL, GURL(), /*rappor_service=*/nullptr);
+  RecordTileImpression(3, TileTitleSource::MANIFEST, TileSource::POPULAR,
+                       ICON_REAL, GURL(), /*rappor_service=*/nullptr);
+  RecordTileImpression(4, TileTitleSource::TITLE_TAG,
+                       TileSource::POPULAR_BAKED_IN, ICON_REAL, GURL(),
+                       /*rappor_service=*/nullptr);
+  RecordTileImpression(5, TileTitleSource::META_TAG,
+                       TileSource::POPULAR_BAKED_IN, ICON_REAL, GURL(),
+                       /*rappor_service=*/nullptr);
+
+  EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.TileTitle.client"),
+              ElementsAre(base::Bucket(kUnknownTitleSource, /*count=*/1)));
+  EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.TileTitle.server"),
+              ElementsAre(base::Bucket(kInferredTitleSource, /*count=*/1)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("NewTabPage.TileTitle.popular_fetched"),
+      ElementsAre(base::Bucket(kManifestTitleSource, /*count=*/1),
+                  base::Bucket(kTitleTagTitleSource, /*count=*/1)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("NewTabPage.TileTitle.popular_baked_in"),
+      ElementsAre(base::Bucket(kMetaTagTitleSource, /*count=*/1),
+                  base::Bucket(kTitleTagTitleSource, /*count=*/1)));
+  EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.TileTitle"),
+              ElementsAre(base::Bucket(kUnknownTitleSource, /*count=*/1),
+                          base::Bucket(kManifestTitleSource, /*count=*/1),
+                          base::Bucket(kMetaTagTitleSource, /*count=*/1),
+                          base::Bucket(kTitleTagTitleSource, /*count=*/2),
+                          base::Bucket(kInferredTitleSource, /*count=*/1)));
+}
+
 TEST(RecordTileClickTest, ShouldRecordUmaForIcon) {
   base::HistogramTester histogram_tester;
-  RecordTileClick(3, TileSource::TOP_SITES, ICON_REAL);
+  RecordTileClick(3, TileTitleSource::UNKNOWN, TileSource::TOP_SITES,
+                  ICON_REAL);
   EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.MostVisited"),
               ElementsAre(base::Bucket(/*min=*/3, /*count=*/1)));
   EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.MostVisited.client"),
@@ -179,7 +230,8 @@
 
 TEST(RecordTileClickTest, ShouldRecordUmaForThumbnail) {
   base::HistogramTester histogram_tester;
-  RecordTileClick(3, TileSource::TOP_SITES, THUMBNAIL);
+  RecordTileClick(3, TileTitleSource::UNKNOWN, TileSource::TOP_SITES,
+                  THUMBNAIL);
   EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.MostVisited"),
               ElementsAre(base::Bucket(/*min=*/3, /*count=*/1)));
   EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.MostVisited.client"),
@@ -208,7 +260,8 @@
 
 TEST(RecordTileClickTest, ShouldNotRecordUnknownTileType) {
   base::HistogramTester histogram_tester;
-  RecordTileClick(3, TileSource::TOP_SITES, UNKNOWN_TILE_TYPE);
+  RecordTileClick(3, TileTitleSource::UNKNOWN, TileSource::TOP_SITES,
+                  UNKNOWN_TILE_TYPE);
   // The click should still get recorded.
   EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.MostVisited"),
               ElementsAre(base::Bucket(/*min=*/3, /*count=*/1)));
@@ -240,12 +293,15 @@
 TEST(RecordTileImpressionTest, ShouldRecordRappor) {
   rappor::TestRapporServiceImpl rappor_service;
 
-  RecordTileImpression(0, TileSource::TOP_SITES, ICON_REAL,
-                       GURL("http://www.site1.com/"), &rappor_service);
-  RecordTileImpression(1, TileSource::TOP_SITES, ICON_COLOR,
-                       GURL("http://www.site2.com/"), &rappor_service);
-  RecordTileImpression(2, TileSource::TOP_SITES, ICON_DEFAULT,
-                       GURL("http://www.site3.com/"), &rappor_service);
+  RecordTileImpression(0, TileTitleSource::UNKNOWN, TileSource::TOP_SITES,
+                       ICON_REAL, GURL("http://www.site1.com/"),
+                       &rappor_service);
+  RecordTileImpression(1, TileTitleSource::UNKNOWN, TileSource::TOP_SITES,
+                       ICON_COLOR, GURL("http://www.site2.com/"),
+                       &rappor_service);
+  RecordTileImpression(2, TileTitleSource::UNKNOWN, TileSource::TOP_SITES,
+                       ICON_DEFAULT, GURL("http://www.site3.com/"),
+                       &rappor_service);
 
   EXPECT_EQ(3, rappor_service.GetReportsCount());
 
@@ -280,15 +336,50 @@
 TEST(RecordTileImpressionTest, ShouldNotRecordRapporForUnknownTileType) {
   rappor::TestRapporServiceImpl rappor_service;
 
-  RecordTileImpression(0, TileSource::TOP_SITES, ICON_REAL,
-                       GURL("http://www.s1.com/"), &rappor_service);
-  RecordTileImpression(1, TileSource::TOP_SITES, UNKNOWN_TILE_TYPE,
-                       GURL("http://www.s2.com/"), &rappor_service);
+  RecordTileImpression(0, TileTitleSource::UNKNOWN, TileSource::TOP_SITES,
+                       ICON_REAL, GURL("http://www.s1.com/"), &rappor_service);
+  RecordTileImpression(1, TileTitleSource::UNKNOWN, TileSource::TOP_SITES,
+                       UNKNOWN_TILE_TYPE, GURL("http://www.s2.com/"),
+                       &rappor_service);
 
   // Unknown tile type shouldn't get reported.
   EXPECT_EQ(1, rappor_service.GetReportsCount());
 }
 
+TEST(RecordTileClickTest, ShouldRecordClicksForTileTitleSource) {
+  base::HistogramTester histogram_tester;
+  RecordTileClick(0, TileTitleSource::UNKNOWN, TileSource::TOP_SITES,
+                  ICON_REAL);
+  RecordTileClick(1, TileTitleSource::UNKNOWN, TileSource::SUGGESTIONS_SERVICE,
+                  ICON_REAL);
+  RecordTileClick(2, TileTitleSource::TITLE_TAG, TileSource::POPULAR,
+                  ICON_REAL);
+  RecordTileClick(3, TileTitleSource::MANIFEST, TileSource::POPULAR, ICON_REAL);
+  RecordTileClick(4, TileTitleSource::TITLE_TAG, TileSource::POPULAR_BAKED_IN,
+                  ICON_REAL);
+  RecordTileClick(5, TileTitleSource::META_TAG, TileSource::POPULAR_BAKED_IN,
+                  ICON_REAL);
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("NewTabPage.TileTitleClicked.client"),
+      ElementsAre(base::Bucket(kUnknownTitleSource, /*count=*/1)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("NewTabPage.TileTitleClicked.server"),
+      ElementsAre(base::Bucket(kUnknownTitleSource, /*count=*/1)));
+  EXPECT_THAT(histogram_tester.GetAllSamples(
+                  "NewTabPage.TileTitleClicked.popular_fetched"),
+              ElementsAre(base::Bucket(kManifestTitleSource, /*count=*/1),
+                          base::Bucket(kTitleTagTitleSource, /*count=*/1)));
+  EXPECT_THAT(histogram_tester.GetAllSamples(
+                  "NewTabPage.TileTitleClicked.popular_baked_in"),
+              ElementsAre(base::Bucket(kMetaTagTitleSource, /*count=*/1),
+                          base::Bucket(kTitleTagTitleSource, /*count=*/1)));
+  EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.TileTitleClicked"),
+              ElementsAre(base::Bucket(kUnknownTitleSource, /*count=*/2),
+                          base::Bucket(kManifestTitleSource, /*count=*/1),
+                          base::Bucket(kMetaTagTitleSource, /*count=*/1),
+                          base::Bucket(kTitleTagTitleSource, /*count=*/2)));
+}
+
 }  // namespace
 }  // namespace metrics
 }  // namespace ntp_tiles
diff --git a/components/ntp_tiles/most_visited_sites.cc b/components/ntp_tiles/most_visited_sites.cc
index 7327615ba..a6fd4753 100644
--- a/components/ntp_tiles/most_visited_sites.cc
+++ b/components/ntp_tiles/most_visited_sites.cc
@@ -291,6 +291,9 @@
     tile.url = visited.url;
     tile.source = TileSource::TOP_SITES;
     tile.whitelist_icon_path = GetWhitelistLargeIconPath(visited.url);
+    // MostVisitedURL.title is either the title or the URL which is treated
+    // exactly as the title. Differentiating here is not worth the overhead.
+    tile.title_source = TileTitleSource::TITLE_TAG;
 
     tiles.push_back(std::move(tile));
   }
@@ -339,6 +342,8 @@
     tile.title = base::UTF8ToUTF16(suggestion_pb.title());
     tile.url = url;
     tile.source = TileSource::SUGGESTIONS_SERVICE;
+    // The title is an aggregation of multiple history entries of one site.
+    tile.title_source = TileTitleSource::INFERRED;
     tile.whitelist_icon_path = GetWhitelistLargeIconPath(url);
     tile.thumbnail_url = GURL(suggestion_pb.thumbnail());
     tile.favicon_url = GURL(suggestion_pb.favicon_url());
@@ -383,6 +388,8 @@
     tile.title = whitelist.title;
     tile.url = whitelist.entry_point;
     tile.source = TileSource::WHITELIST;
+    // User-set. Might be the title but we cannot be sure.
+    tile.title_source = TileTitleSource::UNKNOWN;
     tile.whitelist_icon_path = whitelist.large_icon_path;
     whitelist_tiles.push_back(std::move(tile));
   }
@@ -448,6 +455,7 @@
     NTPTile tile;
     tile.title = popular_site.title;
     tile.url = GURL(popular_site.url);
+    tile.title_source = popular_site.title_source;
     tile.source = popular_site.baked_in ? TileSource::POPULAR_BAKED_IN
                                         : TileSource::POPULAR;
     popular_sites_tiles.push_back(std::move(tile));
@@ -504,6 +512,7 @@
     home_tile.url = home_page_url;
     home_tile.title = title;
     home_tile.source = TileSource::HOMEPAGE;
+    home_tile.title_source = TileTitleSource::TITLE_TAG;  // From history.
 
     new_tiles.push_back(std::move(home_tile));
   }
diff --git a/components/ntp_tiles/ntp_tile.cc b/components/ntp_tiles/ntp_tile.cc
index ea2a62f2..ce64160 100644
--- a/components/ntp_tiles/ntp_tile.cc
+++ b/components/ntp_tiles/ntp_tile.cc
@@ -6,7 +6,8 @@
 
 namespace ntp_tiles {
 
-NTPTile::NTPTile() : source(TileSource::TOP_SITES) {}
+NTPTile::NTPTile()
+    : title_source(TileTitleSource::UNKNOWN), source(TileSource::TOP_SITES) {}
 
 NTPTile::NTPTile(const NTPTile&) = default;
 
@@ -14,6 +15,7 @@
 
 bool operator==(const NTPTile& a, const NTPTile& b) {
   return (a.title == b.title) && (a.url == b.url) && (a.source == b.source) &&
+         (a.title_source == b.title_source) &&
          (a.whitelist_icon_path == b.whitelist_icon_path) &&
          (a.thumbnail_url == b.thumbnail_url) &&
          (a.favicon_url == b.favicon_url);
diff --git a/components/ntp_tiles/ntp_tile.h b/components/ntp_tiles/ntp_tile.h
index a80fc0f0..4dc012c1 100644
--- a/components/ntp_tiles/ntp_tile.h
+++ b/components/ntp_tiles/ntp_tile.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/strings/string16.h"
 #include "components/ntp_tiles/tile_source.h"
+#include "components/ntp_tiles/tile_title_source.h"
 #include "url/gurl.h"
 
 namespace ntp_tiles {
@@ -19,6 +20,7 @@
 struct NTPTile {
   base::string16 title;
   GURL url;
+  TileTitleSource title_source;
   TileSource source;
 
   // Empty unless whitelists are enabled and this site is in a whitelist.
diff --git a/components/ntp_tiles/popular_sites.h b/components/ntp_tiles/popular_sites.h
index 7e6b21db2..4c61f3d 100644
--- a/components/ntp_tiles/popular_sites.h
+++ b/components/ntp_tiles/popular_sites.h
@@ -13,6 +13,7 @@
 #include "base/macros.h"
 #include "base/strings/string16.h"
 #include "components/ntp_tiles/section_type.h"
+#include "components/ntp_tiles/tile_title_source.h"
 #include "url/gurl.h"
 
 namespace base {
@@ -30,7 +31,8 @@
          const GURL& url,
          const GURL& favicon_url,
          const GURL& large_icon_url,
-         const GURL& thumbnail_url);
+         const GURL& thumbnail_url,
+         TileTitleSource title_source);
     Site(const Site& other);
     ~Site();
 
@@ -39,6 +41,8 @@
     GURL favicon_url;
     GURL large_icon_url;
     GURL thumbnail_url;
+
+    TileTitleSource title_source;
     bool baked_in;
     int default_icon_resource;  // < 0 if there is none. Used for popular sites.
   };
diff --git a/components/ntp_tiles/popular_sites_impl.cc b/components/ntp_tiles/popular_sites_impl.cc
index 0c42334..498b4ca 100644
--- a/components/ntp_tiles/popular_sites_impl.cc
+++ b/components/ntp_tiles/popular_sites_impl.cc
@@ -129,8 +129,18 @@
     std::string large_icon_url;
     item->GetString("large_icon_url", &large_icon_url);
 
+    TileTitleSource title_source = TileTitleSource::UNKNOWN;
+    int title_source_int;
+    if (!item->GetInteger("title_source", &title_source_int)) {
+      // Only v6 and later have "title_source". Earlier versions use title tags.
+      title_source = TileTitleSource::TITLE_TAG;
+    } else if (title_source_int <= static_cast<int>(TileTitleSource::LAST) &&
+               title_source_int >= 0) {
+      title_source = static_cast<TileTitleSource>(title_source_int);
+    }
+
     sites.emplace_back(title, GURL(url), GURL(favicon_url),
-                       GURL(large_icon_url), GURL(thumbnail_url));
+                       GURL(large_icon_url), GURL(thumbnail_url), title_source);
     item->GetInteger("default_icon_resource",
                      &sites.back().default_icon_resource);
     item->GetBoolean("baked_in", &sites.back().baked_in);
@@ -241,12 +251,14 @@
                          const GURL& url,
                          const GURL& favicon_url,
                          const GURL& large_icon_url,
-                         const GURL& thumbnail_url)
+                         const GURL& thumbnail_url,
+                         TileTitleSource title_source)
     : title(title),
       url(url),
       favicon_url(favicon_url),
       large_icon_url(large_icon_url),
       thumbnail_url(thumbnail_url),
+      title_source(title_source),
       baked_in(false),
       default_icon_resource(-1) {}
 
diff --git a/components/ntp_tiles/popular_sites_impl_unittest.cc b/components/ntp_tiles/popular_sites_impl_unittest.cc
index e7f3997..c8adc8ce 100644
--- a/components/ntp_tiles/popular_sites_impl_unittest.cc
+++ b/components/ntp_tiles/popular_sites_impl_unittest.cc
@@ -54,6 +54,7 @@
 const char kFaviconUrl[] = "favicon_url";
 const char kSection[] = "section";
 const char kSites[] = "sites";
+const char kTitleSource[] = "title_source";
 
 using TestPopularSite = std::map<std::string, std::string>;
 using TestPopularSiteVector = std::vector<TestPopularSite>;
@@ -83,16 +84,19 @@
             {kTitle, "Wikipedia, fhta Ph'nglui mglw'nafh"},
             {kUrl, "https://zz.m.wikipedia.org/"},
             {kLargeIconUrl, "https://zz.m.wikipedia.org/wikipedia.png"},
+            {kTitleSource, "3"},  // Title extracted from title tag.
         },
         kYouTube{
             {kTitle, "YouTube"},
             {kUrl, "https://m.youtube.com/"},
             {kLargeIconUrl, "https://s.ytimg.com/apple-touch-icon.png"},
+            {kTitleSource, "1"},  // Title extracted from manifest.
         },
         kChromium{
             {kTitle, "The Chromium Project"},
             {kUrl, "https://www.chromium.org/"},
             {kFaviconUrl, "https://www.chromium.org/favicon.ico"},
+            // No "title_source" (like in v5 or earlier). Defaults to TITLE_TAG.
         },
         prefs_(new sync_preferences::TestingPrefServiceSyncable()),
         url_fetcher_factory_(nullptr) {
@@ -113,6 +117,13 @@
     for (const TestPopularSite& site : sites) {
       auto site_value = base::MakeUnique<base::DictionaryValue>();
       for (const std::pair<std::string, std::string>& kv : site) {
+        if (kv.first == kTitleSource) {
+          int source;
+          bool convert_success = base::StringToInt(kv.second, &source);
+          DCHECK(convert_success);
+          site_value->SetInteger(kv.first, source);
+          continue;
+        }
         site_value->SetString(kv.first, kv.second);
       }
       sites_value->Append(std::move(site_value));
@@ -256,6 +267,7 @@
   EXPECT_THAT(sites[0].large_icon_url,
               URLEq("https://zz.m.wikipedia.org/wikipedia.png"));
   EXPECT_THAT(sites[0].favicon_url, URLEq(""));
+  EXPECT_THAT(sites[0].title_source, Eq(TileTitleSource::TITLE_TAG));
 }
 
 TEST_F(PopularSitesTest, Fallback) {
@@ -276,11 +288,15 @@
   EXPECT_THAT(sites[0].large_icon_url,
               URLEq("https://s.ytimg.com/apple-touch-icon.png"));
   EXPECT_THAT(sites[0].favicon_url, URLEq(""));
+  EXPECT_THAT(sites[0].title_source, Eq(TileTitleSource::MANIFEST));
   EXPECT_THAT(sites[1].title, Str16Eq("The Chromium Project"));
   EXPECT_THAT(sites[1].url, URLEq("https://www.chromium.org/"));
   EXPECT_THAT(sites[1].large_icon_url, URLEq(""));
   EXPECT_THAT(sites[1].favicon_url,
               URLEq("https://www.chromium.org/favicon.ico"));
+  // Fall back to TITLE_TAG if there is no "title_source". Version 5 or before
+  // haven't had this property and get titles from <title> tags exclusively.
+  EXPECT_THAT(sites[1].title_source, Eq(TileTitleSource::TITLE_TAG));
 }
 
 TEST_F(PopularSitesTest, PopulatesWithDefaultResoucesOnFailure) {
diff --git a/components/ntp_tiles/tile_title_source.h b/components/ntp_tiles/tile_title_source.h
new file mode 100644
index 0000000..ed5fdd90
--- /dev/null
+++ b/components/ntp_tiles/tile_title_source.h
@@ -0,0 +1,40 @@
+// 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_NTP_TILES_TILE_TITLE_SOURCE_H_
+#define COMPONENTS_NTP_TILES_TILE_TITLE_SOURCE_H_
+
+namespace ntp_tiles {
+
+// The source where the displayed title of an NTP tile originates from.
+//
+// These values must stay in sync with the NTPTileTitleSource enums in
+// enums.xml AND in chrome/browser/resources/local_ntp/most_visited_single.js.
+//
+// A Java counterpart will be generated for this enum.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.suggestions
+enum class TileTitleSource {
+  // The title might be invalid, aggregated, user-set, extracted from history,
+  // not loaded or simply not known.
+  UNKNOWN = 0,
+
+  // The site's manifest contained a usable "(short_)name" attribute.
+  MANIFEST = 1,
+
+  // The site provided a meta tag (e.g. OpenGraph's site_name).
+  META_TAG = 2,
+
+  // The site's title is used as tile title, extracted from the title tag.
+  TITLE_TAG = 3,
+
+  // The title was inferred from multiple signals (e.g. meta tags, url, title).
+  INFERRED = 4,
+
+  // The maximum tile title source value that gets recorded in UMA.
+  LAST = INFERRED
+};
+
+}  // namespace ntp_tiles
+
+#endif  // COMPONENTS_NTP_TILES_TILE_TITLE_SOURCE_H_
diff --git a/components/omnibox/browser/BUILD.gn b/components/omnibox/browser/BUILD.gn
index 1232563..1d2f403 100644
--- a/components/omnibox/browser/BUILD.gn
+++ b/components/omnibox/browser/BUILD.gn
@@ -145,6 +145,7 @@
     "//components/data_use_measurement/core",
     "//components/keyed_service/core",
     "//components/metrics",
+    "//components/navigation_metrics",
     "//components/open_from_clipboard",
     "//components/physical_web/data_source",
     "//components/pref_registry",
diff --git a/components/omnibox/browser/DEPS b/components/omnibox/browser/DEPS
index a8524c1a..f6d92f6 100644
--- a/components/omnibox/browser/DEPS
+++ b/components/omnibox/browser/DEPS
@@ -7,6 +7,7 @@
   "+components/history/core/test",
   "+components/keyed_service/core",
   "+components/metrics",
+  "+components/navigation_metrics",
   "+components/open_from_clipboard",
   "+components/physical_web/data_source",
   "+components/pref_registry",
diff --git a/components/omnibox/browser/omnibox_edit_model.cc b/components/omnibox/browser/omnibox_edit_model.cc
index 3daef43..41ddad1a7 100644
--- a/components/omnibox/browser/omnibox_edit_model.cc
+++ b/components/omnibox/browser/omnibox_edit_model.cc
@@ -20,6 +20,7 @@
 #include "build/build_config.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/metrics/proto/omnibox_event.pb.h"
+#include "components/navigation_metrics/navigation_metrics.h"
 #include "components/omnibox/browser/autocomplete_classifier.h"
 #include "components/omnibox/browser/autocomplete_match_type.h"
 #include "components/omnibox/browser/autocomplete_provider.h"
@@ -662,6 +663,15 @@
         SEARCH_ENGINE_OTHER;
     UMA_HISTOGRAM_ENUMERATION("Omnibox.SearchEngineType", search_engine_type,
                               SEARCH_ENGINE_MAX);
+  } else {
+    // |match| is a URL navigation, not a search.
+    // For logging the below histogram, only record uses that depend on the
+    // omnibox suggestion system, i.e., TYPED navigations.  That is, exclude
+    // omnibox URL interactions that are treated as reloads or link-following
+    // (i.e., cut-and-paste of URLs).
+    if (ui::PageTransitionTypeIncludingQualifiersIs(match.transition,
+                                                    ui::PAGE_TRANSITION_TYPED))
+      navigation_metrics::RecordOmniboxURLNavigation(match.destination_url);
   }
 
   if (disposition != WindowOpenDisposition::NEW_BACKGROUND_TAB) {
diff --git a/components/payments/content/payment_request_state.cc b/components/payments/content/payment_request_state.cc
index 5c7f3f3f..af72000 100644
--- a/components/payments/content/payment_request_state.cc
+++ b/components/payments/content/payment_request_state.cc
@@ -298,7 +298,7 @@
   // Start the normalization of the shipping address.
   // Use the country code from the profile if it is set, otherwise infer it
   // from the |app_locale_|.
-  std::string country_code = data_util::GetCountryCodeWithFallback(
+  std::string country_code = autofill::data_util::GetCountryCodeWithFallback(
       selected_shipping_profile_, app_locale_);
   payment_request_delegate_->GetAddressNormalizer()->StartAddressNormalization(
       *selected_shipping_profile_, country_code, /*timeout_seconds=*/2, this);
@@ -331,7 +331,7 @@
   return !!response_helper_;
 }
 
-AddressNormalizer* PaymentRequestState::GetAddressNormalizer() {
+autofill::AddressNormalizer* PaymentRequestState::GetAddressNormalizer() {
   return payment_request_delegate_->GetAddressNormalizer();
 }
 
diff --git a/components/payments/content/payment_request_state.h b/components/payments/content/payment_request_state.h
index a3e206c..d9348e7a 100644
--- a/components/payments/content/payment_request_state.h
+++ b/components/payments/content/payment_request_state.h
@@ -11,9 +11,9 @@
 
 #include "base/macros.h"
 #include "base/observer_list.h"
+#include "components/autofill/core/browser/address_normalizer.h"
 #include "components/payments/content/payment_request_spec.h"
 #include "components/payments/content/payment_response_helper.h"
-#include "components/payments/core/address_normalizer.h"
 #include "components/payments/core/payments_profile_comparator.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/payment_app_provider.h"
@@ -37,7 +37,7 @@
 // what the merchant has specified, as input into the "is ready to pay"
 // computation.
 class PaymentRequestState : public PaymentResponseHelper::Delegate,
-                            public AddressNormalizer::Delegate,
+                            public autofill::AddressNormalizer::Delegate,
                             public PaymentRequestSpec::Observer {
  public:
   // Any class call add itself as Observer via AddObserver() and receive
@@ -89,7 +89,7 @@
   void OnPaymentResponseReady(
       mojom::PaymentResponsePtr payment_response) override;
 
-  // AddressNormalizer::Delegate
+  // autofill::AddressNormalizer::Delegate
   void OnAddressNormalized(
       const autofill::AutofillProfile& normalized_profile) override;
   void OnCouldNotNormalize(const autofill::AutofillProfile& profile) override;
@@ -200,7 +200,7 @@
   // generation has begun. False otherwise.
   bool IsPaymentAppInvoked() const;
 
-  AddressNormalizer* GetAddressNormalizer();
+  autofill::AddressNormalizer* GetAddressNormalizer();
 
  private:
   // Fetches the Autofill Profiles for this user from the PersonalDataManager,
diff --git a/components/payments/content/payment_response_helper.cc b/components/payments/content/payment_response_helper.cc
index 06a6687..2d0148f91 100644
--- a/components/payments/content/payment_response_helper.cc
+++ b/components/payments/content/payment_response_helper.cc
@@ -5,6 +5,7 @@
 #include "components/payments/content/payment_response_helper.h"
 
 #include <string>
+#include <utility>
 
 #include "base/logging.h"
 #include "base/strings/string_split.h"
@@ -12,6 +13,7 @@
 #include "components/autofill/core/browser/autofill_country.h"
 #include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/browser/phone_number_i18n.h"
 #include "components/payments/content/payment_request_spec.h"
 #include "components/payments/core/payment_request_data_util.h"
 #include "components/payments/core/payment_request_delegate.h"
@@ -190,8 +192,8 @@
 
     const std::string default_region_code =
         autofill::AutofillCountry::CountryCodeForLocale(app_locale_);
-    payment_response->payer_phone =
-        data_util::FormatPhoneForResponse(original_number, default_region_code);
+    payment_response->payer_phone = autofill::i18n::FormatPhoneForResponse(
+        original_number, default_region_code);
   }
 
   delegate_->OnPaymentResponseReady(std::move(payment_response));
diff --git a/components/payments/content/payment_response_helper.h b/components/payments/content/payment_response_helper.h
index fb87bdb..cf3fb261 100644
--- a/components/payments/content/payment_response_helper.h
+++ b/components/payments/content/payment_response_helper.h
@@ -6,8 +6,8 @@
 #define COMPONENTS_PAYMENTS_CONTENT_PAYMENT_RESPONSE_HELPER_H_
 
 #include "base/macros.h"
+#include "components/autofill/core/browser/address_normalizer.h"
 #include "components/autofill/core/browser/autofill_profile.h"
-#include "components/payments/core/address_normalizer.h"
 #include "components/payments/core/payment_instrument.h"
 #include "third_party/WebKit/public/platform/modules/payments/payment_request.mojom.h"
 
@@ -18,7 +18,7 @@
 
 // A helper class to facilitate the creation of the PaymentResponse.
 class PaymentResponseHelper : public PaymentInstrument::Delegate,
-                              public AddressNormalizer::Delegate {
+                              public autofill::AddressNormalizer::Delegate {
  public:
   class Delegate {
    public:
diff --git a/components/payments/core/BUILD.gn b/components/payments/core/BUILD.gn
index b49e0ef..979d4a4 100644
--- a/components/payments/core/BUILD.gn
+++ b/components/payments/core/BUILD.gn
@@ -6,9 +6,6 @@
   sources = [
     "address_normalization_manager.cc",
     "address_normalization_manager.h",
-    "address_normalizer.h",
-    "address_normalizer_impl.cc",
-    "address_normalizer_impl.h",
     "autofill_payment_instrument.cc",
     "autofill_payment_instrument.h",
     "basic_card_response.cc",
@@ -86,8 +83,6 @@
   sources = [
     "payments_test_util.cc",
     "payments_test_util.h",
-    "test_address_normalizer.cc",
-    "test_address_normalizer.h",
     "test_payment_request_delegate.cc",
     "test_payment_request_delegate.h",
   ]
@@ -107,7 +102,6 @@
   testonly = true
   sources = [
     "address_normalization_manager_unittest.cc",
-    "address_normalizer_impl_unittest.cc",
     "autofill_payment_instrument_unittest.cc",
     "basic_card_response_unittest.cc",
     "can_make_payment_query_unittest.cc",
diff --git a/components/payments/core/address_normalization_manager.cc b/components/payments/core/address_normalization_manager.cc
index 97f68f06..9c8ed47 100644
--- a/components/payments/core/address_normalization_manager.cc
+++ b/components/payments/core/address_normalization_manager.cc
@@ -4,9 +4,12 @@
 
 #include "components/payments/core/address_normalization_manager.h"
 
+#include <utility>
+
 #include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/autofill/core/browser/autofill_data_util.h"
+#include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/field_types.h"
 
 namespace payments {
@@ -16,7 +19,7 @@
 }  // namespace
 
 AddressNormalizationManager::AddressNormalizationManager(
-    AddressNormalizer* address_normalizer,
+    autofill::AddressNormalizer* address_normalizer,
     const std::string& default_country_code)
     : default_country_code_(default_country_code),
       address_normalizer_(address_normalizer) {
@@ -65,7 +68,7 @@
 
 AddressNormalizationManager::NormalizerDelegate::NormalizerDelegate(
     AddressNormalizationManager* owner,
-    AddressNormalizer* address_normalizer,
+    autofill::AddressNormalizer* address_normalizer,
     autofill::AutofillProfile* profile)
     : owner_(owner), profile_(profile) {
   DCHECK(owner_);
diff --git a/components/payments/core/address_normalization_manager.h b/components/payments/core/address_normalization_manager.h
index 63ff0f1..d8ff71f 100644
--- a/components/payments/core/address_normalization_manager.h
+++ b/components/payments/core/address_normalization_manager.h
@@ -11,16 +11,15 @@
 
 #include "base/callback.h"
 #include "base/threading/thread_checker.h"
-#include "components/payments/core/address_normalizer.h"
+#include "components/autofill/core/browser/address_normalizer.h"
 
 namespace autofill {
+class AddressNormalizer;
 class AutofillProfile;
 }  // namespace autofill
 
 namespace payments {
 
-class AddressNormalizer;
-
 // Class to handle multiple concurrent address normalization requests. This
 // class is not thread-safe.
 class AddressNormalizationManager {
@@ -28,7 +27,7 @@
   // Initializes an AddressNormalizationManager. |default_country_code| will be
   // used if the country code in an AutofillProfile to normalize is not valid.
   // The AddressNormalizationManager does not own |address_normalizer|.
-  AddressNormalizationManager(AddressNormalizer* address_normalizer,
+  AddressNormalizationManager(autofill::AddressNormalizer* address_normalizer,
                               const std::string& default_country_code);
 
   ~AddressNormalizationManager();
@@ -49,20 +48,20 @@
   // Implements the payments::AddressNormalizer::Delegate interface, and
   // notifies its parent AddressNormalizationManager when normalization has
   // completed.
-  class NormalizerDelegate : public AddressNormalizer::Delegate {
+  class NormalizerDelegate : public autofill::AddressNormalizer::Delegate {
    public:
     // |owner| is the parent AddressNormalizationManager, |address_normalizer|
     // is a pointer to an instance of AddressNormalizer which will handle
     // normalization of |profile|. |profile| will be updated when normalization
     // is complete.
     NormalizerDelegate(AddressNormalizationManager* owner,
-                       AddressNormalizer* address_normalizer,
+                       autofill::AddressNormalizer* address_normalizer,
                        autofill::AutofillProfile* profile);
 
     // Returns whether this delegate has completed or not.
     bool has_completed() const { return has_completed_; }
 
-    // payments::AddressNormalizer::Delegate:
+    // AddressNormalizer::Delegate:
     void OnAddressNormalized(
         const autofill::AutofillProfile& normalized_profile) override;
     void OnCouldNotNormalize(const autofill::AutofillProfile& profile) override;
@@ -96,7 +95,7 @@
   std::vector<std::unique_ptr<NormalizerDelegate>> delegates_;
 
   // An unowned raw pointer to the AddressNormalizer to use.
-  AddressNormalizer* address_normalizer_;
+  autofill::AddressNormalizer* address_normalizer_;
 
   THREAD_CHECKER(thread_checker_);
   DISALLOW_COPY_AND_ASSIGN(AddressNormalizationManager);
diff --git a/components/payments/core/address_normalization_manager_unittest.cc b/components/payments/core/address_normalization_manager_unittest.cc
index 4e58c24..66c7f62 100644
--- a/components/payments/core/address_normalization_manager_unittest.cc
+++ b/components/payments/core/address_normalization_manager_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/memory/ptr_util.h"
-#include "components/payments/core/test_address_normalizer.h"
+#include "components/autofill/core/browser/test_address_normalizer.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace payments {
@@ -17,7 +17,7 @@
   AddressNormalizationManagerTest() {}
 
   void Initialize(const std::string& country_code) {
-    address_normalizer_ = base::MakeUnique<TestAddressNormalizer>();
+    address_normalizer_ = base::MakeUnique<autofill::TestAddressNormalizer>();
     manager_ = base::MakeUnique<AddressNormalizationManager>(
         address_normalizer_.get(), country_code);
   }
@@ -30,7 +30,7 @@
 
   void CompletionCallback() { completion_callback_called_ = true; }
 
-  std::unique_ptr<TestAddressNormalizer> address_normalizer_;
+  std::unique_ptr<autofill::TestAddressNormalizer> address_normalizer_;
   std::unique_ptr<AddressNormalizationManager> manager_;
   bool completion_callback_called_ = false;
 };
diff --git a/components/payments/core/address_normalizer.h b/components/payments/core/address_normalizer.h
deleted file mode 100644
index c46371cf..0000000
--- a/components/payments/core/address_normalizer.h
+++ /dev/null
@@ -1,65 +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_PAYMENTS_CORE_ADDRESS_NORMALIZER_H_
-#define COMPONENTS_PAYMENTS_CORE_ADDRESS_NORMALIZER_H_
-
-#include <string>
-
-#include "third_party/libaddressinput/chromium/chrome_address_validator.h"
-
-namespace autofill {
-class AutofillProfile;
-}
-
-namespace payments {
-
-// A class used to normalize addresses.
-class AddressNormalizer : public autofill::LoadRulesListener {
- public:
-  // The interface for the normalization delegates.
-  class Delegate {
-   public:
-    virtual void OnAddressNormalized(
-        const autofill::AutofillProfile& normalized_profile) = 0;
-
-    virtual void OnCouldNotNormalize(
-        const autofill::AutofillProfile& profile) = 0;
-
-   protected:
-    virtual ~Delegate() {}
-  };
-
-  // The interface for the normalization request.
-  class Request {
-   public:
-    virtual void OnRulesLoaded(bool success) = 0;
-    virtual ~Request() {}
-  };
-
-  // Start loading the validation rules for the specified |region_code|.
-  virtual void LoadRulesForRegion(const std::string& region_code) = 0;
-
-  // Returns whether the rules for the specified |region_code| have finished
-  // loading.
-  virtual bool AreRulesLoadedForRegion(const std::string& region_code) = 0;
-
-  // Starts the normalization of the |profile| based on the |region_code|. The
-  // normalized profile will be returned to the |requester| possibly
-  // asynchronously. If the normalization is not completed in |timeout_seconds|
-  // the requester will be informed and the request cancelled. This value should
-  // be greater or equal to 0, for which it means that the normalization should
-  // happen synchronously, or not at all if the rules are not already loaded.
-  // Will start loading the rules for the |region_code| if they had not started
-  // loading.
-  virtual void StartAddressNormalization(
-      const autofill::AutofillProfile& profile,
-      const std::string& region_code,
-      int timeout_seconds,
-      Delegate* requester) = 0;
-};
-
-}  // namespace payments
-
-#endif  // COMPONENTS_PAYMENTS_CORE_ADDRESS_NORMALIZER_H_
diff --git a/components/payments/core/address_normalizer_impl.cc b/components/payments/core/address_normalizer_impl.cc
deleted file mode 100644
index 12961bd..0000000
--- a/components/payments/core/address_normalizer_impl.cc
+++ /dev/null
@@ -1,189 +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/payments/core/address_normalizer_impl.h"
-
-#include <stddef.h>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/cancelable_callback.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-#include "base/time/time.h"
-#include "components/autofill/core/browser/address_i18n.h"
-#include "components/autofill/core/browser/autofill_profile.h"
-#include "components/payments/core/payment_request_data_util.h"
-#include "third_party/libaddressinput/chromium/chrome_address_validator.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/source.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h"
-
-namespace payments {
-namespace {
-
-using ::autofill::AutofillProfile;
-using ::i18n::addressinput::Source;
-using ::i18n::addressinput::Storage;
-
-class AddressNormalizationRequest : public AddressNormalizer::Request {
- public:
-  // The |delegate| and |address_validator| need to outlive this Request.
-  AddressNormalizationRequest(const AutofillProfile& profile,
-                              const std::string& region_code,
-                              int timeout_seconds,
-                              AddressNormalizer::Delegate* delegate,
-                              autofill::AddressValidator* address_validator)
-      : profile_(profile),
-        region_code_(region_code),
-        delegate_(delegate),
-        address_validator_(address_validator),
-        has_responded_(false),
-        on_timeout_(
-            base::Bind(&::payments::AddressNormalizationRequest::OnRulesLoaded,
-                       base::Unretained(this),
-                       false)) {
-    base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
-        FROM_HERE, on_timeout_.callback(),
-        base::TimeDelta::FromSeconds(timeout_seconds));
-  }
-
-  ~AddressNormalizationRequest() override {}
-
-  void OnRulesLoaded(bool success) override {
-    on_timeout_.Cancel();
-
-    // Check if the timeout happened before the rules were loaded.
-    if (has_responded_)
-      return;
-    has_responded_ = true;
-
-    // In either case, format the phone number.
-    FormatPhoneNumberForResponse();
-
-    if (!success) {
-      delegate_->OnCouldNotNormalize(profile_);
-      return;
-    }
-
-    // The rules should be loaded.
-    DCHECK(address_validator_->AreRulesLoadedForRegion(region_code_));
-
-    // Create the AddressData from the profile.
-    ::i18n::addressinput::AddressData address_data =
-        *autofill::i18n::CreateAddressDataFromAutofillProfile(profile_,
-                                                              region_code_);
-
-    // Normalize the address.
-    if (address_validator_ &&
-        address_validator_->NormalizeAddress(&address_data)) {
-      profile_.SetRawInfo(autofill::ADDRESS_HOME_STATE,
-                          base::UTF8ToUTF16(address_data.administrative_area));
-      profile_.SetRawInfo(autofill::ADDRESS_HOME_CITY,
-                          base::UTF8ToUTF16(address_data.locality));
-      profile_.SetRawInfo(autofill::ADDRESS_HOME_DEPENDENT_LOCALITY,
-                          base::UTF8ToUTF16(address_data.dependent_locality));
-    }
-
-    delegate_->OnAddressNormalized(profile_);
-  }
-
- private:
-  // Tries to format the phone number to the E.164 format to send in the Payment
-  // Response, as defined in the Payment Request spec. Keeps the original
-  // if it cannot be formatted. More info at:
-  // https://w3c.github.io/browser-payment-api/#paymentrequest-updated-algorithm
-  void FormatPhoneNumberForResponse() {
-    const std::string original_number = base::UTF16ToUTF8(profile_.GetInfo(
-        autofill::AutofillType(autofill::PHONE_HOME_WHOLE_NUMBER),
-        region_code_));
-
-    std::string formatted_number =
-        data_util::FormatPhoneForResponse(original_number, region_code_);
-
-    profile_.SetRawInfo(autofill::PHONE_HOME_WHOLE_NUMBER,
-                        base::UTF8ToUTF16(formatted_number));
-  }
-
-  AutofillProfile profile_;
-  std::string region_code_;
-  AddressNormalizer::Delegate* delegate_;
-  autofill::AddressValidator* address_validator_;
-
-  bool has_responded_;
-  base::CancelableCallback<void()> on_timeout_;
-
-  DISALLOW_COPY_AND_ASSIGN(AddressNormalizationRequest);
-};
-
-}  // namespace
-
-AddressNormalizerImpl::AddressNormalizerImpl(std::unique_ptr<Source> source,
-                                             std::unique_ptr<Storage> storage)
-    : address_validator_(std::move(source), std::move(storage), this) {}
-
-AddressNormalizerImpl::~AddressNormalizerImpl() {}
-
-void AddressNormalizerImpl::LoadRulesForRegion(const std::string& region_code) {
-  address_validator_.LoadRules(region_code);
-}
-
-bool AddressNormalizerImpl::AreRulesLoadedForRegion(
-    const std::string& region_code) {
-  return address_validator_.AreRulesLoadedForRegion(region_code);
-}
-
-void AddressNormalizerImpl::StartAddressNormalization(
-    const AutofillProfile& profile,
-    const std::string& region_code,
-    int timeout_seconds,
-    AddressNormalizer::Delegate* requester) {
-  DCHECK(timeout_seconds >= 0);
-
-  std::unique_ptr<AddressNormalizationRequest> request(
-      base::MakeUnique<AddressNormalizationRequest>(profile, region_code,
-                                                    timeout_seconds, requester,
-                                                    &address_validator_));
-
-  // Check if the rules are already loaded.
-  if (AreRulesLoadedForRegion(region_code)) {
-    request->OnRulesLoaded(true);
-  } else {
-    // Setup the variables so the profile gets normalized when the rules have
-    // finished loading.
-    auto it = pending_normalization_.find(region_code);
-    if (it == pending_normalization_.end()) {
-      // If no entry exists yet, create the entry and assign it to |it|.
-      it = pending_normalization_
-               .insert(std::make_pair(region_code,
-                                      std::vector<std::unique_ptr<Request>>()))
-               .first;
-    }
-
-    it->second.push_back(std::move(request));
-
-    // Start loading the rules for that region. If the rules were already in the
-    // process of being loaded, this call will do nothing.
-    LoadRulesForRegion(region_code);
-  }
-}
-
-void AddressNormalizerImpl::OnAddressValidationRulesLoaded(
-    const std::string& region_code,
-    bool success) {
-  // Check if an address normalization is pending.
-  auto it = pending_normalization_.find(region_code);
-  if (it != pending_normalization_.end()) {
-    for (size_t i = 0; i < it->second.size(); ++i) {
-      it->second[i]->OnRulesLoaded(success);
-    }
-    pending_normalization_.erase(it);
-  }
-}
-
-}  // namespace payments
\ No newline at end of file
diff --git a/components/payments/core/address_normalizer_impl.h b/components/payments/core/address_normalizer_impl.h
deleted file mode 100644
index 1444e8a..0000000
--- a/components/payments/core/address_normalizer_impl.h
+++ /dev/null
@@ -1,62 +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_PAYMENTS_CORE_ADDRESS_NORMALIZER_IMPL_H_
-#define COMPONENTS_PAYMENTS_CORE_ADDRESS_NORMALIZER_IMPL_H_
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "components/payments/core/address_normalizer.h"
-
-namespace autofill {
-class AutofillProfile;
-}
-
-namespace i18n {
-namespace addressinput {
-class Source;
-class Storage;
-}
-}
-
-namespace payments {
-
-// A class used to normalize addresses.
-class AddressNormalizerImpl : public AddressNormalizer {
- public:
-  AddressNormalizerImpl(std::unique_ptr<::i18n::addressinput::Source> source,
-                        std::unique_ptr<::i18n::addressinput::Storage> storage);
-  ~AddressNormalizerImpl() override;
-
-  // AddressNormalizer implementation.
-  void LoadRulesForRegion(const std::string& region_code) override;
-  bool AreRulesLoadedForRegion(const std::string& region_code) override;
-  void StartAddressNormalization(const autofill::AutofillProfile& profile,
-                                 const std::string& region_code,
-                                 int timeout_seconds,
-                                 Delegate* requester) override;
-
- private:
-  // Called when the validation rules for the |region_code| have finished
-  // loading. Implementation of the LoadRulesListener interface.
-  void OnAddressValidationRulesLoaded(const std::string& region_code,
-                                      bool success) override;
-
-  // Map associating a region code to pending normalizations.
-  std::map<std::string, std::vector<std::unique_ptr<Request>>>
-      pending_normalization_;
-
-  // The address validator used to normalize addresses.
-  autofill::AddressValidator address_validator_;
-
-  DISALLOW_COPY_AND_ASSIGN(AddressNormalizerImpl);
-};
-
-}  // namespace payments
-
-#endif  // COMPONENTS_PAYMENTS_CORE_ADDRESS_NORMALIZER_IMPL_H_
diff --git a/components/payments/core/address_normalizer_impl_unittest.cc b/components/payments/core/address_normalizer_impl_unittest.cc
deleted file mode 100644
index f38ac14..0000000
--- a/components/payments/core/address_normalizer_impl_unittest.cc
+++ /dev/null
@@ -1,246 +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/payments/core/address_normalizer_impl.h"
-
-#include <utility>
-
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
-#include "components/autofill/core/browser/autofill_profile.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/null_storage.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/source.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h"
-#include "third_party/libaddressinput/src/cpp/test/testdata_source.h"
-
-namespace payments {
-namespace {
-
-using ::autofill::AutofillProfile;
-using ::i18n::addressinput::NullStorage;
-using ::i18n::addressinput::Source;
-using ::i18n::addressinput::Storage;
-using ::i18n::addressinput::TestdataSource;
-
-const char kLocale[] = "US";
-
-// The requester of normalization for this test.
-class NormalizationDelegate : public AddressNormalizer::Delegate {
- public:
-  NormalizationDelegate()
-      : normalized_called_(false), not_normalized_called_(false) {}
-
-  ~NormalizationDelegate() override {}
-
-  void OnAddressNormalized(const autofill::AutofillProfile& profile) override {
-    normalized_called_ = true;
-    profile_ = profile;
-  }
-
-  void OnCouldNotNormalize(const autofill::AutofillProfile& profile) override {
-    not_normalized_called_ = true;
-    profile_ = profile;
-  }
-
-  bool normalized_called() const { return normalized_called_; }
-
-  bool not_normalized_called() const { return not_normalized_called_; }
-
-  const AutofillProfile& profile() const { return profile_; }
-
- private:
-  bool normalized_called_;
-  bool not_normalized_called_;
-  AutofillProfile profile_;
-
-  DISALLOW_COPY_AND_ASSIGN(NormalizationDelegate);
-};
-
-// Used to load region rules for this test.
-class ChromiumTestdataSource : public TestdataSource {
- public:
-  ChromiumTestdataSource() : TestdataSource(true) {}
-
-  ~ChromiumTestdataSource() override {}
-
-  // For this test, only load the rules for the kLocale.
-  void Get(const std::string& key, const Callback& data_ready) const override {
-    data_ready(
-        true, key,
-        new std::string("{\"data/US\": "
-                        "{\"id\":\"data/US\",\"key\":\"US\",\"name\":\"UNITED "
-                        "STATES\",\"lang\":\"en\",\"languages\":\"en\"}}"));
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ChromiumTestdataSource);
-};
-
-// A test subclass of the AddressNormalizerImpl. Used to simulate rules not
-// being loaded.
-class TestAddressNormalizer : public AddressNormalizerImpl {
- public:
-  TestAddressNormalizer(std::unique_ptr<::i18n::addressinput::Source> source,
-                        std::unique_ptr<::i18n::addressinput::Storage> storage)
-      : AddressNormalizerImpl(std::move(source), std::move(storage)),
-        should_load_rules_(true) {}
-
-  ~TestAddressNormalizer() override {}
-
-  void ShouldLoadRules(bool should_load_rules) {
-    should_load_rules_ = should_load_rules;
-  }
-
-  void LoadRulesForRegion(const std::string& region_code) override {
-    if (should_load_rules_) {
-      AddressNormalizerImpl::LoadRulesForRegion(region_code);
-    }
-  }
-
- private:
-  bool should_load_rules_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestAddressNormalizer);
-};
-
-}  // namespace
-
-class AddressNormalizerTest : public testing::Test {
- protected:
-  AddressNormalizerTest()
-      : normalizer_(new TestAddressNormalizer(
-            std::unique_ptr<Source>(new ChromiumTestdataSource),
-            std::unique_ptr<Storage>(new NullStorage))) {}
-
-  ~AddressNormalizerTest() override {}
-
-  const std::unique_ptr<TestAddressNormalizer> normalizer_;
-
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AddressNormalizerTest);
-};
-
-// Tests that rules are not loaded by default.
-TEST_F(AddressNormalizerTest, AreRulesLoadedForRegion_NotLoaded) {
-  EXPECT_FALSE(normalizer_->AreRulesLoadedForRegion(kLocale));
-}
-
-// Tests that the rules are loaded correctly.
-TEST_F(AddressNormalizerTest, AreRulesLoadedForRegion_Loaded) {
-  normalizer_->LoadRulesForRegion(kLocale);
-  EXPECT_TRUE(normalizer_->AreRulesLoadedForRegion(kLocale));
-}
-
-// Tests that if the rules are loaded before the normalization is started, the
-// normalized profile will be returned to the delegate synchronously.
-TEST_F(AddressNormalizerTest, StartNormalization_RulesLoaded) {
-  NormalizationDelegate delegate;
-  AutofillProfile profile;
-
-  // Load the rules.
-  normalizer_->LoadRulesForRegion(kLocale);
-  EXPECT_TRUE(normalizer_->AreRulesLoadedForRegion(kLocale));
-
-  // Start the normalization.
-  normalizer_->StartAddressNormalization(profile, kLocale, 0, &delegate);
-
-  // Since the rules are already loaded, the address should be normalized
-  // synchronously.
-  EXPECT_TRUE(delegate.normalized_called());
-  EXPECT_FALSE(delegate.not_normalized_called());
-}
-
-// Tests that if the rules are not loaded before the normalization and cannot be
-// loaded after, the address will not be normalized and the delegate will be
-// notified.
-TEST_F(AddressNormalizerTest, StartNormalization_RulesNotLoaded_WillNotLoad) {
-  NormalizationDelegate delegate;
-  AutofillProfile profile;
-
-  // Make sure the rules will not be loaded in the StartAddressNormalization
-  // call.
-  normalizer_->ShouldLoadRules(false);
-
-  // Start the normalization.
-  normalizer_->StartAddressNormalization(profile, kLocale, 0, &delegate);
-
-  // Let the timeout execute.
-  scoped_task_environment_.RunUntilIdle();
-
-  // Since the rules are never loaded and the timeout is 0, the delegate should
-  // get notified that the address could not be normalized.
-  EXPECT_FALSE(delegate.normalized_called());
-  EXPECT_TRUE(delegate.not_normalized_called());
-}
-
-// Tests that if the rules are not loaded before the call to
-// StartAddressNormalization, they will be loaded in the call.
-TEST_F(AddressNormalizerTest, StartNormalization_RulesNotLoaded_WillLoad) {
-  NormalizationDelegate delegate;
-  AutofillProfile profile;
-
-  // Start the normalization.
-  normalizer_->StartAddressNormalization(profile, kLocale, 0, &delegate);
-
-  // Even if the rules are not loaded before the call to
-  // StartAddressNormalization, they should get loaded in the call. Since our
-  // test source is synchronous, the normalization will happen synchronously
-  // too.
-  EXPECT_TRUE(normalizer_->AreRulesLoadedForRegion(kLocale));
-  EXPECT_TRUE(delegate.normalized_called());
-  EXPECT_FALSE(delegate.not_normalized_called());
-}
-
-// Tests that the phone number is formatted when the address is normalized.
-TEST_F(AddressNormalizerTest, FormatPhone_AddressNormalized) {
-  NormalizationDelegate delegate;
-  AutofillProfile profile;
-  profile.SetRawInfo(autofill::PHONE_HOME_WHOLE_NUMBER,
-                     base::UTF8ToUTF16("(515) 123-1234"));
-
-  // Load the rules.
-  normalizer_->LoadRulesForRegion(kLocale);
-  EXPECT_TRUE(normalizer_->AreRulesLoadedForRegion(kLocale));
-
-  // Start the normalization.
-  normalizer_->StartAddressNormalization(profile, kLocale, 0, &delegate);
-
-  // Make sure the address was normalized.
-  EXPECT_TRUE(delegate.normalized_called());
-
-  // Expect that the phone number was formatted.
-  EXPECT_EQ("+15151231234", base::UTF16ToUTF8(delegate.profile().GetRawInfo(
-                                autofill::PHONE_HOME_WHOLE_NUMBER)));
-}
-
-// Tests that the phone number is formatted even when the address is not
-// normalized.
-TEST_F(AddressNormalizerTest, FormatPhone_AddressNotNormalized) {
-  NormalizationDelegate delegate;
-  AutofillProfile profile;
-  profile.SetRawInfo(autofill::PHONE_HOME_WHOLE_NUMBER,
-                     base::UTF8ToUTF16("515-123-1234"));
-
-  // Make sure the rules will not be loaded in the StartAddressNormalization
-  // call.
-  normalizer_->ShouldLoadRules(false);
-
-  // Start the normalization.
-  normalizer_->StartAddressNormalization(profile, kLocale, 0, &delegate);
-
-  // Let the timeout execute.
-  scoped_task_environment_.RunUntilIdle();
-
-  // Make sure the address was not normalized.
-  EXPECT_TRUE(delegate.not_normalized_called());
-
-  // Expect that the phone number was formatted.
-  EXPECT_EQ("+15151231234", base::UTF16ToUTF8(delegate.profile().GetRawInfo(
-                                autofill::PHONE_HOME_WHOLE_NUMBER)));
-}
-
-}  // namespace payments
diff --git a/components/payments/core/autofill_payment_instrument.h b/components/payments/core/autofill_payment_instrument.h
index 378ee860..b5b8b00 100644
--- a/components/payments/core/autofill_payment_instrument.h
+++ b/components/payments/core/autofill_payment_instrument.h
@@ -12,10 +12,10 @@
 #include "base/macros.h"
 #include "base/strings/string16.h"
 #include "build/build_config.h"
+#include "components/autofill/core/browser/address_normalizer.h"
 #include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/payments/full_card_request.h"
-#include "components/payments/core/address_normalizer.h"
 #include "components/payments/core/payment_instrument.h"
 
 namespace payments {
@@ -27,7 +27,7 @@
 class AutofillPaymentInstrument
     : public PaymentInstrument,
       public autofill::payments::FullCardRequest::ResultDelegate,
-      public AddressNormalizer::Delegate {
+      public autofill::AddressNormalizer::Delegate {
  public:
   // |billing_profiles| is owned by the caller and should outlive this object.
   // |payment_request_delegate| must outlive this object.
diff --git a/components/payments/core/autofill_payment_instrument_unittest.cc b/components/payments/core/autofill_payment_instrument_unittest.cc
index 328163b..f45115b 100644
--- a/components/payments/core/autofill_payment_instrument_unittest.cc
+++ b/components/payments/core/autofill_payment_instrument_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/macros.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/address_normalizer.h"
 #include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/credit_card.h"
@@ -15,7 +16,6 @@
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/core/browser/test_autofill_client.h"
 #include "components/autofill/core/browser/test_personal_data_manager.h"
-#include "components/payments/core/address_normalizer.h"
 #include "components/payments/core/test_payment_request_delegate.h"
 #include "components/strings/grit/components_strings.h"
 #include "net/url_request/url_request_test_util.h"
@@ -53,7 +53,7 @@
   bool on_instrument_details_error_called_ = false;
 };
 
-class FakeAddressNormalizer : public AddressNormalizer {
+class FakeAddressNormalizer : public autofill::AddressNormalizer {
  public:
   FakeAddressNormalizer() {}
 
@@ -67,7 +67,7 @@
       const autofill::AutofillProfile& profile,
       const std::string& region_code,
       int timeout_seconds,
-      AddressNormalizer::Delegate* requester) override {
+      autofill::AddressNormalizer::Delegate* requester) override {
     profile_ = profile;
     requester_ = requester;
   }
@@ -81,7 +81,7 @@
 
  private:
   autofill::AutofillProfile profile_;
-  AddressNormalizer::Delegate* requester_;
+  autofill::AddressNormalizer::Delegate* requester_;
 };
 
 class FakePaymentRequestDelegate
@@ -126,7 +126,7 @@
     full_card_result_delegate_ = result_delegate;
   }
 
-  AddressNormalizer* GetAddressNormalizer() override {
+  autofill::AddressNormalizer* GetAddressNormalizer() override {
     return &address_normalizer_;
   }
 
diff --git a/components/payments/core/payment_request_base_delegate.h b/components/payments/core/payment_request_base_delegate.h
index 8b48dce8..dafa12b 100644
--- a/components/payments/core/payment_request_base_delegate.h
+++ b/components/payments/core/payment_request_base_delegate.h
@@ -14,6 +14,7 @@
 class GURL;
 
 namespace autofill {
+class AddressNormalizer;
 class CreditCard;
 class PersonalDataManager;
 class RegionDataLoader;
@@ -27,7 +28,6 @@
 
 namespace payments {
 
-class AddressNormalizer;
 class PaymentRequest;
 
 class PaymentRequestBaseDelegate {
@@ -58,7 +58,7 @@
 
   // Returns a pointer to the address normalizer to use for the duration of this
   // Payment Request.
-  virtual AddressNormalizer* GetAddressNormalizer() = 0;
+  virtual autofill::AddressNormalizer* GetAddressNormalizer() = 0;
 
   // Creates a new region data loader that will self delete, or a test mock.
   virtual autofill::RegionDataLoader* GetRegionDataLoader() = 0;
diff --git a/components/payments/core/payment_request_data_util.cc b/components/payments/core/payment_request_data_util.cc
index 33d8057..bc35e6f 100644
--- a/components/payments/core/payment_request_data_util.cc
+++ b/components/payments/core/payment_request_data_util.cc
@@ -5,7 +5,6 @@
 #include "components/payments/core/payment_request_data_util.h"
 
 #include "base/stl_util.h"
-#include "base/strings/string16.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -18,35 +17,11 @@
 #include "components/payments/core/basic_card_response.h"
 #include "components/payments/core/payment_address.h"
 #include "components/payments/core/payment_method_data.h"
-#include "third_party/libphonenumber/phonenumber_api.h"
 #include "url/url_constants.h"
 
 namespace payments {
 namespace data_util {
 
-namespace {
-using ::i18n::phonenumbers::PhoneNumber;
-using ::i18n::phonenumbers::PhoneNumberUtil;
-
-// Formats the |phone_number| to the specified |format|. Returns the original
-// number if the operation is not possible.
-std::string FormatPhoneNumber(const std::string& phone_number,
-                              const std::string& country_code,
-                              PhoneNumberUtil::PhoneNumberFormat format) {
-  PhoneNumber parsed_number;
-  PhoneNumberUtil* phone_number_util = PhoneNumberUtil::GetInstance();
-  if (phone_number_util->Parse(phone_number, country_code, &parsed_number) !=
-      PhoneNumberUtil::NO_PARSING_ERROR) {
-    return phone_number;
-  }
-
-  std::string formatted_number;
-  phone_number_util->Format(parsed_number, format, &formatted_number);
-  return formatted_number;
-}
-
-}  // namespace
-
 PaymentAddress GetPaymentAddressFromAutofillProfile(
     const autofill::AutofillProfile& profile,
     const std::string& app_locale) {
@@ -201,44 +176,6 @@
   out_supported_card_types_set->insert(autofill::CreditCard::CARD_TYPE_UNKNOWN);
 }
 
-base::string16 GetFormattedPhoneNumberForDisplay(
-    const autofill::AutofillProfile& profile,
-    const std::string& locale) {
-  // Since the "+" is removed for some country's phone numbers, try to add a "+"
-  // and see if it is a valid phone number for a country.
-  // Having two "+" in front of a number has no effect on the formatted number.
-  // The reason for this is international phone numbers for another country. For
-  // example, without adding a "+", the US number 1-415-123-1234 for an AU
-  // address would be wrongly formatted as +61 1-415-123-1234 which is invalid.
-  std::string phone = base::UTF16ToUTF8(profile.GetInfo(
-      autofill::AutofillType(autofill::PHONE_HOME_WHOLE_NUMBER), locale));
-  std::string tentative_intl_phone = "+" + phone;
-
-  // Always favor the tentative international phone number if it's determined as
-  // being a valid number.
-  if (autofill::IsValidPhoneNumber(
-          base::UTF8ToUTF16(tentative_intl_phone),
-          GetCountryCodeWithFallback(&profile, locale))) {
-    return base::UTF8ToUTF16(FormatPhoneForDisplay(
-        tentative_intl_phone, GetCountryCodeWithFallback(&profile, locale)));
-  }
-
-  return base::UTF8ToUTF16(FormatPhoneForDisplay(
-      phone, GetCountryCodeWithFallback(&profile, locale)));
-}
-
-std::string FormatPhoneForDisplay(const std::string& phone_number,
-                                  const std::string& country_code) {
-  return FormatPhoneNumber(phone_number, country_code,
-                           PhoneNumberUtil::PhoneNumberFormat::INTERNATIONAL);
-}
-
-std::string FormatPhoneForResponse(const std::string& phone_number,
-                                   const std::string& country_code) {
-  return FormatPhoneNumber(phone_number, country_code,
-                           PhoneNumberUtil::PhoneNumberFormat::E164);
-}
-
 base::string16 FormatCardNumberForDisplay(const base::string16& card_number) {
   base::string16 number = autofill::CreditCard::StripSeparators(card_number);
   if (number.empty() || !base::IsAsciiDigit(number[0]))
@@ -259,14 +196,5 @@
   return number;
 }
 
-std::string GetCountryCodeWithFallback(const autofill::AutofillProfile* profile,
-                                       const std::string& app_locale) {
-  std::string country_code =
-      base::UTF16ToUTF8(profile->GetRawInfo(autofill::ADDRESS_HOME_COUNTRY));
-  if (!autofill::data_util::IsValidCountryCode(country_code))
-    country_code = autofill::AutofillCountry::CountryCodeForLocale(app_locale);
-  return country_code;
-}
-
 }  // namespace data_util
 }  // namespace payments
diff --git a/components/payments/core/payment_request_data_util.h b/components/payments/core/payment_request_data_util.h
index 9e5b56e..51a5400ab 100644
--- a/components/payments/core/payment_request_data_util.h
+++ b/components/payments/core/payment_request_data_util.h
@@ -66,36 +66,11 @@
     const std::vector<PaymentMethodData>& method_data,
     std::set<autofill::CreditCard::CardType>* out_supported_card_types_set);
 
-// Returns the phone number from the given |profile| formatted for display.
-base::string16 GetFormattedPhoneNumberForDisplay(
-    const autofill::AutofillProfile& profile,
-    const std::string& locale);
-
-// Formats the given number |phone_number| to
-// i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat::INTERNATIONAL format
-// by using i18n::phonenumbers::PhoneNumberUtil::Format.
-std::string FormatPhoneForDisplay(const std::string& phone_number,
-                                  const std::string& country_code);
-
-// Formats the given number |phone_number| to
-// i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat::E164 format by using
-// i18n::phonenumbers::PhoneNumberUtil::Format, as defined in the Payment
-// Request spec
-// (https://w3c.github.io/browser-payment-api/#paymentrequest-updated-algorithm)
-std::string FormatPhoneForResponse(const std::string& phone_number,
-                                   const std::string& country_code);
-
 // Formats |card_number| for display. For example, "4111111111111111" is
 // formatted into "4111 1111 1111 1111". This method does not format masked card
 // numbers, which start with a letter.
 base::string16 FormatCardNumberForDisplay(const base::string16& card_number);
 
-// Returns a country code to be used when validating this profile. If the
-// profile has a valid country code set, it is returned. If not, a country code
-// associated with |app_locale| is used as a fallback.
-std::string GetCountryCodeWithFallback(const autofill::AutofillProfile* profile,
-                                       const std::string& app_locale);
-
 }  // namespace data_util
 }  // namespace payments
 
diff --git a/components/payments/core/payment_request_data_util_unittest.cc b/components/payments/core/payment_request_data_util_unittest.cc
index b815c07..de8e4c0 100644
--- a/components/payments/core/payment_request_data_util_unittest.cc
+++ b/components/payments/core/payment_request_data_util_unittest.cc
@@ -78,190 +78,5 @@
       json_response);
 }
 
-// Tests that the phone numbers are correctly formatted for the Payment
-// Response.
-TEST(PaymentRequestDataUtilTest, FormatPhoneForResponse) {
-  EXPECT_EQ("+15151231234", payments::data_util::FormatPhoneForResponse(
-                                "(515) 123-1234", "US"));
-  EXPECT_EQ("+15151231234", payments::data_util::FormatPhoneForResponse(
-                                "(1) 515-123-1234", "US"));
-  EXPECT_EQ("+33142685300",
-            payments::data_util::FormatPhoneForResponse("1 42 68 53 00", "FR"));
-}
-
-// Tests that the phone numbers are correctly formatted to display to the user.
-TEST(PaymentRequestDataUtilTest, FormatPhoneForDisplay) {
-  EXPECT_EQ("+1 515-123-1234",
-            payments::data_util::FormatPhoneForDisplay("5151231234", "US"));
-  EXPECT_EQ("+33 1 42 68 53 00",
-            payments::data_util::FormatPhoneForDisplay("142685300", "FR"));
-}
-
-// Test for the GetFormattedPhoneNumberForDisplay method.
-struct PhoneNumberFormatCase {
-  PhoneNumberFormatCase(const char* phone,
-                        const char* country,
-                        const char* expected_format,
-                        const char* locale = "")
-      : phone(phone),
-        country(country),
-        expected_format(expected_format),
-        locale(locale) {}
-
-  const char* phone;
-  const char* country;
-  const char* expected_format;
-  const char* locale;
-};
-
-class GetFormattedPhoneNumberForDisplayTest
-    : public testing::TestWithParam<PhoneNumberFormatCase> {};
-
-TEST_P(GetFormattedPhoneNumberForDisplayTest,
-       GetFormattedPhoneNumberForDisplay) {
-  autofill::AutofillProfile profile;
-  profile.SetRawInfo(autofill::PHONE_HOME_WHOLE_NUMBER,
-                     base::UTF8ToUTF16(GetParam().phone));
-  profile.SetRawInfo(autofill::ADDRESS_HOME_COUNTRY,
-                     base::UTF8ToUTF16(GetParam().country));
-  EXPECT_EQ(GetParam().expected_format,
-            base::UTF16ToUTF8(
-                GetFormattedPhoneNumberForDisplay(profile, GetParam().locale)));
-}
-
-INSTANTIATE_TEST_CASE_P(
-    GetFormattedPhoneNumberForDisplay,
-    GetFormattedPhoneNumberForDisplayTest,
-    testing::Values(
-        //////////////////////////
-        // US phone in US.
-        //////////////////////////
-        // Formatted phone numbers.
-        PhoneNumberFormatCase("+1 415-555-5555", "US", "+1 415-555-5555"),
-        PhoneNumberFormatCase("1 415-555-5555", "US", "+1 415-555-5555"),
-        PhoneNumberFormatCase("415-555-5555", "US", "+1 415-555-5555"),
-        // Raw phone numbers.
-        PhoneNumberFormatCase("+14155555555", "US", "+1 415-555-5555"),
-        PhoneNumberFormatCase("14155555555", "US", "+1 415-555-5555"),
-        PhoneNumberFormatCase("4155555555", "US", "+1 415-555-5555"),
-
-        //////////////////////////
-        // US phone in CA.
-        //////////////////////////
-        // Formatted phone numbers.
-        PhoneNumberFormatCase("+1 415-555-5555", "CA", "+1 415-555-5555"),
-        PhoneNumberFormatCase("1 415-555-5555", "CA", "+1 415-555-5555"),
-        PhoneNumberFormatCase("415-555-5555", "CA", "+1 415-555-5555"),
-        // Raw phone numbers.
-        PhoneNumberFormatCase("+14155555555", "CA", "+1 415-555-5555"),
-        PhoneNumberFormatCase("14155555555", "CA", "+1 415-555-5555"),
-        PhoneNumberFormatCase("4155555555", "CA", "+1 415-555-5555"),
-
-        //////////////////////////
-        // US phone in AU.
-        //////////////////////////
-        // A US phone with the country code is correctly formatted as an US
-        // number.
-        PhoneNumberFormatCase("+1 415-555-5555", "AU", "+1 415-555-5555"),
-        PhoneNumberFormatCase("1 415-555-5555", "AU", "+1 415-555-5555"),
-        // Without a country code, the phone is formatted for the profile's
-        // country, even if it's invalid.
-        PhoneNumberFormatCase("415-555-5555", "AU", "+61 4155555555"),
-
-        //////////////////////////
-        // US phone in MX.
-        //////////////////////////
-        // A US phone with the country code is correctly formatted as an US
-        // number.
-        PhoneNumberFormatCase("+1 415-555-5555", "MX", "+1 415-555-5555"),
-        // "+52 1 415 555 5555" is a valid number for Mexico,
-        PhoneNumberFormatCase("1 415-555-5555", "MX", "+52 1 415 555 5555"),
-        // Without a country code, the phone is formatted for the profile's
-        // country.
-        PhoneNumberFormatCase("415-555-5555", "MX", "+52 415 555 5555"),
-
-        //////////////////////////
-        // AU phone in AU.
-        //////////////////////////
-        // Formatted phone numbers.
-        PhoneNumberFormatCase("+61 2 9374 4000", "AU", "+61 2 9374 4000"),
-        PhoneNumberFormatCase("61 2 9374 4000", "AU", "+61 2 9374 4000"),
-        PhoneNumberFormatCase("02 9374 4000", "AU", "+61 2 9374 4000"),
-        PhoneNumberFormatCase("2 9374 4000", "AU", "+61 2 9374 4000"),
-        // Raw phone numbers.
-        PhoneNumberFormatCase("+61293744000", "AU", "+61 2 9374 4000"),
-        PhoneNumberFormatCase("61293744000", "AU", "+61 2 9374 4000"),
-        PhoneNumberFormatCase("0293744000", "AU", "+61 2 9374 4000"),
-        PhoneNumberFormatCase("293744000", "AU", "+61 2 9374 4000"),
-
-        //////////////////////////
-        // AU phone in US.
-        //////////////////////////
-        // An AU phone with the country code is correctly formatted as an AU
-        // number.
-        PhoneNumberFormatCase("+61 2 9374 4000", "US", "+61 2 9374 4000"),
-        PhoneNumberFormatCase("61 2 9374 4000", "US", "+61 2 9374 4000"),
-        // Without a country code, the phone is formatted for the profile's
-        // country.
-        // This local AU number fits the length of a US number, so it's
-        // formatted for US.
-        PhoneNumberFormatCase("02 9374 4000", "US", "+1 029-374-4000"),
-        // This local AU number is formatted as an US number, even if it's
-        // invlaid.
-        PhoneNumberFormatCase("2 9374 4000", "US", "+1 293744000"),
-
-        //////////////////////////
-        // MX phone in MX.
-        //////////////////////////
-        // Formatted phone numbers.
-        PhoneNumberFormatCase("+52 55 5342 8400", "MX", "+52 55 5342 8400"),
-        PhoneNumberFormatCase("52 55 5342 8400", "MX", "+52 55 5342 8400"),
-        PhoneNumberFormatCase("55 5342 8400", "MX", "+52 55 5342 8400"),
-        // Raw phone numbers.
-        PhoneNumberFormatCase("+525553428400", "MX", "+52 55 5342 8400"),
-        PhoneNumberFormatCase("525553428400", "MX", "+52 55 5342 8400"),
-        PhoneNumberFormatCase("5553428400", "MX", "+52 55 5342 8400"),
-
-        //////////////////////////
-        // MX phone in US.
-        //////////////////////////
-        // A MX phone with the country code is correctly formatted as a MX
-        // number.
-        PhoneNumberFormatCase("+52 55 5342 8400", "US", "+52 55 5342 8400"),
-        PhoneNumberFormatCase("52 55 5342 8400", "US", "+52 55 5342 8400"),
-        // This local MX number fits the length of a US number, so it's
-        // formatted for US.
-        PhoneNumberFormatCase("55 5342 8400", "US", "+1 555-342-8400")));
-
-INSTANTIATE_TEST_CASE_P(
-    GetFormattedPhoneNumberForDisplay_EdgeCases,
-    GetFormattedPhoneNumberForDisplayTest,
-    testing::Values(
-        //////////////////////////
-        // No country.
-        //////////////////////////
-        // Fallback to locale if no country is set.
-        PhoneNumberFormatCase("52 55 5342 8400",
-                              "",
-                              "+52 55 5342 8400",
-                              "es_MX"),
-        PhoneNumberFormatCase("55 5342 8400", "", "+52 55 5342 8400", "es_MX"),
-        PhoneNumberFormatCase("55 5342 8400", "", "+1 555-342-8400", "en_US"),
-        PhoneNumberFormatCase("61 2 9374 4000", "", "+61 2 9374 4000", "en_AU"),
-        PhoneNumberFormatCase("02 9374 4000", "", "+61 2 9374 4000", "en_AU"),
-
-        //////////////////////////
-        // No country or locale.
-        //////////////////////////
-        // Format according to the country code.
-        PhoneNumberFormatCase("61 2 9374 4000", "", "+61 2 9374 4000"),
-        PhoneNumberFormatCase("52 55 5342 8400", "", "+52 55 5342 8400"),
-        PhoneNumberFormatCase("1 415 555 5555", "", "+1 415-555-5555"),
-        // If no country code is found, formats for US.
-        PhoneNumberFormatCase("02 9374 4000", "", "+1 029-374-4000"),
-        PhoneNumberFormatCase("2 9374 4000", "", "+1 293744000"),
-        PhoneNumberFormatCase("55 5342 8400", "", "+1 555-342-8400"),
-        PhoneNumberFormatCase("52 55 5342 8400", "", "+52 55 5342 8400"),
-        PhoneNumberFormatCase("415-555-5555", "", "+1 415-555-5555")));
 }  // namespace data_util
 }  // namespace payments
diff --git a/components/payments/core/payments_profile_comparator.cc b/components/payments/core/payments_profile_comparator.cc
index 8be6829..e3b49c4 100644
--- a/components/payments/core/payments_profile_comparator.cc
+++ b/components/payments/core/payments_profile_comparator.cc
@@ -10,6 +10,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "components/autofill/core/browser/address_i18n.h"
 #include "components/autofill/core/browser/autofill_country.h"
+#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/validation.h"
@@ -219,7 +220,7 @@
   // is just the region that will be used to check if the number is
   // potentially in a local format.
   std::string country =
-      data_util::GetCountryCodeWithFallback(&profile, app_locale());
+      autofill::data_util::GetCountryCodeWithFallback(&profile, app_locale());
 
   base::string16 phone = profile.GetInfo(
       autofill::AutofillType(autofill::PHONE_HOME_WHOLE_NUMBER), app_locale());
diff --git a/components/payments/core/test_address_normalizer.cc b/components/payments/core/test_address_normalizer.cc
deleted file mode 100644
index e0b9fc8..0000000
--- a/components/payments/core/test_address_normalizer.cc
+++ /dev/null
@@ -1,38 +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/payments/core/test_address_normalizer.h"
-
-namespace payments {
-
-bool TestAddressNormalizer::AreRulesLoadedForRegion(
-    const std::string& region_code) {
-  return true;
-}
-
-void TestAddressNormalizer::StartAddressNormalization(
-    const autofill::AutofillProfile& profile,
-    const std::string& region_code,
-    int timeout_seconds,
-    AddressNormalizer::Delegate* requester) {
-  if (instantaneous_normalization_) {
-    requester->OnAddressNormalized(profile);
-    return;
-  }
-
-  // Setup the necessary variables for the delayed normalization.
-  profile_ = profile;
-  requester_ = requester;
-}
-
-void TestAddressNormalizer::DelayNormalization() {
-  instantaneous_normalization_ = false;
-}
-
-void TestAddressNormalizer::CompleteAddressNormalization() {
-  DCHECK(instantaneous_normalization_ == false);
-  requester_->OnAddressNormalized(profile_);
-}
-
-}  // namespace payments
diff --git a/components/payments/core/test_address_normalizer.h b/components/payments/core/test_address_normalizer.h
deleted file mode 100644
index 56def89de..0000000
--- a/components/payments/core/test_address_normalizer.h
+++ /dev/null
@@ -1,46 +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_PAYMENTS_CORE_TEST_ADDRESS_NORMALIZER_H_
-#define COMPONENTS_PAYMENTS_CORE_TEST_ADDRESS_NORMALIZER_H_
-
-#include "components/payments/core/address_normalizer.h"
-
-#include "components/autofill/core/browser/autofill_profile.h"
-
-namespace payments {
-
-// A simpler version of the address normalizer to be used in tests. Can be set
-// to normalize instantaneously or to wait for a call.
-class TestAddressNormalizer : public AddressNormalizer {
- public:
-  TestAddressNormalizer() {}
-
-  void LoadRulesForRegion(const std::string& region_code) override {}
-
-  bool AreRulesLoadedForRegion(const std::string& region_code) override;
-
-  void StartAddressNormalization(
-      const autofill::AutofillProfile& profile,
-      const std::string& region_code,
-      int timeout_seconds,
-      AddressNormalizer::Delegate* requester) override;
-
-  void OnAddressValidationRulesLoaded(const std::string& region_code,
-                                      bool success) override {}
-
-  void DelayNormalization();
-
-  void CompleteAddressNormalization();
-
- private:
-  autofill::AutofillProfile profile_;
-  AddressNormalizer::Delegate* requester_;
-
-  bool instantaneous_normalization_ = true;
-};
-
-}  // namespace payments
-
-#endif  // COMPONENTS_PAYMENTS_CORE_TEST_ADDRESS_NORMALIZER_H_
\ No newline at end of file
diff --git a/components/payments/core/test_payment_request_delegate.cc b/components/payments/core/test_payment_request_delegate.cc
index d569c16..e90bb7c3 100644
--- a/components/payments/core/test_payment_request_delegate.cc
+++ b/components/payments/core/test_payment_request_delegate.cc
@@ -56,7 +56,8 @@
   full_card_result_delegate_ = result_delegate;
 }
 
-AddressNormalizer* TestPaymentRequestDelegate::GetAddressNormalizer() {
+autofill::AddressNormalizer*
+TestPaymentRequestDelegate::GetAddressNormalizer() {
   return &address_normalizer_;
 }
 
@@ -68,7 +69,8 @@
   return nullptr;
 }
 
-TestAddressNormalizer* TestPaymentRequestDelegate::test_address_normalizer() {
+autofill::TestAddressNormalizer*
+TestPaymentRequestDelegate::test_address_normalizer() {
   return &address_normalizer_;
 }
 
diff --git a/components/payments/core/test_payment_request_delegate.h b/components/payments/core/test_payment_request_delegate.h
index 09cffee..979c1a6 100644
--- a/components/payments/core/test_payment_request_delegate.h
+++ b/components/payments/core/test_payment_request_delegate.h
@@ -10,9 +10,9 @@
 #include "base/message_loop/message_loop.h"
 #include "components/autofill/core/browser/payments/full_card_request.h"
 #include "components/autofill/core/browser/payments/payments_client.h"
+#include "components/autofill/core/browser/test_address_normalizer.h"
 #include "components/autofill/core/browser/test_autofill_client.h"
 #include "components/payments/core/payment_request_delegate.h"
-#include "components/payments/core/test_address_normalizer.h"
 #include "net/url_request/url_request_test_util.h"
 
 namespace payments {
@@ -68,14 +68,14 @@
       const autofill::CreditCard& credit_card,
       base::WeakPtr<autofill::payments::FullCardRequest::ResultDelegate>
           result_delegate) override;
-  AddressNormalizer* GetAddressNormalizer() override;
+  autofill::AddressNormalizer* GetAddressNormalizer() override;
   autofill::RegionDataLoader* GetRegionDataLoader() override;
   ukm::UkmRecorder* GetUkmRecorder() override;
   std::string GetAuthenticatedEmail() const override;
   PrefService* GetPrefService() override;
   bool IsBrowserWindowActive() const override;
 
-  TestAddressNormalizer* test_address_normalizer();
+  autofill::TestAddressNormalizer* test_address_normalizer();
   void DelayFullCardRequestCompletion();
   void CompleteFullCardRequest();
 
@@ -85,7 +85,7 @@
   autofill::PersonalDataManager* personal_data_manager_;
   std::string locale_;
   const GURL last_committed_url_;
-  TestAddressNormalizer address_normalizer_;
+  autofill::TestAddressNormalizer address_normalizer_;
   scoped_refptr<TestURLRequestContextGetter> request_context_;
   autofill::TestAutofillClient autofill_client_;
   autofill::payments::PaymentsClient payments_client_;
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 9a530709..0a75400 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -143,7 +143,7 @@
 #   persistent IDs for all fields (but not for groups!) are needed. These are
 #   specified by the 'id' keys of each policy. NEVER CHANGE EXISTING IDs,
 #   because doing so would break the deployed wire format!
-#   For your editing convenience: highest ID currently used: 390
+#   For your editing convenience: highest ID currently used: 391
 #   And don't forget to also update the EnterprisePolicies enum of
 #   histograms.xml (run 'python tools/metrics/histograms/update_policies.py').
 #
@@ -4316,6 +4316,25 @@
       If this setting is disabled or not set, users will be asked for permission to run plugins that require authorization. These are plugins that can compromise security.''',
     },
     {
+      'name': 'RunAllFlashInAllowMode',
+      'type': 'main',
+      'schema': { 'type': 'boolean' },
+      'supported_on': ['chrome.*:63-', 'chrome_os:63-'],
+      'features': {
+        'dynamic_refresh': True,
+        'per_profile': True,
+      },
+      'example_value': True,
+      'id': 391,
+      'caption': '''Extend Flash content setting to all content''',
+      'tags': ['system-security'],
+      'desc': '''If you enable this setting, all Flash content embedded on websites that have been set to allow Flash in content settings -- either by the user or by enterprise policy -- will be run, including content from other origins or small content.
+
+      To control which websites are allowed to run Flash, see the "DefaultPluginsSetting", "PluginsAllowedForUrls", and "PluginsBlockedForUrls" policies.
+
+      If this setting is disabled or not set, Flash content from other origins or small content might be blocked.''',
+    },
+    {
       'name': 'BookmarkBarEnabled',
       'type': 'main',
       'schema': { 'type': 'boolean' },
@@ -9488,28 +9507,16 @@
       'tags': [],
       'desc': '''Provides configurations for enterprise printers.
 
-      This policy allows you to provide printer configurations to
-      <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> devices.
-      The size of the file must not exceed 5MB and must be encoded in JSON.
-      The format is the same as the NativePrinters dictionary.  It is estimated
-      that a file containing approximately 21,000 printers will encode as a 5MB
-      file.  The cryptographic hash is used to verify the integrity of the
-      download.
+      This policy allows you to provide printer configurations to <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> devices. The size of the file must not exceed 5MB and must be encoded in JSON.  The format is the same as the NativePrinters dictionary.  It is estimated that a file containing approximately 21,000 printers will encode as a 5MB file.  The cryptographic hash is used to verify the integrity of the download.
 
-      The file is downloaded and cached. It will be re-downloaded whenever
-      the URL or the hash changes.
+      The file is downloaded and cached. It will be re-downloaded whenever the URL or the hash changes.
 
-      If this policy is set,
-      <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> will download
-      the file for printer configurations and make printers available in
-      accordance with NativePrintersBulkAccessMode, NativePrintersBulkWhitelist,
-      and NativePrintersBulkBlacklist.
+      If this policy is set, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> will download the file for printer configurations and make printers available in accordance with <ph name="BULK_PRINTERS_ACCESS_MODE">NativePrintersBulkAccessMode</ph>, <ph name="BULK_PRINTERS_WHITELIST">NativePrintersBulkWhitelist</ph>, and <ph name="BULK_PRINTERS_BLACKLIST">NativePrintersBulkBlacklist</ph>.
 
       If you set this policy, users cannot change or override it.
 
-      This policy has no effect on whether users can configure printers on
-      individual devices.  It is intended to be supplementary to the
-      configuration of printers by individual users.''',
+      This policy has no effect on whether users can configure printers on individual devices.  It is intended to be supplementary to the configuration of printers by individual users.
+      ''',
     },
     {
       'name': 'NativePrintersBulkAccessMode',
@@ -9545,17 +9552,11 @@
       'example_value': 1,
       'caption': '''Printer configuration access policy.''',
       'tags': [],
-      'desc': '''Controls which printers from the
-      NativePrintersBulkConfiguration are available to users.
+      'desc': '''Controls which printers from the <ph name="BULK_PRINTERS_POLICY">NativePrintersBulkConfiguration</ph> are available to users.
 
-      Designates which access policy is used for bulk printer configuration.
-      If AllowAll is selected, all printers are shown. If BlacklistRestrction
-      is selected, NativePrintersBulkBlacklist is used to restrict access to
-      the specified printers.  If WhitelistPrintersOnly is selected,
-      NativePrintersWhitelist designates only those printers which are
-      selectable.
+      Designates which access policy is used for bulk printer configuration. If <ph name="PRINTERS_ALLOW_ALL">AllowAll</ph> is selected, all printers are shown. If <ph name="PRINTERS_BLACKLIST">BlacklistRestriction</ph> is selected, <ph name="BULK_PRINTERS_BLACKLIST">NativePrintersBulkBlacklist</ph> is used to restrict access to the specified printers.  If <ph name="PRINTERS_WHITELIST">WhitelistPrintersOnly</ph> is selected, <ph name="BULK_PRINTERS_WHITELIST">NativePrintersBulkWhitelist</ph> designates only those printers which are selectable.
 
-      If this policy is not set, BlacklistRestriction is assumed.
+      If this policy is not set, <ph name="PRINTERS_BLACKLIST">BlacklistRestriction</ph> is assumed.
       ''',
     },
     {
@@ -9576,11 +9577,9 @@
       'tags': [],
       'desc': '''Specifies the printers which a user cannot use.
 
-      This policy is only used if BlacklistRestriction is chosen for
-      NativePrintersBulkAccessMode.
+      This policy is only used if <ph name="PRINTERS_BLACKLIST">BlacklistRestriction</ph> is chosen for <ph name="BULK_PRINTERS_ACCESS_MODE">NativePrintersBulkAccessMode</ph>.
 
-      If this policy is used, all printers are provided to the user except
-      for the ids listed in this policy.
+      If this policy is used, all printers are provided to the user except for the ids listed in this policy.
       ''',
     },
     {
@@ -9601,12 +9600,10 @@
       'tags': [],
       'desc': '''Specifies the printers which a user can use.
 
-      This policy is only used if WhitelistPrintersOnly is chosen for
-      NativePrintersBulkAccessMode.
+      This policy is only used if <ph name="PRINTERS_WHITELIST">WhitelistPrintersOnly</ph> is chosen for <ph name="BULK_PRINTERS_ACCESS_MODE">NativePrintersBulkAccessMode</ph>.
 
-      If this policy is used, only the printers with ids matching the values
-      in this policy are available to the user. The ids must coorespond to
-      the entries in the file specified in NativePrintersBulkConfiguration.''',
+      If this policy is used, only the printers with ids matching the values in this policy are available to the user. The ids must correspond to the entries in the file specified in <ph name="BULK_PRINTERS_POLICY">NativePrintersBulkConfiguration</ph>.
+      ''',
     },
     {
       'name': 'DeviceNativePrinters',
@@ -9634,31 +9631,17 @@
       'tags': [],
       'desc': '''Provides configurations for enterprise printers bound to devices.
 
-      This policy allows you to provide printer configurations to
-      <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> devices.
-      The size of the file must not exceed 5MB and must be encoded in JSON.
-      The format is the same as the NativePrinters dictionary.  It is estimated
-      that a file containing approximately 21,000 printers will encode as a 5MB
-      file.  The cryptographic hash is used to verify the integrity of the
-      download.
+      This policy allows you to provide printer configurations to <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> devices. The size of the file must not exceed 5MB and must be encoded in JSON. The format is the same as the NativePrinters dictionary.  It is estimated that a file containing approximately 21,000 printers will encode as a 5MB file.  The cryptographic hash is used to verify the integrity of the download.
 
-      The file is downloaded and cached. It will be re-downloaded whenever
-      the URL or the hash changes.
+      The file is downloaded and cached. It will be re-downloaded whenever the URL or the hash changes.
 
-      If this policy is set,
-      <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> will download
-      the file for printer configurations and make printers available in
-      accordance with DeviceNativePrintersAccessMode, DeviceNativePrintersWhitelist,
-      and DeviceNativePrintersBlacklist.
+      If this policy is set, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> will download the file for printer configurations and make printers available in accordance with <ph name="DEVICE_PRINTERS_ACCESS_MODE">DeviceNativePrintersAccessMode</ph>, <ph name="DEVICE_PRINTERS_WHITELIST">DeviceNativePrintersWhitelist</ph>, and <ph name="DEVICE_PRINTERS_BLACKLIST">DeviceNativePrintersBlacklist</ph>.
 
-      This policy has no effect on whether users can configure printers on
-      individual devices.  It is intended to be supplementary to the
-      configuration of printers by individual users.
+      This policy has no effect on whether users can configure printers on individual devices.  It is intended to be supplementary to the configuration of printers by individual users.
 
-      This policy is additive to the NativePrintersBulkConfiguration.
+      This policy is additive to the <ph name="BULK_PRINTERS_POLICY">NativePrintersBulkConfiguration</ph>.
 
-      If this policy is unset, there will be no device printers and the other
-      NativeDevicePrinter* policies will be ignroed.''',
+      If this policy is unset, there will be no device printers and the other <ph name="DEVICE_PRINTERS_POLICY_PATTERN">DeviceNativePrinter*</ph> policies will be ignored.''',
     },
     {
       'name': 'DeviceNativePrintersAccessMode',
@@ -9694,17 +9677,11 @@
       'example_value': 1,
       'caption': '''Device printers configuration access policy.''',
       'tags': [],
-      'desc': '''Controls which printers from the
-      DeviceNativePrintersConfiguration are available to users.
+      'desc': '''Controls which printers from the <ph name="DEVICE_PRINTERS_POLICY">DeviceNativePrinters</ph> are available to users.
 
-      Designates which access policy is used for bulk printer configuration.
-      If AllowAll is selected, all printers are shown. If BlacklistRestrction
-      is selected, DeviceNativePrintersBlacklist is used to restrict access to
-      the specified printers.  If WhitelistPrintersOnly is selected,
-      DeviceNativePrintersWhitelist designates only those printers which are
-      selectable.
+      Designates which access policy is used for bulk printer configuration. If <ph name="PRINTERS_ALLOW_ALL">AllowAll</ph> is selected, all printers are shown. If <ph name="PRINTERS_BLACKLIST">BlacklistRestriction</ph> is selected, <ph name="DEVICE_PRINTERS_BLACKLIST">DeviceNativePrintersBlacklist</ph> is used to restrict access to the specified printers.  If <ph name="PRINTERS_WHITELIST">WhitelistPrintersOnly</ph> is selected, <ph name="DEVICE_PRINTERS_WHITELIST">DeviceNativePrintersWhitelist</ph> designates only those printers which are selectable.
 
-      If this policy is not set, BlacklistRestriction is assumed.
+      If this policy is not set, <ph name="PRINTERS_BLACKLIST">BlacklistRestriction</ph> is assumed.
       ''',
     },
     {
@@ -9725,11 +9702,9 @@
       'tags': [],
       'desc': '''Specifies the printers which a user cannot use.
 
-      This policy is only used if BlacklistRestriction is chosen for
-      DeviceNativePrintersAccessMode.
+      This policy is only used if <ph name="PRINTERS_BLACKLIST">BlacklistRestriction</ph> is chosen for <ph name="DEVICE_PRINTERS_ACCESS_MODE">DeviceNativePrintersAccessMode</ph>.
 
-      If this policy is used, all printers are provided to the user except
-      for the ids listed in this policy.
+      If this policy is used, all printers are provided to the user except for the ids listed in this policy.
       ''',
     },
     {
@@ -9751,12 +9726,10 @@
       'tags': [],
       'desc': '''Specifies the printers which a user can use.
 
-      This policy is only used if WhitelistPrintersOnly is chosen for
-      DeviceNativePrintersAccessMode.
+      This policy is only used if <ph name="PRINTERS_WHITELIST">WhitelistPrintersOnly</ph> is chosen for <ph name="DEVICE_PRINTERS_ACCESS_MODE">DeviceNativePrintersAccessMode</ph>
 
-      If this policy is used, only the printers with ids matching the values
-      in this policy are available to the user. The ids must coorespond to
-      the entries in the file specified in DeviceNativePrinters.''',
+      If this policy is used, only the printers with ids matching the values in this policy are available to the user. The ids must correspond to the entries in the file specified in <ph name="DEVICE_PRINTERS_POLICY">DeviceNativePrinters</ph>.
+      ''',
     },
     {
       'name': 'TPMFirmwareUpdateSettings',
@@ -9940,7 +9913,7 @@
           'hash': { "type": "string" }
         },
       },
-      'supported_on': ['chrome_os:57-'],
+      'supported_on': ['chrome_os:61-'],
       'device_only': True,
       'features': {
         'dynamic_refresh': True,
diff --git a/components/printing/test/print_render_frame_helper_browsertest.cc b/components/printing/test/print_render_frame_helper_browsertest.cc
index d8559964..93f1f79 100644
--- a/components/printing/test/print_render_frame_helper_browsertest.cc
+++ b/components/printing/test/print_render_frame_helper_browsertest.cc
@@ -1041,7 +1041,9 @@
 // Test to verify that preview generated only for one page.
 TEST_F(MAYBE_PrintRenderFrameHelperPreviewTest, PrintPreviewForSelectedText) {
   LoadHTML(kMultipageHTML);
-  GetMainFrame()->SelectRange(blink::WebRange(1, 3));
+  GetMainFrame()->SelectRange(blink::WebRange(1, 3),
+                              blink::WebLocalFrame::kHideSelectionHandle,
+                              blink::mojom::SelectionMenuBehavior::kHide);
 
   // Fill in some dummy values.
   base::DictionaryValue dict;
diff --git a/components/safe_browsing/browser/BUILD.gn b/components/safe_browsing/browser/BUILD.gn
index 2121fb2..8c68dcc9 100644
--- a/components/safe_browsing/browser/BUILD.gn
+++ b/components/safe_browsing/browser/BUILD.gn
@@ -28,6 +28,7 @@
     "//components/data_use_measurement/core:core",
     "//components/history/core/browser:browser",
     "//components/safe_browsing:csd_proto",
+    "//components/safe_browsing:features",
     "//components/safe_browsing:safe_browsing",
     "//components/safe_browsing/common:common",
     "//components/safe_browsing/db:database_manager",
diff --git a/components/safe_browsing/browser/threat_details.cc b/components/safe_browsing/browser/threat_details.cc
index bef69f6..312d992 100644
--- a/components/safe_browsing/browser/threat_details.cc
+++ b/components/safe_browsing/browser/threat_details.cc
@@ -21,6 +21,7 @@
 #include "components/safe_browsing/browser/threat_details_history.h"
 #include "components/safe_browsing/common/safebrowsing_messages.h"
 #include "components/safe_browsing/db/hit_report.h"
+#include "components/safe_browsing/features.h"
 #include "components/safe_browsing/web_ui/safe_browsing_ui.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_controller.h"
@@ -85,6 +86,8 @@
       return ClientSafeBrowsingReportRequest::URL_CLIENT_SIDE_MALWARE;
     case SB_THREAT_TYPE_AD_SAMPLE:
       return ClientSafeBrowsingReportRequest::AD_SAMPLE;
+    case SB_THREAT_TYPE_PASSWORD_REUSE:
+      return ClientSafeBrowsingReportRequest::URL_PASSWORD_PROTECTION_PHISHING;
     default:  // Gated by SafeBrowsingBlockingPage::ShouldReportThreatDetails.
       NOTREACHED() << "We should not send report for threat type "
                    << threat_type;
@@ -739,6 +742,12 @@
     return;
   }
 
+  // For measuring performance impact of ad sampling reports, we may want to
+  // do all the heavy lifting of creating the report but not actually send it.
+  if (report_->type() == ClientSafeBrowsingReportRequest::AD_SAMPLE &&
+      base::FeatureList::IsEnabled(kAdSamplerCollectButDontSendFeature))
+    return;
+
   BrowserThread::PostTask(
       content::BrowserThread::UI, FROM_HERE,
       base::Bind(&WebUIInfoSingleton::AddToReportsSent,
diff --git a/components/safe_browsing/features.cc b/components/safe_browsing/features.cc
index f6675a8..b1742833 100644
--- a/components/safe_browsing/features.cc
+++ b/components/safe_browsing/features.cc
@@ -17,6 +17,12 @@
 // them to the ExperimentalFeaturesList below to start displaying their status
 // on the chrome://safe-browsing page.
 
+// Allows an ad sample report to be created but not sent. Used to measure
+// performance impact of report generation.
+const base::Feature kAdSamplerCollectButDontSendFeature{
+    "SafeBrowsingAdSamplerCollectButDontSend",
+    base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Controls various parameters related to occasionally collecting ad samples,
 // for example to control how often collection should occur.
 const base::Feature kAdSamplerTriggerFeature{"SafeBrowsingAdSamplerTrigger",
@@ -67,13 +73,14 @@
   // True if the feature is running at a probability other than 1 or 0.
   bool probabilistically_enabled;
 } kExperimentalFeatures[]{
+    {&kAdSamplerCollectButDontSendFeature, false},
     {&kAdSamplerTriggerFeature, false},
     {&kGaiaPasswordReuseReporting, true},
-    {&kGoogleBrandedPhishingWarning, false},
+    {&kGoogleBrandedPhishingWarning, true},
     {&kLocalDatabaseManagerEnabled, true},
     {&kParallelUrlCheck, true},
-    {&kPasswordFieldOnFocusPinging, true},
-    {&kProtectedPasswordEntryPinging, true},
+    {&kPasswordFieldOnFocusPinging, false},
+    {&kProtectedPasswordEntryPinging, false},
     {&kThreatDomDetailsTagAndAttributeFeature, false},
     {&kTriggerThrottlerDailyQuotaFeature, false},
     {&kV4OnlyEnabled, true},
diff --git a/components/safe_browsing/features.h b/components/safe_browsing/features.h
index f28407d..c4e6475 100644
--- a/components/safe_browsing/features.h
+++ b/components/safe_browsing/features.h
@@ -19,6 +19,7 @@
 
 namespace safe_browsing {
 // Features list
+extern const base::Feature kAdSamplerCollectButDontSendFeature;
 extern const base::Feature kAdSamplerTriggerFeature;
 // Gates logging of GaiaPasswordReuse user events.
 extern const base::Feature kGaiaPasswordReuseReporting;
diff --git a/components/safe_browsing/triggers/trigger_manager.cc b/components/safe_browsing/triggers/trigger_manager.cc
index 10e0c12..eaed42f 100644
--- a/components/safe_browsing/triggers/trigger_manager.cc
+++ b/components/safe_browsing/triggers/trigger_manager.cc
@@ -25,6 +25,9 @@
     case TriggerType::AD_SAMPLE:
       // Ad samples need Scout-level opt-in.
       return true;
+    case TriggerType::GAIA_PASSWORD_REUSE:
+      // Gaia password reuses only need legacy SBER opt-in.
+      return false;
   }
   // By default, require Scout so we are more restrictive on data collection.
   return true;
@@ -40,6 +43,11 @@
       // Ad samples happen in the background so the user must already be opted
       // in before the trigger is allowed to run.
       return true;
+    case TriggerType::GAIA_PASSWORD_REUSE:
+      // For Gaia password reuses, it is unlikely for users to change opt-in
+      // while the trigger runs, so we require opt-in for collection to avoid
+      // overheads.
+      return true;
   }
   // By default, require opt-in for all triggers.
   return true;
diff --git a/components/safe_browsing/triggers/trigger_throttler.cc b/components/safe_browsing/triggers/trigger_throttler.cc
index 0b75905..85e0da91 100644
--- a/components/safe_browsing/triggers/trigger_throttler.cc
+++ b/components/safe_browsing/triggers/trigger_throttler.cc
@@ -79,6 +79,7 @@
     const std::vector<TriggerTypeAndQuotaItem>& trigger_quota_list) {
   switch (trigger_type) {
     case TriggerType::SECURITY_INTERSTITIAL:
+    case TriggerType::GAIA_PASSWORD_REUSE:
       return kUnlimitedTriggerQuota;
     case TriggerType::AD_SAMPLE:
       // These triggers have quota configured via Finch, lookup the value in
diff --git a/components/safe_browsing/triggers/trigger_throttler.h b/components/safe_browsing/triggers/trigger_throttler.h
index f4746d7..cc74c555 100644
--- a/components/safe_browsing/triggers/trigger_throttler.h
+++ b/components/safe_browsing/triggers/trigger_throttler.h
@@ -21,6 +21,7 @@
 enum class TriggerType {
   SECURITY_INTERSTITIAL = 1,
   AD_SAMPLE = 2,
+  GAIA_PASSWORD_REUSE = 3,
 };
 
 struct TriggerTypeHash {
diff --git a/components/safe_browsing/web_ui/safe_browsing_ui.cc b/components/safe_browsing/web_ui/safe_browsing_ui.cc
index 85f5b758..f79f85b1 100644
--- a/components/safe_browsing/web_ui/safe_browsing_ui.cc
+++ b/components/safe_browsing/web_ui/safe_browsing_ui.cc
@@ -9,6 +9,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/base64.h"
 #include "base/base64url.h"
 #include "base/callback.h"
 #include "base/i18n/time_formatting.h"
@@ -253,10 +254,8 @@
   std::string serialized;
   if (report.SerializeToString(&serialized)) {
     std::string base64_encoded;
-    base::Base64UrlEncode(serialized,
-                          base::Base64UrlEncodePolicy::INCLUDE_PADDING,
-                          &base64_encoded);
-    report_request.SetString("base64(serialized)", base64_encoded);
+    base::Base64Encode(serialized, &base64_encoded);
+    report_request.SetString("csbrr(base64)", base64_encoded);
   }
 
   base::Value* report_request_tree = &report_request;
diff --git a/components/search_provider_logos/BUILD.gn b/components/search_provider_logos/BUILD.gn
index 12cb855a..2c1a900 100644
--- a/components/search_provider_logos/BUILD.gn
+++ b/components/search_provider_logos/BUILD.gn
@@ -16,6 +16,8 @@
     "logo_common.h",
     "logo_service.cc",
     "logo_service.h",
+    "logo_service_impl.cc",
+    "logo_service_impl.h",
     "logo_tracker.cc",
     "logo_tracker.h",
     "switches.cc",
@@ -84,7 +86,7 @@
   sources = [
     "google_logo_api_unittest.cc",
     "logo_cache_unittest.cc",
-    "logo_service_unittest.cc",
+    "logo_service_impl_unittest.cc",
   ]
   deps = [
     ":search_provider_logos",
diff --git a/components/search_provider_logos/features.cc b/components/search_provider_logos/features.cc
index dc044a8..9d88a4a 100644
--- a/components/search_provider_logos/features.cc
+++ b/components/search_provider_logos/features.cc
@@ -8,7 +8,7 @@
 namespace features {
 
 const base::Feature kUseDdljsonApi{"UseDdljsonApi",
-                                   base::FEATURE_DISABLED_BY_DEFAULT};
+                                   base::FEATURE_ENABLED_BY_DEFAULT};
 
 const char kDdljsonOverrideUrlParam[] = "ddljson-override-url";
 
diff --git a/components/search_provider_logos/logo_service.cc b/components/search_provider_logos/logo_service.cc
index 40afd4f7..631f827 100644
--- a/components/search_provider_logos/logo_service.cc
+++ b/components/search_provider_logos/logo_service.cc
@@ -4,277 +4,8 @@
 
 #include "components/search_provider_logos/logo_service.h"
 
-#include "base/command_line.h"
-#include "base/feature_list.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/metrics/field_trial_params.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/default_clock.h"
-#include "build/build_config.h"
-#include "components/image_fetcher/core/image_decoder.h"
-#include "components/search_engines/search_terms_data.h"
-#include "components/search_engines/template_url_service.h"
-#include "components/search_provider_logos/features.h"
-#include "components/search_provider_logos/fixed_logo_api.h"
-#include "components/search_provider_logos/google_logo_api.h"
-#include "components/search_provider_logos/logo_cache.h"
-#include "components/search_provider_logos/logo_tracker.h"
-#include "components/search_provider_logos/switches.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "ui/gfx/image/image.h"
-
-using search_provider_logos::LogoDelegate;
-using search_provider_logos::LogoTracker;
-
 namespace search_provider_logos {
-namespace {
 
-const int kDecodeLogoTimeoutSeconds = 30;
-
-// Implements a callback for image_fetcher::ImageDecoder. If Run() is called on
-// a callback returned by GetCallback() within 30 seconds, forwards the decoded
-// image to the wrapped callback. If not, sends an empty image to the wrapped
-// callback instead. Either way, deletes the object and prevents further calls.
-//
-// TODO(sfiera): find a more idiomatic way of setting a deadline on the
-// callback. This is implemented as a self-deleting object in part because it
-// needed to when it used to be a delegate and in part because I couldn't figure
-// out a better way, now that it isn't.
-class ImageDecodedHandlerWithTimeout {
- public:
-  static base::Callback<void(const gfx::Image&)> Wrap(
-      const base::Callback<void(const SkBitmap&)>& image_decoded_callback) {
-    auto* handler = new ImageDecodedHandlerWithTimeout(image_decoded_callback);
-    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-        FROM_HERE,
-        base::Bind(&ImageDecodedHandlerWithTimeout::OnImageDecoded,
-                   handler->weak_ptr_factory_.GetWeakPtr(), gfx::Image()),
-        base::TimeDelta::FromSeconds(kDecodeLogoTimeoutSeconds));
-    return base::Bind(&ImageDecodedHandlerWithTimeout::OnImageDecoded,
-                      handler->weak_ptr_factory_.GetWeakPtr());
-  }
-
- private:
-  explicit ImageDecodedHandlerWithTimeout(
-      const base::Callback<void(const SkBitmap&)>& image_decoded_callback)
-      : image_decoded_callback_(image_decoded_callback),
-        weak_ptr_factory_(this) {}
-
-  void OnImageDecoded(const gfx::Image& decoded_image) {
-    image_decoded_callback_.Run(decoded_image.AsBitmap());
-    delete this;
-  }
-
-  base::Callback<void(const SkBitmap&)> image_decoded_callback_;
-  base::WeakPtrFactory<ImageDecodedHandlerWithTimeout> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(ImageDecodedHandlerWithTimeout);
-};
-
-class LogoDelegateImpl : public search_provider_logos::LogoDelegate {
- public:
-  explicit LogoDelegateImpl(
-      std::unique_ptr<image_fetcher::ImageDecoder> image_decoder)
-      : image_decoder_(std::move(image_decoder)) {}
-
-  ~LogoDelegateImpl() override = default;
-
-  // search_provider_logos::LogoDelegate:
-  void DecodeUntrustedImage(
-      const scoped_refptr<base::RefCountedString>& encoded_image,
-      base::Callback<void(const SkBitmap&)> image_decoded_callback) override {
-    image_decoder_->DecodeImage(
-        encoded_image->data(),
-        gfx::Size(),  // No particular size desired.
-        ImageDecodedHandlerWithTimeout::Wrap(image_decoded_callback));
-  }
-
- private:
-  const std::unique_ptr<image_fetcher::ImageDecoder> image_decoder_;
-
-  DISALLOW_COPY_AND_ASSIGN(LogoDelegateImpl);
-};
-
-void ObserverOnLogoAvailable(LogoObserver* observer,
-                             bool from_cache,
-                             LogoCallbackReason type,
-                             const base::Optional<Logo>& logo) {
-  switch (type) {
-    case LogoCallbackReason::DISABLED:
-    case LogoCallbackReason::CANCELED:
-    case LogoCallbackReason::FAILED:
-      break;
-
-    case LogoCallbackReason::REVALIDATED:
-      // TODO(sfiera): double-check whether we should inform the observer of the
-      // fresh metadata.
-      break;
-
-    case LogoCallbackReason::DETERMINED:
-      observer->OnLogoAvailable(logo ? &logo.value() : nullptr, from_cache);
-      break;
-  }
-  if (!from_cache) {
-    observer->OnObserverRemoved();
-  }
-}
-
-void RunCallbacksWithDisabled(LogoCallbacks callbacks) {
-  if (callbacks.on_cached_encoded_logo_available) {
-    std::move(callbacks.on_cached_encoded_logo_available)
-        .Run(LogoCallbackReason::DISABLED, base::nullopt);
-  }
-  if (callbacks.on_cached_decoded_logo_available) {
-    std::move(callbacks.on_cached_decoded_logo_available)
-        .Run(LogoCallbackReason::DISABLED, base::nullopt);
-  }
-  if (callbacks.on_fresh_encoded_logo_available) {
-    std::move(callbacks.on_fresh_encoded_logo_available)
-        .Run(LogoCallbackReason::DISABLED, base::nullopt);
-  }
-  if (callbacks.on_fresh_decoded_logo_available) {
-    std::move(callbacks.on_fresh_decoded_logo_available)
-        .Run(LogoCallbackReason::DISABLED, base::nullopt);
-  }
-}
-
-}  // namespace
-
-LogoService::LogoService(
-    const base::FilePath& cache_directory,
-    TemplateURLService* template_url_service,
-    std::unique_ptr<image_fetcher::ImageDecoder> image_decoder,
-    scoped_refptr<net::URLRequestContextGetter> request_context_getter,
-    bool use_gray_background)
-    : cache_directory_(cache_directory),
-      template_url_service_(template_url_service),
-      request_context_getter_(request_context_getter),
-      use_gray_background_(use_gray_background),
-      image_decoder_(std::move(image_decoder)) {}
-
-LogoService::~LogoService() = default;
-
-void LogoService::GetLogo(search_provider_logos::LogoObserver* observer) {
-  LogoCallbacks callbacks;
-  callbacks.on_cached_decoded_logo_available =
-      base::BindOnce(ObserverOnLogoAvailable, observer, true);
-  callbacks.on_fresh_decoded_logo_available =
-      base::BindOnce(ObserverOnLogoAvailable, observer, false);
-  GetLogo(std::move(callbacks));
-}
-
-void LogoService::GetLogo(LogoCallbacks callbacks) {
-  if (!template_url_service_) {
-    RunCallbacksWithDisabled(std::move(callbacks));
-    return;
-  }
-
-  const TemplateURL* template_url =
-      template_url_service_->GetDefaultSearchProvider();
-  if (!template_url) {
-    RunCallbacksWithDisabled(std::move(callbacks));
-    return;
-  }
-
-  const base::CommandLine* command_line =
-      base::CommandLine::ForCurrentProcess();
-
-  GURL logo_url;
-  if (command_line->HasSwitch(switches::kSearchProviderLogoURL)) {
-    logo_url = GURL(
-        command_line->GetSwitchValueASCII(switches::kSearchProviderLogoURL));
-  } else {
-#if defined(OS_ANDROID)
-    // Non-Google default search engine logos are currently enabled only on
-    // Android (https://crbug.com/737283).
-    logo_url = template_url->logo_url();
-#endif
-  }
-
-  GURL base_url;
-  GURL doodle_url;
-  const bool is_google = template_url->url_ref().HasGoogleBaseURLs(
-      template_url_service_->search_terms_data());
-  if (is_google) {
-    // TODO(treib): After features::kUseDdljsonApi has launched, put the Google
-    // doodle URL into prepopulated_engines.json.
-    base_url =
-        GURL(template_url_service_->search_terms_data().GoogleBaseURLValue());
-    doodle_url = search_provider_logos::GetGoogleDoodleURL(base_url);
-  } else if (base::FeatureList::IsEnabled(features::kThirdPartyDoodles)) {
-    // First try to get the Doodle URL from the command line, then from a
-    // feature param, and finally the "real" one from TemplateURL.
-    if (command_line->HasSwitch(switches::kThirdPartyDoodleURL)) {
-      doodle_url = GURL(
-          command_line->GetSwitchValueASCII(switches::kThirdPartyDoodleURL));
-    } else {
-      std::string override_url = base::GetFieldTrialParamValueByFeature(
-          features::kThirdPartyDoodles,
-          features::kThirdPartyDoodlesOverrideUrlParam);
-      if (!override_url.empty()) {
-        doodle_url = GURL(override_url);
-      } else {
-        doodle_url = template_url->doodle_url();
-      }
-    }
-    base_url = doodle_url.GetOrigin();
-  }
-
-  if (!logo_url.is_valid() && !doodle_url.is_valid()) {
-    RunCallbacksWithDisabled(std::move(callbacks));
-    return;
-  }
-
-  const bool use_fixed_logo = !doodle_url.is_valid();
-
-  if (!logo_tracker_) {
-    std::unique_ptr<LogoCache> logo_cache = std::move(logo_cache_for_test_);
-    if (!logo_cache) {
-      logo_cache = std::make_unique<LogoCache>(cache_directory_);
-    }
-
-    std::unique_ptr<base::Clock> clock = std::move(clock_for_test_);
-    if (!clock) {
-      clock = std::make_unique<base::DefaultClock>();
-    }
-
-    logo_tracker_ = std::make_unique<LogoTracker>(
-        request_context_getter_,
-        std::make_unique<LogoDelegateImpl>(std::move(image_decoder_)),
-        std::move(logo_cache), std::move(clock));
-  }
-
-  if (use_fixed_logo) {
-    logo_tracker_->SetServerAPI(
-        logo_url, base::Bind(&search_provider_logos::ParseFixedLogoResponse),
-        base::Bind(&search_provider_logos::UseFixedLogoUrl));
-  } else if (is_google) {
-    // TODO(treib): Get rid of this Google special case after
-    // features::kUseDdljsonApi has launched.
-    logo_tracker_->SetServerAPI(
-        doodle_url,
-        search_provider_logos::GetGoogleParseLogoResponseCallback(base_url),
-        search_provider_logos::GetGoogleAppendQueryparamsCallback(
-            use_gray_background_));
-  } else {
-    logo_tracker_->SetServerAPI(
-        doodle_url,
-        base::Bind(&search_provider_logos::GoogleNewParseLogoResponse,
-                   base_url),
-        base::Bind(&search_provider_logos::GoogleNewAppendQueryparamsToLogoURL,
-                   use_gray_background_));
-  }
-
-  logo_tracker_->GetLogo(std::move(callbacks));
-}
-
-void LogoService::SetLogoCacheForTests(std::unique_ptr<LogoCache> cache) {
-  logo_cache_for_test_ = std::move(cache);
-}
-
-void LogoService::SetClockForTests(std::unique_ptr<base::Clock> clock) {
-  clock_for_test_ = std::move(clock);
-}
+LogoService::LogoService() = default;
 
 }  // namespace search_provider_logos
diff --git a/components/search_provider_logos/logo_service.h b/components/search_provider_logos/logo_service.h
index 0cafc58..2ffb09b6 100644
--- a/components/search_provider_logos/logo_service.h
+++ b/components/search_provider_logos/logo_service.h
@@ -5,51 +5,24 @@
 #ifndef COMPONENTS_SEARCH_PROVIDER_LOGOS_ANDROID_LOGO_SERVICE_H_
 #define COMPONENTS_SEARCH_PROVIDER_LOGOS_ANDROID_LOGO_SERVICE_H_
 
-#include <memory>
-
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/search_provider_logos/logo_common.h"
 
-class TemplateURLService;
-
-namespace base {
-class Clock;
-}  // namespace base
-
-namespace image_fetcher {
-class ImageDecoder;
-}  // namespace image_fetcher
-
-namespace net {
-class URLRequestContextGetter;
-}  // namespace net
-
 namespace search_provider_logos {
 
-class LogoCache;
-class LogoTracker;
 class LogoObserver;
 
 // Provides the logo for a profile's default search provider.
 //
 // Example usage:
 //   LogoService* logo_service = LogoServiceFactory::GetForProfile(profile);
-//   logo_service->GetLogo(...);
+//   LogoCallbacks callbacks;
+//   callbacks.on_cached_decoded_logo = base::Bind(ShowLogo);
+//   callbacks.on_fresh_decoded_logo = base::Bind(FadeToLogo);
+//   logo_service->GetLogo(callbacks);
 //
 class LogoService : public KeyedService {
  public:
-  LogoService(
-      const base::FilePath& cache_directory,
-      TemplateURLService* template_url_service,
-      std::unique_ptr<image_fetcher::ImageDecoder> image_decoder,
-      scoped_refptr<net::URLRequestContextGetter> request_context_getter,
-      bool use_gray_background);
-
-  ~LogoService() override;
-
   // Gets the logo for the default search provider and calls the provided
   // callbacks with the encoded and decoded logos. The service will:
   //
@@ -57,7 +30,7 @@
   // 2.  Fetch a fresh logo, and call callbacks.on_fresh_{en,de}coded_logo.
   //
   // At least one member of |callbacks| must be non-null.
-  void GetLogo(LogoCallbacks callbacks);
+  virtual void GetLogo(LogoCallbacks callbacks) = 0;
 
   // Gets the logo for the default search provider and notifies |observer|
   // 0-2 times with the results. The service will:
@@ -69,31 +42,12 @@
   //     |on_fresh_decoded_logo_available| would be called in the callback
   //     interface with type DETERMINED.
   // 3.  Call observer->OnObserverRemoved().
-  void GetLogo(LogoObserver* observer);
+  virtual void GetLogo(LogoObserver* observer) = 0;
 
-  // Overrides the cache used to store logos.
-  void SetLogoCacheForTests(std::unique_ptr<LogoCache> cache);
-
-  // Overrides the clock used to check the time.
-  void SetClockForTests(std::unique_ptr<base::Clock> clock);
+ protected:
+  LogoService();
 
  private:
-  // Constructor arguments.
-  const base::FilePath cache_directory_;
-  TemplateURLService* const template_url_service_;
-  const scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
-  const bool use_gray_background_;
-
-  // logo_tracker_ takes ownership if/when it is initialized.
-  std::unique_ptr<image_fetcher::ImageDecoder> image_decoder_;
-
-  // For testing. logo_tracker_ takes ownership if/when it is initialized.
-  std::unique_ptr<base::Clock> clock_for_test_;
-  std::unique_ptr<LogoCache> logo_cache_for_test_;
-
-  // Lazily initialized on first call to GetLogo().
-  std::unique_ptr<search_provider_logos::LogoTracker> logo_tracker_;
-
   DISALLOW_COPY_AND_ASSIGN(LogoService);
 };
 
diff --git a/components/search_provider_logos/logo_service_impl.cc b/components/search_provider_logos/logo_service_impl.cc
new file mode 100644
index 0000000..c787e5bc
--- /dev/null
+++ b/components/search_provider_logos/logo_service_impl.cc
@@ -0,0 +1,281 @@
+// 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/search_provider_logos/logo_service_impl.h"
+
+#include "base/command_line.h"
+#include "base/feature_list.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/default_clock.h"
+#include "build/build_config.h"
+#include "components/image_fetcher/core/image_decoder.h"
+#include "components/search_engines/search_terms_data.h"
+#include "components/search_engines/template_url_service.h"
+#include "components/search_provider_logos/features.h"
+#include "components/search_provider_logos/fixed_logo_api.h"
+#include "components/search_provider_logos/google_logo_api.h"
+#include "components/search_provider_logos/logo_cache.h"
+#include "components/search_provider_logos/logo_tracker.h"
+#include "components/search_provider_logos/switches.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "ui/gfx/image/image.h"
+
+using search_provider_logos::LogoDelegate;
+using search_provider_logos::LogoTracker;
+
+namespace search_provider_logos {
+namespace {
+
+const int kDecodeLogoTimeoutSeconds = 30;
+
+// Implements a callback for image_fetcher::ImageDecoder. If Run() is called on
+// a callback returned by GetCallback() within 30 seconds, forwards the decoded
+// image to the wrapped callback. If not, sends an empty image to the wrapped
+// callback instead. Either way, deletes the object and prevents further calls.
+//
+// TODO(sfiera): find a more idiomatic way of setting a deadline on the
+// callback. This is implemented as a self-deleting object in part because it
+// needed to when it used to be a delegate and in part because I couldn't figure
+// out a better way, now that it isn't.
+class ImageDecodedHandlerWithTimeout {
+ public:
+  static base::Callback<void(const gfx::Image&)> Wrap(
+      const base::Callback<void(const SkBitmap&)>& image_decoded_callback) {
+    auto* handler = new ImageDecodedHandlerWithTimeout(image_decoded_callback);
+    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+        FROM_HERE,
+        base::Bind(&ImageDecodedHandlerWithTimeout::OnImageDecoded,
+                   handler->weak_ptr_factory_.GetWeakPtr(), gfx::Image()),
+        base::TimeDelta::FromSeconds(kDecodeLogoTimeoutSeconds));
+    return base::Bind(&ImageDecodedHandlerWithTimeout::OnImageDecoded,
+                      handler->weak_ptr_factory_.GetWeakPtr());
+  }
+
+ private:
+  explicit ImageDecodedHandlerWithTimeout(
+      const base::Callback<void(const SkBitmap&)>& image_decoded_callback)
+      : image_decoded_callback_(image_decoded_callback),
+        weak_ptr_factory_(this) {}
+
+  void OnImageDecoded(const gfx::Image& decoded_image) {
+    image_decoded_callback_.Run(decoded_image.AsBitmap());
+    delete this;
+  }
+
+  base::Callback<void(const SkBitmap&)> image_decoded_callback_;
+  base::WeakPtrFactory<ImageDecodedHandlerWithTimeout> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(ImageDecodedHandlerWithTimeout);
+};
+
+class LogoDelegateImpl : public search_provider_logos::LogoDelegate {
+ public:
+  explicit LogoDelegateImpl(
+      std::unique_ptr<image_fetcher::ImageDecoder> image_decoder)
+      : image_decoder_(std::move(image_decoder)) {}
+
+  ~LogoDelegateImpl() override = default;
+
+  // search_provider_logos::LogoDelegate:
+  void DecodeUntrustedImage(
+      const scoped_refptr<base::RefCountedString>& encoded_image,
+      base::Callback<void(const SkBitmap&)> image_decoded_callback) override {
+    image_decoder_->DecodeImage(
+        encoded_image->data(),
+        gfx::Size(),  // No particular size desired.
+        ImageDecodedHandlerWithTimeout::Wrap(image_decoded_callback));
+  }
+
+ private:
+  const std::unique_ptr<image_fetcher::ImageDecoder> image_decoder_;
+
+  DISALLOW_COPY_AND_ASSIGN(LogoDelegateImpl);
+};
+
+void ObserverOnLogoAvailable(LogoObserver* observer,
+                             bool from_cache,
+                             LogoCallbackReason type,
+                             const base::Optional<Logo>& logo) {
+  switch (type) {
+    case LogoCallbackReason::DISABLED:
+    case LogoCallbackReason::CANCELED:
+    case LogoCallbackReason::FAILED:
+      break;
+
+    case LogoCallbackReason::REVALIDATED:
+      // TODO(sfiera): double-check whether we should inform the observer of the
+      // fresh metadata.
+      break;
+
+    case LogoCallbackReason::DETERMINED:
+      observer->OnLogoAvailable(logo ? &logo.value() : nullptr, from_cache);
+      break;
+  }
+  if (!from_cache) {
+    observer->OnObserverRemoved();
+  }
+}
+
+void RunCallbacksWithDisabled(LogoCallbacks callbacks) {
+  if (callbacks.on_cached_encoded_logo_available) {
+    std::move(callbacks.on_cached_encoded_logo_available)
+        .Run(LogoCallbackReason::DISABLED, base::nullopt);
+  }
+  if (callbacks.on_cached_decoded_logo_available) {
+    std::move(callbacks.on_cached_decoded_logo_available)
+        .Run(LogoCallbackReason::DISABLED, base::nullopt);
+  }
+  if (callbacks.on_fresh_encoded_logo_available) {
+    std::move(callbacks.on_fresh_encoded_logo_available)
+        .Run(LogoCallbackReason::DISABLED, base::nullopt);
+  }
+  if (callbacks.on_fresh_decoded_logo_available) {
+    std::move(callbacks.on_fresh_decoded_logo_available)
+        .Run(LogoCallbackReason::DISABLED, base::nullopt);
+  }
+}
+
+}  // namespace
+
+LogoServiceImpl::LogoServiceImpl(
+    const base::FilePath& cache_directory,
+    TemplateURLService* template_url_service,
+    std::unique_ptr<image_fetcher::ImageDecoder> image_decoder,
+    scoped_refptr<net::URLRequestContextGetter> request_context_getter,
+    bool use_gray_background)
+    : LogoService(),
+      cache_directory_(cache_directory),
+      template_url_service_(template_url_service),
+      request_context_getter_(request_context_getter),
+      use_gray_background_(use_gray_background),
+      image_decoder_(std::move(image_decoder)) {}
+
+LogoServiceImpl::~LogoServiceImpl() = default;
+
+void LogoServiceImpl::GetLogo(search_provider_logos::LogoObserver* observer) {
+  LogoCallbacks callbacks;
+  callbacks.on_cached_decoded_logo_available =
+      base::BindOnce(ObserverOnLogoAvailable, observer, true);
+  callbacks.on_fresh_decoded_logo_available =
+      base::BindOnce(ObserverOnLogoAvailable, observer, false);
+  GetLogo(std::move(callbacks));
+}
+
+void LogoServiceImpl::GetLogo(LogoCallbacks callbacks) {
+  if (!template_url_service_) {
+    RunCallbacksWithDisabled(std::move(callbacks));
+    return;
+  }
+
+  const TemplateURL* template_url =
+      template_url_service_->GetDefaultSearchProvider();
+  if (!template_url) {
+    RunCallbacksWithDisabled(std::move(callbacks));
+    return;
+  }
+
+  const base::CommandLine* command_line =
+      base::CommandLine::ForCurrentProcess();
+
+  GURL logo_url;
+  if (command_line->HasSwitch(switches::kSearchProviderLogoURL)) {
+    logo_url = GURL(
+        command_line->GetSwitchValueASCII(switches::kSearchProviderLogoURL));
+  } else {
+#if defined(OS_ANDROID)
+    // Non-Google default search engine logos are currently enabled only on
+    // Android (https://crbug.com/737283).
+    logo_url = template_url->logo_url();
+#endif
+  }
+
+  GURL base_url;
+  GURL doodle_url;
+  const bool is_google = template_url->url_ref().HasGoogleBaseURLs(
+      template_url_service_->search_terms_data());
+  if (is_google) {
+    // TODO(treib): After features::kUseDdljsonApi has launched, put the Google
+    // doodle URL into prepopulated_engines.json.
+    base_url =
+        GURL(template_url_service_->search_terms_data().GoogleBaseURLValue());
+    doodle_url = search_provider_logos::GetGoogleDoodleURL(base_url);
+  } else if (base::FeatureList::IsEnabled(features::kThirdPartyDoodles)) {
+    // First try to get the Doodle URL from the command line, then from a
+    // feature param, and finally the "real" one from TemplateURL.
+    if (command_line->HasSwitch(switches::kThirdPartyDoodleURL)) {
+      doodle_url = GURL(
+          command_line->GetSwitchValueASCII(switches::kThirdPartyDoodleURL));
+    } else {
+      std::string override_url = base::GetFieldTrialParamValueByFeature(
+          features::kThirdPartyDoodles,
+          features::kThirdPartyDoodlesOverrideUrlParam);
+      if (!override_url.empty()) {
+        doodle_url = GURL(override_url);
+      } else {
+        doodle_url = template_url->doodle_url();
+      }
+    }
+    base_url = doodle_url.GetOrigin();
+  }
+
+  if (!logo_url.is_valid() && !doodle_url.is_valid()) {
+    RunCallbacksWithDisabled(std::move(callbacks));
+    return;
+  }
+
+  const bool use_fixed_logo = !doodle_url.is_valid();
+
+  if (!logo_tracker_) {
+    std::unique_ptr<LogoCache> logo_cache = std::move(logo_cache_for_test_);
+    if (!logo_cache) {
+      logo_cache = std::make_unique<LogoCache>(cache_directory_);
+    }
+
+    std::unique_ptr<base::Clock> clock = std::move(clock_for_test_);
+    if (!clock) {
+      clock = std::make_unique<base::DefaultClock>();
+    }
+
+    logo_tracker_ = std::make_unique<LogoTracker>(
+        request_context_getter_,
+        std::make_unique<LogoDelegateImpl>(std::move(image_decoder_)),
+        std::move(logo_cache), std::move(clock));
+  }
+
+  if (use_fixed_logo) {
+    logo_tracker_->SetServerAPI(
+        logo_url, base::Bind(&search_provider_logos::ParseFixedLogoResponse),
+        base::Bind(&search_provider_logos::UseFixedLogoUrl));
+  } else if (is_google) {
+    // TODO(treib): Get rid of this Google special case after
+    // features::kUseDdljsonApi has launched.
+    logo_tracker_->SetServerAPI(
+        doodle_url,
+        search_provider_logos::GetGoogleParseLogoResponseCallback(base_url),
+        search_provider_logos::GetGoogleAppendQueryparamsCallback(
+            use_gray_background_));
+  } else {
+    logo_tracker_->SetServerAPI(
+        doodle_url,
+        base::Bind(&search_provider_logos::GoogleNewParseLogoResponse,
+                   base_url),
+        base::Bind(&search_provider_logos::GoogleNewAppendQueryparamsToLogoURL,
+                   use_gray_background_));
+  }
+
+  logo_tracker_->GetLogo(std::move(callbacks));
+}
+
+void LogoServiceImpl::SetLogoCacheForTests(std::unique_ptr<LogoCache> cache) {
+  logo_cache_for_test_ = std::move(cache);
+}
+
+void LogoServiceImpl::SetClockForTests(std::unique_ptr<base::Clock> clock) {
+  clock_for_test_ = std::move(clock);
+}
+
+}  // namespace search_provider_logos
diff --git a/components/search_provider_logos/logo_service_impl.h b/components/search_provider_logos/logo_service_impl.h
new file mode 100644
index 0000000..cbbb375a
--- /dev/null
+++ b/components/search_provider_logos/logo_service_impl.h
@@ -0,0 +1,77 @@
+// 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_SEARCH_PROVIDER_LOGOS_ANDROID_LOGO_SERVICE_IMPL_H_
+#define COMPONENTS_SEARCH_PROVIDER_LOGOS_ANDROID_LOGO_SERVICE_IMPL_H_
+
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "components/search_provider_logos/logo_common.h"
+#include "components/search_provider_logos/logo_service.h"
+
+class TemplateURLService;
+
+namespace base {
+class Clock;
+}  // namespace base
+
+namespace image_fetcher {
+class ImageDecoder;
+}  // namespace image_fetcher
+
+namespace net {
+class URLRequestContextGetter;
+}  // namespace net
+
+namespace search_provider_logos {
+
+class LogoCache;
+class LogoTracker;
+class LogoObserver;
+
+class LogoServiceImpl : public LogoService {
+ public:
+  LogoServiceImpl(
+      const base::FilePath& cache_directory,
+      TemplateURLService* template_url_service,
+      std::unique_ptr<image_fetcher::ImageDecoder> image_decoder,
+      scoped_refptr<net::URLRequestContextGetter> request_context_getter,
+      bool use_gray_background);
+
+  ~LogoServiceImpl() override;
+
+  // LogoService
+  void GetLogo(LogoCallbacks callbacks) override;
+  void GetLogo(LogoObserver* observer) override;
+
+  // Overrides the cache used to store logos.
+  void SetLogoCacheForTests(std::unique_ptr<LogoCache> cache);
+
+  // Overrides the clock used to check the time.
+  void SetClockForTests(std::unique_ptr<base::Clock> clock);
+
+ private:
+  // Constructor arguments.
+  const base::FilePath cache_directory_;
+  TemplateURLService* const template_url_service_;
+  const scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
+  const bool use_gray_background_;
+
+  // logo_tracker_ takes ownership if/when it is initialized.
+  std::unique_ptr<image_fetcher::ImageDecoder> image_decoder_;
+
+  // For testing. logo_tracker_ takes ownership if/when it is initialized.
+  std::unique_ptr<base::Clock> clock_for_test_;
+  std::unique_ptr<LogoCache> logo_cache_for_test_;
+
+  // Lazily initialized on first call to GetLogo().
+  std::unique_ptr<search_provider_logos::LogoTracker> logo_tracker_;
+
+  DISALLOW_COPY_AND_ASSIGN(LogoServiceImpl);
+};
+
+}  // namespace search_provider_logos
+
+#endif  // COMPONENTS_SEARCH_PROVIDER_LOGOS_ANDROID_LOGO_SERVICE_IMPL_H_
diff --git a/components/search_provider_logos/logo_service_impl_unittest.cc b/components/search_provider_logos/logo_service_impl_unittest.cc
new file mode 100644
index 0000000..5f246b7
--- /dev/null
+++ b/components/search_provider_logos/logo_service_impl_unittest.cc
@@ -0,0 +1,946 @@
+// 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 "components/search_provider_logos/logo_service_impl.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+#include <vector>
+
+#include "base/base64.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/files/file_path.h"
+#include "base/json/json_writer.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/stringprintf.h"
+#include "base/test/mock_callback.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/test/simple_test_clock.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
+#include "base/values.h"
+#include "build/build_config.h"
+#include "components/image_fetcher/core/image_decoder.h"
+#include "components/search_engines/template_url.h"
+#include "components/search_engines/template_url_data.h"
+#include "components/search_engines/template_url_service.h"
+#include "components/search_provider_logos/features.h"
+#include "components/search_provider_logos/fixed_logo_api.h"
+#include "components/search_provider_logos/google_logo_api.h"
+#include "components/search_provider_logos/logo_cache.h"
+#include "components/search_provider_logos/logo_tracker.h"
+#include "net/base/url_util.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_status_code.h"
+#include "net/url_request/test_url_fetcher_factory.h"
+#include "net/url_request/url_request_status.h"
+#include "net/url_request/url_request_test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/image/image.h"
+
+using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::AtMost;
+using ::testing::Eq;
+using ::testing::InSequence;
+using ::testing::Invoke;
+using ::testing::Mock;
+using ::testing::Ne;
+using ::testing::NiceMock;
+using ::testing::Not;
+using ::testing::NotNull;
+using ::testing::Pointee;
+using ::testing::StrictMock;
+using ::testing::Return;
+
+namespace search_provider_logos {
+
+namespace {
+
+using MockLogoCallback = base::MockCallback<LogoCallback>;
+using MockEncodedLogoCallback = base::MockCallback<EncodedLogoCallback>;
+
+scoped_refptr<base::RefCountedString> EncodeBitmapAsPNG(
+    const SkBitmap& bitmap) {
+  scoped_refptr<base::RefCountedMemory> png_bytes =
+      gfx::Image::CreateFrom1xBitmap(bitmap).As1xPNGBytes();
+  scoped_refptr<base::RefCountedString> str = new base::RefCountedString();
+  str->data().assign(png_bytes->front_as<char>(), png_bytes->size());
+  return str;
+}
+
+std::string EncodeBitmapAsPNGBase64(const SkBitmap& bitmap) {
+  scoped_refptr<base::RefCountedString> png_bytes = EncodeBitmapAsPNG(bitmap);
+  std::string encoded_image_base64;
+  base::Base64Encode(png_bytes->data(), &encoded_image_base64);
+  return encoded_image_base64;
+}
+
+SkBitmap MakeBitmap(int width, int height) {
+  SkBitmap bitmap;
+  bitmap.allocN32Pixels(width, height);
+  bitmap.eraseColor(SK_ColorBLUE);
+  return bitmap;
+}
+
+EncodedLogo EncodeLogo(const Logo& logo) {
+  EncodedLogo encoded_logo;
+  encoded_logo.encoded_image = EncodeBitmapAsPNG(logo.image);
+  encoded_logo.metadata = logo.metadata;
+  return encoded_logo;
+}
+
+Logo DecodeLogo(const EncodedLogo& encoded_logo) {
+  Logo logo;
+  logo.image =
+      gfx::Image::CreateFrom1xPNGBytes(encoded_logo.encoded_image->front(),
+                                       encoded_logo.encoded_image->size())
+          .AsBitmap();
+  logo.metadata = encoded_logo.metadata;
+  return logo;
+}
+
+Logo GetSampleLogo(const GURL& logo_url, base::Time response_time) {
+  Logo logo;
+  logo.image = MakeBitmap(2, 5);
+  logo.metadata.can_show_after_expiration = false;
+  logo.metadata.expiration_time =
+      response_time + base::TimeDelta::FromHours(19);
+  logo.metadata.fingerprint = "8bc33a80";
+  logo.metadata.source_url = logo_url;
+  logo.metadata.on_click_url = GURL("http://www.google.com/search?q=potato");
+  logo.metadata.alt_text = "A logo about potatoes";
+  logo.metadata.animated_url = GURL("http://www.google.com/logos/doodle.png");
+  logo.metadata.mime_type = "image/png";
+  return logo;
+}
+
+Logo GetSampleLogo2(const GURL& logo_url, base::Time response_time) {
+  Logo logo;
+  logo.image = MakeBitmap(4, 3);
+  logo.metadata.can_show_after_expiration = true;
+  logo.metadata.expiration_time = base::Time();
+  logo.metadata.fingerprint = "71082741021409127";
+  logo.metadata.source_url = logo_url;
+  logo.metadata.on_click_url = GURL("http://example.com/page25");
+  logo.metadata.alt_text = "The logo for example.com";
+  logo.metadata.mime_type = "image/jpeg";
+  return logo;
+}
+
+std::string MakeServerResponse(const SkBitmap& image,
+                               const std::string& on_click_url,
+                               const std::string& alt_text,
+                               const std::string& animated_url,
+                               const std::string& mime_type,
+                               const std::string& fingerprint,
+                               base::TimeDelta time_to_live) {
+  base::DictionaryValue dict;
+
+  std::string data_uri = "data:";
+  data_uri += mime_type;
+  data_uri += ";base64,";
+  data_uri += EncodeBitmapAsPNGBase64(image);
+
+  dict.SetString("ddljson.target_url", on_click_url);
+  dict.SetString("ddljson.alt_text", alt_text);
+  if (animated_url.empty()) {
+    dict.SetString("ddljson.doodle_type", "SIMPLE");
+    if (!image.isNull())
+      dict.SetString("ddljson.data_uri", data_uri);
+  } else {
+    dict.SetString("ddljson.doodle_type", "ANIMATED");
+    dict.SetBoolean("ddljson.large_image.is_animated_gif", true);
+    dict.SetString("ddljson.large_image.url", animated_url);
+    if (!image.isNull())
+      dict.SetString("ddljson.cta_data_uri", data_uri);
+  }
+  dict.SetString("ddljson.fingerprint", fingerprint);
+  if (time_to_live != base::TimeDelta())
+    dict.SetInteger("ddljson.time_to_live_ms",
+                    static_cast<int>(time_to_live.InMilliseconds()));
+
+  std::string output;
+  base::JSONWriter::Write(dict, &output);
+  return output;
+}
+
+std::string MakeServerResponse(const Logo& logo, base::TimeDelta time_to_live) {
+  return MakeServerResponse(
+      logo.image, logo.metadata.on_click_url.spec(), logo.metadata.alt_text,
+      logo.metadata.animated_url.spec(), logo.metadata.mime_type,
+      logo.metadata.fingerprint, time_to_live);
+}
+
+template <typename Arg, typename Matcher>
+bool Match(const Arg& arg,
+           const Matcher& matcher,
+           ::testing::MatchResultListener* result_listener) {
+  return ::testing::Matcher<Arg>(matcher).MatchAndExplain(arg, result_listener);
+}
+
+MATCHER_P(DecodesTo, decoded_logo, "") {
+  return Match(DecodeLogo(arg), Eq(decoded_logo), result_listener);
+}
+
+class MockLogoCache : public LogoCache {
+ public:
+  MockLogoCache() : LogoCache(base::FilePath()) {
+    // Delegate actions to the *Internal() methods by default.
+    ON_CALL(*this, UpdateCachedLogoMetadata(_))
+        .WillByDefault(
+            Invoke(this, &MockLogoCache::UpdateCachedLogoMetadataInternal));
+    ON_CALL(*this, GetCachedLogoMetadata())
+        .WillByDefault(
+            Invoke(this, &MockLogoCache::GetCachedLogoMetadataInternal));
+    ON_CALL(*this, SetCachedLogo(_))
+        .WillByDefault(Invoke(this, &MockLogoCache::SetCachedLogoInternal));
+  }
+
+  MOCK_METHOD1(UpdateCachedLogoMetadata, void(const LogoMetadata& metadata));
+  MOCK_METHOD0(GetCachedLogoMetadata, const LogoMetadata*());
+  MOCK_METHOD1(SetCachedLogo, void(const EncodedLogo* logo));
+  // GetCachedLogo() can't be mocked since it returns a scoped_ptr, which is
+  // non-copyable. Instead create a method that's pinged when GetCachedLogo() is
+  // called.
+  MOCK_METHOD0(OnGetCachedLogo, void());
+
+  void EncodeAndSetCachedLogo(const Logo& logo) {
+    EncodedLogo encoded_logo = EncodeLogo(logo);
+    SetCachedLogo(&encoded_logo);
+  }
+
+  void ExpectSetCachedLogo(const Logo* expected_logo) {
+    Mock::VerifyAndClearExpectations(this);
+    if (expected_logo) {
+      EXPECT_CALL(*this, SetCachedLogo(Pointee(DecodesTo(*expected_logo))));
+    } else {
+      EXPECT_CALL(*this, SetCachedLogo(nullptr));
+    }
+  }
+
+  void UpdateCachedLogoMetadataInternal(const LogoMetadata& metadata) {
+    ASSERT_TRUE(logo_.get());
+    ASSERT_TRUE(metadata_.get());
+    EXPECT_EQ(metadata_->fingerprint, metadata.fingerprint);
+    metadata_.reset(new LogoMetadata(metadata));
+    logo_->metadata = metadata;
+  }
+
+  const LogoMetadata* GetCachedLogoMetadataInternal() {
+    return metadata_.get();
+  }
+
+  void SetCachedLogoInternal(const EncodedLogo* logo) {
+    logo_ = logo ? std::make_unique<EncodedLogo>(*logo) : nullptr;
+    metadata_ = logo ? std::make_unique<LogoMetadata>(logo->metadata) : nullptr;
+  }
+
+  std::unique_ptr<EncodedLogo> GetCachedLogo() override {
+    OnGetCachedLogo();
+    return logo_ ? std::make_unique<EncodedLogo>(*logo_) : nullptr;
+  }
+
+ private:
+  std::unique_ptr<LogoMetadata> metadata_;
+  std::unique_ptr<EncodedLogo> logo_;
+};
+
+class FakeImageDecoder : public image_fetcher::ImageDecoder {
+ public:
+  void DecodeImage(
+      const std::string& image_data,
+      const gfx::Size& desired_image_frame_size,
+      const image_fetcher::ImageDecodedCallback& callback) override {
+    gfx::Image image = gfx::Image::CreateFrom1xPNGBytes(
+        reinterpret_cast<const uint8_t*>(image_data.data()), image_data.size());
+    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                  base::Bind(callback, image));
+  }
+};
+
+class LogoServiceImplTest : public ::testing::Test {
+ protected:
+  LogoServiceImplTest()
+      : template_url_service_(nullptr, 0),
+        test_clock_(new base::SimpleTestClock()),
+        logo_cache_(new NiceMock<MockLogoCache>()),
+        fake_url_fetcher_factory_(nullptr) {
+    feature_list_.InitAndEnableFeature(features::kThirdPartyDoodles);
+
+    // Default search engine with logo. All 3P doodle_urls use ddljson API.
+    AddSearchEngine("ex", "Logo Example",
+                    "https://example.com/?q={searchTerms}",
+                    GURL("https://example.com/logo.json"),
+                    /*make_default=*/true);
+
+    test_clock_->SetNow(base::Time::FromJsTime(INT64_C(1388686828000)));
+    logo_service_ = std::make_unique<LogoServiceImpl>(
+        base::FilePath(), &template_url_service_,
+        std::make_unique<FakeImageDecoder>(),
+        new net::TestURLRequestContextGetter(
+            base::ThreadTaskRunnerHandle::Get()),
+        /*use_gray_background=*/false);
+    logo_service_->SetClockForTests(base::WrapUnique(test_clock_));
+    logo_service_->SetLogoCacheForTests(base::WrapUnique(logo_cache_));
+  }
+
+  void TearDown() override {
+    // |logo_service_|'s LogoTracker owns |logo_cache_|, which gets destroyed on
+    // a background sequence after the LogoTracker's destruction. Ensure that
+    // |logo_cache_| is actually destroyed before the test ends to make gmock
+    // happy.
+    logo_service_.reset();
+    task_environment_.RunUntilIdle();
+  }
+
+  // Returns the response that the server would send for the given logo.
+  std::string ServerResponse(const Logo& logo) const;
+
+  // Sets the response to be returned when the LogoTracker fetches the logo.
+  void SetServerResponse(const std::string& response,
+                         net::URLRequestStatus::Status request_status =
+                             net::URLRequestStatus::SUCCESS,
+                         net::HttpStatusCode response_code = net::HTTP_OK);
+
+  // Sets the response to be returned when the LogoTracker fetches the logo and
+  // provides the given fingerprint.
+  void SetServerResponseWhenFingerprint(
+      const std::string& fingerprint,
+      const std::string& response_when_fingerprint,
+      net::URLRequestStatus::Status request_status =
+          net::URLRequestStatus::SUCCESS,
+      net::HttpStatusCode response_code = net::HTTP_OK);
+
+  const GURL& DoodleURL() const;
+
+  // Calls logo_service_->GetLogo() and waits for the asynchronous response(s).
+  void GetLogo(LogoCallbacks callbacks);
+  void GetDecodedLogo(LogoCallback cached, LogoCallback fresh);
+  void GetEncodedLogo(EncodedLogoCallback cached, EncodedLogoCallback fresh);
+
+  void AddSearchEngine(base::StringPiece keyword,
+                       base::StringPiece short_name,
+                       const std::string& url,
+                       GURL doodle_url,
+                       bool make_default);
+
+  base::test::ScopedFeatureList feature_list_;
+  base::test::ScopedTaskEnvironment task_environment_;
+  TemplateURLService template_url_service_;
+  base::SimpleTestClock* test_clock_;
+  NiceMock<MockLogoCache>* logo_cache_;
+  net::FakeURLFetcherFactory fake_url_fetcher_factory_;
+  std::unique_ptr<LogoServiceImpl> logo_service_;
+};
+
+std::string LogoServiceImplTest::ServerResponse(const Logo& logo) const {
+  base::TimeDelta time_to_live;
+  if (!logo.metadata.expiration_time.is_null())
+    time_to_live = logo.metadata.expiration_time - test_clock_->Now();
+  return MakeServerResponse(logo, time_to_live);
+}
+
+void LogoServiceImplTest::SetServerResponse(
+    const std::string& response,
+    net::URLRequestStatus::Status request_status,
+    net::HttpStatusCode response_code) {
+  SetServerResponseWhenFingerprint(std::string(), response, request_status,
+                                   response_code);
+}
+
+void LogoServiceImplTest::SetServerResponseWhenFingerprint(
+    const std::string& fingerprint,
+    const std::string& response_when_fingerprint,
+    net::URLRequestStatus::Status request_status,
+    net::HttpStatusCode response_code) {
+  GURL url_with_fp =
+      GoogleNewAppendQueryparamsToLogoURL(false, DoodleURL(), fingerprint);
+  fake_url_fetcher_factory_.SetFakeResponse(
+      url_with_fp, response_when_fingerprint, response_code, request_status);
+}
+
+const GURL& LogoServiceImplTest::DoodleURL() const {
+  return template_url_service_.GetDefaultSearchProvider()->doodle_url();
+}
+
+void LogoServiceImplTest::GetLogo(LogoCallbacks callbacks) {
+  logo_service_->GetLogo(std::move(callbacks));
+  task_environment_.RunUntilIdle();
+}
+
+void LogoServiceImplTest::GetDecodedLogo(LogoCallback cached,
+                                         LogoCallback fresh) {
+  LogoCallbacks callbacks;
+  callbacks.on_cached_decoded_logo_available = std::move(cached);
+  callbacks.on_fresh_decoded_logo_available = std::move(fresh);
+  GetLogo(std::move(callbacks));
+}
+
+void LogoServiceImplTest::GetEncodedLogo(EncodedLogoCallback cached,
+                                         EncodedLogoCallback fresh) {
+  LogoCallbacks callbacks;
+  callbacks.on_cached_encoded_logo_available = std::move(cached);
+  callbacks.on_fresh_encoded_logo_available = std::move(fresh);
+  GetLogo(std::move(callbacks));
+}
+
+void LogoServiceImplTest::AddSearchEngine(base::StringPiece keyword,
+                                          base::StringPiece short_name,
+                                          const std::string& url,
+                                          GURL doodle_url,
+                                          bool make_default) {
+  TemplateURLData search_url;
+  search_url.SetKeyword(base::ASCIIToUTF16(keyword));
+  search_url.SetShortName(base::ASCIIToUTF16(short_name));
+  search_url.SetURL(url);
+  search_url.doodle_url = doodle_url;
+
+  TemplateURL* template_url =
+      template_url_service_.Add(std::make_unique<TemplateURL>(search_url));
+  if (make_default) {
+    template_url_service_.SetUserSelectedDefaultSearchProvider(template_url);
+  }
+}
+
+// Tests -----------------------------------------------------------------------
+
+TEST_F(LogoServiceImplTest, CTAURLHasComma) {
+  GURL url_with_fp = GoogleLegacyAppendQueryparamsToLogoURL(
+      false, GURL("http://logourl.com/path"), "abc123");
+  EXPECT_EQ("http://logourl.com/path?async=es_dfp:abc123,cta:1",
+            url_with_fp.spec());
+
+  url_with_fp = GoogleLegacyAppendQueryparamsToLogoURL(
+      false, GURL("http://logourl.com/?a=b"), "");
+  EXPECT_EQ("http://logourl.com/?a=b&async=cta:1", url_with_fp.spec());
+}
+
+TEST_F(LogoServiceImplTest, CTAGrayBackgroundHasCommas) {
+  GURL url_with_fp = GoogleLegacyAppendQueryparamsToLogoURL(
+      true, GURL("http://logourl.com/path"), "abc123");
+  EXPECT_EQ(
+      "http://logourl.com/path?async=es_dfp:abc123,cta:1,transp:1,graybg:1",
+      url_with_fp.spec());
+
+  url_with_fp = GoogleLegacyAppendQueryparamsToLogoURL(
+      true, GURL("http://logourl.com/?a=b"), "");
+  EXPECT_EQ("http://logourl.com/?a=b&async=cta:1,transp:1,graybg:1",
+            url_with_fp.spec());
+}
+
+TEST_F(LogoServiceImplTest, DownloadAndCacheLogo) {
+  StrictMock<MockLogoCallback> cached;
+  StrictMock<MockLogoCallback> fresh;
+  Logo logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  SetServerResponse(ServerResponse(logo));
+  logo_cache_->ExpectSetCachedLogo(&logo);
+  EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
+  EXPECT_CALL(fresh, Run(LogoCallbackReason::DETERMINED, Eq(logo)));
+  GetDecodedLogo(cached.Get(), fresh.Get());
+}
+
+TEST_F(LogoServiceImplTest, DownloadAndCacheEncodedLogo) {
+  StrictMock<MockEncodedLogoCallback> cached;
+  StrictMock<MockEncodedLogoCallback> fresh;
+  Logo logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  EncodedLogo encoded_logo = EncodeLogo(logo);
+  SetServerResponse(ServerResponse(logo));
+  logo_cache_->ExpectSetCachedLogo(&logo);
+  EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
+  EXPECT_CALL(fresh, Run(LogoCallbackReason::DETERMINED, Eq(encoded_logo)));
+  GetEncodedLogo(cached.Get(), fresh.Get());
+}
+
+TEST_F(LogoServiceImplTest, ShouldReturnDisabledWhenDSEHasNoLogo) {
+  AddSearchEngine("cr", "Chromium", "https://www.chromium.org/?q={searchTerms}",
+                  GURL(/* logo disabled */), /*make_default=*/true);
+
+  {
+    StrictMock<MockLogoCallback> cached;
+    StrictMock<MockLogoCallback> fresh;
+    EXPECT_CALL(cached, Run(LogoCallbackReason::DISABLED, Eq(base::nullopt)));
+    EXPECT_CALL(fresh, Run(LogoCallbackReason::DISABLED, Eq(base::nullopt)));
+    GetDecodedLogo(cached.Get(), fresh.Get());
+  }
+
+  {
+    StrictMock<MockEncodedLogoCallback> cached;
+    StrictMock<MockEncodedLogoCallback> fresh;
+    EXPECT_CALL(cached, Run(LogoCallbackReason::DISABLED, Eq(base::nullopt)));
+    EXPECT_CALL(fresh, Run(LogoCallbackReason::DISABLED, Eq(base::nullopt)));
+    GetEncodedLogo(cached.Get(), fresh.Get());
+  }
+}
+
+TEST_F(LogoServiceImplTest, EmptyCacheAndFailedDownload) {
+  EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0);
+  EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(0);
+  EXPECT_CALL(*logo_cache_, SetCachedLogo(nullptr)).Times(AnyNumber());
+
+  {
+    StrictMock<MockLogoCallback> cached;
+    StrictMock<MockLogoCallback> fresh;
+    SetServerResponse("server is borked");
+    EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
+    EXPECT_CALL(fresh, Run(LogoCallbackReason::REVALIDATED, Eq(base::nullopt)));
+    GetDecodedLogo(cached.Get(), fresh.Get());
+  }
+
+  {
+    StrictMock<MockLogoCallback> cached;
+    StrictMock<MockLogoCallback> fresh;
+    SetServerResponse("", net::URLRequestStatus::FAILED, net::HTTP_OK);
+    EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
+    EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(base::nullopt)));
+    GetDecodedLogo(cached.Get(), fresh.Get());
+  }
+
+  {
+    StrictMock<MockLogoCallback> cached;
+    StrictMock<MockLogoCallback> fresh;
+    SetServerResponse("", net::URLRequestStatus::SUCCESS,
+                      net::HTTP_BAD_GATEWAY);
+    EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
+    EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(base::nullopt)));
+    GetDecodedLogo(cached.Get(), fresh.Get());
+  }
+}
+
+TEST_F(LogoServiceImplTest, AcceptMinimalLogoResponse) {
+  Logo logo;
+  logo.image = MakeBitmap(1, 2);
+  logo.metadata.source_url = DoodleURL();
+  logo.metadata.can_show_after_expiration = true;
+  logo.metadata.mime_type = "image/png";
+
+  std::string response =
+      ")]}' {\"ddljson\":{\"data_uri\":\"data:image/png;base64," +
+      EncodeBitmapAsPNGBase64(logo.image) + "\"}}";
+
+  SetServerResponse(response);
+
+  StrictMock<MockLogoCallback> cached;
+  StrictMock<MockLogoCallback> fresh;
+  EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
+  EXPECT_CALL(fresh, Run(LogoCallbackReason::DETERMINED, Eq(logo)));
+
+  GetDecodedLogo(cached.Get(), fresh.Get());
+}
+
+TEST_F(LogoServiceImplTest, ReturnCachedLogo) {
+  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  logo_cache_->EncodeAndSetCachedLogo(cached_logo);
+  SetServerResponseWhenFingerprint(cached_logo.metadata.fingerprint, "",
+                                   net::URLRequestStatus::FAILED, net::HTTP_OK);
+
+  EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0);
+  EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(0);
+  EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1));
+
+  StrictMock<MockLogoCallback> cached;
+  StrictMock<MockLogoCallback> fresh;
+  EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
+  EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(base::nullopt)));
+
+  GetDecodedLogo(cached.Get(), fresh.Get());
+}
+
+TEST_F(LogoServiceImplTest, ValidateCachedLogo) {
+  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  logo_cache_->EncodeAndSetCachedLogo(cached_logo);
+
+  // During revalidation, the image data and mime_type are absent.
+  Logo fresh_logo = cached_logo;
+  fresh_logo.image.reset();
+  fresh_logo.metadata.mime_type.clear();
+  fresh_logo.metadata.expiration_time =
+      test_clock_->Now() + base::TimeDelta::FromDays(8);
+  SetServerResponseWhenFingerprint(fresh_logo.metadata.fingerprint,
+                                   ServerResponse(fresh_logo));
+
+  {
+    EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(1);
+    EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(0);
+    EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1));
+
+    StrictMock<MockLogoCallback> cached;
+    StrictMock<MockLogoCallback> fresh;
+    EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
+    EXPECT_CALL(fresh, Run(LogoCallbackReason::REVALIDATED, Eq(base::nullopt)));
+    GetDecodedLogo(cached.Get(), fresh.Get());
+  }
+
+  ASSERT_TRUE(logo_cache_->GetCachedLogoMetadata());
+  EXPECT_EQ(fresh_logo.metadata.expiration_time,
+            logo_cache_->GetCachedLogoMetadata()->expiration_time);
+
+  {
+    // Ensure that cached logo is still returned correctly on subsequent
+    // requests. In particular, the metadata should stay valid.
+    // http://crbug.com/480090
+    EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(1);
+    EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(0);
+    EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1));
+
+    StrictMock<MockLogoCallback> cached;
+    StrictMock<MockLogoCallback> fresh;
+    EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
+    EXPECT_CALL(fresh, Run(LogoCallbackReason::REVALIDATED, Eq(base::nullopt)));
+    GetDecodedLogo(cached.Get(), fresh.Get());
+  }
+}
+
+TEST_F(LogoServiceImplTest, UpdateCachedLogoMetadata) {
+  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  logo_cache_->EncodeAndSetCachedLogo(cached_logo);
+
+  Logo fresh_logo = cached_logo;
+  fresh_logo.image.reset();
+  fresh_logo.metadata.mime_type.clear();
+  fresh_logo.metadata.on_click_url = GURL("http://new.onclick.url");
+  fresh_logo.metadata.alt_text = "new alt text";
+  fresh_logo.metadata.animated_url = GURL("http://new.animated.url");
+  fresh_logo.metadata.expiration_time =
+      test_clock_->Now() + base::TimeDelta::FromDays(8);
+  SetServerResponseWhenFingerprint(fresh_logo.metadata.fingerprint,
+                                   ServerResponse(fresh_logo));
+
+  // On the first request, the cached logo should be used.
+  {
+    StrictMock<MockLogoCallback> cached;
+    StrictMock<MockLogoCallback> fresh;
+    EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
+    EXPECT_CALL(fresh, Run(LogoCallbackReason::REVALIDATED, Eq(base::nullopt)));
+    GetDecodedLogo(cached.Get(), fresh.Get());
+  }
+
+  // Subsequently, the cached image should be returned along with the updated
+  // metadata.
+  {
+    Logo expected_logo = fresh_logo;
+    expected_logo.image = cached_logo.image;
+    expected_logo.metadata.mime_type = cached_logo.metadata.mime_type;
+    StrictMock<MockLogoCallback> cached;
+    StrictMock<MockLogoCallback> fresh;
+    EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(expected_logo)));
+    EXPECT_CALL(fresh, Run(LogoCallbackReason::REVALIDATED, Eq(base::nullopt)));
+    GetDecodedLogo(cached.Get(), fresh.Get());
+  }
+}
+
+TEST_F(LogoServiceImplTest, UpdateCachedLogo) {
+  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  logo_cache_->EncodeAndSetCachedLogo(cached_logo);
+
+  Logo fresh_logo = GetSampleLogo2(DoodleURL(), test_clock_->Now());
+  SetServerResponseWhenFingerprint(cached_logo.metadata.fingerprint,
+                                   ServerResponse(fresh_logo));
+
+  logo_cache_->ExpectSetCachedLogo(&fresh_logo);
+  EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0);
+  EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1));
+
+  StrictMock<MockLogoCallback> cached;
+  StrictMock<MockLogoCallback> fresh;
+  EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
+  EXPECT_CALL(fresh, Run(LogoCallbackReason::DETERMINED, Eq(fresh_logo)));
+  GetDecodedLogo(cached.Get(), fresh.Get());
+}
+
+TEST_F(LogoServiceImplTest, InvalidateCachedLogo) {
+  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  logo_cache_->EncodeAndSetCachedLogo(cached_logo);
+
+  // This response means there's no current logo.
+  SetServerResponseWhenFingerprint(cached_logo.metadata.fingerprint,
+                                   ")]}' {\"update\":{}}");
+
+  logo_cache_->ExpectSetCachedLogo(nullptr);
+  EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0);
+  EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1));
+
+  StrictMock<MockLogoCallback> cached;
+  StrictMock<MockLogoCallback> fresh;
+  EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
+  EXPECT_CALL(fresh, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
+
+  GetDecodedLogo(cached.Get(), fresh.Get());
+}
+
+TEST_F(LogoServiceImplTest, DeleteCachedLogoFromOldUrl) {
+  SetServerResponse("", net::URLRequestStatus::FAILED, net::HTTP_OK);
+  Logo cached_logo =
+      GetSampleLogo(GURL("http://oldsearchprovider.com"), test_clock_->Now());
+  logo_cache_->EncodeAndSetCachedLogo(cached_logo);
+
+  EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0);
+  EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(0);
+  EXPECT_CALL(*logo_cache_, SetCachedLogo(nullptr)).Times(AnyNumber());
+  EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1));
+
+  StrictMock<MockLogoCallback> cached;
+  StrictMock<MockLogoCallback> fresh;
+  EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
+  EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(base::nullopt)));
+
+  GetDecodedLogo(cached.Get(), fresh.Get());
+}
+
+TEST_F(LogoServiceImplTest, LogoWithTTLCannotBeShownAfterExpiration) {
+  Logo logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  base::TimeDelta time_to_live = base::TimeDelta::FromDays(3);
+  logo.metadata.expiration_time = test_clock_->Now() + time_to_live;
+  SetServerResponse(ServerResponse(logo));
+  LogoCallbacks callbacks;
+  callbacks.on_fresh_decoded_logo_available = base::Bind(
+      [](LogoCallbackReason type, const base::Optional<Logo>& logo) {});
+  GetLogo(std::move(callbacks));
+
+  const LogoMetadata* cached_metadata = logo_cache_->GetCachedLogoMetadata();
+  ASSERT_TRUE(cached_metadata);
+  EXPECT_FALSE(cached_metadata->can_show_after_expiration);
+  EXPECT_EQ(test_clock_->Now() + time_to_live,
+            cached_metadata->expiration_time);
+}
+
+TEST_F(LogoServiceImplTest, LogoWithoutTTLCanBeShownAfterExpiration) {
+  Logo logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  base::TimeDelta time_to_live = base::TimeDelta();
+  SetServerResponse(MakeServerResponse(logo, time_to_live));
+  LogoCallbacks callbacks;
+  callbacks.on_fresh_decoded_logo_available = base::Bind(
+      [](LogoCallbackReason type, const base::Optional<Logo>& logo) {});
+  GetLogo(std::move(callbacks));
+
+  const LogoMetadata* cached_metadata = logo_cache_->GetCachedLogoMetadata();
+  ASSERT_TRUE(cached_metadata);
+  EXPECT_TRUE(cached_metadata->can_show_after_expiration);
+  EXPECT_EQ(test_clock_->Now() + base::TimeDelta::FromDays(30),
+            cached_metadata->expiration_time);
+}
+
+TEST_F(LogoServiceImplTest, UseSoftExpiredCachedLogo) {
+  SetServerResponse("", net::URLRequestStatus::FAILED, net::HTTP_OK);
+  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  cached_logo.metadata.expiration_time =
+      test_clock_->Now() - base::TimeDelta::FromSeconds(1);
+  cached_logo.metadata.can_show_after_expiration = true;
+  logo_cache_->EncodeAndSetCachedLogo(cached_logo);
+
+  EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0);
+  EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(0);
+  EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1));
+
+  StrictMock<MockLogoCallback> cached;
+  StrictMock<MockLogoCallback> fresh;
+  EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
+  EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(base::nullopt)));
+
+  GetDecodedLogo(cached.Get(), fresh.Get());
+}
+
+TEST_F(LogoServiceImplTest, RerequestSoftExpiredCachedLogo) {
+  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  cached_logo.metadata.expiration_time =
+      test_clock_->Now() - base::TimeDelta::FromDays(5);
+  cached_logo.metadata.can_show_after_expiration = true;
+  logo_cache_->EncodeAndSetCachedLogo(cached_logo);
+
+  Logo fresh_logo = GetSampleLogo2(DoodleURL(), test_clock_->Now());
+  SetServerResponse(ServerResponse(fresh_logo));
+
+  logo_cache_->ExpectSetCachedLogo(&fresh_logo);
+  EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0);
+  EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1));
+
+  StrictMock<MockLogoCallback> cached;
+  StrictMock<MockLogoCallback> fresh;
+  EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
+  EXPECT_CALL(fresh, Run(LogoCallbackReason::DETERMINED, Eq(fresh_logo)));
+
+  GetDecodedLogo(cached.Get(), fresh.Get());
+}
+
+TEST_F(LogoServiceImplTest, DeleteAncientCachedLogo) {
+  SetServerResponse("", net::URLRequestStatus::FAILED, net::HTTP_OK);
+  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  cached_logo.metadata.expiration_time =
+      test_clock_->Now() - base::TimeDelta::FromDays(200);
+  cached_logo.metadata.can_show_after_expiration = true;
+  logo_cache_->EncodeAndSetCachedLogo(cached_logo);
+
+  EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0);
+  EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(0);
+  EXPECT_CALL(*logo_cache_, SetCachedLogo(nullptr)).Times(AnyNumber());
+  EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1));
+
+  StrictMock<MockLogoCallback> cached;
+  StrictMock<MockLogoCallback> fresh;
+  EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
+  EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(base::nullopt)));
+
+  GetDecodedLogo(cached.Get(), fresh.Get());
+}
+
+TEST_F(LogoServiceImplTest, DeleteExpiredCachedLogo) {
+  SetServerResponse("", net::URLRequestStatus::FAILED, net::HTTP_OK);
+  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  cached_logo.metadata.expiration_time =
+      test_clock_->Now() - base::TimeDelta::FromSeconds(1);
+  cached_logo.metadata.can_show_after_expiration = false;
+  logo_cache_->EncodeAndSetCachedLogo(cached_logo);
+
+  EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0);
+  EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(0);
+  EXPECT_CALL(*logo_cache_, SetCachedLogo(nullptr)).Times(AnyNumber());
+  EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1));
+
+  StrictMock<MockLogoCallback> cached;
+  StrictMock<MockLogoCallback> fresh;
+  EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
+  EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(base::nullopt)));
+
+  GetDecodedLogo(cached.Get(), fresh.Get());
+}
+
+// Tests that deal with multiple listeners.
+
+void EnqueueCallbacks(LogoServiceImpl* logo_service,
+                      std::vector<LogoCallback>* cached_callbacks,
+                      std::vector<LogoCallback>* fresh_callbacks,
+                      size_t start_index) {
+  DCHECK_EQ(cached_callbacks->size(), fresh_callbacks->size());
+  if (start_index >= cached_callbacks->size())
+    return;
+
+  LogoCallbacks callbacks;
+  callbacks.on_cached_decoded_logo_available =
+      std::move((*cached_callbacks)[start_index]);
+  callbacks.on_fresh_decoded_logo_available =
+      std::move((*fresh_callbacks)[start_index]);
+  logo_service->GetLogo(std::move(callbacks));
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::Bind(&EnqueueCallbacks, logo_service, cached_callbacks,
+                            fresh_callbacks, start_index + 1));
+}
+
+#if defined(THREAD_SANITIZER)
+// Flakes on Linux TSan: http://crbug/754599 (data race).
+#define MAYBE_SupportOverlappingLogoRequests \
+  DISABLED_SupportOverlappingLogoRequests
+#else
+#define MAYBE_SupportOverlappingLogoRequests SupportOverlappingLogoRequests
+#endif
+TEST_F(LogoServiceImplTest, MAYBE_SupportOverlappingLogoRequests) {
+  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  logo_cache_->EncodeAndSetCachedLogo(cached_logo);
+  ON_CALL(*logo_cache_, SetCachedLogo(_)).WillByDefault(Return());
+
+  Logo fresh_logo = GetSampleLogo2(DoodleURL(), test_clock_->Now());
+  std::string response = ServerResponse(fresh_logo);
+  SetServerResponse(response);
+  SetServerResponseWhenFingerprint(cached_logo.metadata.fingerprint, response);
+
+  const int kNumListeners = 10;
+  std::vector<std::unique_ptr<MockLogoCallback>> mocks;
+  std::vector<LogoCallback> cached_callbacks;
+  std::vector<LogoCallback> fresh_callbacks;
+  for (int i = 0; i < kNumListeners; ++i) {
+    mocks.push_back(std::make_unique<MockLogoCallback>());
+    EXPECT_CALL(*mocks.back(),
+                Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
+    cached_callbacks.push_back(mocks.back()->Get());
+
+    mocks.push_back(std::make_unique<MockLogoCallback>());
+    EXPECT_CALL(*mocks.back(),
+                Run(LogoCallbackReason::DETERMINED, Eq(fresh_logo)));
+    fresh_callbacks.push_back(mocks.back()->Get());
+  }
+  EnqueueCallbacks(logo_service_.get(), &cached_callbacks, &fresh_callbacks, 0);
+
+  EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(AtMost(3));
+  EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(3));
+
+  task_environment_.RunUntilIdle();
+}
+
+TEST_F(LogoServiceImplTest, DeleteCallbacksWhenLogoURLChanged) {
+  StrictMock<MockLogoCallback> first_cached;
+  StrictMock<MockLogoCallback> first_fresh;
+  EXPECT_CALL(first_cached,
+              Run(LogoCallbackReason::CANCELED, Eq(base::nullopt)));
+  EXPECT_CALL(first_fresh,
+              Run(LogoCallbackReason::CANCELED, Eq(base::nullopt)));
+  LogoCallbacks first_callbacks;
+  first_callbacks.on_cached_decoded_logo_available = first_cached.Get();
+  first_callbacks.on_fresh_decoded_logo_available = first_fresh.Get();
+  logo_service_->GetLogo(std::move(first_callbacks));
+
+  // Change default search engine; new DSE has a doodle URL.
+  AddSearchEngine("cr", "Chromium", "https://www.chromium.org/?q={searchTerms}",
+                  GURL("https://chromium.org/logo.json"),
+                  /*make_default=*/true);
+
+  Logo logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  SetServerResponse(ServerResponse(logo));
+
+  StrictMock<MockLogoCallback> second_cached;
+  StrictMock<MockLogoCallback> second_fresh;
+  EXPECT_CALL(second_cached,
+              Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
+  EXPECT_CALL(second_fresh, Run(LogoCallbackReason::DETERMINED, Eq(logo)));
+  LogoCallbacks second_callbacks;
+  second_callbacks.on_cached_decoded_logo_available = second_cached.Get();
+  second_callbacks.on_fresh_decoded_logo_available = second_fresh.Get();
+  logo_service_->GetLogo(std::move(second_callbacks));
+
+  task_environment_.RunUntilIdle();
+}
+
+}  // namespace
+
+bool operator==(const Logo& a, const Logo& b) {
+  return (a.image.width() == b.image.width()) &&
+         (a.image.height() == b.image.height()) &&
+         (a.metadata.on_click_url == b.metadata.on_click_url) &&
+         (a.metadata.source_url == b.metadata.source_url) &&
+         (a.metadata.animated_url == b.metadata.animated_url) &&
+         (a.metadata.alt_text == b.metadata.alt_text) &&
+         (a.metadata.mime_type == b.metadata.mime_type) &&
+         (a.metadata.fingerprint == b.metadata.fingerprint) &&
+         (a.metadata.can_show_after_expiration ==
+          b.metadata.can_show_after_expiration);
+}
+
+bool operator==(const EncodedLogo& a, const EncodedLogo& b) {
+  return DecodeLogo(a) == DecodeLogo(b);
+}
+
+void PrintTo(const Logo& logo, std::ostream* ostr) {
+  *ostr << "image size: " << logo.image.width() << "x" << logo.image.height()
+        << "\non_click_url: " << logo.metadata.on_click_url
+        << "\nsource_url: " << logo.metadata.source_url
+        << "\nanimated_url: " << logo.metadata.animated_url
+        << "\nalt_text: " << logo.metadata.alt_text
+        << "\nmime_type: " << logo.metadata.mime_type
+        << "\nfingerprint: " << logo.metadata.fingerprint
+        << "\ncan_show_after_expiration: "
+        << logo.metadata.can_show_after_expiration;
+}
+
+void PrintTo(const EncodedLogo& logo, std::ostream* ostr) {
+  PrintTo(DecodeLogo(logo), ostr);
+}
+
+}  // namespace search_provider_logos
diff --git a/components/search_provider_logos/logo_service_unittest.cc b/components/search_provider_logos/logo_service_unittest.cc
deleted file mode 100644
index 784e3f14..0000000
--- a/components/search_provider_logos/logo_service_unittest.cc
+++ /dev/null
@@ -1,945 +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 "components/search_provider_logos/logo_service.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/base64.h"
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/files/file_path.h"
-#include "base/json/json_writer.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/stringprintf.h"
-#include "base/test/mock_callback.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/test/simple_test_clock.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "base/values.h"
-#include "build/build_config.h"
-#include "components/image_fetcher/core/image_decoder.h"
-#include "components/search_engines/template_url.h"
-#include "components/search_engines/template_url_data.h"
-#include "components/search_engines/template_url_service.h"
-#include "components/search_provider_logos/features.h"
-#include "components/search_provider_logos/fixed_logo_api.h"
-#include "components/search_provider_logos/google_logo_api.h"
-#include "components/search_provider_logos/logo_cache.h"
-#include "components/search_provider_logos/logo_tracker.h"
-#include "net/base/url_util.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_status_code.h"
-#include "net/url_request/test_url_fetcher_factory.h"
-#include "net/url_request/url_request_status.h"
-#include "net/url_request/url_request_test_util.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/image/image.h"
-
-using ::testing::_;
-using ::testing::AnyNumber;
-using ::testing::AtMost;
-using ::testing::Eq;
-using ::testing::InSequence;
-using ::testing::Invoke;
-using ::testing::Mock;
-using ::testing::Ne;
-using ::testing::NiceMock;
-using ::testing::Not;
-using ::testing::NotNull;
-using ::testing::Pointee;
-using ::testing::StrictMock;
-using ::testing::Return;
-
-namespace search_provider_logos {
-
-namespace {
-
-using MockLogoCallback = base::MockCallback<LogoCallback>;
-using MockEncodedLogoCallback = base::MockCallback<EncodedLogoCallback>;
-
-scoped_refptr<base::RefCountedString> EncodeBitmapAsPNG(
-    const SkBitmap& bitmap) {
-  scoped_refptr<base::RefCountedMemory> png_bytes =
-      gfx::Image::CreateFrom1xBitmap(bitmap).As1xPNGBytes();
-  scoped_refptr<base::RefCountedString> str = new base::RefCountedString();
-  str->data().assign(png_bytes->front_as<char>(), png_bytes->size());
-  return str;
-}
-
-std::string EncodeBitmapAsPNGBase64(const SkBitmap& bitmap) {
-  scoped_refptr<base::RefCountedString> png_bytes = EncodeBitmapAsPNG(bitmap);
-  std::string encoded_image_base64;
-  base::Base64Encode(png_bytes->data(), &encoded_image_base64);
-  return encoded_image_base64;
-}
-
-SkBitmap MakeBitmap(int width, int height) {
-  SkBitmap bitmap;
-  bitmap.allocN32Pixels(width, height);
-  bitmap.eraseColor(SK_ColorBLUE);
-  return bitmap;
-}
-
-EncodedLogo EncodeLogo(const Logo& logo) {
-  EncodedLogo encoded_logo;
-  encoded_logo.encoded_image = EncodeBitmapAsPNG(logo.image);
-  encoded_logo.metadata = logo.metadata;
-  return encoded_logo;
-}
-
-Logo DecodeLogo(const EncodedLogo& encoded_logo) {
-  Logo logo;
-  logo.image =
-      gfx::Image::CreateFrom1xPNGBytes(encoded_logo.encoded_image->front(),
-                                       encoded_logo.encoded_image->size())
-          .AsBitmap();
-  logo.metadata = encoded_logo.metadata;
-  return logo;
-}
-
-Logo GetSampleLogo(const GURL& logo_url, base::Time response_time) {
-  Logo logo;
-  logo.image = MakeBitmap(2, 5);
-  logo.metadata.can_show_after_expiration = false;
-  logo.metadata.expiration_time =
-      response_time + base::TimeDelta::FromHours(19);
-  logo.metadata.fingerprint = "8bc33a80";
-  logo.metadata.source_url = logo_url;
-  logo.metadata.on_click_url = GURL("http://www.google.com/search?q=potato");
-  logo.metadata.alt_text = "A logo about potatoes";
-  logo.metadata.animated_url = GURL("http://www.google.com/logos/doodle.png");
-  logo.metadata.mime_type = "image/png";
-  return logo;
-}
-
-Logo GetSampleLogo2(const GURL& logo_url, base::Time response_time) {
-  Logo logo;
-  logo.image = MakeBitmap(4, 3);
-  logo.metadata.can_show_after_expiration = true;
-  logo.metadata.expiration_time = base::Time();
-  logo.metadata.fingerprint = "71082741021409127";
-  logo.metadata.source_url = logo_url;
-  logo.metadata.on_click_url = GURL("http://example.com/page25");
-  logo.metadata.alt_text = "The logo for example.com";
-  logo.metadata.mime_type = "image/jpeg";
-  return logo;
-}
-
-std::string MakeServerResponse(const SkBitmap& image,
-                               const std::string& on_click_url,
-                               const std::string& alt_text,
-                               const std::string& animated_url,
-                               const std::string& mime_type,
-                               const std::string& fingerprint,
-                               base::TimeDelta time_to_live) {
-  base::DictionaryValue dict;
-
-  std::string data_uri = "data:";
-  data_uri += mime_type;
-  data_uri += ";base64,";
-  data_uri += EncodeBitmapAsPNGBase64(image);
-
-  dict.SetString("ddljson.target_url", on_click_url);
-  dict.SetString("ddljson.alt_text", alt_text);
-  if (animated_url.empty()) {
-    dict.SetString("ddljson.doodle_type", "SIMPLE");
-    if (!image.isNull())
-      dict.SetString("ddljson.data_uri", data_uri);
-  } else {
-    dict.SetString("ddljson.doodle_type", "ANIMATED");
-    dict.SetBoolean("ddljson.large_image.is_animated_gif", true);
-    dict.SetString("ddljson.large_image.url", animated_url);
-    if (!image.isNull())
-      dict.SetString("ddljson.cta_data_uri", data_uri);
-  }
-  dict.SetString("ddljson.fingerprint", fingerprint);
-  if (time_to_live != base::TimeDelta())
-    dict.SetInteger("ddljson.time_to_live_ms",
-                    static_cast<int>(time_to_live.InMilliseconds()));
-
-  std::string output;
-  base::JSONWriter::Write(dict, &output);
-  return output;
-}
-
-std::string MakeServerResponse(const Logo& logo, base::TimeDelta time_to_live) {
-  return MakeServerResponse(
-      logo.image, logo.metadata.on_click_url.spec(), logo.metadata.alt_text,
-      logo.metadata.animated_url.spec(), logo.metadata.mime_type,
-      logo.metadata.fingerprint, time_to_live);
-}
-
-template <typename Arg, typename Matcher>
-bool Match(const Arg& arg,
-           const Matcher& matcher,
-           ::testing::MatchResultListener* result_listener) {
-  return ::testing::Matcher<Arg>(matcher).MatchAndExplain(arg, result_listener);
-}
-
-MATCHER_P(DecodesTo, decoded_logo, "") {
-  return Match(DecodeLogo(arg), Eq(decoded_logo), result_listener);
-}
-
-class MockLogoCache : public LogoCache {
- public:
-  MockLogoCache() : LogoCache(base::FilePath()) {
-    // Delegate actions to the *Internal() methods by default.
-    ON_CALL(*this, UpdateCachedLogoMetadata(_))
-        .WillByDefault(
-            Invoke(this, &MockLogoCache::UpdateCachedLogoMetadataInternal));
-    ON_CALL(*this, GetCachedLogoMetadata())
-        .WillByDefault(
-            Invoke(this, &MockLogoCache::GetCachedLogoMetadataInternal));
-    ON_CALL(*this, SetCachedLogo(_))
-        .WillByDefault(Invoke(this, &MockLogoCache::SetCachedLogoInternal));
-  }
-
-  MOCK_METHOD1(UpdateCachedLogoMetadata, void(const LogoMetadata& metadata));
-  MOCK_METHOD0(GetCachedLogoMetadata, const LogoMetadata*());
-  MOCK_METHOD1(SetCachedLogo, void(const EncodedLogo* logo));
-  // GetCachedLogo() can't be mocked since it returns a scoped_ptr, which is
-  // non-copyable. Instead create a method that's pinged when GetCachedLogo() is
-  // called.
-  MOCK_METHOD0(OnGetCachedLogo, void());
-
-  void EncodeAndSetCachedLogo(const Logo& logo) {
-    EncodedLogo encoded_logo = EncodeLogo(logo);
-    SetCachedLogo(&encoded_logo);
-  }
-
-  void ExpectSetCachedLogo(const Logo* expected_logo) {
-    Mock::VerifyAndClearExpectations(this);
-    if (expected_logo) {
-      EXPECT_CALL(*this, SetCachedLogo(Pointee(DecodesTo(*expected_logo))));
-    } else {
-      EXPECT_CALL(*this, SetCachedLogo(nullptr));
-    }
-  }
-
-  void UpdateCachedLogoMetadataInternal(const LogoMetadata& metadata) {
-    ASSERT_TRUE(logo_.get());
-    ASSERT_TRUE(metadata_.get());
-    EXPECT_EQ(metadata_->fingerprint, metadata.fingerprint);
-    metadata_.reset(new LogoMetadata(metadata));
-    logo_->metadata = metadata;
-  }
-
-  const LogoMetadata* GetCachedLogoMetadataInternal() {
-    return metadata_.get();
-  }
-
-  void SetCachedLogoInternal(const EncodedLogo* logo) {
-    logo_ = logo ? std::make_unique<EncodedLogo>(*logo) : nullptr;
-    metadata_ = logo ? std::make_unique<LogoMetadata>(logo->metadata) : nullptr;
-  }
-
-  std::unique_ptr<EncodedLogo> GetCachedLogo() override {
-    OnGetCachedLogo();
-    return logo_ ? std::make_unique<EncodedLogo>(*logo_) : nullptr;
-  }
-
- private:
-  std::unique_ptr<LogoMetadata> metadata_;
-  std::unique_ptr<EncodedLogo> logo_;
-};
-
-class FakeImageDecoder : public image_fetcher::ImageDecoder {
- public:
-  void DecodeImage(
-      const std::string& image_data,
-      const gfx::Size& desired_image_frame_size,
-      const image_fetcher::ImageDecodedCallback& callback) override {
-    gfx::Image image = gfx::Image::CreateFrom1xPNGBytes(
-        reinterpret_cast<const uint8_t*>(image_data.data()), image_data.size());
-    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
-                                                  base::Bind(callback, image));
-  }
-};
-
-class LogoServiceTest : public ::testing::Test {
- protected:
-  LogoServiceTest()
-      : template_url_service_(nullptr, 0),
-        test_clock_(new base::SimpleTestClock()),
-        logo_cache_(new NiceMock<MockLogoCache>()),
-        fake_url_fetcher_factory_(nullptr) {
-    feature_list_.InitAndEnableFeature(features::kThirdPartyDoodles);
-
-    // Default search engine with logo. All 3P doodle_urls use ddljson API.
-    AddSearchEngine("ex", "Logo Example",
-                    "https://example.com/?q={searchTerms}",
-                    GURL("https://example.com/logo.json"),
-                    /*make_default=*/true);
-
-    test_clock_->SetNow(base::Time::FromJsTime(INT64_C(1388686828000)));
-    logo_service_ =
-        std::make_unique<LogoService>(base::FilePath(), &template_url_service_,
-                                      std::make_unique<FakeImageDecoder>(),
-                                      new net::TestURLRequestContextGetter(
-                                          base::ThreadTaskRunnerHandle::Get()),
-                                      /*use_gray_background=*/false);
-    logo_service_->SetClockForTests(base::WrapUnique(test_clock_));
-    logo_service_->SetLogoCacheForTests(base::WrapUnique(logo_cache_));
-  }
-
-  void TearDown() override {
-    // |logo_service_|'s LogoTracker owns |logo_cache_|, which gets destroyed on
-    // a background sequence after the LogoTracker's destruction. Ensure that
-    // |logo_cache_| is actually destroyed before the test ends to make gmock
-    // happy.
-    logo_service_.reset();
-    task_environment_.RunUntilIdle();
-  }
-
-  // Returns the response that the server would send for the given logo.
-  std::string ServerResponse(const Logo& logo) const;
-
-  // Sets the response to be returned when the LogoTracker fetches the logo.
-  void SetServerResponse(const std::string& response,
-                         net::URLRequestStatus::Status request_status =
-                             net::URLRequestStatus::SUCCESS,
-                         net::HttpStatusCode response_code = net::HTTP_OK);
-
-  // Sets the response to be returned when the LogoTracker fetches the logo and
-  // provides the given fingerprint.
-  void SetServerResponseWhenFingerprint(
-      const std::string& fingerprint,
-      const std::string& response_when_fingerprint,
-      net::URLRequestStatus::Status request_status =
-          net::URLRequestStatus::SUCCESS,
-      net::HttpStatusCode response_code = net::HTTP_OK);
-
-  const GURL& DoodleURL() const;
-
-  // Calls logo_service_->GetLogo() and waits for the asynchronous response(s).
-  void GetLogo(LogoCallbacks callbacks);
-  void GetDecodedLogo(LogoCallback cached, LogoCallback fresh);
-  void GetEncodedLogo(EncodedLogoCallback cached, EncodedLogoCallback fresh);
-
-  void AddSearchEngine(base::StringPiece keyword,
-                       base::StringPiece short_name,
-                       const std::string& url,
-                       GURL doodle_url,
-                       bool make_default);
-
-  base::test::ScopedFeatureList feature_list_;
-  base::test::ScopedTaskEnvironment task_environment_;
-  TemplateURLService template_url_service_;
-  base::SimpleTestClock* test_clock_;
-  NiceMock<MockLogoCache>* logo_cache_;
-  net::FakeURLFetcherFactory fake_url_fetcher_factory_;
-  std::unique_ptr<LogoService> logo_service_;
-};
-
-std::string LogoServiceTest::ServerResponse(const Logo& logo) const {
-  base::TimeDelta time_to_live;
-  if (!logo.metadata.expiration_time.is_null())
-    time_to_live = logo.metadata.expiration_time - test_clock_->Now();
-  return MakeServerResponse(logo, time_to_live);
-}
-
-void LogoServiceTest::SetServerResponse(
-    const std::string& response,
-    net::URLRequestStatus::Status request_status,
-    net::HttpStatusCode response_code) {
-  SetServerResponseWhenFingerprint(std::string(), response, request_status,
-                                   response_code);
-}
-
-void LogoServiceTest::SetServerResponseWhenFingerprint(
-    const std::string& fingerprint,
-    const std::string& response_when_fingerprint,
-    net::URLRequestStatus::Status request_status,
-    net::HttpStatusCode response_code) {
-  GURL url_with_fp =
-      GoogleNewAppendQueryparamsToLogoURL(false, DoodleURL(), fingerprint);
-  fake_url_fetcher_factory_.SetFakeResponse(
-      url_with_fp, response_when_fingerprint, response_code, request_status);
-}
-
-const GURL& LogoServiceTest::DoodleURL() const {
-  return template_url_service_.GetDefaultSearchProvider()->doodle_url();
-}
-
-void LogoServiceTest::GetLogo(LogoCallbacks callbacks) {
-  logo_service_->GetLogo(std::move(callbacks));
-  task_environment_.RunUntilIdle();
-}
-
-void LogoServiceTest::GetDecodedLogo(LogoCallback cached, LogoCallback fresh) {
-  LogoCallbacks callbacks;
-  callbacks.on_cached_decoded_logo_available = std::move(cached);
-  callbacks.on_fresh_decoded_logo_available = std::move(fresh);
-  GetLogo(std::move(callbacks));
-}
-
-void LogoServiceTest::GetEncodedLogo(EncodedLogoCallback cached,
-                                     EncodedLogoCallback fresh) {
-  LogoCallbacks callbacks;
-  callbacks.on_cached_encoded_logo_available = std::move(cached);
-  callbacks.on_fresh_encoded_logo_available = std::move(fresh);
-  GetLogo(std::move(callbacks));
-}
-
-void LogoServiceTest::AddSearchEngine(base::StringPiece keyword,
-                                      base::StringPiece short_name,
-                                      const std::string& url,
-                                      GURL doodle_url,
-                                      bool make_default) {
-  TemplateURLData search_url;
-  search_url.SetKeyword(base::ASCIIToUTF16(keyword));
-  search_url.SetShortName(base::ASCIIToUTF16(short_name));
-  search_url.SetURL(url);
-  search_url.doodle_url = doodle_url;
-
-  TemplateURL* template_url =
-      template_url_service_.Add(std::make_unique<TemplateURL>(search_url));
-  if (make_default) {
-    template_url_service_.SetUserSelectedDefaultSearchProvider(template_url);
-  }
-}
-
-// Tests -----------------------------------------------------------------------
-
-TEST_F(LogoServiceTest, CTAURLHasComma) {
-  GURL url_with_fp = GoogleLegacyAppendQueryparamsToLogoURL(
-      false, GURL("http://logourl.com/path"), "abc123");
-  EXPECT_EQ("http://logourl.com/path?async=es_dfp:abc123,cta:1",
-            url_with_fp.spec());
-
-  url_with_fp = GoogleLegacyAppendQueryparamsToLogoURL(
-      false, GURL("http://logourl.com/?a=b"), "");
-  EXPECT_EQ("http://logourl.com/?a=b&async=cta:1", url_with_fp.spec());
-}
-
-TEST_F(LogoServiceTest, CTAGrayBackgroundHasCommas) {
-  GURL url_with_fp = GoogleLegacyAppendQueryparamsToLogoURL(
-      true, GURL("http://logourl.com/path"), "abc123");
-  EXPECT_EQ(
-      "http://logourl.com/path?async=es_dfp:abc123,cta:1,transp:1,graybg:1",
-      url_with_fp.spec());
-
-  url_with_fp = GoogleLegacyAppendQueryparamsToLogoURL(
-      true, GURL("http://logourl.com/?a=b"), "");
-  EXPECT_EQ("http://logourl.com/?a=b&async=cta:1,transp:1,graybg:1",
-            url_with_fp.spec());
-}
-
-TEST_F(LogoServiceTest, DownloadAndCacheLogo) {
-  StrictMock<MockLogoCallback> cached;
-  StrictMock<MockLogoCallback> fresh;
-  Logo logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
-  SetServerResponse(ServerResponse(logo));
-  logo_cache_->ExpectSetCachedLogo(&logo);
-  EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
-  EXPECT_CALL(fresh, Run(LogoCallbackReason::DETERMINED, Eq(logo)));
-  GetDecodedLogo(cached.Get(), fresh.Get());
-}
-
-TEST_F(LogoServiceTest, DownloadAndCacheEncodedLogo) {
-  StrictMock<MockEncodedLogoCallback> cached;
-  StrictMock<MockEncodedLogoCallback> fresh;
-  Logo logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
-  EncodedLogo encoded_logo = EncodeLogo(logo);
-  SetServerResponse(ServerResponse(logo));
-  logo_cache_->ExpectSetCachedLogo(&logo);
-  EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
-  EXPECT_CALL(fresh, Run(LogoCallbackReason::DETERMINED, Eq(encoded_logo)));
-  GetEncodedLogo(cached.Get(), fresh.Get());
-}
-
-TEST_F(LogoServiceTest, ShouldReturnDisabledWhenDSEHasNoLogo) {
-  AddSearchEngine("cr", "Chromium", "https://www.chromium.org/?q={searchTerms}",
-                  GURL(/* logo disabled */), /*make_default=*/true);
-
-  {
-    StrictMock<MockLogoCallback> cached;
-    StrictMock<MockLogoCallback> fresh;
-    EXPECT_CALL(cached, Run(LogoCallbackReason::DISABLED, Eq(base::nullopt)));
-    EXPECT_CALL(fresh, Run(LogoCallbackReason::DISABLED, Eq(base::nullopt)));
-    GetDecodedLogo(cached.Get(), fresh.Get());
-  }
-
-  {
-    StrictMock<MockEncodedLogoCallback> cached;
-    StrictMock<MockEncodedLogoCallback> fresh;
-    EXPECT_CALL(cached, Run(LogoCallbackReason::DISABLED, Eq(base::nullopt)));
-    EXPECT_CALL(fresh, Run(LogoCallbackReason::DISABLED, Eq(base::nullopt)));
-    GetEncodedLogo(cached.Get(), fresh.Get());
-  }
-}
-
-TEST_F(LogoServiceTest, EmptyCacheAndFailedDownload) {
-  EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0);
-  EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(0);
-  EXPECT_CALL(*logo_cache_, SetCachedLogo(nullptr)).Times(AnyNumber());
-
-  {
-    StrictMock<MockLogoCallback> cached;
-    StrictMock<MockLogoCallback> fresh;
-    SetServerResponse("server is borked");
-    EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
-    EXPECT_CALL(fresh, Run(LogoCallbackReason::REVALIDATED, Eq(base::nullopt)));
-    GetDecodedLogo(cached.Get(), fresh.Get());
-  }
-
-  {
-    StrictMock<MockLogoCallback> cached;
-    StrictMock<MockLogoCallback> fresh;
-    SetServerResponse("", net::URLRequestStatus::FAILED, net::HTTP_OK);
-    EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
-    EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(base::nullopt)));
-    GetDecodedLogo(cached.Get(), fresh.Get());
-  }
-
-  {
-    StrictMock<MockLogoCallback> cached;
-    StrictMock<MockLogoCallback> fresh;
-    SetServerResponse("", net::URLRequestStatus::SUCCESS,
-                      net::HTTP_BAD_GATEWAY);
-    EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
-    EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(base::nullopt)));
-    GetDecodedLogo(cached.Get(), fresh.Get());
-  }
-}
-
-TEST_F(LogoServiceTest, AcceptMinimalLogoResponse) {
-  Logo logo;
-  logo.image = MakeBitmap(1, 2);
-  logo.metadata.source_url = DoodleURL();
-  logo.metadata.can_show_after_expiration = true;
-  logo.metadata.mime_type = "image/png";
-
-  std::string response =
-      ")]}' {\"ddljson\":{\"data_uri\":\"data:image/png;base64," +
-      EncodeBitmapAsPNGBase64(logo.image) + "\"}}";
-
-  SetServerResponse(response);
-
-  StrictMock<MockLogoCallback> cached;
-  StrictMock<MockLogoCallback> fresh;
-  EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
-  EXPECT_CALL(fresh, Run(LogoCallbackReason::DETERMINED, Eq(logo)));
-
-  GetDecodedLogo(cached.Get(), fresh.Get());
-}
-
-TEST_F(LogoServiceTest, ReturnCachedLogo) {
-  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
-  logo_cache_->EncodeAndSetCachedLogo(cached_logo);
-  SetServerResponseWhenFingerprint(cached_logo.metadata.fingerprint, "",
-                                   net::URLRequestStatus::FAILED, net::HTTP_OK);
-
-  EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0);
-  EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(0);
-  EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1));
-
-  StrictMock<MockLogoCallback> cached;
-  StrictMock<MockLogoCallback> fresh;
-  EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
-  EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(base::nullopt)));
-
-  GetDecodedLogo(cached.Get(), fresh.Get());
-}
-
-TEST_F(LogoServiceTest, ValidateCachedLogo) {
-  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
-  logo_cache_->EncodeAndSetCachedLogo(cached_logo);
-
-  // During revalidation, the image data and mime_type are absent.
-  Logo fresh_logo = cached_logo;
-  fresh_logo.image.reset();
-  fresh_logo.metadata.mime_type.clear();
-  fresh_logo.metadata.expiration_time =
-      test_clock_->Now() + base::TimeDelta::FromDays(8);
-  SetServerResponseWhenFingerprint(fresh_logo.metadata.fingerprint,
-                                   ServerResponse(fresh_logo));
-
-  {
-    EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(1);
-    EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(0);
-    EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1));
-
-    StrictMock<MockLogoCallback> cached;
-    StrictMock<MockLogoCallback> fresh;
-    EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
-    EXPECT_CALL(fresh, Run(LogoCallbackReason::REVALIDATED, Eq(base::nullopt)));
-    GetDecodedLogo(cached.Get(), fresh.Get());
-  }
-
-  ASSERT_TRUE(logo_cache_->GetCachedLogoMetadata());
-  EXPECT_EQ(fresh_logo.metadata.expiration_time,
-            logo_cache_->GetCachedLogoMetadata()->expiration_time);
-
-  {
-    // Ensure that cached logo is still returned correctly on subsequent
-    // requests. In particular, the metadata should stay valid.
-    // http://crbug.com/480090
-    EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(1);
-    EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(0);
-    EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1));
-
-    StrictMock<MockLogoCallback> cached;
-    StrictMock<MockLogoCallback> fresh;
-    EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
-    EXPECT_CALL(fresh, Run(LogoCallbackReason::REVALIDATED, Eq(base::nullopt)));
-    GetDecodedLogo(cached.Get(), fresh.Get());
-  }
-}
-
-TEST_F(LogoServiceTest, UpdateCachedLogoMetadata) {
-  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
-  logo_cache_->EncodeAndSetCachedLogo(cached_logo);
-
-  Logo fresh_logo = cached_logo;
-  fresh_logo.image.reset();
-  fresh_logo.metadata.mime_type.clear();
-  fresh_logo.metadata.on_click_url = GURL("http://new.onclick.url");
-  fresh_logo.metadata.alt_text = "new alt text";
-  fresh_logo.metadata.animated_url = GURL("http://new.animated.url");
-  fresh_logo.metadata.expiration_time =
-      test_clock_->Now() + base::TimeDelta::FromDays(8);
-  SetServerResponseWhenFingerprint(fresh_logo.metadata.fingerprint,
-                                   ServerResponse(fresh_logo));
-
-  // On the first request, the cached logo should be used.
-  {
-    StrictMock<MockLogoCallback> cached;
-    StrictMock<MockLogoCallback> fresh;
-    EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
-    EXPECT_CALL(fresh, Run(LogoCallbackReason::REVALIDATED, Eq(base::nullopt)));
-    GetDecodedLogo(cached.Get(), fresh.Get());
-  }
-
-  // Subsequently, the cached image should be returned along with the updated
-  // metadata.
-  {
-    Logo expected_logo = fresh_logo;
-    expected_logo.image = cached_logo.image;
-    expected_logo.metadata.mime_type = cached_logo.metadata.mime_type;
-    StrictMock<MockLogoCallback> cached;
-    StrictMock<MockLogoCallback> fresh;
-    EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(expected_logo)));
-    EXPECT_CALL(fresh, Run(LogoCallbackReason::REVALIDATED, Eq(base::nullopt)));
-    GetDecodedLogo(cached.Get(), fresh.Get());
-  }
-}
-
-TEST_F(LogoServiceTest, UpdateCachedLogo) {
-  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
-  logo_cache_->EncodeAndSetCachedLogo(cached_logo);
-
-  Logo fresh_logo = GetSampleLogo2(DoodleURL(), test_clock_->Now());
-  SetServerResponseWhenFingerprint(cached_logo.metadata.fingerprint,
-                                   ServerResponse(fresh_logo));
-
-  logo_cache_->ExpectSetCachedLogo(&fresh_logo);
-  EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0);
-  EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1));
-
-  StrictMock<MockLogoCallback> cached;
-  StrictMock<MockLogoCallback> fresh;
-  EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
-  EXPECT_CALL(fresh, Run(LogoCallbackReason::DETERMINED, Eq(fresh_logo)));
-  GetDecodedLogo(cached.Get(), fresh.Get());
-}
-
-TEST_F(LogoServiceTest, InvalidateCachedLogo) {
-  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
-  logo_cache_->EncodeAndSetCachedLogo(cached_logo);
-
-  // This response means there's no current logo.
-  SetServerResponseWhenFingerprint(cached_logo.metadata.fingerprint,
-                                   ")]}' {\"update\":{}}");
-
-  logo_cache_->ExpectSetCachedLogo(nullptr);
-  EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0);
-  EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1));
-
-  StrictMock<MockLogoCallback> cached;
-  StrictMock<MockLogoCallback> fresh;
-  EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
-  EXPECT_CALL(fresh, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
-
-  GetDecodedLogo(cached.Get(), fresh.Get());
-}
-
-TEST_F(LogoServiceTest, DeleteCachedLogoFromOldUrl) {
-  SetServerResponse("", net::URLRequestStatus::FAILED, net::HTTP_OK);
-  Logo cached_logo =
-      GetSampleLogo(GURL("http://oldsearchprovider.com"), test_clock_->Now());
-  logo_cache_->EncodeAndSetCachedLogo(cached_logo);
-
-  EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0);
-  EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(0);
-  EXPECT_CALL(*logo_cache_, SetCachedLogo(nullptr)).Times(AnyNumber());
-  EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1));
-
-  StrictMock<MockLogoCallback> cached;
-  StrictMock<MockLogoCallback> fresh;
-  EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
-  EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(base::nullopt)));
-
-  GetDecodedLogo(cached.Get(), fresh.Get());
-}
-
-TEST_F(LogoServiceTest, LogoWithTTLCannotBeShownAfterExpiration) {
-  Logo logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
-  base::TimeDelta time_to_live = base::TimeDelta::FromDays(3);
-  logo.metadata.expiration_time = test_clock_->Now() + time_to_live;
-  SetServerResponse(ServerResponse(logo));
-  LogoCallbacks callbacks;
-  callbacks.on_fresh_decoded_logo_available = base::Bind(
-      [](LogoCallbackReason type, const base::Optional<Logo>& logo) {});
-  GetLogo(std::move(callbacks));
-
-  const LogoMetadata* cached_metadata = logo_cache_->GetCachedLogoMetadata();
-  ASSERT_TRUE(cached_metadata);
-  EXPECT_FALSE(cached_metadata->can_show_after_expiration);
-  EXPECT_EQ(test_clock_->Now() + time_to_live,
-            cached_metadata->expiration_time);
-}
-
-TEST_F(LogoServiceTest, LogoWithoutTTLCanBeShownAfterExpiration) {
-  Logo logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
-  base::TimeDelta time_to_live = base::TimeDelta();
-  SetServerResponse(MakeServerResponse(logo, time_to_live));
-  LogoCallbacks callbacks;
-  callbacks.on_fresh_decoded_logo_available = base::Bind(
-      [](LogoCallbackReason type, const base::Optional<Logo>& logo) {});
-  GetLogo(std::move(callbacks));
-
-  const LogoMetadata* cached_metadata = logo_cache_->GetCachedLogoMetadata();
-  ASSERT_TRUE(cached_metadata);
-  EXPECT_TRUE(cached_metadata->can_show_after_expiration);
-  EXPECT_EQ(test_clock_->Now() + base::TimeDelta::FromDays(30),
-            cached_metadata->expiration_time);
-}
-
-TEST_F(LogoServiceTest, UseSoftExpiredCachedLogo) {
-  SetServerResponse("", net::URLRequestStatus::FAILED, net::HTTP_OK);
-  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
-  cached_logo.metadata.expiration_time =
-      test_clock_->Now() - base::TimeDelta::FromSeconds(1);
-  cached_logo.metadata.can_show_after_expiration = true;
-  logo_cache_->EncodeAndSetCachedLogo(cached_logo);
-
-  EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0);
-  EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(0);
-  EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1));
-
-  StrictMock<MockLogoCallback> cached;
-  StrictMock<MockLogoCallback> fresh;
-  EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
-  EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(base::nullopt)));
-
-  GetDecodedLogo(cached.Get(), fresh.Get());
-}
-
-TEST_F(LogoServiceTest, RerequestSoftExpiredCachedLogo) {
-  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
-  cached_logo.metadata.expiration_time =
-      test_clock_->Now() - base::TimeDelta::FromDays(5);
-  cached_logo.metadata.can_show_after_expiration = true;
-  logo_cache_->EncodeAndSetCachedLogo(cached_logo);
-
-  Logo fresh_logo = GetSampleLogo2(DoodleURL(), test_clock_->Now());
-  SetServerResponse(ServerResponse(fresh_logo));
-
-  logo_cache_->ExpectSetCachedLogo(&fresh_logo);
-  EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0);
-  EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1));
-
-  StrictMock<MockLogoCallback> cached;
-  StrictMock<MockLogoCallback> fresh;
-  EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
-  EXPECT_CALL(fresh, Run(LogoCallbackReason::DETERMINED, Eq(fresh_logo)));
-
-  GetDecodedLogo(cached.Get(), fresh.Get());
-}
-
-TEST_F(LogoServiceTest, DeleteAncientCachedLogo) {
-  SetServerResponse("", net::URLRequestStatus::FAILED, net::HTTP_OK);
-  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
-  cached_logo.metadata.expiration_time =
-      test_clock_->Now() - base::TimeDelta::FromDays(200);
-  cached_logo.metadata.can_show_after_expiration = true;
-  logo_cache_->EncodeAndSetCachedLogo(cached_logo);
-
-  EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0);
-  EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(0);
-  EXPECT_CALL(*logo_cache_, SetCachedLogo(nullptr)).Times(AnyNumber());
-  EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1));
-
-  StrictMock<MockLogoCallback> cached;
-  StrictMock<MockLogoCallback> fresh;
-  EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
-  EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(base::nullopt)));
-
-  GetDecodedLogo(cached.Get(), fresh.Get());
-}
-
-TEST_F(LogoServiceTest, DeleteExpiredCachedLogo) {
-  SetServerResponse("", net::URLRequestStatus::FAILED, net::HTTP_OK);
-  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
-  cached_logo.metadata.expiration_time =
-      test_clock_->Now() - base::TimeDelta::FromSeconds(1);
-  cached_logo.metadata.can_show_after_expiration = false;
-  logo_cache_->EncodeAndSetCachedLogo(cached_logo);
-
-  EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0);
-  EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(0);
-  EXPECT_CALL(*logo_cache_, SetCachedLogo(nullptr)).Times(AnyNumber());
-  EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1));
-
-  StrictMock<MockLogoCallback> cached;
-  StrictMock<MockLogoCallback> fresh;
-  EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
-  EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(base::nullopt)));
-
-  GetDecodedLogo(cached.Get(), fresh.Get());
-}
-
-// Tests that deal with multiple listeners.
-
-void EnqueueCallbacks(LogoService* logo_service,
-                      std::vector<LogoCallback>* cached_callbacks,
-                      std::vector<LogoCallback>* fresh_callbacks,
-                      size_t start_index) {
-  DCHECK_EQ(cached_callbacks->size(), fresh_callbacks->size());
-  if (start_index >= cached_callbacks->size())
-    return;
-
-  LogoCallbacks callbacks;
-  callbacks.on_cached_decoded_logo_available =
-      std::move((*cached_callbacks)[start_index]);
-  callbacks.on_fresh_decoded_logo_available =
-      std::move((*fresh_callbacks)[start_index]);
-  logo_service->GetLogo(std::move(callbacks));
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(&EnqueueCallbacks, logo_service, cached_callbacks,
-                            fresh_callbacks, start_index + 1));
-}
-
-#if defined(THREAD_SANITIZER)
-// Flakes on Linux TSan: http://crbug/754599 (data race).
-#define MAYBE_SupportOverlappingLogoRequests \
-  DISABLED_SupportOverlappingLogoRequests
-#else
-#define MAYBE_SupportOverlappingLogoRequests SupportOverlappingLogoRequests
-#endif
-TEST_F(LogoServiceTest, MAYBE_SupportOverlappingLogoRequests) {
-  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
-  logo_cache_->EncodeAndSetCachedLogo(cached_logo);
-  ON_CALL(*logo_cache_, SetCachedLogo(_)).WillByDefault(Return());
-
-  Logo fresh_logo = GetSampleLogo2(DoodleURL(), test_clock_->Now());
-  std::string response = ServerResponse(fresh_logo);
-  SetServerResponse(response);
-  SetServerResponseWhenFingerprint(cached_logo.metadata.fingerprint, response);
-
-  const int kNumListeners = 10;
-  std::vector<std::unique_ptr<MockLogoCallback>> mocks;
-  std::vector<LogoCallback> cached_callbacks;
-  std::vector<LogoCallback> fresh_callbacks;
-  for (int i = 0; i < kNumListeners; ++i) {
-    mocks.push_back(std::make_unique<MockLogoCallback>());
-    EXPECT_CALL(*mocks.back(),
-                Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
-    cached_callbacks.push_back(mocks.back()->Get());
-
-    mocks.push_back(std::make_unique<MockLogoCallback>());
-    EXPECT_CALL(*mocks.back(),
-                Run(LogoCallbackReason::DETERMINED, Eq(fresh_logo)));
-    fresh_callbacks.push_back(mocks.back()->Get());
-  }
-  EnqueueCallbacks(logo_service_.get(), &cached_callbacks, &fresh_callbacks, 0);
-
-  EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(AtMost(3));
-  EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(3));
-
-  task_environment_.RunUntilIdle();
-}
-
-TEST_F(LogoServiceTest, DeleteCallbacksWhenLogoURLChanged) {
-  StrictMock<MockLogoCallback> first_cached;
-  StrictMock<MockLogoCallback> first_fresh;
-  EXPECT_CALL(first_cached,
-              Run(LogoCallbackReason::CANCELED, Eq(base::nullopt)));
-  EXPECT_CALL(first_fresh,
-              Run(LogoCallbackReason::CANCELED, Eq(base::nullopt)));
-  LogoCallbacks first_callbacks;
-  first_callbacks.on_cached_decoded_logo_available = first_cached.Get();
-  first_callbacks.on_fresh_decoded_logo_available = first_fresh.Get();
-  logo_service_->GetLogo(std::move(first_callbacks));
-
-  // Change default search engine; new DSE has a doodle URL.
-  AddSearchEngine("cr", "Chromium", "https://www.chromium.org/?q={searchTerms}",
-                  GURL("https://chromium.org/logo.json"),
-                  /*make_default=*/true);
-
-  Logo logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
-  SetServerResponse(ServerResponse(logo));
-
-  StrictMock<MockLogoCallback> second_cached;
-  StrictMock<MockLogoCallback> second_fresh;
-  EXPECT_CALL(second_cached,
-              Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
-  EXPECT_CALL(second_fresh, Run(LogoCallbackReason::DETERMINED, Eq(logo)));
-  LogoCallbacks second_callbacks;
-  second_callbacks.on_cached_decoded_logo_available = second_cached.Get();
-  second_callbacks.on_fresh_decoded_logo_available = second_fresh.Get();
-  logo_service_->GetLogo(std::move(second_callbacks));
-
-  task_environment_.RunUntilIdle();
-}
-
-}  // namespace
-
-bool operator==(const Logo& a, const Logo& b) {
-  return (a.image.width() == b.image.width()) &&
-         (a.image.height() == b.image.height()) &&
-         (a.metadata.on_click_url == b.metadata.on_click_url) &&
-         (a.metadata.source_url == b.metadata.source_url) &&
-         (a.metadata.animated_url == b.metadata.animated_url) &&
-         (a.metadata.alt_text == b.metadata.alt_text) &&
-         (a.metadata.mime_type == b.metadata.mime_type) &&
-         (a.metadata.fingerprint == b.metadata.fingerprint) &&
-         (a.metadata.can_show_after_expiration ==
-          b.metadata.can_show_after_expiration);
-}
-
-bool operator==(const EncodedLogo& a, const EncodedLogo& b) {
-  return DecodeLogo(a) == DecodeLogo(b);
-}
-
-void PrintTo(const Logo& logo, std::ostream* ostr) {
-  *ostr << "image size: " << logo.image.width() << "x" << logo.image.height()
-        << "\non_click_url: " << logo.metadata.on_click_url
-        << "\nsource_url: " << logo.metadata.source_url
-        << "\nanimated_url: " << logo.metadata.animated_url
-        << "\nalt_text: " << logo.metadata.alt_text
-        << "\nmime_type: " << logo.metadata.mime_type
-        << "\nfingerprint: " << logo.metadata.fingerprint
-        << "\ncan_show_after_expiration: "
-        << logo.metadata.can_show_after_expiration;
-}
-
-void PrintTo(const EncodedLogo& logo, std::ostream* ostr) {
-  PrintTo(DecodeLogo(logo), ostr);
-}
-
-}  // namespace search_provider_logos
diff --git a/components/sync/engine_impl/cycle/test_util.cc b/components/sync/engine_impl/cycle/test_util.cc
index c23c7ce..92947fde3 100644
--- a/components/sync/engine_impl/cycle/test_util.cc
+++ b/components/sync/engine_impl/cycle/test_util.cc
@@ -4,8 +4,6 @@
 
 #include "components/sync/engine_impl/cycle/test_util.h"
 
-#include <map>
-
 namespace syncer {
 namespace test_util {
 
@@ -113,16 +111,6 @@
   cycle->delegate()->OnReceivedLongPollIntervalUpdate(new_poll);
 }
 
-void SimulateSessionsCommitDelayUpdateImpl(ModelTypeSet requested_types,
-                                           NudgeTracker* nudge_tracker,
-                                           SyncCycle* cycle,
-                                           const base::TimeDelta& new_delay) {
-  SimulateNormalSuccess(requested_types, nudge_tracker, cycle);
-  std::map<ModelType, base::TimeDelta> delay_map;
-  delay_map[SESSIONS] = new_delay;
-  cycle->delegate()->OnReceivedCustomNudgeDelays(delay_map);
-}
-
 void SimulateGuRetryDelayCommandImpl(SyncCycle* cycle, base::TimeDelta delay) {
   cycle->mutable_status_controller()->set_last_download_updates_result(
       SYNCER_OK);
diff --git a/components/sync/engine_impl/cycle/test_util.h b/components/sync/engine_impl/cycle/test_util.h
index ece6906..77b111d 100644
--- a/components/sync/engine_impl/cycle/test_util.h
+++ b/components/sync/engine_impl/cycle/test_util.h
@@ -66,12 +66,6 @@
                                     SyncCycle* cycle,
                                     const base::TimeDelta& new_poll);
 
-// Works with normal cycles.
-void SimulateSessionsCommitDelayUpdateImpl(ModelTypeSet requested_types,
-                                           NudgeTracker* nudge_tracker,
-                                           SyncCycle* cycle,
-                                           const base::TimeDelta& new_delay);
-
 ACTION_P(SimulateThrottled, throttle) {
   SimulateThrottledImpl(arg0, throttle);
 }
@@ -88,10 +82,6 @@
   SimulatePollIntervalUpdateImpl(arg0, arg1, poll);
 }
 
-ACTION_P(SimulateSessionsCommitDelayUpdate, poll) {
-  SimulateSessionsCommitDelayUpdateImpl(arg0, arg1, arg2, poll);
-}
-
 ACTION_P(SimulateGuRetryDelayCommand, delay) {
   SimulateGuRetryDelayCommandImpl(arg0, delay);
 }
diff --git a/components/user_manager/user_manager_base.cc b/components/user_manager/user_manager_base.cc
index 961e3b7..40cbd3e 100644
--- a/components/user_manager/user_manager_base.cc
+++ b/components/user_manager/user_manager_base.cc
@@ -307,10 +307,9 @@
   if (user_loading_stage_ == STAGE_LOADED) {
     DeleteUser(RemoveRegularOrSupervisedUserFromList(account_id));
   } else if (user_loading_stage_ == STAGE_LOADING) {
-    DCHECK(IsSupervisedAccountId(account_id) ||
-           HasPendingBootstrap(account_id));
-    // Special case, removing partially-constructed supervised user or
-    // boostrapping user during user list loading.
+    DCHECK(IsSupervisedAccountId(account_id));
+    // Special case, removing partially-constructed supervised user during user
+    // list loading.
     ListPrefUpdate users_update(GetLocalState(), kRegularUsers);
     users_update->Remove(base::Value(account_id.GetUserEmail()), nullptr);
     OnUserRemoved(account_id);
@@ -739,10 +738,6 @@
   is_current_user_new_ = is_new;
 }
 
-bool UserManagerBase::HasPendingBootstrap(const AccountId& account_id) const {
-  return false;
-}
-
 void UserManagerBase::SetOwnerId(const AccountId& owner_account_id) {
   owner_account_id_ = owner_account_id;
   CallUpdateLoginState();
diff --git a/components/user_manager/user_manager_base.h b/components/user_manager/user_manager_base.h
index da6898f..686f990 100644
--- a/components/user_manager/user_manager_base.h
+++ b/components/user_manager/user_manager_base.h
@@ -118,9 +118,6 @@
   // not full initialized yet" flag.
   virtual void SetIsCurrentUserNew(bool is_new);
 
-  // TODO(xiyuan): Figure out a better way to expose this info.
-  virtual bool HasPendingBootstrap(const AccountId& account_id) const;
-
   // Helper function that converts users from |users_list| to |users_vector| and
   // |users_set|. Duplicates and users already present in |existing_users| are
   // skipped.
diff --git a/components/viz/client/BUILD.gn b/components/viz/client/BUILD.gn
index 5eff4385..8a7c5d5 100644
--- a/components/viz/client/BUILD.gn
+++ b/components/viz/client/BUILD.gn
@@ -4,17 +4,23 @@
 
 import("//components/viz/viz.gni")
 
-viz_source_set("client") {
+viz_component("client") {
   sources = [
     "client_layer_tree_frame_sink.cc",
     "client_layer_tree_frame_sink.h",
     "client_shared_bitmap_manager.cc",
     "client_shared_bitmap_manager.h",
+    "frame_eviction_manager.cc",
+    "frame_eviction_manager.h",
+    "frame_evictor.cc",
+    "frame_evictor.h",
     "hit_test_data_provider.h",
     "local_surface_id_provider.cc",
     "local_surface_id_provider.h",
   ]
 
+  defines = [ "VIZ_CLIENT_IMPLEMENTATION" ]
+
   public_deps = [
     "//base",
     "//cc",
diff --git a/components/viz/client/client_layer_tree_frame_sink.h b/components/viz/client/client_layer_tree_frame_sink.h
index 44b7d88..83824e36 100644
--- a/components/viz/client/client_layer_tree_frame_sink.h
+++ b/components/viz/client/client_layer_tree_frame_sink.h
@@ -8,6 +8,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "cc/trees/layer_tree_frame_sink.h"
+#include "components/viz/client/viz_client_export.h"
 #include "components/viz/common/frame_sinks/begin_frame_source.h"
 #include "components/viz/common/gpu/context_provider.h"
 #include "components/viz/common/surfaces/local_surface_id_allocator.h"
@@ -21,11 +22,12 @@
 class LocalSurfaceIdProvider;
 class SharedBitmapManager;
 
-class ClientLayerTreeFrameSink : public cc::LayerTreeFrameSink,
-                                 public mojom::CompositorFrameSinkClient,
-                                 public ExternalBeginFrameSourceClient {
+class VIZ_CLIENT_EXPORT ClientLayerTreeFrameSink
+    : public cc::LayerTreeFrameSink,
+      public mojom::CompositorFrameSinkClient,
+      public ExternalBeginFrameSourceClient {
  public:
-  struct InitParams {
+  struct VIZ_CLIENT_EXPORT InitParams {
     InitParams();
     ~InitParams();
 
diff --git a/components/viz/client/client_shared_bitmap_manager.h b/components/viz/client/client_shared_bitmap_manager.h
index 553bb57..4df7ffe 100644
--- a/components/viz/client/client_shared_bitmap_manager.h
+++ b/components/viz/client/client_shared_bitmap_manager.h
@@ -13,6 +13,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/shared_memory.h"
 #include "base/synchronization/lock.h"
+#include "components/viz/client/viz_client_export.h"
 #include "components/viz/common/resources/shared_bitmap_manager.h"
 #include "mojo/public/cpp/bindings/thread_safe_interface_ptr.h"
 #include "services/viz/public/interfaces/compositing/shared_bitmap_allocation_notifier.mojom.h"
@@ -22,7 +23,7 @@
 // A SharedBitmapManager implementation for use outside of the display
 // compositor's process. This implementation supports SharedBitmaps that
 // can be transported over process boundaries to the display compositor.
-class ClientSharedBitmapManager : public SharedBitmapManager {
+class VIZ_CLIENT_EXPORT ClientSharedBitmapManager : public SharedBitmapManager {
  public:
   explicit ClientSharedBitmapManager(
       scoped_refptr<mojom::ThreadSafeSharedBitmapAllocationNotifierPtr>
diff --git a/components/viz/client/frame_eviction_manager.cc b/components/viz/client/frame_eviction_manager.cc
new file mode 100644
index 0000000..f668659
--- /dev/null
+++ b/components/viz/client/frame_eviction_manager.cc
@@ -0,0 +1,168 @@
+// 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/viz/client/frame_eviction_manager.h"
+
+#include <algorithm>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/memory/memory_coordinator_client_registry.h"
+#include "base/memory/memory_coordinator_proxy.h"
+#include "base/memory/memory_pressure_listener.h"
+#include "base/memory/memory_pressure_monitor.h"
+#include "base/memory/shared_memory.h"
+#include "base/sys_info.h"
+#include "build/build_config.h"
+
+namespace viz {
+namespace {
+
+const int kModeratePressurePercentage = 50;
+const int kCriticalPressurePercentage = 10;
+
+}  // namespace
+
+FrameEvictionManager* FrameEvictionManager::GetInstance() {
+  return base::Singleton<FrameEvictionManager>::get();
+}
+
+void FrameEvictionManager::AddFrame(FrameEvictionManagerClient* frame,
+                                    bool locked) {
+  RemoveFrame(frame);
+  if (locked)
+    locked_frames_[frame] = 1;
+  else
+    unlocked_frames_.push_front(frame);
+  CullUnlockedFrames(GetMaxNumberOfSavedFrames());
+}
+
+void FrameEvictionManager::RemoveFrame(FrameEvictionManagerClient* frame) {
+  std::map<FrameEvictionManagerClient*, size_t>::iterator locked_iter =
+      locked_frames_.find(frame);
+  if (locked_iter != locked_frames_.end())
+    locked_frames_.erase(locked_iter);
+  unlocked_frames_.remove(frame);
+}
+
+void FrameEvictionManager::LockFrame(FrameEvictionManagerClient* frame) {
+  std::list<FrameEvictionManagerClient*>::iterator unlocked_iter =
+      std::find(unlocked_frames_.begin(), unlocked_frames_.end(), frame);
+  if (unlocked_iter != unlocked_frames_.end()) {
+    DCHECK(locked_frames_.find(frame) == locked_frames_.end());
+    unlocked_frames_.remove(frame);
+    locked_frames_[frame] = 1;
+  } else {
+    DCHECK(locked_frames_.find(frame) != locked_frames_.end());
+    locked_frames_[frame]++;
+  }
+}
+
+void FrameEvictionManager::UnlockFrame(FrameEvictionManagerClient* frame) {
+  DCHECK(locked_frames_.find(frame) != locked_frames_.end());
+  size_t locked_count = locked_frames_[frame];
+  DCHECK(locked_count);
+  if (locked_count > 1) {
+    locked_frames_[frame]--;
+  } else {
+    RemoveFrame(frame);
+    unlocked_frames_.push_front(frame);
+    CullUnlockedFrames(GetMaxNumberOfSavedFrames());
+  }
+}
+
+size_t FrameEvictionManager::GetMaxNumberOfSavedFrames() const {
+  int percentage = 100;
+  auto* memory_coordinator_proxy = base::MemoryCoordinatorProxy::GetInstance();
+  if (memory_coordinator_proxy) {
+    switch (memory_coordinator_proxy->GetCurrentMemoryState()) {
+      case base::MemoryState::NORMAL:
+        percentage = 100;
+        break;
+      case base::MemoryState::THROTTLED:
+        percentage = kCriticalPressurePercentage;
+        break;
+      case base::MemoryState::SUSPENDED:
+      case base::MemoryState::UNKNOWN:
+        NOTREACHED();
+        break;
+    }
+  } else {
+    base::MemoryPressureMonitor* monitor = base::MemoryPressureMonitor::Get();
+
+    if (!monitor)
+      return max_number_of_saved_frames_;
+
+    // Until we have a global OnMemoryPressureChanged event we need to query the
+    // value from our specific pressure monitor.
+    switch (monitor->GetCurrentPressureLevel()) {
+      case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
+        percentage = 100;
+        break;
+      case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
+        percentage = kModeratePressurePercentage;
+        break;
+      case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
+        percentage = kCriticalPressurePercentage;
+        break;
+    }
+  }
+  size_t frames = (max_number_of_saved_frames_ * percentage) / 100;
+  return std::max(static_cast<size_t>(1), frames);
+}
+
+FrameEvictionManager::FrameEvictionManager()
+    : memory_pressure_listener_(new base::MemoryPressureListener(
+          base::Bind(&FrameEvictionManager::OnMemoryPressure,
+                     base::Unretained(this)))) {
+  base::MemoryCoordinatorClientRegistry::GetInstance()->Register(this);
+  max_number_of_saved_frames_ =
+#if defined(OS_ANDROID)
+      // If the amount of memory on the device is >= 3.5 GB, save up to 5
+      // frames.
+      base::SysInfo::AmountOfPhysicalMemoryMB() < 1024 * 3.5f ? 1 : 5;
+#else
+      std::min(5, 2 + (base::SysInfo::AmountOfPhysicalMemoryMB() / 256));
+#endif
+}
+
+FrameEvictionManager::~FrameEvictionManager() {}
+
+void FrameEvictionManager::CullUnlockedFrames(size_t saved_frame_limit) {
+  while (!unlocked_frames_.empty() &&
+         unlocked_frames_.size() + locked_frames_.size() > saved_frame_limit) {
+    size_t old_size = unlocked_frames_.size();
+    // Should remove self from list.
+    unlocked_frames_.back()->EvictCurrentFrame();
+    DCHECK_EQ(unlocked_frames_.size() + 1, old_size);
+  }
+}
+
+void FrameEvictionManager::OnMemoryPressure(
+    base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
+  switch (memory_pressure_level) {
+    case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
+      PurgeMemory(kModeratePressurePercentage);
+      break;
+    case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
+      PurgeMemory(kCriticalPressurePercentage);
+      break;
+    case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
+      // No need to change anything when there is no pressure.
+      return;
+  }
+}
+
+void FrameEvictionManager::OnPurgeMemory() {
+  PurgeMemory(kCriticalPressurePercentage);
+}
+
+void FrameEvictionManager::PurgeMemory(int percentage) {
+  int saved_frame_limit = max_number_of_saved_frames_;
+  if (saved_frame_limit <= 1)
+    return;
+  CullUnlockedFrames(std::max(1, (saved_frame_limit * percentage) / 100));
+}
+
+}  // namespace viz
diff --git a/components/viz/client/frame_eviction_manager.h b/components/viz/client/frame_eviction_manager.h
new file mode 100644
index 0000000..3504afa
--- /dev/null
+++ b/components/viz/client/frame_eviction_manager.h
@@ -0,0 +1,81 @@
+// 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_VIZ_CLIENT_FRAME_EVICTION_MANAGER_H_
+#define COMPONENTS_VIZ_CLIENT_FRAME_EVICTION_MANAGER_H_
+
+#include <stddef.h>
+
+#include <list>
+#include <map>
+
+#include "base/macros.h"
+#include "base/memory/memory_coordinator_client.h"
+#include "base/memory/memory_pressure_listener.h"
+#include "base/memory/singleton.h"
+#include "components/viz/client/viz_client_export.h"
+
+namespace viz {
+
+class FrameEvictionManagerClient {
+ public:
+  virtual ~FrameEvictionManagerClient() {}
+  virtual void EvictCurrentFrame() = 0;
+};
+
+// This class is responsible for globally managing which renderers keep their
+// compositor frame when offscreen. We actively discard compositor frames for
+// offscreen tabs, but keep a minimum amount, as an LRU cache, to make switching
+// between a small set of tabs faster. The limit is a soft limit, because
+// clients can lock their frame to prevent it from being discarded, e.g. if the
+// tab is visible, or while capturing a screenshot.
+class VIZ_CLIENT_EXPORT FrameEvictionManager
+    : public base::MemoryCoordinatorClient {
+ public:
+  static FrameEvictionManager* GetInstance();
+
+  void AddFrame(FrameEvictionManagerClient*, bool locked);
+  void RemoveFrame(FrameEvictionManagerClient*);
+  void LockFrame(FrameEvictionManagerClient*);
+  void UnlockFrame(FrameEvictionManagerClient*);
+
+  size_t GetMaxNumberOfSavedFrames() const;
+
+  // For testing only
+  void set_max_number_of_saved_frames(size_t max_number_of_saved_frames) {
+    max_number_of_saved_frames_ = max_number_of_saved_frames;
+  }
+
+  // React on memory pressure events to adjust the number of cached frames.
+  // Please make this private when crbug.com/443824 has been fixed.
+  void OnMemoryPressure(
+      base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
+
+ private:
+  FrameEvictionManager();
+  ~FrameEvictionManager() override;
+
+  // base::MemoryCoordinatorClient implementation:
+  void OnPurgeMemory() override;
+
+  void CullUnlockedFrames(size_t saved_frame_limit);
+
+  void PurgeMemory(int percentage);
+
+  friend struct base::DefaultSingletonTraits<FrameEvictionManager>;
+
+  // Listens for system under pressure notifications and adjusts number of
+  // cached frames accordingly.
+  std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
+
+  std::map<FrameEvictionManagerClient*, size_t> locked_frames_;
+  std::list<FrameEvictionManagerClient*> unlocked_frames_;
+  size_t max_number_of_saved_frames_;
+
+  DISALLOW_COPY_AND_ASSIGN(FrameEvictionManager);
+};
+
+}  // namespace viz
+
+#endif  // COMPONENTS_VIZ_CLIENT_FRAME_EVICTION_MANAGER_H_
diff --git a/components/viz/client/frame_evictor.cc b/components/viz/client/frame_evictor.cc
new file mode 100644
index 0000000..e4529fc
--- /dev/null
+++ b/components/viz/client/frame_evictor.cc
@@ -0,0 +1,56 @@
+// 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/viz/client/frame_evictor.h"
+
+#include "base/logging.h"
+
+namespace viz {
+
+FrameEvictor::FrameEvictor(FrameEvictorClient* client)
+    : client_(client), has_frame_(false), visible_(false) {}
+
+FrameEvictor::~FrameEvictor() {
+  DiscardedFrame();
+}
+
+void FrameEvictor::SwappedFrame(bool visible) {
+  visible_ = visible;
+  has_frame_ = true;
+  FrameEvictionManager::GetInstance()->AddFrame(this, visible);
+}
+
+void FrameEvictor::DiscardedFrame() {
+  FrameEvictionManager::GetInstance()->RemoveFrame(this);
+  has_frame_ = false;
+}
+
+void FrameEvictor::SetVisible(bool visible) {
+  if (visible_ == visible)
+    return;
+  visible_ = visible;
+  if (has_frame_) {
+    if (visible) {
+      LockFrame();
+    } else {
+      UnlockFrame();
+    }
+  }
+}
+
+void FrameEvictor::LockFrame() {
+  DCHECK(has_frame_);
+  FrameEvictionManager::GetInstance()->LockFrame(this);
+}
+
+void FrameEvictor::UnlockFrame() {
+  DCHECK(has_frame_);
+  FrameEvictionManager::GetInstance()->UnlockFrame(this);
+}
+
+void FrameEvictor::EvictCurrentFrame() {
+  client_->EvictDelegatedFrame();
+}
+
+}  // namespace viz
diff --git a/components/viz/client/frame_evictor.h b/components/viz/client/frame_evictor.h
new file mode 100644
index 0000000..95d5d3d
--- /dev/null
+++ b/components/viz/client/frame_evictor.h
@@ -0,0 +1,45 @@
+// 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_VIZ_CLIENT_FRAME_EVICTOR_H_
+#define COMPONENTS_VIZ_CLIENT_FRAME_EVICTOR_H_
+
+#include "base/macros.h"
+#include "components/viz/client/frame_eviction_manager.h"
+
+namespace viz {
+
+class FrameEvictorClient {
+ public:
+  virtual ~FrameEvictorClient() {}
+  virtual void EvictDelegatedFrame() = 0;
+};
+
+class VIZ_CLIENT_EXPORT FrameEvictor : public FrameEvictionManagerClient {
+ public:
+  // |client| must outlive |this|.
+  explicit FrameEvictor(FrameEvictorClient* client);
+  ~FrameEvictor() override;
+
+  void SwappedFrame(bool visible);
+  void DiscardedFrame();
+  void SetVisible(bool visible);
+  void LockFrame();
+  void UnlockFrame();
+  bool HasFrame() { return has_frame_; }
+
+ private:
+  // FrameEvictionManagerClient implementation.
+  void EvictCurrentFrame() override;
+
+  FrameEvictorClient* client_;
+  bool has_frame_;
+  bool visible_;
+
+  DISALLOW_COPY_AND_ASSIGN(FrameEvictor);
+};
+
+}  // namespace viz
+
+#endif  // COMPONENTS_VIZ_CLIENT_FRAME_EVICTOR_H_
diff --git a/components/viz/client/hit_test_data_provider.h b/components/viz/client/hit_test_data_provider.h
index 7301242..809dab2 100644
--- a/components/viz/client/hit_test_data_provider.h
+++ b/components/viz/client/hit_test_data_provider.h
@@ -9,11 +9,12 @@
 #include <vector>
 
 #include "base/macros.h"
+#include "components/viz/client/viz_client_export.h"
 #include "services/viz/public/interfaces/hit_test/hit_test_region_list.mojom.h"
 
 namespace viz {
 
-class HitTestDataProvider {
+class VIZ_CLIENT_EXPORT HitTestDataProvider {
  public:
   HitTestDataProvider() = default;
   virtual ~HitTestDataProvider() = default;
diff --git a/components/viz/client/local_surface_id_provider.h b/components/viz/client/local_surface_id_provider.h
index 500f2205..fa8e51cd 100644
--- a/components/viz/client/local_surface_id_provider.h
+++ b/components/viz/client/local_surface_id_provider.h
@@ -5,6 +5,7 @@
 #ifndef COMPONENTS_VIZ_CLIENT_LOCAL_SURFACE_ID_PROVIDER_H_
 #define COMPONENTS_VIZ_CLIENT_LOCAL_SURFACE_ID_PROVIDER_H_
 
+#include "components/viz/client/viz_client_export.h"
 #include "components/viz/common/surfaces/local_surface_id.h"
 #include "components/viz/common/surfaces/local_surface_id_allocator.h"
 #include "ui/gfx/geometry/size.h"
@@ -12,7 +13,7 @@
 namespace viz {
 class CompositorFrame;
 
-class LocalSurfaceIdProvider {
+class VIZ_CLIENT_EXPORT LocalSurfaceIdProvider {
  public:
   LocalSurfaceIdProvider();
   virtual ~LocalSurfaceIdProvider();
@@ -24,7 +25,8 @@
   DISALLOW_COPY_AND_ASSIGN(LocalSurfaceIdProvider);
 };
 
-class DefaultLocalSurfaceIdProvider : public LocalSurfaceIdProvider {
+class VIZ_CLIENT_EXPORT DefaultLocalSurfaceIdProvider
+    : public LocalSurfaceIdProvider {
  public:
   DefaultLocalSurfaceIdProvider();
 
diff --git a/components/viz/client/viz_client_export.h b/components/viz/client/viz_client_export.h
new file mode 100644
index 0000000..4e7088f
--- /dev/null
+++ b/components/viz/client/viz_client_export.h
@@ -0,0 +1,29 @@
+// 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_VIZ_CLIENT_VIZ_CLIENT_EXPORT_H_
+#define COMPONENTS_VIZ_CLIENT_VIZ_CLIENT_EXPORT_H_
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(VIZ_CLIENT_IMPLEMENTATION)
+#define VIZ_CLIENT_EXPORT __declspec(dllexport)
+#else
+#define VIZ_CLIENT_EXPORT __declspec(dllimport)
+#endif  // defined(VIZ_CLIENT_IMPLEMENTATION)
+
+#else  // defined(WIN32)
+#if defined(VIZ_CLIENT_IMPLEMENTATION)
+#define VIZ_CLIENT_EXPORT __attribute__((visibility("default")))
+#else
+#define VIZ_CLIENT_EXPORT
+#endif
+#endif
+
+#else  // defined(COMPONENT_BUILD)
+#define VIZ_CLIENT_EXPORT
+#endif
+
+#endif  // COMPONENTS_VIZ_CLIENT_VIZ_CLIENT_EXPORT_H_
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn
index fe99255..d3bb1741 100644
--- a/components/viz/common/BUILD.gn
+++ b/components/viz/common/BUILD.gn
@@ -42,6 +42,8 @@
     "frame_sinks/copy_output_request.h",
     "frame_sinks/copy_output_result.cc",
     "frame_sinks/copy_output_result.h",
+    "frame_sinks/copy_output_util.cc",
+    "frame_sinks/copy_output_util.h",
     "frame_sinks/delay_based_time_source.cc",
     "frame_sinks/delay_based_time_source.h",
     "gl_helper.cc",
@@ -170,6 +172,7 @@
   testonly = true
   sources = [
     "frame_sinks/begin_frame_args_unittest.cc",
+    "frame_sinks/copy_output_util_unittest.cc",
     "frame_sinks/delay_based_time_source_unittest.cc",
     "gl_helper_unittest.cc",
     "gpu/context_cache_controller_unittest.cc",
diff --git a/components/viz/common/frame_sinks/copy_output_request.cc b/components/viz/common/frame_sinks/copy_output_request.cc
index 32e993f..b844147 100644
--- a/components/viz/common/frame_sinks/copy_output_request.cc
+++ b/components/viz/common/frame_sinks/copy_output_request.cc
@@ -16,7 +16,9 @@
 CopyOutputRequest::CopyOutputRequest(ResultFormat result_format,
                                      CopyOutputRequestCallback result_callback)
     : result_format_(result_format),
-      result_callback_(std::move(result_callback)) {
+      result_callback_(std::move(result_callback)),
+      scale_from_(1, 1),
+      scale_to_(1, 1) {
   DCHECK(!result_callback_.is_null());
   TRACE_EVENT_ASYNC_BEGIN0("viz", "CopyOutputRequest", this);
 }
@@ -28,6 +30,23 @@
   }
 }
 
+void CopyOutputRequest::SetScaleRatio(const gfx::Vector2d& scale_from,
+                                      const gfx::Vector2d& scale_to) {
+  DCHECK_GT(scale_from.x(), 0);
+  DCHECK_GT(scale_from.y(), 0);
+  DCHECK_GT(scale_to.x(), 0);
+  DCHECK_GT(scale_to.y(), 0);
+  scale_from_ = scale_from;
+  scale_to_ = scale_to;
+}
+
+void CopyOutputRequest::SetUniformScaleRatio(int scale_from, int scale_to) {
+  DCHECK_GT(scale_from, 0);
+  DCHECK_GT(scale_to, 0);
+  scale_from_ = gfx::Vector2d(scale_from, scale_from);
+  scale_to_ = gfx::Vector2d(scale_to, scale_to);
+}
+
 void CopyOutputRequest::SendResult(std::unique_ptr<CopyOutputResult> result) {
   TRACE_EVENT_ASYNC_END1("viz", "CopyOutputRequest", this, "success",
                          !result->IsEmpty());
diff --git a/components/viz/common/frame_sinks/copy_output_request.h b/components/viz/common/frame_sinks/copy_output_request.h
index d7e1dc0a..d72d6e0 100644
--- a/components/viz/common/frame_sinks/copy_output_request.h
+++ b/components/viz/common/frame_sinks/copy_output_request.h
@@ -17,6 +17,7 @@
 #include "components/viz/common/resources/single_release_callback.h"
 #include "components/viz/common/viz_common_export.h"
 #include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/vector2d.h"
 
 namespace viz {
 
@@ -62,6 +63,22 @@
   }
   bool has_result_task_runner() const { return !!result_task_runner_; }
 
+  // Optionally specify that the result should be scaled. |scale_from| and
+  // |scale_to| describe the scale ratio in terms of relative sizes: Downscale
+  // if |scale_from| > |scale_to|, upscale if |scale_from| < |scale_to|, and
+  // no scaling if |scale_from| == |scale_to|. Neither argument may be zero.
+  //
+  // There are two setters: SetScaleRatio() allows for requesting an arbitrary
+  // scale in each dimension, which is sometimes useful for minor "tweaks" that
+  // optimize visual quality. SetUniformScaleRatio() scales both dimensions by
+  // the same amount.
+  void SetScaleRatio(const gfx::Vector2d& scale_from,
+                     const gfx::Vector2d& scale_to);
+  void SetUniformScaleRatio(int scale_from, int scale_to);
+  const gfx::Vector2d& scale_from() const { return scale_from_; }
+  const gfx::Vector2d& scale_to() const { return scale_to_; }
+  bool is_scaled() const { return scale_from_ != scale_to_; }
+
   // Optionally specify the source of this copy request. If set when this copy
   // request is submitted to a layer, a prior uncommitted copy request from the
   // same source will be aborted.
@@ -101,6 +118,8 @@
   const ResultFormat result_format_;
   CopyOutputRequestCallback result_callback_;
   scoped_refptr<base::TaskRunner> result_task_runner_;
+  gfx::Vector2d scale_from_;
+  gfx::Vector2d scale_to_;
   base::Optional<base::UnguessableToken> source_;
   base::Optional<gfx::Rect> area_;
   base::Optional<TextureMailbox> texture_mailbox_;
diff --git a/components/viz/common/frame_sinks/copy_output_result.h b/components/viz/common/frame_sinks/copy_output_result.h
index d72f868..e0b3b545 100644
--- a/components/viz/common/frame_sinks/copy_output_result.h
+++ b/components/viz/common/frame_sinks/copy_output_result.h
@@ -45,7 +45,9 @@
   Format format() const { return format_; }
 
   // Returns the result Rect, which is the position and size of the image data
-  // within the surface/layer (see CopyOutputRequest::set_area()).
+  // within the surface/layer (see CopyOutputRequest::set_area()). If a scale
+  // ratio was set in the request, this will be in the scaled, NOT the original,
+  // coordinate space.
   const gfx::Rect& rect() const { return rect_; }
   const gfx::Size& size() const { return rect_.size(); }
 
diff --git a/components/viz/common/frame_sinks/copy_output_util.cc b/components/viz/common/frame_sinks/copy_output_util.cc
new file mode 100644
index 0000000..243b791
--- /dev/null
+++ b/components/viz/common/frame_sinks/copy_output_util.cc
@@ -0,0 +1,68 @@
+// 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/viz/common/frame_sinks/copy_output_util.h"
+
+#include <stdint.h>
+
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/vector2d.h"
+
+namespace viz {
+namespace copy_output {
+
+namespace {
+
+// Returns the same values as std::ceil(t * numerator / denominator), but
+// without introducing floating-point math and using 64-bit integer ops to avoid
+// overflow.
+int64_t CeilScale(int32_t t, int32_t numerator, int32_t denominator) {
+  int64_t x = static_cast<int64_t>(t) * numerator;
+  if (x > 0)
+    x += denominator - 1;
+  return x / denominator;
+}
+
+// Returns the same values as std::floor(t * numerator / denominator), but
+// without introducing floating-point math and using 64-bit integer ops to avoid
+// overflow.
+int64_t FloorScale(int32_t t, int32_t numerator, int32_t denominator) {
+  if (t < 0)
+    return -CeilScale(-t, numerator, denominator);
+  return (static_cast<int64_t>(t) * numerator) / denominator;
+}
+
+}  // namespace
+
+gfx::Rect ComputeResultRect(const gfx::Rect& area,
+                            const gfx::Vector2d& scale_from,
+                            const gfx::Vector2d& scale_to) {
+  DCHECK_GT(scale_from.x(), 0);
+  DCHECK_GT(scale_from.y(), 0);
+  DCHECK_GT(scale_to.x(), 0);
+  DCHECK_GT(scale_to.y(), 0);
+
+  const int64_t x = FloorScale(area.x(), scale_to.x(), scale_from.x());
+  const int64_t y = FloorScale(area.y(), scale_to.y(), scale_from.y());
+  const int64_t w = CeilScale(area.width(), scale_to.x(), scale_from.x());
+  const int64_t h = CeilScale(area.height(), scale_to.y(), scale_from.y());
+
+  // These constants define the "reasonable" range of result Rect coordinates.
+  constexpr int kMaxOriginOffset = (1 << 24) - 1;  // Arbitrary, but practical.
+  constexpr int kMaxDimension = (1 << 15) - 1;     // From media/base/limits.h.
+
+  // If the result Rect is not "safely reasonable," return an empty Rect instead
+  // to indicate to the client that scaling should not be attempted.
+  if (x < -kMaxOriginOffset || x > kMaxOriginOffset || y < -kMaxOriginOffset ||
+      y > kMaxOriginOffset || w <= 0 || w > kMaxDimension || h <= 0 ||
+      h > kMaxDimension) {
+    return gfx::Rect();
+  }
+
+  return gfx::Rect(static_cast<int>(x), static_cast<int>(y),
+                   static_cast<int>(w), static_cast<int>(h));
+}
+
+}  // namespace copy_output
+}  // namespace viz
diff --git a/components/viz/common/frame_sinks/copy_output_util.h b/components/viz/common/frame_sinks/copy_output_util.h
new file mode 100644
index 0000000..b0db4159
--- /dev/null
+++ b/components/viz/common/frame_sinks/copy_output_util.h
@@ -0,0 +1,29 @@
+// 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_VIZ_COMMON_FRAME_SINKS_COPY_OUTPUT_UTIL_H_
+#define COMPONENTS_VIZ_COMMON_FRAME_SINKS_COPY_OUTPUT_UTIL_H_
+
+#include "components/viz/common/viz_common_export.h"
+
+namespace gfx {
+class Rect;
+class Vector2d;
+}  // namespace gfx
+
+namespace viz {
+namespace copy_output {
+
+// Returns the pixels in the scaled result coordinate space that are affected by
+// the source |area| and scaling ratio. If application of the scaling ratio
+// generates coordinates that are out-of-range or otherwise not "safely
+// reasonable," an empty Rect is returned.
+gfx::Rect VIZ_COMMON_EXPORT ComputeResultRect(const gfx::Rect& area,
+                                              const gfx::Vector2d& scale_from,
+                                              const gfx::Vector2d& scale_to);
+
+}  // namespace copy_output
+}  // namespace viz
+
+#endif  // COMPONENTS_VIZ_COMMON_FRAME_SINKS_COPY_OUTPUT_UTIL_H_
diff --git a/components/viz/common/frame_sinks/copy_output_util_unittest.cc b/components/viz/common/frame_sinks/copy_output_util_unittest.cc
new file mode 100644
index 0000000..132a9097
--- /dev/null
+++ b/components/viz/common/frame_sinks/copy_output_util_unittest.cc
@@ -0,0 +1,152 @@
+// 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/viz/common/frame_sinks/copy_output_util.h"
+
+#include <limits>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/vector2d.h"
+
+namespace viz {
+namespace copy_output {
+
+namespace {
+
+// Some very large integers that should be big enough to trigger overflow
+// conditions, if the implementation is doing bad math.
+constexpr int kMaxInt = std::numeric_limits<int>::max();
+constexpr int kMaxEvenInt = kMaxInt - 1;
+
+// These are all equivalent to a scale ratio of 1:1.
+constexpr gfx::Vector2d kNonScalingVectors[5][2] = {
+    {gfx::Vector2d(1, 1), gfx::Vector2d(1, 1)},
+    {gfx::Vector2d(42, 1), gfx::Vector2d(42, 1)},
+    {gfx::Vector2d(1, 42), gfx::Vector2d(1, 42)},
+    {gfx::Vector2d(kMaxInt, 1), gfx::Vector2d(kMaxInt, 1)},
+    {gfx::Vector2d(1, kMaxInt), gfx::Vector2d(1, kMaxInt)},
+};
+
+// These are all equivalent to a scale ratio of 1:2 in the X direction.
+constexpr gfx::Vector2d kDoublingXVectors[4][2] = {
+    {gfx::Vector2d(1, 1), gfx::Vector2d(2, 1)},
+    {gfx::Vector2d(21, 1), gfx::Vector2d(42, 1)},
+    {gfx::Vector2d(kMaxEvenInt / 2, 1), gfx::Vector2d(kMaxEvenInt, 1)},
+    {gfx::Vector2d(kMaxEvenInt / 2, kMaxInt),
+     gfx::Vector2d(kMaxEvenInt, kMaxInt)},
+};
+
+// These are all equivalent to a scale ratio of 1:2 in the Y direction.
+constexpr gfx::Vector2d kDoublingYVectors[4][2] = {
+    {gfx::Vector2d(1, 1), gfx::Vector2d(1, 2)},
+    {gfx::Vector2d(1, 55), gfx::Vector2d(1, 110)},
+    {gfx::Vector2d(1, kMaxEvenInt / 2), gfx::Vector2d(1, kMaxEvenInt)},
+    {gfx::Vector2d(kMaxInt, kMaxEvenInt / 2),
+     gfx::Vector2d(kMaxInt, kMaxEvenInt)},
+};
+
+TEST(CopyOutputUtil, ComputesValidResultRects) {
+  for (const gfx::Vector2d* v : kNonScalingVectors) {
+    SCOPED_TRACE(::testing::Message()
+                 << "v[0]=" << v[0].ToString() << ", v[1]=" << v[1].ToString());
+    EXPECT_EQ(gfx::Rect(1, 2, 3, 4),
+              ComputeResultRect(gfx::Rect(1, 2, 3, 4), v[0], v[1]));
+    EXPECT_EQ(gfx::Rect(-1, 2, 3, 4),
+              ComputeResultRect(gfx::Rect(-1, 2, 3, 4), v[0], v[1]));
+    EXPECT_EQ(gfx::Rect(1, -2, 3, 4),
+              ComputeResultRect(gfx::Rect(1, -2, 3, 4), v[0], v[1]));
+  }
+  for (const gfx::Vector2d* v : kDoublingXVectors) {
+    SCOPED_TRACE(::testing::Message()
+                 << "v[0]=" << v[0].ToString() << ", v[1]=" << v[1].ToString());
+    EXPECT_EQ(gfx::Rect(2, 2, 6, 4),
+              ComputeResultRect(gfx::Rect(1, 2, 3, 4), v[0], v[1]));
+    EXPECT_EQ(gfx::Rect(-2, 2, 6, 4),
+              ComputeResultRect(gfx::Rect(-1, 2, 3, 4), v[0], v[1]));
+    EXPECT_EQ(gfx::Rect(2, -2, 6, 4),
+              ComputeResultRect(gfx::Rect(1, -2, 3, 4), v[0], v[1]));
+  }
+  for (const gfx::Vector2d* v : kDoublingYVectors) {
+    SCOPED_TRACE(::testing::Message()
+                 << "v[0]=" << v[0].ToString() << ", v[1]=" << v[1].ToString());
+    EXPECT_EQ(gfx::Rect(1, 4, 3, 8),
+              ComputeResultRect(gfx::Rect(1, 2, 3, 4), v[0], v[1]));
+    EXPECT_EQ(gfx::Rect(-1, 4, 3, 8),
+              ComputeResultRect(gfx::Rect(-1, 2, 3, 4), v[0], v[1]));
+    EXPECT_EQ(gfx::Rect(1, -4, 3, 8),
+              ComputeResultRect(gfx::Rect(1, -2, 3, 4), v[0], v[1]));
+  }
+
+  // Scale 3:2 in the X direction and 7:3 in the Y direction.
+  constexpr gfx::Vector2d kWeirdScaleFrom = gfx::Vector2d(3, 7);
+  constexpr gfx::Vector2d kWeirdScaleTo = gfx::Vector2d(2, 3);
+  EXPECT_EQ(
+      gfx::Rect(0, 0, 1, 1),
+      ComputeResultRect(gfx::Rect(1, 1, 1, 2), kWeirdScaleFrom, kWeirdScaleTo));
+  EXPECT_EQ(gfx::Rect(-1, -1, 1, 1),
+            ComputeResultRect(gfx::Rect(-1, -1, 1, 2), kWeirdScaleFrom,
+                              kWeirdScaleTo));
+  EXPECT_EQ(
+      gfx::Rect(2, 3, 2, 3),
+      ComputeResultRect(gfx::Rect(3, 7, 3, 7), kWeirdScaleFrom, kWeirdScaleTo));
+  EXPECT_EQ(gfx::Rect(-2, -3, 4, 6),
+            ComputeResultRect(gfx::Rect(-3, -7, 6, 14), kWeirdScaleFrom,
+                              kWeirdScaleTo));
+  EXPECT_EQ(gfx::Rect((1 << 24) * 2 / 3, (1 << 25) * 3 / 7,
+                      (1 << 15) * 2 / 3 + 1, (1 << 16) * 3 / 7 + 1),
+            ComputeResultRect(gfx::Rect(1 << 24, 1 << 25, 1 << 15, 1 << 16),
+                              kWeirdScaleFrom, kWeirdScaleTo));
+  EXPECT_EQ(
+      gfx::Rect(-(1 << 24) * 2 / 3 - 1, -(1 << 25) * 3 / 7 - 1,
+                (1 << 15) * 2 / 3 + 1, (1 << 16) * 3 / 7 + 1),
+      ComputeResultRect(gfx::Rect(-(1 << 24), -(1 << 25), 1 << 15, 1 << 16),
+                        kWeirdScaleFrom, kWeirdScaleTo));
+}
+
+TEST(CopyOutputUtil, IdentifiesUnreasonableResultRects) {
+  // When the scale ratio is too great for even a 1x1 rect to be scaled:
+  EXPECT_EQ(gfx::Rect(),
+            ComputeResultRect(gfx::Rect(1, 1, 1, 1), gfx::Vector2d(1, 1),
+                              gfx::Vector2d(1 << 30, 1)));
+  EXPECT_EQ(gfx::Rect(),
+            ComputeResultRect(gfx::Rect(1, 1, 1, 1), gfx::Vector2d(1, 1),
+                              gfx::Vector2d(1, 1 << 30)));
+  EXPECT_EQ(gfx::Rect(),
+            ComputeResultRect(gfx::Rect(1, 1, 1, 1), gfx::Vector2d(1, 1),
+                              gfx::Vector2d(1 << 30, 1 << 30)));
+
+  // When the rect and scale ratio are large, but produce unreasonable results:
+  EXPECT_EQ(gfx::Rect(), ComputeResultRect(gfx::Rect(0, 0, 1 << 12, 1 << 13),
+                                           gfx::Vector2d(1, 1),
+                                           gfx::Vector2d(1 << 4, 1 << 3)));
+  EXPECT_EQ(gfx::Rect(), ComputeResultRect(gfx::Rect(1 << 20, 1 << 21, 1, 1),
+                                           gfx::Vector2d(1, 1),
+                                           gfx::Vector2d(1 << 4, 1 << 3)));
+  EXPECT_EQ(
+      gfx::Rect(),
+      ComputeResultRect(gfx::Rect(-(1 << 20), -(1 << 21), 1, 1),
+                        gfx::Vector2d(1, 1), gfx::Vector2d(1 << 4, 1 << 3)));
+
+  // Boundary condition: Right on the edge of "unreasonable."
+  EXPECT_EQ(gfx::Rect((1 << 9) * ((1 << 15) - 1), 1, (1 << 15) - 1, 1),
+            ComputeResultRect(gfx::Rect(1 << 9, 1, 1, 1), gfx::Vector2d(1, 1),
+                              gfx::Vector2d((1 << 15) - 1, 1)));
+  EXPECT_EQ(
+      gfx::Rect(-(1 << 9) * ((1 << 15) - 1), 1, (1 << 15) - 1, 1),
+      ComputeResultRect(gfx::Rect(-(1 << 9), 1, 1, 1), gfx::Vector2d(1, 1),
+                        gfx::Vector2d((1 << 15) - 1, 1)));
+  EXPECT_EQ(gfx::Rect(1, (1 << 9) * ((1 << 15) - 1), 1, (1 << 15) - 1),
+            ComputeResultRect(gfx::Rect(1, 1 << 9, 1, 1), gfx::Vector2d(1, 1),
+                              gfx::Vector2d(1, (1 << 15) - 1)));
+  EXPECT_EQ(
+      gfx::Rect(1, -(1 << 9) * ((1 << 15) - 1), 1, (1 << 15) - 1),
+      ComputeResultRect(gfx::Rect(1, -(1 << 9), 1, 1), gfx::Vector2d(1, 1),
+                        gfx::Vector2d(1, (1 << 15) - 1)));
+}
+
+}  // namespace
+
+}  // namespace copy_output
+}  // namespace viz
diff --git a/components/viz/host/hit_test/hit_test_query.cc b/components/viz/host/hit_test/hit_test_query.cc
index 438c7b4..9e85ae3 100644
--- a/components/viz/host/hit_test/hit_test_query.cc
+++ b/components/viz/host/hit_test/hit_test_query.cc
@@ -61,6 +61,27 @@
   return target;
 }
 
+gfx::Point HitTestQuery::TransformLocationForTarget(
+    EventSource event_source,
+    const std::vector<FrameSinkId>& target_ancestors,
+    const gfx::Point& location_in_root) const {
+  if (!active_hit_test_list_size_)
+    return location_in_root;
+
+  gfx::Point location_in_target(location_in_root);
+  // TODO(riajiang): Cache the matrix product such that the transform can be
+  // done immediately. crbug/758062.
+  DCHECK(target_ancestors.size() > 0u &&
+         target_ancestors[target_ancestors.size() - 1] ==
+             active_hit_test_list_->frame_sink_id);
+  bool success = TransformLocationForTargetRecursively(
+      event_source, target_ancestors, target_ancestors.size() - 1,
+      active_hit_test_list_, &location_in_target);
+  // Must provide a valid target.
+  DCHECK(success);
+  return location_in_target;
+}
+
 bool HitTestQuery::FindTargetInRegionForLocation(
     EventSource event_source,
     const gfx::Point& location_in_parent,
@@ -107,4 +128,49 @@
   return false;
 }
 
+bool HitTestQuery::TransformLocationForTargetRecursively(
+    EventSource event_source,
+    const std::vector<FrameSinkId>& target_ancestors,
+    size_t target_ancestor,
+    AggregatedHitTestRegion* region,
+    gfx::Point* location_in_target) const {
+  bool match_touch_or_mouse_region =
+      ShouldUseTouchBounds(event_source)
+          ? (region->flags & mojom::kHitTestTouch) != 0u
+          : (region->flags & mojom::kHitTestMouse) != 0u;
+  if ((region->flags & mojom::kHitTestChildSurface) == 0u &&
+      !match_touch_or_mouse_region) {
+    return false;
+  }
+
+  region->transform.TransformPoint(location_in_target);
+  location_in_target->Offset(-region->rect.x(), -region->rect.y());
+  if (!target_ancestor)
+    return true;
+
+  if (region->child_count < 0 ||
+      region->child_count >
+          (active_hit_test_list_ + active_hit_test_list_size_ - region - 1)) {
+    return false;
+  }
+  AggregatedHitTestRegion* child_region = region + 1;
+  AggregatedHitTestRegion* child_region_end =
+      child_region + region->child_count;
+  while (child_region < child_region_end) {
+    if (child_region->frame_sink_id == target_ancestors[target_ancestor - 1]) {
+      return TransformLocationForTargetRecursively(
+          event_source, target_ancestors, target_ancestor - 1, child_region,
+          location_in_target);
+    }
+
+    if (child_region->child_count < 0 ||
+        child_region->child_count >= region->child_count) {
+      return false;
+    }
+    child_region = child_region + child_region->child_count + 1;
+  }
+
+  return false;
+}
+
 }  // namespace viz
diff --git a/components/viz/host/hit_test/hit_test_query.h b/components/viz/host/hit_test/hit_test_query.h
index ee02e90d..201e6e0 100644
--- a/components/viz/host/hit_test/hit_test_query.h
+++ b/components/viz/host/hit_test/hit_test_query.h
@@ -79,6 +79,16 @@
   Target FindTargetForLocation(EventSource event_source,
                                const gfx::Point& location_in_root) const;
 
+  // When a target window is already known, e.g. capture/latched window, convert
+  // |location_in_root| to be in the coordinate space of the target.
+  // |target_ancestors| contains the FrameSinkId from target to root.
+  // |target_ancestors.front()| is the target, and |target_ancestors.back()|
+  // is the root.
+  gfx::Point TransformLocationForTarget(
+      EventSource event_source,
+      const std::vector<FrameSinkId>& target_ancestors,
+      const gfx::Point& location_in_root) const;
+
  private:
   // Helper function to find |target| for |location_in_parent| in the |region|,
   // returns true if a target is found and false otherwise. |location_in_parent|
@@ -88,6 +98,16 @@
                                      AggregatedHitTestRegion* region,
                                      Target* target) const;
 
+  // Transform |location_in_target| to be in |region|'s coordinate space.
+  // |location_in_target| is in the coordinate space of |region|'s parent at the
+  // beginning.
+  bool TransformLocationForTargetRecursively(
+      EventSource event_source,
+      const std::vector<FrameSinkId>& target_ancestors,
+      size_t target_ancestor,
+      AggregatedHitTestRegion* region,
+      gfx::Point* location_in_target) const;
+
   uint32_t handle_buffer_sizes_[2];
   mojo::ScopedSharedBufferMapping handle_buffers_[2];
 
diff --git a/components/viz/host/hit_test/hit_test_query_unittest.cc b/components/viz/host/hit_test/hit_test_query_unittest.cc
index 2e40e3f..e21e8e88 100644
--- a/components/viz/host/hit_test/hit_test_query_unittest.cc
+++ b/components/viz/host/hit_test/hit_test_query_unittest.cc
@@ -335,6 +335,65 @@
   EXPECT_EQ(target4.flags, mojom::kHitTestMine | mojom::kHitTestMouse);
 }
 
+// Tests transforming location to be in target's coordinate system given the
+// target's ancestor list, in the case of ClippedChildWithChildUnderneath test.
+TEST_F(HitTestQueryTest, ClippedChildWithChildUnderneathTransform) {
+  FrameSinkId e_id = FrameSinkId(1, 1);
+  FrameSinkId c_id = FrameSinkId(2, 2);
+  FrameSinkId a_id = FrameSinkId(3, 3);
+  FrameSinkId b_id = FrameSinkId(4, 4);
+  FrameSinkId d_id = FrameSinkId(5, 5);
+  gfx::Rect e_bounds_in_e = gfx::Rect(0, 0, 600, 600);
+  gfx::Rect c_bounds_in_e = gfx::Rect(0, 0, 800, 800);
+  gfx::Rect a_bounds_in_c = gfx::Rect(0, 0, 200, 100);
+  gfx::Rect b_bounds_in_c = gfx::Rect(0, 100, 800, 600);
+  gfx::Rect d_bounds_in_e = gfx::Rect(0, 0, 800, 800);
+  gfx::Transform transform_e_to_e, transform_e_to_c, transform_c_to_a,
+      transform_c_to_b, transform_e_to_d;
+  transform_e_to_c.Translate(-200, -100);
+  transform_e_to_d.Translate(-400, -50);
+  AggregatedHitTestRegion* aggregated_hit_test_region_list =
+      aggregated_hit_test_region();
+  aggregated_hit_test_region_list[0] =
+      AggregatedHitTestRegion(e_id, mojom::kHitTestMine | mojom::kHitTestMouse,
+                              e_bounds_in_e, transform_e_to_e, 4);  // e
+  aggregated_hit_test_region_list[1] = AggregatedHitTestRegion(
+      c_id, mojom::kHitTestChildSurface | mojom::kHitTestIgnore, c_bounds_in_e,
+      transform_e_to_c, 2);  // c
+  aggregated_hit_test_region_list[2] =
+      AggregatedHitTestRegion(a_id, mojom::kHitTestMine | mojom::kHitTestMouse,
+                              a_bounds_in_c, transform_c_to_a, 0);  // a
+  aggregated_hit_test_region_list[3] =
+      AggregatedHitTestRegion(b_id, mojom::kHitTestMine | mojom::kHitTestMouse,
+                              b_bounds_in_c, transform_c_to_b, 0);  // b
+  aggregated_hit_test_region_list[4] =
+      AggregatedHitTestRegion(d_id, mojom::kHitTestMine | mojom::kHitTestMouse,
+                              d_bounds_in_e, transform_e_to_d, 0);  // d
+
+  // All points are in e's coordinate system when we reach this case.
+  gfx::Point point1(1, 1);
+  gfx::Point point2(202, 102);
+  gfx::Point point3(450, 150);
+  gfx::Point point4(202, 202);
+
+  std::vector<FrameSinkId> target_ancestors1{e_id};
+  EXPECT_EQ(hit_test_query().TransformLocationForTarget(
+                EventSource::MOUSE, target_ancestors1, point1),
+            point1);
+  std::vector<FrameSinkId> target_ancestors2{a_id, c_id, e_id};
+  EXPECT_EQ(hit_test_query().TransformLocationForTarget(
+                EventSource::MOUSE, target_ancestors2, point2),
+            gfx::Point(2, 2));
+  std::vector<FrameSinkId> target_ancestors3{d_id, e_id};
+  EXPECT_EQ(hit_test_query().TransformLocationForTarget(
+                EventSource::MOUSE, target_ancestors3, point3),
+            gfx::Point(50, 100));
+  std::vector<FrameSinkId> target_ancestors4{b_id, c_id, e_id};
+  EXPECT_EQ(hit_test_query().TransformLocationForTarget(
+                EventSource::MOUSE, target_ancestors4, point4),
+            gfx::Point(2, 2));
+}
+
 // One embedder with two clipped children with a tab and transparent background.
 //
 //  +e-------------+
@@ -451,6 +510,93 @@
   EXPECT_EQ(target7.flags, mojom::kHitTestMine | mojom::kHitTestMouse);
 }
 
+// Tests transforming location to be in target's coordinate system given the
+// target's ancestor list, in the case of
+// ClippedChildrenWithTabAndTransparentBackground test.
+TEST_F(HitTestQueryTest,
+       ClippedChildrenWithTabAndTransparentBackgroundTransform) {
+  FrameSinkId e_id = FrameSinkId(1, 1);
+  FrameSinkId c1_id = FrameSinkId(2, 2);
+  FrameSinkId a_id = FrameSinkId(3, 3);
+  FrameSinkId b_id = FrameSinkId(4, 4);
+  FrameSinkId c2_id = FrameSinkId(5, 5);
+  FrameSinkId g_id = FrameSinkId(6, 6);
+  FrameSinkId h_id = FrameSinkId(7, 7);
+  gfx::Rect e_bounds_in_e = gfx::Rect(0, 0, 600, 1200);
+  gfx::Rect c1_bounds_in_e = gfx::Rect(0, 0, 800, 500);
+  gfx::Rect a_bounds_in_c1 = gfx::Rect(0, 0, 200, 100);
+  gfx::Rect b_bounds_in_c1 = gfx::Rect(0, 0, 800, 400);
+  gfx::Rect c2_bounds_in_e = gfx::Rect(0, 0, 800, 500);
+  gfx::Rect g_bounds_in_c2 = gfx::Rect(0, 0, 200, 100);
+  gfx::Rect h_bounds_in_c2 = gfx::Rect(0, 0, 800, 800);
+  gfx::Transform transform_e_to_e, transform_e_to_c1, transform_c1_to_a,
+      transform_c1_to_b, transform_e_to_c2, transform_c2_to_g,
+      transform_c2_to_h;
+  transform_e_to_c1.Translate(-200, -100);
+  transform_c1_to_b.Translate(0, -100);
+  transform_e_to_c2.Translate(-200, -700);
+  transform_c2_to_h.Translate(0, -100);
+  AggregatedHitTestRegion* aggregated_hit_test_region_list =
+      aggregated_hit_test_region();
+  aggregated_hit_test_region_list[0] =
+      AggregatedHitTestRegion(e_id, mojom::kHitTestMine | mojom::kHitTestMouse,
+                              e_bounds_in_e, transform_e_to_e, 6);  // e
+  aggregated_hit_test_region_list[1] = AggregatedHitTestRegion(
+      c1_id, mojom::kHitTestChildSurface | mojom::kHitTestIgnore,
+      c1_bounds_in_e, transform_e_to_c1, 2);  // c1
+  aggregated_hit_test_region_list[2] =
+      AggregatedHitTestRegion(a_id, mojom::kHitTestMine | mojom::kHitTestMouse,
+                              a_bounds_in_c1, transform_c1_to_a, 0);  // a
+  aggregated_hit_test_region_list[3] =
+      AggregatedHitTestRegion(b_id, mojom::kHitTestMine | mojom::kHitTestMouse,
+                              b_bounds_in_c1, transform_c1_to_b, 0);  // b
+  aggregated_hit_test_region_list[4] = AggregatedHitTestRegion(
+      c2_id, mojom::kHitTestChildSurface | mojom::kHitTestIgnore,
+      c2_bounds_in_e, transform_e_to_c2, 2);  // c2
+  aggregated_hit_test_region_list[5] =
+      AggregatedHitTestRegion(g_id, mojom::kHitTestMine | mojom::kHitTestMouse,
+                              g_bounds_in_c2, transform_c2_to_g, 0);  // g
+  aggregated_hit_test_region_list[6] =
+      AggregatedHitTestRegion(h_id, mojom::kHitTestMine | mojom::kHitTestMouse,
+                              h_bounds_in_c2, transform_c2_to_h, 0);  // h
+
+  // All points are in e's coordinate system when we reach this case.
+  gfx::Point point1(1, 1);
+  gfx::Point point2(202, 102);
+  gfx::Point point3(403, 103);
+  gfx::Point point4(202, 202);
+  gfx::Point point5(250, 750);
+  gfx::Point point6(450, 750);
+  gfx::Point point7(350, 1100);
+
+  std::vector<FrameSinkId> target_ancestors1{e_id};
+  EXPECT_EQ(hit_test_query().TransformLocationForTarget(
+                EventSource::MOUSE, target_ancestors1, point1),
+            point1);
+  std::vector<FrameSinkId> target_ancestors2{a_id, c1_id, e_id};
+  EXPECT_EQ(hit_test_query().TransformLocationForTarget(
+                EventSource::MOUSE, target_ancestors2, point2),
+            gfx::Point(2, 2));
+  EXPECT_EQ(hit_test_query().TransformLocationForTarget(
+                EventSource::MOUSE, target_ancestors1, point3),
+            point3);
+  std::vector<FrameSinkId> target_ancestors3{b_id, c1_id, e_id};
+  EXPECT_EQ(hit_test_query().TransformLocationForTarget(
+                EventSource::MOUSE, target_ancestors3, point4),
+            gfx::Point(2, 2));
+  std::vector<FrameSinkId> target_ancestors4{g_id, c2_id, e_id};
+  EXPECT_EQ(hit_test_query().TransformLocationForTarget(
+                EventSource::MOUSE, target_ancestors4, point5),
+            gfx::Point(50, 50));
+  EXPECT_EQ(hit_test_query().TransformLocationForTarget(
+                EventSource::MOUSE, target_ancestors1, point6),
+            point6);
+  std::vector<FrameSinkId> target_ancestors5{h_id, c2_id, e_id};
+  EXPECT_EQ(hit_test_query().TransformLocationForTarget(
+                EventSource::MOUSE, target_ancestors5, point7),
+            gfx::Point(150, 300));
+}
+
 // Children that are multiple layers deep.
 //
 //  +e--------------------+
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
index e47a47b..15cb98f 100644
--- a/components/viz/service/BUILD.gn
+++ b/components/viz/service/BUILD.gn
@@ -93,10 +93,6 @@
     "frame_sinks/compositor_frame_sink_support_manager.h",
     "frame_sinks/direct_layer_tree_frame_sink.cc",
     "frame_sinks/direct_layer_tree_frame_sink.h",
-    "frame_sinks/frame_eviction_manager.cc",
-    "frame_sinks/frame_eviction_manager.h",
-    "frame_sinks/frame_evictor.cc",
-    "frame_sinks/frame_evictor.h",
     "frame_sinks/frame_sink_manager_client.h",
     "frame_sinks/frame_sink_manager_impl.cc",
     "frame_sinks/frame_sink_manager_impl.h",
diff --git a/components/viz/service/display/gl_renderer.cc b/components/viz/service/display/gl_renderer.cc
index f8a8af42..d45ebf9 100644
--- a/components/viz/service/display/gl_renderer.cc
+++ b/components/viz/service/display/gl_renderer.cc
@@ -2667,6 +2667,10 @@
   gfx::Rect copy_rect = current_frame()->current_render_pass->output_rect;
   gfx::ColorSpace render_pass_color_space =
       current_frame()->current_render_pass->color_space;
+  if (request->is_scaled()) {
+    // TODO(crbug/760348): Coming soon!
+    return;
+  }
   if (request->has_area())
     copy_rect.Intersect(request->area());
   GetFramebufferPixelsAsync(copy_rect, render_pass_color_space,
diff --git a/components/viz/service/display/software_renderer.cc b/components/viz/service/display/software_renderer.cc
index b66b1716..37e078ed 100644
--- a/components/viz/service/display/software_renderer.cc
+++ b/components/viz/service/display/software_renderer.cc
@@ -11,6 +11,7 @@
 #include "cc/resources/scoped_resource.h"
 #include "components/viz/common/display/renderer_settings.h"
 #include "components/viz/common/frame_sinks/copy_output_request.h"
+#include "components/viz/common/frame_sinks/copy_output_util.h"
 #include "components/viz/common/quads/debug_border_draw_quad.h"
 #include "components/viz/common/quads/picture_draw_quad.h"
 #include "components/viz/common/quads/render_pass_draw_quad.h"
@@ -20,6 +21,7 @@
 #include "components/viz/service/display/output_surface.h"
 #include "components/viz/service/display/output_surface_frame.h"
 #include "components/viz/service/display/software_output_device.h"
+#include "skia/ext/image_operations.h"
 #include "skia/ext/opacity_filter_canvas.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -583,21 +585,79 @@
       break;
   }
 
-  gfx::Rect copy_rect = current_frame()->current_render_pass->output_rect;
-  if (request->has_area())
-    copy_rect.Intersect(request->area());
-  gfx::Rect window_copy_rect = MoveFromDrawToWindowSpace(copy_rect);
+  // Finalize the source rect, either as the entire RenderPass's output rect, or
+  // the client-provided area clamped to the output rect.
+  if (request->has_area()) {
+    gfx::Rect clamped_area = request->area();
+    clamped_area.Intersect(current_frame()->current_render_pass->output_rect);
+    request->set_area(clamped_area);
+  } else {
+    request->set_area(current_frame()->current_render_pass->output_rect);
+  }
 
+  gfx::Rect result_rect;
   SkBitmap bitmap;
-  bitmap.allocPixels(SkImageInfo::MakeN32Premul(
-      window_copy_rect.width(), window_copy_rect.height(),
-      current_canvas_->imageInfo().refColorSpace()));
-  if (!current_canvas_->readPixels(bitmap, window_copy_rect.x(),
-                                   window_copy_rect.y()))
-    return;  // |request| auto-sends empty result on out-of-scope.
+  if (request->is_scaled()) {
+    // Compute the rect of the pixels in the copy output result's coordinate
+    // space that are affected by the requested copy area. If there will be zero
+    // pixels of output or the scaling ratio was not reasonable, do not proceed.
+    result_rect = copy_output::ComputeResultRect(
+        request->area(), request->scale_from(), request->scale_to());
+    if (result_rect.IsEmpty())
+      return;
+
+    // Resolve the source for the scaling input: Initialize a SkPixmap that
+    // selects the current RenderPass's output rect within the current canvas
+    // and provides access to its pixels.
+    SkPixmap render_pass_output;
+    if (!current_canvas_->peekPixels(&render_pass_output))
+      return;
+    {
+      const gfx::Rect subrect = MoveFromDrawToWindowSpace(
+          current_frame()->current_render_pass->output_rect);
+      render_pass_output = SkPixmap(
+          render_pass_output.info().makeWH(subrect.width(), subrect.height()),
+          render_pass_output.addr(subrect.x(), subrect.y()),
+          render_pass_output.rowBytes());
+    }
+    const gfx::Size scaled_output_size =
+        copy_output::ComputeResultRect(
+            gfx::Rect(render_pass_output.width(), render_pass_output.height()),
+            request->scale_from(), request->scale_to())
+            .size();
+    DCHECK(gfx::Rect(scaled_output_size).Contains(result_rect));
+
+    // Execute the scaling: For downscaling, use the RESIZE_BETTER strategy
+    // (appropriate for thumbnailing); and, for upscaling, use the RESIZE_BEST
+    // strategy. Note that processing is only done on the subset of the
+    // RenderPass output that contributes to the result.
+    using skia::ImageOperations;
+    const bool is_downscale_in_both_dimensions =
+        request->scale_to().x() < request->scale_from().x() &&
+        request->scale_to().y() < request->scale_from().y();
+    const ImageOperations::ResizeMethod method =
+        is_downscale_in_both_dimensions ? ImageOperations::RESIZE_BETTER
+                                        : ImageOperations::RESIZE_BEST;
+    bitmap = ImageOperations::Resize(
+        render_pass_output, method, scaled_output_size.width(),
+        scaled_output_size.height(),
+        SkIRect{result_rect.x(), result_rect.y(), result_rect.right(),
+                result_rect.bottom()});
+  } else /* if (!request->is_scaled()) */ {
+    result_rect = request->area();
+    if (result_rect.IsEmpty())
+      return;
+    const gfx::Rect window_copy_rect = MoveFromDrawToWindowSpace(result_rect);
+    bitmap.allocPixels(SkImageInfo::MakeN32Premul(
+        window_copy_rect.width(), window_copy_rect.height(),
+        current_canvas_->imageInfo().refColorSpace()));
+    if (!current_canvas_->readPixels(bitmap, window_copy_rect.x(),
+                                     window_copy_rect.y()))
+      return;
+  }
 
   request->SendResult(
-      std::make_unique<CopyOutputSkBitmapResult>(copy_rect, bitmap));
+      std::make_unique<CopyOutputSkBitmapResult>(result_rect, bitmap));
 }
 
 void SoftwareRenderer::SetEnableDCLayers(bool enable) {
diff --git a/components/viz/service/display/software_renderer_unittest.cc b/components/viz/service/display/software_renderer_unittest.cc
index 53106f60..c3c51e3 100644
--- a/components/viz/service/display/software_renderer_unittest.cc
+++ b/components/viz/service/display/software_renderer_unittest.cc
@@ -14,10 +14,12 @@
 #include "cc/test/fake_output_surface_client.h"
 #include "cc/test/fake_resource_provider.h"
 #include "cc/test/geometry_test_utils.h"
+#include "cc/test/pixel_test_utils.h"
 #include "cc/test/render_pass_test_utils.h"
 #include "cc/test/test_shared_bitmap_manager.h"
 #include "components/viz/common/frame_sinks/copy_output_request.h"
 #include "components/viz/common/frame_sinks/copy_output_result.h"
+#include "components/viz/common/frame_sinks/copy_output_util.h"
 #include "components/viz/common/quads/compositor_frame_metadata.h"
 #include "components/viz/common/quads/render_pass.h"
 #include "components/viz/common/quads/render_pass_draw_quad.h"
@@ -448,5 +450,160 @@
   EXPECT_EQ(gfx::RectF(2, 2, 3, 3), device->clip_rect_at_end());
 }
 
+class SoftwareRendererScaledCopyOutputTest
+    : public SoftwareRendererTest,
+      public testing::WithParamInterface<std::tuple<int, int, int, int>> {};
+
+// This tests that copy requests requesting scaled results execute correctly.
+// The test procedure creates a scene similar to the wall art that can be found
+// in the stairwell of a certain Google office building: A white "background"
+// (W=white) and four blocks of different colors (r=red, g=green, b=blue,
+// y=yellow).
+//
+//   WWWWWWWWWWWWWWWWWWWWWWWW
+//   WWWWWWWWWWWWWWWWWWWWWWWW
+//   WWWWrrrrWWWWWWWWggggWWWW
+//   WWWWrrrrWWWWWWWWggggWWWW
+//   WWWWWWWWWWWWWWWWWWWWWWWW
+//   WWWWWWWWWWWWWWWWWWWWWWWW
+//   WWWWbbbbWWWWWWWWyyyyWWWW
+//   WWWWbbbbWWWWWWWWyyyyWWWW
+//   WWWWWWWWWWWWWWWWWWWWWWWW
+//   WWWWWWWWWWWWWWWWWWWWWWWW
+//
+// The scene is drawn, which also causes the copy request to execute. Then, the
+// resulting bitmap is compared against an expected bitmap.
+TEST_P(SoftwareRendererScaledCopyOutputTest, ScaledCopyOfDrawnFrame) {
+  constexpr gfx::Size viewport_size = gfx::Size(24, 10);
+  constexpr int x_block = 4;
+  constexpr int y_block = 2;
+  constexpr SkColor smaller_pass_colors[4] = {SK_ColorRED, SK_ColorGREEN,
+                                              SK_ColorBLUE, SK_ColorYELLOW};
+  constexpr SkColor root_pass_color = SK_ColorWHITE;
+
+  // Test parameters: The scaling ratios for the copy requests.
+  const gfx::Vector2d scale_from(std::get<0>(GetParam()),
+                                 std::get<1>(GetParam()));
+  const gfx::Vector2d scale_to(std::get<2>(GetParam()),
+                               std::get<3>(GetParam()));
+
+  InitializeRenderer(base::WrapUnique(new SoftwareOutputDevice));
+  RenderPassList list;
+
+  // Create the render passes drawn on top of the root render pass.
+  RenderPass* smaller_passes[4];
+  gfx::Rect smaller_pass_rects[4];
+  int pass_id = 5;
+  for (int i = 0; i < 4; ++i, --pass_id) {
+    smaller_pass_rects[i] =
+        gfx::Rect(i % 2 == 0 ? x_block : (viewport_size.width() - 2 * x_block),
+                  i / 2 == 0 ? y_block : (viewport_size.height() - 2 * y_block),
+                  x_block, y_block);
+    smaller_passes[i] = AddRenderPass(&list, pass_id, smaller_pass_rects[i],
+                                      gfx::Transform(), cc::FilterOperations());
+    cc::AddQuad(smaller_passes[i], smaller_pass_rects[i],
+                smaller_pass_colors[i]);
+  }
+
+  // Create the root render pass and add all the child passes to it.
+  RenderPass* root_pass =
+      cc::AddRenderPass(&list, pass_id, gfx::Rect(viewport_size),
+                        gfx::Transform(), cc::FilterOperations());
+  for (int i = 0; i < 4; ++i)
+    cc::AddRenderPassQuad(root_pass, smaller_passes[i]);
+  cc::AddQuad(root_pass, gfx::Rect(viewport_size), root_pass_color);
+
+  renderer()->DecideRenderPassAllocationsForFrame(list);
+
+  // Make a copy request and execute it by drawing a frame. A subset of the
+  // viewport is requested, to test that scaled offsets are being computed
+  // correctly as well.
+  const gfx::Rect copy_rect(x_block, y_block,
+                            viewport_size.width() - 2 * x_block,
+                            viewport_size.height() - 2 * y_block);
+  std::unique_ptr<CopyOutputResult> result;
+  {
+    base::RunLoop loop;
+    std::unique_ptr<CopyOutputRequest> request(new CopyOutputRequest(
+        CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+        base::BindOnce(
+            [](std::unique_ptr<CopyOutputResult>* test_result,
+               const base::Closure& quit_closure,
+               std::unique_ptr<CopyOutputResult> result_from_renderer) {
+              *test_result = std::move(result_from_renderer);
+              quit_closure.Run();
+            },
+            &result, loop.QuitClosure())));
+    request->set_area(copy_rect);
+    request->SetScaleRatio(scale_from, scale_to);
+    list.back()->copy_requests.push_back(std::move(request));
+    renderer()->DrawFrame(&list, 1.0f, viewport_size);
+    loop.Run();
+  }
+
+  // Check that the result succeeded and provides a bitmap of the expected size.
+  const gfx::Rect expected_result_rect =
+      copy_output::ComputeResultRect(copy_rect, scale_from, scale_to);
+  EXPECT_EQ(expected_result_rect, result->rect());
+  const SkBitmap result_bitmap = result->AsSkBitmap();
+  ASSERT_TRUE(result_bitmap.readyToDraw());
+  ASSERT_EQ(expected_result_rect.width(), result_bitmap.width());
+  ASSERT_EQ(expected_result_rect.height(), result_bitmap.height());
+
+  // Create the "expected result" bitmap.
+  SkBitmap expected_bitmap;
+  expected_bitmap.allocN32Pixels(expected_result_rect.width(),
+                                 expected_result_rect.height());
+  expected_bitmap.eraseColor(root_pass_color);
+  for (int i = 0; i < 4; ++i) {
+    gfx::Rect rect = smaller_pass_rects[i] - copy_rect.OffsetFromOrigin();
+    rect = copy_output::ComputeResultRect(rect, scale_from, scale_to);
+    expected_bitmap.erase(
+        smaller_pass_colors[i],
+        SkIRect{rect.x(), rect.y(), rect.right(), rect.bottom()});
+  }
+
+  // Do an approximate comparison of the result bitmap to the expected one to
+  // confirm the position and size of the color values in the result is correct.
+  // Allow for pixel values to be a bit off: The scaler algorithms are not using
+  // a naïve box filter, and so will blend things together at edge boundaries.
+  int num_bad_pixels = 0;
+  gfx::Point first_failure_position;
+  for (int y = 0; y < expected_bitmap.height(); ++y) {
+    for (int x = 0; x < expected_bitmap.width(); ++x) {
+      const SkColor expected = expected_bitmap.getColor(x, y);
+      const SkColor actual = result_bitmap.getColor(x, y);
+      const bool red_bad =
+          (SkColorGetR(expected) < 0x80) != (SkColorGetR(actual) < 0x80);
+      const bool green_bad =
+          (SkColorGetG(expected) < 0x80) != (SkColorGetG(actual) < 0x80);
+      const bool blue_bad =
+          (SkColorGetB(expected) < 0x80) != (SkColorGetB(actual) < 0x80);
+      const bool alpha_bad =
+          (SkColorGetA(expected) < 0x80) != (SkColorGetA(actual) < 0x80);
+      if (red_bad || green_bad || blue_bad || alpha_bad) {
+        if (num_bad_pixels == 0)
+          first_failure_position = gfx::Point(x, y);
+        ++num_bad_pixels;
+      }
+    }
+  }
+  EXPECT_EQ(0, num_bad_pixels)
+      << "First failure position at: " << first_failure_position.ToString()
+      << "\nExpected bitmap: " << cc::GetPNGDataUrl(expected_bitmap)
+      << "\nActual bitmap: " << cc::GetPNGDataUrl(result_bitmap);
+}
+
+INSTANTIATE_TEST_CASE_P(,
+                        SoftwareRendererScaledCopyOutputTest,
+                        ::testing::Values(std::make_tuple(1, 1, 1, 1),
+                                          std::make_tuple(1, 1, 2, 1),
+                                          std::make_tuple(1, 1, 3, 1),
+                                          std::make_tuple(1, 1, 1, 2),
+                                          std::make_tuple(1, 1, 1, 3),
+                                          std::make_tuple(2, 1, 1, 1),
+                                          std::make_tuple(1, 2, 1, 1),
+                                          std::make_tuple(2, 2, 1, 1)));
+
 }  // namespace
 }  // namespace viz
diff --git a/components/viz/service/frame_sinks/frame_eviction_manager.cc b/components/viz/service/frame_sinks/frame_eviction_manager.cc
deleted file mode 100644
index c99b119..0000000
--- a/components/viz/service/frame_sinks/frame_eviction_manager.cc
+++ /dev/null
@@ -1,168 +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/viz/service/frame_sinks/frame_eviction_manager.h"
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/memory/memory_coordinator_client_registry.h"
-#include "base/memory/memory_coordinator_proxy.h"
-#include "base/memory/memory_pressure_listener.h"
-#include "base/memory/memory_pressure_monitor.h"
-#include "base/memory/shared_memory.h"
-#include "base/sys_info.h"
-#include "build/build_config.h"
-
-namespace viz {
-namespace {
-
-const int kModeratePressurePercentage = 50;
-const int kCriticalPressurePercentage = 10;
-
-}  // namespace
-
-FrameEvictionManager* FrameEvictionManager::GetInstance() {
-  return base::Singleton<FrameEvictionManager>::get();
-}
-
-void FrameEvictionManager::AddFrame(FrameEvictionManagerClient* frame,
-                                    bool locked) {
-  RemoveFrame(frame);
-  if (locked)
-    locked_frames_[frame] = 1;
-  else
-    unlocked_frames_.push_front(frame);
-  CullUnlockedFrames(GetMaxNumberOfSavedFrames());
-}
-
-void FrameEvictionManager::RemoveFrame(FrameEvictionManagerClient* frame) {
-  std::map<FrameEvictionManagerClient*, size_t>::iterator locked_iter =
-      locked_frames_.find(frame);
-  if (locked_iter != locked_frames_.end())
-    locked_frames_.erase(locked_iter);
-  unlocked_frames_.remove(frame);
-}
-
-void FrameEvictionManager::LockFrame(FrameEvictionManagerClient* frame) {
-  std::list<FrameEvictionManagerClient*>::iterator unlocked_iter =
-      std::find(unlocked_frames_.begin(), unlocked_frames_.end(), frame);
-  if (unlocked_iter != unlocked_frames_.end()) {
-    DCHECK(locked_frames_.find(frame) == locked_frames_.end());
-    unlocked_frames_.remove(frame);
-    locked_frames_[frame] = 1;
-  } else {
-    DCHECK(locked_frames_.find(frame) != locked_frames_.end());
-    locked_frames_[frame]++;
-  }
-}
-
-void FrameEvictionManager::UnlockFrame(FrameEvictionManagerClient* frame) {
-  DCHECK(locked_frames_.find(frame) != locked_frames_.end());
-  size_t locked_count = locked_frames_[frame];
-  DCHECK(locked_count);
-  if (locked_count > 1) {
-    locked_frames_[frame]--;
-  } else {
-    RemoveFrame(frame);
-    unlocked_frames_.push_front(frame);
-    CullUnlockedFrames(GetMaxNumberOfSavedFrames());
-  }
-}
-
-size_t FrameEvictionManager::GetMaxNumberOfSavedFrames() const {
-  int percentage = 100;
-  auto* memory_coordinator_proxy = base::MemoryCoordinatorProxy::GetInstance();
-  if (memory_coordinator_proxy) {
-    switch (memory_coordinator_proxy->GetCurrentMemoryState()) {
-      case base::MemoryState::NORMAL:
-        percentage = 100;
-        break;
-      case base::MemoryState::THROTTLED:
-        percentage = kCriticalPressurePercentage;
-        break;
-      case base::MemoryState::SUSPENDED:
-      case base::MemoryState::UNKNOWN:
-        NOTREACHED();
-        break;
-    }
-  } else {
-    base::MemoryPressureMonitor* monitor = base::MemoryPressureMonitor::Get();
-
-    if (!monitor)
-      return max_number_of_saved_frames_;
-
-    // Until we have a global OnMemoryPressureChanged event we need to query the
-    // value from our specific pressure monitor.
-    switch (monitor->GetCurrentPressureLevel()) {
-      case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
-        percentage = 100;
-        break;
-      case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
-        percentage = kModeratePressurePercentage;
-        break;
-      case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
-        percentage = kCriticalPressurePercentage;
-        break;
-    }
-  }
-  size_t frames = (max_number_of_saved_frames_ * percentage) / 100;
-  return std::max(static_cast<size_t>(1), frames);
-}
-
-FrameEvictionManager::FrameEvictionManager()
-    : memory_pressure_listener_(new base::MemoryPressureListener(
-          base::Bind(&FrameEvictionManager::OnMemoryPressure,
-                     base::Unretained(this)))) {
-  base::MemoryCoordinatorClientRegistry::GetInstance()->Register(this);
-  max_number_of_saved_frames_ =
-#if defined(OS_ANDROID)
-      // If the amount of memory on the device is >= 3.5 GB, save up to 5
-      // frames.
-      base::SysInfo::AmountOfPhysicalMemoryMB() < 1024 * 3.5f ? 1 : 5;
-#else
-      std::min(5, 2 + (base::SysInfo::AmountOfPhysicalMemoryMB() / 256));
-#endif
-}
-
-FrameEvictionManager::~FrameEvictionManager() {}
-
-void FrameEvictionManager::CullUnlockedFrames(size_t saved_frame_limit) {
-  while (!unlocked_frames_.empty() &&
-         unlocked_frames_.size() + locked_frames_.size() > saved_frame_limit) {
-    size_t old_size = unlocked_frames_.size();
-    // Should remove self from list.
-    unlocked_frames_.back()->EvictCurrentFrame();
-    DCHECK_EQ(unlocked_frames_.size() + 1, old_size);
-  }
-}
-
-void FrameEvictionManager::OnMemoryPressure(
-    base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
-  switch (memory_pressure_level) {
-    case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
-      PurgeMemory(kModeratePressurePercentage);
-      break;
-    case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
-      PurgeMemory(kCriticalPressurePercentage);
-      break;
-    case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
-      // No need to change anything when there is no pressure.
-      return;
-  }
-}
-
-void FrameEvictionManager::OnPurgeMemory() {
-  PurgeMemory(kCriticalPressurePercentage);
-}
-
-void FrameEvictionManager::PurgeMemory(int percentage) {
-  int saved_frame_limit = max_number_of_saved_frames_;
-  if (saved_frame_limit <= 1)
-    return;
-  CullUnlockedFrames(std::max(1, (saved_frame_limit * percentage) / 100));
-}
-
-}  // namespace viz
diff --git a/components/viz/service/frame_sinks/frame_eviction_manager.h b/components/viz/service/frame_sinks/frame_eviction_manager.h
deleted file mode 100644
index 81b9212..0000000
--- a/components/viz/service/frame_sinks/frame_eviction_manager.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_VIZ_SERVICE_FRAME_SINKS_FRAME_EVICTION_MANAGER_H_
-#define COMPONENTS_VIZ_SERVICE_FRAME_SINKS_FRAME_EVICTION_MANAGER_H_
-
-#include <stddef.h>
-
-#include <list>
-#include <map>
-
-#include "base/macros.h"
-#include "base/memory/memory_coordinator_client.h"
-#include "base/memory/memory_pressure_listener.h"
-#include "base/memory/singleton.h"
-#include "components/viz/service/viz_service_export.h"
-
-namespace viz {
-
-class VIZ_SERVICE_EXPORT FrameEvictionManagerClient {
- public:
-  virtual ~FrameEvictionManagerClient() {}
-  virtual void EvictCurrentFrame() = 0;
-};
-
-// This class is responsible for globally managing which renderers keep their
-// compositor frame when offscreen. We actively discard compositor frames for
-// offscreen tabs, but keep a minimum amount, as an LRU cache, to make switching
-// between a small set of tabs faster. The limit is a soft limit, because
-// clients can lock their frame to prevent it from being discarded, e.g. if the
-// tab is visible, or while capturing a screenshot.
-class VIZ_SERVICE_EXPORT FrameEvictionManager
-    : public base::MemoryCoordinatorClient {
- public:
-  static FrameEvictionManager* GetInstance();
-
-  void AddFrame(FrameEvictionManagerClient*, bool locked);
-  void RemoveFrame(FrameEvictionManagerClient*);
-  void LockFrame(FrameEvictionManagerClient*);
-  void UnlockFrame(FrameEvictionManagerClient*);
-
-  size_t GetMaxNumberOfSavedFrames() const;
-
-  // For testing only
-  void set_max_number_of_saved_frames(size_t max_number_of_saved_frames) {
-    max_number_of_saved_frames_ = max_number_of_saved_frames;
-  }
-
-  // React on memory pressure events to adjust the number of cached frames.
-  // Please make this private when crbug.com/443824 has been fixed.
-  void OnMemoryPressure(
-      base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
-
- private:
-  FrameEvictionManager();
-  ~FrameEvictionManager() override;
-
-  // base::MemoryCoordinatorClient implementation:
-  void OnPurgeMemory() override;
-
-  void CullUnlockedFrames(size_t saved_frame_limit);
-
-  void PurgeMemory(int percentage);
-
-  friend struct base::DefaultSingletonTraits<FrameEvictionManager>;
-
-  // Listens for system under pressure notifications and adjusts number of
-  // cached frames accordingly.
-  std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
-
-  std::map<FrameEvictionManagerClient*, size_t> locked_frames_;
-  std::list<FrameEvictionManagerClient*> unlocked_frames_;
-  size_t max_number_of_saved_frames_;
-
-  DISALLOW_COPY_AND_ASSIGN(FrameEvictionManager);
-};
-
-}  // namespace viz
-
-#endif  // COMPONENTS_VIZ_SERVICE_FRAME_SINKS_FRAME_EVICTION_MANAGER_H_
diff --git a/components/viz/service/frame_sinks/frame_evictor.cc b/components/viz/service/frame_sinks/frame_evictor.cc
deleted file mode 100644
index 086f9fc..0000000
--- a/components/viz/service/frame_sinks/frame_evictor.cc
+++ /dev/null
@@ -1,56 +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/viz/service/frame_sinks/frame_evictor.h"
-
-#include "base/logging.h"
-
-namespace viz {
-
-FrameEvictor::FrameEvictor(FrameEvictorClient* client)
-    : client_(client), has_frame_(false), visible_(false) {}
-
-FrameEvictor::~FrameEvictor() {
-  DiscardedFrame();
-}
-
-void FrameEvictor::SwappedFrame(bool visible) {
-  visible_ = visible;
-  has_frame_ = true;
-  FrameEvictionManager::GetInstance()->AddFrame(this, visible);
-}
-
-void FrameEvictor::DiscardedFrame() {
-  FrameEvictionManager::GetInstance()->RemoveFrame(this);
-  has_frame_ = false;
-}
-
-void FrameEvictor::SetVisible(bool visible) {
-  if (visible_ == visible)
-    return;
-  visible_ = visible;
-  if (has_frame_) {
-    if (visible) {
-      LockFrame();
-    } else {
-      UnlockFrame();
-    }
-  }
-}
-
-void FrameEvictor::LockFrame() {
-  DCHECK(has_frame_);
-  FrameEvictionManager::GetInstance()->LockFrame(this);
-}
-
-void FrameEvictor::UnlockFrame() {
-  DCHECK(has_frame_);
-  FrameEvictionManager::GetInstance()->UnlockFrame(this);
-}
-
-void FrameEvictor::EvictCurrentFrame() {
-  client_->EvictDelegatedFrame();
-}
-
-}  // namespace viz
diff --git a/components/viz/service/frame_sinks/frame_evictor.h b/components/viz/service/frame_sinks/frame_evictor.h
deleted file mode 100644
index be6ef5d..0000000
--- a/components/viz/service/frame_sinks/frame_evictor.h
+++ /dev/null
@@ -1,46 +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_VIZ_SERVICE_FRAME_SINKS_FRAME_EVICTOR_H_
-#define COMPONENTS_VIZ_SERVICE_FRAME_SINKS_FRAME_EVICTOR_H_
-
-#include "base/macros.h"
-#include "components/viz/service/frame_sinks/frame_eviction_manager.h"
-#include "components/viz/service/viz_service_export.h"
-
-namespace viz {
-
-class VIZ_SERVICE_EXPORT FrameEvictorClient {
- public:
-  virtual ~FrameEvictorClient() {}
-  virtual void EvictDelegatedFrame() = 0;
-};
-
-class VIZ_SERVICE_EXPORT FrameEvictor : public FrameEvictionManagerClient {
- public:
-  // |client| must outlive |this|.
-  explicit FrameEvictor(FrameEvictorClient* client);
-  ~FrameEvictor() override;
-
-  void SwappedFrame(bool visible);
-  void DiscardedFrame();
-  void SetVisible(bool visible);
-  void LockFrame();
-  void UnlockFrame();
-  bool HasFrame() { return has_frame_; }
-
- private:
-  // FrameEvictionManagerClient implementation.
-  void EvictCurrentFrame() override;
-
-  FrameEvictorClient* client_;
-  bool has_frame_;
-  bool visible_;
-
-  DISALLOW_COPY_AND_ASSIGN(FrameEvictor);
-};
-
-}  // namespace viz
-
-#endif  // COMPONENTS_VIZ_SERVICE_FRAME_SINKS_FRAME_EVICTOR_H_
diff --git a/components/viz/test/data/mask_as_blending_circle.png b/components/viz/test/data/mask_as_blending_circle.png
new file mode 100644
index 0000000..c697c52
--- /dev/null
+++ b/components/viz/test/data/mask_as_blending_circle.png
Binary files differ
diff --git a/components/viz/test/data/mask_as_blending_circle_underflow.png b/components/viz/test/data/mask_as_blending_circle_underflow.png
new file mode 100644
index 0000000..38ff04bb
--- /dev/null
+++ b/components/viz/test/data/mask_as_blending_circle_underflow.png
Binary files differ
diff --git a/components/viz/test/data/mask_as_blending_noop.png b/components/viz/test/data/mask_as_blending_noop.png
new file mode 100644
index 0000000..494c0091
--- /dev/null
+++ b/components/viz/test/data/mask_as_blending_noop.png
Binary files differ
diff --git a/components/viz/test/data/mask_as_blending_rotated_circle.png b/components/viz/test/data/mask_as_blending_rotated_circle.png
new file mode 100644
index 0000000..75b15de
--- /dev/null
+++ b/components/viz/test/data/mask_as_blending_rotated_circle.png
Binary files differ
diff --git a/components/viz/test/data/mask_as_blending_rotated_circle_underflow.png b/components/viz/test/data/mask_as_blending_rotated_circle_underflow.png
new file mode 100644
index 0000000..f74995d
--- /dev/null
+++ b/components/viz/test/data/mask_as_blending_rotated_circle_underflow.png
Binary files differ
diff --git a/components/zoom/zoom_controller.cc b/components/zoom/zoom_controller.cc
index 0242a35..e1b07f6 100644
--- a/components/zoom/zoom_controller.cc
+++ b/components/zoom/zoom_controller.cc
@@ -10,6 +10,7 @@
 #include "content/public/browser/navigation_details.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
@@ -142,12 +143,11 @@
   event_data_.reset(new ZoomChangedEventData(web_contents(), GetZoomLevel(),
                                              zoom_level, zoom_mode_,
                                              false /* can_show_bubble */));
-  int render_process_id = web_contents()->GetRenderProcessHost()->GetID();
-  int render_view_id = web_contents()->GetRenderViewHost()->GetRoutingID();
+  int process_id = web_contents()->GetRenderViewHost()->GetProcess()->GetID();
+  int view_id = web_contents()->GetRenderViewHost()->GetRoutingID();
   if (zoom_mode_ == ZOOM_MODE_ISOLATED ||
-      zoom_map->UsesTemporaryZoomLevel(render_process_id, render_view_id)) {
-    zoom_map->SetTemporaryZoomLevel(render_process_id, render_view_id,
-                                    zoom_level);
+      zoom_map->UsesTemporaryZoomLevel(process_id, view_id)) {
+    zoom_map->SetTemporaryZoomLevel(process_id, view_id, zoom_level);
   } else {
     if (!entry) {
       last_client_ = NULL;
@@ -173,8 +173,8 @@
   content::HostZoomMap* zoom_map =
       content::HostZoomMap::GetForWebContents(web_contents());
   DCHECK(zoom_map);
-  int render_process_id = web_contents()->GetRenderProcessHost()->GetID();
-  int render_view_id = web_contents()->GetRenderViewHost()->GetRoutingID();
+  int process_id = web_contents()->GetRenderViewHost()->GetProcess()->GetID();
+  int view_id = web_contents()->GetRenderViewHost()->GetRoutingID();
   double original_zoom_level = GetZoomLevel();
 
   DCHECK(!event_data_);
@@ -199,7 +199,7 @@
           double origin_zoom_level =
               zoom_map->GetZoomLevelForHostAndScheme(url.scheme(), host);
           event_data_->new_zoom_level = origin_zoom_level;
-          zoom_map->SetTemporaryZoomLevel(render_process_id, render_view_id,
+          zoom_map->SetTemporaryZoomLevel(process_id, view_id,
                                           origin_zoom_level);
         } else {
           // The host will need a level prior to removing the temporary level.
@@ -209,7 +209,7 @@
         }
       }
       // Remove per-tab zoom data for this tab. No event callback expected.
-      zoom_map->ClearTemporaryZoomLevel(render_process_id, render_view_id);
+      zoom_map->ClearTemporaryZoomLevel(process_id, view_id);
       break;
     }
     case ZOOM_MODE_ISOLATED: {
@@ -217,7 +217,7 @@
       // page needs an initial isolated zoom back to the same level it was at
       // in the other mode.
       if (zoom_mode_ != ZOOM_MODE_DISABLED) {
-        zoom_map->SetTemporaryZoomLevel(render_process_id, render_view_id,
+        zoom_map->SetTemporaryZoomLevel(process_id, view_id,
                                         original_zoom_level);
       } else {
         // When we don't call any HostZoomMap set functions, we send the event
@@ -233,7 +233,7 @@
       // page needs to be resized to the default zoom. While in manual mode,
       // the zoom level is handled independently.
       if (zoom_mode_ != ZOOM_MODE_DISABLED) {
-        zoom_map->SetTemporaryZoomLevel(render_process_id, render_view_id,
+        zoom_map->SetTemporaryZoomLevel(process_id, view_id,
                                         GetDefaultZoomLevel());
         zoom_level_ = original_zoom_level;
       } else {
@@ -249,8 +249,7 @@
       // The page needs to be zoomed back to default before disabling the zoom
       double new_zoom_level = GetDefaultZoomLevel();
       event_data_->new_zoom_level = new_zoom_level;
-      zoom_map->SetTemporaryZoomLevel(render_process_id, render_view_id,
-                                      new_zoom_level);
+      zoom_map->SetTemporaryZoomLevel(process_id, view_id, new_zoom_level);
       break;
     }
   }
@@ -264,8 +263,8 @@
   if (zoom_mode_ != ZOOM_MODE_ISOLATED && zoom_mode_ != ZOOM_MODE_MANUAL)
     return;
 
-  int render_process_id = web_contents()->GetRenderProcessHost()->GetID();
-  int render_view_id = web_contents()->GetRenderViewHost()->GetRoutingID();
+  int process_id = web_contents()->GetRenderViewHost()->GetProcess()->GetID();
+  int view_id = web_contents()->GetRenderViewHost()->GetRoutingID();
   content::HostZoomMap* zoom_map =
       content::HostZoomMap::GetForWebContents(web_contents());
   zoom_level_ = zoom_map->GetDefaultZoomLevel();
@@ -281,7 +280,7 @@
   // Note: it's possible the render_process/view ids have disappeared (e.g.
   // if we navigated to a new origin), but this won't cause a problem in the
   // call below.
-  zoom_map->ClearTemporaryZoomLevel(render_process_id, render_view_id);
+  zoom_map->ClearTemporaryZoomLevel(process_id, view_id);
   zoom_mode_ = ZOOM_MODE_DEFAULT;
 }
 
@@ -369,10 +368,9 @@
 }
 
 void ZoomController::SetPageScaleFactorIsOneForTesting(bool is_one) {
-  int render_process_id = web_contents()->GetRenderProcessHost()->GetID();
-  int render_view_id = web_contents()->GetRenderViewHost()->GetRoutingID();
-  host_zoom_map_->SetPageScaleFactorIsOneForView(render_process_id,
-                                                 render_view_id, is_one);
+  int process_id = web_contents()->GetRenderViewHost()->GetProcess()->GetID();
+  int view_id = web_contents()->GetRenderViewHost()->GetRoutingID();
+  host_zoom_map_->SetPageScaleFactorIsOneForView(process_id, view_id, is_one);
 }
 
 bool ZoomController::PageScaleFactorIsOne() const {
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 80ad5d32..d9c3a1f 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -52,6 +52,7 @@
     "//components/tracing:startup_tracing",
     "//components/url_formatter",
     "//components/variations",
+    "//components/viz/client",
     "//components/viz/common",
     "//components/viz/host",
     "//components/viz/service",
@@ -238,6 +239,8 @@
     "accessibility/accessibility_tree_formatter.h",
     "accessibility/accessibility_tree_formatter_blink.cc",
     "accessibility/accessibility_tree_formatter_blink.h",
+    "accessibility/accessibility_tree_formatter_browser.cc",
+    "accessibility/accessibility_tree_formatter_browser.h",
     "accessibility/accessibility_tree_formatter_mac.mm",
     "accessibility/accessibility_tree_formatter_stub.cc",
     "accessibility/accessibility_tree_formatter_utils_win.cc",
diff --git a/content/browser/accessibility/accessibility_tree_formatter.cc b/content/browser/accessibility/accessibility_tree_formatter.cc
index 6a37b87..7e80f8d 100644
--- a/content/browser/accessibility/accessibility_tree_formatter.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter.cc
@@ -29,7 +29,6 @@
 const int kIndentSymbolCount = 2;
 const char kSkipString[] = "@NO_DUMP";
 const char kSkipChildren[] = "@NO_CHILDREN_DUMP";
-const char kChildrenDictAttr[] = "children";
 
 }  // namespace
 
@@ -40,36 +39,12 @@
 AccessibilityTreeFormatter::~AccessibilityTreeFormatter() {
 }
 
-std::unique_ptr<base::DictionaryValue>
-AccessibilityTreeFormatter::BuildAccessibilityTree(BrowserAccessibility* root) {
-  CHECK(root);
-  std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
-  RecursiveBuildAccessibilityTree(*root, dict.get());
-  return dict;
-}
-
 void AccessibilityTreeFormatter::FormatAccessibilityTree(
     BrowserAccessibility* root, base::string16* contents) {
   std::unique_ptr<base::DictionaryValue> dict = BuildAccessibilityTree(root);
   RecursiveFormatAccessibilityTree(*(dict.get()), contents);
 }
 
-void AccessibilityTreeFormatter::RecursiveBuildAccessibilityTree(
-    const BrowserAccessibility& node, base::DictionaryValue* dict) {
-  AddProperties(node, dict);
-
-  auto children = base::MakeUnique<base::ListValue>();
-
-  for (size_t i = 0; i < ChildCount(node); ++i) {
-    BrowserAccessibility* child_node = GetChild(node, i);
-    std::unique_ptr<base::DictionaryValue> child_dict(
-        new base::DictionaryValue);
-    RecursiveBuildAccessibilityTree(*child_node, child_dict.get());
-    children->Append(std::move(child_dict));
-  }
-  dict->Set(kChildrenDictAttr, std::move(children));
-}
-
 void AccessibilityTreeFormatter::RecursiveFormatAccessibilityTree(
     const base::DictionaryValue& dict, base::string16* contents, int depth) {
   base::string16 indent = base::string16(depth * kIndentSymbolCount,
@@ -102,17 +77,6 @@
   filters_ = filters;
 }
 
-uint32_t AccessibilityTreeFormatter::ChildCount(
-    const BrowserAccessibility& node) const {
-  return node.PlatformChildCount();
-}
-
-BrowserAccessibility* AccessibilityTreeFormatter::GetChild(
-    const BrowserAccessibility& node,
-    uint32_t i) const {
-  return node.PlatformGetChild(i);
-}
-
 // static
 bool AccessibilityTreeFormatter::MatchesFilters(
     const std::vector<Filter>& filters,
diff --git a/content/browser/accessibility/accessibility_tree_formatter.h b/content/browser/accessibility/accessibility_tree_formatter.h
index d9804ee2..71a78995 100644
--- a/content/browser/accessibility/accessibility_tree_formatter.h
+++ b/content/browser/accessibility/accessibility_tree_formatter.h
@@ -17,6 +17,10 @@
 #include "content/browser/accessibility/browser_accessibility.h"
 #include "content/common/content_export.h"
 
+namespace {
+const char kChildrenDictAttr[] = "children";
+}
+
 namespace content {
 
 // A utility class for formatting platform-specific accessibility information,
@@ -71,8 +75,8 @@
   //     "children": [ ]
   //   } ]
   // }
-  std::unique_ptr<base::DictionaryValue> BuildAccessibilityTree(
-      BrowserAccessibility* root);
+  virtual std::unique_ptr<base::DictionaryValue> BuildAccessibilityTree(
+      BrowserAccessibility* root) = 0;
 
   // Dumps a BrowserAccessibility tree into a string.
   void FormatAccessibilityTree(
@@ -115,15 +119,6 @@
   // Overridden by platform subclasses.
   //
 
-  virtual uint32_t ChildCount(const BrowserAccessibility& node) const;
-
-  virtual BrowserAccessibility* GetChild(const BrowserAccessibility& node,
-                                         uint32_t i) const;
-
-  // Add the attributes for each node into the given dict.
-  virtual void AddProperties(const BrowserAccessibility& node,
-                             base::DictionaryValue* dict) = 0;
-
   // Returns a platform specific representation of a BrowserAccessibility.
   virtual base::string16 ToString(const base::DictionaryValue& node) = 0;
 
@@ -150,8 +145,6 @@
   void RecursiveFormatAccessibilityTree(const BrowserAccessibility& node,
                                         base::string16* contents,
                                         int indent);
-  void RecursiveBuildAccessibilityTree(const BrowserAccessibility& node,
-                                       base::DictionaryValue* tree_node);
   void RecursiveFormatAccessibilityTree(const base::DictionaryValue& tree_node,
                                         base::string16* contents,
                                         int depth = 0);
diff --git a/content/browser/accessibility/accessibility_tree_formatter_android.cc b/content/browser/accessibility/accessibility_tree_formatter_android.cc
index eb7f6fb..1d4b55d 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_android.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_android.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/accessibility/accessibility_tree_formatter.h"
+#include "content/browser/accessibility/accessibility_tree_formatter_browser.h"
 
 #include <string>
 
@@ -71,7 +71,8 @@
 
 }  // namespace
 
-class AccessibilityTreeFormatterAndroid : public AccessibilityTreeFormatter {
+class AccessibilityTreeFormatterAndroid
+    : public AccessibilityTreeFormatterBrowser {
  public:
   AccessibilityTreeFormatterAndroid();
   ~AccessibilityTreeFormatterAndroid() override;
diff --git a/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc b/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
index 65b9f696..a0507f27 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/accessibility/accessibility_tree_formatter.h"
+#include "content/browser/accessibility/accessibility_tree_formatter_browser.h"
 
 #include <atk/atk.h>
 
@@ -19,7 +19,8 @@
 
 namespace content {
 
-class AccessibilityTreeFormatterAuraLinux : public AccessibilityTreeFormatter {
+class AccessibilityTreeFormatterAuraLinux
+    : public AccessibilityTreeFormatterBrowser {
  public:
   explicit AccessibilityTreeFormatterAuraLinux();
   ~AccessibilityTreeFormatterAuraLinux() override;
diff --git a/content/browser/accessibility/accessibility_tree_formatter_blink.cc b/content/browser/accessibility/accessibility_tree_formatter_blink.cc
index 1c1c81a..d4d9d34b 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_blink.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_blink.cc
@@ -21,8 +21,7 @@
 namespace content {
 
 AccessibilityTreeFormatterBlink::AccessibilityTreeFormatterBlink()
-    : AccessibilityTreeFormatter() {
-}
+    : AccessibilityTreeFormatterBrowser() {}
 
 AccessibilityTreeFormatterBlink::~AccessibilityTreeFormatterBlink() {
 }
@@ -30,6 +29,9 @@
 const char* const TREE_DATA_ATTRIBUTES[] = {"TreeData.textSelStartOffset",
                                             "TreeData.textSelEndOffset"};
 
+const char* STATE_FOCUSED = "focused";
+const char* STATE_OFFSCREEN = "offscreen";
+
 uint32_t AccessibilityTreeFormatterBlink::ChildCount(
     const BrowserAccessibility& node) const {
   if (node.HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID))
@@ -152,15 +154,13 @@
   for (int state_index = ui::AX_STATE_NONE;
        state_index <= ui::AX_STATE_LAST;
        ++state_index) {
-    if (state_index == ui::AX_STATE_OFFSCREEN)
-      continue;
     auto state = static_cast<ui::AXState>(state_index);
     if (node.HasState(state))
       dict->SetBoolean(ui::ToString(state), true);
   }
 
   if (offscreen)
-    dict->SetBoolean(ui::ToString(ui::AX_STATE_OFFSCREEN), true);
+    dict->SetBoolean(STATE_OFFSCREEN, true);
 
   for (int attr_index = ui::AX_STRING_ATTRIBUTE_NONE;
        attr_index <= ui::AX_STRING_ATTRIBUTE_LAST;
@@ -267,6 +267,15 @@
     WriteAttribute(false, ui::ToString(state), &line);
   }
 
+  // Offscreen and Focused states are not in the state list.
+  bool value = false;
+  dict.GetBoolean(STATE_OFFSCREEN, &value);
+  if (value)
+    WriteAttribute(false, STATE_OFFSCREEN, &line);
+  dict.GetBoolean(STATE_FOCUSED, &value);
+  if (value)
+    WriteAttribute(false, STATE_FOCUSED, &line);
+
   WriteAttribute(false,
                  FormatCoordinates("location", "boundsX", "boundsY", dict),
                  &line);
diff --git a/content/browser/accessibility/accessibility_tree_formatter_blink.h b/content/browser/accessibility/accessibility_tree_formatter_blink.h
index 1a5e0cd..d31190d 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_blink.h
+++ b/content/browser/accessibility/accessibility_tree_formatter_blink.h
@@ -7,12 +7,12 @@
 
 #include <stdint.h>
 
-#include "content/browser/accessibility/accessibility_tree_formatter.h"
+#include "content/browser/accessibility/accessibility_tree_formatter_browser.h"
 
 namespace content {
 
 class CONTENT_EXPORT AccessibilityTreeFormatterBlink
-    : public AccessibilityTreeFormatter {
+    : public AccessibilityTreeFormatterBrowser {
  public:
   explicit AccessibilityTreeFormatterBlink();
   ~AccessibilityTreeFormatterBlink() override;
diff --git a/content/browser/accessibility/accessibility_tree_formatter_browser.cc b/content/browser/accessibility/accessibility_tree_formatter_browser.cc
new file mode 100644
index 0000000..17412d3
--- /dev/null
+++ b/content/browser/accessibility/accessibility_tree_formatter_browser.cc
@@ -0,0 +1,48 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/accessibility/accessibility_tree_formatter_browser.h"
+
+#include "base/memory/ptr_util.h"
+
+namespace content {
+
+std::unique_ptr<base::DictionaryValue>
+AccessibilityTreeFormatterBrowser::BuildAccessibilityTree(
+    BrowserAccessibility* root) {
+  CHECK(root);
+  std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
+  RecursiveBuildAccessibilityTree(*root, dict.get());
+  return dict;
+}
+
+void AccessibilityTreeFormatterBrowser::RecursiveBuildAccessibilityTree(
+    const BrowserAccessibility& node,
+    base::DictionaryValue* dict) {
+  AddProperties(node, dict);
+
+  auto children = base::MakeUnique<base::ListValue>();
+
+  for (size_t i = 0; i < ChildCount(node); ++i) {
+    BrowserAccessibility* child_node = GetChild(node, i);
+    std::unique_ptr<base::DictionaryValue> child_dict(
+        new base::DictionaryValue);
+    RecursiveBuildAccessibilityTree(*child_node, child_dict.get());
+    children->Append(std::move(child_dict));
+  }
+  dict->Set(kChildrenDictAttr, std::move(children));
+}
+
+uint32_t AccessibilityTreeFormatterBrowser::ChildCount(
+    const BrowserAccessibility& node) const {
+  return node.PlatformChildCount();
+}
+
+BrowserAccessibility* AccessibilityTreeFormatterBrowser::GetChild(
+    const BrowserAccessibility& node,
+    uint32_t i) const {
+  return node.PlatformGetChild(i);
+}
+
+}  // namespace content
diff --git a/content/browser/accessibility/accessibility_tree_formatter_browser.h b/content/browser/accessibility/accessibility_tree_formatter_browser.h
new file mode 100644
index 0000000..9e153ba
--- /dev/null
+++ b/content/browser/accessibility/accessibility_tree_formatter_browser.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_TREE_FORMATTER_BROWSER_H_
+#define CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_TREE_FORMATTER_BROWSER_H_
+
+#include "content/browser/accessibility/accessibility_tree_formatter.h"
+
+#include "base/macros.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "content/browser/accessibility/browser_accessibility.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Inheritable class for tree formatters that rely on browser infrastructure for
+// walking the tree and getting properties. Tree formatters that walk native
+// objects should not inherit from this class.
+class CONTENT_EXPORT AccessibilityTreeFormatterBrowser
+    : public AccessibilityTreeFormatter {
+ public:
+  std::unique_ptr<base::DictionaryValue> BuildAccessibilityTree(
+      BrowserAccessibility* root) override;
+
+ protected:
+  void RecursiveBuildAccessibilityTree(const BrowserAccessibility& node,
+                                       base::DictionaryValue* dict);
+  virtual uint32_t ChildCount(const BrowserAccessibility& node) const;
+
+  virtual BrowserAccessibility* GetChild(const BrowserAccessibility& node,
+                                         uint32_t i) const;
+
+  // Add the attributes for each node into the given dict.
+  virtual void AddProperties(const BrowserAccessibility& node,
+                             base::DictionaryValue* dict) = 0;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_TREE_FORMATTER_BROWSER_H_
diff --git a/content/browser/accessibility/accessibility_tree_formatter_mac.mm b/content/browser/accessibility/accessibility_tree_formatter_mac.mm
index 607d882..810f354c0 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_mac.mm
+++ b/content/browser/accessibility/accessibility_tree_formatter_mac.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/accessibility/accessibility_tree_formatter.h"
+#include "content/browser/accessibility/accessibility_tree_formatter_browser.h"
 
 #import <Cocoa/Cocoa.h>
 
@@ -204,7 +204,7 @@
 
 }  // namespace
 
-class AccessibilityTreeFormatterMac : public AccessibilityTreeFormatter {
+class AccessibilityTreeFormatterMac : public AccessibilityTreeFormatterBrowser {
  public:
   explicit AccessibilityTreeFormatterMac();
   ~AccessibilityTreeFormatterMac() override;
diff --git a/content/browser/accessibility/accessibility_tree_formatter_stub.cc b/content/browser/accessibility/accessibility_tree_formatter_stub.cc
index 4fae96e..72e9af1 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_stub.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_stub.cc
@@ -3,11 +3,12 @@
 // found in the LICENSE file.
 
 #include "base/strings/string_number_conversions.h"
-#include "content/browser/accessibility/accessibility_tree_formatter.h"
+#include "content/browser/accessibility/accessibility_tree_formatter_browser.h"
 
 namespace content {
 
-class AccessibilityTreeFormatterStub : public AccessibilityTreeFormatter {
+class AccessibilityTreeFormatterStub
+    : public AccessibilityTreeFormatterBrowser {
  public:
   explicit AccessibilityTreeFormatterStub();
   ~AccessibilityTreeFormatterStub() override;
@@ -30,8 +31,7 @@
 #endif
 
 AccessibilityTreeFormatterStub::AccessibilityTreeFormatterStub()
-    : AccessibilityTreeFormatter() {
-}
+    : AccessibilityTreeFormatterBrowser() {}
 
 AccessibilityTreeFormatterStub::~AccessibilityTreeFormatterStub() {
 }
diff --git a/content/browser/accessibility/accessibility_tree_formatter_win.cc b/content/browser/accessibility/accessibility_tree_formatter_win.cc
index fc0d733..25fc4d4 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_win.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_win.cc
@@ -21,6 +21,7 @@
 #include "base/values.h"
 #include "base/win/scoped_bstr.h"
 #include "base/win/scoped_comptr.h"
+#include "base/win/scoped_variant.h"
 #include "content/browser/accessibility/accessibility_tree_formatter_utils_win.h"
 #include "content/browser/accessibility/browser_accessibility_manager.h"
 #include "content/browser/accessibility/browser_accessibility_win.h"
@@ -35,13 +36,46 @@
   AccessibilityTreeFormatterWin();
   ~AccessibilityTreeFormatterWin() override;
 
+  std::unique_ptr<base::DictionaryValue> BuildAccessibilityTree(
+      BrowserAccessibility* start) override;
+  std::unique_ptr<base::DictionaryValue> BuildAccessibilityTree(
+      base::win::ScopedComPtr<IAccessible> start,
+      LONG window_x = 0,
+      LONG window_y = 0);
+
  private:
+  void RecursiveBuildAccessibilityTree(
+      const base::win::ScopedComPtr<IAccessible> node,
+      base::DictionaryValue* dict,
+      LONG root_x,
+      LONG root_y);
+
   const base::FilePath::StringType GetExpectedFileSuffix() override;
   const std::string GetAllowEmptyString() override;
   const std::string GetAllowString() override;
   const std::string GetDenyString() override;
-  void AddProperties(const BrowserAccessibility& node,
-                     base::DictionaryValue* dict) override;
+  void AddProperties(const base::win::ScopedComPtr<IAccessible>,
+                     base::DictionaryValue* dict,
+                     LONG root_x,
+                     LONG root_y);
+  void AddMSAAProperties(const base::win::ScopedComPtr<IAccessible>,
+                         base::DictionaryValue* dict,
+                         LONG root_x,
+                         LONG root_y);
+  void AddSimpleDOMNodeProperties(const base::win::ScopedComPtr<IAccessible>,
+                                  base::DictionaryValue* dict);
+  bool AddIA2Properties(const base::win::ScopedComPtr<IAccessible>,
+                        base::DictionaryValue* dict);
+  void AddIA2ActionProperties(const base::win::ScopedComPtr<IAccessible>,
+                              base::DictionaryValue* dict);
+  void AddIA2HypertextProperties(const base::win::ScopedComPtr<IAccessible>,
+                                 base::DictionaryValue* dict);
+  void AddIA2TextProperties(const base::win::ScopedComPtr<IAccessible>,
+                            base::DictionaryValue* dict);
+  void AddIA2TableProperties(const base::win::ScopedComPtr<IAccessible>,
+                             base::DictionaryValue* dict);
+  void AddIA2ValueProperties(const base::win::ScopedComPtr<IAccessible>,
+                             base::DictionaryValue* dict);
   base::string16 ToString(const base::DictionaryValue& node) override;
 };
 
@@ -57,13 +91,157 @@
 AccessibilityTreeFormatterWin::~AccessibilityTreeFormatterWin() {
 }
 
+static HRESULT QuerySimpleDOMNode(IAccessible* accessible,
+                                  ISimpleDOMNode** simple_dom_node) {
+  // IA2 Spec dictates that IServiceProvider should be used instead of
+  // QueryInterface when retrieving IAccessible2.
+  base::win::ScopedComPtr<IServiceProvider> service_provider;
+  HRESULT hr = accessible->QueryInterface(service_provider.GetAddressOf());
+  if (FAILED(hr))
+    return hr;
+  return service_provider->QueryService(IID_ISimpleDOMNode, simple_dom_node);
+}
+
+static HRESULT QueryIAccessible2(IAccessible* accessible,
+                                 IAccessible2** accessible2) {
+  // IA2 Spec dictates that IServiceProvider should be used instead of
+  // QueryInterface when retrieving IAccessible2.
+  base::win::ScopedComPtr<IServiceProvider> service_provider;
+  HRESULT hr = accessible->QueryInterface(service_provider.GetAddressOf());
+  if (FAILED(hr))
+    return hr;
+  return service_provider->QueryService(IID_IAccessible2, accessible2);
+}
+
+static HRESULT QueryIAccessibleAction(IAccessible* accessible,
+                                      IAccessibleAction** accessibleAction) {
+  // IA2 Spec dictates that IServiceProvider should be used instead of
+  // QueryInterface when retrieving alternate interfaces.
+  base::win::ScopedComPtr<IServiceProvider> service_provider;
+  HRESULT hr = accessible->QueryInterface(service_provider.GetAddressOf());
+  if (FAILED(hr))
+    return hr;
+
+  return service_provider->QueryService(IID_IAccessibleAction,
+                                        accessibleAction);
+}
+
+static HRESULT QueryIAccessibleHypertext(
+    IAccessible* accessible,
+    IAccessibleHypertext** accessibleHypertext) {
+  // IA2 Spec dictates that IServiceProvider should be used instead of
+  // QueryInterface when retrieving alternate interfaces.
+  base::win::ScopedComPtr<IServiceProvider> service_provider;
+  HRESULT hr = accessible->QueryInterface(service_provider.GetAddressOf());
+  if (FAILED(hr))
+    return hr;
+  return service_provider->QueryService(IID_IAccessibleHypertext,
+                                        accessibleHypertext);
+}
+
+static HRESULT QueryIAccessibleTable(IAccessible* accessible,
+                                     IAccessibleTable** accessibleTable) {
+  // IA2 Spec dictates that IServiceProvider should be used instead of
+  // QueryInterface when retrieving alternate interfaces.
+  base::win::ScopedComPtr<IServiceProvider> service_provider;
+  HRESULT hr = accessible->QueryInterface(service_provider.GetAddressOf());
+  if (FAILED(hr))
+    return hr;
+  return service_provider->QueryService(IID_IAccessibleTable, accessibleTable);
+}
+
+static HRESULT QueryIAccessibleText(IAccessible* accessible,
+                                    IAccessibleText** accessibleText) {
+  // IA2 Spec dictates that IServiceProvider should be used instead of
+  // QueryInterface when retrieving alternate interfaces.
+  base::win::ScopedComPtr<IServiceProvider> service_provider;
+  HRESULT hr = accessible->QueryInterface(service_provider.GetAddressOf());
+  if (FAILED(hr))
+    return hr;
+  return service_provider->QueryService(IID_IAccessibleText, accessibleText);
+}
+
+static HRESULT QueryIAccessibleValue(IAccessible* accessible,
+                                     IAccessibleValue** accessibleValue) {
+  // IA2 Spec dictates that IServiceProvider should be used instead of
+  // QueryInterface when retrieving alternate interfaces.
+  base::win::ScopedComPtr<IServiceProvider> service_provider;
+  HRESULT hr = accessible->QueryInterface(service_provider.GetAddressOf());
+  if (FAILED(hr))
+    return hr;
+  return service_provider->QueryService(IID_IAccessibleValue, accessibleValue);
+}
+
+std::unique_ptr<base::DictionaryValue>
+AccessibilityTreeFormatterWin::BuildAccessibilityTree(
+    BrowserAccessibility* start_node) {
+  DCHECK(start_node);
+
+  VARIANT variant_self;
+  variant_self.vt = VT_I4;
+  variant_self.lVal = CHILDID_SELF;
+  LONG root_x, root_y, root_width, root_height;
+  BrowserAccessibility* root =
+      start_node->manager()->GetRootManager()->GetRoot();
+  HRESULT hr = ToBrowserAccessibilityWin(root)->GetCOM()->accLocation(
+      &root_x, &root_y, &root_width, &root_height, variant_self);
+  DCHECK(SUCCEEDED(hr));
+
+  base::win::ScopedComPtr<IAccessible> start_ia =
+      ToBrowserAccessibilityComWin(start_node);
+
+  return BuildAccessibilityTree(start_ia, root_x, root_y);
+}
+
+std::unique_ptr<base::DictionaryValue>
+AccessibilityTreeFormatterWin::BuildAccessibilityTree(
+    base::win::ScopedComPtr<IAccessible> start,
+    LONG root_x,
+    LONG root_y) {
+  CHECK(start);
+
+  std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
+  RecursiveBuildAccessibilityTree(start, dict.get(), root_x, root_y);
+
+  return dict;
+}
+
+void AccessibilityTreeFormatterWin::RecursiveBuildAccessibilityTree(
+    const base::win::ScopedComPtr<IAccessible> node,
+    base::DictionaryValue* dict,
+    LONG root_x,
+    LONG root_y) {
+  AddProperties(node, dict, root_x, root_y);
+
+  auto children = base::MakeUnique<base::ListValue>();
+
+  LONG child_count;
+  if (S_OK != node->get_accChildCount(&child_count))
+    return;
+
+  for (int index = 1; index <= child_count; ++index) {
+    base::win::ScopedVariant childid_index(index);
+    base::win::ScopedComPtr<IDispatch> child_dispatch;
+    base::win::ScopedComPtr<IAccessible> child_accessible;
+    if (S_OK ==
+            node->get_accChild(childid_index, child_dispatch.GetAddressOf()) &&
+        S_OK == child_dispatch.CopyTo(child_accessible.GetAddressOf())) {
+      std::unique_ptr<base::DictionaryValue> child_dict(
+          new base::DictionaryValue);
+      RecursiveBuildAccessibilityTree(child_accessible, child_dict.get(),
+                                      root_x, root_y);
+      children->Append(std::move(child_dict));
+    }
+  }
+  dict->Set(kChildrenDictAttr, std::move(children));
+}
+
 const char* const ALL_ATTRIBUTES[] = {
     "name",
     "value",
     "states",
     "attributes",
     "text_attributes",
-    "role_name",
     "ia2_hypertext",
     "currentValue",
     "minimumValue",
@@ -92,224 +270,113 @@
     "inner_html",
 };
 
-namespace {
-
-base::string16 GetIA2Hypertext(BrowserAccessibilityWin& ax_object) {
-  base::win::ScopedBstr text_bstr;
-  HRESULT hr;
-
-  hr = ax_object.GetCOM()->get_text(0, IA2_TEXT_OFFSET_LENGTH,
-                                    text_bstr.Receive());
-  if (FAILED(hr))
-    return base::string16();
-
-  base::string16 ia2_hypertext(text_bstr, text_bstr.Length());
-  // IA2 Spec calls embedded objects hyperlinks. We stick to embeds for clarity.
-  LONG number_of_embeds;
-  hr = ax_object.GetCOM()->get_nHyperlinks(&number_of_embeds);
-  if (FAILED(hr) || number_of_embeds == 0)
-    return ia2_hypertext;
-
-  // Replace all embedded characters with the child indices of the accessibility
-  // objects they refer to.
-  base::string16 embedded_character(
-      1, BrowserAccessibilityComWin::kEmbeddedCharacter);
-  size_t character_index = 0;
-  size_t hypertext_index = 0;
-  while (hypertext_index < ia2_hypertext.length()) {
-    if (ia2_hypertext[hypertext_index] !=
-        BrowserAccessibilityComWin::kEmbeddedCharacter) {
-      ++character_index;
-      ++hypertext_index;
-      continue;
-    }
-
-    LONG index_of_embed;
-    hr = ax_object.GetCOM()->get_hyperlinkIndex(character_index,
-                                                &index_of_embed);
-    // S_FALSE will be returned if no embedded object is found at the given
-    // embedded character offset. Exclude child index from such cases.
-    LONG child_index = -1;
-    if (hr == S_OK) {
-      DCHECK_GE(index_of_embed, 0);
-      base::win::ScopedComPtr<IAccessibleHyperlink> embedded_object;
-      hr = ax_object.GetCOM()->get_hyperlink(index_of_embed,
-                                             embedded_object.GetAddressOf());
-      DCHECK(SUCCEEDED(hr));
-      base::win::ScopedComPtr<IAccessible2> ax_embed;
-      hr = embedded_object.CopyTo(ax_embed.GetAddressOf());
-      DCHECK(SUCCEEDED(hr));
-      hr = ax_embed->get_indexInParent(&child_index);
-      DCHECK(SUCCEEDED(hr));
-    }
-
-    base::string16 child_index_str(L"<obj");
-    if (child_index >= 0) {
-      base::StringAppendF(&child_index_str, L"%d>", child_index);
-    } else {
-      base::StringAppendF(&child_index_str, L">");
-    }
-    base::ReplaceFirstSubstringAfterOffset(&ia2_hypertext, hypertext_index,
-        embedded_character, child_index_str);
-    ++character_index;
-    hypertext_index += child_index_str.length();
-    --number_of_embeds;
+void AccessibilityTreeFormatterWin::AddProperties(
+    const base::win::ScopedComPtr<IAccessible> node,
+    base::DictionaryValue* dict,
+    LONG root_x,
+    LONG root_y) {
+  AddMSAAProperties(node, dict, root_x, root_y);
+  AddSimpleDOMNodeProperties(node, dict);
+  if (AddIA2Properties(node, dict)) {
+    AddIA2ActionProperties(node, dict);
+    AddIA2HypertextProperties(node, dict);
+    AddIA2TableProperties(node, dict);
+    AddIA2TextProperties(node, dict);
+    AddIA2ValueProperties(node, dict);
   }
-  DCHECK_EQ(number_of_embeds, 0);
-
-  return ia2_hypertext;
 }
 
-}  // namespace
-
-void AccessibilityTreeFormatterWin::AddProperties(
-    const BrowserAccessibility& node, base::DictionaryValue* dict) {
-  dict->SetInteger("id", node.GetId());
-  BrowserAccessibilityWin* ax_object =
-      ToBrowserAccessibilityWin(const_cast<BrowserAccessibility*>(&node));
-  DCHECK(ax_object);
-
+void AccessibilityTreeFormatterWin::AddMSAAProperties(
+    const base::win::ScopedComPtr<IAccessible> node,
+    base::DictionaryValue* dict,
+    LONG root_x,
+    LONG root_y) {
   VARIANT variant_self;
   variant_self.vt = VT_I4;
   variant_self.lVal = CHILDID_SELF;
 
-  long ia2_role = 0;
-  if (SUCCEEDED(ax_object->GetCOM()->role(&ia2_role))) {
-    dict->SetString("role", IAccessible2RoleToString(ia2_role));
+  base::win::ScopedBstr temp_bstr;
+
+  LONG ia_role = 0;
+  VARIANT ia_role_variant;
+  if (SUCCEEDED(node->get_accRole(variant_self, &ia_role_variant))) {
+    if (ia_role_variant.vt == VT_I4) {
+      ia_role = ia_role_variant.lVal;
+      dict->SetString("role", IAccessible2RoleToString(ia_role));
+    } else if (ia_role_variant.vt == VT_BSTR) {
+      dict->SetString("role", base::string16(ia_role_variant.bstrVal));
+    }
   }
 
-  base::win::ScopedBstr temp_bstr;
   // If S_FALSE it means there is no name
-  if (S_OK ==
-      ax_object->GetCOM()->get_accName(variant_self, temp_bstr.Receive())) {
+  if (S_OK == node->get_accName(variant_self, temp_bstr.Receive())) {
     base::string16 name = base::string16(temp_bstr, temp_bstr.Length());
 
     // Ignore a JAWS workaround where the name of a document is " ".
-    if (name != L" " || ia2_role != ROLE_SYSTEM_DOCUMENT)
+    if (name != L" " || ia_role != ROLE_SYSTEM_DOCUMENT)
       dict->SetString("name", name);
   }
   temp_bstr.Reset();
 
-  if (SUCCEEDED(
-          ax_object->GetCOM()->get_accValue(variant_self, temp_bstr.Receive())))
+  if (SUCCEEDED(node->get_accValue(variant_self, temp_bstr.Receive())))
     dict->SetString("value", base::string16(temp_bstr, temp_bstr.Length()));
   temp_bstr.Reset();
 
-  std::vector<base::string16> state_strings;
-
   int32_t ia_state = 0;
   VARIANT ia_state_variant;
-  if (ax_object->GetCOM()->get_accState(variant_self, &ia_state_variant) ==
-          S_OK &&
+  if (node->get_accState(variant_self, &ia_state_variant) == S_OK &&
       ia_state_variant.vt == VT_I4) {
     ia_state = ia_state_variant.intVal;
-  }
 
-  // Avoid flakiness: these states depend on whether the window is focused
-  // and the position of the mouse cursor.
-  ia_state &= ~STATE_SYSTEM_HOTTRACKED;
-  ia_state &= ~STATE_SYSTEM_OFFSCREEN;
+    if (true /* reduced_flakiness_mode_ */) {  // TODO
+      // Avoid flakiness: these states depend on whether the window is focused
+      // and the position of the mouse cursor.
+      ia_state &= ~STATE_SYSTEM_HOTTRACKED;
+      ia_state &= ~STATE_SYSTEM_OFFSCREEN;
 
-  // For testing, having the focused state may also cause flakiness if the
-  // window isn't in the foreground.
-  ia_state &= ~STATE_SYSTEM_FOCUSED;
+      // For testing, having the focused state may also cause flakiness if the
+      // window isn't in the foreground.
+      ia_state &= ~STATE_SYSTEM_FOCUSED;
+    }
 
-  AccessibleStates states;
-  if (ax_object->GetCOM()->get_states(&states) == S_OK) {
+    std::vector<base::string16> state_strings;
     IAccessibleStateToStringVector(ia_state, &state_strings);
-    IAccessible2StateToStringVector(states, &state_strings);
     std::unique_ptr<base::ListValue> states(new base::ListValue());
-    for (const base::string16& state_string : state_strings)
-      states->AppendString(base::UTF16ToUTF8(state_string));
+    states->AppendStrings(state_strings);
     dict->Set("states", std::move(states));
   }
 
-  if (ax_object->GetCOM()->get_attributes(temp_bstr.Receive()) == S_OK) {
-    // get_attributes() returns a semicolon delimited string. Turn it into a
-    // ListValue
-    std::vector<base::string16> ia2_attributes = base::SplitString(
-        base::string16(temp_bstr, temp_bstr.Length()), base::string16(1, ';'),
-        base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
-
-    std::unique_ptr<base::ListValue> attributes(new base::ListValue());
-    for (const base::string16& ia2_attribute : ia2_attributes)
-      attributes->AppendString(base::UTF16ToUTF8(ia2_attribute));
-    dict->Set("attributes", std::move(attributes));
-  }
-  temp_bstr.Reset();
-
-  ax_object->GetCOM()->ComputeStylesIfNeeded();
-  const std::map<int, std::vector<base::string16>>& ia2_text_attributes =
-      ax_object->GetCOM()->offset_to_text_attributes();
-  std::unique_ptr<base::ListValue> text_attributes(new base::ListValue());
-  for (const auto& style_span : ia2_text_attributes) {
-    int start_offset = style_span.first;
-    text_attributes->AppendString("offset:" + base::IntToString(start_offset));
-    for (const base::string16& text_attribute : style_span.second)
-      text_attributes->AppendString(base::UTF16ToUTF8(text_attribute));
-  }
-  dict->Set("text_attributes", std::move(text_attributes));
-
-  dict->SetString("role_name", ax_object->GetCOM()->role_name());
-  dict->SetString("ia2_hypertext", GetIA2Hypertext(*ax_object));
-
-  VARIANT currentValue;
-  if (ax_object->GetCOM()->get_currentValue(&currentValue) == S_OK)
-    dict->SetDouble("currentValue", V_R8(&currentValue));
-
-  VARIANT minimumValue;
-  if (ax_object->GetCOM()->get_minimumValue(&minimumValue) == S_OK)
-    dict->SetDouble("minimumValue", V_R8(&minimumValue));
-
-  VARIANT maximumValue;
-  if (ax_object->GetCOM()->get_maximumValue(&maximumValue) == S_OK)
-    dict->SetDouble("maximumValue", V_R8(&maximumValue));
-
-  if (SUCCEEDED(ax_object->GetCOM()->get_accDescription(variant_self,
-                                                        temp_bstr.Receive()))) {
+  if (SUCCEEDED(node->get_accDescription(variant_self, temp_bstr.Receive()))) {
     dict->SetString("description", base::string16(temp_bstr,
         temp_bstr.Length()));
   }
   temp_bstr.Reset();
 
   // |get_accDefaultAction| returns a localized string.
-  if (SUCCEEDED(ax_object->GetCOM()->get_accDefaultAction(
-          variant_self, temp_bstr.Receive()))) {
+  if (SUCCEEDED(
+          node->get_accDefaultAction(variant_self, temp_bstr.Receive()))) {
     dict->SetString("default_action", base::string16(temp_bstr,
         temp_bstr.Length()));
   }
   temp_bstr.Reset();
 
-  // |IAccessibleAction::get_name| returns a localized string.
-  if (SUCCEEDED(ax_object->GetCOM()->get_name(0 /* action_index */,
-                                              temp_bstr.Receive()))) {
-    dict->SetString("action_name",
-                    base::string16(temp_bstr, temp_bstr.Length()));
-  }
-  temp_bstr.Reset();
-
-  if (SUCCEEDED(ax_object->GetCOM()->get_accKeyboardShortcut(
-          variant_self, temp_bstr.Receive()))) {
+  if (SUCCEEDED(
+          node->get_accKeyboardShortcut(variant_self, temp_bstr.Receive()))) {
     dict->SetString("keyboard_shortcut", base::string16(temp_bstr,
         temp_bstr.Length()));
   }
   temp_bstr.Reset();
 
-  if (SUCCEEDED(
-          ax_object->GetCOM()->get_accHelp(variant_self, temp_bstr.Receive())))
+  if (SUCCEEDED(node->get_accHelp(variant_self, temp_bstr.Receive())))
     dict->SetString("help", base::string16(temp_bstr, temp_bstr.Length()));
+
   temp_bstr.Reset();
 
-  BrowserAccessibility* root = node.manager()->GetRootManager()->GetRoot();
-  LONG left, top, width, height;
-  LONG root_left, root_top, root_width, root_height;
-  if (SUCCEEDED(ax_object->GetCOM()->accLocation(&left, &top, &width, &height,
-                                                 variant_self)) &&
-      SUCCEEDED(ToBrowserAccessibilityWin(root)->GetCOM()->accLocation(
-          &root_left, &root_top, &root_width, &root_height, variant_self))) {
+  LONG x, y, width, height;
+  if (SUCCEEDED(node->accLocation(&x, &y, &width, &height, variant_self))) {
     auto location = base::MakeUnique<base::DictionaryValue>();
-    location->SetInteger("x", left - root_left);
-    location->SetInteger("y", top - root_top);
+    location->SetInteger("x", x - root_x);
+    location->SetInteger("y", y - root_y);
     dict->Set("location", std::move(location));
 
     auto size = base::MakeUnique<base::DictionaryValue>();
@@ -317,85 +384,283 @@
     size->SetInteger("height", height);
     dict->Set("size", std::move(size));
   }
+}
 
-  LONG index_in_parent;
-  if (SUCCEEDED(ax_object->GetCOM()->get_indexInParent(&index_in_parent)))
-    dict->SetInteger("index_in_parent", index_in_parent);
+void AccessibilityTreeFormatterWin::AddSimpleDOMNodeProperties(
+    const base::win::ScopedComPtr<IAccessible> node,
+    base::DictionaryValue* dict) {
+  base::win::ScopedComPtr<ISimpleDOMNode> simple_dom_node;
 
-  LONG n_relations;
-  if (SUCCEEDED(ax_object->GetCOM()->get_nRelations(&n_relations)))
-    dict->SetInteger("n_relations", n_relations);
+  if (S_OK != QuerySimpleDOMNode(node.Get(), simple_dom_node.GetAddressOf()))
+    return;  // No IA2Value, we are finished with this node.
 
-  LONG group_level, similar_items_in_group, position_in_group;
-  // |GetGroupPosition| returns S_FALSE when no grouping information is
-  // available so avoid using |SUCCEEDED|.
-  if (ax_object->GetCOM()->get_groupPosition(
-          &group_level, &similar_items_in_group, &position_in_group) == S_OK) {
-    dict->SetInteger("group_level", group_level);
-    dict->SetInteger("similar_items_in_group", similar_items_in_group);
-    dict->SetInteger("position_in_group", position_in_group);
-  }
+  base::win::ScopedBstr temp_bstr;
 
-  LONG table_rows;
-  if (SUCCEEDED(ax_object->GetCOM()->get_nRows(&table_rows)))
-    dict->SetInteger("table_rows", table_rows);
-
-  LONG table_columns;
-  if (SUCCEEDED(ax_object->GetCOM()->get_nRows(&table_columns)))
-    dict->SetInteger("table_columns", table_columns);
-
-  LONG row_index;
-  if (SUCCEEDED(ax_object->GetCOM()->get_rowIndex(&row_index)))
-    dict->SetInteger("row_index", row_index);
-
-  LONG column_index;
-  if (SUCCEEDED(ax_object->GetCOM()->get_columnIndex(&column_index)))
-    dict->SetInteger("column_index", column_index);
-
-  LONG n_characters;
-  if (SUCCEEDED(ax_object->GetCOM()->get_nCharacters(&n_characters)))
-    dict->SetInteger("n_characters", n_characters);
-
-  LONG caret_offset;
-  if (ax_object->GetCOM()->get_caretOffset(&caret_offset) == S_OK)
-    dict->SetInteger("caret_offset", caret_offset);
-
-  LONG n_selections;
-  if (SUCCEEDED(ax_object->GetCOM()->get_nSelections(&n_selections))) {
-    dict->SetInteger("n_selections", n_selections);
-    if (n_selections > 0) {
-      LONG start, end;
-      if (SUCCEEDED(ax_object->GetCOM()->get_selection(0, &start, &end))) {
-        dict->SetInteger("selection_start", start);
-        dict->SetInteger("selection_end", end);
-      }
-    }
-  }
-
-  if (SUCCEEDED(ax_object->GetCOM()->get_localizedExtendedRole(
-          temp_bstr.Receive()))) {
-    dict->SetString("localized_extended_role", base::string16(temp_bstr,
-        temp_bstr.Length()));
-  }
-  temp_bstr.Reset();
-
-  if (SUCCEEDED(ax_object->GetCOM()->get_innerHTML(temp_bstr.Receive()))) {
+  if (SUCCEEDED(simple_dom_node->get_innerHTML(temp_bstr.Receive()))) {
     dict->SetString("inner_html",
                     base::string16(temp_bstr, temp_bstr.Length()));
   }
   temp_bstr.Reset();
 }
 
+bool AccessibilityTreeFormatterWin::AddIA2Properties(
+    const base::win::ScopedComPtr<IAccessible> node,
+    base::DictionaryValue* dict) {
+  base::win::ScopedComPtr<IAccessible2> ia2;
+  if (S_OK != QueryIAccessible2(node.Get(), ia2.GetAddressOf()))
+    return false;  // No IA2, we are finished with this node.
+
+  LONG ia2_role = 0;
+  if (SUCCEEDED(ia2->role(&ia2_role))) {
+    dict->SetKey("msaa_legacy_role", dict->Clone());
+    // Overwrite MSAA role which is more limited.
+    dict->SetString("role", IAccessible2RoleToString(ia2_role));
+  }
+
+  std::vector<base::string16> state_strings;
+  AccessibleStates states;
+  if (ia2->get_states(&states) == S_OK) {
+    IAccessible2StateToStringVector(states, &state_strings);
+    // Append IA2 state list to MSAA state
+    base::ListValue* states_list;
+    if (dict->GetList("states", &states_list))
+      states_list->AppendStrings(state_strings);
+  }
+
+  base::win::ScopedBstr temp_bstr;
+
+  if (ia2->get_attributes(temp_bstr.Receive()) == S_OK) {
+    // get_attributes() returns a semicolon delimited string. Turn it into a
+    // ListValue
+    std::vector<base::string16> ia2_attributes = base::SplitString(
+        base::string16(temp_bstr, temp_bstr.Length()), base::string16(1, ';'),
+        base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
+
+    std::unique_ptr<base::ListValue> attributes(new base::ListValue());
+    attributes->AppendStrings(ia2_attributes);
+    dict->Set("attributes", std::move(attributes));
+  }
+  temp_bstr.Reset();
+
+  LONG index_in_parent;
+  if (SUCCEEDED(ia2->get_indexInParent(&index_in_parent)))
+    dict->SetInteger("index_in_parent", index_in_parent);
+
+  LONG n_relations;
+  if (SUCCEEDED(ia2->get_nRelations(&n_relations)))
+    dict->SetInteger("n_relations", n_relations);
+
+  LONG group_level, similar_items_in_group, position_in_group;
+  // |GetGroupPosition| returns S_FALSE when no grouping information is
+  // available so avoid using |SUCCEEDED|.
+  if (ia2->get_groupPosition(&group_level, &similar_items_in_group,
+                             &position_in_group) == S_OK) {
+    dict->SetInteger("group_level", group_level);
+    dict->SetInteger("similar_items_in_group", similar_items_in_group);
+    dict->SetInteger("position_in_group", position_in_group);
+  }
+
+  if (SUCCEEDED(ia2->get_localizedExtendedRole(temp_bstr.Receive()))) {
+    dict->SetString("localized_extended_role",
+                    base::string16(temp_bstr, temp_bstr.Length()));
+  }
+  temp_bstr.Reset();
+
+  return true;
+}
+
+void AccessibilityTreeFormatterWin::AddIA2ActionProperties(
+    const base::win::ScopedComPtr<IAccessible> node,
+    base::DictionaryValue* dict) {
+  base::win::ScopedComPtr<IAccessibleAction> ia2action;
+  if (S_OK != QueryIAccessibleAction(node.Get(), ia2action.GetAddressOf()))
+    return;  // No IA2Value, we are finished with this node.
+
+  base::win::ScopedBstr temp_bstr;
+
+  // |IAccessibleAction::get_name| returns a localized string.
+  if (SUCCEEDED(
+          ia2action->get_name(0 /* action_index */, temp_bstr.Receive()))) {
+    dict->SetString("action_name",
+                    base::string16(temp_bstr, temp_bstr.Length()));
+  }
+}
+
+void AccessibilityTreeFormatterWin::AddIA2HypertextProperties(
+    base::win::ScopedComPtr<IAccessible> node,
+    base::DictionaryValue* dict) {
+  base::win::ScopedComPtr<IAccessibleHypertext> ia2hyper;
+  if (S_OK != QueryIAccessibleHypertext(node.Get(), ia2hyper.GetAddressOf()))
+    return;  // No IA2, we are finished with this node
+
+  base::win::ScopedBstr text_bstr;
+  HRESULT hr;
+
+  hr = ia2hyper->get_text(0, IA2_TEXT_OFFSET_LENGTH, text_bstr.Receive());
+  if (FAILED(hr))
+    return;
+
+  base::string16 ia2_hypertext(text_bstr, text_bstr.Length());
+  // IA2 Spec calls embedded objects hyperlinks. We stick to embeds for clarity.
+  LONG number_of_embeds;
+  hr = ia2hyper->get_nHyperlinks(&number_of_embeds);
+  if (SUCCEEDED(hr) && number_of_embeds > 0) {
+    // Replace all embedded characters with the child indices of the
+    // accessibility objects they refer to.
+    base::string16 embedded_character(
+        1, BrowserAccessibilityComWin::kEmbeddedCharacter);
+    size_t character_index = 0;
+    size_t hypertext_index = 0;
+    while (hypertext_index < ia2_hypertext.length()) {
+      if (ia2_hypertext[hypertext_index] !=
+          BrowserAccessibilityComWin::kEmbeddedCharacter) {
+        ++character_index;
+        ++hypertext_index;
+        continue;
+      }
+
+      LONG index_of_embed;
+      hr = ia2hyper->get_hyperlinkIndex(character_index, &index_of_embed);
+      // S_FALSE will be returned if no embedded object is found at the given
+      // embedded character offset. Exclude child index from such cases.
+      LONG child_index = -1;
+      if (hr == S_OK) {
+        DCHECK_GE(index_of_embed, 0);
+        base::win::ScopedComPtr<IAccessibleHyperlink> embedded_object;
+        hr = ia2hyper->get_hyperlink(index_of_embed,
+                                     embedded_object.GetAddressOf());
+        DCHECK(SUCCEEDED(hr));
+        base::win::ScopedComPtr<IAccessible2> ax_embed;
+        hr = embedded_object.CopyTo(ax_embed.GetAddressOf());
+        DCHECK(SUCCEEDED(hr));
+        hr = ax_embed->get_indexInParent(&child_index);
+        DCHECK(SUCCEEDED(hr));
+      }
+
+      base::string16 child_index_str(L"<obj");
+      if (child_index >= 0) {
+        base::StringAppendF(&child_index_str, L"%d>", child_index);
+      } else {
+        base::StringAppendF(&child_index_str, L">");
+      }
+      base::ReplaceFirstSubstringAfterOffset(
+          &ia2_hypertext, hypertext_index, embedded_character, child_index_str);
+      ++character_index;
+      hypertext_index += child_index_str.length();
+      --number_of_embeds;
+    }
+  }
+  DCHECK_EQ(number_of_embeds, 0);
+
+  dict->SetString("ia2_hypertext", ia2_hypertext);
+}
+
+void AccessibilityTreeFormatterWin::AddIA2TableProperties(
+    const base::win::ScopedComPtr<IAccessible> node,
+    base::DictionaryValue* dict) {
+  base::win::ScopedComPtr<IAccessibleTable> ia2table;
+  if (S_OK != QueryIAccessibleTable(node.Get(), ia2table.GetAddressOf()))
+    return;  // No IA2Text, we are finished with this node.
+
+  LONG table_rows;
+  if (SUCCEEDED(ia2table->get_nRows(&table_rows)))
+    dict->SetInteger("table_rows", table_rows);
+
+  LONG table_columns;
+  if (SUCCEEDED(ia2table->get_nColumns(&table_columns)))
+    dict->SetInteger("table_columns", table_columns);
+}
+
+void AccessibilityTreeFormatterWin::AddIA2TextProperties(
+    const base::win::ScopedComPtr<IAccessible> node,
+    base::DictionaryValue* dict) {
+  base::win::ScopedComPtr<IAccessibleText> ia2text;
+  if (S_OK != QueryIAccessibleText(node.Get(), ia2text.GetAddressOf()))
+    return;  // No IA2Text, we are finished with this node.
+
+  LONG n_characters;
+  if (SUCCEEDED(ia2text->get_nCharacters(&n_characters)))
+    dict->SetInteger("n_characters", n_characters);
+
+  LONG caret_offset;
+  if (ia2text->get_caretOffset(&caret_offset) == S_OK)
+    dict->SetInteger("caret_offset", caret_offset);
+
+  LONG n_selections;
+  if (SUCCEEDED(ia2text->get_nSelections(&n_selections))) {
+    dict->SetInteger("n_selections", n_selections);
+    if (n_selections > 0) {
+      LONG start, end;
+      if (SUCCEEDED(ia2text->get_selection(0, &start, &end))) {
+        dict->SetInteger("selection_start", start);
+        dict->SetInteger("selection_end", end);
+      }
+    }
+  }
+
+  // Handle IA2 text attributes, adding them as a list.
+  // IA2 text attributes comes formatted as a single string, as follows:
+  // https://wiki.linuxfoundation.org/accessibility/iaccessible2/textattributes
+  std::unique_ptr<base::ListValue> text_attributes(new base::ListValue());
+  LONG current_offset = 0, start_offset, end_offset;
+  while (current_offset < n_characters) {
+    // TODO(aleventhal) n_characters is not actually useful for ending the
+    // loop, because it counts embedded object characters as more than 1,
+    // meaning that it counts all the text in the subtree. However, the
+    // offsets used in other IAText methods only count the embedded object
+    // characters as 1.
+    base::win::ScopedBstr temp_bstr;
+    HRESULT hr = ia2text->get_attributes(current_offset, &start_offset,
+                                         &end_offset, temp_bstr.Receive());
+    // The below start_offset < current_offset check is needed because
+    // nCharacters is not helpful as described above.
+    // When asking for a range past the end of the string, this will occur,
+    // although it's not clear whether that's desired or whether
+    // S_FALSE or an error should be returned when the offset is out of range.
+    if (FAILED(hr) || start_offset < current_offset)
+      break;
+    // DCHECK(start_offset == current_offset);  // Always at text range start.
+    if (hr == S_OK && temp_bstr && wcslen(temp_bstr)) {
+      // Append offset:<number>.
+      base::string16 offset_str =
+          base::ASCIIToUTF16("offset:") + base::IntToString16(start_offset);
+      text_attributes->AppendString(offset_str);
+      // Append name:value pairs.
+      std::vector<base::string16> name_val_pairs =
+          SplitString(base::string16(temp_bstr), base::ASCIIToUTF16(";"),
+                      base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
+      text_attributes->AppendStrings(name_val_pairs);
+    }
+    current_offset = end_offset;
+  }
+
+  dict->Set("text_attributes", std::move(text_attributes));
+}
+
+void AccessibilityTreeFormatterWin::AddIA2ValueProperties(
+    const base::win::ScopedComPtr<IAccessible> node,
+    base::DictionaryValue* dict) {
+  base::win::ScopedComPtr<IAccessibleValue> ia2value;
+  if (S_OK != QueryIAccessibleValue(node.Get(), ia2value.GetAddressOf()))
+    return;  // No IA2Value, we are finished with this node.
+
+  VARIANT currentValue;
+  if (ia2value->get_currentValue(&currentValue) == S_OK)
+    dict->SetDouble("currentValue", V_R8(&currentValue));
+
+  VARIANT minimumValue;
+  if (ia2value->get_minimumValue(&minimumValue) == S_OK)
+    dict->SetDouble("minimumValue", V_R8(&minimumValue));
+
+  VARIANT maximumValue;
+  if (ia2value->get_maximumValue(&maximumValue) == S_OK)
+    dict->SetDouble("maximumValue", V_R8(&maximumValue));
+}
+
 base::string16 AccessibilityTreeFormatterWin::ToString(
     const base::DictionaryValue& dict) {
   base::string16 line;
 
-  if (show_ids()) {
-    int id_value;
-    dict.GetInteger("id", &id_value);
-    WriteAttribute(true, base::IntToString16(id_value), &line);
-  }
-
   base::string16 role_value;
   dict.GetString("role", &role_value);
   WriteAttribute(true, base::UTF16ToUTF8(role_value), &line);
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc
index 1612f40..94a6440 100644
--- a/content/browser/accessibility/browser_accessibility.cc
+++ b/content/browser/accessibility/browser_accessibility.cc
@@ -882,6 +882,12 @@
   return gfx::ToEnclosingRect(bounds);
 }
 
+bool BrowserAccessibility::IsOffscreen() const {
+  bool offscreen = false;
+  RelativeToAbsoluteBounds(gfx::RectF(), false, &offscreen);
+  return offscreen;
+}
+
 gfx::NativeViewAccessible BrowserAccessibility::GetNativeViewAccessible() {
   // TODO(703369) On Windows, where we have started to migrate to an
   // AXPlatformNode implementation, the BrowserAccessibilityWin subclass has
diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h
index 3ddedd3..f94f3f9 100644
--- a/content/browser/accessibility/browser_accessibility.h
+++ b/content/browser/accessibility/browser_accessibility.h
@@ -345,6 +345,7 @@
   gfx::AcceleratedWidget GetTargetForNativeAccessibilityEvent() override;
   bool AccessibilityPerformAction(const ui::AXActionData& data) override;
   bool ShouldIgnoreHoveredStateForTesting() override;
+  bool IsOffscreen() const override;
 
  protected:
   using AXPlatformPositionInstance = AXPlatformPosition::AXPositionInstance;
diff --git a/content/browser/accessibility/browser_accessibility_manager.h b/content/browser/accessibility/browser_accessibility_manager.h
index 9486d9f..9fdf2e24 100644
--- a/content/browser/accessibility/browser_accessibility_manager.h
+++ b/content/browser/accessibility/browser_accessibility_manager.h
@@ -361,9 +361,6 @@
       const std::vector<ui::AXTreeDelegate::Change>& changes) override;
 
   BrowserAccessibilityDelegate* delegate() const { return delegate_; }
-  void set_delegate(BrowserAccessibilityDelegate* delegate) {
-    delegate_ = delegate;
-  }
 
   // If this BrowserAccessibilityManager is a child frame or guest frame,
   // return the BrowserAccessibilityManager from the highest ancestor frame
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.cc b/content/browser/accessibility/browser_accessibility_manager_win.cc
index 92bd304..5e298f3 100644
--- a/content/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -96,13 +96,6 @@
   return delegate->AccessibilityGetAcceleratedWidget();
 }
 
-IAccessible* BrowserAccessibilityManagerWin::GetParentIAccessible() {
-  BrowserAccessibilityDelegate* delegate = GetDelegateFromRootManager();
-  if (!delegate)
-    return NULL;
-  return delegate->AccessibilityGetNativeViewAccessible();
-}
-
 void BrowserAccessibilityManagerWin::OnIAccessible2Used() {
   // When IAccessible2 APIs have been used elsewhere in the codebase,
   // enable basic web accessibility support. (Full screen reader support is
@@ -144,12 +137,9 @@
                              GetRoot());
   }
 
-  if (!can_fire_events &&
-      !load_complete_pending_ &&
-      event_type == ui::AX_EVENT_LOAD_COMPLETE &&
-      GetRoot() &&
-      !GetRoot()->HasState(ui::AX_STATE_OFFSCREEN) &&
-      GetRoot()->PlatformChildCount() > 0) {
+  if (!can_fire_events && !load_complete_pending_ &&
+      event_type == ui::AX_EVENT_LOAD_COMPLETE && GetRoot() &&
+      !GetRoot()->IsOffscreen() && GetRoot()->PlatformChildCount() > 0) {
     load_complete_pending_ = true;
   }
 
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.h b/content/browser/accessibility/browser_accessibility_manager_win.h
index c13c164..c00cf5d1 100644
--- a/content/browser/accessibility/browser_accessibility_manager_win.h
+++ b/content/browser/accessibility/browser_accessibility_manager_win.h
@@ -35,9 +35,6 @@
   // Get the closest containing HWND.
   HWND GetParentHWND();
 
-  // The IAccessible for the parent window.
-  IAccessible* GetParentIAccessible();
-
   // IAccessible2UsageObserver
   void OnIAccessible2Used() override;
 
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index ecbb9a34..125f399 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -1537,6 +1537,10 @@
   RunHtmlTest(FILE_PATH_LITERAL("q.html"));
 }
 
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityReplaceData) {
+  RunHtmlTest(FILE_PATH_LITERAL("replace-data.html"));
+}
+
 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityRuby) {
   RunHtmlTest(FILE_PATH_LITERAL("ruby.html"));
 }
diff --git a/content/browser/accessibility/one_shot_accessibility_tree_search.cc b/content/browser/accessibility/one_shot_accessibility_tree_search.cc
index 16694f6..468d6839 100644
--- a/content/browser/accessibility/one_shot_accessibility_tree_search.cc
+++ b/content/browser/accessibility/one_shot_accessibility_tree_search.cc
@@ -12,6 +12,7 @@
 #include "content/browser/accessibility/browser_accessibility.h"
 #include "content/browser/accessibility/browser_accessibility_manager.h"
 #include "ui/accessibility/ax_enums.h"
+#include "ui/accessibility/ax_node.h"
 #include "ui/accessibility/ax_role_properties.h"
 
 namespace content {
@@ -183,8 +184,7 @@
   }
 
   if (visible_only_) {
-    if (node->HasState(ui::AX_STATE_INVISIBLE) ||
-        node->HasState(ui::AX_STATE_OFFSCREEN)) {
+    if (node->HasState(ui::AX_STATE_INVISIBLE) || node->IsOffscreen()) {
       return false;
     }
   }
diff --git a/content/browser/accessibility/one_shot_accessibility_tree_search_unittest.cc b/content/browser/accessibility/one_shot_accessibility_tree_search_unittest.cc
index 6fc5415..fe3cbfe 100644
--- a/content/browser/accessibility/one_shot_accessibility_tree_search_unittest.cc
+++ b/content/browser/accessibility/one_shot_accessibility_tree_search_unittest.cc
@@ -54,6 +54,7 @@
   root.id = 1;
   root.SetName("Document");
   root.role = ui::AX_ROLE_ROOT_WEB_AREA;
+  root.location = gfx::RectF(0, 0, 800, 600);
   root.child_ids.push_back(2);
   root.child_ids.push_back(3);
   root.child_ids.push_back(6);
@@ -83,7 +84,7 @@
   footer.id = 6;
   footer.SetName("Footer");
   footer.role = ui::AX_ROLE_FOOTER;
-  footer.AddState(ui::AX_STATE_OFFSCREEN);
+  footer.location = gfx::RectF(0, 650, 100, 800);
 
   tree_.reset(new TestBrowserAccessibilityManager(
       MakeAXTreeUpdate(root, heading, list, list_item_1, list_item_2, footer)));
diff --git a/content/browser/android/java/gin_java_bridge_dispatcher_host.cc b/content/browser/android/java/gin_java_bridge_dispatcher_host.cc
index 55a902efa..fd3edd3e 100644
--- a/content/browser/android/java/gin_java_bridge_dispatcher_host.cc
+++ b/content/browser/android/java/gin_java_bridge_dispatcher_host.cc
@@ -47,7 +47,7 @@
 void GinJavaBridgeDispatcherHost::InstallFilterAndRegisterAllRoutingIds() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (named_objects_.empty() ||
-      !web_contents()->GetRenderProcessHost()->GetChannel()) {
+      !web_contents()->GetMainFrame()->GetProcess()->GetChannel()) {
     return;
   }
 
diff --git a/content/browser/android/java/gin_java_bridge_message_filter.cc b/content/browser/android/java/gin_java_bridge_message_filter.cc
index 4e628c8..9838877bc 100644
--- a/content/browser/android/java/gin_java_bridge_message_filter.cc
+++ b/content/browser/android/java/gin_java_bridge_message_filter.cc
@@ -87,7 +87,7 @@
 // static
 scoped_refptr<GinJavaBridgeMessageFilter> GinJavaBridgeMessageFilter::FromHost(
     GinJavaBridgeDispatcherHost* host, bool create_if_not_exists) {
-  RenderProcessHost* rph = host->web_contents()->GetRenderProcessHost();
+  RenderProcessHost* rph = host->web_contents()->GetMainFrame()->GetProcess();
   scoped_refptr<GinJavaBridgeMessageFilter> filter =
       base::UserDataAdapter<GinJavaBridgeMessageFilter>::Get(
           rph, kGinJavaBridgeMessageFilterKey);
@@ -173,7 +173,7 @@
 // static
 void GinJavaBridgeMessageFilter::RemoveFilter(
     GinJavaBridgeDispatcherHost* host) {
-  RenderProcessHost* rph = host->web_contents()->GetRenderProcessHost();
+  RenderProcessHost* rph = host->web_contents()->GetMainFrame()->GetProcess();
   rph->RemoveUserData(kGinJavaBridgeMessageFilterKey);
 }
 
diff --git a/content/browser/android/selection_popup_controller.cc b/content/browser/android/selection_popup_controller.cc
index a932b3d..68b7b5f 100644
--- a/content/browser/android/selection_popup_controller.cc
+++ b/content/browser/android/selection_popup_controller.cc
@@ -131,7 +131,16 @@
                           params.source_type == ui::MENU_SOURCE_LONG_PRESS ||
                           params.source_type == ui::MENU_SOURCE_TOUCH_HANDLE ||
                           params.source_type == ui::MENU_SOURCE_STYLUS;
-  if (!from_touch || (!params.is_editable && params.selection_text.empty()))
+
+  const bool from_selection_adjustment =
+      params.source_type == ui::MENU_SOURCE_ADJUST_SELECTION;
+
+  // If source_type is not in the list then return.
+  if (!from_touch && !from_selection_adjustment)
+    return false;
+
+  // Don't show paste pop-up for non-editable textarea.
+  if (!params.is_editable && params.selection_text.empty())
     return false;
 
   const bool can_select_all =
@@ -151,7 +160,7 @@
       params.selection_rect.right(),
       params.selection_rect.bottom() + handle_height, params.is_editable,
       is_password_type, jselected_text, can_select_all, can_edit_richly,
-      should_suggest);
+      should_suggest, from_selection_adjustment);
   return true;
 }
 
diff --git a/content/browser/appcache/appcache_url_loader_job.cc b/content/browser/appcache/appcache_url_loader_job.cc
index a69da883..0a45271 100644
--- a/content/browser/appcache/appcache_url_loader_job.cc
+++ b/content/browser/appcache/appcache_url_loader_job.cc
@@ -176,14 +176,14 @@
     network_loader_->SetPriority(priority, intra_priority_value);
 }
 
-void AppCacheURLLoaderJob::PauseCachingResponseBody() {
+void AppCacheURLLoaderJob::PauseReadingBodyFromNet() {
   if (network_loader_)
-    network_loader_->PauseCachingResponseBody();
+    network_loader_->PauseReadingBodyFromNet();
 }
 
-void AppCacheURLLoaderJob::ResumeCachingResponseBody() {
+void AppCacheURLLoaderJob::ResumeReadingBodyFromNet() {
   if (network_loader_)
-    network_loader_->ResumeCachingResponseBody();
+    network_loader_->ResumeReadingBodyFromNet();
 }
 
 void AppCacheURLLoaderJob::OnReceiveResponse(
diff --git a/content/browser/appcache/appcache_url_loader_job.h b/content/browser/appcache/appcache_url_loader_job.h
index 35eb62f5..d4da7d7 100644
--- a/content/browser/appcache/appcache_url_loader_job.h
+++ b/content/browser/appcache/appcache_url_loader_job.h
@@ -79,8 +79,8 @@
   void FollowRedirect() override;
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override;
-  void PauseCachingResponseBody() override;
-  void ResumeCachingResponseBody() override;
+  void PauseReadingBodyFromNet() override;
+  void ResumeReadingBodyFromNet() override;
 
   // mojom::URLLoaderClient implementation.
   // These methods are called by the network loader for subresource requests
diff --git a/content/browser/background_fetch/background_fetch_delegate_proxy.cc b/content/browser/background_fetch/background_fetch_delegate_proxy.cc
index bdca8fd..4543a70 100644
--- a/content/browser/background_fetch/background_fetch_delegate_proxy.cc
+++ b/content/browser/background_fetch/background_fetch_delegate_proxy.cc
@@ -46,8 +46,8 @@
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
     DCHECK(request);
 
-    // TODO(crbug/757760): This can be nullptr, is if the delegate has shut
-    // down, in which case we need to make sure this is retried when the browser
+    // TODO(crbug/757760): This can be nullptr, if the delegate has shut down,
+    // in which case we need to make sure this is retried when the browser
     // restarts.
     if (!delegate_)
       return;
@@ -108,6 +108,8 @@
   void OnDownloadComplete(
       const std::string& guid,
       std::unique_ptr<BackgroundFetchResult> result) override;
+  void OnDownloadFailed(const std::string& guid,
+                        BackgroundFetchDelegate::FailureReason reason) override;
   void OnDownloadStarted(
       const std::string& guid,
       std::unique_ptr<content::BackgroundFetchResponse> response) override;
@@ -142,6 +144,12 @@
                      io_parent_, guid, std::move(result)));
 }
 
+void BackgroundFetchDelegateProxy::Core::OnDownloadFailed(
+    const std::string& guid,
+    BackgroundFetchDelegate::FailureReason reason) {
+  // TODO(delphick): do something with this
+}
+
 void BackgroundFetchDelegateProxy::Core::OnDownloadStarted(
     const std::string& guid,
     std::unique_ptr<content::BackgroundFetchResponse> response) {
diff --git a/content/browser/background_sync/background_sync_manager_unittest.cc b/content/browser/background_sync/background_sync_manager_unittest.cc
index ccf69e7..1e50d17 100644
--- a/content/browser/background_sync/background_sync_manager_unittest.cc
+++ b/content/browser/background_sync/background_sync_manager_unittest.cc
@@ -478,7 +478,8 @@
   ServiceWorkerRegistrationHandle* handle =
       dispatcher_host->FindRegistrationHandle(provider_id,
                                               sw_registration_1_->id());
-  dispatcher_host->OnDecrementRegistrationRefCount(handle->handle_id());
+  dispatcher_host->UnregisterServiceWorkerRegistrationHandle(
+      handle->handle_id());
 
   // Ensure |sw_registration_1_| is the last reference to the registration.
   ASSERT_TRUE(sw_registration_1_->HasOneRef());
diff --git a/content/browser/blob_storage/blob_url_loader_factory.cc b/content/browser/blob_storage/blob_url_loader_factory.cc
index 750f6bd..99b6378 100644
--- a/content/browser/blob_storage/blob_url_loader_factory.cc
+++ b/content/browser/blob_storage/blob_url_loader_factory.cc
@@ -107,8 +107,8 @@
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override {}
 
-  void PauseCachingResponseBody() override {}
-  void ResumeCachingResponseBody() override {}
+  void PauseReadingBodyFromNet() override {}
+  void ResumeReadingBodyFromNet() override {}
 
   // storage::MojoBlobReader::Delegate implementation:
   mojo::ScopedDataPipeProducerHandle PassDataPipe() override {
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 82b763f5..03712d0 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -328,12 +328,25 @@
 MSVC_DISABLE_OPTIMIZE()
 MSVC_PUSH_DISABLE_WARNING(4748)
 
+NOINLINE void ResetThread_DB() {
+  volatile int inhibit_comdat = __LINE__;
+  ALLOW_UNUSED_LOCAL(inhibit_comdat);
+  BrowserThreadImpl::StopRedirectionOfThreadID(BrowserThread::DB);
+}
+
 NOINLINE void ResetThread_FILE() {
   volatile int inhibit_comdat = __LINE__;
   ALLOW_UNUSED_LOCAL(inhibit_comdat);
   BrowserThreadImpl::StopRedirectionOfThreadID(BrowserThread::FILE);
 }
 
+NOINLINE void ResetThread_FILE_USER_BLOCKING() {
+  volatile int inhibit_comdat = __LINE__;
+  ALLOW_UNUSED_LOCAL(inhibit_comdat);
+  BrowserThreadImpl::StopRedirectionOfThreadID(
+      BrowserThread::FILE_USER_BLOCKING);
+}
+
 #if defined(OS_ANDROID)
 NOINLINE void ResetThread_PROCESS_LAUNCHER(
     std::unique_ptr<BrowserProcessSubThread> thread) {
@@ -349,6 +362,21 @@
 }
 #endif  // defined(OS_ANDROID)
 
+#if defined(OS_WIN)
+NOINLINE void ResetThread_CACHE(
+    std::unique_ptr<BrowserProcessSubThread> thread) {
+  volatile int inhibit_comdat = __LINE__;
+  ALLOW_UNUSED_LOCAL(inhibit_comdat);
+    thread.reset();
+}
+#else   // defined(OS_WIN)
+NOINLINE void ResetThread_CACHE() {
+  volatile int inhibit_comdat = __LINE__;
+  ALLOW_UNUSED_LOCAL(inhibit_comdat);
+  BrowserThreadImpl::StopRedirectionOfThreadID(BrowserThread::CACHE);
+}
+#endif  // defined(OS_WIN)
+
 NOINLINE void ResetThread_IO(std::unique_ptr<BrowserProcessSubThread> thread) {
   volatile int inhibit_comdat = __LINE__;
   ALLOW_UNUSED_LOCAL(inhibit_comdat);
@@ -1023,6 +1051,18 @@
         base::TaskShutdownBehavior::BLOCK_SHUTDOWN};
 
     switch (thread_id) {
+      case BrowserThread::DB:
+        TRACE_EVENT_BEGIN1("startup",
+            "BrowserMainLoop::CreateThreads:start",
+            "Thread", "BrowserThread::DB");
+        non_ui_non_io_task_runner_traits = kUserVisibleTraits;
+        break;
+      case BrowserThread::FILE_USER_BLOCKING:
+        TRACE_EVENT_BEGIN1("startup",
+            "BrowserMainLoop::CreateThreads:start",
+            "Thread", "BrowserThread::FILE_USER_BLOCKING");
+        non_ui_non_io_task_runner_traits = kUserBlockingTraits;
+        break;
       case BrowserThread::FILE:
         TRACE_EVENT_BEGIN1("startup",
             "BrowserMainLoop::CreateThreads:start",
@@ -1044,6 +1084,23 @@
         non_ui_non_io_task_runner_traits = kUserBlockingTraits;
 #endif  // defined(OS_ANDROID)
         break;
+      case BrowserThread::CACHE:
+        TRACE_EVENT_BEGIN1("startup",
+            "BrowserMainLoop::CreateThreads:start",
+            "Thread", "BrowserThread::CACHE");
+#if defined(OS_WIN)
+        // TaskScheduler doesn't support async I/O on Windows as CACHE thread is
+        // the only user and this use case is going away in
+        // https://codereview.chromium.org/2216583003/.
+        // TODO(gavinp): Remove this ifdef (and thus enable redirection of the
+        // CACHE thread on Windows) once that CL lands.
+        thread_to_start = &cache_thread_;
+        options = io_message_loop_options;
+        options.timer_slack = base::TIMER_SLACK_MAXIMUM;
+#else  // OS_WIN
+        non_ui_non_io_task_runner_traits = kUserBlockingTraits;
+#endif  // OS_WIN
+        break;
       case BrowserThread::IO:
         TRACE_EVENT_BEGIN1("startup",
             "BrowserMainLoop::CreateThreads:start",
@@ -1244,6 +1301,11 @@
       //
       // - (Not sure why DB stops last.)
       switch (thread_id) {
+        case BrowserThread::DB: {
+          TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:DBThread");
+          ResetThread_DB();
+          break;
+        }
         case BrowserThread::FILE: {
           TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:FileThread");
           // Clean up state that lives on or uses the FILE thread before it goes
@@ -1253,6 +1315,12 @@
           ResetThread_FILE();
           break;
         }
+        case BrowserThread::FILE_USER_BLOCKING: {
+          TRACE_EVENT0("shutdown",
+                       "BrowserMainLoop::Subsystem:FileUserBlockingThread");
+          ResetThread_FILE_USER_BLOCKING();
+          break;
+        }
         case BrowserThread::PROCESS_LAUNCHER: {
           TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:LauncherThread");
 #if defined(OS_ANDROID)
@@ -1262,6 +1330,15 @@
 #endif  // defined(OS_ANDROID)
           break;
         }
+        case BrowserThread::CACHE: {
+          TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:CacheThread");
+#if defined(OS_WIN)
+          ResetThread_CACHE(std::move(cache_thread_));
+#else   // defined(OS_WIN)
+          ResetThread_CACHE();
+#endif  // defined(OS_WIN)
+          break;
+        }
         case BrowserThread::IO: {
           TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:IOThread");
           ResetThread_IO(std::move(io_thread_));
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc
index b2bc69be..8b6a311 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -7,6 +7,8 @@
 #include <stddef.h>
 
 #include <algorithm>
+#include <string>
+#include <utility>
 
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
@@ -1107,7 +1109,7 @@
 
 void BrowserPluginGuest::OnShowWidget(int route_id,
                                       const gfx::Rect& initial_rect) {
-  int process_id = GetWebContents()->GetRenderProcessHost()->GetID();
+  int process_id = GetWebContents()->GetMainFrame()->GetProcess()->GetID();
   GetWebContents()->ShowCreatedWidget(process_id, route_id, initial_rect);
 }
 
diff --git a/content/browser/browser_thread_impl.cc b/content/browser/browser_thread_impl.cc
index 5c5ada96..276ad382 100644
--- a/content/browser/browser_thread_impl.cc
+++ b/content/browser/browser_thread_impl.cc
@@ -33,8 +33,11 @@
 // 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_DBThread",  // DB
   "Chrome_FileThread",  // FILE
+  "Chrome_FileUserBlockingThread",  // FILE_USER_BLOCKING
   "Chrome_ProcessLauncherThread",  // PROCESS_LAUNCHER
+  "Chrome_CacheThread",  // CACHE
   "Chrome_IOThread",  // IO
 };
 
@@ -179,8 +182,11 @@
   }
 #endif  // DCHECK_IS_ON()
 
-  if (identifier_ == BrowserThread::FILE ||
-      identifier_ == BrowserThread::PROCESS_LAUNCHER) {
+  if (identifier_ == BrowserThread::DB ||
+      identifier_ == BrowserThread::FILE ||
+      identifier_ == BrowserThread::FILE_USER_BLOCKING ||
+      identifier_ == BrowserThread::PROCESS_LAUNCHER ||
+      identifier_ == BrowserThread::CACHE) {
     // Nesting and task observers are not allowed on redirected threads.
     base::RunLoop::DisallowNestingOnCurrentThread();
     message_loop()->DisallowTaskObservers();
@@ -205,12 +211,25 @@
   CHECK_GT(line_number, 0);
 }
 
+NOINLINE void BrowserThreadImpl::DBThreadRun(base::RunLoop* run_loop) {
+  volatile int line_number = __LINE__;
+  Thread::Run(run_loop);
+  CHECK_GT(line_number, 0);
+}
+
 NOINLINE void BrowserThreadImpl::FileThreadRun(base::RunLoop* run_loop) {
   volatile int line_number = __LINE__;
   Thread::Run(run_loop);
   CHECK_GT(line_number, 0);
 }
 
+NOINLINE void BrowserThreadImpl::FileUserBlockingThreadRun(
+    base::RunLoop* run_loop) {
+  volatile int line_number = __LINE__;
+  Thread::Run(run_loop);
+  CHECK_GT(line_number, 0);
+}
+
 NOINLINE void BrowserThreadImpl::ProcessLauncherThreadRun(
     base::RunLoop* run_loop) {
   volatile int line_number = __LINE__;
@@ -218,6 +237,12 @@
   CHECK_GT(line_number, 0);
 }
 
+NOINLINE void BrowserThreadImpl::CacheThreadRun(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);
@@ -244,10 +269,16 @@
   switch (identifier_) {
     case BrowserThread::UI:
       return UIThreadRun(run_loop);
+    case BrowserThread::DB:
+      return DBThreadRun(run_loop);
     case BrowserThread::FILE:
       return FileThreadRun(run_loop);
+    case BrowserThread::FILE_USER_BLOCKING:
+      return FileUserBlockingThreadRun(run_loop);
     case BrowserThread::PROCESS_LAUNCHER:
       return ProcessLauncherThreadRun(run_loop);
+    case BrowserThread::CACHE:
+      return CacheThreadRun(run_loop);
     case BrowserThread::IO:
       return IOThreadRun(run_loop);
     case BrowserThread::ID_COUNT:
diff --git a/content/browser/browser_thread_impl.h b/content/browser/browser_thread_impl.h
index 91db6018d..a9eca4c 100644
--- a/content/browser/browser_thread_impl.h
+++ b/content/browser/browser_thread_impl.h
@@ -76,8 +76,11 @@
   // 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 DBThreadRun(base::RunLoop* run_loop);
   void FileThreadRun(base::RunLoop* run_loop);
+  void FileUserBlockingThreadRun(base::RunLoop* run_loop);
   void ProcessLauncherThreadRun(base::RunLoop* run_loop);
+  void CacheThreadRun(base::RunLoop* run_loop);
   void IOThreadRun(base::RunLoop* run_loop);
 
   static bool PostTaskHelper(BrowserThread::ID identifier,
diff --git a/content/browser/child_process_launcher_browsertest.cc b/content/browser/child_process_launcher_browsertest.cc
index f48279b7..e6ee248 100644
--- a/content/browser/child_process_launcher_browsertest.cc
+++ b/content/browser/child_process_launcher_browsertest.cc
@@ -6,6 +6,7 @@
 #include "content/browser/child_process_launcher.h"
 #include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/content_browser_test.h"
@@ -36,7 +37,7 @@
   bool simulate_failure_;
 };
 
-}
+}  // namespace
 
 namespace content {
 
@@ -63,8 +64,8 @@
   client = new MockChildProcessLauncherClient;
   window->LoadURL(url);
   client->client_ = static_cast<RenderProcessHostImpl*>(
-      window->web_contents()->GetRenderProcessHost())
-      ->child_process_launcher_->ReplaceClientForTest(client);
+                        window->web_contents()->GetMainFrame()->GetProcess())
+                        ->child_process_launcher_->ReplaceClientForTest(client);
   client->simulate_failure_ = true;
   nav_observer1.Wait();
   delete client;
diff --git a/content/browser/child_process_security_policy_browsertest.cc b/content/browser/child_process_security_policy_browsertest.cc
index 3e4264d..942d5d2 100644
--- a/content/browser/child_process_security_policy_browsertest.cc
+++ b/content/browser/child_process_security_policy_browsertest.cc
@@ -8,6 +8,7 @@
 #include "build/build_config.h"
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/common/result_codes.h"
 #include "content/public/test/content_browser_test.h"
@@ -48,7 +49,8 @@
           1U);
 
   WebContents* web_contents = shell()->web_contents();
-  web_contents->GetRenderProcessHost()->Shutdown(RESULT_CODE_KILLED, true);
+  web_contents->GetMainFrame()->GetProcess()->Shutdown(RESULT_CODE_KILLED,
+                                                       true);
 
   web_contents->GetController().Reload(ReloadType::NORMAL, true);
   EXPECT_EQ(
diff --git a/content/browser/cross_site_transfer_browsertest.cc b/content/browser/cross_site_transfer_browsertest.cc
index 29d7514..f18e993 100644
--- a/content/browser/cross_site_transfer_browsertest.cc
+++ b/content/browser/cross_site_transfer_browsertest.cc
@@ -482,7 +482,8 @@
   EXPECT_TRUE(delegate->file_chosen());
 
   // Remember the old process id for a sanity check below.
-  int old_process_id = shell()->web_contents()->GetRenderProcessHost()->GetID();
+  int old_process_id =
+      shell()->web_contents()->GetMainFrame()->GetProcess()->GetID();
 
   // Submit the form.
   TestNavigationObserver form_post_observer(shell()->web_contents(), 1);
@@ -495,7 +496,8 @@
             shell()->web_contents()->GetLastCommittedURL());
 
   // Verify that the test really verifies access of a *new* renderer process.
-  int new_process_id = shell()->web_contents()->GetRenderProcessHost()->GetID();
+  int new_process_id =
+      shell()->web_contents()->GetMainFrame()->GetProcess()->GetID();
   ASSERT_NE(new_process_id, old_process_id);
 
   // MAIN VERIFICATION: Check if the new renderer process is able to read the
diff --git a/content/browser/devtools/devtools_frontend_host_impl.cc b/content/browser/devtools/devtools_frontend_host_impl.cc
index 2234903..ab6e4b0 100644
--- a/content/browser/devtools/devtools_frontend_host_impl.cc
+++ b/content/browser/devtools/devtools_frontend_host_impl.cc
@@ -6,6 +6,8 @@
 
 #include <stddef.h>
 
+#include <string>
+
 #include "content/browser/bad_message.h"
 #include "content/browser/devtools/grit/devtools_resources_map.h"
 #include "content/common/devtools_messages.h"
@@ -69,7 +71,7 @@
 }
 
 void DevToolsFrontendHostImpl::BadMessageRecieved() {
-  bad_message::ReceivedBadMessage(web_contents()->GetRenderProcessHost(),
+  bad_message::ReceivedBadMessage(web_contents()->GetMainFrame()->GetProcess(),
                                   bad_message::DFH_BAD_EMBEDDER_MESSAGE);
 }
 
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
index 0513176..7e509e3 100644
--- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -858,7 +858,7 @@
 }
 
 // Setting frame size (through RWHV) is not supported on Android.
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_LINUX)
 #define MAYBE_CaptureScreenshotArea DISABLED_CaptureScreenshotArea
 #else
 #define MAYBE_CaptureScreenshotArea CaptureScreenshotArea
diff --git a/content/browser/devtools/protocol/storage_handler.cc b/content/browser/devtools/protocol/storage_handler.cc
index e0b373a..823de300 100644
--- a/content/browser/devtools/protocol/storage_handler.cc
+++ b/content/browser/devtools/protocol/storage_handler.cc
@@ -12,6 +12,7 @@
 #include "base/strings/string_split.h"
 #include "content/browser/cache_storage/cache_storage_context_impl.h"
 #include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/indexed_db/indexed_db_context_impl.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/storage_partition.h"
 #include "storage/browser/quota/quota_client.h"
@@ -94,16 +95,157 @@
 }
 }  // namespace
 
+// Observer that listens on the IO thread for cache storage notifications and
+// informs the StorageHandler on the UI thread for origins of interest.
+// Created on the UI thread but predominantly used and deleted on the IO thread.
+// Registered on creation as an observer in CacheStorageContextImpl,
+// unregistered on destruction.
+class StorageHandler::CacheStorageObserver : CacheStorageContextImpl::Observer {
+ public:
+  CacheStorageObserver(base::WeakPtr<StorageHandler> owner_storage_handler,
+                       CacheStorageContextImpl* cache_storage_context)
+      : owner_(owner_storage_handler), context_(cache_storage_context) {
+    BrowserThread::PostTask(
+        BrowserThread::IO, FROM_HERE,
+        base::BindOnce(&CacheStorageObserver::AddObserverOnIOThread,
+                       base::Unretained(this)));
+  }
+
+  ~CacheStorageObserver() override {
+    DCHECK_CURRENTLY_ON(BrowserThread::IO);
+    context_->RemoveObserver(this);
+  }
+
+  void TrackOriginOnIOThread(const url::Origin& origin) {
+    DCHECK_CURRENTLY_ON(BrowserThread::IO);
+    if (origins_.find(origin) != origins_.end())
+      return;
+    origins_.insert(origin);
+  }
+
+  void UntrackOriginOnIOThread(const url::Origin& origin) {
+    DCHECK_CURRENTLY_ON(BrowserThread::IO);
+    origins_.erase(origin);
+  }
+
+  void OnCacheListChanged(const url::Origin& origin) override {
+    auto found = origins_.find(origin);
+    if (found == origins_.end())
+      return;
+    BrowserThread::PostTask(
+        BrowserThread::UI, FROM_HERE,
+        base::BindOnce(&StorageHandler::NotifyCacheStorageListChanged, owner_,
+                       origin.Serialize()));
+  }
+
+  void OnCacheContentChanged(const url::Origin& origin,
+                             const std::string& cache_name) override {
+    if (origins_.find(origin) == origins_.end())
+      return;
+    BrowserThread::PostTask(
+        BrowserThread::UI, FROM_HERE,
+        base::BindOnce(&StorageHandler::NotifyCacheStorageContentChanged,
+                       owner_, origin.Serialize(), cache_name));
+  }
+
+ private:
+  void AddObserverOnIOThread() {
+    DCHECK_CURRENTLY_ON(BrowserThread::IO);
+    context_->AddObserver(this);
+  }
+
+  // Maintained on the IO thread to avoid thread contention.
+  base::flat_set<url::Origin> origins_;
+
+  base::WeakPtr<StorageHandler> owner_;
+  scoped_refptr<CacheStorageContextImpl> context_;
+
+  DISALLOW_COPY_AND_ASSIGN(CacheStorageObserver);
+};
+
+// Observer that listens on the IDB thread for IndexedDB notifications and
+// informs the StorageHandler on the UI thread for origins of interest.
+// Created on the UI thread but predominantly used and deleted on the IDB
+// thread.
+// Registered on creation as an observer in IndexedDBContextImpl, unregistered
+// on destruction.
+class StorageHandler::IndexedDBObserver : IndexedDBContextImpl::Observer {
+ public:
+  IndexedDBObserver(base::WeakPtr<StorageHandler> owner_storage_handler,
+                    IndexedDBContextImpl* indexed_db_context)
+      : owner_(owner_storage_handler), context_(indexed_db_context) {
+    context_->TaskRunner()->PostTask(
+        FROM_HERE, base::BindOnce(&IndexedDBObserver::AddObserverOnIDBThread,
+                                  base::Unretained(this)));
+  }
+
+  ~IndexedDBObserver() override {
+    DCHECK(context_->TaskRunner()->RunsTasksInCurrentSequence());
+    context_->RemoveObserver(this);
+  }
+
+  void TrackOriginOnIDBThread(const url::Origin& origin) {
+    DCHECK(context_->TaskRunner()->RunsTasksInCurrentSequence());
+    if (origins_.find(origin) != origins_.end())
+      return;
+    origins_.insert(origin);
+  }
+
+  void UntrackOriginOnIDBThread(const url::Origin& origin) {
+    DCHECK(context_->TaskRunner()->RunsTasksInCurrentSequence());
+    origins_.erase(origin);
+  }
+
+  void OnIndexedDBListChanged(const url::Origin& origin) override {
+    auto found = origins_.find(origin);
+    if (found == origins_.end())
+      return;
+    BrowserThread::PostTask(
+        BrowserThread::UI, FROM_HERE,
+        base::BindOnce(&StorageHandler::NotifyIndexedDBListChanged, owner_,
+                       origin.Serialize()));
+  }
+
+  void OnIndexedDBContentChanged(
+      const url::Origin& origin,
+      const base::string16& database_name,
+      const base::string16& object_store_name) override {
+    auto found = origins_.find(origin);
+    if (found == origins_.end())
+      return;
+    BrowserThread::PostTask(
+        BrowserThread::UI, FROM_HERE,
+        base::BindOnce(&StorageHandler::NotifyIndexedDBContentChanged, owner_,
+                       origin.Serialize(), database_name, object_store_name));
+  }
+
+  base::SequencedTaskRunner* TaskRunner() const {
+    return context_->TaskRunner();
+  }
+
+ private:
+  void AddObserverOnIDBThread() {
+    DCHECK(context_->TaskRunner()->RunsTasksInCurrentSequence());
+    context_->AddObserver(this);
+  }
+
+  // Maintained on the IDB thread to avoid thread contention.
+  base::flat_set<url::Origin> origins_;
+
+  base::WeakPtr<StorageHandler> owner_;
+  scoped_refptr<IndexedDBContextImpl> context_;
+
+  DISALLOW_COPY_AND_ASSIGN(IndexedDBObserver);
+};
+
 StorageHandler::StorageHandler()
     : DevToolsDomainHandler(Storage::Metainfo::domainName),
       host_(nullptr),
       weak_ptr_factory_(this) {}
 
 StorageHandler::~StorageHandler() {
-  if (cache_storage_observer_) {
-    BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE,
-                              cache_storage_observer_.release());
-  }
+  DCHECK(!cache_storage_observer_);
+  DCHECK(!indexed_db_observer_);
 }
 
 void StorageHandler::Wire(UberDispatcher* dispatcher) {
@@ -115,6 +257,19 @@
   host_ = host;
 }
 
+Response StorageHandler::Disable() {
+  if (cache_storage_observer_) {
+    BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE,
+                              cache_storage_observer_.release());
+  }
+  if (indexed_db_observer_) {
+    indexed_db_observer_->TaskRunner()->DeleteSoon(
+        FROM_HERE, std::move(indexed_db_observer_));
+  }
+
+  return Response::OK();
+}
+
 Response StorageHandler::ClearDataForOrigin(
     const std::string& origin,
     const std::string& storage_types) {
@@ -179,75 +334,6 @@
                      origin_url, base::Passed(std::move(callback))));
 }
 
-// Observer that listens on the IO thread for cache storage notifications and
-// informs the StorageHandler on the UI for origins of interest.
-// Created on the UI thread but predominantly used and deleted on the IO thread.
-// Registered on creation as an observer in CacheStorageContext, unregistered on
-// destruction
-class StorageHandler::CacheStorageObserver : CacheStorageContextImpl::Observer {
- public:
-  CacheStorageObserver(base::WeakPtr<StorageHandler> owner_storage_handler,
-                       CacheStorageContextImpl* cache_storage_context)
-      : owner_(owner_storage_handler), context_(cache_storage_context) {
-    BrowserThread::PostTask(
-        BrowserThread::IO, FROM_HERE,
-        base::BindOnce(&CacheStorageObserver::AddObserverOnIOThread,
-                       base::Unretained(this)));
-  }
-
-  ~CacheStorageObserver() override {
-    DCHECK_CURRENTLY_ON(BrowserThread::IO);
-    context_->RemoveObserver(this);
-  }
-
-  void TrackOriginOnIOThread(const url::Origin& origin) {
-    DCHECK_CURRENTLY_ON(BrowserThread::IO);
-    if (origins_.find(origin) != origins_.end())
-      return;
-    origins_.insert(origin);
-  }
-
-  void UntrackOriginOnIOThread(const url::Origin& origin) {
-    DCHECK_CURRENTLY_ON(BrowserThread::IO);
-    origins_.erase(origin);
-  }
-
- private:
-  void AddObserverOnIOThread() {
-    DCHECK_CURRENTLY_ON(BrowserThread::IO);
-    context_->AddObserver(this);
-  }
-
-  void OnCacheListChanged(const url::Origin& origin) override {
-    auto found = origins_.find(origin);
-    if (found == origins_.end())
-      return;
-    BrowserThread::PostTask(
-        BrowserThread::UI, FROM_HERE,
-        base::BindOnce(&StorageHandler::NotifyCacheStorageListChanged, owner_,
-                       origin.Serialize()));
-  }
-
-  void OnCacheContentChanged(const url::Origin& origin,
-                             const std::string& cache_name) override {
-    auto found = origins_.find(origin);
-    if (found == origins_.end())
-      return;
-    BrowserThread::PostTask(
-        BrowserThread::UI, FROM_HERE,
-        base::BindOnce(&StorageHandler::NotifyCacheStorageContentChanged,
-                       owner_, origin.Serialize(), cache_name));
-  }
-
-  // Maintained on the IO thread to avoid mutex contention.
-  base::flat_set<url::Origin> origins_;
-
-  base::WeakPtr<StorageHandler> owner_;
-  scoped_refptr<CacheStorageContextImpl> context_;
-
-  DISALLOW_COPY_AND_ASSIGN(CacheStorageObserver);
-};
-
 Response StorageHandler::TrackCacheStorageForOrigin(const std::string& origin) {
   if (!host_)
     return Response::InternalError();
@@ -281,10 +367,41 @@
   return Response::OK();
 }
 
+Response StorageHandler::TrackIndexedDBForOrigin(const std::string& origin) {
+  if (!host_)
+    return Response::InternalError();
+
+  GURL origin_url(origin);
+  if (!origin_url.is_valid())
+    return Response::InvalidParams(origin + " is not a valid URL");
+
+  GetIndexedDBObserver()->TaskRunner()->PostTask(
+      FROM_HERE, base::BindOnce(&IndexedDBObserver::TrackOriginOnIDBThread,
+                                base::Unretained(GetIndexedDBObserver()),
+                                url::Origin(origin_url)));
+  return Response::OK();
+}
+
+Response StorageHandler::UntrackIndexedDBForOrigin(const std::string& origin) {
+  if (!host_)
+    return Response::InternalError();
+
+  GURL origin_url(origin);
+  if (!origin_url.is_valid())
+    return Response::InvalidParams(origin + " is not a valid URL");
+
+  GetIndexedDBObserver()->TaskRunner()->PostTask(
+      FROM_HERE, base::BindOnce(&IndexedDBObserver::UntrackOriginOnIDBThread,
+                                base::Unretained(GetIndexedDBObserver()),
+                                url::Origin(origin_url)));
+  return Response::OK();
+}
+
 StorageHandler::CacheStorageObserver*
 StorageHandler::GetCacheStorageObserver() {
-  if (cache_storage_observer_ == nullptr) {
-    cache_storage_observer_ = base::MakeUnique<CacheStorageObserver>(
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  if (!cache_storage_observer_) {
+    cache_storage_observer_ = std::make_unique<CacheStorageObserver>(
         weak_ptr_factory_.GetWeakPtr(),
         static_cast<CacheStorageContextImpl*>(host_->GetProcess()
                                                   ->GetStoragePartition()
@@ -293,6 +410,17 @@
   return cache_storage_observer_.get();
 }
 
+StorageHandler::IndexedDBObserver* StorageHandler::GetIndexedDBObserver() {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  if (!indexed_db_observer_) {
+    indexed_db_observer_ = std::make_unique<IndexedDBObserver>(
+        weak_ptr_factory_.GetWeakPtr(),
+        static_cast<IndexedDBContextImpl*>(
+            host_->GetProcess()->GetStoragePartition()->GetIndexedDBContext()));
+  }
+  return indexed_db_observer_.get();
+}
+
 void StorageHandler::NotifyCacheStorageListChanged(const std::string& origin) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   frontend_->CacheStorageListUpdated(origin);
@@ -304,5 +432,19 @@
   frontend_->CacheStorageContentUpdated(origin, name);
 }
 
+void StorageHandler::NotifyIndexedDBListChanged(const std::string& origin) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  frontend_->IndexedDBListUpdated(origin);
+}
+
+void StorageHandler::NotifyIndexedDBContentChanged(
+    const std::string& origin,
+    const base::string16& database_name,
+    const base::string16& object_store_name) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  frontend_->IndexedDBContentUpdated(origin, base::UTF16ToUTF8(database_name),
+                                     base::UTF16ToUTF8(object_store_name));
+}
+
 }  // namespace protocol
 }  // namespace content
diff --git a/content/browser/devtools/protocol/storage_handler.h b/content/browser/devtools/protocol/storage_handler.h
index 0845ff5..8d0d6d1c 100644
--- a/content/browser/devtools/protocol/storage_handler.h
+++ b/content/browser/devtools/protocol/storage_handler.h
@@ -14,6 +14,7 @@
 #include "content/browser/cache_storage/cache_storage_context_impl.h"
 #include "content/browser/devtools/protocol/devtools_domain_handler.h"
 #include "content/browser/devtools/protocol/storage.h"
+#include "content/browser/indexed_db/indexed_db_context_impl.h"
 
 namespace content {
 
@@ -27,31 +28,46 @@
   StorageHandler();
   ~StorageHandler() override;
 
+  // content::protocol::DevToolsDomainHandler
   void Wire(UberDispatcher* dispatcher) override;
   void SetRenderFrameHost(RenderFrameHostImpl* host) override;
+  Response Disable() override;
 
+  // content::protocol::storage::Backend
   Response ClearDataForOrigin(
       const std::string& origin,
       const std::string& storage_types) override;
   void GetUsageAndQuota(
       const String& origin,
       std::unique_ptr<GetUsageAndQuotaCallback> callback) override;
+
   // Ignores all double calls to track an origin.
   Response TrackCacheStorageForOrigin(const std::string& origin) override;
   Response UntrackCacheStorageForOrigin(const std::string& origin) override;
+  Response TrackIndexedDBForOrigin(const std::string& origin) override;
+  Response UntrackIndexedDBForOrigin(const std::string& origin) override;
 
  private:
   // See definition for lifetime information.
   class CacheStorageObserver;
+  class IndexedDBObserver;
 
+  // Not thread safe.
   CacheStorageObserver* GetCacheStorageObserver();
+  IndexedDBObserver* GetIndexedDBObserver();
+
   void NotifyCacheStorageListChanged(const std::string& origin);
   void NotifyCacheStorageContentChanged(const std::string& origin,
                                         const std::string& name);
+  void NotifyIndexedDBListChanged(const std::string& origin);
+  void NotifyIndexedDBContentChanged(const std::string& origin,
+                                     const base::string16& database_name,
+                                     const base::string16& object_store_name);
 
   std::unique_ptr<Storage::Frontend> frontend_;
   RenderFrameHostImpl* host_;
   std::unique_ptr<CacheStorageObserver> cache_storage_observer_;
+  std::unique_ptr<IndexedDBObserver> indexed_db_observer_;
 
   base::WeakPtrFactory<StorageHandler> weak_ptr_factory_;
 
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc
index ee81848..50e0b5e 100644
--- a/content/browser/download/download_browsertest.cc
+++ b/content/browser/download/download_browsertest.cc
@@ -487,6 +487,7 @@
 std::unique_ptr<net::test_server::HttpResponse>
 HandleRequestAndSendBasicResponse(
     const std::string& relative_url,
+    net::HttpStatusCode code,
     const base::StringPairs& headers,
     const std::string& content_type,
     const std::string& body,
@@ -498,6 +499,7 @@
       response->AddCustomHeader(pair.first, pair.second);
     response->set_content_type(content_type);
     response->set_content(body);
+    response->set_code(code);
   }
   return std::move(response);
 }
@@ -506,11 +508,12 @@
 // HTTP 200 status code, a Content-Type header and a body.
 net::EmbeddedTestServer::HandleRequestCallback CreateBasicResponseHandler(
     const std::string& relative_url,
+    net::HttpStatusCode code,
     const base::StringPairs& headers,
     const std::string& content_type,
     const std::string& body) {
-  return base::Bind(&HandleRequestAndSendBasicResponse, relative_url, headers,
-                    content_type, body);
+  return base::Bind(&HandleRequestAndSendBasicResponse, relative_url, code,
+                    headers, content_type, body);
 }
 
 // Helper class to "flatten" handling of
@@ -2321,8 +2324,9 @@
       net::EmbeddedTestServer::Type::TYPE_HTTPS);
   net::EmbeddedTestServer http_origin(net::EmbeddedTestServer::Type::TYPE_HTTP);
   https_origin.ServeFilesFromDirectory(GetTestFilePath("download", ""));
-  http_origin.RegisterRequestHandler(CreateBasicResponseHandler(
-      "/download", base::StringPairs(), "application/octet-stream", "Hello"));
+  http_origin.RegisterRequestHandler(
+      CreateBasicResponseHandler("/download", net::HTTP_OK, base::StringPairs(),
+                                 "application/octet-stream", "Hello"));
   ASSERT_TRUE(https_origin.InitializeAndListen());
   ASSERT_TRUE(http_origin.InitializeAndListen());
 
@@ -2358,7 +2362,7 @@
   cookie_header.push_back(
       std::make_pair(std::string("Set-Cookie"), std::string("A=B")));
   origin_one.RegisterRequestHandler(CreateBasicResponseHandler(
-      "/foo", cookie_header, "application/octet-stream", "abcd"));
+      "/foo", net::HTTP_OK, cookie_header, "application/octet-stream", "abcd"));
   ASSERT_TRUE(origin_one.Start());
 
   origin_two.RegisterRequestHandler(
@@ -2419,8 +2423,9 @@
       CreateRedirectHandler("/ping", origin_two.GetURL("/download")));
   origin_one.StartAcceptingConnections();
 
-  origin_two.RegisterRequestHandler(CreateBasicResponseHandler(
-      "/download", base::StringPairs(), "application/octet-stream", "Hello"));
+  origin_two.RegisterRequestHandler(
+      CreateBasicResponseHandler("/download", net::HTTP_OK, base::StringPairs(),
+                                 "application/octet-stream", "Hello"));
   origin_two.StartAcceptingConnections();
 
   NavigateToURLAndWaitForDownload(
@@ -2468,8 +2473,9 @@
       CreateRedirectHandler("/ping", origin_two.GetURL("/pong")));
   origin_two.RegisterRequestHandler(
       CreateRedirectHandler("/pong", origin_one.GetURL("/download")));
-  origin_one.RegisterRequestHandler(CreateBasicResponseHandler(
-      "/download", base::StringPairs(), "application/octet-stream", "Hello"));
+  origin_one.RegisterRequestHandler(
+      CreateBasicResponseHandler("/download", net::HTTP_OK, base::StringPairs(),
+                                 "application/octet-stream", "Hello"));
 
   origin_one.StartAcceptingConnections();
   origin_two.StartAcceptingConnections();
@@ -2846,4 +2852,93 @@
             downloads[0]->GetTargetFilePath().BaseName().value());
 }
 
+// Verify that the response body of non-successful server response can be
+// downloaded to a file, when |fetch_error_body| sets to true.
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, FetchErrorResponseBody) {
+  net::EmbeddedTestServer server;
+  const std::string kNotFoundURL = "/404notfound";
+  const std::string kNotFoundResponseBody = "This is response body.";
+
+  server.RegisterRequestHandler(CreateBasicResponseHandler(
+      kNotFoundURL, net::HTTP_NOT_FOUND, base::StringPairs(), "text/html",
+      kNotFoundResponseBody));
+  ASSERT_TRUE(server.Start());
+  GURL url = server.GetURL(kNotFoundURL);
+
+  std::unique_ptr<DownloadUrlParameters> download_parameters(
+      DownloadUrlParameters::CreateForWebContentsMainFrame(
+          shell()->web_contents(), url, TRAFFIC_ANNOTATION_FOR_TESTS));
+  // Fetch non-successful response body.
+  download_parameters->set_fetch_error_body(true);
+
+  DownloadManager* download_manager = DownloadManagerForShell(shell());
+  std::unique_ptr<DownloadTestObserver> observer(CreateWaiter(shell(), 1));
+  download_manager->DownloadUrl(std::move(download_parameters));
+  observer->WaitForFinished();
+  std::vector<DownloadItem*> items;
+  download_manager->GetAllDownloads(&items);
+  EXPECT_EQ(1u, items.size());
+
+  // Verify the error response body in the file.
+  {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    std::string file_content;
+    ASSERT_TRUE(
+        base::ReadFileToString(items[0]->GetTargetFilePath(), &file_content));
+    EXPECT_EQ(kNotFoundResponseBody, file_content);
+  }
+}
+
+// Verify the case that the first response is HTTP 200, and then interrupted,
+// and the second response is HTTP 404, the response body of 404 should be
+// fetched.
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, FetchErrorResponseBodyResumption) {
+  const std::string kNotFoundResponseBody = "This is 404 response body.";
+  GURL url;
+
+  TestDownloadRequestHandler server;
+  TestDownloadRequestHandler::Parameters server_params =
+      TestDownloadRequestHandler::Parameters::WithSingleInterruption();
+  url = server.url();
+  server.StartServing(server_params);
+
+  // Wait for an interrupted download.
+  std::unique_ptr<DownloadUrlParameters> download_parameters(
+      DownloadUrlParameters::CreateForWebContentsMainFrame(
+          shell()->web_contents(), url, TRAFFIC_ANNOTATION_FOR_TESTS));
+  download_parameters->set_fetch_error_body(true);
+  DownloadManager* download_manager = DownloadManagerForShell(shell());
+
+  std::unique_ptr<DownloadTestObserver> observer;
+  observer.reset(new content::DownloadTestObserverInterrupted(
+      download_manager, 1,
+      content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL));
+
+  download_manager->DownloadUrl(std::move(download_parameters));
+  observer->WaitForFinished();
+
+  std::vector<DownloadItem*> items;
+  download_manager->GetAllDownloads(&items);
+  EXPECT_EQ(1u, items.size());
+
+  // Now server will start to response 404 with empty body.
+  const std::string k404ResponseHeader = "HTTP/1.1 404 Not found\r\n\r\n";
+  server.StartServingStaticResponse(k404ResponseHeader);
+  DownloadItem* download = items[0];
+
+  // The fetch error body should be cached in download item. The download should
+  // start from beginning.
+  download->Resume();
+  WaitForCompletion(download);
+
+  // The file should be empty.
+  {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    std::string file_content;
+    ASSERT_TRUE(
+        base::ReadFileToString(items[0]->GetTargetFilePath(), &file_content));
+    EXPECT_EQ(std::string(), file_content);
+  }
+}
+
 }  // namespace content
diff --git a/content/browser/download/download_create_info.h b/content/browser/download/download_create_info.h
index d2c85027..af6eac17 100644
--- a/content/browser/download/download_create_info.h
+++ b/content/browser/download/download_create_info.h
@@ -144,6 +144,10 @@
   // The HTTP request method.
   std::string method;
 
+  // Whether the download should fetch the response body for non successful HTTP
+  // response.
+  bool fetch_error_body = false;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(DownloadCreateInfo);
 };
diff --git a/content/browser/download/download_item_impl.cc b/content/browser/download/download_item_impl.cc
index e26a147e..80844327 100644
--- a/content/browser/download/download_item_impl.cc
+++ b/content/browser/download/download_item_impl.cc
@@ -93,30 +93,28 @@
 // Wrapper around DownloadFile::Detach and DownloadFile::Cancel that
 // takes ownership of the DownloadFile and hence implicitly destroys it
 // at the end of the function.
-static base::FilePath DownloadFileDetach(
-    std::unique_ptr<DownloadFile> download_file) {
+base::FilePath DownloadFileDetach(std::unique_ptr<DownloadFile> download_file) {
   DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
   base::FilePath full_path = download_file->FullPath();
   download_file->Detach();
   return full_path;
 }
 
-static base::FilePath MakeCopyOfDownloadFile(DownloadFile* download_file) {
+base::FilePath MakeCopyOfDownloadFile(DownloadFile* download_file) {
   DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
   base::FilePath temp_file_path;
-  if (base::CreateTemporaryFile(&temp_file_path) &&
-      base::CopyFile(download_file->FullPath(), temp_file_path)) {
-    return temp_file_path;
-  } else {
-    // Deletes the file at |temp_file_path|.
-    if (!base::DirectoryExists(temp_file_path))
-      base::DeleteFile(temp_file_path, false);
-    temp_file_path.clear();
+  if (!base::CreateTemporaryFile(&temp_file_path))
+    return base::FilePath();
+
+  if (!base::CopyFile(download_file->FullPath(), temp_file_path)) {
+    DeleteDownloadedFile(temp_file_path);
     return base::FilePath();
   }
+
+  return temp_file_path;
 }
 
-static void DownloadFileCancel(std::unique_ptr<DownloadFile> download_file) {
+void DownloadFileCancel(std::unique_ptr<DownloadFile> download_file) {
   DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
   download_file->Cancel();
 }
@@ -304,6 +302,7 @@
       etag_(info.etag),
       net_log_(net_log),
       is_updating_observers_(false),
+      fetch_error_body_(info.fetch_error_body),
       weak_ptr_factory_(this) {
   delegate_->Attach();
   Init(true /* actively downloading */, SRC_ACTIVE_DOWNLOAD);
@@ -2203,6 +2202,7 @@
   download_params->set_etag(GetETag());
   download_params->set_hash_of_partial_file(GetHash());
   download_params->set_hash_state(std::move(hash_state_));
+  download_params->set_fetch_error_body(fetch_error_body_);
 
   // Note that resumed downloads disallow redirects. Hence the referrer URL
   // (which is the contents of the Referer header for the last download request)
diff --git a/content/browser/download/download_item_impl.h b/content/browser/download/download_item_impl.h
index 88b9179..6a7fc588 100644
--- a/content/browser/download/download_item_impl.h
+++ b/content/browser/download/download_item_impl.h
@@ -759,6 +759,10 @@
   // Check whether the download item is updating its observers.
   bool is_updating_observers_;
 
+  // Whether the download should fetch the response body for non successful HTTP
+  // response.
+  bool fetch_error_body_ = false;
+
   base::WeakPtrFactory<DownloadItemImpl> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(DownloadItemImpl);
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index 7742e3b..aba8ba0 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -69,10 +69,9 @@
 namespace content {
 namespace {
 
-scoped_refptr<URLLoaderFactoryGetter> GetURLLoaderFactoryGetter(
-    BrowserContext* context,
-    int render_process_id,
-    int render_frame_id) {
+StoragePartitionImpl* GetStoragePartition(BrowserContext* context,
+                                          int render_process_id,
+                                          int render_frame_id) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   SiteInstance* site_instance = nullptr;
@@ -82,9 +81,8 @@
     if (render_frame_host_)
       site_instance = render_frame_host_->GetSiteInstance();
   }
-  StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
+  return static_cast<StoragePartitionImpl*>(
       BrowserContext::GetStoragePartition(context, site_instance));
-  return partition->url_loader_factory_getter();
 }
 
 bool CanRequestURLFromRenderer(int render_process_id, GURL url) {
@@ -167,6 +165,7 @@
     std::unique_ptr<DownloadUrlParameters> params,
     std::unique_ptr<ResourceRequest> request,
     scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
+    scoped_refptr<storage::FileSystemContext> file_system_context,
     uint32_t download_id,
     base::WeakPtr<DownloadManagerImpl> download_manager) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -184,7 +183,7 @@
   return DownloadManagerImpl::UniqueUrlDownloadHandlerPtr(
       ResourceDownloader::BeginDownload(
           download_manager, std::move(params), std::move(request),
-          url_loader_factory_getter, download_id, false)
+          url_loader_factory_getter, file_system_context, download_id, false)
           .release());
 }
 
@@ -738,15 +737,16 @@
   if (base::FeatureList::IsEnabled(features::kNetworkService)) {
     std::unique_ptr<ResourceRequest> request = CreateResourceRequest(
         params.get());
+    StoragePartitionImpl* storage_partition =
+        GetStoragePartition(browser_context_, params->render_process_host_id(),
+                            params->render_frame_host_routing_id());
     BrowserThread::PostTaskAndReplyWithResult(
         BrowserThread::IO, FROM_HERE,
-        base::BindOnce(&BeginResourceDownload, std::move(params),
-                       std::move(request),
-                       GetURLLoaderFactoryGetter(
-                           browser_context_, params->render_process_host_id(),
-                           params->render_frame_host_routing_id()),
-                       content::DownloadItem::kInvalidId,
-                       weak_factory_.GetWeakPtr()),
+        base::BindOnce(
+            &BeginResourceDownload, std::move(params), std::move(request),
+            storage_partition->url_loader_factory_getter(),
+            make_scoped_refptr(storage_partition->GetFileSystemContext()),
+            content::DownloadItem::kInvalidId, weak_factory_.GetWeakPtr()),
         base::BindOnce(&DownloadManagerImpl::AddUrlDownloadHandler,
                        weak_factory_.GetWeakPtr()));
   } else {
diff --git a/content/browser/download/download_request_core.cc b/content/browser/download/download_request_core.cc
index 7a49194..49d60f75 100644
--- a/content/browser/download/download_request_core.cc
+++ b/content/browser/download/download_request_core.cc
@@ -65,6 +65,7 @@
   uint32_t download_id() const { return download_id_; }
   std::string guid() const { return guid_; }
   bool is_transient() const { return transient_; }
+  bool fetch_error_body() const { return fetch_error_body_; }
   const DownloadUrlParameters::OnStartedCallback& callback() const {
     return on_started_callback_;
   }
@@ -75,6 +76,7 @@
   std::unique_ptr<DownloadSaveInfo> save_info_;
   uint32_t download_id_ = DownloadItem::kInvalidId;
   std::string guid_;
+  bool fetch_error_body_ = false;
   bool transient_ = false;
   DownloadUrlParameters::OnStartedCallback on_started_callback_;
 };
@@ -91,6 +93,7 @@
       new DownloadSaveInfo(parameters->GetSaveInfo()));
   request_data->download_id_ = download_id;
   request_data->guid_ = parameters->guid();
+  request_data->fetch_error_body_ = parameters->fetch_error_body();
   request_data->transient_ = parameters->is_transient();
   request_data->on_started_callback_ = parameters->callback();
   request->SetUserData(&kKey, std::move(request_data));
@@ -131,6 +134,7 @@
     : delegate_(delegate),
       request_(request),
       download_id_(DownloadItem::kInvalidId),
+      fetch_error_body_(false),
       transient_(false),
       bytes_read_(0),
       pause_count_(0),
@@ -165,6 +169,7 @@
     save_info_ = request_data->TakeSaveInfo();
     download_id_ = request_data->download_id();
     guid_ = request_data->guid();
+    fetch_error_body_ = request_data->fetch_error_body();
     transient_ = request_data->is_transient();
     on_started_callback_ = request_data->callback();
     DownloadRequestData::Detach(request_);
@@ -200,6 +205,7 @@
   create_info->transient = transient_;
   create_info->response_headers = request()->response_headers();
   create_info->offset = create_info->save_info->offset;
+  create_info->fetch_error_body = fetch_error_body_;
   return create_info;
 }
 
@@ -212,7 +218,7 @@
   DownloadInterruptReason result =
       request()->response_headers()
           ? HandleSuccessfulServerResponse(*request()->response_headers(),
-                                           save_info_.get())
+                                           save_info_.get(), fetch_error_body_)
           : DOWNLOAD_INTERRUPT_REASON_NONE;
 
   if (request()->response_headers()) {
diff --git a/content/browser/download/download_request_core.h b/content/browser/download/download_request_core.h
index 52fd227..130ab42f 100644
--- a/content/browser/download/download_request_core.h
+++ b/content/browser/download/download_request_core.h
@@ -126,6 +126,7 @@
   std::unique_ptr<DownloadSaveInfo> save_info_;
   uint32_t download_id_;
   std::string guid_;
+  bool fetch_error_body_;
   bool transient_;
   DownloadUrlParameters::OnStartedCallback on_started_callback_;
 
diff --git a/content/browser/download/download_response_handler.cc b/content/browser/download/download_response_handler.cc
index 2e1bc68..7419a69 100644
--- a/content/browser/download/download_response_handler.cc
+++ b/content/browser/download/download_response_handler.cc
@@ -50,7 +50,8 @@
     Delegate* delegate,
     std::unique_ptr<DownloadSaveInfo> save_info,
     bool is_parallel_request,
-    bool is_transient)
+    bool is_transient,
+    bool fetch_error_body)
     : delegate_(delegate),
       started_(false),
       save_info_(std::move(save_info)),
@@ -58,6 +59,7 @@
       method_(resource_request->method),
       referrer_(resource_request->referrer),
       is_transient_(is_transient),
+      fetch_error_body_(fetch_error_body),
       has_strong_validators_(false) {
   if (!is_parallel_request)
     RecordDownloadCount(UNTHROTTLED_COUNT);
@@ -109,9 +111,10 @@
       base::Time::Now(), net::NetLogWithSource(), std::move(save_info_));
 
   DownloadInterruptReason result =
-      head.headers ? HandleSuccessfulServerResponse(
-                         *head.headers, create_info->save_info.get())
-                   : DOWNLOAD_INTERRUPT_REASON_NONE;
+      head.headers
+          ? HandleSuccessfulServerResponse(
+                *head.headers, create_info->save_info.get(), fetch_error_body_)
+          : DOWNLOAD_INTERRUPT_REASON_NONE;
 
   create_info->result = result;
   if (result == DOWNLOAD_INTERRUPT_REASON_NONE)
diff --git a/content/browser/download/download_response_handler.h b/content/browser/download/download_response_handler.h
index 0881b1d..5115110 100644
--- a/content/browser/download/download_response_handler.h
+++ b/content/browser/download/download_response_handler.h
@@ -38,7 +38,8 @@
                           Delegate* delegate,
                           std::unique_ptr<DownloadSaveInfo> save_info,
                           bool is_parallel_request,
-                          bool is_transient);
+                          bool is_transient,
+                          bool fetch_error_body);
   ~DownloadResponseHandler() override;
 
   // mojom::URLLoaderClient
@@ -77,6 +78,7 @@
   std::string method_;
   GURL referrer_;
   bool is_transient_;
+  bool fetch_error_body_;
   net::CertStatus cert_status_;
   bool has_strong_validators_;
   GURL origin_;
diff --git a/content/browser/download/download_utils.cc b/content/browser/download/download_utils.cc
index 3891418..7bf8252 100644
--- a/content/browser/download/download_utils.cc
+++ b/content/browser/download/download_utils.cc
@@ -274,7 +274,9 @@
 
 DownloadInterruptReason HandleSuccessfulServerResponse(
     const net::HttpResponseHeaders& http_headers,
-    DownloadSaveInfo* save_info) {
+    DownloadSaveInfo* save_info,
+    bool fetch_error_body) {
+  DownloadInterruptReason result = DOWNLOAD_INTERRUPT_REASON_NONE;
   switch (http_headers.response_code()) {
     case -1:  // Non-HTTP request.
     case net::HTTP_OK:
@@ -300,22 +302,22 @@
     // resource not being found since there is no entity to download.
 
     case net::HTTP_NOT_FOUND:
-      return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
+      result = DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
       break;
 
     case net::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE:
       // Retry by downloading from the start automatically:
       // If we haven't received data when we get this error, we won't.
-      return DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE;
+      result = DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE;
       break;
     case net::HTTP_UNAUTHORIZED:
     case net::HTTP_PROXY_AUTHENTICATION_REQUIRED:
       // Server didn't authorize this request.
-      return DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED;
+      result = DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED;
       break;
     case net::HTTP_FORBIDDEN:
       // Server forbids access to this resource.
-      return DOWNLOAD_INTERRUPT_REASON_SERVER_FORBIDDEN;
+      result = DOWNLOAD_INTERRUPT_REASON_SERVER_FORBIDDEN;
       break;
     default:  // All other errors.
       // Redirection and informational codes should have been handled earlier
@@ -325,20 +327,26 @@
       // This will change extensions::api::download::InterruptReason.
       DCHECK_NE(3, http_headers.response_code() / 100);
       DCHECK_NE(1, http_headers.response_code() / 100);
-      return DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED;
+      result = DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED;
   }
 
+  if (result != DOWNLOAD_INTERRUPT_REASON_NONE && !fetch_error_body)
+    return result;
+
   // The caller is expecting a partial response.
   if (save_info && (save_info->offset > 0 || save_info->length > 0)) {
     if (http_headers.response_code() != net::HTTP_PARTIAL_CONTENT) {
       // Server should send partial content when "If-Match" or
       // "If-Unmodified-Since" check passes, and the range request header has
       // last byte position. e.g. "Range:bytes=50-99".
-      if (save_info->length != DownloadSaveInfo::kLengthFullContent)
+      if (save_info->length != DownloadSaveInfo::kLengthFullContent &&
+          !fetch_error_body)
         return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
 
       // Requested a partial range, but received the entire response, when
       // the range request header is "Range:bytes={offset}-".
+      // The response can be HTTP 200 or other error code when
+      // |fetch_error_body| is true.
       save_info->offset = 0;
       save_info->hash_of_partial_file.clear();
       save_info->hash_state.reset();
diff --git a/content/browser/download/download_utils.h b/content/browser/download/download_utils.h
index a9f85bc..b1cafe2a 100644
--- a/content/browser/download/download_utils.h
+++ b/content/browser/download/download_utils.h
@@ -35,9 +35,13 @@
 std::unique_ptr<net::URLRequest> CONTENT_EXPORT CreateURLRequestOnIOThread(
     DownloadUrlParameters* params);
 
+// Parse the HTTP server response code.
+// If |fetch_error_body| is true, most of HTTP response codes will be accepted
+// as successful response.
 DownloadInterruptReason CONTENT_EXPORT
 HandleSuccessfulServerResponse(const net::HttpResponseHeaders& http_headers,
-                               DownloadSaveInfo* save_info);
+                               DownloadSaveInfo* save_info,
+                               bool fetch_error_body);
 
 // Parse response headers and update |create_info| accordingly.
 CONTENT_EXPORT void HandleResponseHeaders(
diff --git a/content/browser/download/resource_downloader.cc b/content/browser/download/resource_downloader.cc
index 2b8d74f5..a4be18d 100644
--- a/content/browser/download/resource_downloader.cc
+++ b/content/browser/download/resource_downloader.cc
@@ -4,10 +4,12 @@
 
 #include "content/browser/download/resource_downloader.h"
 
+#include "content/browser/blob_storage/blob_url_loader_factory.h"
 #include "content/browser/download/download_utils.h"
 #include "content/common/throttling_url_loader.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
+#include "storage/browser/fileapi/file_system_context.h"
 
 namespace content {
 
@@ -47,6 +49,7 @@
     std::unique_ptr<DownloadUrlParameters> params,
     std::unique_ptr<ResourceRequest> request,
     scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
+    scoped_refptr<storage::FileSystemContext> file_system_context,
     uint32_t download_id,
     bool is_parallel_request) {
   mojom::URLLoaderFactoryPtr* factory =
@@ -56,9 +59,9 @@
   auto downloader = base::MakeUnique<ResourceDownloader>(
       delegate, std::move(request),
       base::MakeUnique<DownloadSaveInfo>(params->GetSaveInfo()), download_id,
-      params->guid(), is_parallel_request, params->is_transient());
-  downloader->Start(factory, std::move(params));
-
+      params->guid(), is_parallel_request, params->is_transient(),
+      params->fetch_error_body());
+  downloader->Start(factory, file_system_context, std::move(params));
   return downloader;
 }
 
@@ -75,7 +78,7 @@
   auto downloader = base::MakeUnique<ResourceDownloader>(
       delegate, std::move(resource_request),
       base::MakeUnique<DownloadSaveInfo>(), content::DownloadItem::kInvalidId,
-      std::string(), false, false);
+      std::string(), false, false, false);
   downloader->InterceptResponse(std::move(url_loader), response,
                                 std::move(consumer_handle), ssl_status,
                                 std::move(completion_status));
@@ -89,14 +92,17 @@
     uint32_t download_id,
     std::string guid,
     bool is_parallel_request,
-    bool is_transient)
+    bool is_transient,
+    bool fetch_error_body)
     : delegate_(delegate),
       resource_request_(std::move(resource_request)),
       response_handler_(resource_request_.get(),
                         this,
                         std::move(save_info),
                         is_parallel_request,
-                        is_transient),
+                        is_transient,
+                        fetch_error_body),
+      blob_client_binding_(&response_handler_),
       download_id_(download_id),
       guid_(guid),
       weak_ptr_factory_(this) {}
@@ -105,17 +111,28 @@
 
 void ResourceDownloader::Start(
     mojom::URLLoaderFactoryPtr* factory,
+    scoped_refptr<storage::FileSystemContext> file_system_context,
     std::unique_ptr<DownloadUrlParameters> download_url_parameters) {
   callback_ = download_url_parameters->callback();
-  url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
-      factory->get(), std::vector<std::unique_ptr<URLLoaderThrottle>>(),
-      0,  // routing_id
-      0,  // request_id
-      mojom::kURLLoadOptionSendSSLInfo | mojom::kURLLoadOptionSniffMimeType,
-      *(resource_request_.get()), &response_handler_,
-      download_url_parameters->GetNetworkTrafficAnnotation());
-  url_loader_->SetPriority(net::RequestPriority::IDLE,
-                           0 /* intra_priority_value */);
+  if (download_url_parameters->url().SchemeIs(url::kBlobScheme)) {
+    mojom::URLLoaderRequest url_loader_request;
+    mojom::URLLoaderClientPtr client;
+    blob_client_binding_.Bind(mojo::MakeRequest(&client));
+    BlobURLLoaderFactory::CreateLoaderAndStart(
+        std::move(url_loader_request), *(resource_request_.get()),
+        std::move(client), download_url_parameters->GetBlobDataHandle(),
+        file_system_context.get());
+  } else {
+    url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
+        factory->get(), std::vector<std::unique_ptr<URLLoaderThrottle>>(),
+        0,  // routing_id
+        0,  // request_id
+        mojom::kURLLoadOptionSendSSLInfo | mojom::kURLLoadOptionSniffMimeType,
+        *(resource_request_.get()), &response_handler_,
+        download_url_parameters->GetNetworkTrafficAnnotation());
+    url_loader_->SetPriority(net::RequestPriority::IDLE,
+                             0 /* intra_priority_value */);
+  }
 }
 
 void ResourceDownloader::InterceptResponse(
diff --git a/content/browser/download/resource_downloader.h b/content/browser/download/resource_downloader.h
index 6b00e687..a542a80 100644
--- a/content/browser/download/resource_downloader.h
+++ b/content/browser/download/resource_downloader.h
@@ -11,6 +11,7 @@
 #include "content/public/browser/ssl_status.h"
 #include "content/public/common/resource_request.h"
 #include "content/public/common/url_loader.mojom.h"
+#include "mojo/public/cpp/bindings/binding.h"
 
 namespace content {
 
@@ -26,6 +27,7 @@
       std::unique_ptr<DownloadUrlParameters> download_url_parameters,
       std::unique_ptr<ResourceRequest> request,
       scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
+      scoped_refptr<storage::FileSystemContext> file_system_context,
       uint32_t download_id,
       bool is_parallel_request);
 
@@ -45,7 +47,8 @@
                      uint32_t download_id,
                      std::string guid,
                      bool is_parallel_request,
-                     bool is_transient);
+                     bool is_transient,
+                     bool fetch_error_body);
   ResourceDownloader(base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
                      std::unique_ptr<ThrottlingURLLoader> url_loader);
   ~ResourceDownloader() override;
@@ -59,6 +62,7 @@
  private:
   // Helper method to start the network request.
   void Start(mojom::URLLoaderFactoryPtr* factory,
+             scoped_refptr<storage::FileSystemContext> file_system_context,
              std::unique_ptr<DownloadUrlParameters> download_url_parameters);
 
   // Intercepts the navigation response and takes ownership of the |url_loader|.
@@ -80,6 +84,9 @@
   // Object for handing the server response.
   DownloadResponseHandler response_handler_;
 
+  // URLLoaderClient binding for loading a blob.
+  mojo::Binding<mojom::URLLoaderClient> blob_client_binding_;
+
   // ID of the download, or DownloadItem::kInvalidId if this is a new
   // download.
   uint32_t download_id_;
diff --git a/content/browser/frame_host/frame_tree_browsertest.cc b/content/browser/frame_host/frame_tree_browsertest.cc
index 459f3ca..41c2dacb 100644
--- a/content/browser/frame_host/frame_tree_browsertest.cc
+++ b/content/browser/frame_host/frame_tree_browsertest.cc
@@ -7,6 +7,7 @@
 #include "build/build_config.h"
 #include "content/browser/frame_host/frame_tree.h"
 #include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/browser/notification_service.h"
@@ -626,7 +627,7 @@
 
   EXPECT_NE(shell()->web_contents()->GetRenderViewHost(), rvh);
   EXPECT_NE(shell()->web_contents()->GetSiteInstance(), child_instance);
-  EXPECT_NE(shell()->web_contents()->GetRenderProcessHost(), rph);
+  EXPECT_NE(shell()->web_contents()->GetMainFrame()->GetProcess(), rph);
 
   // Ensure that the root node has a proxy for the child node's SiteInstance.
   EXPECT_TRUE(root->render_manager()->GetRenderFrameProxyHost(child_instance));
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 cfcaca7..c4c2621 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
@@ -127,10 +127,13 @@
   SendInput(base::MakeUnique<InputMsg_SelectRange>(routing_id_, point, extent));
 }
 
-void LegacyIPCFrameInputHandler::AdjustSelectionByCharacterOffset(int32_t start,
-                                                                  int32_t end) {
+void LegacyIPCFrameInputHandler::AdjustSelectionByCharacterOffset(
+    int32_t start,
+    int32_t end,
+    blink::mojom::SelectionMenuBehavior selection_menu_behavior) {
   SendInput(base::MakeUnique<InputMsg_AdjustSelectionByCharacterOffset>(
-      routing_id_, start, end));
+      routing_id_, start, end,
+      selection_menu_behavior == blink::mojom::SelectionMenuBehavior::kShow));
 }
 
 void LegacyIPCFrameInputHandler::MoveRangeSelectionExtent(
diff --git a/content/browser/frame_host/input/legacy_ipc_frame_input_handler.h b/content/browser/frame_host/input/legacy_ipc_frame_input_handler.h
index 7db8410..4f56627 100644
--- a/content/browser/frame_host/input/legacy_ipc_frame_input_handler.h
+++ b/content/browser/frame_host/input/legacy_ipc_frame_input_handler.h
@@ -45,7 +45,10 @@
   void SelectAll() override;
   void CollapseSelection() override;
   void SelectRange(const gfx::Point& base, const gfx::Point& extent) override;
-  void AdjustSelectionByCharacterOffset(int32_t start, int32_t end) override;
+  void AdjustSelectionByCharacterOffset(
+      int32_t start,
+      int32_t end,
+      blink::mojom::SelectionMenuBehavior selection_menu_behavior) override;
   void MoveRangeSelectionExtent(const gfx::Point& extent) override;
   void ScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect) override;
   void MoveCaret(const gfx::Point& point) override;
diff --git a/content/browser/frame_host/interstitial_page_impl.cc b/content/browser/frame_host/interstitial_page_impl.cc
index 28a7ddf..daedc9e 100644
--- a/content/browser/frame_host/interstitial_page_impl.cc
+++ b/content/browser/frame_host/interstitial_page_impl.cc
@@ -4,6 +4,8 @@
 
 #include "content/browser/frame_host/interstitial_page_impl.h"
 
+#include <map>
+#include <string>
 #include <utility>
 #include <vector>
 
@@ -170,7 +172,8 @@
           this,
           this,
           static_cast<WebContentsImpl*>(web_contents))),
-      original_child_id_(web_contents->GetRenderProcessHost()->GetID()),
+      original_child_id_(
+          web_contents->GetRenderViewHost()->GetProcess()->GetID()),
       original_rvh_id_(web_contents->GetRenderViewHost()->GetRoutingID()),
       should_revert_web_contents_title_(false),
       resource_dispatcher_host_notified_(false),
@@ -211,7 +214,7 @@
       // So we should not discard that new pending navigation entry.
       // See http://crbug.com/9791
       if (new_navigation_ && interstitial->new_navigation_)
-        interstitial->should_discard_pending_nav_entry_= false;
+        interstitial->should_discard_pending_nav_entry_ = false;
       interstitial->DontProceed();
     }
   }
diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
index 25fc173..6390e2c9 100644
--- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc
+++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -24,6 +24,7 @@
 #include "content/browser/frame_host/frame_tree.h"
 #include "content/browser/frame_host/navigation_entry_impl.h"
 #include "content/browser/frame_host/navigation_handle_impl.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/common/frame_messages.h"
@@ -58,16 +59,16 @@
 
 namespace {
 
-static std::string kAddNamedFrameScript =
-      "var f = document.createElement('iframe');"
-      "f.name = 'foo-frame-name';"
-      "document.body.appendChild(f);";
-static std::string kAddFrameScript =
-      "var f = document.createElement('iframe');"
-      "document.body.appendChild(f);";
-static std::string kRemoveFrameScript =
-      "var f = document.querySelector('iframe');"
-      "f.parentNode.removeChild(f);";
+static const char kAddNamedFrameScript[] =
+    "var f = document.createElement('iframe');"
+    "f.name = 'foo-frame-name';"
+    "document.body.appendChild(f);";
+static const char kAddFrameScript[] =
+    "var f = document.createElement('iframe');"
+    "document.body.appendChild(f);";
+static const char kRemoveFrameScript[] =
+    "var f = document.querySelector('iframe');"
+    "f.parentNode.removeChild(f);";
 
 }  // namespace
 
@@ -4087,7 +4088,8 @@
 
   // Also check going back in the original tab after a renderer crash.
   NavigationController& controller = shell()->web_contents()->GetController();
-  RenderProcessHost* process = shell()->web_contents()->GetRenderProcessHost();
+  RenderProcessHost* process =
+      shell()->web_contents()->GetMainFrame()->GetProcess();
   RenderProcessHostWatcher crash_observer(
       process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
   process->Shutdown(0, false);
@@ -4864,7 +4866,7 @@
 namespace {
 class RenderProcessKilledObserver : public WebContentsObserver {
  public:
-  RenderProcessKilledObserver(WebContents* web_contents)
+  explicit RenderProcessKilledObserver(WebContents* web_contents)
       : WebContentsObserver(web_contents) {}
   ~RenderProcessKilledObserver() override {}
 
@@ -4873,7 +4875,7 @@
              base::TerminationStatus::TERMINATION_STATUS_PROCESS_WAS_KILLED);
   }
 };
-}
+}  // namespace
 
 // This tests a race in Reload with ReloadType::ORIGINAL_REQUEST_URL, where a
 // cross-origin reload was causing an in-flight replaceState to look like a
@@ -6365,7 +6367,7 @@
 class AllowDialogIPCOnCommitFilter : public BrowserMessageFilter,
                                      public WebContentsDelegate {
  public:
-  AllowDialogIPCOnCommitFilter(WebContents* web_contents)
+  explicit AllowDialogIPCOnCommitFilter(WebContents* web_contents)
       : BrowserMessageFilter(FrameMsgStart),
         render_frame_host_(web_contents->GetMainFrame()) {
     web_contents_observer_.Observe(web_contents);
@@ -6675,7 +6677,7 @@
   scoped_refptr<MessageLoopRunner> message_loop_runner_;
 };
 
-}  // namespace {
+}  // namespace
 
 // Check that NavigationController::LoadURLParams::extra_headers are not copied
 // to subresource requests.
@@ -6785,7 +6787,6 @@
   EXPECT_TRUE(navigation_observer.has_committed());
   EXPECT_FALSE(navigation_observer.was_same_document());
   EXPECT_FALSE(navigation_observer.was_renderer_initiated());
-
 }
 
 // Tests that a same document browser-initiated navigation is properly reported
@@ -6926,6 +6927,59 @@
             controller.GetLastCommittedEntry()->GetURL().spec());
 }
 
+// Same-document navigations can sometimes succeed but then later be blocked by
+// policy (e.g., X-Frame-Options) after a page is restored or reloaded.  Ensure
+// that navigating back from a newly blocked URL in a subframe is not treated as
+// same-document, even if it had been same-document originally.
+// See https://crbug.com/765291.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+                       BackSameDocumentAfterBlockedSubframe) {
+  NavigationControllerImpl& controller = static_cast<NavigationControllerImpl&>(
+      shell()->web_contents()->GetController());
+
+  GURL start_url(embedded_test_server()->GetURL(
+      "/navigation_controller/page_with_iframe_simple.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), start_url));
+
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetFrameTree()
+                            ->root();
+
+  // pushState to a URL that will be blocked by XFO if loaded from scratch.
+  {
+    FrameNavigateParamsCapturer capturer(root->child_at(0));
+    std::string pushStateToXfo =
+        "history.pushState({}, '', '/x-frame-options-deny.html')";
+    EXPECT_TRUE(ExecuteScript(root->child_at(0), pushStateToXfo));
+    capturer.Wait();
+    EXPECT_TRUE(capturer.is_same_document());
+  }
+
+  // Navigate the main frame to another page.
+  GURL new_url(embedded_test_server()->GetURL(
+      "/navigation_controller/simple_page_1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), new_url));
+
+  // Go back, causing the subframe to be blocked by XFO.
+  {
+    TestNavigationObserver observer(shell()->web_contents());
+    controller.GoBack();
+    observer.Wait();
+  }
+  EXPECT_EQ(GURL("data:,"), root->child_at(0)->current_url());
+
+  // Go back again.  This would have been same-document if the prior navigation
+  // had succeeded.
+  {
+    TestNavigationObserver observer(shell()->web_contents());
+    controller.GoBack();
+    observer.Wait();
+  }
+
+  // Check that the renderer is still alive.
+  EXPECT_TRUE(ExecuteScript(root->child_at(0), "console.log('Success');"));
+}
+
 // If the main frame does a load, it should not be reported as a subframe
 // navigation. This used to occur in the following case:
 // 1. You're on a site with frames.
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 773f314..32ed84f45 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -168,16 +168,6 @@
 #include "device/vr/vr_service.mojom.h"  // nogncheck
 #endif
 
-// This is temporary to try to locate a core trampler.
-// TODO(bcwhite):  Remove when crbug/736675 is resolved.
-#if defined(OS_ANDROID)
-#include "base/metrics/statistics_recorder.h"
-#define VALIDATE_ALL_HISTOGRAMS(x) \
-  base::StatisticsRecorder::ValidateAllHistograms(x)
-#else
-#define VALIDATE_ALL_HISTOGRAMS(x)
-#endif
-
 using base::TimeDelta;
 
 namespace content {
@@ -586,8 +576,6 @@
 }
 
 RenderFrameHostImpl::~RenderFrameHostImpl() {
-  VALIDATE_ALL_HISTOGRAMS(11);
-
   // Destroying navigation handle may call into delegates/observers,
   // so we do it early while |this| object is still in a sane state.
   navigation_handle_.reset();
@@ -596,16 +584,12 @@
   // RenderFrameHost during cleanup.
   ClearAllWebUI();
 
-  VALIDATE_ALL_HISTOGRAMS(12);
-
   SetLastCommittedSiteUrl(GURL());
 
   GetProcess()->RemoveRoute(routing_id_);
   g_routing_id_frame_map.Get().erase(
       RenderFrameHostID(GetProcess()->GetID(), routing_id_));
 
-  VALIDATE_ALL_HISTOGRAMS(13);
-
   if (overlay_routing_token_)
     g_token_frame_map.Get().erase(*overlay_routing_token_);
 
@@ -614,15 +598,11 @@
   if (delegate_ && render_frame_created_)
     delegate_->RenderFrameDeleted(this);
 
-  VALIDATE_ALL_HISTOGRAMS(14);
-
   // If this was the last active frame in the SiteInstance, the
   // DecrementActiveFrameCount call will trigger the deletion of the
   // SiteInstance's proxies.
   GetSiteInstance()->DecrementActiveFrameCount();
 
-  VALIDATE_ALL_HISTOGRAMS(15);
-
   // If this RenderFrameHost is swapping with a RenderFrameProxyHost, the
   // RenderFrame will already be deleted in the renderer process. Main frame
   // RenderFrames will be cleaned up as part of deleting its RenderView if the
@@ -639,26 +619,18 @@
   // the dtor has run.  (It may also be null in tests.)
   swapout_event_monitor_timeout_.reset();
 
-  VALIDATE_ALL_HISTOGRAMS(16);
-
   for (const auto& iter : visual_state_callbacks_)
     iter.second.Run(false);
 
-  VALIDATE_ALL_HISTOGRAMS(17);
-
   if (render_widget_host_ &&
       render_widget_host_->owned_by_render_frame_host()) {
     // Shutdown causes the RenderWidgetHost to delete itself.
     render_widget_host_->ShutdownAndDestroyWidget(true);
   }
 
-  VALIDATE_ALL_HISTOGRAMS(18);
-
   // Notify the FrameTree that this RFH is going away, allowing it to shut down
   // the corresponding RenderViewHost if it is no longer needed.
   frame_tree_->ReleaseRenderViewHostRef(render_view_host_);
-
-  VALIDATE_ALL_HISTOGRAMS(19);
 }
 
 int RenderFrameHostImpl::GetRoutingID() {
@@ -1907,16 +1879,12 @@
   if (!is_waiting_for_swapout_ack_)
     return;
 
-  VALIDATE_ALL_HISTOGRAMS(21);
-
   TRACE_EVENT_ASYNC_END0("navigation", "RenderFrameHostImpl::SwapOut", this);
   if (swapout_event_monitor_timeout_)
     swapout_event_monitor_timeout_->Stop();
 
   ClearAllWebUI();
 
-  VALIDATE_ALL_HISTOGRAMS(22);
-
   // If this is a main frame RFH that's about to be deleted, update its RVH's
   // swapped-out state here. https://crbug.com/505887
   if (frame_tree_node_->IsMainFrame()) {
@@ -1924,13 +1892,9 @@
     render_view_host_->set_is_swapped_out(true);
   }
 
-  VALIDATE_ALL_HISTOGRAMS(23);
-
   bool deleted =
       frame_tree_node_->render_manager()->DeleteFromPendingList(this);
   CHECK(deleted);
-
-  VALIDATE_ALL_HISTOGRAMS(24);
 }
 
 void RenderFrameHostImpl::DisableSwapOutTimerForTesting() {
diff --git a/content/browser/frame_host/render_frame_host_impl_browsertest.cc b/content/browser/frame_host/render_frame_host_impl_browsertest.cc
index ca7c620..e03378fb 100644
--- a/content/browser/frame_host/render_frame_host_impl_browsertest.cc
+++ b/content/browser/frame_host/render_frame_host_impl_browsertest.cc
@@ -692,4 +692,64 @@
   EXPECT_EQ(xhr_loaded_title, watcher.WaitAndGetTitle());
 }
 
+// A browser-initiated javascript-url navigation must not prevent the current
+// document from loading.
+// See https://crbug.com/766149.
+IN_PROC_BROWSER_TEST_F(ContentBrowserTest,
+                       BrowserInitiatedJavascriptUrlDoNotPreventLoading) {
+  ControllableHttpResponse main_document_response(embedded_test_server(),
+                                                  "/main_document");
+  EXPECT_TRUE(embedded_test_server()->Start());
+
+  GURL main_document_url(embedded_test_server()->GetURL("/main_document"));
+  TestNavigationManager main_document_observer(shell()->web_contents(),
+                                               main_document_url);
+
+  // 1) Navigate. Send the header but not the body. The navigation commits in
+  //    the browser. The renderer is still loading the document.
+  {
+    shell()->LoadURL(main_document_url);
+    EXPECT_TRUE(main_document_observer.WaitForRequestStart());
+    main_document_observer.ResumeNavigation();  // Send the request.
+
+    main_document_response.WaitForRequest();
+    main_document_response.Send(
+        "HTTP/1.1 200 OK\r\n"
+        "Connection: close\r\n"
+        "Content-Type: text/html; charset=utf-8\r\n"
+        "\r\n");
+
+    EXPECT_TRUE(main_document_observer.WaitForResponse());
+    main_document_observer.ResumeNavigation();  // Commit the navigation.
+  }
+
+  // 2) A browser-initiated javascript-url navigation happens.
+  {
+    GURL javascript_url(
+        "javascript:window.domAutomationController.send('done')");
+    shell()->LoadURL(javascript_url);
+    DOMMessageQueue dom_message_queue(WebContents::FromRenderFrameHost(
+        shell()->web_contents()->GetMainFrame()));
+    std::string done;
+    EXPECT_TRUE(dom_message_queue.WaitForMessage(&done));
+    EXPECT_EQ("\"done\"", done);
+  }
+
+  // 3) The end of the response is issued. The renderer must be able to receive
+  //    it.
+  {
+    const base::string16 document_loaded_title =
+        base::ASCIIToUTF16("document loaded");
+    TitleWatcher watcher(shell()->web_contents(), document_loaded_title);
+    main_document_response.Send(
+        "<script>"
+        "   window.onload = function(){"
+        "     document.title = 'document loaded'"
+        "   }"
+        "</script>");
+    main_document_response.Done();
+    EXPECT_EQ(document_loaded_title, watcher.WaitAndGetTitle());
+  }
+}
+
 }  // namespace content
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc
index 2efe7997..0401dd24 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -1293,6 +1293,14 @@
         dest_url.SchemeIs(kChromeUIScheme)) {
       return SiteInstanceDescriptor(parent_site_instance);
     }
+
+    // TEMPORARY HACK: Don't create OOPIFs on the NTP.  Remove this when the NTP
+    // supports OOPIFs or is otherwise omitted from site isolation policy.
+    // See https://crbug.com/566091.
+    if (GetContentClient()->browser()->ShouldStayInParentProcessForNTP(
+            dest_url, parent_site_instance)) {
+      return SiteInstanceDescriptor(parent_site_instance);
+    }
   }
 
   // If we haven't used our SiteInstance (and thus RVH) yet, then we can use it
diff --git a/content/browser/frame_host/render_frame_host_manager_browsertest.cc b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
index b05e9aa9..8198fbf2 100644
--- a/content/browser/frame_host/render_frame_host_manager_browsertest.cc
+++ b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
@@ -21,6 +21,7 @@
 #include "base/values.h"
 #include "build/build_config.h"
 #include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/browser/frame_host/render_frame_proxy_host.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/site_instance_impl.h"
@@ -1813,7 +1814,7 @@
                         std::string(kChromeUIGpuHost));
   NavigateToURL(shell(), webui_url);
   EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
-                  shell()->web_contents()->GetRenderProcessHost()->GetID()));
+      shell()->web_contents()->GetMainFrame()->GetProcess()->GetID()));
 
   // Crash the renderer of the WebUI page.
   RenderProcessHostWatcher crash_observer(
@@ -1859,7 +1860,7 @@
                         std::string(kChromeUIGpuHost));
   NavigateToURL(shell(), webui_url);
   EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
-                  shell()->web_contents()->GetRenderProcessHost()->GetID()));
+      shell()->web_contents()->GetMainFrame()->GetProcess()->GetID()));
 
   // Visit a debug URL that manages to commit, then go back.
   NavigateToURL(shell(), GURL(kChromeUIDumpURL));
@@ -1892,7 +1893,7 @@
                       std::string(kChromeUIGpuHost)));
   NavigateToURL(shell(), webui_url);
   EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
-                  shell()->web_contents()->GetRenderProcessHost()->GetID()));
+      shell()->web_contents()->GetMainFrame()->GetProcess()->GetID()));
   WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
       shell()->web_contents());
   FrameTreeNode* root = web_contents->GetFrameTree()->root();
@@ -1938,7 +1939,7 @@
                       std::string(kChromeUIGpuHost)));
   NavigateToURL(shell(), webui_url);
   EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
-                  shell()->web_contents()->GetRenderProcessHost()->GetID()));
+      shell()->web_contents()->GetMainFrame()->GetProcess()->GetID()));
 
   // Go back and ensure we have no WebUI bindings.
   TestNavigationObserver back_nav_load_observer(shell()->web_contents());
@@ -1946,7 +1947,7 @@
   back_nav_load_observer.Wait();
   EXPECT_EQ(original_url, shell()->web_contents()->GetLastCommittedURL());
   EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
-                  shell()->web_contents()->GetRenderProcessHost()->GetID()));
+      shell()->web_contents()->GetMainFrame()->GetProcess()->GetID()));
 }
 
 // crbug.com/372360
@@ -1965,7 +1966,7 @@
   // Visit a WebUI page with bindings.
   NavigateToURL(shell(), url1);
   EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
-                  shell()->web_contents()->GetRenderProcessHost()->GetID()));
+      shell()->web_contents()->GetMainFrame()->GetProcess()->GetID()));
   SiteInstance* site_instance1 = shell()->web_contents()->GetSiteInstance();
 
   // Open a new tab. Initially it gets a render view in the original tab's
@@ -2009,7 +2010,7 @@
                         std::string(kChromeUIGpuHost));
   EXPECT_TRUE(NavigateToURL(shell(), web_ui_url));
   EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
-      shell()->web_contents()->GetRenderProcessHost()->GetID()));
+      shell()->web_contents()->GetMainFrame()->GetProcess()->GetID()));
 
   // Capture the SiteInstance before navigating to about:blank to ensure
   // it doesn't change.
@@ -2022,7 +2023,7 @@
   GURL regular_page_url(embedded_test_server()->GetURL("/title2.html"));
   EXPECT_TRUE(NavigateToURL(shell(), regular_page_url));
   EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
-      shell()->web_contents()->GetRenderProcessHost()->GetID()));
+      shell()->web_contents()->GetMainFrame()->GetProcess()->GetID()));
 }
 
 // crbug.com/615274
@@ -2100,7 +2101,8 @@
   // Navigate and try to get page to reference this file in its PageState.
   GURL url1(embedded_test_server()->GetURL("/file_input.html"));
   NavigateToURL(shell(), url1);
-  int process_id = shell()->web_contents()->GetRenderProcessHost()->GetID();
+  int process_id =
+      shell()->web_contents()->GetMainFrame()->GetProcess()->GetID();
   std::unique_ptr<FileChooserDelegate> delegate(new FileChooserDelegate(file));
   shell()->web_contents()->SetDelegate(delegate.get());
   EXPECT_TRUE(
@@ -2120,12 +2122,12 @@
 
   // Navigate to a different process and wait for the old process to exit.
   RenderProcessHostWatcher exit_observer(
-      shell()->web_contents()->GetRenderProcessHost(),
+      shell()->web_contents()->GetMainFrame()->GetProcess(),
       RenderProcessHostWatcher::WATCH_FOR_HOST_DESTRUCTION);
   NavigateToURL(shell(), GetCrossSiteURL("/title1.html"));
   exit_observer.Wait();
   EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
-      shell()->web_contents()->GetRenderProcessHost()->GetID(), file));
+      shell()->web_contents()->GetMainFrame()->GetProcess()->GetID(), file));
 
   // The renderer process should not have been killed.  This is the important
   // part of the test.  If this fails, then we didn't get a PageState to check
@@ -2157,7 +2159,8 @@
   // Navigate to url and get it to reference a file in its PageState.
   GURL url1(embedded_test_server()->GetURL("/file_input.html"));
   NavigateToURL(shell(), url1);
-  int process_id = shell()->web_contents()->GetRenderProcessHost()->GetID();
+  int process_id =
+      shell()->web_contents()->GetMainFrame()->GetProcess()->GetID();
   std::unique_ptr<FileChooserDelegate> delegate(new FileChooserDelegate(file));
   shell()->web_contents()->SetDelegate(delegate.get());
   EXPECT_TRUE(
@@ -2174,12 +2177,12 @@
   // Navigate to a different process without access to the file, and wait for
   // the old process to exit.
   RenderProcessHostWatcher exit_observer(
-      shell()->web_contents()->GetRenderProcessHost(),
+      shell()->web_contents()->GetMainFrame()->GetProcess(),
       RenderProcessHostWatcher::WATCH_FOR_HOST_DESTRUCTION);
   NavigateToURL(shell(), GetCrossSiteURL("/title1.html"));
   exit_observer.Wait();
   EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
-      shell()->web_contents()->GetRenderProcessHost()->GetID(), file));
+      shell()->web_contents()->GetMainFrame()->GetProcess()->GetID(), file));
 
   // Ensure that the file ended up in the PageState of the previous entry.
   NavigationEntry* prev_entry =
@@ -2195,11 +2198,11 @@
   shell()->web_contents()->GetController().GoBack();
   back_nav_load_observer.Wait();
   EXPECT_NE(process_id,
-            shell()->web_contents()->GetRenderProcessHost()->GetID());
+            shell()->web_contents()->GetMainFrame()->GetProcess()->GetID());
 
   // Ensure that the file access still exists in the new process ID.
   EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
-      shell()->web_contents()->GetRenderProcessHost()->GetID(), file));
+      shell()->web_contents()->GetMainFrame()->GetProcess()->GetID(), file));
 
   // Navigate to a same site page to trigger a PageState update and ensure the
   // renderer is not killed.
@@ -2220,7 +2223,8 @@
   NavigateToURL(shell(), url1);
   WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
   FrameTreeNode* root = wc->GetFrameTree()->root();
-  int process_id = shell()->web_contents()->GetRenderProcessHost()->GetID();
+  int process_id =
+      shell()->web_contents()->GetMainFrame()->GetProcess()->GetID();
   std::unique_ptr<FileChooserDelegate> delegate(new FileChooserDelegate(file));
   shell()->web_contents()->SetDelegate(delegate.get());
   EXPECT_TRUE(ExecuteScript(root->child_at(0),
@@ -2247,12 +2251,12 @@
   // Navigate to a different process without access to the file, and wait for
   // the old process to exit.
   RenderProcessHostWatcher exit_observer(
-      shell()->web_contents()->GetRenderProcessHost(),
+      shell()->web_contents()->GetMainFrame()->GetProcess(),
       RenderProcessHostWatcher::WATCH_FOR_HOST_DESTRUCTION);
   NavigateToURL(shell(), GetCrossSiteURL("/title1.html"));
   exit_observer.Wait();
   EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
-      shell()->web_contents()->GetRenderProcessHost()->GetID(), file));
+      shell()->web_contents()->GetMainFrame()->GetProcess()->GetID(), file));
 
   // Ensure that the file ended up in the PageState of the previous entry.
   NavigationEntry* prev_entry =
@@ -2268,11 +2272,11 @@
   shell()->web_contents()->GetController().GoToIndex(0);
   back_nav_load_observer.Wait();
   EXPECT_NE(process_id,
-            shell()->web_contents()->GetRenderProcessHost()->GetID());
+            shell()->web_contents()->GetMainFrame()->GetProcess()->GetID());
 
   // Ensure that the file access still exists in the new process ID.
   EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
-      shell()->web_contents()->GetRenderProcessHost()->GetID(), file));
+      shell()->web_contents()->GetMainFrame()->GetProcess()->GetID(), file));
 
   // Do another in-page navigation in the child to make sure we hear a PageState
   // with the chosen file.
diff --git a/content/browser/geolocation/geolocation_service_impl_unittest.cc b/content/browser/geolocation/geolocation_service_impl_unittest.cc
index 7fd35508de9..c1d2602 100644
--- a/content/browser/geolocation/geolocation_service_impl_unittest.cc
+++ b/content/browser/geolocation/geolocation_service_impl_unittest.cc
@@ -18,6 +18,7 @@
 #include "device/geolocation/public/interfaces/geoposition.mojom.h"
 #include "services/service_manager/public/cpp/bind_source_info.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebFeaturePolicyFeature.h"
 
 using base::test::ScopedFeatureList;
 using blink::mojom::PermissionStatus;
@@ -90,7 +91,13 @@
     permission_manager_.reset(new TestPermissionManager);
   }
 
-  void CreateEmbeddedFrameAndGeolocationService() {
+  void CreateEmbeddedFrameAndGeolocationService(bool allow_via_feature_policy) {
+    if (allow_via_feature_policy) {
+      RenderFrameHostTester::For(main_rfh())
+          ->SimulateFeaturePolicyHeader(
+              blink::WebFeaturePolicyFeature::kGeolocation,
+              std::vector<url::Origin>{url::Origin(kEmbeddedUrl)});
+    }
     RenderFrameHost* embedded_rfh =
         RenderFrameHostTester::For(main_rfh())->AppendChild("");
     RenderFrameHostTester::For(embedded_rfh)->InitializeRenderFrameIfNeeded();
@@ -130,7 +137,7 @@
   ScopedFeatureList feature_list;
   feature_list.InitFromCommandLine(
       features::kUseFeaturePolicyForPermissions.name, std::string());
-  CreateEmbeddedFrameAndGeolocationService();
+  CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/false);
 
   permission_manager()->SetRequestCallback(
       base::Bind([](const PermissionCallback& callback) {
@@ -157,10 +164,7 @@
   ScopedFeatureList feature_list;
   feature_list.InitFromCommandLine(
       features::kUseFeaturePolicyForPermissions.name, std::string());
-  main_test_rfh()->SimulateFeaturePolicyHeader(
-      blink::WebFeaturePolicyFeature::kGeolocation,
-      {url::Origin(kEmbeddedUrl)});
-  CreateEmbeddedFrameAndGeolocationService();
+  CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/true);
 
   permission_manager()->SetRequestCallback(
       base::Bind([](const PermissionCallback& callback) {
@@ -188,7 +192,7 @@
 }
 
 TEST_F(GeolocationServiceTest, PermissionGrantedSync) {
-  CreateEmbeddedFrameAndGeolocationService();
+  CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/true);
   permission_manager()->SetRequestCallback(
       base::Bind([](const PermissionCallback& callback) {
         callback.Run(PermissionStatus::GRANTED);
@@ -215,7 +219,7 @@
 }
 
 TEST_F(GeolocationServiceTest, PermissionDeniedSync) {
-  CreateEmbeddedFrameAndGeolocationService();
+  CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/true);
   permission_manager()->SetRequestCallback(
       base::Bind([](const PermissionCallback& callback) {
         callback.Run(PermissionStatus::DENIED);
@@ -237,7 +241,7 @@
 }
 
 TEST_F(GeolocationServiceTest, PermissionGrantedAsync) {
-  CreateEmbeddedFrameAndGeolocationService();
+  CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/true);
   permission_manager()->SetRequestId(42);
   permission_manager()->SetRequestCallback(
       base::Bind([](const PermissionCallback& permission_callback) {
@@ -270,7 +274,7 @@
 }
 
 TEST_F(GeolocationServiceTest, PermissionDeniedAsync) {
-  CreateEmbeddedFrameAndGeolocationService();
+  CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/true);
   permission_manager()->SetRequestId(42);
   permission_manager()->SetRequestCallback(
       base::Bind([](const PermissionCallback& permission_callback) {
@@ -298,7 +302,7 @@
 }
 
 TEST_F(GeolocationServiceTest, ServiceClosedBeforePermissionResponse) {
-  CreateEmbeddedFrameAndGeolocationService();
+  CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/true);
   permission_manager()->SetRequestId(42);
   GeolocationPtr geolocation;
   service()->CreateGeolocation(mojo::MakeRequest(&geolocation), true);
diff --git a/content/browser/indexed_db/indexed_db_browsertest.cc b/content/browser/indexed_db/indexed_db_browsertest.cc
index 6d933de..10e8e48f 100644
--- a/content/browser/indexed_db/indexed_db_browsertest.cc
+++ b/content/browser/indexed_db/indexed_db_browsertest.cc
@@ -29,6 +29,7 @@
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
@@ -582,7 +583,7 @@
   signal_when_finished->Signal();
 }
 
-const std::string s_corrupt_db_test_prefix = "/corrupt/test/";
+static const char s_corrupt_db_test_prefix[] = "/corrupt/test/";
 
 static std::unique_ptr<net::test_server::HttpResponse> CorruptDBRequestHandler(
     IndexedDBContextImpl* context,
@@ -592,7 +593,8 @@
     const net::test_server::HttpRequest& request) {
   std::string request_path;
   if (path.find(s_corrupt_db_test_prefix) != std::string::npos)
-    request_path = request.relative_url.substr(s_corrupt_db_test_prefix.size());
+    request_path = request.relative_url.substr(
+        std::string(s_corrupt_db_test_prefix).size());
   else
     return std::unique_ptr<net::test_server::HttpResponse>();
 
@@ -711,11 +713,12 @@
                  origin, s_corrupt_db_test_prefix, this));
   embedded_test_server()->StartAcceptingConnections();
 
-  std::string test_file = s_corrupt_db_test_prefix +
+  std::string test_file = std::string(s_corrupt_db_test_prefix) +
                           "corrupted_open_db_detection.html#" + GetParam();
   SimpleTest(embedded_test_server()->GetURL(test_file));
 
-  test_file = s_corrupt_db_test_prefix + "corrupted_open_db_recovery.html";
+  test_file =
+      std::string(s_corrupt_db_test_prefix) + "corrupted_open_db_recovery.html";
   SimpleTest(embedded_test_server()->GetURL(test_file));
 }
 
@@ -820,7 +823,7 @@
   base::string16 expected_title16(ASCIIToUTF16("setVersion(3) complete"));
   TitleWatcher title_watcher(new_shell->web_contents(), expected_title16);
 
-  shell()->web_contents()->GetRenderProcessHost()->Shutdown(0, true);
+  shell()->web_contents()->GetMainFrame()->GetProcess()->Shutdown(0, true);
   shell()->Close();
 
   EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
diff --git a/content/browser/indexed_db/indexed_db_context_impl.cc b/content/browser/indexed_db/indexed_db_context_impl.cc
index b687171..fcf17be 100644
--- a/content/browser/indexed_db/indexed_db_context_impl.cc
+++ b/content/browser/indexed_db/indexed_db_context_impl.cc
@@ -470,6 +470,32 @@
   QueryDiskAndUpdateQuotaUsage(origin);
 }
 
+void IndexedDBContextImpl::AddObserver(
+    IndexedDBContextImpl::Observer* observer) {
+  DCHECK(!observers_.HasObserver(observer));
+  observers_.AddObserver(observer);
+}
+
+void IndexedDBContextImpl::RemoveObserver(
+    IndexedDBContextImpl::Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+void IndexedDBContextImpl::NotifyIndexedDBListChanged(const Origin& origin) {
+  for (auto& observer : observers_)
+    observer.OnIndexedDBListChanged(origin);
+}
+
+void IndexedDBContextImpl::NotifyIndexedDBContentChanged(
+    const Origin& origin,
+    const base::string16& database_name,
+    const base::string16& object_store_name) {
+  for (auto& observer : observers_) {
+    observer.OnIndexedDBContentChanged(origin, database_name,
+                                       object_store_name);
+  }
+}
+
 IndexedDBContextImpl::~IndexedDBContextImpl() {
   if (factory_.get()) {
     TaskRunner()->PostTask(FROM_HERE,
@@ -551,6 +577,7 @@
     quota_manager_proxy()->NotifyStorageModified(
         storage::QuotaClient::kIndexedDatabase, origin.GetURL(),
         storage::kStorageTypeTemporary, difference);
+    NotifyIndexedDBListChanged(origin);
   }
 }
 
diff --git a/content/browser/indexed_db/indexed_db_context_impl.h b/content/browser/indexed_db/indexed_db_context_impl.h
index 5197234..81d70264 100644
--- a/content/browser/indexed_db/indexed_db_context_impl.h
+++ b/content/browser/indexed_db/indexed_db_context_impl.h
@@ -11,7 +11,6 @@
 #include <map>
 #include <memory>
 #include <set>
-#include <string>
 #include <vector>
 
 #include "base/compiler_specific.h"
@@ -51,6 +50,18 @@
     FORCE_CLOSE_REASON_MAX
   };
 
+  class Observer {
+   public:
+    virtual void OnIndexedDBListChanged(const url::Origin& origin) = 0;
+    virtual void OnIndexedDBContentChanged(
+        const url::Origin& origin,
+        const base::string16& database_name,
+        const base::string16& object_store_name) = 0;
+
+   protected:
+    virtual ~Observer() {};
+  };
+
   // The indexed db directory.
   static const base::FilePath::CharType kIndexedDBDirectory[];
 
@@ -125,6 +136,15 @@
 
   bool is_incognito() const { return data_path_.empty(); }
 
+  // Only callable on the IDB task runner.
+  void AddObserver(Observer* observer);
+  void RemoveObserver(Observer* observer);
+
+  void NotifyIndexedDBListChanged(const url::Origin& origin);
+  void NotifyIndexedDBContentChanged(const url::Origin& origin,
+                                     const base::string16& database_name,
+                                     const base::string16& object_store_name);
+
  protected:
   ~IndexedDBContextImpl() override;
 
@@ -162,6 +182,7 @@
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
   std::unique_ptr<std::set<url::Origin>> origin_set_;
   std::map<url::Origin, int64_t> origin_size_map_;
+  base::ObserverList<Observer> observers_;
 
   DISALLOW_COPY_AND_ASSIGN(IndexedDBContextImpl);
 };
diff --git a/content/browser/indexed_db/indexed_db_database.cc b/content/browser/indexed_db/indexed_db_database.cc
index dc061a7..0943ddbd 100644
--- a/content/browser/indexed_db/indexed_db_database.cc
+++ b/content/browser/indexed_db/indexed_db_database.cc
@@ -1380,6 +1380,9 @@
                         ? blink::kWebIDBAdd
                         : blink::kWebIDBPut,
                     IndexedDBKeyRange(*key), &params->value);
+  factory_->NotifyIndexedDBContentChanged(
+      origin(), metadata_.name,
+      metadata_.object_stores[params->object_store_id].name);
   return s;
 }
 
@@ -1678,6 +1681,8 @@
   callbacks->OnSuccess();
   FilterObservation(transaction, object_store_id, blink::kWebIDBDelete,
                     *key_range, nullptr);
+  factory_->NotifyIndexedDBContentChanged(
+      origin(), metadata_.name, metadata_.object_stores[object_store_id].name);
   return s;
 }
 
@@ -1708,6 +1713,8 @@
 
   FilterObservation(transaction, object_store_id, blink::kWebIDBClear,
                     IndexedDBKeyRange(), nullptr);
+  factory_->NotifyIndexedDBContentChanged(
+      origin(), metadata_.name, metadata_.object_stores[object_store_id].name);
   return s;
 }
 
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc b/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
index 73c5e2f..793a82dd 100644
--- a/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
@@ -132,6 +132,23 @@
   callback.Run();
 }
 
+class TestIndexedDBObserver : public IndexedDBContextImpl::Observer {
+ public:
+  void OnIndexedDBListChanged(const url::Origin& origin) override {
+    ++notify_list_changed_count;
+  }
+
+  void OnIndexedDBContentChanged(
+      const url::Origin& origin,
+      const base::string16& database_name,
+      const base::string16& object_store_name) override {
+    ++notify_content_changed_count;
+  }
+
+  int notify_list_changed_count = 0;
+  int notify_content_changed_count = 0;
+};
+
 }  // namespace
 
 class IndexedDBDispatcherHostTest : public testing::Test {
@@ -807,4 +824,314 @@
   EXPECT_EQ(::indexed_db::mojom::Status::OK, callback_result);
 }
 
+TEST_F(IndexedDBDispatcherHostTest, NotifyIndexedDBListChanged) {
+  const int64_t kDBVersion1 = 1;
+  const int64_t kDBVersion2 = 2;
+  const int64_t kDBVersion3 = 3;
+  const int64_t kTransactionId1 = 1;
+  const int64_t kTransactionId2 = 2;
+  const int64_t kTransactionId3 = 3;
+  const int64_t kObjectStoreId = 10;
+  const int64_t kIndexId = 100;
+  const char kObjectStoreName[] = "os";
+  const char kIndexName[] = "index";
+
+  TestIndexedDBObserver observer;
+  context_impl_->AddObserver(&observer);
+
+  // Open connection 1.
+  TestDatabaseConnection connection1(url::Origin(GURL(kOrigin)),
+                                     base::UTF8ToUTF16(kDatabaseName),
+                                     kDBVersion1, kTransactionId1);
+  IndexedDBDatabaseMetadata metadata1;
+  DatabaseAssociatedPtrInfo database_info1;
+  EXPECT_EQ(0, observer.notify_list_changed_count);
+  {
+    base::RunLoop loop;
+    EXPECT_CALL(
+        *connection1.open_callbacks,
+        MockedUpgradeNeeded(IsAssociatedInterfacePtrInfoValid(true),
+                            IndexedDBDatabaseMetadata::NO_VERSION,
+                            blink::kWebIDBDataLossNone, std::string(), _))
+        .WillOnce(testing::DoAll(MoveArg<0>(&database_info1),
+                                 testing::SaveArg<4>(&metadata1),
+                                 RunClosure(loop.QuitClosure())));
+
+    // Queue open request message.
+    connection1.Open(idb_mojo_factory_.get());
+    loop.Run();
+  }
+  EXPECT_TRUE(database_info1.is_valid());
+  EXPECT_EQ(connection1.version, metadata1.version);
+  EXPECT_EQ(connection1.db_name, metadata1.name);
+
+  // Create object store and index.
+  connection1.database.Bind(std::move(database_info1));
+  {
+    ::testing::InSequence dummy;
+    base::RunLoop loop;
+    base::Closure quit_closure = base::BarrierClosure(2, loop.QuitClosure());
+
+    EXPECT_CALL(*connection1.connection_callbacks, Complete(kTransactionId1))
+        .Times(1)
+        .WillOnce(RunClosure(quit_closure));
+    EXPECT_CALL(
+        *connection1.open_callbacks,
+        MockedSuccessDatabase(IsAssociatedInterfacePtrInfoValid(false), _))
+        .Times(1)
+        .WillOnce(RunClosure(quit_closure));
+
+    ASSERT_TRUE(connection1.database.is_bound());
+    connection1.database->CreateObjectStore(kTransactionId1, kObjectStoreId,
+                                            base::UTF8ToUTF16(kObjectStoreName),
+                                            content::IndexedDBKeyPath(), false);
+    connection1.database->CreateIndex(kTransactionId1, kObjectStoreId, kIndexId,
+                                      base::UTF8ToUTF16(kIndexName),
+                                      content::IndexedDBKeyPath(), false,
+                                      false);
+    connection1.database->Commit(kTransactionId1);
+    loop.Run();
+  }
+  EXPECT_EQ(2, observer.notify_list_changed_count);
+  connection1.database->Close();
+
+  // Open connection 2.
+  TestDatabaseConnection connection2(url::Origin(GURL(kOrigin)),
+                                     base::UTF8ToUTF16(kDatabaseName),
+                                     kDBVersion2, kTransactionId2);
+  IndexedDBDatabaseMetadata metadata2;
+  DatabaseAssociatedPtrInfo database_info2;
+  {
+    ::testing::InSequence dummy;
+    base::RunLoop loop;
+    EXPECT_CALL(*connection2.open_callbacks,
+                MockedUpgradeNeeded(IsAssociatedInterfacePtrInfoValid(true),
+                                    kDBVersion1, blink::kWebIDBDataLossNone,
+                                    std::string(), _))
+        .WillOnce(testing::DoAll(MoveArg<0>(&database_info2),
+                                 testing::SaveArg<4>(&metadata2),
+                                 RunClosure(loop.QuitClosure())));
+
+    // Queue open request message.
+    connection2.Open(idb_mojo_factory_.get());
+    loop.Run();
+  }
+  EXPECT_TRUE(database_info2.is_valid());
+  EXPECT_EQ(connection2.version, metadata2.version);
+  EXPECT_EQ(connection2.db_name, metadata2.name);
+
+  // Delete index.
+  connection2.database.Bind(std::move(database_info2));
+  {
+    ::testing::InSequence dummy;
+    base::RunLoop loop;
+    base::Closure quit_closure = base::BarrierClosure(2, loop.QuitClosure());
+
+    EXPECT_CALL(*connection2.connection_callbacks, Complete(kTransactionId2))
+        .Times(1)
+        .WillOnce(RunClosure(quit_closure));
+    EXPECT_CALL(
+        *connection2.open_callbacks,
+        MockedSuccessDatabase(IsAssociatedInterfacePtrInfoValid(false), _))
+        .Times(1)
+        .WillOnce(RunClosure(quit_closure));
+
+    ASSERT_TRUE(connection2.database.is_bound());
+    connection2.database->DeleteIndex(kTransactionId2, kObjectStoreId,
+                                      kIndexId);
+    connection2.database->Commit(kTransactionId2);
+    loop.Run();
+  }
+  EXPECT_EQ(3, observer.notify_list_changed_count);
+  connection2.database->Close();
+
+  // Open connection 3.
+  TestDatabaseConnection connection3(url::Origin(GURL(kOrigin)),
+                                     base::UTF8ToUTF16(kDatabaseName),
+                                     kDBVersion3, kTransactionId3);
+  IndexedDBDatabaseMetadata metadata3;
+  DatabaseAssociatedPtrInfo database_info3;
+  {
+    ::testing::InSequence dummy;
+    base::RunLoop loop;
+    EXPECT_CALL(*connection3.open_callbacks,
+                MockedUpgradeNeeded(IsAssociatedInterfacePtrInfoValid(true),
+                                    kDBVersion2, blink::kWebIDBDataLossNone,
+                                    std::string(), _))
+        .WillOnce(testing::DoAll(MoveArg<0>(&database_info3),
+                                 testing::SaveArg<4>(&metadata3),
+                                 RunClosure(loop.QuitClosure())));
+
+    // Queue open request message.
+    connection3.Open(idb_mojo_factory_.get());
+    loop.Run();
+  }
+  EXPECT_TRUE(database_info3.is_valid());
+  EXPECT_EQ(connection3.version, metadata3.version);
+  EXPECT_EQ(connection3.db_name, metadata3.name);
+
+  // Delete object store.
+  connection3.database.Bind(std::move(database_info3));
+  {
+    ::testing::InSequence dummy;
+    base::RunLoop loop;
+    base::Closure quit_closure = base::BarrierClosure(2, loop.QuitClosure());
+
+    EXPECT_CALL(*connection3.connection_callbacks, Complete(kTransactionId3))
+        .Times(1)
+        .WillOnce(RunClosure(quit_closure));
+    EXPECT_CALL(
+        *connection3.open_callbacks,
+        MockedSuccessDatabase(IsAssociatedInterfacePtrInfoValid(false), _))
+        .Times(1)
+        .WillOnce(RunClosure(quit_closure));
+
+    ASSERT_TRUE(connection3.database.is_bound());
+    connection3.database->DeleteObjectStore(kTransactionId3, kObjectStoreId);
+    connection3.database->Commit(kTransactionId3);
+    loop.Run();
+  }
+  EXPECT_EQ(4, observer.notify_list_changed_count);
+
+  context_impl_->RemoveObserver(&observer);
+}
+
+TEST_F(IndexedDBDispatcherHostTest, NotifyIndexedDBContentChanged) {
+  const int64_t kDBVersion1 = 1;
+  const int64_t kDBVersion2 = 2;
+  const int64_t kTransactionId1 = 1;
+  const int64_t kTransactionId2 = 2;
+  const int64_t kObjectStoreId = 10;
+  const char kObjectStoreName[] = "os";
+
+  TestIndexedDBObserver observer;
+  context_impl_->AddObserver(&observer);
+
+  // Open connection 1.
+  TestDatabaseConnection connection1(url::Origin(GURL(kOrigin)),
+                                     base::UTF8ToUTF16(kDatabaseName),
+                                     kDBVersion1, kTransactionId1);
+  IndexedDBDatabaseMetadata metadata1;
+  DatabaseAssociatedPtrInfo database_info1;
+  EXPECT_EQ(0, observer.notify_list_changed_count);
+  EXPECT_EQ(0, observer.notify_content_changed_count);
+  {
+    base::RunLoop loop;
+    EXPECT_CALL(
+        *connection1.open_callbacks,
+        MockedUpgradeNeeded(IsAssociatedInterfacePtrInfoValid(true),
+                            IndexedDBDatabaseMetadata::NO_VERSION,
+                            blink::kWebIDBDataLossNone, std::string(), _))
+        .WillOnce(testing::DoAll(MoveArg<0>(&database_info1),
+                                 testing::SaveArg<4>(&metadata1),
+                                 RunClosure(loop.QuitClosure())));
+
+    // Queue open request message.
+    connection1.Open(idb_mojo_factory_.get());
+    loop.Run();
+  }
+  EXPECT_TRUE(database_info1.is_valid());
+  EXPECT_EQ(connection1.version, metadata1.version);
+  EXPECT_EQ(connection1.db_name, metadata1.name);
+
+  // Add object store entry.
+  connection1.database.Bind(std::move(database_info1));
+  {
+    ::testing::InSequence dummy;
+    base::RunLoop loop;
+    base::Closure quit_closure = base::BarrierClosure(3, loop.QuitClosure());
+
+    auto put_callbacks =
+        base::MakeUnique<StrictMock<MockMojoIndexedDBCallbacks>>();
+
+    EXPECT_CALL(*put_callbacks, SuccessKey(_))
+        .Times(1)
+        .WillOnce(RunClosure(quit_closure));
+    EXPECT_CALL(*connection1.connection_callbacks, Complete(kTransactionId1))
+        .Times(1)
+        .WillOnce(RunClosure(quit_closure));
+    EXPECT_CALL(
+        *connection1.open_callbacks,
+        MockedSuccessDatabase(IsAssociatedInterfacePtrInfoValid(false), _))
+        .Times(1)
+        .WillOnce(RunClosure(quit_closure));
+
+    ASSERT_TRUE(connection1.database.is_bound());
+    connection1.database->CreateObjectStore(kTransactionId1, kObjectStoreId,
+                                            base::UTF8ToUTF16(kObjectStoreName),
+                                            content::IndexedDBKeyPath(), false);
+    connection1.database->Put(
+        kTransactionId1, kObjectStoreId,
+        ::indexed_db::mojom::Value::New(
+            "value", std::vector<::indexed_db::mojom::BlobInfoPtr>()),
+        content::IndexedDBKey(base::UTF8ToUTF16("key")),
+        blink::kWebIDBPutModeAddOnly,
+        std::vector<content::IndexedDBIndexKeys>(),
+        put_callbacks->CreateInterfacePtrAndBind());
+    connection1.database->Commit(kTransactionId1);
+    loop.Run();
+  }
+  EXPECT_EQ(2, observer.notify_list_changed_count);
+  EXPECT_EQ(1, observer.notify_content_changed_count);
+  connection1.database->Close();
+
+  // Open connection 2.
+  TestDatabaseConnection connection2(url::Origin(GURL(kOrigin)),
+                                     base::UTF8ToUTF16(kDatabaseName),
+                                     kDBVersion2, kTransactionId2);
+  IndexedDBDatabaseMetadata metadata2;
+  DatabaseAssociatedPtrInfo database_info2;
+  {
+    ::testing::InSequence dummy;
+    base::RunLoop loop;
+    EXPECT_CALL(*connection2.open_callbacks,
+                MockedUpgradeNeeded(IsAssociatedInterfacePtrInfoValid(true),
+                                    kDBVersion1, blink::kWebIDBDataLossNone,
+                                    std::string(), _))
+        .WillOnce(testing::DoAll(MoveArg<0>(&database_info2),
+                                 testing::SaveArg<4>(&metadata2),
+                                 RunClosure(loop.QuitClosure())));
+
+    // Queue open request message.
+    connection2.Open(idb_mojo_factory_.get());
+    loop.Run();
+  }
+  EXPECT_TRUE(database_info2.is_valid());
+  EXPECT_EQ(connection2.version, metadata2.version);
+  EXPECT_EQ(connection2.db_name, metadata2.name);
+
+  // Clear object store.
+  connection2.database.Bind(std::move(database_info2));
+  {
+    ::testing::InSequence dummy;
+    base::RunLoop loop;
+    base::Closure quit_closure = base::BarrierClosure(3, loop.QuitClosure());
+
+    auto clear_callbacks =
+        base::MakeUnique<StrictMock<MockMojoIndexedDBCallbacks>>();
+
+    EXPECT_CALL(*clear_callbacks, Success())
+        .Times(1)
+        .WillOnce(RunClosure(quit_closure));
+    EXPECT_CALL(*connection2.connection_callbacks, Complete(kTransactionId2))
+        .Times(1)
+        .WillOnce(RunClosure(quit_closure));
+    EXPECT_CALL(
+        *connection2.open_callbacks,
+        MockedSuccessDatabase(IsAssociatedInterfacePtrInfoValid(false), _))
+        .Times(1)
+        .WillOnce(RunClosure(quit_closure));
+
+    ASSERT_TRUE(connection2.database.is_bound());
+    connection2.database->Clear(kTransactionId2, kObjectStoreId,
+                                clear_callbacks->CreateInterfacePtrAndBind());
+    connection2.database->Commit(kTransactionId2);
+    loop.Run();
+  }
+  EXPECT_EQ(3, observer.notify_list_changed_count);
+  EXPECT_EQ(2, observer.notify_content_changed_count);
+
+  context_impl_->RemoveObserver(&observer);
+}
+
 }  // namespace content
diff --git a/content/browser/indexed_db/indexed_db_factory.h b/content/browser/indexed_db/indexed_db_factory.h
index a1816d1..72551dc 100644
--- a/content/browser/indexed_db/indexed_db_factory.h
+++ b/content/browser/indexed_db/indexed_db_factory.h
@@ -10,7 +10,6 @@
 #include <map>
 #include <memory>
 #include <set>
-#include <string>
 #include <utility>
 
 #include "base/files/file_path.h"
@@ -94,6 +93,11 @@
 
   virtual size_t GetConnectionCount(const url::Origin& origin) const = 0;
 
+  virtual void NotifyIndexedDBContentChanged(
+      const url::Origin& origin,
+      const base::string16& database_name,
+      const base::string16& object_store_name) = 0;
+
  protected:
   friend class base::RefCountedThreadSafe<IndexedDBFactory>;
 
diff --git a/content/browser/indexed_db/indexed_db_factory_impl.cc b/content/browser/indexed_db/indexed_db_factory_impl.cc
index f683909..043749d 100644
--- a/content/browser/indexed_db/indexed_db_factory_impl.cc
+++ b/content/browser/indexed_db/indexed_db_factory_impl.cc
@@ -619,4 +619,14 @@
   return count;
 }
 
+void IndexedDBFactoryImpl::NotifyIndexedDBContentChanged(
+    const url::Origin& origin,
+    const base::string16& database_name,
+    const base::string16& object_store_name) {
+  if (!context_)
+    return;
+  context_->NotifyIndexedDBContentChanged(origin, database_name,
+                                          object_store_name);
+}
+
 }  // namespace content
diff --git a/content/browser/indexed_db/indexed_db_factory_impl.h b/content/browser/indexed_db/indexed_db_factory_impl.h
index ebefeeb7..410af6f1 100644
--- a/content/browser/indexed_db/indexed_db_factory_impl.h
+++ b/content/browser/indexed_db/indexed_db_factory_impl.h
@@ -10,7 +10,6 @@
 #include <map>
 #include <memory>
 #include <set>
-#include <string>
 
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
@@ -80,6 +79,11 @@
 
   size_t GetConnectionCount(const url::Origin& origin) const override;
 
+  void NotifyIndexedDBContentChanged(
+      const url::Origin& origin,
+      const base::string16& database_name,
+      const base::string16& object_store_name) override;
+
  protected:
   ~IndexedDBFactoryImpl() override;
 
diff --git a/content/browser/indexed_db/mock_indexed_db_factory.h b/content/browser/indexed_db/mock_indexed_db_factory.h
index e0c7670..71ae5bdb 100644
--- a/content/browser/indexed_db/mock_indexed_db_factory.h
+++ b/content/browser/indexed_db/mock_indexed_db_factory.h
@@ -8,7 +8,6 @@
 #include <stddef.h>
 
 #include <memory>
-#include <string>
 
 #include "base/macros.h"
 #include "content/browser/indexed_db/indexed_db_factory.h"
@@ -88,6 +87,12 @@
   MOCK_METHOD2(ReportOutstandingBlobs,
                void(const url::Origin& origin, bool blobs_outstanding));
 
+  MOCK_METHOD1(NotifyIndexedDBListChanged, void(const url::Origin& origin));
+  MOCK_METHOD3(NotifyIndexedDBContentChanged,
+               void(const url::Origin& origin,
+                    const base::string16& database_name,
+                    const base::string16& object_store_name));
+
  protected:
   virtual ~MockIndexedDBFactory();
 
diff --git a/content/browser/loader/mojo_async_resource_handler.cc b/content/browser/loader/mojo_async_resource_handler.cc
index d42ac3d..516ddfc 100644
--- a/content/browser/loader/mojo_async_resource_handler.cc
+++ b/content/browser/loader/mojo_async_resource_handler.cc
@@ -382,11 +382,11 @@
       request(), priority, intra_priority_value);
 }
 
-void MojoAsyncResourceHandler::PauseCachingResponseBody() {
+void MojoAsyncResourceHandler::PauseReadingBodyFromNet() {
   NOTREACHED();
 }
 
-void MojoAsyncResourceHandler::ResumeCachingResponseBody() {
+void MojoAsyncResourceHandler::ResumeReadingBodyFromNet() {
   NOTREACHED();
 }
 
diff --git a/content/browser/loader/mojo_async_resource_handler.h b/content/browser/loader/mojo_async_resource_handler.h
index 899e105f..c189a6a 100644
--- a/content/browser/loader/mojo_async_resource_handler.h
+++ b/content/browser/loader/mojo_async_resource_handler.h
@@ -82,8 +82,8 @@
   void FollowRedirect() override;
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override;
-  void PauseCachingResponseBody() override;
-  void ResumeCachingResponseBody() override;
+  void PauseReadingBodyFromNet() override;
+  void ResumeReadingBodyFromNet() override;
 
   void OnWritableForTesting();
   static void SetAllocationSizeForTesting(size_t size);
diff --git a/content/browser/loader/resource_dispatcher_host_browsertest.cc b/content/browser/loader/resource_dispatcher_host_browsertest.cc
index 71add9e..3a1f764 100644
--- a/content/browser/loader/resource_dispatcher_host_browsertest.cc
+++ b/content/browser/loader/resource_dispatcher_host_browsertest.cc
@@ -23,6 +23,7 @@
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/resource_dispatcher_host_delegate.h"
 #include "content/public/browser/resource_request_info.h"
 #include "content/public/browser/web_contents.h"
@@ -270,9 +271,9 @@
 // response to call to AsyncResourceHandler::OnResponseComplete.
 IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
                        SyncXMLHttpRequest_Cancelled) {
-  embedded_test_server()->RegisterRequestHandler(
-      base::Bind(&CancelOnRequest, "/hung",
-                 shell()->web_contents()->GetRenderProcessHost()->GetID()));
+  embedded_test_server()->RegisterRequestHandler(base::Bind(
+      &CancelOnRequest, "/hung",
+      shell()->web_contents()->GetMainFrame()->GetProcess()->GetID()));
 
   ASSERT_TRUE(embedded_test_server()->Start());
   WaitForLoadStop(shell()->web_contents());
diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc
index 94efb12..60bee78 100644
--- a/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -45,6 +45,7 @@
 #include "content/common/view_messages.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/global_request_id.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/resource_context.h"
@@ -911,8 +912,8 @@
         new TestWebContentsObserver(web_contents_.get()));
     web_contents_filter_ = new TestFilterSpecifyingChild(
         browser_context_->GetResourceContext(),
-        web_contents_->GetRenderProcessHost()->GetID());
-    child_ids_.insert(web_contents_->GetRenderProcessHost()->GetID());
+        web_contents_->GetMainFrame()->GetProcess()->GetID());
+    child_ids_.insert(web_contents_->GetMainFrame()->GetProcess()->GetID());
     request_context_getter_ = new net::TestURLRequestContextGetter(
         content::BrowserThread::GetTaskRunnerForThread(
             content::BrowserThread::UI));
@@ -1204,7 +1205,7 @@
                                                          const GURL& url,
                                                          ResourceType type) {
   ResourceRequest request = CreateResourceRequest("GET", type, url);
-  request.origin_pid = web_contents_->GetRenderProcessHost()->GetID();
+  request.origin_pid = web_contents_->GetMainFrame()->GetProcess()->GetID();
   request.render_frame_id = web_contents_->GetMainFrame()->GetRoutingID();
   ResourceHostMsg_RequestResource msg(
       web_contents_->GetRenderViewHost()->GetRoutingID(), request_id, request,
@@ -1246,7 +1247,7 @@
   DownloadManagerImpl::BeginDownloadRequest(
       std::move(request), Referrer(), browser_context_->GetResourceContext(),
       false,  // is_content_initiated
-      web_contents_->GetRenderProcessHost()->GetID(),
+      web_contents_->GetRenderViewHost()->GetProcess()->GetID(),
       web_contents_->GetRenderViewHost()->GetRoutingID(),
       web_contents_->GetMainFrame()->GetRoutingID(), false);
 }
diff --git a/content/browser/media/android/browser_media_player_manager.cc b/content/browser/media/android/browser_media_player_manager.cc
index 0671a0e..d45c0f4 100644
--- a/content/browser/media/android/browser_media_player_manager.cc
+++ b/content/browser/media/android/browser_media_player_manager.cc
@@ -259,7 +259,7 @@
 media::MediaResourceGetter*
 BrowserMediaPlayerManager::GetMediaResourceGetter() {
   if (!media_resource_getter_.get()) {
-    RenderProcessHost* host = web_contents()->GetRenderProcessHost();
+    RenderProcessHost* host = web_contents()->GetMainFrame()->GetProcess();
     BrowserContext* context = host->GetBrowserContext();
     StoragePartition* partition = host->GetStoragePartition();
     storage::FileSystemContext* file_system_context =
@@ -358,11 +358,9 @@
     const MediaPlayerHostMsg_Initialize_Params& media_player_params) {
   DestroyPlayer(media_player_params.player_id);
 
-  RenderProcessHostImpl* host = static_cast<RenderProcessHostImpl*>(
-      web_contents()->GetRenderProcessHost());
-  auto player = CreateMediaPlayer(media_player_params,
-                                  host->GetBrowserContext()->IsOffTheRecord());
-
+  bool is_off_the_record =
+      web_contents()->GetBrowserContext()->IsOffTheRecord();
+  auto player = CreateMediaPlayer(media_player_params, is_off_the_record);
   if (!player)
     return;
 
diff --git a/content/browser/media/capture/desktop_capture_device.cc b/content/browser/media/capture/desktop_capture_device.cc
index ec6a861..d905d071 100644
--- a/content/browser/media/capture/desktop_capture_device.cc
+++ b/content/browser/media/capture/desktop_capture_device.cc
@@ -84,7 +84,7 @@
  public:
   Core(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
        std::unique_ptr<webrtc::DesktopCapturer> capturer,
-       DesktopMediaID::Source type);
+       DesktopMediaID::Type type);
   ~Core() override;
 
   // Implementation of VideoCaptureDevice methods.
@@ -146,7 +146,7 @@
   bool first_capture_returned_;
 
   // The type of the capturer.
-  DesktopMediaID::Source capturer_type_;
+  DesktopMediaID::Type capturer_type_;
 
   // The system time when we receive the first frame.
   base::TimeTicks first_ref_time_;
@@ -165,7 +165,7 @@
 DesktopCaptureDevice::Core::Core(
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     std::unique_ptr<webrtc::DesktopCapturer> capturer,
-    DesktopMediaID::Source type)
+    DesktopMediaID::Type type)
     : task_runner_(task_runner),
       desktop_capturer_(std::move(capturer)),
       capture_in_progress_(false),
@@ -234,7 +234,7 @@
 
   if (!first_capture_returned_) {
     first_capture_returned_ = true;
-    if (capturer_type_ == DesktopMediaID::SOURCE_SCREEN) {
+    if (capturer_type_ == DesktopMediaID::TYPE_SCREEN) {
       IncrementDesktopCaptureCounter(success ? FIRST_SCREEN_CAPTURE_SUCCEEDED
                                              : FIRST_SCREEN_CAPTURE_FAILED);
     } else {
@@ -255,7 +255,7 @@
 
   // The two UMA_ blocks must be put in its own scope since it creates a static
   // variable which expected constant histogram name.
-  if (capturer_type_ == DesktopMediaID::SOURCE_SCREEN) {
+  if (capturer_type_ == DesktopMediaID::TYPE_SCREEN) {
     UMA_HISTOGRAM_TIMES(kUmaScreenCaptureTime, capture_time);
   } else {
     UMA_HISTOGRAM_TIMES(kUmaWindowCaptureTime, capture_time);
@@ -428,8 +428,8 @@
   auto options = CreateDesktopCaptureOptions();
   std::unique_ptr<webrtc::DesktopCapturer> capturer;
 
-  switch (source.source_type) {
-    case DesktopMediaID::SOURCE_SCREEN: {
+  switch (source.type) {
+    case DesktopMediaID::TYPE_SCREEN: {
       std::unique_ptr<webrtc::DesktopCapturer> screen_capturer(
           webrtc::DesktopCapturer::CreateScreenCapturer(options));
       if (screen_capturer && screen_capturer->SelectSource(source.id)) {
@@ -437,13 +437,13 @@
             std::move(screen_capturer), options));
         IncrementDesktopCaptureCounter(SCREEN_CAPTURER_CREATED);
         IncrementDesktopCaptureCounter(
-            source.is_audio_capture() ? SCREEN_CAPTURER_CREATED_WITH_AUDIO
-                                      : SCREEN_CAPTURER_CREATED_WITHOUT_AUDIO);
+            source.audio_share ? SCREEN_CAPTURER_CREATED_WITH_AUDIO
+                               : SCREEN_CAPTURER_CREATED_WITHOUT_AUDIO);
       }
       break;
     }
 
-    case DesktopMediaID::SOURCE_WINDOW: {
+    case DesktopMediaID::TYPE_WINDOW: {
       std::unique_ptr<webrtc::DesktopCapturer> window_capturer =
           webrtc::CroppingWindowCapturer::CreateCapturer(options);
       if (window_capturer && window_capturer->SelectSource(source.id)) {
@@ -460,8 +460,7 @@
 
   std::unique_ptr<media::VideoCaptureDevice> result;
   if (capturer)
-    result.reset(
-        new DesktopCaptureDevice(std::move(capturer), source.source_type));
+    result.reset(new DesktopCaptureDevice(std::move(capturer), source.type));
 
   return result;
 }
@@ -499,7 +498,7 @@
 
 DesktopCaptureDevice::DesktopCaptureDevice(
     std::unique_ptr<webrtc::DesktopCapturer> capturer,
-    DesktopMediaID::Source type)
+    DesktopMediaID::Type type)
     : thread_("desktopCaptureThread") {
 #if defined(OS_WIN)
   // On Windows the thread must be a UI thread.
diff --git a/content/browser/media/capture/desktop_capture_device.h b/content/browser/media/capture/desktop_capture_device.h
index 938f0e3..033cc20 100644
--- a/content/browser/media/capture/desktop_capture_device.h
+++ b/content/browser/media/capture/desktop_capture_device.h
@@ -52,7 +52,7 @@
 
   DesktopCaptureDevice(
       std::unique_ptr<webrtc::DesktopCapturer> desktop_capturer,
-      DesktopMediaID::Source type);
+      DesktopMediaID::Type type);
 
   base::Thread thread_;
   std::unique_ptr<Core> core_;
diff --git a/content/browser/media/capture/desktop_capture_device_aura.cc b/content/browser/media/capture/desktop_capture_device_aura.cc
index b003e728f..a80e012 100644
--- a/content/browser/media/capture/desktop_capture_device_aura.cc
+++ b/content/browser/media/capture/desktop_capture_device_aura.cc
@@ -25,8 +25,8 @@
   aura::Window* window = DesktopMediaID::GetAuraWindowById(source);
   if (window) {
     machine->SetWindow(window);
-    if (source.source_type == DesktopMediaID::SOURCE_SCREEN) {
-      if (source.is_audio_capture())
+    if (source.type == DesktopMediaID::TYPE_SCREEN) {
+      if (source.audio_share)
         IncrementDesktopCaptureCounter(SCREEN_CAPTURER_CREATED_WITH_AUDIO);
       else
         IncrementDesktopCaptureCounter(SCREEN_CAPTURER_CREATED_WITHOUT_AUDIO);
diff --git a/content/browser/media/capture/desktop_capture_device_aura_unittest.cc b/content/browser/media/capture/desktop_capture_device_aura_unittest.cc
index f0b3abcc..1a6654f 100644
--- a/content/browser/media/capture/desktop_capture_device_aura_unittest.cc
+++ b/content/browser/media/capture/desktop_capture_device_aura_unittest.cc
@@ -151,7 +151,7 @@
   std::unique_ptr<media::VideoCaptureDevice> capture_device =
       DesktopCaptureDeviceAura::Create(
           content::DesktopMediaID::RegisterAuraWindow(
-              content::DesktopMediaID::SOURCE_SCREEN, root_window()));
+              content::DesktopMediaID::TYPE_SCREEN, root_window()));
   ASSERT_TRUE(capture_device);
 
   std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
diff --git a/content/browser/media/capture/desktop_capture_device_unittest.cc b/content/browser/media/capture/desktop_capture_device_unittest.cc
index eaead7a..ec0eda7 100644
--- a/content/browser/media/capture/desktop_capture_device_unittest.cc
+++ b/content/browser/media/capture/desktop_capture_device_unittest.cc
@@ -258,7 +258,7 @@
   void CreateScreenCaptureDevice(
       std::unique_ptr<webrtc::DesktopCapturer> capturer) {
     capture_device_.reset(new DesktopCaptureDevice(
-        std::move(capturer), DesktopMediaID::SOURCE_SCREEN));
+        std::move(capturer), DesktopMediaID::TYPE_SCREEN));
   }
 
   void CopyFrame(const uint8_t* frame,
diff --git a/content/browser/media/media_color_browsertest.cc b/content/browser/media/media_color_browsertest.cc
index 6bc9300c..82fbe3d 100644
--- a/content/browser/media/media_color_browsertest.cc
+++ b/content/browser/media/media_color_browsertest.cc
@@ -22,7 +22,13 @@
 
 // Android doesn't support Theora.
 #if !defined(OS_ANDROID)
-IN_PROC_BROWSER_TEST_F(MediaColorTest, Yuv420pTheora) {
+// This fails on Linux: http://crbug.com/767926.
+#if defined(OS_LINUX)
+#define MAYBE_Yuv420pTheora DISABLED_Yuv420pTheora
+#else
+#define MAYBE_Yuv420pTheora Yuv420pTheora
+#endif
+IN_PROC_BROWSER_TEST_F(MediaColorTest, MAYBE_Yuv420pTheora) {
   RunColorTest("yuv420p.ogv");
 }
 
@@ -35,7 +41,13 @@
 }
 #endif  // !defined(OS_ANDROID)
 
-IN_PROC_BROWSER_TEST_F(MediaColorTest, Yuv420pVp8) {
+// This fails on Linux: http://crbug.com/767926.
+#if defined(OS_LINUX)
+#define MAYBE_Yuv420pVp8 DISABLED_Yuv420pVp8
+#else
+#define MAYBE_Yuv420pVp8 Yuv420pVp8
+#endif
+IN_PROC_BROWSER_TEST_F(MediaColorTest, MAYBE_Yuv420pVp8) {
   RunColorTest("yuv420p.webm");
 }
 
@@ -46,8 +58,8 @@
 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
 
 // This fails on some Android devices: http://crbug.com/649199,
-// http://crbug.com/649185.
-#if defined(OS_ANDROID)
+// and Linux: http://crbug.com/767926.
+#if defined(OS_LINUX) || defined(OS_ANDROID)
 #define MAYBE_Yuv420pH264 DISABLED_Yuv420pH264
 #else
 #define MAYBE_Yuv420pH264 Yuv420pH264
@@ -56,9 +68,9 @@
   RunColorTest("yuv420p.mp4");
 }
 
-// This test fails on Android: http://crbug.com/647818, and OSX:
-// http://crbug.com/647838.
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
+// This test fails on Android: http://crbug.com/647818, OSX:
+// http://crbug.com/647838 and Linux: http://crbug.com/767926.
+#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_ANDROID)
 #define MAYBE_Yuvj420pH264 DISABLED_Yuvj420pH264
 #else
 #define MAYBE_Yuvj420pH264 Yuvj420pH264
diff --git a/content/browser/media/media_devices_permission_checker_unittest.cc b/content/browser/media/media_devices_permission_checker_unittest.cc
index a67f43c5..d9b45a4 100644
--- a/content/browser/media/media_devices_permission_checker_unittest.cc
+++ b/content/browser/media/media_devices_permission_checker_unittest.cc
@@ -121,7 +121,8 @@
   // Ensure that the policy is ignored if kUseFeaturePolicyForPermissions is
   // disabled.
   base::test::ScopedFeatureList empty_feature_list;
-  empty_feature_list.Init();
+  empty_feature_list.InitAndDisableFeature(
+      features::kUseFeaturePolicyForPermissions);
   EXPECT_TRUE(CheckPermission(MEDIA_DEVICE_TYPE_AUDIO_INPUT));
   EXPECT_TRUE(CheckPermission(MEDIA_DEVICE_TYPE_VIDEO_INPUT));
 }
diff --git a/content/browser/permissions/permission_service_impl.cc b/content/browser/permissions/permission_service_impl.cc
index 3ac708d..1999795 100644
--- a/content/browser/permissions/permission_service_impl.cc
+++ b/content/browser/permissions/permission_service_impl.cc
@@ -106,11 +106,6 @@
   if (feature_policy_feature == blink::WebFeaturePolicyFeature::kNotFound)
     return true;
 
-  // If there is no frame, there is no policy, so disable the feature for
-  // safety.
-  if (!rfh)
-    return false;
-
   return rfh->IsFeatureEnabled(feature_policy_feature);
 }
 
@@ -342,7 +337,11 @@
   if (!browser_context)
     return PermissionStatus::DENIED;
 
-  if (!browser_context->GetPermissionManager() ||
+  if (!browser_context->GetPermissionManager())
+    return PermissionStatus::DENIED;
+
+  // If there is no frame (i.e. this is a worker) ignore the feature policy.
+  if (context_->render_frame_host() &&
       !AllowedByFeaturePolicy(context_->render_frame_host(), type)) {
     return PermissionStatus::DENIED;
   }
diff --git a/content/browser/permissions/permission_service_impl_unittest.cc b/content/browser/permissions/permission_service_impl_unittest.cc
index 33f59d2..cc0c05c 100644
--- a/content/browser/permissions/permission_service_impl_unittest.cc
+++ b/content/browser/permissions/permission_service_impl_unittest.cc
@@ -161,7 +161,8 @@
   // Ensure that the policy is ignored if kUseFeaturePolicyForPermissions is
   // disabled.
   base::test::ScopedFeatureList empty_feature_list;
-  empty_feature_list.Init();
+  empty_feature_list.InitAndDisableFeature(
+      features::kUseFeaturePolicyForPermissions);
   EXPECT_EQ(PermissionStatus::GRANTED, HasPermission(PermissionName::MIDI));
 }
 
diff --git a/content/browser/renderer_host/delegated_frame_host.h b/content/browser/renderer_host/delegated_frame_host.h
index 4a228fc4..5231b3e 100644
--- a/content/browser/renderer_host/delegated_frame_host.h
+++ b/content/browser/renderer_host/delegated_frame_host.h
@@ -11,11 +11,11 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/memory/weak_ptr.h"
+#include "components/viz/client/frame_evictor.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
 #include "components/viz/common/frame_sinks/begin_frame_source.h"
 #include "components/viz/common/frame_sinks/copy_output_result.h"
 #include "components/viz/host/host_frame_sink_client.h"
-#include "components/viz/service/frame_sinks/frame_evictor.h"
 #include "content/browser/compositor/image_transport_factory.h"
 #include "content/browser/compositor/owned_mailbox.h"
 #include "content/browser/renderer_host/dip_util.h"
diff --git a/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc b/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
index 92cdc20d..e0d8bfc1 100644
--- a/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
+++ b/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
@@ -272,11 +272,11 @@
     return;
   }
 
-  if (desktop_id.source_type == DesktopMediaID::SOURCE_WEB_CONTENTS) {
+  if (desktop_id.type == DesktopMediaID::TYPE_WEB_CONTENTS) {
 #if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
     video_capture_device = WebContentsVideoCaptureDevice::Create(id);
     IncrementDesktopCaptureCounter(TAB_VIDEO_CAPTURER_CREATED);
-    if (desktop_id.is_audio_capture()) {
+    if (desktop_id.audio_share) {
       IncrementDesktopCaptureCounter(TAB_VIDEO_CAPTURER_CREATED_WITH_AUDIO);
     } else {
       IncrementDesktopCaptureCounter(TAB_VIDEO_CAPTURER_CREATED_WITHOUT_AUDIO);
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc
index 488cc34..0eff1c5 100644
--- a/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -1037,8 +1037,7 @@
     return;
   }
 
-  const bool is_screen_capture = video_type == MEDIA_DESKTOP_VIDEO_CAPTURE ||
-                                 audio_type == MEDIA_DESKTOP_AUDIO_CAPTURE;
+  const bool is_screen_capture = video_type == MEDIA_DESKTOP_VIDEO_CAPTURE;
   if (is_screen_capture && !SetupScreenCaptureRequest(request)) {
     FinalizeRequestFailed(label,
                           request,
@@ -1136,16 +1135,12 @@
   DCHECK(request->audio_type() == MEDIA_DESKTOP_AUDIO_CAPTURE ||
          request->video_type() == MEDIA_DESKTOP_VIDEO_CAPTURE);
 
-  // For screen capture we support three valid combinations:
+  // For screen capture we only support two valid combinations:
   // (1) screen video capture only, or
-  // (2) loopback audio capture only, or
-  // (3) screen video capture with loopback audio capture.
-  if (!((request->video_type() == MEDIA_DESKTOP_VIDEO_CAPTURE &&
-         request->audio_type() == MEDIA_NO_SERVICE) ||
-        (request->video_type() == MEDIA_NO_SERVICE &&
-         request->audio_type() == MEDIA_DESKTOP_AUDIO_CAPTURE) ||
-        (request->video_type() == MEDIA_DESKTOP_VIDEO_CAPTURE &&
-         request->audio_type() == MEDIA_DESKTOP_AUDIO_CAPTURE))) {
+  // (2) screen video capture with loopback audio capture.
+  if (request->video_type() != MEDIA_DESKTOP_VIDEO_CAPTURE ||
+      (request->audio_type() != MEDIA_NO_SERVICE &&
+       request->audio_type() != MEDIA_DESKTOP_AUDIO_CAPTURE)) {
     LOG(ERROR) << "Invalid screen capture request.";
     return false;
   }
@@ -1161,19 +1156,9 @@
     }
   }
 
-  std::string audio_device_id;
-  if (request->audio_type() == MEDIA_DESKTOP_AUDIO_CAPTURE) {
-    const std::string& audio_stream_source =
-        request->controls.audio.stream_source;
-
-    if (audio_stream_source == kMediaStreamSourceSystem &&
-        !request->controls.audio.device_id.empty()) {
-      audio_device_id = request->controls.audio.device_id;
-    }
-
-    if (audio_device_id.empty())
-      audio_device_id = video_device_id;
-  }
+  const std::string audio_device_id =
+      request->audio_type() == MEDIA_DESKTOP_AUDIO_CAPTURE ? video_device_id
+                                                           : "";
 
   request->CreateUIRequest(audio_device_id, video_device_id);
   return true;
@@ -1691,7 +1676,7 @@
 
     DesktopMediaID media_id = DesktopMediaID::Parse(device.id);
     // WebContentsVideoCaptureDevice is used for tab/webcontents.
-    if (media_id.source_type == DesktopMediaID::SOURCE_WEB_CONTENTS)
+    if (media_id.type == DesktopMediaID::TYPE_WEB_CONTENTS)
       continue;
 #if defined(USE_AURA)
     // DesktopCaptureDevicAura is used when aura_id is valid.
diff --git a/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc b/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
index 1bb7def..6408784 100644
--- a/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
+++ b/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
@@ -420,7 +420,8 @@
   // Ensure that the policy is ignored if kUseFeaturePolicyForPermissions is
   // disabled.
   base::test::ScopedFeatureList empty_feature_list;
-  empty_feature_list.Init();
+  empty_feature_list.InitAndDisableFeature(
+      features::kUseFeaturePolicyForPermissions);
   GetResultForRequest(CreateRequest(main_rfh(), MEDIA_DEVICE_AUDIO_CAPTURE,
                                     MEDIA_DEVICE_VIDEO_CAPTURE),
                       &devices, &result);
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 38b45c4..5a7b74e6 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -261,16 +261,6 @@
 #define IntToStringType base::IntToString
 #endif
 
-// This is temporary to try to locate a core trampler.
-// TODO(bcwhite):  Remove when crbug/736675 is resolved.
-#if defined(OS_ANDROID)
-#include "base/metrics/statistics_recorder.h"
-#define VALIDATE_ALL_HISTOGRAMS(x) \
-  base::StatisticsRecorder::ValidateAllHistograms(x)
-#else
-#define VALIDATE_ALL_HISTOGRAMS(x)
-#endif
-
 namespace content {
 namespace {
 
@@ -3000,8 +2990,6 @@
   }
   delayed_cleanup_needed_ = false;
 
-  VALIDATE_ALL_HISTOGRAMS(61);
-
   // Records the time when the process starts kept alive by the ref count for
   // UMA.
   if (listeners_.IsEmpty() && keep_alive_ref_count_ > 0 &&
@@ -3029,8 +3017,6 @@
 
   DCHECK_EQ(0, pending_views_);
 
-  VALIDATE_ALL_HISTOGRAMS(62);
-
   // If the process associated with this RenderProcessHost is still alive,
   // notify all observers that the process has exited cleanly, even though it
   // will be destroyed a bit later. Observers shouldn't rely on this process
@@ -3041,17 +3027,12 @@
           this, base::TERMINATION_STATUS_NORMAL_TERMINATION, 0);
     }
   }
-
-  VALIDATE_ALL_HISTOGRAMS(63);
-
   for (auto& observer : observers_)
     observer.RenderProcessHostDestroyed(this);
   NotificationService::current()->Notify(
       NOTIFICATION_RENDERER_PROCESS_TERMINATED,
       Source<RenderProcessHost>(this), NotificationService::NoDetails());
 
-  VALIDATE_ALL_HISTOGRAMS(64);
-
   if (connection_filter_id_ !=
         ServiceManagerConnection::kInvalidConnectionFilterId) {
     ServiceManagerConnection* service_manager_connection =
@@ -3060,8 +3041,6 @@
     service_manager_connection->RemoveConnectionFilter(connection_filter_id_);
     connection_filter_id_ =
         ServiceManagerConnection::kInvalidConnectionFilterId;
-
-    VALIDATE_ALL_HISTOGRAMS(65);
   }
 
 #ifndef NDEBUG
@@ -3070,8 +3049,6 @@
   base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
   deleting_soon_ = true;
 
-  VALIDATE_ALL_HISTOGRAMS(66);
-
   // It's important not to wait for the DeleteTask to delete the channel
   // proxy. Kill it off now. That way, in case the profile is going away, the
   // rest of the objects attached to this RenderProcessHost start going
@@ -3079,22 +3056,16 @@
   // OnChannelClosed() to IPC::ChannelProxy::Context on the IO thread.
   ResetChannelProxy();
 
-  VALIDATE_ALL_HISTOGRAMS(67);
-
   // Its important to remove the kSessionStorageHolder after the channel
   // has been reset to avoid deleting the underlying namespaces prior
   // to processing ipcs referring to them.
   DCHECK(!channel_);
   RemoveUserData(kSessionStorageHolderKey);
 
-  VALIDATE_ALL_HISTOGRAMS(68);
-
   // Remove ourself from the list of renderer processes so that we can't be
   // reused in between now and when the Delete task runs.
   UnregisterHost(GetID());
 
-  VALIDATE_ALL_HISTOGRAMS(69);
-
   instance_weak_factory_.reset(
       new base::WeakPtrFactory<RenderProcessHostImpl>(this));
 }
@@ -3658,7 +3629,6 @@
   // It should not be possible for a process death notification to come in while
   // we are dying.
   DCHECK(!deleting_soon_);
-  VALIDATE_ALL_HISTOGRAMS(10);
 
   // child_process_launcher_ can be NULL in single process mode or if fast
   // termination happened.
@@ -3683,8 +3653,6 @@
 
   RendererClosedDetails details(status, exit_code);
 
-  VALIDATE_ALL_HISTOGRAMS(20);
-
   child_process_launcher_.reset();
   is_dead_ = true;
   if (route_provider_binding_.is_bound())
@@ -3695,8 +3663,6 @@
 
   UpdateProcessPriority();
 
-  VALIDATE_ALL_HISTOGRAMS(30);
-
   within_process_died_observer_ = true;
   NotificationService::current()->Notify(
       NOTIFICATION_RENDERER_PROCESS_CLOSED, Source<RenderProcessHost>(this),
@@ -3707,8 +3673,6 @@
 
   RemoveUserData(kSessionStorageHolderKey);
 
-  VALIDATE_ALL_HISTOGRAMS(40);
-
   base::IDMap<IPC::Listener*>::iterator iter(&listeners_);
   while (!iter.IsAtEnd()) {
     iter.GetCurrentValue()->OnMessageReceived(FrameHostMsg_RenderProcessGone(
@@ -3716,8 +3680,6 @@
     iter.Advance();
   }
 
-  VALIDATE_ALL_HISTOGRAMS(50);
-
   // Initialize a new ChannelProxy in case this host is re-used for a new
   // process. This ensures that new messages can be sent on the host ASAP (even
   // before Init()) and they'll eventually reach the new process.
@@ -3725,8 +3687,6 @@
   // Note that this may have already been called by one of the above observers
   EnableSendQueue();
 
-  VALIDATE_ALL_HISTOGRAMS(60);
-
   // It's possible that one of the calls out to the observers might have caused
   // this object to be no longer needed.
   if (delayed_cleanup_needed_)
@@ -3743,7 +3703,6 @@
 
   // This object is not deleted at this point and might be reused later.
   // TODO(darin): clean this up
-  VALIDATE_ALL_HISTOGRAMS(99);
 }
 
 size_t RenderProcessHost::GetActiveViewCount() {
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.cc b/content/browser/renderer_host/render_widget_host_input_event_router.cc
index 094cdba..48202ab 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router.cc
+++ b/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -41,6 +41,10 @@
 
 void RenderWidgetHostInputEventRouter::OnRenderWidgetHostViewBaseDestroyed(
     RenderWidgetHostViewBase* view) {
+  // RenderWidgetHostViewBase::RemoveObserver() should only ever be called
+  // in this function, except during the shutdown of this class. This prevents
+  // removal of an observed view that is being tracked as an event target
+  // without cleaning up dangling pointers to it.
   view->RemoveObserver(this);
 
   // Remove this view from the owner_map.
@@ -100,6 +104,8 @@
 }
 
 void RenderWidgetHostInputEventRouter::ClearAllObserverRegistrations() {
+  // Since we're shutting down, it's safe to call RenderWidgetHostViewBase::
+  // RemoveObserver() directly here.
   for (auto entry : owner_map_)
     entry.second->RemoveObserver(this);
   owner_map_.clear();
@@ -830,8 +836,12 @@
     const viz::FrameSinkId& id) {
   auto it_to_remove = owner_map_.find(id);
   if (it_to_remove != owner_map_.end()) {
-    it_to_remove->second->RemoveObserver(this);
-    owner_map_.erase(it_to_remove);
+    // If we remove a view from the observer list, we need to be sure to do a
+    // cleanup of the various targets and target maps, else we will end up with
+    // stale values if the view destructs and isn't an observer anymore.
+    // Note: the view the iterator points at will be deleted in the following
+    // call, and shouldn't be used after this point.
+    OnRenderWidgetHostViewBaseDestroyed(it_to_remove->second);
   }
 
   for (auto it = hittest_data_.begin(); it != hittest_data_.end();) {
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
index 5cc2da1..a552a90 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -18,10 +18,10 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/process/process.h"
+#include "components/viz/client/frame_evictor.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
 #include "components/viz/common/frame_sinks/begin_frame_source.h"
 #include "components/viz/common/quads/selection.h"
-#include "components/viz/service/frame_sinks/frame_evictor.h"
 #include "content/browser/renderer_host/input/mouse_wheel_phase_handler.h"
 #include "content/browser/renderer_host/input/stylus_text_selector.h"
 #include "content/browser/renderer_host/render_widget_host_view_base.h"
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 9436f9e7..ac4ddc4 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -779,8 +779,6 @@
       ui::OnScreenKeyboardDisplayManager::GetInstance();
   DCHECK(osk_display_manager);
   if (editable && host_->GetView() && host_->delegate()) {
-    if (keyboard_observer_)
-      osk_display_manager->RemoveObserver(keyboard_observer_.get());
     keyboard_observer_.reset(new WinScreenKeyboardObserver(
         this, location_dips_screen, device_scale_factor_, window_));
     virtual_keyboard_requested_ =
@@ -1587,13 +1585,6 @@
 void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path* mask) const {
 }
 
-void RenderWidgetHostViewAura::OnFirstSurfaceActivation(
-    const viz::SurfaceInfo& surface_info) {
-  if (!is_guest_view_hack_)
-    return;
-  host_->GetView()->OnFirstSurfaceActivation(surface_info);
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // RenderWidgetHostViewAura, ui::EventHandler implementation:
 
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index 35e99f1..208f3bb 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -261,7 +261,6 @@
   void OnWindowTargetVisibilityChanged(bool visible) override;
   bool HasHitTestMask() const override;
   void GetHitTestMask(gfx::Path* mask) const override;
-  void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
 
   // Overridden from ui::EventHandler:
   void OnKeyEvent(ui::KeyEvent* event) override;
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h
index e259ebeb..ba93df4 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -64,7 +64,6 @@
 
 namespace viz {
 class SurfaceHittestDelegate;
-class SurfaceInfo;
 }
 
 namespace content {
@@ -235,7 +234,6 @@
       viz::CompositorFrame frame) = 0;
 
   virtual void OnDidNotProduceFrame(const viz::BeginFrameAck& ack) {}
-  virtual void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) {}
 
   // This method exists to allow removing of displayed graphics, after a new
   // page has been loaded, to prevent the displayed URL from being out of sync
diff --git a/content/browser/sandbox_parameters_mac.mm b/content/browser/sandbox_parameters_mac.mm
index 4658c8a..6338d651 100644
--- a/content/browser/sandbox_parameters_mac.mm
+++ b/content/browser/sandbox_parameters_mac.mm
@@ -70,7 +70,7 @@
                              std::to_string(getpid())));
 
   std::string logging_path =
-      GetContentClient()->browser()->GetLoggingFileName().value();
+      GetContentClient()->browser()->GetLoggingFileName(*command_line).value();
   CHECK(client->SetParameter(Sandbox::kSandboxLoggingPathAsLiteral,
                              logging_path));
 
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
index b53161a..95b2940 100644
--- a/content/browser/security_exploit_browsertest.cc
+++ b/content/browser/security_exploit_browsertest.cc
@@ -111,7 +111,7 @@
     next_rfh = wc->GetRenderManagerForTesting()->pending_frame_host();
 
   EXPECT_TRUE(next_rfh);
-  EXPECT_NE(shell->web_contents()->GetRenderProcessHost()->GetID(),
+  EXPECT_NE(shell->web_contents()->GetMainFrame()->GetProcess()->GetID(),
             next_rfh->GetProcess()->GetID());
 
   return next_rfh;
diff --git a/content/browser/service_manager/service_manager_context.cc b/content/browser/service_manager/service_manager_context.cc
index 27c353f..a94f5b1f 100644
--- a/content/browser/service_manager/service_manager_context.cc
+++ b/content/browser/service_manager/service_manager_context.cc
@@ -19,6 +19,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task_scheduler/post_task.h"
+#include "build/build_config.h"
 #include "content/browser/child_process_launcher.h"
 #include "content/browser/gpu/gpu_process_host.h"
 #include "content/browser/service_manager/common_browser_interfaces.h"
@@ -56,6 +57,7 @@
 #include "services/service_manager/public/interfaces/service.mojom.h"
 #include "services/service_manager/runner/common/client_util.h"
 #include "services/service_manager/runner/host/service_process_launcher.h"
+#include "services/service_manager/sandbox/sandbox_type.h"
 #include "services/service_manager/service_manager.h"
 #include "services/shape_detection/public/interfaces/constants.mojom.h"
 #include "services/video_capture/public/cpp/constants.h"
@@ -67,6 +69,10 @@
 #include "jni/ContentNfcDelegate_jni.h"
 #endif
 
+#if defined(OS_WIN)
+#include "content/browser/renderer_host/dwrite_font_proxy_message_filter_win.h"
+#endif
+
 namespace content {
 
 namespace {
@@ -84,12 +90,18 @@
     service_manager::mojom::ConnectResult query_result,
     const std::string& sandbox_string) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  service_manager::SandboxType sandbox_type =
+      service_manager::UtilitySandboxTypeFromString(sandbox_string);
+
   UtilityProcessHostImpl* process_host =
       new UtilityProcessHostImpl(nullptr, nullptr);
+#if defined(OS_WIN)
+  if (sandbox_type == service_manager::SANDBOX_TYPE_PPAPI)
+    process_host->AddFilter(new DWriteFontProxyMessageFilter());
+#endif
   process_host->SetName(process_name);
   process_host->SetServiceIdentity(service_manager::Identity(service_name));
-  process_host->SetSandboxType(
-      service_manager::UtilitySandboxTypeFromString(sandbox_string));
+  process_host->SetSandboxType(sandbox_type);
   process_host->Start();
 
   service_manager::mojom::ServiceFactoryPtr service_factory;
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc
index 63d6013d..cda33fb 100644
--- a/content/browser/service_worker/service_worker_browsertest.cc
+++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -51,6 +51,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/resource_dispatcher_host.h"
@@ -416,13 +417,13 @@
   return info;
 }
 
-const std::string kNavigationPreloadAbortError =
-    "The service worker navigation preload request was cancelled before "
-    "'preloadResponse' settled. If you intend to use 'preloadResponse', use "
-    "waitUntil() or respondWith() to wait for the promise to settle.";
-const std::string kNavigationPreloadNetworkError =
-    "The service worker navigation preload request failed with a network "
-    "error.";
+const char kNavigationPreloadAbortError[] =
+    "NetworkError: The service worker navigation preload request was cancelled "
+    "before 'preloadResponse' settled. If you intend to use 'preloadResponse', "
+    "use waitUntil() or respondWith() to wait for the promise to settle.";
+const char kNavigationPreloadNetworkError[] =
+    "NetworkError: The service worker navigation preload request failed with "
+    "a network error.";
 
 }  // namespace
 
@@ -468,7 +469,8 @@
 
   void AssociateRendererProcessToPattern(const GURL& pattern) {
     wrapper_->process_manager()->AddProcessReferenceToPattern(
-        pattern, shell()->web_contents()->GetRenderProcessHost()->GetID());
+        pattern,
+        shell()->web_contents()->GetMainFrame()->GetProcess()->GetID());
   }
 
  private:
@@ -1653,7 +1655,8 @@
  private:
   class CustomResponse : public net::test_server::HttpResponse {
    public:
-    CustomResponse(const std::string& response) : response_(response) {}
+    explicit CustomResponse(const std::string& response)
+        : response_(response) {}
     ~CustomResponse() override {}
 
     void SendResponse(
@@ -1976,8 +1979,7 @@
   title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("RESOLVED"));
   NavigateToURL(shell(), page_url);
   EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
-  EXPECT_EQ("NetworkError: " + kNavigationPreloadNetworkError,
-            GetTextContent());
+  EXPECT_EQ(kNavigationPreloadNetworkError, GetTextContent());
 
   console_observer->WaitForConsoleMessages(1);
   const base::string16 expected =
@@ -2000,7 +2002,7 @@
       kWorkerUrl, kEnableNavigationPreloadScript + kPreloadResponseTestScript,
       "text/javascript");
 
-  EXPECT_EQ("NetworkError: " + kNavigationPreloadAbortError,
+  EXPECT_EQ(kNavigationPreloadAbortError,
             LoadNavigationPreloadTestPage(page_url, worker_url, "REJECTED"));
 }
 
@@ -2124,7 +2126,7 @@
   // According to the spec, multiple Location headers is not an error. So the
   // preloadResponse must be resolved with an opaque redirect response.
   // But Chrome treats multiple Location headers as an error (crbug.com/98895).
-  EXPECT_EQ("NetworkError: " + kNavigationPreloadNetworkError,
+  EXPECT_EQ(kNavigationPreloadNetworkError,
             LoadNavigationPreloadTestPage(page_url, worker_url, "REJECTED"));
 
   console_observer->WaitForConsoleMessages(1);
@@ -2161,7 +2163,7 @@
   // preloadResponse must be resolve with an opaque redirect response. But
   // currently Chrome handles the invalid location URL in the browser process as
   // an error. crbug.com/707185
-  EXPECT_EQ("NetworkError: " + kNavigationPreloadNetworkError,
+  EXPECT_EQ(kNavigationPreloadNetworkError,
             LoadNavigationPreloadTestPage(page_url, worker_url, "REJECTED"));
 
   // The page request must be sent only once, since the worker responded with
@@ -2405,7 +2407,7 @@
   StopObserver observer(run_loop.QuitClosure());
   RunOnIOThread(base::Bind(&ServiceWorkerVersion::AddListener,
                            base::Unretained(version_.get()), &observer));
-  shell()->web_contents()->GetRenderProcessHost()->Shutdown(
+  shell()->web_contents()->GetMainFrame()->GetProcess()->Shutdown(
       content::RESULT_CODE_KILLED, false /* wait */);
   run_loop.Run();
 
@@ -2792,9 +2794,9 @@
   }
 
  private:
-  static const std::string kPageUrl;
-  static const std::string kWorkerUrl;
-  static const std::string kScriptUrl;
+  static const char kPageUrl[];
+  static const char kWorkerUrl[];
+  static const char kScriptUrl[];
   static const int kV8CacheTimeStampDataSize;
 
   void RegisterAndActivateServiceWorker() {
@@ -2843,11 +2845,11 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerV8CacheStrategiesTest);
 };
 
-const std::string ServiceWorkerV8CacheStrategiesTest::kPageUrl =
+const char ServiceWorkerV8CacheStrategiesTest::kPageUrl[] =
     "/service_worker/v8_cache_test.html";
-const std::string ServiceWorkerV8CacheStrategiesTest::kWorkerUrl =
+const char ServiceWorkerV8CacheStrategiesTest::kWorkerUrl[] =
     "/service_worker/fetch_event_response_via_cache.js";
-const std::string ServiceWorkerV8CacheStrategiesTest::kScriptUrl =
+const char ServiceWorkerV8CacheStrategiesTest::kScriptUrl[] =
     "/service_worker/v8_cache_test.js";
 // V8ScriptRunner::setCacheTimeStamp() stores 12 byte data (tag + timestamp).
 const int ServiceWorkerV8CacheStrategiesTest::kV8CacheTimeStampDataSize =
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.cc b/content/browser/service_worker/service_worker_dispatcher_host.cc
index 261ac251..82725af 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host.cc
+++ b/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -170,10 +170,6 @@
                         OnIncrementServiceWorkerRefCount)
     IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount,
                         OnDecrementServiceWorkerRefCount)
-    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementRegistrationRefCount,
-                        OnIncrementRegistrationRefCount)
-    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementRegistrationRefCount,
-                        OnDecrementRegistrationRefCount)
     IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_TerminateWorker, OnTerminateWorker)
     IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_EnableNavigationPreload,
                         OnEnableNavigationPreload)
@@ -212,9 +208,14 @@
 }
 
 void ServiceWorkerDispatcherHost::RegisterServiceWorkerRegistrationHandle(
-    std::unique_ptr<ServiceWorkerRegistrationHandle> handle) {
+    ServiceWorkerRegistrationHandle* handle) {
   int handle_id = handle->handle_id();
-  registration_handles_.AddWithID(std::move(handle), handle_id);
+  registration_handles_.AddWithID(base::WrapUnique(handle), handle_id);
+}
+
+void ServiceWorkerDispatcherHost::UnregisterServiceWorkerRegistrationHandle(
+    int handle_id) {
+  registration_handles_.Remove(handle_id);
 }
 
 ServiceWorkerHandle* ServiceWorkerDispatcherHost::FindServiceWorkerHandle(
@@ -234,23 +235,21 @@
   return nullptr;
 }
 
-ServiceWorkerRegistrationHandle*
-ServiceWorkerDispatcherHost::GetOrCreateRegistrationHandle(
+blink::mojom::ServiceWorkerRegistrationObjectInfoPtr
+ServiceWorkerDispatcherHost::CreateRegistrationObjectInfo(
     base::WeakPtr<ServiceWorkerProviderHost> provider_host,
     ServiceWorkerRegistration* registration) {
   DCHECK(provider_host);
   ServiceWorkerRegistrationHandle* existing_handle =
       FindRegistrationHandle(provider_host->provider_id(), registration->id());
   if (existing_handle) {
-    existing_handle->IncrementRefCount();
-    return existing_handle;
+    return existing_handle->CreateObjectInfo();
   }
-  std::unique_ptr<ServiceWorkerRegistrationHandle> new_handle(
-      new ServiceWorkerRegistrationHandle(GetContext()->AsWeakPtr(),
-                                          provider_host, registration));
-  ServiceWorkerRegistrationHandle* new_handle_ptr = new_handle.get();
-  RegisterServiceWorkerRegistrationHandle(std::move(new_handle));
-  return new_handle_ptr;
+  // ServiceWorkerRegistrationHandle ctor will register itself into
+  // |registration_handles_|.
+  auto* new_handle = new ServiceWorkerRegistrationHandle(
+      GetContext()->AsWeakPtr(), this, provider_host, registration);
+  return new_handle->CreateObjectInfo();
 }
 
 base::WeakPtr<ServiceWorkerDispatcherHost>
@@ -878,9 +877,7 @@
     ServiceWorkerRegistration* registration,
     blink::mojom::ServiceWorkerRegistrationObjectInfoPtr* out_info,
     ServiceWorkerVersionAttributes* out_attrs) {
-  ServiceWorkerRegistrationHandle* handle =
-      GetOrCreateRegistrationHandle(provider_host, registration);
-  *out_info = handle->GetObjectInfo();
+  *out_info = CreateRegistrationObjectInfo(provider_host, registration);
 
   out_attrs->installing = provider_host->GetOrCreateServiceWorkerHandle(
       registration->installing_version());
@@ -960,36 +957,6 @@
     handles_.Remove(handle_id);
 }
 
-void ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount(
-    int registration_handle_id) {
-  TRACE_EVENT0("ServiceWorker",
-               "ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount");
-  ServiceWorkerRegistrationHandle* handle =
-      registration_handles_.Lookup(registration_handle_id);
-  if (!handle) {
-    bad_message::ReceivedBadMessage(
-        this, bad_message::SWDH_INCREMENT_REGISTRATION_BAD_HANDLE);
-    return;
-  }
-  handle->IncrementRefCount();
-}
-
-void ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount(
-    int registration_handle_id) {
-  TRACE_EVENT0("ServiceWorker",
-               "ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount");
-  ServiceWorkerRegistrationHandle* handle =
-      registration_handles_.Lookup(registration_handle_id);
-  if (!handle) {
-    bad_message::ReceivedBadMessage(
-        this, bad_message::SWDH_DECREMENT_REGISTRATION_BAD_HANDLE);
-    return;
-  }
-  handle->DecrementRefCount();
-  if (handle->HasNoRefCount())
-    registration_handles_.Remove(registration_handle_id);
-}
-
 void ServiceWorkerDispatcherHost::UnregistrationComplete(
     int thread_id,
     int request_id,
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.h b/content/browser/service_worker/service_worker_dispatcher_host.h
index 0e75e80c..93403538 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host.h
+++ b/content/browser/service_worker/service_worker_dispatcher_host.h
@@ -88,12 +88,12 @@
   // be destroyed.
   bool Send(IPC::Message* message) override;
 
-  // Virtual for testing.
+  // Following methods are virtual only for testing.
   virtual void RegisterServiceWorkerHandle(
       std::unique_ptr<ServiceWorkerHandle> handle);
-  // Virtual for testing.
   virtual void RegisterServiceWorkerRegistrationHandle(
-      std::unique_ptr<ServiceWorkerRegistrationHandle> handle);
+      ServiceWorkerRegistrationHandle* handle);
+  virtual void UnregisterServiceWorkerRegistrationHandle(int handle_id);
 
   ServiceWorkerHandle* FindServiceWorkerHandle(int provider_id,
                                                int64_t version_id);
@@ -107,9 +107,12 @@
       blink::mojom::ServiceWorkerRegistrationObjectInfoPtr* out_info,
       ServiceWorkerVersionAttributes* out_attrs);
 
-  // Returns the existing registration handle whose reference count is
-  // incremented or a newly created one if it doesn't exist.
-  ServiceWorkerRegistrationHandle* GetOrCreateRegistrationHandle(
+  // Returns an object info representing |registration|. The object info holds a
+  // Mojo connection to the ServiceWorkerRegistrationHandle for the
+  // |registration| to ensure the handle stays alive while the object info is
+  // alive. A new handle is created if one does not already exist.
+  blink::mojom::ServiceWorkerRegistrationObjectInfoPtr
+  CreateRegistrationObjectInfo(
       base::WeakPtr<ServiceWorkerProviderHost> provider_host,
       ServiceWorkerRegistration* registration);
 
@@ -166,8 +169,6 @@
   void OnCountFeature(int64_t version_id, uint32_t feature);
   void OnIncrementServiceWorkerRefCount(int handle_id);
   void OnDecrementServiceWorkerRefCount(int handle_id);
-  void OnIncrementRegistrationRefCount(int registration_handle_id);
-  void OnDecrementRegistrationRefCount(int registration_handle_id);
   void OnPostMessageToWorker(
       int handle_id,
       int provider_id,
@@ -212,7 +213,7 @@
 
   ServiceWorkerRegistrationHandle* FindRegistrationHandle(
       int provider_id,
-      int64_t registration_handle_id);
+      int64_t registration_id);
 
   // Callbacks from ServiceWorkerContextCore
   void UpdateComplete(int thread_id,
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.cc b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
index 4d70010..24452b8 100644
--- a/content/browser/service_worker/service_worker_fetch_dispatcher.cc
+++ b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -60,11 +60,11 @@
     loader_->SetPriority(priority, intra_priority_value);
   }
 
-  void PauseCachingResponseBody() override {
-    loader_->PauseCachingResponseBody();
+  void PauseReadingBodyFromNet() override {
+    loader_->PauseReadingBodyFromNet();
   }
-  void ResumeCachingResponseBody() override {
-    loader_->ResumeCachingResponseBody();
+  void ResumeReadingBodyFromNet() override {
+    loader_->ResumeReadingBodyFromNet();
   }
 
   mojom::URLLoaderPtr CreateInterfacePtrAndBind() {
diff --git a/content/browser/service_worker/service_worker_installed_scripts_sender.cc b/content/browser/service_worker/service_worker_installed_scripts_sender.cc
index d500b47..5e14a4c 100644
--- a/content/browser/service_worker/service_worker_installed_scripts_sender.cc
+++ b/content/browser/service_worker/service_worker_installed_scripts_sender.cc
@@ -92,7 +92,7 @@
          ServiceWorkerInstalledScriptsSender* owner)
       : reader_(std::move(reader)),
         owner_(owner),
-        watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL),
+        body_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL),
         weak_factory_(this) {}
 
   void Start() {
@@ -142,9 +142,9 @@
     }
 
     // Start sending body.
-    watcher_.Watch(body_handle_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
-                   base::Bind(&Sender::OnWritableBody, AsWeakPtr()));
-    watcher_.ArmOrNotify();
+    body_watcher_.Watch(body_handle_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
+                        base::Bind(&Sender::OnWritableBody, AsWeakPtr()));
+    body_watcher_.ArmOrNotify();
 
     scoped_refptr<net::HttpResponseHeaders> headers =
         http_info->http_info->headers;
@@ -176,11 +176,11 @@
   void OnWritableBody(MojoResult) {
     // It isn't necessary to handle MojoResult here since BeginWrite() returns
     // an equivalent error.
-    DCHECK(!pending_write_);
+    DCHECK(!body_pending_write_);
     DCHECK(body_handle_.is_valid());
     uint32_t num_bytes = 0;
     MojoResult rv = network::NetToMojoPendingBuffer::BeginWrite(
-        &body_handle_, &pending_write_, &num_bytes);
+        &body_handle_, &body_pending_write_, &num_bytes);
     switch (rv) {
       case MOJO_RESULT_INVALID_ARGUMENT:
       case MOJO_RESULT_BUSY:
@@ -190,17 +190,18 @@
         CompleteSendIfNeeded(FinishedReason::kConnectionError);
         return;
       case MOJO_RESULT_SHOULD_WAIT:
-        watcher_.ArmOrNotify();
+        body_watcher_.ArmOrNotify();
         return;
       case MOJO_RESULT_OK:
-        // |body_handle_| must have been taken by |pending_write_|.
-        DCHECK(pending_write_);
+        // |body_handle_| must have been taken by |body_pending_write_|.
+        DCHECK(body_pending_write_);
         DCHECK(!body_handle_.is_valid());
         break;
     }
 
     scoped_refptr<network::NetToMojoIOBuffer> buffer =
-        base::MakeRefCounted<network::NetToMojoIOBuffer>(pending_write_.get());
+        base::MakeRefCounted<network::NetToMojoIOBuffer>(
+            body_pending_write_.get());
     reader_->ReadData(buffer.get(), num_bytes,
                       base::Bind(&Sender::OnResponseDataRead, AsWeakPtr()));
   }
@@ -209,30 +210,30 @@
     if (read_bytes < 0) {
       ServiceWorkerMetrics::CountReadResponseResult(
           ServiceWorkerMetrics::READ_DATA_ERROR);
-      watcher_.Cancel();
+      body_watcher_.Cancel();
       body_handle_.reset();
       CompleteSendIfNeeded(FinishedReason::kResponseReaderError);
       return;
     }
-    body_handle_ = pending_write_->Complete(read_bytes);
+    body_handle_ = body_pending_write_->Complete(read_bytes);
     DCHECK(body_handle_.is_valid());
-    pending_write_ = nullptr;
+    body_pending_write_ = nullptr;
     ServiceWorkerMetrics::CountReadResponseResult(
         ServiceWorkerMetrics::READ_OK);
     if (read_bytes == 0) {
       // All data has been read.
-      watcher_.Cancel();
+      body_watcher_.Cancel();
       body_handle_.reset();
       CompleteSendIfNeeded(FinishedReason::kSuccess);
       return;
     }
-    watcher_.ArmOrNotify();
+    body_watcher_.ArmOrNotify();
   }
 
   void OnMetaDataSent(MetaDataSender::Status status) {
     meta_data_sender_.reset();
     if (status != MetaDataSender::Status::kSuccess) {
-      watcher_.Cancel();
+      body_watcher_.Cancel();
       body_handle_.reset();
       CompleteSendIfNeeded(FinishedReason::kMetaDataSenderError);
       return;
@@ -257,7 +258,7 @@
   bool WasMetadataWritten() const { return !meta_data_sender_; }
 
   bool WasBodyWritten() const {
-    return !body_handle_.is_valid() && !pending_write_;
+    return !body_handle_.is_valid() && !body_pending_write_;
   }
 
   base::WeakPtr<Sender> AsWeakPtr() { return weak_factory_.GetWeakPtr(); }
@@ -269,12 +270,11 @@
   std::unique_ptr<MetaDataSender> meta_data_sender_;
 
   // For body.
-  scoped_refptr<network::NetToMojoPendingBuffer> pending_write_;
-  mojo::SimpleWatcher watcher_;
-
-  // Pipes.
-  mojo::ScopedDataPipeProducerHandle meta_data_handle_;
+  // Either |body_handle_| or |body_pending_write_| is valid during body is
+  // streamed.
   mojo::ScopedDataPipeProducerHandle body_handle_;
+  scoped_refptr<network::NetToMojoPendingBuffer> body_pending_write_;
+  mojo::SimpleWatcher body_watcher_;
 
   base::WeakPtrFactory<Sender> weak_factory_;
 };
diff --git a/content/browser/service_worker/service_worker_job_unittest.cc b/content/browser/service_worker/service_worker_job_unittest.cc
index 3016242..7eda9d90 100644
--- a/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_job_unittest.cc
@@ -61,8 +61,17 @@
     handles_.push_back(std::move(handle));
   }
   void RegisterServiceWorkerRegistrationHandle(
-      std::unique_ptr<ServiceWorkerRegistrationHandle> handle) override {
-    registration_handles_.push_back(std::move(handle));
+      ServiceWorkerRegistrationHandle* handle) override {
+    registration_handles_.push_back(base::WrapUnique(handle));
+  }
+  void UnregisterServiceWorkerRegistrationHandle(int handle_id) override {
+    auto iter = registration_handles_.begin();
+    for (; iter != registration_handles_.end(); ++iter) {
+      if ((*iter)->handle_id() == handle_id)
+        break;
+    }
+    ASSERT_NE(registration_handles_.end(), iter);
+    registration_handles_.erase(iter);
   }
 
   void RemoveHandles() {
diff --git a/content/browser/service_worker/service_worker_process_manager.cc b/content/browser/service_worker/service_worker_process_manager.cc
index ef13976..738c25b2 100644
--- a/content/browser/service_worker/service_worker_process_manager.cc
+++ b/content/browser/service_worker/service_worker_process_manager.cc
@@ -14,6 +14,7 @@
 #include "content/browser/site_instance_impl.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/site_instance.h"
+#include "content/public/common/browser_side_navigation_policy.h"
 #include "content/public/common/child_process_host.h"
 #include "url/gurl.h"
 
@@ -182,7 +183,10 @@
   DCHECK(!base::ContainsKey(instance_info_, embedded_worker_id))
       << embedded_worker_id << " already has a process allocated";
 
-  if (can_use_existing_process) {
+  // In non-PlzNavigate, we must manually track renderer processes in order to
+  // use an existing process. In PlzNavigate, we can depend on SiteInstance to
+  // return an existing process, so just skip this part.
+  if (!content::IsBrowserSideNavigationEnabled() && can_use_existing_process) {
     int process_id = FindAvailableProcess(pattern);
     if (process_id != ChildProcessHost::kInvalidUniqueID) {
       RenderProcessHost::FromID(process_id)->IncrementKeepAliveRefCount();
diff --git a/content/browser/service_worker/service_worker_process_manager.h b/content/browser/service_worker/service_worker_process_manager.h
index 10ba8a5..5fb9dd4d 100644
--- a/content/browser/service_worker/service_worker_process_manager.h
+++ b/content/browser/service_worker/service_worker_process_manager.h
@@ -114,8 +114,9 @@
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTest, SortProcess);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTest,
                            FindAvailableProcess);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTest,
-                           AllocateWorkerProcess_FindAvailableProcess);
+  FRIEND_TEST_ALL_PREFIXES(
+      ServiceWorkerProcessManagerTest,
+      AllocateWorkerProcess_FindAvailableProcess_NonPlzNavigate);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTest,
                            AllocateWorkerProcess_WithProcessReuse);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTest,
diff --git a/content/browser/service_worker/service_worker_process_manager_unittest.cc b/content/browser/service_worker/service_worker_process_manager_unittest.cc
index a88ece9..01dca660 100644
--- a/content/browser/service_worker/service_worker_process_manager_unittest.cc
+++ b/content/browser/service_worker/service_worker_process_manager_unittest.cc
@@ -6,9 +6,11 @@
 
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/test/scoped_feature_list.h"
 #include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/common/service_worker/embedded_worker_settings.h"
 #include "content/public/common/child_process_host.h"
+#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"
@@ -108,8 +110,13 @@
   EXPECT_EQ(host3->GetID(), process_manager_->FindAvailableProcess(pattern_));
 }
 
+// This tests the process host tracking by ServiceWorkerProcessManager
+// which only is done when PlzNavigate is disabled.
 TEST_F(ServiceWorkerProcessManagerTest,
-       AllocateWorkerProcess_FindAvailableProcess) {
+       AllocateWorkerProcess_FindAvailableProcess_NonPlzNavigate) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndDisableFeature(features::kBrowserSideNavigation);
+
   const int kEmbeddedWorkerId1 = 100;
   const int kEmbeddedWorkerId2 = 200;
   const int kEmbeddedWorkerId3 = 300;
diff --git a/content/browser/service_worker/service_worker_registration_handle.cc b/content/browser/service_worker/service_worker_registration_handle.cc
index 59658c4..dffa2a7 100644
--- a/content/browser/service_worker/service_worker_registration_handle.cc
+++ b/content/browser/service_worker/service_worker_registration_handle.cc
@@ -5,7 +5,9 @@
 #include "content/browser/service_worker/service_worker_registration_handle.h"
 
 #include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_dispatcher_host.h"
 #include "content/browser/service_worker/service_worker_handle.h"
+#include "content/browser/service_worker/service_worker_provider_host.h"
 #include "content/common/service_worker/service_worker_messages.h"
 #include "content/common/service_worker/service_worker_types.h"
 #include "content/public/common/service_worker_modes.h"
@@ -15,30 +17,24 @@
 
 ServiceWorkerRegistrationHandle::ServiceWorkerRegistrationHandle(
     base::WeakPtr<ServiceWorkerContextCore> context,
+    ServiceWorkerDispatcherHost* dispatcher_host,
     base::WeakPtr<ServiceWorkerProviderHost> provider_host,
     ServiceWorkerRegistration* registration)
-    : context_(context),
+    : dispatcher_host_(dispatcher_host),
       provider_host_(provider_host),
       provider_id_(provider_host ? provider_host->provider_id()
                                  : kInvalidServiceWorkerProviderId),
       handle_id_(context
                      ? context->GetNewRegistrationHandleId()
                      : blink::mojom::kInvalidServiceWorkerRegistrationHandleId),
-      ref_count_(1),
       registration_(registration) {
   DCHECK(registration_.get());
-  ChangedVersionAttributesMask changed_mask;
-  if (registration->installing_version())
-    changed_mask.add(ChangedVersionAttributesMask::INSTALLING_VERSION);
-  if (registration->waiting_version())
-    changed_mask.add(ChangedVersionAttributesMask::WAITING_VERSION);
-  if (registration->active_version())
-    changed_mask.add(ChangedVersionAttributesMask::ACTIVE_VERSION);
-  SetVersionAttributes(changed_mask,
-                       registration->installing_version(),
-                       registration->waiting_version(),
-                       registration->active_version());
   registration_->AddListener(this);
+  bindings_.set_connection_error_handler(
+      base::Bind(&ServiceWorkerRegistrationHandle::OnConnectionError,
+                 base::Unretained(this)));
+
+  dispatcher_host_->RegisterServiceWorkerRegistrationHandle(this);
 }
 
 ServiceWorkerRegistrationHandle::~ServiceWorkerRegistrationHandle() {
@@ -47,25 +43,16 @@
 }
 
 blink::mojom::ServiceWorkerRegistrationObjectInfoPtr
-ServiceWorkerRegistrationHandle::GetObjectInfo() {
+ServiceWorkerRegistrationHandle::CreateObjectInfo() {
   auto info = blink::mojom::ServiceWorkerRegistrationObjectInfo::New();
   info->handle_id = handle_id_;
   info->options = blink::mojom::ServiceWorkerRegistrationOptions::New(
       registration_->pattern());
   info->registration_id = registration_->id();
+  bindings_.AddBinding(this, mojo::MakeRequest(&info->host_ptr_info));
   return info;
 }
 
-void ServiceWorkerRegistrationHandle::IncrementRefCount() {
-  DCHECK_GT(ref_count_, 0);
-  ++ref_count_;
-}
-
-void ServiceWorkerRegistrationHandle::DecrementRefCount() {
-  DCHECK_GT(ref_count_, 0);
-  --ref_count_;
-}
-
 void ServiceWorkerRegistrationHandle::OnVersionAttributesChanged(
     ServiceWorkerRegistration* registration,
     ChangedVersionAttributesMask changed_mask,
@@ -108,4 +95,12 @@
                                                   active_version);
 }
 
+void ServiceWorkerRegistrationHandle::OnConnectionError() {
+  // If there are still bindings, |this| is still being used.
+  if (!bindings_.empty())
+    return;
+  // Will destroy |this|.
+  dispatcher_host_->UnregisterServiceWorkerRegistrationHandle(handle_id_);
+}
+
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_registration_handle.h b/content/browser/service_worker/service_worker_registration_handle.h
index ac151c2..b3fa835 100644
--- a/content/browser/service_worker/service_worker_registration_handle.h
+++ b/content/browser/service_worker/service_worker_registration_handle.h
@@ -14,38 +14,38 @@
 #include "content/browser/service_worker/service_worker_version.h"
 #include "content/common/content_export.h"
 #include "content/common/service_worker/service_worker_types.h"
+#include "mojo/public/cpp/bindings/associated_binding_set.h"
 #include "third_party/WebKit/public/platform/modules/serviceworker/service_worker_registration.mojom.h"
 
 namespace content {
 
 class ServiceWorkerContextCore;
+class ServiceWorkerDispatcherHost;
 class ServiceWorkerVersion;
 
-// Roughly corresponds to one WebServiceWorkerRegistration object in the
-// renderer process.
-//
-// The renderer process maintains the reference count by owning a
-// ServiceWorkerRegistrationHandleReference for each reference it has to the
-// registration object. ServiceWorkerRegistrationHandleReference creation and
-// destruction sends an IPC to the browser process, which adjusts the
-// ServiceWorkerRegistrationHandle refcount.
+// TODO(leonhsl): Merge this class into ServiceWorkerRegistration.
+
+// ServiceWorkerRegistrationHandle has a 1:1 correspondence to
+// WebServiceWorkerRegistration in the renderer process.
+// WebServiceWorkerRegistration owns ServiceWorkerRegistrationHandle via an
+// associated interface pointer to
+// blink::mojom::ServiceWorkerRegistrationObjectHost.
 //
 // Has a reference to the corresponding ServiceWorkerRegistration in order to
 // ensure that the registration is alive while this handle is around.
 class CONTENT_EXPORT ServiceWorkerRegistrationHandle
-    : public ServiceWorkerRegistration::Listener {
+    : public blink::mojom::ServiceWorkerRegistrationObjectHost,
+      public ServiceWorkerRegistration::Listener {
  public:
   ServiceWorkerRegistrationHandle(
       base::WeakPtr<ServiceWorkerContextCore> context,
+      ServiceWorkerDispatcherHost* dispatcher_host,
       base::WeakPtr<ServiceWorkerProviderHost> provider_host,
       ServiceWorkerRegistration* registration);
-  virtual ~ServiceWorkerRegistrationHandle();
+  ~ServiceWorkerRegistrationHandle() override;
 
-  blink::mojom::ServiceWorkerRegistrationObjectInfoPtr GetObjectInfo();
-
-  bool HasNoRefCount() const { return ref_count_ <= 0; }
-  void IncrementRefCount();
-  void DecrementRefCount();
+  // Establishes a new mojo connection into |bindings_|.
+  blink::mojom::ServiceWorkerRegistrationObjectInfoPtr CreateObjectInfo();
 
   int provider_id() const { return provider_id_; }
   int handle_id() const { return handle_id_; }
@@ -69,11 +69,16 @@
       ServiceWorkerVersion* waiting_version,
       ServiceWorkerVersion* active_version);
 
-  base::WeakPtr<ServiceWorkerContextCore> context_;
+  void OnConnectionError();
+
+  // |dispatcher_host_| is valid throughout lifetime of |this| because it owns
+  // |this|.
+  ServiceWorkerDispatcherHost* dispatcher_host_;
   base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
   const int provider_id_;
   const int handle_id_;
-  int ref_count_;  // Created with 1.
+  mojo::AssociatedBindingSet<blink::mojom::ServiceWorkerRegistrationObjectHost>
+      bindings_;
 
   // This handle is the primary owner of this registration.
   scoped_refptr<ServiceWorkerRegistration> registration_;
diff --git a/content/browser/service_worker/service_worker_registration_unittest.cc b/content/browser/service_worker/service_worker_registration_unittest.cc
index 607247c1..6304a37 100644
--- a/content/browser/service_worker/service_worker_registration_unittest.cc
+++ b/content/browser/service_worker/service_worker_registration_unittest.cc
@@ -7,6 +7,7 @@
 #include <stdint.h>
 #include <utility>
 
+#include "base/compiler_specific.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
 #include "base/run_loop.h"
@@ -16,9 +17,11 @@
 #include "content/browser/service_worker/embedded_worker_status.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_dispatcher_host.h"
 #include "content/browser/service_worker/service_worker_registration_handle.h"
 #include "content/browser/service_worker/service_worker_test_utils.h"
 #include "content/common/service_worker/service_worker_utils.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 "third_party/WebKit/public/platform/modules/serviceworker/service_worker_registration.mojom.h"
@@ -177,14 +180,18 @@
 TEST_F(ServiceWorkerRegistrationTest, FailedRegistrationNoCrash) {
   const GURL kScope("http://www.example.not/");
   int64_t kRegistrationId = 1L;
-  scoped_refptr<ServiceWorkerRegistration> registration =
-      new ServiceWorkerRegistration(
-          blink::mojom::ServiceWorkerRegistrationOptions(kScope),
-          kRegistrationId, context()->AsWeakPtr());
-  std::unique_ptr<ServiceWorkerRegistrationHandle> handle(
-      new ServiceWorkerRegistrationHandle(
-          context()->AsWeakPtr(), base::WeakPtr<ServiceWorkerProviderHost>(),
-          registration.get()));
+  auto registration = base::MakeRefCounted<ServiceWorkerRegistration>(
+      blink::mojom::ServiceWorkerRegistrationOptions(kScope), kRegistrationId,
+      context()->AsWeakPtr());
+  auto dispatcher_host = base::MakeRefCounted<ServiceWorkerDispatcherHost>(
+      helper_->mock_render_process_id(),
+      helper_->browser_context()->GetResourceContext());
+  // ServiceWorkerRegistrationHandle ctor will make |handle| be owned by
+  // |dispatcher_host|.
+  auto* handle = new ServiceWorkerRegistrationHandle(
+      context()->AsWeakPtr(), dispatcher_host.get(),
+      base::WeakPtr<ServiceWorkerProviderHost>(), registration.get());
+  ALLOW_UNUSED_LOCAL(handle);
   registration->NotifyRegistrationFailed();
   // Don't crash when handle gets destructed.
 }
diff --git a/content/browser/service_worker/service_worker_script_url_loader.cc b/content/browser/service_worker/service_worker_script_url_loader.cc
index f676b83..b4d45d0 100644
--- a/content/browser/service_worker/service_worker_script_url_loader.cc
+++ b/content/browser/service_worker/service_worker_script_url_loader.cc
@@ -116,12 +116,12 @@
   network_loader_->SetPriority(priority, intra_priority_value);
 }
 
-void ServiceWorkerScriptURLLoader::PauseCachingResponseBody() {
-  network_loader_->PauseCachingResponseBody();
+void ServiceWorkerScriptURLLoader::PauseReadingBodyFromNet() {
+  network_loader_->PauseReadingBodyFromNet();
 }
 
-void ServiceWorkerScriptURLLoader::ResumeCachingResponseBody() {
-  network_loader_->ResumeCachingResponseBody();
+void ServiceWorkerScriptURLLoader::ResumeReadingBodyFromNet() {
+  network_loader_->ResumeReadingBodyFromNet();
 }
 
 // URLLoaderClient for network loader ------------------------------------------
diff --git a/content/browser/service_worker/service_worker_script_url_loader.h b/content/browser/service_worker/service_worker_script_url_loader.h
index 5a9f9a9..4c5d93c0 100644
--- a/content/browser/service_worker/service_worker_script_url_loader.h
+++ b/content/browser/service_worker/service_worker_script_url_loader.h
@@ -63,8 +63,8 @@
   void FollowRedirect() override;
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override;
-  void PauseCachingResponseBody() override;
-  void ResumeCachingResponseBody() override;
+  void PauseReadingBodyFromNet() override;
+  void ResumeReadingBodyFromNet() override;
 
   // mojom::URLLoaderClient for the network load:
   void OnReceiveResponse(const ResourceResponseHead& response_head,
diff --git a/content/browser/service_worker/service_worker_test_utils.cc b/content/browser/service_worker/service_worker_test_utils.cc
index 6d41dad..a69a338e 100644
--- a/content/browser/service_worker/service_worker_test_utils.cc
+++ b/content/browser/service_worker/service_worker_test_utils.cc
@@ -33,6 +33,7 @@
     mojom::ServiceWorkerProviderInfoForStartWorkerPtr info) {
   client_request_ = std::move(info->client_request);
   host_ptr_.Bind(std::move(info->host_ptr_info));
+  registration_object_info_ = std::move(info->registration);
 }
 
 std::unique_ptr<ServiceWorkerProviderHost> CreateProviderHostForWindow(
diff --git a/content/browser/service_worker/service_worker_test_utils.h b/content/browser/service_worker/service_worker_test_utils.h
index 1f01c94..377da430 100644
--- a/content/browser/service_worker/service_worker_test_utils.h
+++ b/content/browser/service_worker/service_worker_test_utils.h
@@ -15,6 +15,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/content_switches.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/modules/serviceworker/service_worker_registration.mojom.h"
 
 namespace content {
 
@@ -77,6 +78,9 @@
   // This is the other end of ServiceWorkerContainerAssociatedPtr owned by
   // content::ServiceWorkerProviderHost.
   mojom::ServiceWorkerContainerAssociatedRequest client_request_;
+  // This is to keep alive the corresponding content::ServiceWorkerRegistration.
+  blink::mojom::ServiceWorkerRegistrationObjectInfoPtr
+      registration_object_info_;
 
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRemoteProviderEndpoint);
 };
diff --git a/content/browser/service_worker/service_worker_url_loader_job.cc b/content/browser/service_worker/service_worker_url_loader_job.cc
index f6ad3449..9793c4f1 100644
--- a/content/browser/service_worker/service_worker_url_loader_job.cc
+++ b/content/browser/service_worker/service_worker_url_loader_job.cc
@@ -5,6 +5,7 @@
 #include "content/browser/service_worker/service_worker_url_loader_job.h"
 
 #include "base/guid.h"
+#include "base/optional.h"
 #include "content/browser/blob_storage/blob_url_loader_factory.h"
 #include "content/browser/service_worker/service_worker_fetch_dispatcher.h"
 #include "content/browser/service_worker/service_worker_version.h"
@@ -25,49 +26,32 @@
 
 namespace {
 
-// TODO(horo): We should have shared logic with
-// net::URLRequestJob::ComputeRedirectInfo()
-std::unique_ptr<net::RedirectInfo> ComputeRedirectInfo(
+base::Optional<net::RedirectInfo> ComputeRedirectInfo(
     const ResourceRequest& original_request,
-    const ResourceResponseHead& response_head) {
+    const ResourceResponseHead& response_head,
+    bool token_binding_negotiated) {
   std::string new_location;
   if (!response_head.headers->IsRedirect(&new_location))
-    return nullptr;
+    return base::nullopt;
 
-  const int status = response_head.headers->response_code();
-  const std::string& method = original_request.method;
-  const GURL& url = original_request.url;
-  const GURL location = url.Resolve(new_location);
+  std::string referrer_string;
+  net::URLRequest::ReferrerPolicy referrer_policy;
+  Referrer::ComputeReferrerInfo(
+      &referrer_string, &referrer_policy,
+      Referrer(original_request.referrer, original_request.referrer_policy));
 
-  std::unique_ptr<net::RedirectInfo> redirect_info =
-      base::MakeUnique<net::RedirectInfo>();
-  redirect_info->status_code = status;
-  // The request method may change, depending on the status code.
-  // See the comments in net::URLRequestJob::ComputeRedirectInfo() for details.
-  redirect_info->new_method =
-      ((status == 303 && method != "HEAD") ||
-       ((status == 301 || status == 302) && method == "POST"))
-          ? "GET"
-          : method;
-  if (url.is_valid() && url.has_ref() && !location.has_ref()) {
-    GURL::Replacements replacements;
-    replacements.SetRef(url.spec().data(),
-                        url.parsed_for_possibly_invalid_spec().ref);
-    redirect_info->new_url = location.ReplaceComponents(replacements);
-  } else {
-    redirect_info->new_url = location;
-  }
-  // If the request is a MAIN_FRAME request, the first-party URL gets updated
-  // on redirects.
-  redirect_info->new_site_for_cookies =
+  // If the request is a MAIN_FRAME request, the first-party URL gets
+  // updated on redirects.
+  const net::URLRequest::FirstPartyURLPolicy first_party_url_policy =
       original_request.resource_type == RESOURCE_TYPE_MAIN_FRAME
-          ? redirect_info->new_url
-          : original_request.site_for_cookies;
-  // TODO(horo): Set new_referrer_policy and new_referrer by checking
-  // Referrer-Policy header.
-  // TODO(horo): Set referred_token_binding_host by checking
-  // include-referred-token-binding-id header.
-  return redirect_info;
+          ? net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT
+          : net::URLRequest::NEVER_CHANGE_FIRST_PARTY_URL;
+  return net::RedirectInfo::ComputeRedirectInfo(
+      original_request.method, original_request.url,
+      original_request.site_for_cookies, first_party_url_policy,
+      referrer_policy, referrer_string, response_head.headers.get(),
+      response_head.headers->response_code(),
+      original_request.url.Resolve(new_location), token_binding_negotiated);
 }
 
 }  // namespace
@@ -351,8 +335,12 @@
       did_navigation_preload_;
   response_head_.load_timing.receive_headers_end = base::TimeTicks::Now();
 
-  if (std::unique_ptr<net::RedirectInfo> redirect_info =
-          ComputeRedirectInfo(resource_request_, response_head_)) {
+  // Handle a redirect response. ComputeRedirectInfo returns non-null redirect
+  // info if the given response is a redirect.
+  base::Optional<net::RedirectInfo> redirect_info =
+      ComputeRedirectInfo(resource_request_, response_head_,
+                          ssl_info_ && ssl_info_->token_binding_negotiated);
+  if (redirect_info) {
     response_head_.encoded_data_length = 0;
     url_loader_client_->OnReceiveRedirect(*redirect_info, response_head_);
     status_ = Status::kCompleted;
@@ -403,9 +391,9 @@
   NOTIMPLEMENTED();
 }
 
-void ServiceWorkerURLLoaderJob::PauseCachingResponseBody() {}
+void ServiceWorkerURLLoaderJob::PauseReadingBodyFromNet() {}
 
-void ServiceWorkerURLLoaderJob::ResumeCachingResponseBody() {}
+void ServiceWorkerURLLoaderJob::ResumeReadingBodyFromNet() {}
 
 // Blob URLLoaderClient implementation for blob reading ------------
 
diff --git a/content/browser/service_worker/service_worker_url_loader_job.h b/content/browser/service_worker/service_worker_url_loader_job.h
index 9662028..2b6195f1 100644
--- a/content/browser/service_worker/service_worker_url_loader_job.h
+++ b/content/browser/service_worker/service_worker_url_loader_job.h
@@ -128,8 +128,8 @@
   void FollowRedirect() override;
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override;
-  void PauseCachingResponseBody() override;
-  void ResumeCachingResponseBody() override;
+  void PauseReadingBodyFromNet() override;
+  void ResumeReadingBodyFromNet() override;
 
   // mojom::URLLoaderClient for Blob response reading (used only when
   // the SW response had valid blob UUID):
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 1b8300e..277009e5 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -8,8 +8,11 @@
 #include <stdint.h>
 
 #include <algorithm>
+#include <list>
 #include <map>
+#include <memory>
 #include <set>
+#include <utility>
 #include <vector>
 
 #include "base/bind.h"
@@ -38,6 +41,7 @@
 #include "content/browser/frame_host/navigation_controller_impl.h"
 #include "content/browser/frame_host/navigation_entry_impl.h"
 #include "content/browser/frame_host/navigator.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/browser/frame_host/render_frame_proxy_host.h"
 #include "content/browser/gpu/compositor_util.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
@@ -524,7 +528,7 @@
 // This observer is used to wait for its owner FrameTreeNode to become deleted.
 class FrameDeletedObserver : public FrameTreeNode::Observer {
  public:
-  FrameDeletedObserver(FrameTreeNode* owner)
+  explicit FrameDeletedObserver(FrameTreeNode* owner)
       : owner_(owner), message_loop_runner_(new MessageLoopRunner) {
     owner->AddObserver(this);
   }
@@ -623,8 +627,7 @@
 // SitePerProcessBrowserTest
 //
 
-SitePerProcessBrowserTest::SitePerProcessBrowserTest() {
-};
+SitePerProcessBrowserTest::SitePerProcessBrowserTest() {}
 
 std::string SitePerProcessBrowserTest::DepictFrameTree(FrameTreeNode* node) {
   return visualizer_.DepictFrameTree(node);
@@ -849,7 +852,7 @@
   RenderProcessHost* rph = child->current_frame_host()->GetProcess();
   EXPECT_NE(shell()->web_contents()->GetRenderViewHost(), rvh);
   EXPECT_NE(shell()->web_contents()->GetSiteInstance(), site_instance);
-  EXPECT_NE(shell()->web_contents()->GetRenderProcessHost(), rph);
+  EXPECT_NE(shell()->web_contents()->GetMainFrame()->GetProcess(), rph);
   {
     // There should be now two RenderWidgetHosts, one for each process
     // rendering a frame.
@@ -900,7 +903,7 @@
             child->current_frame_host()->GetSiteInstance());
   EXPECT_NE(site_instance,
             child->current_frame_host()->GetSiteInstance());
-  EXPECT_NE(shell()->web_contents()->GetRenderProcessHost(),
+  EXPECT_NE(shell()->web_contents()->GetMainFrame()->GetProcess(),
             child->current_frame_host()->GetProcess());
   EXPECT_NE(rph, child->current_frame_host()->GetProcess());
   {
@@ -969,7 +972,7 @@
 class InputEventAckWaiter
     : public content::RenderWidgetHost::InputEventObserver {
  public:
-  InputEventAckWaiter(blink::WebInputEvent::Type ack_type_waiting_for)
+  explicit InputEventAckWaiter(blink::WebInputEvent::Type ack_type_waiting_for)
       : message_loop_runner_(new content::MessageLoopRunner),
         ack_type_waiting_for_(ack_type_waiting_for),
         desired_ack_type_received_(false) {}
@@ -2785,8 +2788,8 @@
   void FollowRedirect() override {}
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override {}
-  void PauseCachingResponseBody() override {}
-  void ResumeCachingResponseBody() override {}
+  void PauseReadingBodyFromNet() override {}
+  void ResumeReadingBodyFromNet() override {}
 };
 
 class FailingLoadFactory : public mojom::URLLoaderFactory {
@@ -2807,7 +2810,8 @@
 
   void Clone(mojom::URLLoaderFactoryRequest request) override { NOTREACHED(); }
 };
-}
+
+}  // namespace
 
 // Ensure that a cross-site page ends up in the correct process when it
 // successfully loads after earlier encountering a network error for it.
@@ -3390,7 +3394,7 @@
 
     EXPECT_EQ(observer.last_navigation_url(), https_url);
     EXPECT_FALSE(observer.last_navigation_succeeded());
-   }
+  }
 
   {
     // Load same-site client-redirect page into Iframe,
@@ -3425,7 +3429,7 @@
                                     server_redirect_http_url));
     EXPECT_EQ(observer.last_navigation_url(), http_url);
     EXPECT_TRUE(observer.last_navigation_succeeded());
-   }
+  }
 
   {
     // Load same-site client-redirect page into Iframe,
@@ -6328,7 +6332,7 @@
   runner->Quit();
 }
 
-}  // namespace anonymous
+}  // anonymous namespace
 
 // https://crbug.com/592320
 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
@@ -6547,7 +6551,7 @@
 }
 #endif
 
-}  // namespace anonymous
+}  // anonymous namespace
 
 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
                        InputEventRouterGestureTargetMapTest) {
@@ -9964,7 +9968,7 @@
 
 class NavigationHandleWatcher : public WebContentsObserver {
  public:
-  NavigationHandleWatcher(WebContents* web_contents)
+  explicit NavigationHandleWatcher(WebContents* web_contents)
       : WebContentsObserver(web_contents) {}
   void DidStartNavigation(NavigationHandle* navigation_handle) override {
     DCHECK_EQ(GURL("http://b.com/"),
diff --git a/content/browser/speech/speech_recognition_dispatcher_host.cc b/content/browser/speech/speech_recognition_dispatcher_host.cc
index 624698f..24f48701 100644
--- a/content/browser/speech/speech_recognition_dispatcher_host.cc
+++ b/content/browser/speech/speech_recognition_dispatcher_host.cc
@@ -13,6 +13,7 @@
 #include "content/browser/speech/speech_recognition_manager_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/common/speech_recognition_messages.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/speech_recognition_manager_delegate.h"
 #include "content/public/browser/speech_recognition_session_config.h"
 #include "content/public/browser/speech_recognition_session_context.h"
@@ -107,7 +108,7 @@
     // the context of the outer WebContents or the embedder since we will use it
     // to decide permission.
     embedder_render_process_id =
-        outer_web_contents->GetRenderProcessHost()->GetID();
+        outer_web_contents->GetRenderViewHost()->GetProcess()->GetID();
     DCHECK_NE(embedder_render_process_id, 0);
     embedder_render_view_id =
         outer_web_contents->GetRenderViewHost()->GetRoutingID();
diff --git a/content/browser/utility_process_host_impl.cc b/content/browser/utility_process_host_impl.cc
index 8a087ed..e739de1c 100644
--- a/content/browser/utility_process_host_impl.cc
+++ b/content/browser/utility_process_host_impl.cc
@@ -21,6 +21,7 @@
 #include "content/common/child_process_host_impl.h"
 #include "content/common/in_process_child_thread_params.h"
 #include "content/common/service_manager/child_connection.h"
+#include "content/public/browser/browser_message_filter.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/utility_process_host_client.h"
@@ -214,6 +215,10 @@
   service_identity_ = identity;
 }
 
+void UtilityProcessHostImpl::AddFilter(BrowserMessageFilter* filter) {
+  process_->AddFilter(filter);
+}
+
 bool UtilityProcessHostImpl::StartProcess() {
   if (started_)
     return true;
diff --git a/content/browser/utility_process_host_impl.h b/content/browser/utility_process_host_impl.h
index 5fca0c95..96d33522 100644
--- a/content/browser/utility_process_host_impl.h
+++ b/content/browser/utility_process_host_impl.h
@@ -24,6 +24,7 @@
 }
 
 namespace content {
+class BrowserMessageFilter;
 class BrowserChildProcessHostImpl;
 class InProcessChildThreadParams;
 
@@ -58,6 +59,7 @@
   void BindInterface(const std::string& interface_name,
                      mojo::ScopedMessagePipeHandle interface_pipe) override;
   void SetName(const base::string16& name) override;
+  void AddFilter(BrowserMessageFilter* filter) override;
 
   void set_child_flags(int flags) { child_flags_ = flags; }
 
diff --git a/content/browser/web_contents/web_contents_android.cc b/content/browser/web_contents/web_contents_android.cc
index 66742a9..714b251 100644
--- a/content/browser/web_contents/web_contents_android.cc
+++ b/content/browser/web_contents/web_contents_android.cc
@@ -430,8 +430,10 @@
     JNIEnv* env,
     const JavaParamRef<jobject>& obj,
     jint start_adjust,
-    jint end_adjust) {
-  web_contents_->AdjustSelectionByCharacterOffset(start_adjust, end_adjust);
+    jint end_adjust,
+    jboolean show_selection_menu) {
+  web_contents_->AdjustSelectionByCharacterOffset(start_adjust, end_adjust,
+                                                  show_selection_menu);
 }
 
 void WebContentsAndroid::EvaluateJavaScript(
diff --git a/content/browser/web_contents/web_contents_android.h b/content/browser/web_contents/web_contents_android.h
index ff9c7043..779d633 100644
--- a/content/browser/web_contents/web_contents_android.h
+++ b/content/browser/web_contents/web_contents_android.h
@@ -123,7 +123,8 @@
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj,
       jint start_adjust,
-      jint end_adjust);
+      jint end_adjust,
+      jboolean show_selection_menu);
   void EvaluateJavaScript(JNIEnv* env,
                           const base::android::JavaParamRef<jobject>& obj,
                           const base::android::JavaParamRef<jstring>& script,
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 6d85772..894f77e 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -937,7 +937,7 @@
   return host ? host->GetProcess() : NULL;
 }
 
-RenderFrameHostImpl* WebContentsImpl::GetMainFrame() {
+RenderFrameHostImpl* WebContentsImpl::GetMainFrame() const {
   return frame_tree_.root()->current_frame_host();
 }
 
@@ -1532,7 +1532,7 @@
       view->Hide();
 
     if (!ShowingInterstitialPage())
-      SetVisibilityForChildViews(true);
+      SetVisibilityForChildViews(false);
 
     SendPageMessage(new PageMsg_WasHidden(MSG_ROUTING_NONE));
   }
@@ -2887,14 +2887,19 @@
   focused_frame->GetFrameInputHandler()->MoveCaret(extent);
 }
 
-void WebContentsImpl::AdjustSelectionByCharacterOffset(int start_adjust,
-                                                       int end_adjust) {
+void WebContentsImpl::AdjustSelectionByCharacterOffset(
+    int start_adjust,
+    int end_adjust,
+    bool show_selection_menu) {
   RenderFrameHostImpl* focused_frame = GetFocusedFrame();
   if (!focused_frame)
     return;
 
+  using blink::mojom::SelectionMenuBehavior;
   focused_frame->GetFrameInputHandler()->AdjustSelectionByCharacterOffset(
-      start_adjust, end_adjust);
+      start_adjust, end_adjust,
+      show_selection_menu ? SelectionMenuBehavior::kShow
+                          : SelectionMenuBehavior::kHide);
 }
 
 void WebContentsImpl::UpdatePreferredSize(const gfx::Size& pref_size) {
@@ -5816,7 +5821,7 @@
                                       int active_match_ordinal,
                                       bool final_update) {
   if (delegate_ && !is_being_destroyed_ &&
-      !GetRenderProcessHost()->FastShutdownStarted()) {
+      !GetMainFrame()->GetProcess()->FastShutdownStarted()) {
     delegate_->FindReply(this, request_id, number_of_matches, selection_rect,
                          active_match_ordinal, final_update);
   }
@@ -5842,7 +5847,7 @@
     return;
   }
   // Notify for UI updates if the state changes.
-  DCHECK(bluetooth_connected_device_count_ != 0);
+  DCHECK_NE(bluetooth_connected_device_count_, 0u);
   bluetooth_connected_device_count_--;
   if (bluetooth_connected_device_count_ == 0) {
     NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 3e92189..7479d51 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -12,6 +12,8 @@
 #include <memory>
 #include <set>
 #include <string>
+#include <utility>
+#include <vector>
 
 #include "base/compiler_specific.h"
 #include "base/gtest_prod_util.h"
@@ -305,7 +307,7 @@
   const GURL& GetVisibleURL() const override;
   const GURL& GetLastCommittedURL() const override;
   RenderProcessHost* GetRenderProcessHost() const override;
-  RenderFrameHostImpl* GetMainFrame() override;
+  RenderFrameHostImpl* GetMainFrame() const override;
   RenderFrameHostImpl* GetFocusedFrame() override;
   RenderFrameHostImpl* FindFrameByFrameTreeNodeId(int frame_tree_node_id,
                                                   int process_id) override;
@@ -704,8 +706,9 @@
   void MoveRangeSelectionExtent(const gfx::Point& extent) override;
   void SelectRange(const gfx::Point& base, const gfx::Point& extent) override;
   void MoveCaret(const gfx::Point& extent) override;
-  void AdjustSelectionByCharacterOffset(int start_adjust, int end_adjust)
-      override;
+  void AdjustSelectionByCharacterOffset(int start_adjust,
+                                        int end_adjust,
+                                        bool show_selection_menu) override;
   RenderWidgetHostInputEventRouter* GetInputEventRouter() override;
   void ReplicatePageFocus(bool is_focused) override;
   RenderWidgetHostImpl* GetFocusedRenderWidgetHost(
@@ -1015,7 +1018,7 @@
   };
 
   // See WebContents::Create for a description of these parameters.
-  WebContentsImpl(BrowserContext* browser_context);
+  explicit WebContentsImpl(BrowserContext* browser_context);
 
   // Add and remove observers for page navigation notifications. The order in
   // which notifications are sent to observers is undefined. Clients must be
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index 7523135..12f1303 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -82,12 +82,11 @@
 // they are correct, after the LoadNotificationDetails object is deleted.
 class LoadStopNotificationObserver : public WindowedNotificationObserver {
  public:
-  LoadStopNotificationObserver(NavigationController* controller)
+  explicit LoadStopNotificationObserver(NavigationController* controller)
       : WindowedNotificationObserver(NOTIFICATION_LOAD_STOP,
                                      Source<NavigationController>(controller)),
         session_index_(-1),
-        controller_(NULL) {
-  }
+        controller_(NULL) {}
   void Observe(int type,
                const NotificationSource& source,
                const NotificationDetails& details) override {
@@ -418,10 +417,8 @@
 // in subsequent tests.
 class RenderFrameCreatedObserver : public WebContentsObserver {
  public:
-  RenderFrameCreatedObserver(Shell* shell)
-      : WebContentsObserver(shell->web_contents()),
-        last_rfh_(NULL) {
-  }
+  explicit RenderFrameCreatedObserver(Shell* shell)
+      : WebContentsObserver(shell->web_contents()), last_rfh_(NULL) {}
 
   void RenderFrameCreated(RenderFrameHost* render_frame_host) override {
     last_rfh_ = render_frame_host;
@@ -520,7 +517,7 @@
 
 class DidGetResourceResponseStartObserver : public WebContentsObserver {
  public:
-  DidGetResourceResponseStartObserver(Shell* shell)
+  explicit DidGetResourceResponseStartObserver(Shell* shell)
       : WebContentsObserver(shell->web_contents()), shell_(shell) {
     shell->web_contents()->SetDelegate(&delegate_);
     EXPECT_FALSE(shell->web_contents()->IsWaitingForResponse());
@@ -567,7 +564,7 @@
 
 struct LoadProgressDelegateAndObserver : public WebContentsDelegate,
                                          public WebContentsObserver {
-  LoadProgressDelegateAndObserver(Shell* shell)
+  explicit LoadProgressDelegateAndObserver(Shell* shell)
       : WebContentsObserver(shell->web_contents()),
         did_start_loading(false),
         did_stop_loading(false) {
@@ -688,7 +685,7 @@
 }
 
 struct FirstVisuallyNonEmptyPaintObserver : public WebContentsObserver {
-  FirstVisuallyNonEmptyPaintObserver(Shell* shell)
+  explicit FirstVisuallyNonEmptyPaintObserver(Shell* shell)
       : WebContentsObserver(shell->web_contents()),
         did_fist_visually_non_empty_paint_(false) {}
 
@@ -744,7 +741,7 @@
   DISALLOW_COPY_AND_ASSIGN(WebDisplayModeDelegate);
 };
 
-}
+}  // namespace
 
 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, ChangeDisplayMode) {
   ASSERT_TRUE(embedded_test_server()->Start());
@@ -775,7 +772,7 @@
 // See WebContentsImplBrowserTest.ChangePageScale.
 class MockPageScaleObserver : public WebContentsObserver {
  public:
-  MockPageScaleObserver(Shell* shell)
+  explicit MockPageScaleObserver(Shell* shell)
       : WebContentsObserver(shell->web_contents()),
         got_page_scale_update_(false) {
     // Once OnPageScaleFactorChanged is called, quit the run loop.
@@ -1262,7 +1259,7 @@
   ASSERT_TRUE(web_contents->GetMainFrame());
   EXPECT_TRUE(web_contents->GetMainFrame()->IsRenderFrameLive());
   EXPECT_TRUE(web_contents->GetController().IsInitialBlankNavigation());
-  int renderer_id = web_contents->GetRenderProcessHost()->GetID();
+  int renderer_id = web_contents->GetMainFrame()->GetProcess()->GetID();
 
   TestNavigationObserver same_tab_observer(web_contents.get(), 1);
   NavigationController::LoadURLParams params(url);
@@ -1272,7 +1269,7 @@
   same_tab_observer.Wait();
 
   // Check that pre-warmed process is used.
-  EXPECT_EQ(renderer_id, web_contents->GetRenderProcessHost()->GetID());
+  EXPECT_EQ(renderer_id, web_contents->GetMainFrame()->GetProcess()->GetID());
   EXPECT_EQ(1, web_contents->GetController().GetEntryCount());
   NavigationEntry* entry =
       web_contents->GetController().GetLastCommittedEntry();
@@ -1302,7 +1299,7 @@
   ASSERT_TRUE(web_contents->GetMainFrame());
   EXPECT_TRUE(web_contents->GetMainFrame()->IsRenderFrameLive());
   EXPECT_TRUE(web_contents->GetController().IsInitialBlankNavigation());
-  int renderer_id = web_contents->GetRenderProcessHost()->GetID();
+  int renderer_id = web_contents->GetMainFrame()->GetProcess()->GetID();
 
   TestNavigationObserver same_tab_observer(web_contents.get(), 1);
   NavigationController::LoadURLParams params(web_ui_url);
@@ -1312,7 +1309,7 @@
   same_tab_observer.Wait();
 
   // Check that pre-warmed process isn't used.
-  EXPECT_NE(renderer_id, web_contents->GetRenderProcessHost()->GetID());
+  EXPECT_NE(renderer_id, web_contents->GetMainFrame()->GetProcess()->GetID());
   EXPECT_EQ(1, web_contents->GetController().GetEntryCount());
   NavigationEntry* entry =
       web_contents->GetController().GetLastCommittedEntry();
diff --git a/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc b/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc
index 008ee47f..2a5989cd1 100644
--- a/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc
+++ b/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc
@@ -21,7 +21,8 @@
 // process and hence does not support capture: https://crbug.com/641559.
 #define MAYBE_CaptureFromMediaElement DISABLED_CaptureFromMediaElement
 #else
-#define MAYBE_CaptureFromMediaElement CaptureFromMediaElement
+// crbug.com/769903: Disabling due to TSAN error.
+#define MAYBE_CaptureFromMediaElement DISABLED_CaptureFromMediaElement
 #endif
 
 namespace {
diff --git a/content/child/BUILD.gn b/content/child/BUILD.gn
index c87ee77..597f47a 100644
--- a/content/child/BUILD.gn
+++ b/content/child/BUILD.gn
@@ -156,8 +156,6 @@
     "service_worker/service_worker_network_provider.h",
     "service_worker/service_worker_provider_context.cc",
     "service_worker/service_worker_provider_context.h",
-    "service_worker/service_worker_registration_handle_reference.cc",
-    "service_worker/service_worker_registration_handle_reference.h",
     "service_worker/service_worker_subresource_loader.cc",
     "service_worker/service_worker_subresource_loader.h",
     "service_worker/web_service_worker_impl.cc",
diff --git a/content/child/assert_matching_enums.cc b/content/child/assert_matching_enums.cc
index 3348c32..afeecd98 100644
--- a/content/child/assert_matching_enums.cc
+++ b/content/child/assert_matching_enums.cc
@@ -101,5 +101,7 @@
 STATIC_ASSERT_ENUM(blink::kMenuSourceLongTap, ui::MENU_SOURCE_LONG_TAP);
 STATIC_ASSERT_ENUM(blink::kMenuSourceTouchHandle, ui::MENU_SOURCE_TOUCH_HANDLE);
 STATIC_ASSERT_ENUM(blink::kMenuSourceStylus, ui::MENU_SOURCE_STYLUS);
+STATIC_ASSERT_ENUM(blink::kMenuSourceAdjustSelection,
+                   ui::MENU_SOURCE_ADJUST_SELECTION);
 
 } // namespace content
diff --git a/content/child/blink_platform_impl.cc b/content/child/blink_platform_impl.cc
index bdbe41e..072fe0c 100644
--- a/content/child/blink_platform_impl.cc
+++ b/content/child/blink_platform_impl.cc
@@ -484,47 +484,6 @@
 const DataResource kDataResources[] = {
     {"missingImage", IDR_BROKENIMAGE, ui::SCALE_FACTOR_100P, false},
     {"missingImage@2x", IDR_BROKENIMAGE, ui::SCALE_FACTOR_200P, false},
-    {"mediaplayerPause", IDR_MEDIAPLAYER_PAUSE_BUTTON, ui::SCALE_FACTOR_100P,
-     false},
-    {"mediaplayerPlay", IDR_MEDIAPLAYER_PLAY_BUTTON, ui::SCALE_FACTOR_100P,
-     false},
-    {"mediaplayerSoundNotMuted", IDR_MEDIAPLAYER_SOUND_NOT_MUTED_BUTTON,
-     ui::SCALE_FACTOR_100P, false},
-    {"mediaplayerSoundMuted", IDR_MEDIAPLAYER_SOUND_MUTED_BUTTON,
-     ui::SCALE_FACTOR_100P, false},
-    {"mediaplayerSliderThumb", IDR_MEDIAPLAYER_SLIDER_THUMB,
-     ui::SCALE_FACTOR_100P, false},
-    {"mediaplayerVolumeSliderThumb", IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB,
-     ui::SCALE_FACTOR_100P, false},
-    {"mediaplayerClosedCaption", IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON,
-     ui::SCALE_FACTOR_100P, false},
-    {"mediaplayerClosedCaptionDisabled",
-     IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_DISABLED, ui::SCALE_FACTOR_100P,
-     false},
-    {"mediaplayerEnterFullscreen", IDR_MEDIAPLAYER_ENTER_FULLSCREEN_BUTTON,
-     ui::SCALE_FACTOR_100P, false},
-    {"mediaplayerExitFullscreen", IDR_MEDIAPLAYER_EXIT_FULLSCREEN_BUTTON,
-     ui::SCALE_FACTOR_100P, false},
-    {"mediaplayerCastOff", IDR_MEDIAPLAYER_CAST_BUTTON_OFF,
-     ui::SCALE_FACTOR_100P, false},
-    {"mediaplayerCastOn", IDR_MEDIAPLAYER_CAST_BUTTON_ON, ui::SCALE_FACTOR_100P,
-     false},
-    {"mediaplayerOverlayCastOff", IDR_MEDIAPLAYER_OVERLAY_CAST_BUTTON_OFF,
-     ui::SCALE_FACTOR_100P, false},
-    {"mediaplayerOverlayPlay", IDR_MEDIAPLAYER_OVERLAY_PLAY_BUTTON,
-     ui::SCALE_FACTOR_100P, false},
-    {"mediaRemotingCastIcon", IDR_MEDIA_REMOTING_CAST_ICON,
-     ui::SCALE_FACTOR_100P, false},
-    {"mediaplayerTrackSelectionCheckmark",
-     IDR_MEDIAPLAYER_TRACKSELECTION_CHECKMARK, ui::SCALE_FACTOR_100P, false},
-    {"mediaplayerClosedCaptionsIcon", IDR_MEDIAPLAYER_CLOSEDCAPTIONS_ICON,
-     ui::SCALE_FACTOR_100P, false},
-    {"mediaplayerSubtitlesIcon", IDR_MEDIAPLAYER_SUBTITLES_ICON,
-     ui::SCALE_FACTOR_100P, false},
-    {"mediaplayerOverflowMenu", IDR_MEDIAPLAYER_OVERFLOW_MENU_ICON,
-     ui::SCALE_FACTOR_100P, false},
-    {"mediaplayerDownloadIcon", IDR_MEDIAPLAYER_DOWNLOAD_ICON,
-     ui::SCALE_FACTOR_100P, false},
     {"searchCancel", IDR_SEARCH_CANCEL, ui::SCALE_FACTOR_100P, false},
     {"searchCancelPressed", IDR_SEARCH_CANCEL_PRESSED, ui::SCALE_FACTOR_100P,
      false},
@@ -543,8 +502,9 @@
     {"fullscreenAndroid.css", IDR_UASTYLE_FULLSCREEN_ANDROID_CSS,
      ui::SCALE_FACTOR_NONE, true},
     // Not limited to Android since it's used for mobile layouts in inspector.
-    {"mediaControlsAndroid.css", IDR_UASTYLE_MEDIA_CONTROLS_ANDROID_CSS,
-     ui::SCALE_FACTOR_NONE, true},
+    {"legacyMediaControlsAndroid.css",
+     IDR_UASTYLE_LEGACY_MEDIA_CONTROLS_ANDROID_CSS, ui::SCALE_FACTOR_NONE,
+     true},
     // Not limited to Linux since it's used for mobile layouts in inspector.
     {"themeChromiumLinux.css", IDR_UASTYLE_THEME_CHROMIUM_LINUX_CSS,
      ui::SCALE_FACTOR_NONE, true},
@@ -558,8 +518,10 @@
      ui::SCALE_FACTOR_NONE, true},
     {"svg.css", IDR_UASTYLE_SVG_CSS, ui::SCALE_FACTOR_NONE, true},
     {"mathml.css", IDR_UASTYLE_MATHML_CSS, ui::SCALE_FACTOR_NONE, true},
-    {"mediaControls.css", IDR_UASTYLE_MEDIA_CONTROLS_CSS, ui::SCALE_FACTOR_NONE,
-     true},
+    {"legacyMediaControls.css", IDR_UASTYLE_LEGACY_MEDIA_CONTROLS_CSS,
+     ui::SCALE_FACTOR_NONE, false},
+    {"modernMediaControls.css", IDR_UASTYLE_MODERN_MEDIA_CONTROLS_CSS,
+     ui::SCALE_FACTOR_NONE, false},
     {"fullscreen.css", IDR_UASTYLE_FULLSCREEN_CSS, ui::SCALE_FACTOR_NONE, true},
     {"xhtmlmp.css", IDR_UASTYLE_XHTMLMP_CSS, ui::SCALE_FACTOR_NONE, true},
     {"viewportAndroid.css", IDR_UASTYLE_VIEWPORT_ANDROID_CSS,
diff --git a/content/child/loader/cors_url_loader.cc b/content/child/loader/cors_url_loader.cc
index 060a7cf..e661c122 100644
--- a/content/child/loader/cors_url_loader.cc
+++ b/content/child/loader/cors_url_loader.cc
@@ -44,12 +44,12 @@
   network_loader_->SetPriority(priority, intra_priority_value);
 }
 
-void CORSURLLoader::PauseCachingResponseBody() {
-  network_loader_->PauseCachingResponseBody();
+void CORSURLLoader::PauseReadingBodyFromNet() {
+  network_loader_->PauseReadingBodyFromNet();
 }
 
-void CORSURLLoader::ResumeCachingResponseBody() {
-  network_loader_->ResumeCachingResponseBody();
+void CORSURLLoader::ResumeReadingBodyFromNet() {
+  network_loader_->ResumeReadingBodyFromNet();
 }
 
 // mojom::URLLoaderClient for simply proxying network for now:
diff --git a/content/child/loader/cors_url_loader.h b/content/child/loader/cors_url_loader.h
index 1c4fc221..efa8f94 100644
--- a/content/child/loader/cors_url_loader.h
+++ b/content/child/loader/cors_url_loader.h
@@ -34,8 +34,8 @@
   void FollowRedirect() override;
   void SetPriority(net::RequestPriority priority,
                    int intra_priority_value) override;
-  void PauseCachingResponseBody() override;
-  void ResumeCachingResponseBody() override;
+  void PauseReadingBodyFromNet() override;
+  void ResumeReadingBodyFromNet() override;
 
   // mojom::URLLoaderClient overrides:
   void OnReceiveResponse(const ResourceResponseHead& head,
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index 0020ff8..d4bdf99 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -415,6 +415,9 @@
   WebRuntimeFeatures::EnableAllowActivationDelegationAttr(
       base::FeatureList::IsEnabled(features::kAllowActivationDelegationAttr));
 
+  WebRuntimeFeatures::EnableModernMediaControls(
+      base::FeatureList::IsEnabled(media::kUseModernMediaControls));
+
   // Enable explicitly enabled features, and then disable explicitly disabled
   // ones.
   for (const std::string& feature :
diff --git a/content/child/service_worker/service_worker_dispatcher.cc b/content/child/service_worker/service_worker_dispatcher.cc
index e8bc938..dcedf97 100644
--- a/content/child/service_worker/service_worker_dispatcher.cc
+++ b/content/child/service_worker/service_worker_dispatcher.cc
@@ -9,6 +9,7 @@
 
 #include "base/lazy_instance.h"
 #include "base/memory/ptr_util.h"
+#include "base/memory/ref_counted.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
 #include "base/threading/thread_local.h"
@@ -16,7 +17,6 @@
 #include "base/trace_event/trace_event.h"
 #include "content/child/service_worker/service_worker_handle_reference.h"
 #include "content/child/service_worker/service_worker_provider_context.h"
-#include "content/child/service_worker/service_worker_registration_handle_reference.h"
 #include "content/child/service_worker/web_service_worker_impl.h"
 #include "content/child/service_worker/web_service_worker_registration_impl.h"
 #include "content/child/thread_safe_sender.h"
@@ -247,11 +247,9 @@
     return found->second;
 
   // WebServiceWorkerRegistrationImpl constructor calls
-  // AddServiceWorkerRegistration.
-  scoped_refptr<WebServiceWorkerRegistrationImpl> registration(
-      new WebServiceWorkerRegistrationImpl(
-          ServiceWorkerRegistrationHandleReference::Create(
-              std::move(info), thread_safe_sender_.get())));
+  // AddServiceWorkerRegistration to add itself into |registrations_|.
+  auto registration =
+      base::MakeRefCounted<WebServiceWorkerRegistrationImpl>(std::move(info));
 
   registration->SetInstalling(
       GetOrCreateServiceWorker(ServiceWorkerHandleReference::Create(
@@ -271,8 +269,6 @@
     const ServiceWorkerVersionAttributes& attrs) {
   int32_t registration_handle_id = info->handle_id;
 
-  std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration_ref =
-      Adopt(std::move(info));
   std::unique_ptr<ServiceWorkerHandleReference> installing_ref =
       Adopt(attrs.installing);
   std::unique_ptr<ServiceWorkerHandleReference> waiting_ref =
@@ -286,9 +282,9 @@
     return found->second;
 
   // WebServiceWorkerRegistrationImpl constructor calls
-  // AddServiceWorkerRegistration.
-  scoped_refptr<WebServiceWorkerRegistrationImpl> registration(
-      new WebServiceWorkerRegistrationImpl(std::move(registration_ref)));
+  // AddServiceWorkerRegistration to add itself into |registrations_|.
+  auto registration =
+      base::MakeRefCounted<WebServiceWorkerRegistrationImpl>(std::move(info));
   registration->SetInstalling(
       GetOrCreateServiceWorker(std::move(installing_ref)));
   registration->SetWaiting(GetOrCreateServiceWorker(std::move(waiting_ref)));
@@ -618,13 +614,6 @@
   registrations_.erase(registration_handle_id);
 }
 
-std::unique_ptr<ServiceWorkerRegistrationHandleReference>
-ServiceWorkerDispatcher::Adopt(
-    blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info) {
-  return ServiceWorkerRegistrationHandleReference::Adopt(
-      std::move(info), thread_safe_sender_.get());
-}
-
 std::unique_ptr<ServiceWorkerHandleReference> ServiceWorkerDispatcher::Adopt(
     const ServiceWorkerObjectInfo& info) {
   return ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get());
diff --git a/content/child/service_worker/service_worker_dispatcher.h b/content/child/service_worker/service_worker_dispatcher.h
index 0e4e52580..a87c24ce 100644
--- a/content/child/service_worker/service_worker_dispatcher.h
+++ b/content/child/service_worker/service_worker_dispatcher.h
@@ -40,7 +40,6 @@
 
 class ServiceWorkerHandleReference;
 class ServiceWorkerProviderContext;
-class ServiceWorkerRegistrationHandleReference;
 class ThreadSafeSender;
 class WebServiceWorkerImpl;
 class WebServiceWorkerRegistrationImpl;
@@ -230,8 +229,6 @@
 
   // Assumes that the given object information retains an interprocess handle
   // reference passed from the browser process, and adopts it.
-  std::unique_ptr<ServiceWorkerRegistrationHandleReference> Adopt(
-      blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info);
   std::unique_ptr<ServiceWorkerHandleReference> Adopt(
       const ServiceWorkerObjectInfo& info);
 
diff --git a/content/child/service_worker/service_worker_dispatcher_unittest.cc b/content/child/service_worker/service_worker_dispatcher_unittest.cc
index c013d51..d14bef97d 100644
--- a/content/child/service_worker/service_worker_dispatcher_unittest.cc
+++ b/content/child/service_worker/service_worker_dispatcher_unittest.cc
@@ -16,6 +16,7 @@
 #include "content/common/service_worker/service_worker_types.h"
 #include "ipc/ipc_sync_message_filter.h"
 #include "ipc/ipc_test_sink.h"
+#include "mojo/public/cpp/bindings/associated_binding_set.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerProviderClient.h"
 #include "third_party/WebKit/public/platform/modules/serviceworker/service_worker_registration.mojom.h"
@@ -24,6 +25,25 @@
 
 namespace {
 
+class MockServiceWorkerRegistrationObjectHost
+    : public blink::mojom::ServiceWorkerRegistrationObjectHost {
+ public:
+  MockServiceWorkerRegistrationObjectHost() = default;
+  ~MockServiceWorkerRegistrationObjectHost() override = default;
+
+  void AddBinding(
+      blink::mojom::ServiceWorkerRegistrationObjectHostAssociatedRequest
+          request) {
+    bindings_.AddBinding(this, std::move(request));
+  }
+
+  int GetBindingCount() const { return bindings_.size(); }
+
+ private:
+  mojo::AssociatedBindingSet<blink::mojom::ServiceWorkerRegistrationObjectHost>
+      bindings_;
+};
+
 class ServiceWorkerTestSender : public ThreadSafeSender {
  public:
   explicit ServiceWorkerTestSender(IPC::TestSink* ipc_sink)
@@ -59,6 +79,8 @@
     *info = blink::mojom::ServiceWorkerRegistrationObjectInfo::New();
     (*info)->handle_id = 10;
     (*info)->registration_id = 20;
+    remote_registration_object_host_.AddBinding(
+        mojo::MakeRequest(&(*info)->host_ptr_info));
 
     attrs->active.handle_id = 100;
     attrs->active.version_id = 200;
@@ -102,12 +124,17 @@
   ServiceWorkerDispatcher* dispatcher() { return dispatcher_.get(); }
   ThreadSafeSender* thread_safe_sender() { return sender_.get(); }
   IPC::TestSink* ipc_sink() { return &ipc_sink_; }
+  const MockServiceWorkerRegistrationObjectHost&
+  remote_registration_object_host() const {
+    return remote_registration_object_host_;
+  }
 
  private:
   base::MessageLoop message_loop_;
   IPC::TestSink ipc_sink_;
   std::unique_ptr<ServiceWorkerDispatcher> dispatcher_;
   scoped_refptr<ServiceWorkerTestSender> sender_;
+  MockServiceWorkerRegistrationObjectHost remote_registration_object_host_;
 
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDispatcherTest);
 };
@@ -340,99 +367,139 @@
 }
 
 TEST_F(ServiceWorkerDispatcherTest, GetOrCreateRegistration) {
-  blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info;
-  ServiceWorkerVersionAttributes attrs;
-  CreateObjectInfoAndVersionAttributes(&info, &attrs);
+  scoped_refptr<WebServiceWorkerRegistrationImpl> registration1;
+  scoped_refptr<WebServiceWorkerRegistrationImpl> registration2;
 
-  // Should return a registration object newly created with incrementing
-  // the refcounts.
-  scoped_refptr<WebServiceWorkerRegistrationImpl> registration1(
-      dispatcher()->GetOrCreateRegistration(info.Clone(), attrs));
-  EXPECT_TRUE(registration1);
-  EXPECT_TRUE(ContainsRegistration(info->handle_id));
-  EXPECT_EQ(info->registration_id, registration1->RegistrationId());
-  ASSERT_EQ(4UL, ipc_sink()->message_count());
-  EXPECT_EQ(ServiceWorkerHostMsg_IncrementRegistrationRefCount::ID,
-            ipc_sink()->GetMessageAt(0)->type());
-  EXPECT_EQ(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount::ID,
-            ipc_sink()->GetMessageAt(1)->type());
-  EXPECT_EQ(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount::ID,
-            ipc_sink()->GetMessageAt(2)->type());
-  EXPECT_EQ(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount::ID,
-            ipc_sink()->GetMessageAt(3)->type());
+  {
+    blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info;
+    ServiceWorkerVersionAttributes attrs;
+    CreateObjectInfoAndVersionAttributes(&info, &attrs);
+    int64_t registration_id = info->registration_id;
+    int32_t handle_id = info->handle_id;
+    // The 1st ServiceWorkerRegistrationObjectHost Mojo connection has been
+    // added.
+    ASSERT_EQ(1, remote_registration_object_host().GetBindingCount());
+
+    // Should return a registration object newly created with incrementing
+    // the refcounts.
+    registration1 =
+        dispatcher()->GetOrCreateRegistration(std::move(info), attrs);
+    EXPECT_TRUE(registration1);
+    EXPECT_TRUE(ContainsRegistration(handle_id));
+    EXPECT_EQ(registration_id, registration1->RegistrationId());
+    EXPECT_EQ(1, remote_registration_object_host().GetBindingCount());
+    ASSERT_EQ(3UL, ipc_sink()->message_count());
+    EXPECT_EQ(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount::ID,
+              ipc_sink()->GetMessageAt(0)->type());
+    EXPECT_EQ(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount::ID,
+              ipc_sink()->GetMessageAt(1)->type());
+    EXPECT_EQ(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount::ID,
+              ipc_sink()->GetMessageAt(2)->type());
+  }
 
   ipc_sink()->ClearMessages();
 
-  // Should return the same registration object without incrementing the
-  // refcounts.
-  scoped_refptr<WebServiceWorkerRegistrationImpl> registration2(
-      dispatcher()->GetOrCreateRegistration(std::move(info), attrs));
-  EXPECT_TRUE(registration2);
-  EXPECT_EQ(registration1, registration2);
-  EXPECT_EQ(0UL, ipc_sink()->message_count());
+  {
+    blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info;
+    ServiceWorkerVersionAttributes attrs;
+    CreateObjectInfoAndVersionAttributes(&info, &attrs);
+    // The 2nd Mojo connection has been added.
+    ASSERT_EQ(2, remote_registration_object_host().GetBindingCount());
+    // Should return the same registration object without incrementing the
+    // refcounts.
+    registration2 =
+        dispatcher()->GetOrCreateRegistration(std::move(info), attrs);
+    EXPECT_TRUE(registration2);
+    EXPECT_EQ(registration1, registration2);
+    // The 2nd Mojo connection has been dropped.
+    base::RunLoop().RunUntilIdle();
+    EXPECT_EQ(1, remote_registration_object_host().GetBindingCount());
+    EXPECT_EQ(0UL, ipc_sink()->message_count());
+  }
 
   ipc_sink()->ClearMessages();
 
   // The registration dtor decrements the refcounts.
   registration1 = nullptr;
   registration2 = nullptr;
-  ASSERT_EQ(4UL, ipc_sink()->message_count());
+  ASSERT_EQ(3UL, ipc_sink()->message_count());
   EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
             ipc_sink()->GetMessageAt(0)->type());
   EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
             ipc_sink()->GetMessageAt(1)->type());
   EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
             ipc_sink()->GetMessageAt(2)->type());
-  EXPECT_EQ(ServiceWorkerHostMsg_DecrementRegistrationRefCount::ID,
-            ipc_sink()->GetMessageAt(3)->type());
+  // The 1st Mojo connection has been dropped.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(0, remote_registration_object_host().GetBindingCount());
 }
 
 TEST_F(ServiceWorkerDispatcherTest, GetOrAdoptRegistration) {
-  blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info;
-  ServiceWorkerVersionAttributes attrs;
-  CreateObjectInfoAndVersionAttributes(&info, &attrs);
+  scoped_refptr<WebServiceWorkerRegistrationImpl> registration1;
+  scoped_refptr<WebServiceWorkerRegistrationImpl> registration2;
 
-  // Should return a registration object newly created with adopting the
-  // refcounts.
-  scoped_refptr<WebServiceWorkerRegistrationImpl> registration1(
-      dispatcher()->GetOrAdoptRegistration(info.Clone(), attrs));
-  EXPECT_TRUE(registration1);
-  EXPECT_TRUE(ContainsRegistration(info->handle_id));
-  EXPECT_EQ(info->registration_id, registration1->RegistrationId());
-  EXPECT_EQ(0UL, ipc_sink()->message_count());
+  {
+    blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info;
+    ServiceWorkerVersionAttributes attrs;
+    CreateObjectInfoAndVersionAttributes(&info, &attrs);
+    int64_t registration_id = info->registration_id;
+    int32_t handle_id = info->handle_id;
+    // The 1st ServiceWorkerRegistrationObjectHost Mojo connection has been
+    // added.
+    ASSERT_EQ(1, remote_registration_object_host().GetBindingCount());
+
+    // Should return a registration object newly created with adopting the
+    // refcounts.
+    registration1 =
+        dispatcher()->GetOrAdoptRegistration(std::move(info), attrs);
+    EXPECT_TRUE(registration1);
+    EXPECT_TRUE(ContainsRegistration(handle_id));
+    EXPECT_EQ(registration_id, registration1->RegistrationId());
+    EXPECT_EQ(1, remote_registration_object_host().GetBindingCount());
+    EXPECT_EQ(0UL, ipc_sink()->message_count());
+  }
 
   ipc_sink()->ClearMessages();
 
-  // Should return the same registration object without incrementing the
-  // refcounts.
-  scoped_refptr<WebServiceWorkerRegistrationImpl> registration2(
-      dispatcher()->GetOrAdoptRegistration(std::move(info), attrs));
-  EXPECT_TRUE(registration2);
-  EXPECT_EQ(registration1, registration2);
-  ASSERT_EQ(4UL, ipc_sink()->message_count());
-  EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
-            ipc_sink()->GetMessageAt(0)->type());
-  EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
-            ipc_sink()->GetMessageAt(1)->type());
-  EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
-            ipc_sink()->GetMessageAt(2)->type());
-  EXPECT_EQ(ServiceWorkerHostMsg_DecrementRegistrationRefCount::ID,
-            ipc_sink()->GetMessageAt(3)->type());
+  {
+    blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info;
+    ServiceWorkerVersionAttributes attrs;
+    CreateObjectInfoAndVersionAttributes(&info, &attrs);
+    // The 2nd Mojo connection has been added.
+    ASSERT_EQ(2, remote_registration_object_host().GetBindingCount());
+    // Should return the same registration object without incrementing the
+    // refcounts.
+    registration2 =
+        dispatcher()->GetOrAdoptRegistration(std::move(info), attrs);
+    EXPECT_TRUE(registration2);
+    EXPECT_EQ(registration1, registration2);
+    // The 2nd Mojo connection has been dropped.
+    base::RunLoop().RunUntilIdle();
+    EXPECT_EQ(1, remote_registration_object_host().GetBindingCount());
+    ASSERT_EQ(3UL, ipc_sink()->message_count());
+    EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
+              ipc_sink()->GetMessageAt(0)->type());
+    EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
+              ipc_sink()->GetMessageAt(1)->type());
+    EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
+              ipc_sink()->GetMessageAt(2)->type());
+  }
 
   ipc_sink()->ClearMessages();
 
   // The registration dtor decrements the refcounts.
   registration1 = nullptr;
   registration2 = nullptr;
-  ASSERT_EQ(4UL, ipc_sink()->message_count());
+  ASSERT_EQ(3UL, ipc_sink()->message_count());
   EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
             ipc_sink()->GetMessageAt(0)->type());
   EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
             ipc_sink()->GetMessageAt(1)->type());
   EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
             ipc_sink()->GetMessageAt(2)->type());
-  EXPECT_EQ(ServiceWorkerHostMsg_DecrementRegistrationRefCount::ID,
-            ipc_sink()->GetMessageAt(3)->type());
+  // The 1st Mojo connection has been dropped.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(0, remote_registration_object_host().GetBindingCount());
 }
 
 }  // namespace content
diff --git a/content/child/service_worker/service_worker_network_provider.cc b/content/child/service_worker/service_worker_network_provider.cc
index 333456bf..875038a3 100644
--- a/content/child/service_worker/service_worker_network_provider.cc
+++ b/content/child/service_worker/service_worker_network_provider.cc
@@ -10,7 +10,6 @@
 #include "content/child/service_worker/service_worker_dispatcher.h"
 #include "content/child/service_worker/service_worker_handle_reference.h"
 #include "content/child/service_worker/service_worker_provider_context.h"
-#include "content/child/service_worker/service_worker_registration_handle_reference.h"
 #include "content/child/thread_safe_sender.h"
 #include "content/common/navigation_params.h"
 #include "content/common/service_worker/service_worker_messages.h"
@@ -311,17 +310,15 @@
       info->provider_id, SERVICE_WORKER_PROVIDER_FOR_CONTROLLER,
       std::move(info->client_request), std::move(info->host_ptr_info),
       dispatcher, nullptr /* loader_factory_getter */);
-  std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration =
-      ServiceWorkerRegistrationHandleReference::Adopt(
-          std::move(info->registration), sender);
   std::unique_ptr<ServiceWorkerHandleReference> installing =
       ServiceWorkerHandleReference::Adopt(info->attributes.installing, sender);
   std::unique_ptr<ServiceWorkerHandleReference> waiting =
       ServiceWorkerHandleReference::Adopt(info->attributes.waiting, sender);
   std::unique_ptr<ServiceWorkerHandleReference> active =
       ServiceWorkerHandleReference::Adopt(info->attributes.active, sender);
-  context_->SetRegistration(std::move(registration), std::move(installing),
-                            std::move(waiting), std::move(active));
+  context_->SetRegistrationForServiceWorkerGlobalScope(
+      std::move(info->registration), std::move(installing), std::move(waiting),
+      std::move(active));
 
   if (info->script_loader_factory_ptr_info.is_valid()) {
     script_loader_factory_.Bind(
diff --git a/content/child/service_worker/service_worker_provider_context.cc b/content/child/service_worker/service_worker_provider_context.cc
index 429e00c5..2af7d5157 100644
--- a/content/child/service_worker/service_worker_provider_context.cc
+++ b/content/child/service_worker/service_worker_provider_context.cc
@@ -15,7 +15,6 @@
 #include "content/child/service_worker/controller_service_worker_connector.h"
 #include "content/child/service_worker/service_worker_dispatcher.h"
 #include "content/child/service_worker/service_worker_handle_reference.h"
-#include "content/child/service_worker/service_worker_registration_handle_reference.h"
 #include "content/child/service_worker/service_worker_subresource_loader.h"
 #include "content/child/thread_safe_sender.h"
 #include "content/child/worker_thread_registry.h"
@@ -75,7 +74,14 @@
 struct ServiceWorkerProviderContext::ControllerState {
   ControllerState() = default;
   ~ControllerState() = default;
-  std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration;
+  // |registration->host_ptr_info| will be taken by
+  // ServiceWorkerProviderContext::TakeRegistrationForServiceWorkerGlobalScope()
+  // means after that |registration| will be in a half-way taken state.
+  // TODO(leonhsl): To avoid the half-way taken state mentioned above, make
+  // ServiceWorkerProviderContext::TakeRegistrationForServiceWorkerGlobalScope()
+  // take/reset all information of |registration|, |installing|, |waiting| and
+  // |active| all at once.
+  blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration;
   std::unique_ptr<ServiceWorkerHandleReference> installing;
   std::unique_ptr<ServiceWorkerHandleReference> waiting;
   std::unique_ptr<ServiceWorkerHandleReference> active;
@@ -114,8 +120,8 @@
   }
 }
 
-void ServiceWorkerProviderContext::SetRegistration(
-    std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration,
+void ServiceWorkerProviderContext::SetRegistrationForServiceWorkerGlobalScope(
+    blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration,
     std::unique_ptr<ServiceWorkerHandleReference> installing,
     std::unique_ptr<ServiceWorkerHandleReference> waiting,
     std::unique_ptr<ServiceWorkerHandleReference> active) {
@@ -130,14 +136,19 @@
   state->active = std::move(active);
 }
 
-void ServiceWorkerProviderContext::GetRegistration(
+void ServiceWorkerProviderContext::TakeRegistrationForServiceWorkerGlobalScope(
     blink::mojom::ServiceWorkerRegistrationObjectInfoPtr* info,
     ServiceWorkerVersionAttributes* attrs) {
   DCHECK(!main_thread_task_runner_->RunsTasksInCurrentSequence());
   ControllerState* state = controller_state_.get();
   DCHECK(state);
   DCHECK(state->registration);
-  *info = state->registration->info().Clone();
+  DCHECK(state->registration->host_ptr_info.is_valid());
+  *info = blink::mojom::ServiceWorkerRegistrationObjectInfo::New(
+      state->registration->registration_id, state->registration->handle_id,
+      state->registration->options->Clone(),
+      std::move(state->registration->host_ptr_info));
+
   if (state->installing)
     attrs->installing = state->installing->info();
   if (state->waiting)
diff --git a/content/child/service_worker/service_worker_provider_context.h b/content/child/service_worker/service_worker_provider_context.h
index 5f699bc..b09c55a 100644
--- a/content/child/service_worker/service_worker_provider_context.h
+++ b/content/child/service_worker/service_worker_provider_context.h
@@ -30,7 +30,6 @@
 }
 
 class ServiceWorkerHandleReference;
-class ServiceWorkerRegistrationHandleReference;
 struct ServiceWorkerProviderContextDeleter;
 
 // ServiceWorkerProviderContext stores common state for service worker
@@ -82,19 +81,22 @@
   int provider_id() const { return provider_id_; }
 
   // For service worker execution contexts. Sets the registration for
-  // ServiceWorkerGlobalScope#registration. Unlike GetRegistration(),
-  // called on the main thread. SetRegistration() is called during
-  // the setup for service worker startup, so it is guaranteed to be called
-  // before GetRegistration().
-  void SetRegistration(
-      std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration,
+  // ServiceWorkerGlobalScope#registration. Unlike
+  // TakeRegistrationForServiceWorkerGlobalScope(), called on the main thread.
+  // SetRegistrationForServiceWorkerGlobalScope() is called during the setup for
+  // service worker startup, so it is guaranteed to be called before
+  // TakeRegistrationForServiceWorkerGlobalScope().
+  void SetRegistrationForServiceWorkerGlobalScope(
+      blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration,
       std::unique_ptr<ServiceWorkerHandleReference> installing,
       std::unique_ptr<ServiceWorkerHandleReference> waiting,
       std::unique_ptr<ServiceWorkerHandleReference> active);
 
   // For service worker execution contexts. Used for initializing
   // ServiceWorkerGlobalScope#registration. Called on the worker thread.
-  void GetRegistration(
+  // This takes ServiceWorkerRegistrationObjectHost ptr info from
+  // ControllerState::registration.
+  void TakeRegistrationForServiceWorkerGlobalScope(
       blink::mojom::ServiceWorkerRegistrationObjectInfoPtr* info,
       ServiceWorkerVersionAttributes* attrs);
 
diff --git a/content/child/service_worker/service_worker_provider_context_unittest.cc b/content/child/service_worker/service_worker_provider_context_unittest.cc
index 76f6a5a..0adc051 100644
--- a/content/child/service_worker/service_worker_provider_context_unittest.cc
+++ b/content/child/service_worker/service_worker_provider_context_unittest.cc
@@ -9,7 +9,6 @@
 #include "content/child/service_worker/service_worker_dispatcher.h"
 #include "content/child/service_worker/service_worker_handle_reference.h"
 #include "content/child/service_worker/service_worker_provider_context.h"
-#include "content/child/service_worker/service_worker_registration_handle_reference.h"
 #include "content/child/service_worker/web_service_worker_impl.h"
 #include "content/child/service_worker/web_service_worker_registration_impl.h"
 #include "content/child/thread_safe_sender.h"
@@ -20,6 +19,7 @@
 #include "content/public/common/url_loader_factory.mojom.h"
 #include "ipc/ipc_sync_message_filter.h"
 #include "ipc/ipc_test_sink.h"
+#include "mojo/public/cpp/bindings/associated_binding_set.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/public/platform/modules/serviceworker/service_worker_registration.mojom.h"
 
@@ -27,6 +27,25 @@
 
 namespace {
 
+class MockServiceWorkerRegistrationObjectHost
+    : public blink::mojom::ServiceWorkerRegistrationObjectHost {
+ public:
+  MockServiceWorkerRegistrationObjectHost() = default;
+  ~MockServiceWorkerRegistrationObjectHost() override = default;
+
+  void AddBinding(
+      blink::mojom::ServiceWorkerRegistrationObjectHostAssociatedRequest
+          request) {
+    bindings_.AddBinding(this, std::move(request));
+  }
+
+  int GetBindingCount() const { return bindings_.size(); }
+
+ private:
+  mojo::AssociatedBindingSet<blink::mojom::ServiceWorkerRegistrationObjectHost>
+      bindings_;
+};
+
 class ServiceWorkerTestSender : public ThreadSafeSender {
  public:
   explicit ServiceWorkerTestSender(IPC::TestSink* ipc_sink)
@@ -59,6 +78,8 @@
     *info = blink::mojom::ServiceWorkerRegistrationObjectInfo::New();
     (*info)->handle_id = 10;
     (*info)->registration_id = 20;
+    remote_registration_object_host_.AddBinding(
+        mojo::MakeRequest(&(*info)->host_ptr_info));
 
     attrs->active.handle_id = 100;
     attrs->active.version_id = 200;
@@ -71,12 +92,17 @@
   ThreadSafeSender* thread_safe_sender() { return sender_.get(); }
   IPC::TestSink* ipc_sink() { return &ipc_sink_; }
   ServiceWorkerDispatcher* dispatcher() { return dispatcher_.get(); }
+  const MockServiceWorkerRegistrationObjectHost&
+  remote_registration_object_host() const {
+    return remote_registration_object_host_;
+  }
 
  private:
   base::MessageLoop message_loop_;
   IPC::TestSink ipc_sink_;
   std::unique_ptr<ServiceWorkerDispatcher> dispatcher_;
   scoped_refptr<ServiceWorkerTestSender> sender_;
+  MockServiceWorkerRegistrationObjectHost remote_registration_object_host_;
 
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderContextTest);
 };
@@ -87,9 +113,8 @@
   blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration_info;
   ServiceWorkerVersionAttributes version_attrs;
   CreateObjectInfoAndVersionAttributes(&registration_info, &version_attrs);
-  std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration =
-      ServiceWorkerRegistrationHandleReference::Adopt(
-          std::move(registration_info), thread_safe_sender());
+  // ServiceWorkerRegistrationObjectHost Mojo connection has been added.
+  ASSERT_EQ(1, remote_registration_object_host().GetBindingCount());
   std::unique_ptr<ServiceWorkerHandleReference> installing =
       ServiceWorkerHandleReference::Adopt(version_attrs.installing,
                                           thread_safe_sender());
@@ -107,23 +132,24 @@
       dispatcher(), nullptr /* loader_factory_getter */);
 
   // The passed references should be adopted and owned by the provider context.
-  provider_context->SetRegistration(std::move(registration),
-                                    std::move(installing), std::move(waiting),
-                                    std::move(active));
+  provider_context->SetRegistrationForServiceWorkerGlobalScope(
+      std::move(registration_info), std::move(installing), std::move(waiting),
+      std::move(active));
   EXPECT_EQ(0UL, ipc_sink()->message_count());
 
   // Destruction of the provider context should release references to the
   // associated registration and its versions.
   provider_context = nullptr;
-  ASSERT_EQ(4UL, ipc_sink()->message_count());
+  ASSERT_EQ(3UL, ipc_sink()->message_count());
   EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
             ipc_sink()->GetMessageAt(0)->type());
   EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
             ipc_sink()->GetMessageAt(1)->type());
   EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
             ipc_sink()->GetMessageAt(2)->type());
-  EXPECT_EQ(ServiceWorkerHostMsg_DecrementRegistrationRefCount::ID,
-            ipc_sink()->GetMessageAt(3)->type());
+  // ServiceWorkerRegistrationObjectHost Mojo connection got broken.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(0, remote_registration_object_host().GetBindingCount());
 }
 
 }  // namespace content
diff --git a/content/child/service_worker/service_worker_registration_handle_reference.cc b/content/child/service_worker/service_worker_registration_handle_reference.cc
deleted file mode 100644
index d45f7b8..0000000
--- a/content/child/service_worker/service_worker_registration_handle_reference.cc
+++ /dev/null
@@ -1,51 +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 "content/child/service_worker/service_worker_registration_handle_reference.h"
-
-#include "base/memory/ptr_util.h"
-#include "content/child/thread_safe_sender.h"
-#include "content/common/service_worker/service_worker_messages.h"
-#include "third_party/WebKit/public/platform/modules/serviceworker/service_worker_registration.mojom.h"
-
-namespace content {
-
-std::unique_ptr<ServiceWorkerRegistrationHandleReference>
-ServiceWorkerRegistrationHandleReference::Create(
-    blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info,
-    ThreadSafeSender* sender) {
-  return base::WrapUnique(new ServiceWorkerRegistrationHandleReference(
-      std::move(info), sender, true));
-}
-
-std::unique_ptr<ServiceWorkerRegistrationHandleReference>
-ServiceWorkerRegistrationHandleReference::Adopt(
-    blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info,
-    ThreadSafeSender* sender) {
-  return base::WrapUnique(new ServiceWorkerRegistrationHandleReference(
-      std::move(info), sender, false));
-}
-
-ServiceWorkerRegistrationHandleReference::
-    ServiceWorkerRegistrationHandleReference(
-        blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info,
-        ThreadSafeSender* sender,
-        bool increment_ref_in_ctor)
-    : info_(std::move(info)), sender_(sender) {
-  DCHECK_NE(blink::mojom::kInvalidServiceWorkerRegistrationHandleId,
-            info_->handle_id);
-  DCHECK(sender_.get());
-  if (!increment_ref_in_ctor)
-    return;
-  sender_->Send(
-      new ServiceWorkerHostMsg_IncrementRegistrationRefCount(info_->handle_id));
-}
-
-ServiceWorkerRegistrationHandleReference::
-~ServiceWorkerRegistrationHandleReference() {
-  sender_->Send(
-      new ServiceWorkerHostMsg_DecrementRegistrationRefCount(info_->handle_id));
-}
-
-}  // namespace content
diff --git a/content/child/service_worker/service_worker_registration_handle_reference.h b/content/child/service_worker/service_worker_registration_handle_reference.h
deleted file mode 100644
index 4b796761..0000000
--- a/content/child/service_worker/service_worker_registration_handle_reference.h
+++ /dev/null
@@ -1,63 +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 CONTENT_CHILD_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_HANDLE_REFERENCE_H_
-#define CONTENT_CHILD_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_HANDLE_REFERENCE_H_
-
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "content/common/service_worker/service_worker_types.h"
-#include "third_party/WebKit/public/platform/modules/serviceworker/service_worker_registration.mojom.h"
-#include "url/gurl.h"
-
-namespace content {
-
-class ThreadSafeSender;
-
-// Represents an interprocess reference to ServiceWorkerRegistrationHandle
-// managed in the browser process. The constructor and destructor sends a
-// message to increment or decrement the reference count to the browser
-// process.
-class CONTENT_EXPORT ServiceWorkerRegistrationHandleReference {
- public:
-  // Creates a new ServiceWorkerRegistrationHandleReference and increments
-  // ref-count.
-  static std::unique_ptr<ServiceWorkerRegistrationHandleReference> Create(
-      blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info,
-      ThreadSafeSender* sender);
-
-  // Creates a new ServiceWorkerRegistrationHandleReference by adopting a
-  // ref-count.
-  static std::unique_ptr<ServiceWorkerRegistrationHandleReference> Adopt(
-      blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info,
-      ThreadSafeSender* sender);
-
-  ~ServiceWorkerRegistrationHandleReference();
-
-  const blink::mojom::ServiceWorkerRegistrationObjectInfo& info() const {
-    return *info_;
-  }
-  int handle_id() const { return info_->handle_id; }
-  GURL scope() const { return info_->options->scope; }
-  int64_t registration_id() const { return info_->registration_id; }
-
- private:
-  ServiceWorkerRegistrationHandleReference(
-      blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info,
-      ThreadSafeSender* sender,
-      bool increment_ref_in_ctor);
-
-  blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info_;
-  scoped_refptr<ThreadSafeSender> sender_;
-
-  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRegistrationHandleReference);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_CHILD_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_HANDLE_REFERENCE_H_
diff --git a/content/child/service_worker/service_worker_subresource_loader.cc b/content/child/service_worker/service_worker_subresource_loader.cc
index 7f218cac..93eca998 100644
--- a/content/child/service_worker/service_worker_subresource_loader.cc
+++ b/content/child/service_worker/service_worker_subresource_loader.cc
@@ -217,9 +217,9 @@
   // Not supported (do nothing).
 }
 
-void ServiceWorkerSubresourceLoader::PauseCachingResponseBody() {}
+void ServiceWorkerSubresourceLoader::PauseReadingBodyFromNet() {}
 
-void ServiceWorkerSubresourceLoader::ResumeCachingResponseBody() {}
+void ServiceWorkerSubresourceLoader::ResumeReadingBodyFromNet() {}
 
 // ServiceWorkerSubresourceLoader: URLLoaderClient for Blob reading ---------
 
diff --git a/content/child/service_worker/service_worker_subresource_loader.h b/content/child/service_worker/service_worker_subresource_loader.h
index 461ec63..9f13a6d8 100644
--- a/content/child/service_worker/service_worker_subresource_loader.h
+++ b/content/child/service_worker/service_worker_subresource_loader.h
@@ -78,8 +78,8 @@
   void FollowRedirect() override;
   void SetPriority(net::RequestPriority priority,
                    int intra_priority_value) override;
-  void PauseCachingResponseBody() override;
-  void ResumeCachingResponseBody() override;
+  void PauseReadingBodyFromNet() override;
+  void ResumeReadingBodyFromNet() override;
 
   // Calls url_loader_client_->OnReceiveResponse() with |response_head_|.
   void CommitResponseHeaders();
diff --git a/content/child/service_worker/web_service_worker_registration_impl.cc b/content/child/service_worker/web_service_worker_registration_impl.cc
index 147cf8d..83878bb 100644
--- a/content/child/service_worker/web_service_worker_registration_impl.cc
+++ b/content/child/service_worker/web_service_worker_registration_impl.cc
@@ -9,7 +9,6 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "content/child/service_worker/service_worker_dispatcher.h"
-#include "content/child/service_worker/service_worker_registration_handle_reference.h"
 #include "content/child/service_worker/web_service_worker_impl.h"
 #include "content/child/service_worker/web_service_worker_provider_impl.h"
 #include "content/common/service_worker/service_worker_types.h"
@@ -52,15 +51,15 @@
 WebServiceWorkerRegistrationImpl::QueuedTask::~QueuedTask() {}
 
 WebServiceWorkerRegistrationImpl::WebServiceWorkerRegistrationImpl(
-    std::unique_ptr<ServiceWorkerRegistrationHandleReference> handle_ref)
-    : handle_ref_(std::move(handle_ref)), proxy_(nullptr) {
-  DCHECK(handle_ref_);
+    blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info)
+    : info_(std::move(info)), proxy_(nullptr) {
+  DCHECK(info_);
   DCHECK_NE(blink::mojom::kInvalidServiceWorkerRegistrationHandleId,
-            handle_ref_->handle_id());
+            info_->handle_id);
   ServiceWorkerDispatcher* dispatcher =
       ServiceWorkerDispatcher::GetThreadSpecificInstance();
   DCHECK(dispatcher);
-  dispatcher->AddServiceWorkerRegistration(handle_ref_->handle_id(), this);
+  dispatcher->AddServiceWorkerRegistration(info_->handle_id, this);
 }
 
 void WebServiceWorkerRegistrationImpl::SetInstalling(
@@ -121,7 +120,7 @@
 }
 
 blink::WebURL WebServiceWorkerRegistrationImpl::Scope() const {
-  return handle_ref_->scope();
+  return info_->options->scope;
 }
 
 void WebServiceWorkerRegistrationImpl::Update(
@@ -189,7 +188,7 @@
 }
 
 int64_t WebServiceWorkerRegistrationImpl::RegistrationId() const {
-  return handle_ref_->registration_id();
+  return info_->registration_id;
 }
 
 // static
@@ -198,14 +197,14 @@
     const scoped_refptr<WebServiceWorkerRegistrationImpl>& registration) {
   if (!registration)
     return nullptr;
-  return base::MakeUnique<HandleImpl>(registration);
+  return std::make_unique<HandleImpl>(registration);
 }
 
 WebServiceWorkerRegistrationImpl::~WebServiceWorkerRegistrationImpl() {
   ServiceWorkerDispatcher* dispatcher =
       ServiceWorkerDispatcher::GetThreadSpecificInstance();
   if (dispatcher)
-    dispatcher->RemoveServiceWorkerRegistration(handle_ref_->handle_id());
+    dispatcher->RemoveServiceWorkerRegistration(info_->handle_id);
 }
 
 }  // namespace content
diff --git a/content/child/service_worker/web_service_worker_registration_impl.h b/content/child/service_worker/web_service_worker_registration_impl.h
index 1248aff77..a5eb5fe 100644
--- a/content/child/service_worker/web_service_worker_registration_impl.h
+++ b/content/child/service_worker/web_service_worker_registration_impl.h
@@ -15,6 +15,7 @@
 #include "base/memory/ref_counted.h"
 #include "content/common/content_export.h"
 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerRegistration.h"
+#include "third_party/WebKit/public/platform/modules/serviceworker/service_worker_registration.mojom.h"
 
 namespace blink {
 class WebServiceWorkerRegistrationProxy;
@@ -22,14 +23,14 @@
 
 namespace content {
 
-class ServiceWorkerRegistrationHandleReference;
 class WebServiceWorkerImpl;
 
 // Each instance corresponds to one ServiceWorkerRegistration object in JS
 // context, and is held by ServiceWorkerRegistration object in Blink's C++ layer
 // via WebServiceWorkerRegistration::Handle.
 //
-// Each instance holds one ServiceWorkerRegistrationHandleReference so that
+// Each instance holds one mojo connection of interface
+// blink::mojom::ServiceWorkerRegistrationObjectHost inside |info_|, so that
 // corresponding ServiceWorkerRegistrationHandle doesn't go away in the browser
 // process while the ServiceWorkerRegistration object is alive.
 class CONTENT_EXPORT WebServiceWorkerRegistrationImpl
@@ -37,7 +38,7 @@
       public base::RefCounted<WebServiceWorkerRegistrationImpl> {
  public:
   explicit WebServiceWorkerRegistrationImpl(
-      std::unique_ptr<ServiceWorkerRegistrationHandleReference> handle_ref);
+      blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info);
 
   void SetInstalling(const scoped_refptr<WebServiceWorkerImpl>& service_worker);
   void SetWaiting(const scoped_refptr<WebServiceWorkerImpl>& service_worker);
@@ -100,7 +101,7 @@
 
   void RunQueuedTasks();
 
-  std::unique_ptr<ServiceWorkerRegistrationHandleReference> handle_ref_;
+  blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info_;
   blink::WebServiceWorkerRegistrationProxy* proxy_;
 
   std::vector<QueuedTask> queued_tasks_;
diff --git a/content/common/input/input_handler.mojom b/content/common/input/input_handler.mojom
index 905aa5bd..b7a8296 100644
--- a/content/common/input/input_handler.mojom
+++ b/content/common/input/input_handler.mojom
@@ -7,11 +7,12 @@
 import "content/common/native_types.mojom";
 import "mojo/common/string16.mojom";
 import "services/ui/public/interfaces/ime/ime.mojom";
+import "third_party/WebKit/public/web/selection_menu_behavior.mojom";
 import "ui/events/mojo/event.mojom";
 import "ui/events/mojo/event_constants.mojom";
-import "ui/latency/mojo/latency_info.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 import "ui/gfx/range/mojo/range.mojom";
+import "ui/latency/mojo/latency_info.mojom";
 
 
 // These structs are purposely duplicated from ui/events/mojom/event.mojom.
@@ -309,8 +310,10 @@
   // Sent by the browser to ask the renderer to adjust the selection start and
   // end points by the given amounts. A negative amount moves the selection
   // towards the beginning of the document, a positive amount moves the
-  // selection towards the end of the document.
-  AdjustSelectionByCharacterOffset(int32 start, int32 end);
+  // selection towards the end of the document. Will send show selection menu
+  // event when needed.
+  AdjustSelectionByCharacterOffset(
+      int32 start, int32 end, blink.mojom.SelectionMenuBehavior behavior);
 
   // Requests the renderer to move the selection extent point to a new position.
   // Expects a MoveRangeSelectionExtent_ACK message when finished.
diff --git a/content/common/input_messages.h b/content/common/input_messages.h
index 9c0aeb0..1cfd6f5f 100644
--- a/content/common/input_messages.h
+++ b/content/common/input_messages.h
@@ -292,10 +292,12 @@
 // Sent by the browser to ask the renderer to adjust the selection start and
 // end points by the given amounts. A negative amount moves the selection
 // towards the beginning of the document, a positive amount moves the selection
-// towards the end of the document.
-IPC_MESSAGE_ROUTED2(InputMsg_AdjustSelectionByCharacterOffset,
+// towards the end of the document. Will send show selection menu event when
+// needed.
+IPC_MESSAGE_ROUTED3(InputMsg_AdjustSelectionByCharacterOffset,
                     int /* start_adjust*/,
-                    int /* end_adjust */)
+                    int /* end_adjust */,
+                    bool /* show_selection_menu */)
 
 // Requests the renderer to move the selection extent point to a new position.
 // Expects a MoveRangeSelectionExtent_ACK message when finished.
diff --git a/content/common/sandbox_linux/bpf_cros_amd_gpu_policy_linux.cc b/content/common/sandbox_linux/bpf_cros_amd_gpu_policy_linux.cc
index 9486797d..a72d87e 100644
--- a/content/common/sandbox_linux/bpf_cros_amd_gpu_policy_linux.cc
+++ b/content/common/sandbox_linux/bpf_cros_amd_gpu_policy_linux.cc
@@ -88,15 +88,17 @@
 // openat and in the non-Chrome OS case unlink allowed.
 ResultExpr CrosAmdGpuBrokerProcessPolicy::EvaluateSyscall(int sysno) const {
   switch (sysno) {
-    case __NR_access:
     case __NR_faccessat:
-    case __NR_open:
     case __NR_openat:
+#if !defined(__aarch64__)
+    case __NR_access:
+    case __NR_open:
 #if !defined(OS_CHROMEOS)
     // The broker process needs to able to unlink the temporary
     // files that it may create. This is used by DRI3.
     case __NR_unlink:
-#endif
+#endif  // !defined(OS_CHROMEOS)
+#endif  // !define(__aarch64__)
       return Allow();
     default:
       return CrosAmdGpuProcessPolicy::EvaluateSyscall(sysno);
@@ -112,12 +114,14 @@
 ResultExpr CrosAmdGpuProcessPolicy::EvaluateSyscall(int sysno) const {
   switch (sysno) {
     case __NR_fstatfs:
-    case __NR_getdents:
-    case __NR_readlink:
     case __NR_sched_setscheduler:
-    case __NR_stat:
     case __NR_sysinfo:
     case __NR_uname:
+#if !defined(__aarch64__)
+    case __NR_getdents:
+    case __NR_readlink:
+    case __NR_stat:
+#endif
       return Allow();
 #if defined(__x86_64__)
     // Allow only AF_UNIX for |domain|.
diff --git a/content/common/sandbox_linux/sandbox_linux.cc b/content/common/sandbox_linux/sandbox_linux.cc
index 9d20602..570e64f 100644
--- a/content/common/sandbox_linux/sandbox_linux.cc
+++ b/content/common/sandbox_linux/sandbox_linux.cc
@@ -394,44 +394,54 @@
   }
   // Limit the address space to 4GB.
   // This is in the hope of making some kernel exploits more complex and less
-  // reliable. It also limits sprays a little on 64-bit.
+  // reliable. It also limits sprays a little on 64 bits.
   rlim_t address_space_limit = std::numeric_limits<uint32_t>::max();
   rlim_t address_space_limit_max = std::numeric_limits<uint32_t>::max();
-#if defined(__LP64__)
-  // On 64 bits, V8 and possibly others will reserve massive memory ranges and
-  // rely on on-demand paging for allocation.  Unfortunately, even
-  // MADV_DONTNEED ranges  count towards RLIMIT_AS so this is not an option.
-  // See crbug.com/169327 for a discussion.
-  // On the GPU process, irrespective of V8, we can exhaust a 4GB address space
-  // under normal usage, see crbug.com/271119
-  // For now, increase limit to 16GB for renderer and worker and GPU processes
-  // to accomodate.
-  if (process_type == switches::kRendererProcess ||
-      process_type == switches::kGpuProcess) {
-    address_space_limit = 1L << 34;
-    // WebAssembly memory objects use a large amount of address space when
-    // trap-based bounds checks are enabled. To accomodate this, we allow the
-    // address space limit to adjust dynamically up to a certain limit. The
-    // limit is currently 4TiB, which should allow enough address space for any
-    // reasonable page. See https://crbug.com/750378
-    if (base::FeatureList::IsEnabled(features::kWebAssemblyTrapHandler)) {
-      address_space_limit_max = 1L << 42;
-    } else {
-      // If we are not using trap-based bounds checks, there's no reason to
-      // allow the address space limit to grow.
-      address_space_limit_max = address_space_limit;
+
+  if (sizeof(rlim_t) == 8) {
+    // On 64 bits, V8 and possibly others will reserve massive memory ranges and
+    // rely on on-demand paging for allocation.  Unfortunately, even
+    // MADV_DONTNEED ranges count towards RLIMIT_AS so this is not an option.
+    // See crbug.com/169327 for a discussion.
+    // On the GPU process, irrespective of V8, we can exhaust a 4GB address
+    // space under normal usage, see crbug.com/271119.
+    // For now, increase limit to 16GB for renderer, worker, and GPU processes
+    // to accomodate.
+    if (process_type == switches::kRendererProcess ||
+        process_type == switches::kGpuProcess) {
+      address_space_limit = 1ULL << 34;
+      // WebAssembly memory objects use a large amount of address space when
+      // trap-based bounds checks are enabled. To accomodate this, we allow the
+      // address space limit to adjust dynamically up to a certain limit. The
+      // limit is currently 4TiB, which should allow enough address space for
+      // any reasonable page. See https://crbug.com/750378.
+      if (base::FeatureList::IsEnabled(features::kWebAssemblyTrapHandler)) {
+        address_space_limit_max = 1ULL << 42;
+      } else {
+        // If we are not using trap-based bounds checks, there's no reason to
+        // allow the address space limit to grow.
+        address_space_limit_max = address_space_limit;
+      }
     }
   }
-#endif  // defined(__LP64__)
 
-  // On all platforms, add a limit to the brk() heap that would prevent
+  // By default, add a limit to the VmData memory area that would prevent
   // allocations that can't be index by an int.
-  const rlim_t kNewDataSegmentMaxSize = std::numeric_limits<int>::max();
+  rlim_t new_data_segment_max_size = std::numeric_limits<int>::max();
+
+  if (sizeof(rlim_t) == 8) {
+    // On 64 bits, increase the RLIMIT_DATA limit to 8GB.
+    // RLIMIT_DATA did not account for mmap()-ed memory until
+    // https://github.com/torvalds/linux/commit/84638335900f1995495838fe1bd4870c43ec1f6.
+    // When Chrome runs on devices with this patch, it will OOM very easily.
+    // See https://crbug.com/752185.
+    new_data_segment_max_size = 1ULL << 33;
+  }
 
   bool limited_as = sandbox::ResourceLimits::LowerSoftAndHardLimits(
       RLIMIT_AS, address_space_limit, address_space_limit_max);
   bool limited_data =
-      sandbox::ResourceLimits::Lower(RLIMIT_DATA, kNewDataSegmentMaxSize);
+      sandbox::ResourceLimits::Lower(RLIMIT_DATA, new_data_segment_max_size);
 
   // Cache the resource limit before turning on the sandbox.
   base::SysInfo::AmountOfVirtualMemory();
diff --git a/content/common/service_worker/service_worker_messages.h b/content/common/service_worker/service_worker_messages.h
index a5a5f63..c2994d8e 100644
--- a/content/common/service_worker/service_worker_messages.h
+++ b/content/common/service_worker/service_worker_messages.h
@@ -210,14 +210,6 @@
 IPC_MESSAGE_CONTROL1(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount,
                      int /* handle_id */)
 
-// Increments and decrements the ServiceWorkerRegistration object's reference
-// counting in the browser side. The registration object is created with
-// ref-count==1 initially.
-IPC_MESSAGE_CONTROL1(ServiceWorkerHostMsg_IncrementRegistrationRefCount,
-                     int /* registration_handle_id */)
-IPC_MESSAGE_CONTROL1(ServiceWorkerHostMsg_DecrementRegistrationRefCount,
-                     int /* registration_handle_id */)
-
 // Tells the browser to terminate a service worker. Used in layout tests to
 // verify behavior when a service worker isn't running.
 IPC_MESSAGE_CONTROL1(ServiceWorkerHostMsg_TerminateWorker,
diff --git a/content/gpu/gpu_child_thread.cc b/content/gpu/gpu_child_thread.cc
index d9de3c3c..28b2d8a3 100644
--- a/content/gpu/gpu_child_thread.cc
+++ b/content/gpu/gpu_child_thread.cc
@@ -185,8 +185,7 @@
   gpu_service_->set_in_host_process(in_browser_process_);
 }
 
-GpuChildThread::~GpuChildThread() {
-}
+GpuChildThread::~GpuChildThread() {}
 
 void GpuChildThread::Init(const base::Time& process_start_time) {
   gpu_service_->set_start_time(process_start_time);
@@ -272,14 +271,18 @@
       sync_point_manager, ChildProcess::current()->GetShutDownEvent());
   CHECK(gpu_service_->media_gpu_channel_manager());
 
+  media::AndroidOverlayMojoFactoryCB overlay_factory_cb;
+#if defined(OS_ANDROID)
+  overlay_factory_cb = base::Bind(&GpuChildThread::CreateAndroidOverlay,
+                                  base::ThreadTaskRunnerHandle::Get());
+  gpu_service_->media_gpu_channel_manager()->SetOverlayFactory(
+      overlay_factory_cb);
+#endif
+
   // Only set once per process instance.
   service_factory_.reset(new GpuServiceFactory(
-      gpu_service_->media_gpu_channel_manager()->AsWeakPtr()));
-
-#if defined(OS_ANDROID)
-  gpu_service_->media_gpu_channel_manager()->SetOverlayFactory(
-      base::Bind(&GpuChildThread::CreateAndroidOverlay));
-#endif
+      gpu_service_->media_gpu_channel_manager()->AsWeakPtr(),
+      overlay_factory_cb));
 
   if (GetContentClient()->gpu())  // NULL in tests.
     GetContentClient()->gpu()->GpuServiceInitialized(gpu_preferences);
@@ -304,13 +307,32 @@
 #if defined(OS_ANDROID)
 // static
 std::unique_ptr<media::AndroidOverlay> GpuChildThread::CreateAndroidOverlay(
+    scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+    std::unique_ptr<service_manager::ServiceContextRef> context_ref,
     const base::UnguessableToken& routing_token,
     media::AndroidOverlayConfig config) {
-  media::mojom::AndroidOverlayProviderPtr provider_ptr;
-  ChildThread::Get()->GetConnector()->BindInterface(
-      content::mojom::kBrowserServiceName, &provider_ptr);
+  media::mojom::AndroidOverlayProviderPtr overlay_provider;
+  if (main_task_runner->RunsTasksInCurrentSequence()) {
+    ChildThread::Get()->GetConnector()->BindInterface(
+        content::mojom::kBrowserServiceName, &overlay_provider);
+  } else {
+    // Create a connector on this sequence and bind it on the main thread.
+    service_manager::mojom::ConnectorRequest request;
+    auto connector = service_manager::Connector::Create(&request);
+    connector->BindInterface(content::mojom::kBrowserServiceName,
+                             &overlay_provider);
+    auto bind_connector_request =
+        [](service_manager::mojom::ConnectorRequest request) {
+          ChildThread::Get()->GetConnector()->BindConnectorRequest(
+              std::move(request));
+        };
+    main_task_runner->PostTask(
+        FROM_HERE, base::BindOnce(bind_connector_request, std::move(request)));
+  }
+
   return base::MakeUnique<media::MojoAndroidOverlay>(
-      std::move(provider_ptr), std::move(config), routing_token);
+      std::move(overlay_provider), std::move(config), routing_token,
+      std::move(context_ref));
 }
 #endif
 
diff --git a/content/gpu/gpu_child_thread.h b/content/gpu/gpu_child_thread.h
index fd479a8..2f89ff2 100644
--- a/content/gpu/gpu_child_thread.h
+++ b/content/gpu/gpu_child_thread.h
@@ -32,6 +32,7 @@
 #include "media/base/android_overlay_mojo_factory.h"
 #include "mojo/public/cpp/bindings/associated_binding_set.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
+#include "services/service_manager/public/cpp/service_context_ref.h"
 #include "services/service_manager/public/interfaces/service_factory.mojom.h"
 #include "services/ui/gpu/interfaces/gpu_main.mojom.h"
 #include "ui/gfx/native_widget_types.h"
@@ -106,6 +107,8 @@
 
 #if defined(OS_ANDROID)
   static std::unique_ptr<media::AndroidOverlay> CreateAndroidOverlay(
+      scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+      std::unique_ptr<service_manager::ServiceContextRef> context_ref,
       const base::UnguessableToken& routing_token,
       media::AndroidOverlayConfig);
 #endif
diff --git a/content/gpu/gpu_service_factory.cc b/content/gpu/gpu_service_factory.cc
index b2a7ac12..eaafbda 100644
--- a/content/gpu/gpu_service_factory.cc
+++ b/content/gpu/gpu_service_factory.cc
@@ -18,10 +18,12 @@
 namespace content {
 
 GpuServiceFactory::GpuServiceFactory(
-    base::WeakPtr<media::MediaGpuChannelManager> media_gpu_channel_manager) {
+    base::WeakPtr<media::MediaGpuChannelManager> media_gpu_channel_manager,
+    media::AndroidOverlayMojoFactoryCB android_overlay_factory_cb) {
 #if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
   task_runner_ = base::ThreadTaskRunnerHandle::Get();
   media_gpu_channel_manager_ = std::move(media_gpu_channel_manager);
+  android_overlay_factory_cb_ = std::move(android_overlay_factory_cb);
 #endif
 }
 
@@ -30,8 +32,9 @@
 void GpuServiceFactory::RegisterServices(ServiceMap* services) {
 #if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
   service_manager::EmbeddedServiceInfo info;
-  info.factory = base::Bind(&media::CreateGpuMediaService, task_runner_,
-                            media_gpu_channel_manager_);
+  info.factory =
+      base::Bind(&media::CreateGpuMediaService, task_runner_,
+                 media_gpu_channel_manager_, android_overlay_factory_cb_);
   info.use_own_thread = true;
   services->insert(std::make_pair("media", info));
 #endif
diff --git a/content/gpu/gpu_service_factory.h b/content/gpu/gpu_service_factory.h
index 7009859..3d8411d 100644
--- a/content/gpu/gpu_service_factory.h
+++ b/content/gpu/gpu_service_factory.h
@@ -10,6 +10,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/single_thread_task_runner.h"
 #include "content/child/service_factory.h"
+#include "media/base/android_overlay_mojo_factory.h"
 #include "media/mojo/features.h"
 
 namespace media {
@@ -21,8 +22,9 @@
 // Customization of ServiceFactory for the GPU process.
 class GpuServiceFactory : public ServiceFactory {
  public:
-  explicit GpuServiceFactory(
-      base::WeakPtr<media::MediaGpuChannelManager> media_gpu_channel_manager);
+  GpuServiceFactory(
+      base::WeakPtr<media::MediaGpuChannelManager> media_gpu_channel_manager,
+      media::AndroidOverlayMojoFactoryCB android_overlay_factory_cb);
   ~GpuServiceFactory() override;
 
   // ServiceFactory overrides:
@@ -36,6 +38,7 @@
   // implementation doesn't care.
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
   base::WeakPtr<media::MediaGpuChannelManager> media_gpu_channel_manager_;
+  media::AndroidOverlayMojoFactoryCB android_overlay_factory_cb_;
 #endif
 
   DISALLOW_COPY_AND_ASSIGN(GpuServiceFactory);
diff --git a/content/network/url_loader_impl.cc b/content/network/url_loader_impl.cc
index b2c3c4c..f83b780 100644
--- a/content/network/url_loader_impl.cc
+++ b/content/network/url_loader_impl.cc
@@ -238,12 +238,12 @@
   NOTIMPLEMENTED();
 }
 
-void URLLoaderImpl::PauseCachingResponseBody() {
+void URLLoaderImpl::PauseReadingBodyFromNet() {
   // TODO(yzshen): add implementation.
   NOTIMPLEMENTED();
 }
 
-void URLLoaderImpl::ResumeCachingResponseBody() {
+void URLLoaderImpl::ResumeReadingBodyFromNet() {
   // TODO(yzshen): add implementation.
   NOTIMPLEMENTED();
 }
diff --git a/content/network/url_loader_impl.h b/content/network/url_loader_impl.h
index b4153e4..22fc113 100644
--- a/content/network/url_loader_impl.h
+++ b/content/network/url_loader_impl.h
@@ -51,8 +51,8 @@
   void FollowRedirect() override;
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override;
-  void PauseCachingResponseBody() override;
-  void ResumeCachingResponseBody() override;
+  void PauseReadingBodyFromNet() override;
+  void ResumeReadingBodyFromNet() override;
 
   // net::URLRequest::Delegate methods:
   void OnReceivedRedirect(net::URLRequest* url_request,
diff --git a/content/public/android/java/src/org/chromium/content/browser/SelectionPopupController.java b/content/public/android/java/src/org/chromium/content/browser/SelectionPopupController.java
index 579a007..47dc71f 100644
--- a/content/public/android/java/src/org/chromium/content/browser/SelectionPopupController.java
+++ b/content/public/android/java/src/org/chromium/content/browser/SelectionPopupController.java
@@ -138,10 +138,6 @@
     // SelectionClient was able to classify it, otherwise null.
     private SelectionClient.Result mClassificationResult;
 
-    // This variable is set to true when showActionMode() is postponed till classification result
-    // arrives or till the selection is adjusted based on the classification result.
-    private boolean mPendingShowActionMode;
-
     // Whether a scroll is in progress.
     private boolean mScrollInProgress;
 
@@ -231,6 +227,10 @@
         return mResultCallback;
     }
 
+    public SelectionClient.Result getClassificationResult() {
+        return mClassificationResult;
+    }
+
     public SelectionClient getSelectionClient() {
         return mSelectionClient;
     }
@@ -250,10 +250,11 @@
         mAllowedMenuItems = allowedMenuItems;
     }
 
+    @VisibleForTesting
     @CalledByNative
-    private void showSelectionMenu(int left, int top, int right, int bottom, boolean isEditable,
+    public void showSelectionMenu(int left, int top, int right, int bottom, boolean isEditable,
             boolean isPasswordType, String selectionText, boolean canSelectAll,
-            boolean canRichlyEdit, boolean shouldSuggest) {
+            boolean canRichlyEdit, boolean shouldSuggest, boolean fromSelectionAdjustment) {
         mSelectionRect.set(left, top, right, bottom);
         mEditable = isEditable;
         mLastSelectedText = selectionText;
@@ -263,15 +264,17 @@
         mCanEditRichly = canRichlyEdit;
         mUnselectAllOnDismiss = true;
         if (hasSelection()) {
-            if (mSelectionClient != null
-                    && mSelectionClient.requestSelectionPopupUpdates(shouldSuggest)) {
-                // Rely on |mSelectionClient| sending a classification request and the request
-                // always calling onClassified() callback.
-                mPendingShowActionMode = true;
-            } else {
+            // From selection adjustment, show menu directly.
+            if (fromSelectionAdjustment) {
                 showActionModeOrClearOnFailure();
+                return;
             }
 
+            // Show menu if there is no updates from SelectionClient.
+            if (mSelectionClient == null
+                    || !mSelectionClient.requestSelectionPopupUpdates(shouldSuggest)) {
+                showActionModeOrClearOnFailure();
+            }
         } else {
             createAndShowPastePopup();
         }
@@ -285,8 +288,6 @@
      * <p> If the action mode cannot be created the selection is cleared.
      */
     public void showActionModeOrClearOnFailure() {
-        mPendingShowActionMode = false;
-
         if (!isActionModeSupported() || !hasSelection()) return;
 
         // Just refresh the view if action mode already exists.
@@ -404,7 +405,6 @@
      */
     @Override
     public void finishActionMode() {
-        mPendingShowActionMode = false;
         mHidden = false;
         if (mView != null) mView.removeCallbacks(mRepeatingHideRunnable);
 
@@ -996,11 +996,7 @@
 
             case SelectionEventType.SELECTION_HANDLES_MOVED:
                 mSelectionRect.set(left, top, right, bottom);
-                if (mPendingShowActionMode) {
-                    showActionModeOrClearOnFailure();
-                } else {
-                    invalidateContentRect();
-                }
+                invalidateContentRect();
                 break;
 
             case SelectionEventType.SELECTION_HANDLES_CLEARED:
@@ -1107,7 +1103,6 @@
 
         mClassificationResult = null;
 
-        assert !mPendingShowActionMode;
         assert !mHidden;
     }
 
@@ -1170,9 +1165,7 @@
         public void onClassified(SelectionClient.Result result) {
             // If the selection does not exist any more, discard |result|.
             if (!hasSelection()) {
-                assert !mHidden;
-                assert mClassificationResult == null;
-                mPendingShowActionMode = false;
+                mClassificationResult = null;
                 return;
             }
 
@@ -1183,7 +1176,6 @@
             // remove this check.
             if (result.startAdjust > 0 || result.endAdjust < 0) {
                 mClassificationResult = null;
-                mPendingShowActionMode = false;
                 showActionModeOrClearOnFailure();
                 return;
             }
@@ -1192,20 +1184,12 @@
             // mode has been dismissed.
             mClassificationResult = result;
 
-            // Do not recreate the action mode if it has been cancelled (by ActionMode.finish())
-            // and not recreated after that.
-            if (!mPendingShowActionMode && !isActionModeValid()) {
-                assert !mHidden;
-                return;
-            }
-
             // Update the selection range if needed.
             if (!(result.startAdjust == 0 && result.endAdjust == 0)) {
-                // This call causes SELECTION_HANDLES_MOVED event.
-                mWebContents.adjustSelectionByCharacterOffset(result.startAdjust, result.endAdjust);
-
-                // Remain pending until SELECTION_HANDLES_MOVED arrives.
-                if (mPendingShowActionMode) return;
+                // This call will cause showSelectionMenu again.
+                mWebContents.adjustSelectionByCharacterOffset(
+                        result.startAdjust, result.endAdjust, /* show_selection_menu = */ true);
+                return;
             }
 
             // Rely on this method to clear |mHidden| and unhide the action mode.
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/LGEmailActionModeWorkaround.java b/content/public/android/java/src/org/chromium/content/browser/input/LGEmailActionModeWorkaround.java
index 08d874cc..694c424 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/LGEmailActionModeWorkaround.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/LGEmailActionModeWorkaround.java
@@ -54,9 +54,9 @@
     private static boolean shouldAllowActionModeDestroyOnNonUiThread(Context context) {
         String appName = context.getPackageName();
         int versionCode = PackageUtils.getPackageVersion(context, appName);
-        int appTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
         if (versionCode == -1) return false;
 
+        int appTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
         if (appTargetSdkVersion < Build.VERSION_CODES.M
                 || appTargetSdkVersion > Build.VERSION_CODES.N) {
             return false;
diff --git a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
index 3bc17e2..772567a56 100644
--- a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
@@ -369,9 +369,10 @@
     }
 
     @Override
-    public void adjustSelectionByCharacterOffset(int startAdjust, int endAdjust) {
+    public void adjustSelectionByCharacterOffset(
+            int startAdjust, int endAdjust, boolean showSelectionMenu) {
         nativeAdjustSelectionByCharacterOffset(
-                mNativeWebContentsAndroid, startAdjust, endAdjust);
+                mNativeWebContentsAndroid, startAdjust, endAdjust, showSelectionMenu);
     }
 
     @Override
@@ -674,8 +675,8 @@
             boolean enableHiding, boolean enableShowing, boolean animate);
     private native void nativeScrollFocusedEditableNodeIntoView(long nativeWebContentsAndroid);
     private native void nativeSelectWordAroundCaret(long nativeWebContentsAndroid);
-    private native void nativeAdjustSelectionByCharacterOffset(
-            long nativeWebContentsAndroid, int startAdjust, int endAdjust);
+    private native void nativeAdjustSelectionByCharacterOffset(long nativeWebContentsAndroid,
+            int startAdjust, int endAdjust, boolean showSelectionMenu);
     private native String nativeGetLastCommittedURL(long nativeWebContentsAndroid);
     private native boolean nativeIsIncognito(long nativeWebContentsAndroid);
     private native void nativeResumeLoadingCreatedWebContents(long nativeWebContentsAndroid);
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java b/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
index a1915f9e..eed6d71f 100644
--- a/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
+++ b/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
@@ -239,8 +239,10 @@
      * amount moves the selection towards the end of the document.
      * @param startAdjust The amount to adjust the start of the selection.
      * @param endAdjust The amount to adjust the end of the selection.
+     * @param showSelectionMenu if true, show selection menu after adjustment.
      */
-    public void adjustSelectionByCharacterOffset(int startAdjust, int endAdjust);
+    public void adjustSelectionByCharacterOffset(
+            int startAdjust, int endAdjust, boolean showSelectionMenu);
 
     /**
      * Gets the last committed URL. It represents the current page that is
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreSelectionTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreSelectionTest.java
index 3addf25..0e07d09 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreSelectionTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreSelectionTest.java
@@ -8,6 +8,7 @@
 import android.content.ClipboardManager;
 import android.content.Context;
 import android.content.Intent;
+import android.support.test.filters.MediumTest;
 import android.support.test.filters.SmallTest;
 import android.text.TextUtils;
 
@@ -48,6 +49,7 @@
             + "<br/><input id=\"input_text\" type=\"text\" value=\"SampleInputText\" />"
             + "<br/><textarea id=\"textarea\" rows=\"2\" cols=\"20\">SampleTextArea</textarea>"
             + "<br/><input id=\"password\" type=\"password\" value=\"SamplePassword\" size=\"10\"/>"
+            + "<br/><p><span id=\"smart_selection\">1600 Amphitheatre Parkway</span></p>"
             + "<br/><p><span id=\"plain_text_1\">SamplePlainTextOne</span></p>"
             + "<br/><p><span id=\"plain_text_2\">SamplePlainTextTwo</span></p>"
             + "<br/><input id=\"disabled_text\" type=\"text\" disabled value=\"Sample Text\" />"
@@ -56,6 +58,40 @@
     private ContentViewCore mContentViewCore;
     private SelectionPopupController mSelectionPopupController;
 
+    private static class TestSelectionClient implements SelectionClient {
+        private SelectionClient.Result mResult;
+        private SelectionClient.ResultCallback mResultCallback;
+
+        @Override
+        public void onSelectionChanged(String selection) {}
+
+        @Override
+        public void onSelectionEvent(int eventType, float posXPix, float poxYPix) {}
+
+        @Override
+        public void showUnhandledTapUIIfNeeded(int x, int y) {}
+
+        @Override
+        public void selectWordAroundCaretAck(boolean didSelect, int startAdjust, int endAdjust) {}
+
+        @Override
+        public boolean requestSelectionPopupUpdates(boolean shouldSuggest) {
+            ThreadUtils.postOnUiThread(() -> mResultCallback.onClassified(mResult));
+            return true;
+        }
+
+        @Override
+        public void cancelAllRequests() {}
+
+        public void setResult(SelectionClient.Result result) {
+            mResult = result;
+        }
+
+        public void setResultCallback(SelectionClient.ResultCallback callback) {
+            mResultCallback = callback;
+        }
+    }
+
     @Before
     public void setUp() throws Exception {
         mActivityTestRule.launchContentShellWithUrl(DATA_URL);
@@ -292,6 +328,30 @@
         Assert.assertFalse(mSelectionPopupController.canPasteAsPlainText());
     }
 
+    @Test
+    @MediumTest
+    @Feature({"TextInput", "SmartSelection"})
+    public void testSmartSelectionNormalFlow() throws Throwable {
+        SelectionClient.Result result = new SelectionClient.Result();
+        result.startAdjust = -5;
+        result.endAdjust = 8;
+        result.label = "Maps";
+
+        TestSelectionClient client = new TestSelectionClient();
+        client.setResult(result);
+        client.setResultCallback(mSelectionPopupController.getResultCallback());
+
+        mSelectionPopupController.setSelectionClient(client);
+
+        DOMUtils.longPressNode(mContentViewCore, "smart_selection");
+        waitForSelectActionBarVisible(true);
+
+        SelectionClient.Result returnResult = mSelectionPopupController.getClassificationResult();
+        Assert.assertEquals(-5, returnResult.startAdjust);
+        Assert.assertEquals(8, returnResult.endAdjust);
+        Assert.assertEquals("Maps", returnResult.label);
+    }
+
     /*
     @SmallTest
     @Feature({"TextInput"})
diff --git a/content/public/android/junit/src/org/chromium/content/browser/SelectionPopupControllerTest.java b/content/public/android/junit/src/org/chromium/content/browser/SelectionPopupControllerTest.java
index 10647ae..ca569e2 100644
--- a/content/public/android/junit/src/org/chromium/content/browser/SelectionPopupControllerTest.java
+++ b/content/public/android/junit/src/org/chromium/content/browser/SelectionPopupControllerTest.java
@@ -4,17 +4,29 @@
 
 package org.chromium.content.browser;
 
-import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isA;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.content.pm.PackageManager;
+import android.view.ActionMode;
 import android.view.View;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.InOrder;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowLog;
 
 import org.chromium.base.test.util.Feature;
 import org.chromium.content_public.browser.WebContents;
@@ -27,14 +39,24 @@
 @RunWith(LocalRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
 public class SelectionPopupControllerTest {
-    SelectionPopupController mController;
-    Context mContext;
-    WindowAndroid mWindowAndroid;
-    WebContents mWebContents;
-    View mView;
-    RenderCoordinates mRenderCoordinates;
+    private SelectionPopupController mController;
+    private Context mContext;
+    private WindowAndroid mWindowAndroid;
+    private WebContents mWebContents;
+    private View mView;
+    private RenderCoordinates mRenderCoordinates;
+    private ActionMode mActionMode;
+    private PackageManager mPackageManager;
 
-    class MySelectionClient implements SelectionClient {
+    private static final String MOUNTAIN_FULL = "585 Franklin Street, Mountain View, CA 94041";
+    private static final String MOUNTAIN = "Mountain";
+    private static final String AMPHITHEATRE_FULL = "1600 Amphitheatre Parkway";
+    private static final String AMPHITHEATRE = "Amphitheatre";
+
+    private class TestSelectionClient implements SelectionClient {
+        private SelectionClient.Result mResult;
+        private SelectionClient.ResultCallback mResultCallback;
+
         @Override
         public void onSelectionChanged(String selection) {}
 
@@ -49,31 +71,231 @@
 
         @Override
         public boolean requestSelectionPopupUpdates(boolean shouldSuggest) {
-            return false;
+            mResultCallback.onClassified(mResult);
+            return true;
         }
 
         @Override
         public void cancelAllRequests() {}
+
+        public void setResult(SelectionClient.Result result) {
+            mResult = result;
+        }
+
+        public void setResultCallback(SelectionClient.ResultCallback callback) {
+            mResultCallback = callback;
+        }
+    }
+
+    class SelectionClientOnlyReturnTrue extends TestSelectionClient {
+        @Override
+        public boolean requestSelectionPopupUpdates(boolean shouldSuggest) {
+            return true;
+        }
     }
 
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
+        ShadowLog.stream = System.out;
 
         mContext = Mockito.mock(Context.class);
         mWindowAndroid = Mockito.mock(WindowAndroid.class);
         mWebContents = Mockito.mock(WebContents.class);
         mView = Mockito.mock(View.class);
         mRenderCoordinates = Mockito.mock(RenderCoordinates.class);
+        mActionMode = Mockito.mock(ActionMode.class);
+        mPackageManager = Mockito.mock(PackageManager.class);
+
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
 
         mController = SelectionPopupController.createForTesting(
                 mContext, mWindowAndroid, mWebContents, mView, mRenderCoordinates);
     }
 
     @Test
-    @Feature({"SmartSelection"})
+    @Feature({"TextInput", "SmartSelection"})
     public void testSmartSelectionAdjustSelectionRange() {
-        assertNotNull(mController);
-        MySelectionClient client = new MySelectionClient();
+        InOrder order = inOrder(mWebContents, mView);
+        SelectionClient.Result result = resultForAmphitheatre();
+
+        // Setup SelectionClient for SelectionPopupController.
+        TestSelectionClient client = new TestSelectionClient();
+        client.setResult(result);
+        client.setResultCallback(mController.getResultCallback());
+        mController.setSelectionClient(client);
+
+        // Long press triggered showSelectionMenu() call.
+        mController.showSelectionMenu(0, 0, 0, 0, /* isEditable = */ true,
+                /* isPasswordType = */ false, AMPHITHEATRE, /* canSelectAll = */ true,
+                /* canRichlyEdit = */ true, /* shouldSuggest = */ true,
+                /* fromSelectionAdjustment = */ false);
+
+        // adjustSelectionByCharacterOffset() should be called.
+        order.verify(mWebContents)
+                .adjustSelectionByCharacterOffset(result.startAdjust, result.endAdjust, true);
+        assertFalse(mController.isActionModeValid());
+
+        when(mView.startActionMode(any(FloatingActionModeCallback.class), anyInt()))
+                .thenReturn(mActionMode);
+
+        // Call showSelectionMenu again, which is adjustSelectionByCharacterOffset triggered.
+        mController.showSelectionMenu(0, 0, 0, 0, /* isEditable = */ true,
+                /* isPasswordType = */ false, AMPHITHEATRE_FULL,
+                /* canSelectAll = */ true,
+                /* canRichlyEdit = */ true, /* shouldSuggest = */ true,
+                /* fromSelectionAdjustment = */ true);
+
+        order.verify(mView).startActionMode(
+                isA(FloatingActionModeCallback.class), eq(ActionMode.TYPE_FLOATING));
+
+        SelectionClient.Result returnResult = mController.getClassificationResult();
+        assertEquals(-5, returnResult.startAdjust);
+        assertEquals(8, returnResult.endAdjust);
+        assertEquals("Maps", returnResult.label);
+
+        assertTrue(mController.isActionModeValid());
+    }
+
+    @Test
+    @Feature({"TextInput", "SmartSelection"})
+    public void testSmartSelectionAnotherLongPressAfterAdjustment() {
+        InOrder order = inOrder(mWebContents, mView);
+        SelectionClient.Result result = resultForAmphitheatre();
+        SelectionClient.Result newResult = resultForMountain();
+
+        // Set SelectionClient for SelectionPopupController.
+        TestSelectionClient client = new TestSelectionClient();
+        client.setResult(result);
+        client.setResultCallback(mController.getResultCallback());
+        mController.setSelectionClient(client);
+
+        // Long press triggered showSelectionMenu() call.
+        mController.showSelectionMenu(0, 0, 0, 0, /* isEditable = */ true,
+                /* isPasswordType = */ false, AMPHITHEATRE, /* canSelectAll = */ true,
+                /* canRichlyEdit = */ true, /* shouldSuggest = */ true,
+                /* fromSelectionAdjustment = */ false);
+
+        // adjustSelectionByCharacterOffset() should be called.
+        order.verify(mWebContents)
+                .adjustSelectionByCharacterOffset(result.startAdjust, result.endAdjust, true);
+        assertFalse(mController.isActionModeValid());
+
+        // Another long press triggered showSelectionMenu() call.
+        client.setResult(newResult);
+        mController.showSelectionMenu(0, 0, 0, 0, /* isEditable = */ true,
+                /* isPasswordType = */ false, MOUNTAIN, /* canSelectAll = */ true,
+                /* canRichlyEdit = */ true, /* shouldSuggest = */ true,
+                /* fromSelectionAdjustment = */ false);
+        order.verify(mWebContents)
+                .adjustSelectionByCharacterOffset(newResult.startAdjust, newResult.endAdjust, true);
+        assertFalse(mController.isActionModeValid());
+
+        when(mView.startActionMode(any(FloatingActionModeCallback.class), anyInt()))
+                .thenReturn(mActionMode);
+
+        // First adjustSelectionByCharacterOffset() triggered.
+        mController.showSelectionMenu(0, 0, 0, 0, /* isEditable = */ true,
+                /* isPasswordType = */ false, AMPHITHEATRE_FULL,
+                /* canSelectAll = */ true,
+                /* canRichlyEdit = */ true, /* shouldSuggest = */ true,
+                /* fromSelectionAdjustment = */ true);
+
+        SelectionClient.Result returnResult = mController.getClassificationResult();
+        assertEquals(-21, returnResult.startAdjust);
+        assertEquals(15, returnResult.endAdjust);
+        assertEquals("Maps", returnResult.label);
+
+        // Second adjustSelectionByCharacterOffset() triggered.
+        mController.showSelectionMenu(0, 0, 0, 0, /* isEditable = */ true,
+                /* isPasswordType = */ false, MOUNTAIN_FULL,
+                /* canSelectAll = */ true,
+                /* canRichlyEdit = */ true, /* shouldSuggest = */ true,
+                /* fromSelectionAdjustment = */ true);
+
+        order.verify(mView).startActionMode(
+                isA(FloatingActionModeCallback.class), eq(ActionMode.TYPE_FLOATING));
+        assertTrue(mController.isActionModeValid());
+    }
+
+    @Test
+    @Feature({"TextInput", "SmartSelection"})
+    public void testSmartSelectionAnotherLongPressBeforeAdjustment() {
+        InOrder order = inOrder(mWebContents, mView);
+        SelectionClient.Result result = resultForAmphitheatre();
+        SelectionClient.Result newResult = resultForMountain();
+
+        // This client won't call SmartSelectionCallback.
+        TestSelectionClient client = new SelectionClientOnlyReturnTrue();
+        mController.setSelectionClient(client);
+
+        // Long press triggered showSelectionMenu() call.
+        mController.showSelectionMenu(0, 0, 0, 0, /* isEditable = */ true,
+                /* isPasswordType = */ false, AMPHITHEATRE, /* canSelectAll = */ true,
+                /* canRichlyEdit = */ true, /* shouldSuggest = */ true,
+                /* fromSelectionAdjustment = */ false);
+
+        // Another long press triggered showSelectionMenu() call.
+        mController.showSelectionMenu(0, 0, 0, 0, /* isEditable = */ true,
+                /* isPasswordType = */ false, MOUNTAIN, /* canSelectAll = */ true,
+                /* canRichlyEdit = */ true, /* shouldSuggest = */ true,
+                /* fromSelectionAdjustment = */ false);
+
+        // Then we done with the first classification.
+        mController.getResultCallback().onClassified(result);
+
+        // Followed by the second classifaction.
+        mController.getResultCallback().onClassified(newResult);
+
+        // adjustSelectionByCharacterOffset() should be called.
+        order.verify(mWebContents)
+                .adjustSelectionByCharacterOffset(result.startAdjust, result.endAdjust, true);
+        order.verify(mWebContents)
+                .adjustSelectionByCharacterOffset(newResult.startAdjust, newResult.endAdjust, true);
+        assertFalse(mController.isActionModeValid());
+
+        when(mView.startActionMode(any(FloatingActionModeCallback.class), anyInt()))
+                .thenReturn(mActionMode);
+
+        // First adjustSelectionByCharacterOffset() triggered.
+        mController.showSelectionMenu(0, 0, 0, 0, /* isEditable = */ true,
+                /* isPasswordType = */ false, AMPHITHEATRE_FULL,
+                /* canSelectAll = */ true,
+                /* canRichlyEdit = */ true, /* shouldSuggest = */ true,
+                /* fromSelectionAdjustment = */ true);
+
+        SelectionClient.Result returnResult = mController.getClassificationResult();
+        assertEquals(-21, returnResult.startAdjust);
+        assertEquals(15, returnResult.endAdjust);
+        assertEquals("Maps", returnResult.label);
+
+        // Second adjustSelectionByCharacterOffset() triggered.
+        mController.showSelectionMenu(0, 0, 0, 0, /* isEditable = */ true,
+                /* isPasswordType = */ false, MOUNTAIN_FULL,
+                /* canSelectAll = */ true,
+                /* canRichlyEdit = */ true, /* shouldSuggest = */ true,
+                /* fromSelectionAdjustment = */ true);
+
+        order.verify(mView).startActionMode(
+                isA(FloatingActionModeCallback.class), eq(ActionMode.TYPE_FLOATING));
+        assertTrue(mController.isActionModeValid());
+    }
+
+    // Result generated by long press "Amphitheatre" in "1600 Amphitheatre Parkway".
+    private SelectionClient.Result resultForAmphitheatre() {
+        SelectionClient.Result result = new SelectionClient.Result();
+        result.startAdjust = -5;
+        result.endAdjust = 8;
+        result.label = "Maps";
+        return result;
+    }
+
+    // Result generated by long press "Mountain" in "585 Franklin Street, Mountain View, CA 94041".
+    private SelectionClient.Result resultForMountain() {
+        SelectionClient.Result result = new SelectionClient.Result();
+        result.startAdjust = -21;
+        result.endAdjust = 15;
+        result.label = "Maps";
+        return result;
     }
 }
diff --git a/content/public/browser/background_fetch_delegate.h b/content/public/browser/background_fetch_delegate.h
index 597f5d8b9..e8f0cb2 100644
--- a/content/public/browser/background_fetch_delegate.h
+++ b/content/public/browser/background_fetch_delegate.h
@@ -32,6 +32,21 @@
 // TODO(delphick): Move this content/public/browser.
 class CONTENT_EXPORT BackgroundFetchDelegate {
  public:
+  // Failures that happen after the download has already started.
+  enum FailureReason {
+    // Used when the download has been aborted after reaching a threshold where
+    // it was decided it is not worth attempting to start again. This could be
+    // either due to a specific number of failed retry attempts or a specific
+    // number of wasted bytes due to the download restarting.
+    NETWORK,
+
+    // Used when the download was not completed before the timeout.
+    TIMEDOUT,
+
+    // Used when the failure reason is unknown.
+    UNKNOWN,
+  };
+
   // Client interface that a BackgroundFetchDelegate would use to signal the
   // progress of a background fetch.
   class Client {
@@ -55,6 +70,9 @@
         const std::string& guid,
         std::unique_ptr<BackgroundFetchResult> result) = 0;
 
+    virtual void OnDownloadFailed(const std::string& guid,
+                                  FailureReason reason) = 0;
+
     // Called by the delegate when it's shutting down to signal that the
     // delegate is no longer valid.
     virtual void OnDelegateShutdown() = 0;
diff --git a/content/public/browser/browser_thread.h b/content/public/browser/browser_thread.h
index 75dfc0d..472a713 100644
--- a/content/public/browser/browser_thread.h
+++ b/content/public/browser/browser_thread.h
@@ -67,6 +67,9 @@
     // The main thread in the browser.
     UI,
 
+    // This is the thread that interacts with the database.
+    DB,
+
     // This is the thread that interacts with the file system.
     // DEPRECATED: prefer base/task_scheduler/post_task.h for new classes
     // requiring a background file I/O task runner, i.e.:
@@ -77,11 +80,23 @@
     //         is visible but non-blocking to the user.
     FILE,
 
+    // Used for file system operations that block user interactions.
+    // Responsiveness of this thread affect users.
+    // DEPRECATED: prefer base/task_scheduler/post_task.h for new classes
+    // requiring a user-blocking file I/O task runner, i.e.:
+    //   base::CreateSequencedTaskRunnerWithTraits(
+    //       {base::MayBlock(), base::TaskPriority::USER_BLOCKING})
+    FILE_USER_BLOCKING,
+
     // Used to launch and terminate Chrome processes.
     PROCESS_LAUNCHER,
 
+    // This is the thread to handle slow HTTP cache operations.
+    CACHE,
+
     // This is the thread that processes non-blocking IO, i.e. IPC and network.
-    // Blocking IO should happen in TaskScheduler.
+    // Blocking IO should happen on other threads like DB, FILE,
+    // FILE_USER_BLOCKING and CACHE depending on the usage.
     IO,
 
     // NOTE: do not add new threads here that are only used by a small number of
@@ -271,6 +286,7 @@
   struct DeleteOnUIThread : public DeleteOnThread<UI> { };
   struct DeleteOnIOThread : public DeleteOnThread<IO> { };
   struct DeleteOnFileThread : public DeleteOnThread<FILE> { };
+  struct DeleteOnDBThread : public DeleteOnThread<DB> { };
 
   // Returns an appropriate error message for when DCHECK_CURRENTLY_ON() fails.
   static std::string GetDCheckCurrentlyOnErrorMessage(ID expected);
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index c36bb80..60f3339 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -106,6 +106,12 @@
   return false;
 }
 
+bool ContentBrowserClient::ShouldStayInParentProcessForNTP(
+    const GURL& url,
+    SiteInstance* parent_site_instance) {
+  return false;
+}
+
 bool ContentBrowserClient::IsSuitableHost(RenderProcessHost* process_host,
                                           const GURL& site_url) {
   return true;
@@ -165,7 +171,8 @@
   return empty;
 }
 
-base::FilePath ContentBrowserClient::GetLoggingFileName() {
+base::FilePath ContentBrowserClient::GetLoggingFileName(
+    const base::CommandLine& command_line) {
   return base::FilePath();
 }
 
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index a44b59f..c6a9a9b 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -280,6 +280,12 @@
       const GURL& url,
       SiteInstance* parent_site_instance);
 
+  // Temporary hack to determine whether to skip OOPIFs on the new tab page.
+  // TODO(creis): Remove when https://crbug.com/566091 is fixed.
+  virtual bool ShouldStayInParentProcessForNTP(
+      const GURL& url,
+      SiteInstance* parent_site_instance);
+
   // Returns whether a new view for a given |site_url| can be launched in a
   // given |process_host|.
   virtual bool IsSuitableHost(RenderProcessHost* process_host,
@@ -350,7 +356,8 @@
 
   // Returns the fully qualified path to the log file name, or an empty path.
   // This function is used by the sandbox to allow write access to the log.
-  virtual base::FilePath GetLoggingFileName();
+  virtual base::FilePath GetLoggingFileName(
+      const base::CommandLine& command_line);
 
   // Allow the embedder to control if an AppCache can be used for the given url.
   // This is called on the IO thread.
diff --git a/content/public/browser/desktop_media_id.cc b/content/public/browser/desktop_media_id.cc
index 6f3cd83..affd921 100644
--- a/content/public/browser/desktop_media_id.cc
+++ b/content/public/browser/desktop_media_id.cc
@@ -80,12 +80,11 @@
 #if defined(USE_AURA)
 
 // static
-DesktopMediaID DesktopMediaID::RegisterAuraWindow(
-    DesktopMediaID::Source source_type,
-    aura::Window* window) {
-  DCHECK(source_type == SOURCE_SCREEN || source_type == SOURCE_WINDOW);
+DesktopMediaID DesktopMediaID::RegisterAuraWindow(DesktopMediaID::Type type,
+                                                  aura::Window* window) {
+  DCHECK(type == TYPE_SCREEN || type == TYPE_WINDOW);
   DCHECK(window);
-  DesktopMediaID media_id(source_type, kNullId);
+  DesktopMediaID media_id(type, kNullId);
   media_id.aura_id = AuraWindowRegistry::GetInstance()->RegisterWindow(window);
   return media_id;
 }
@@ -99,38 +98,28 @@
 
 bool DesktopMediaID::operator<(const DesktopMediaID& other) const {
 #if defined(USE_AURA)
-  return std::tie(source_type, id, aura_id, web_contents_id, capture_type) <
-         std::tie(other.source_type, other.id, other.aura_id,
-                  other.web_contents_id, other.capture_type);
+  return std::tie(type, id, aura_id, web_contents_id, audio_share) <
+         std::tie(other.type, other.id, other.aura_id, other.web_contents_id,
+                  other.audio_share);
 #else
-  return std::tie(source_type, id, web_contents_id, capture_type) <
-         std::tie(other.source_type, other.id, other.web_contents_id,
-                  other.capture_type);
+  return std::tie(type, id, web_contents_id, audio_share) <
+         std::tie(other.type, other.id, other.web_contents_id,
+                  other.audio_share);
 #endif
 }
 
 bool DesktopMediaID::operator==(const DesktopMediaID& other) const {
 #if defined(USE_AURA)
-  return source_type == other.source_type && id == other.id &&
-         aura_id == other.aura_id && web_contents_id == other.web_contents_id &&
-         capture_type == other.capture_type;
-#else
-  return source_type == other.source_type && id == other.id &&
+  return type == other.type && id == other.id && aura_id == other.aura_id &&
          web_contents_id == other.web_contents_id &&
-         capture_type == other.capture_type;
+         audio_share == other.audio_share;
+#else
+  return type == other.type && id == other.id &&
+         web_contents_id == other.web_contents_id &&
+         audio_share == other.audio_share;
 #endif
 }
 
-void DesktopMediaID::set_video_capture(bool capture) {
-  capture_type =
-      (capture_type & ~CAPTURE_VIDEO) | (capture ? CAPTURE_VIDEO : 0);
-}
-
-void DesktopMediaID::set_audio_capture(bool capture) {
-  capture_type =
-      (capture_type & ~CAPTURE_AUDIO) | (capture ? CAPTURE_AUDIO : 0);
-}
-
 // static
 // Input string should in format:
 // for WebContents:
@@ -142,7 +131,7 @@
   // For WebContents type.
   WebContentsMediaCaptureId web_id;
   if (WebContentsMediaCaptureId::Parse(str, &web_id))
-    return DesktopMediaID(SOURCE_WEB_CONTENTS, 0, web_id);
+    return DesktopMediaID(TYPE_WEB_CONTENTS, 0, web_id);
 
   // For screen and window types.
   std::vector<std::string> parts = base::SplitString(
@@ -156,11 +145,11 @@
     return DesktopMediaID();
 #endif
 
-  Source source_type = SOURCE_NONE;
+  Type type = TYPE_NONE;
   if (parts[0] == kScreenPrefix) {
-    source_type = SOURCE_SCREEN;
+    type = TYPE_SCREEN;
   } else if (parts[0] == kWindowPrefix) {
-    source_type = SOURCE_WINDOW;
+    type = TYPE_WINDOW;
   } else {
     return DesktopMediaID();
   }
@@ -169,7 +158,7 @@
   if (!base::StringToInt64(parts[1], &id))
     return DesktopMediaID();
 
-  DesktopMediaID media_id(source_type, id);
+  DesktopMediaID media_id(type, id);
 
 #if defined(USE_AURA)
   int64_t aura_id;
@@ -183,17 +172,17 @@
 
 std::string DesktopMediaID::ToString() const {
   std::string prefix;
-  switch (source_type) {
-    case SOURCE_NONE:
+  switch (type) {
+    case TYPE_NONE:
       NOTREACHED();
       return std::string();
-    case SOURCE_SCREEN:
+    case TYPE_SCREEN:
       prefix = kScreenPrefix;
       break;
-    case SOURCE_WINDOW:
+    case TYPE_WINDOW:
       prefix = kWindowPrefix;
       break;
-    case SOURCE_WEB_CONTENTS:
+    case TYPE_WEB_CONTENTS:
       return web_contents_id.ToString();
       break;
   }
diff --git a/content/public/browser/desktop_media_id.h b/content/public/browser/desktop_media_id.h
index 6a47243..7b6cd1f 100644
--- a/content/public/browser/desktop_media_id.h
+++ b/content/public/browser/desktop_media_id.h
@@ -23,13 +23,7 @@
 // stored in MediaStreamRequest::requested_video_device_id.
 struct CONTENT_EXPORT DesktopMediaID {
  public:
-  enum Source {
-    SOURCE_NONE,
-    SOURCE_SCREEN,
-    SOURCE_WINDOW,
-    SOURCE_WEB_CONTENTS
-  };
-  enum Capture { CAPTURE_VIDEO = 1, CAPTURE_AUDIO = 2 };
+  enum Type { TYPE_NONE, TYPE_SCREEN, TYPE_WINDOW, TYPE_WEB_CONTENTS };
 
   typedef intptr_t Id;
 
@@ -38,8 +32,7 @@
 
 #if defined(USE_AURA)
   // Assigns integer identifier to the |window| and returns its DesktopMediaID.
-  static DesktopMediaID RegisterAuraWindow(Source source_type,
-                                           aura::Window* window);
+  static DesktopMediaID RegisterAuraWindow(Type type, aura::Window* window);
 
   // Returns the Window that was previously registered using
   // RegisterAuraWindow(), else nullptr.
@@ -48,30 +41,23 @@
 
   DesktopMediaID() = default;
 
-  DesktopMediaID(Source source_type, Id id)
-      : source_type(source_type), id(id) {}
+  DesktopMediaID(Type type, Id id) : type(type), id(id) {}
 
-  DesktopMediaID(Source source_type,
-                 Id id,
-                 WebContentsMediaCaptureId web_contents_id)
-      : source_type(source_type), id(id), web_contents_id(web_contents_id) {}
+  DesktopMediaID(Type type, Id id, WebContentsMediaCaptureId web_contents_id)
+      : type(type), id(id), web_contents_id(web_contents_id) {}
 
-  DesktopMediaID(Source source_type, Id id, uint32_t capture_type)
-      : source_type(source_type), id(id), capture_type(capture_type) {}
+  DesktopMediaID(Type type, Id id, bool audio_share)
+      : type(type), id(id), audio_share(audio_share) {}
 
   // Operators so that DesktopMediaID can be used with STL containers.
   bool operator<(const DesktopMediaID& other) const;
   bool operator==(const DesktopMediaID& other) const;
 
-  bool is_null() const { return source_type == SOURCE_NONE; }
-  void set_video_capture(bool capture);
-  void set_audio_capture(bool capture);
-  bool is_video_capture() const { return capture_type & CAPTURE_VIDEO; }
-  bool is_audio_capture() const { return capture_type & CAPTURE_AUDIO; }
-  static DesktopMediaID Parse(const std::string& str);
+  bool is_null() const { return type == TYPE_NONE; }
   std::string ToString() const;
+  static DesktopMediaID Parse(const std::string& str);
 
-  Source source_type = SOURCE_NONE;
+  Type type = TYPE_NONE;
 
   // The IDs referring to the target native screen or window.  |id| will be
   // non-null if and only if it refers to a native screen/window.  |aura_id|
@@ -84,8 +70,8 @@
   Id aura_id = kNullId;
 #endif
 
-  // This bitmask of Capture values records the type of media captured.
-  uint32_t capture_type = CAPTURE_VIDEO;
+  // This records whether the desktop share has sound or not.
+  bool audio_share = false;
 
   // This id contains information for WebContents capture.
   WebContentsMediaCaptureId web_contents_id;
diff --git a/content/public/browser/download_url_parameters.cc b/content/public/browser/download_url_parameters.cc
index b5f9466..39665ac 100644
--- a/content/public/browser/download_url_parameters.cc
+++ b/content/public/browser/download_url_parameters.cc
@@ -45,6 +45,7 @@
       url_request_context_getter_(url_request_context_getter),
       url_(url),
       do_not_prompt_for_login_(false),
+      fetch_error_body_(false),
       transient_(false),
       traffic_annotation_(traffic_annotation) {}
 
diff --git a/content/public/browser/download_url_parameters.h b/content/public/browser/download_url_parameters.h
index d52fa49..ab8bb8783 100644
--- a/content/public/browser/download_url_parameters.h
+++ b/content/public/browser/download_url_parameters.h
@@ -209,6 +209,12 @@
     do_not_prompt_for_login_ = do_not_prompt;
   }
 
+  // Sets whether to download the response body even if the server returns
+  // non-successful HTTP response code, like "HTTP NOT FOUND".
+  void set_fetch_error_body(bool fetch_error_body) {
+    fetch_error_body_ = fetch_error_body;
+  }
+
   // Sets whether the download is to be treated as transient. A transient
   // download is short-lived and is not shown in the UI.
   void set_transient(bool transient) { transient_ = transient; }
@@ -270,6 +276,7 @@
   bool prompt() const { return save_info_.prompt_for_save_location; }
   const GURL& url() const { return url_; }
   bool do_not_prompt_for_login() const { return do_not_prompt_for_login_; }
+  bool fetch_error_body() const { return fetch_error_body_; }
   bool is_transient() const { return transient_; }
   std::string guid() const { return guid_; }
 
@@ -307,6 +314,7 @@
   DownloadSaveInfo save_info_;
   GURL url_;
   bool do_not_prompt_for_login_;
+  bool fetch_error_body_;
   bool transient_;
   std::string guid_;
   std::unique_ptr<storage::BlobDataHandle> blob_data_handle_;
diff --git a/content/public/browser/utility_process_host.h b/content/public/browser/utility_process_host.h
index a49c8acd..489f267 100644
--- a/content/public/browser/utility_process_host.h
+++ b/content/public/browser/utility_process_host.h
@@ -23,6 +23,7 @@
 }
 
 namespace content {
+class BrowserMessageFilter;
 class UtilityProcessHostClient;
 struct ChildProcessData;
 
@@ -82,6 +83,9 @@
 
   // Set the name of the process to appear in the task manager.
   virtual void SetName(const base::string16& name) = 0;
+
+  // Adds an IPC message filter.
+  virtual void AddFilter(BrowserMessageFilter* filter) = 0;
 };
 
 };  // namespace content
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index 57f5b07b..74b7cb1 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -9,6 +9,8 @@
 
 #include <memory>
 #include <set>
+#include <string>
+#include <vector>
 
 #include "base/callback_forward.h"
 #include "base/files/file_path.h"
@@ -248,7 +250,7 @@
   virtual RenderProcessHost* GetRenderProcessHost() const = 0;
 
   // Returns the main frame for the currently active view.
-  virtual RenderFrameHost* GetMainFrame() = 0;
+  virtual RenderFrameHost* GetMainFrame() const = 0;
 
   // Returns the focused frame for the currently active view.
   virtual RenderFrameHost* GetFocusedFrame() = 0;
@@ -516,7 +518,8 @@
   // beginning of the document, a positive amount moves the selection towards
   // the end of the document.
   virtual void AdjustSelectionByCharacterOffset(int start_adjust,
-                                                int end_adjust) = 0;
+                                                int end_adjust,
+                                                bool show_selection_menu) = 0;
 
   // Replaces the currently selected word or a word around the cursor.
   virtual void Replace(const base::string16& word) = 0;
@@ -739,8 +742,9 @@
 
   // Returns true if the WebContents is responsible for displaying a subframe
   // in a different process from its parent page.
-  // TODO: this doesn't really belong here. With site isolation, this should be
-  // removed since we can then embed iframes in different processes.
+  // TODO(lazyboy): https://crbug.com/542893: this doesn't really belong here.
+  // With site isolation, this should be removed since we can then embed iframes
+  // in different processes.
   virtual bool IsSubframe() const = 0;
 
   // Finds text on a page. |search_text| should not be empty.
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 377ea6d6..55bf6c2 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -176,7 +176,7 @@
 
 // ES6 Modules dynamic imports.
 const base::Feature kModuleScriptsDynamicImport{
-    "ModuleScriptsDynamicImport", base::FEATURE_DISABLED_BY_DEFAULT};
+    "ModuleScriptsDynamicImport", base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Resource fetch optimizations for workers. See crbug.com/443374
 const base::Feature kOffMainThreadFetch{"OffMainThreadFetch",
diff --git a/content/public/common/referrer.cc b/content/public/common/referrer.cc
index af1b7fa..6e7d055 100644
--- a/content/public/common/referrer.cc
+++ b/content/public/common/referrer.cc
@@ -86,15 +86,26 @@
 // static
 void Referrer::SetReferrerForRequest(net::URLRequest* request,
                                      const Referrer& referrer) {
-  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  std::string referrer_string;
+  net::URLRequest::ReferrerPolicy referrer_policy;
+  ComputeReferrerInfo(&referrer_string, &referrer_policy, referrer);
+  request->SetReferrer(referrer_string);
+  request->set_referrer_policy(referrer_policy);
+}
+
+// static
+void Referrer::ComputeReferrerInfo(std::string* out_referrer_string,
+                                   net::URLRequest::ReferrerPolicy* out_policy,
+                                   const Referrer& referrer) {
   if (!referrer.url.is_valid() ||
-      command_line->HasSwitch(switches::kNoReferrers)) {
-    request->SetReferrer(std::string());
+      base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kNoReferrers)) {
+    *out_referrer_string = std::string();
   } else {
-    request->SetReferrer(referrer.url.spec());
+    *out_referrer_string = referrer.url.spec();
   }
 
-  request->set_referrer_policy(ReferrerPolicyForUrlRequest(referrer));
+  *out_policy = ReferrerPolicyForUrlRequest(referrer);
 }
 
 // static
diff --git a/content/public/common/referrer.h b/content/public/common/referrer.h
index 9352725..8ed7590 100644
--- a/content/public/common/referrer.h
+++ b/content/public/common/referrer.h
@@ -30,6 +30,10 @@
   static void SetReferrerForRequest(net::URLRequest* request,
                                     const Referrer& referrer);
 
+  static void ComputeReferrerInfo(std::string* out_referrer_string,
+                                  net::URLRequest::ReferrerPolicy* out_policy,
+                                  const Referrer& referrer);
+
   static net::URLRequest::ReferrerPolicy ReferrerPolicyForUrlRequest(
       const Referrer& referrer);
 
diff --git a/content/public/common/simple_url_loader.cc b/content/public/common/simple_url_loader.cc
index 8e3b9777..1cf3c637 100644
--- a/content/public/common/simple_url_loader.cc
+++ b/content/public/common/simple_url_loader.cc
@@ -10,12 +10,18 @@
 #include <limits>
 
 #include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.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/sequence_checker.h"
+#include "base/sequenced_task_runner.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/task_scheduler/task_traits.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "content/public/common/resource_request.h"
 #include "content/public/common/resource_response.h"
 #include "content/public/common/url_loader.mojom.h"
@@ -24,6 +30,7 @@
 #include "mojo/public/cpp/system/data_pipe.h"
 #include "mojo/public/cpp/system/simple_watcher.h"
 #include "net/base/net_errors.h"
+#include "net/base/request_priority.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 
 namespace content {
@@ -64,9 +71,7 @@
   };
 
   BodyReader(Delegate* delegate, int64_t max_body_size)
-      : handle_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL),
-        delegate_(delegate),
-        max_body_size_(max_body_size) {
+      : delegate_(delegate), max_body_size_(max_body_size) {
     DCHECK_GE(max_body_size_, 0);
   }
 
@@ -80,7 +85,9 @@
   void Start(mojo::ScopedDataPipeConsumerHandle body_data_pipe) {
     DCHECK(!body_data_pipe_.is_valid());
     body_data_pipe_ = std::move(body_data_pipe);
-    handle_watcher_.Watch(
+    handle_watcher_ = std::make_unique<mojo::SimpleWatcher>(
+        FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL);
+    handle_watcher_->Watch(
         body_data_pipe_.get(),
         MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
         MOJO_WATCH_CONDITION_SATISFIED,
@@ -104,7 +111,7 @@
       MojoResult result = body_data_pipe_->BeginReadData(
           &body_data, &read_size, MOJO_READ_DATA_FLAG_NONE);
       if (result == MOJO_RESULT_SHOULD_WAIT) {
-        handle_watcher_.ArmOrNotify();
+        handle_watcher_->ArmOrNotify();
         return;
       }
 
@@ -144,12 +151,12 @@
 
   // Frees Mojo resources and prevents any more Mojo messages from arriving.
   void ClosePipe() {
-    handle_watcher_.Cancel();
+    handle_watcher_.reset();
     body_data_pipe_.reset();
   }
 
   mojo::ScopedDataPipeConsumerHandle body_data_pipe_;
-  mojo::SimpleWatcher handle_watcher_;
+  std::unique_ptr<mojo::SimpleWatcher> handle_watcher_;
 
   Delegate* const delegate_;
 
@@ -228,6 +235,285 @@
   DISALLOW_COPY_AND_ASSIGN(SaveToStringBodyHandler);
 };
 
+// BodyHandler implementation for saving the response to a file
+class SaveToFileBodyHandler : public BodyHandler {
+ public:
+  // |net_priority| is the priority from the ResourceRequest, and is used to
+  // determine the TaskPriority of the sequence used to read from the response
+  // body and write to the file.
+  SaveToFileBodyHandler(SimpleURLLoaderImpl* simple_url_loader,
+                        SimpleURLLoader::DownloadToFileCompleteCallback
+                            download_to_file_complete_callback,
+                        const base::FilePath& path,
+                        uint64_t max_body_size,
+                        net::RequestPriority request_priority)
+      : BodyHandler(simple_url_loader),
+        download_to_file_complete_callback_(
+            std::move(download_to_file_complete_callback)),
+        weak_ptr_factory_(this) {
+    // Choose the TaskPriority based on the net request priority.
+    // TODO(mmenke): Can something better be done here?
+    base::TaskPriority task_priority;
+    if (request_priority >= net::MEDIUM) {
+      task_priority = base::TaskPriority::USER_BLOCKING;
+    } else if (request_priority >= net::LOW) {
+      task_priority = base::TaskPriority::USER_VISIBLE;
+    } else {
+      task_priority = base::TaskPriority::BACKGROUND;
+    }
+
+    // Can only do this after initializing the WeakPtrFactory.
+    file_writer_ =
+        std::make_unique<FileWriter>(path, max_body_size, task_priority);
+  }
+
+  ~SaveToFileBodyHandler() override {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    if (file_writer_)
+      FileWriter::Destroy(std::move(file_writer_), base::OnceClosure());
+  }
+
+  // BodyHandler implementation:
+  void OnStartLoadingResponseBody(
+      mojo::ScopedDataPipeConsumerHandle body_data_pipe) override {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    file_writer_->StartWriting(std::move(body_data_pipe),
+                               base::BindOnce(&SaveToFileBodyHandler::OnDone,
+                                              weak_ptr_factory_.GetWeakPtr()));
+  }
+
+  void NotifyConsumerOfCompletion(bool destroy_results) override {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    DCHECK(!download_to_file_complete_callback_.is_null());
+
+    if (destroy_results) {
+      // Prevent the FileWriter from calling OnDone().
+      weak_ptr_factory_.InvalidateWeakPtrs();
+
+      // To avoid any issues if the consumer tries to re-download a file to the
+      // same location, don't invoke the callback until any partially downloaded
+      // file has been destroyed.
+      FileWriter::Destroy(
+          std::move(file_writer_),
+          base::Bind(&SaveToFileBodyHandler::InvokeCallbackAsynchronously,
+                     weak_ptr_factory_.GetWeakPtr()));
+      return;
+    }
+
+    file_writer_->ReleaseFile();
+    std::move(download_to_file_complete_callback_).Run(path_);
+  }
+
+ private:
+  // Class to read from a mojo::ScopedDataPipeConsumerHandle and write the
+  // contents to a file. Does all reading and writing on a separate file
+  // SequencedTaskRunner. All public methods except the destructor are called on
+  // BodyHandler's TaskRunner.  All private methods and the destructor are run
+  // on the file TaskRunner.
+  //
+  // Destroys the file that it's saving to on destruction, unless ReleaseFile()
+  // is called first, so on cancellation and errors, the default behavior is to
+  // clean up after itself.
+  //
+  // FileWriter is owned by the SaveToFileBodyHandler and destroyed by a task
+  // moving its unique_ptr to the |file_writer_task_runner_|. As a result, tasks
+  // posted to |file_writer_task_runner_| can always use base::Unretained. Tasks
+  // posted the other way, however, require the SaveToFileBodyHandler to use
+  // WeakPtrs, since the SaveToFileBodyHandler can be destroyed at any time.
+  class FileWriter : public BodyReader::Delegate {
+   public:
+    using OnDoneCallback = base::OnceCallback<void(net::Error error,
+                                                   int64_t total_bytes,
+                                                   const base::FilePath& path)>;
+
+    explicit FileWriter(const base::FilePath& path,
+                        int64_t max_body_size,
+                        base::TaskPriority priority)
+        : body_handler_task_runner_(base::SequencedTaskRunnerHandle::Get()),
+          file_writer_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
+              {base::MayBlock(), priority,
+               base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
+          path_(path),
+          body_reader_(std::make_unique<BodyReader>(this, max_body_size)) {
+      DCHECK(body_handler_task_runner_->RunsTasksInCurrentSequence());
+    }
+
+    // Starts reading from |body_data_pipe| and writing to the file.
+    void StartWriting(mojo::ScopedDataPipeConsumerHandle body_data_pipe,
+                      OnDoneCallback on_done_callback) {
+      DCHECK(body_handler_task_runner_->RunsTasksInCurrentSequence());
+      file_writer_task_runner_->PostTask(
+          FROM_HERE,
+          base::BindOnce(&FileWriter::StartWritingOnFileSequence,
+                         base::Unretained(this), std::move(body_data_pipe),
+                         std::move(on_done_callback)));
+    }
+
+    // Releases ownership of the downloaded file. If not called before
+    // destruction, file will automatically be destroyed in the destructor.
+    void ReleaseFile() {
+      DCHECK(body_handler_task_runner_->RunsTasksInCurrentSequence());
+      file_writer_task_runner_->PostTask(
+          FROM_HERE, base::BindOnce(&FileWriter::ReleaseFileOnFileSequence,
+                                    base::Unretained(this)));
+    }
+
+    // Destroys the FileWriter on the file TaskRunner.
+    //
+    // If |on_destroyed_closure| is non-null, it will be invoked on the caller's
+    // task runner once the FileWriter has been destroyed.
+    static void Destroy(std::unique_ptr<FileWriter> file_writer,
+                        base::OnceClosure on_destroyed_closure) {
+      DCHECK(
+          file_writer->body_handler_task_runner_->RunsTasksInCurrentSequence());
+      // Have to stash this pointer before posting a task, since |file_writer|
+      // is bound to the callback that's posted to the TaskRunner.
+      base::SequencedTaskRunner* task_runner =
+          file_writer->file_writer_task_runner_.get();
+
+      task_runner->PostTask(FROM_HERE,
+                            base::BindOnce(&FileWriter::DestroyOnFileSequence,
+                                           std::move(file_writer),
+                                           std::move(on_destroyed_closure)));
+    }
+
+    // Destructor is only public so the consumer can keep it in a unique_ptr.
+    // Class must be destroyed by using Destroy().
+    ~FileWriter() override {
+      DCHECK(file_writer_task_runner_->RunsTasksInCurrentSequence());
+      file_.Close();
+
+      if (owns_file_) {
+        DCHECK(!path_.empty());
+        base::DeleteFile(path_, false /* recursive */);
+      }
+    }
+
+   private:
+    void StartWritingOnFileSequence(
+        mojo::ScopedDataPipeConsumerHandle body_data_pipe,
+        OnDoneCallback on_done_callback) {
+      DCHECK(file_writer_task_runner_->RunsTasksInCurrentSequence());
+      DCHECK(!file_.IsValid());
+
+      // Try to create the file.
+      file_.Initialize(path_,
+                       base::File::FLAG_WRITE | base::File::FLAG_CREATE_ALWAYS);
+      if (!file_.IsValid()) {
+        body_handler_task_runner_->PostTask(
+            FROM_HERE, base::BindOnce(std::move(on_done_callback),
+                                      net::MapSystemError(
+                                          logging::GetLastSystemErrorCode()),
+                                      0, base::FilePath()));
+        return;
+      }
+
+      on_done_callback_ = std::move(on_done_callback);
+      owns_file_ = true;
+      body_reader_->Start(std::move(body_data_pipe));
+    }
+
+    // BodyReader::Delegate implementation:
+    net::Error OnDataRead(uint32_t length, const char* data) override {
+      DCHECK(file_writer_task_runner_->RunsTasksInCurrentSequence());
+      while (length > 0) {
+        int written = file_.WriteAtCurrentPos(
+            data, std::min(length, static_cast<uint32_t>(
+                                       std::numeric_limits<int>::max())));
+        if (written < 0)
+          return net::MapSystemError(logging::GetLastSystemErrorCode());
+        length -= written;
+        data += written;
+      }
+
+      return net::OK;
+    }
+
+    void OnDone(net::Error error, int64_t total_bytes) override {
+      DCHECK(file_writer_task_runner_->RunsTasksInCurrentSequence());
+      // This should only be called if the file was successfully created.
+      DCHECK(file_.IsValid());
+
+      // Close the file so that there's no ownership contention when the
+      // consumer uses it.
+      file_.Close();
+
+      body_handler_task_runner_->PostTask(
+          FROM_HERE, base::BindOnce(std::move(on_done_callback_), error,
+                                    total_bytes, path_));
+    }
+
+    // Closes the file, so it won't be deleted on destruction.
+    void ReleaseFileOnFileSequence() {
+      DCHECK(file_writer_task_runner_->RunsTasksInCurrentSequence());
+      owns_file_ = false;
+    }
+
+    static void DestroyOnFileSequence(std::unique_ptr<FileWriter> file_writer,
+                                      base::OnceClosure on_destroyed_closure) {
+      DCHECK(
+          file_writer->file_writer_task_runner_->RunsTasksInCurrentSequence());
+
+      // Need to grab this before deleting |file_writer|.
+      scoped_refptr<base::SequencedTaskRunner> body_handler_task_runner =
+          file_writer->body_handler_task_runner_;
+
+      // Need to delete |FileWriter| before posting a task to invoke the
+      // callback.
+      file_writer.reset();
+
+      if (on_destroyed_closure)
+        body_handler_task_runner->PostTask(FROM_HERE,
+                                           std::move(on_destroyed_closure));
+    }
+
+    // These are set on cosntruction and accessed on both task runners.
+    const scoped_refptr<base::SequencedTaskRunner> body_handler_task_runner_;
+    const scoped_refptr<base::SequencedTaskRunner> file_writer_task_runner_;
+
+    // After construction, all other values are only read and written on the
+    // |file_writer_task_runner_|.
+
+    base::FilePath path_;
+    // File being downloaded to. Created just before reading from the data pipe.
+    base::File file_;
+
+    OnDoneCallback on_done_callback_;
+
+    std::unique_ptr<BodyReader> body_reader_;
+
+    // If true, destroys the file in the destructor. Set to true once the file
+    // is created.
+    bool owns_file_ = false;
+
+    DISALLOW_COPY_AND_ASSIGN(FileWriter);
+  };
+
+  // Called by FileWriter::Destroy after deleting a partially downloaded file.
+  void InvokeCallbackAsynchronously() {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    std::move(download_to_file_complete_callback_).Run(base::FilePath());
+  }
+
+  void OnDone(net::Error error,
+              int64_t total_bytes,
+              const base::FilePath& path);
+
+  // Path of the file. Set in OnDone().
+  base::FilePath path_;
+
+  SimpleURLLoader::DownloadToFileCompleteCallback
+      download_to_file_complete_callback_;
+
+  std::unique_ptr<FileWriter> file_writer_;
+
+  SEQUENCE_CHECKER(sequence_checker_);
+
+  base::WeakPtrFactory<SaveToFileBodyHandler> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(SaveToFileBodyHandler);
+};
+
 class SimpleURLLoaderImpl : public SimpleURLLoader,
                             public mojom::URLLoaderClient {
  public:
@@ -245,6 +531,13 @@
       mojom::URLLoaderFactory* url_loader_factory,
       const net::NetworkTrafficAnnotationTag& annotation_tag,
       BodyAsStringCallback body_as_string_callback) override;
+  void DownloadToFile(
+      const ResourceRequest& resource_request,
+      mojom::URLLoaderFactory* url_loader_factory,
+      const net::NetworkTrafficAnnotationTag& annotation_tag,
+      DownloadToFileCompleteCallback download_to_file_complete_callback,
+      const base::FilePath& file_path,
+      int64_t max_body_size) override;
   void SetAllowPartialResults(bool allow_partial_results) override;
   void SetAllowHttpErrorResults(bool allow_http_error_results) override;
   int NetError() const override;
@@ -352,6 +645,13 @@
   std::move(body_as_string_callback_).Run(std::move(body_));
 }
 
+void SaveToFileBodyHandler::OnDone(net::Error error,
+                                   int64_t total_bytes,
+                                   const base::FilePath& path) {
+  path_ = path;
+  simple_url_loader()->OnBodyHandlerDone(error, total_bytes);
+}
+
 SimpleURLLoaderImpl::SimpleURLLoaderImpl() : client_binding_(this) {
   // Allow creation and use on different threads.
   DETACH_FROM_SEQUENCE(sequence_checker_);
@@ -384,6 +684,19 @@
   StartInternal(resource_request, url_loader_factory, annotation_tag);
 }
 
+void SimpleURLLoaderImpl::DownloadToFile(
+    const ResourceRequest& resource_request,
+    mojom::URLLoaderFactory* url_loader_factory,
+    const net::NetworkTrafficAnnotationTag& annotation_tag,
+    DownloadToFileCompleteCallback download_to_file_complete_callback,
+    const base::FilePath& file_path,
+    int64_t max_body_size) {
+  body_handler_ = std::make_unique<SaveToFileBodyHandler>(
+      this, std::move(download_to_file_complete_callback), file_path,
+      max_body_size, resource_request.priority);
+  StartInternal(resource_request, url_loader_factory, annotation_tag);
+}
+
 void SimpleURLLoaderImpl::SetAllowPartialResults(bool allow_partial_results) {
   // Simplest way to check if a request has not yet been started.
   DCHECK(!body_handler_);
diff --git a/content/public/common/simple_url_loader.h b/content/public/common/simple_url_loader.h
index b68b34b..7cd6b74 100644
--- a/content/public/common/simple_url_loader.h
+++ b/content/public/common/simple_url_loader.h
@@ -7,12 +7,17 @@
 
 #include <stdint.h>
 
+#include <limits>
 #include <memory>
 #include <string>
 
 #include "base/callback_forward.h"
 #include "content/common/content_export.h"
 
+namespace base {
+class FilePath;
+}
+
 namespace net {
 struct NetworkTrafficAnnotationTag;
 }  // namespace net
@@ -53,6 +58,11 @@
   using BodyAsStringCallback =
       base::OnceCallback<void(std::unique_ptr<std::string> response_body)>;
 
+  // Callback used when download the response body to a file. On failure, |path|
+  // will be empty.
+  using DownloadToFileCompleteCallback =
+      base::OnceCallback<void(const base::FilePath& path)>;
+
   static std::unique_ptr<SimpleURLLoader> Create();
 
   virtual ~SimpleURLLoader();
@@ -65,7 +75,9 @@
   // or consume the data as it is received.
   //
   // Whether the request succeeds or fails, or the body exceeds |max_body_size|,
-  // |body_as_string_callback| will be invoked on completion.
+  // |body_as_string_callback| will be invoked on completion. Deleting the
+  // SimpleURLLoader before the callback is invoked will return in cancelling
+  // the request, and the callback will not be called.
   virtual void DownloadToString(
       const ResourceRequest& resource_request,
       mojom::URLLoaderFactory* url_loader_factory,
@@ -75,13 +87,36 @@
 
   // Same as DownloadToString, but downloads to a buffer of unbounded size,
   // potentially causing a crash if the amount of addressable memory is
-  // exceeded. It's recommended consumers use DownloadToString instead.
+  // exceeded. It's recommended consumers use one of the other download methods
+  // instead (DownloadToString if the body is expected to be of reasonable
+  // length, or DownloadToFile otherwise).
   virtual void DownloadToStringOfUnboundedSizeUntilCrashAndDie(
       const ResourceRequest& resource_request,
       mojom::URLLoaderFactory* url_loader_factory,
       const net::NetworkTrafficAnnotationTag& annotation_tag,
       BodyAsStringCallback body_as_string_callback) = 0;
 
+  // SimpleURLLoader will download the entire response to a file at the
+  // specified path. File I/O will happen on another sequence, so it's safe to
+  // use this on any sequence.
+  //
+  // If there's a file, network, or http error, or the max limit
+  // is exceeded, the file will be automatically destroyed before the callback
+  // is invoked and en empty path passed to the callback, unless
+  // SetAllowPartialResults() and/or SetAllowHttpErrorResults() were used to
+  // indicate partial results are allowed.
+  //
+  // If the SimpleURLLoader is destroyed before it has invoked the callback, the
+  // downloaded file will be deleted asynchronously and the callback will not be
+  // invoked, regardless of other settings.
+  virtual void DownloadToFile(
+      const ResourceRequest& resource_request,
+      mojom::URLLoaderFactory* url_loader_factory,
+      const net::NetworkTrafficAnnotationTag& annotation_tag,
+      DownloadToFileCompleteCallback download_to_file_complete_callback,
+      const base::FilePath& file_path,
+      int64_t max_body_size = std::numeric_limits<int64_t>::max()) = 0;
+
   // Sets whether partially received results are allowed. Defaults to false.
   // When true, if an error is received after reading the body starts or the max
   // allowed body size exceeded, the partial response body that was received
diff --git a/content/public/common/simple_url_loader_unittest.cc b/content/public/common/simple_url_loader_unittest.cc
index c095f48..c1a12a5 100644
--- a/content/public/common/simple_url_loader_unittest.cc
+++ b/content/public/common/simple_url_loader_unittest.cc
@@ -9,6 +9,9 @@
 #include <string>
 
 #include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
 #include "base/format_macros.h"
 #include "base/logging.h"
 #include "base/macros.h"
@@ -16,6 +19,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/optional.h"
 #include "base/run_loop.h"
+#include "base/sequence_checker.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/scoped_task_environment.h"
@@ -57,21 +61,83 @@
 // The body of the truncated response (After truncation).
 const char kTruncatedBody[] = "Truncated Body";
 
-// Class to make it easier to start a SimpleURLLoader and wait for it to
-// complete.
-class WaitForStringHelper {
+// Class to make it easier to start a SimpleURLLoader, wait for it to complete,
+// and check the result.
+class SimpleLoaderTestHelper {
  public:
-  WaitForStringHelper() : simple_url_loader_(SimpleURLLoader::Create()) {}
+  // What the response should be downloaded to.
+  enum class DownloadType { TO_STRING, TO_FILE };
 
-  ~WaitForStringHelper() {}
+  explicit SimpleLoaderTestHelper(DownloadType download_type)
+      : download_type_(download_type),
+        simple_url_loader_(SimpleURLLoader::Create()) {
+    // Create a desistination directory, if downloading to a file.
+    if (download_type_ == DownloadType::TO_FILE) {
+      EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
+      dest_path_ = temp_dir_.GetPath().AppendASCII("foo");
+    }
+  }
+
+  ~SimpleLoaderTestHelper() {}
+
+  // File path that will be written to.
+  const base::FilePath& dest_path() const {
+    DCHECK_EQ(DownloadType::TO_FILE, download_type_);
+    return dest_path_;
+  }
+
+  // Starts a SimpleURLLoader using the method corresponding to the
+  // DownloadType, but does not wait for it to complete. The default
+  // |max_body_size| of -1 means don't use a max body size (Use
+  // DownloadToStringOfUnboundedSizeUntilCrashAndDie for string downloads, and
+  // don't specify a size for other types of downloads).
+  void StartRequest(mojom::URLLoaderFactory* url_loader_factory,
+                    const ResourceRequest& resource_request,
+                    int64_t max_body_size = -1) {
+    EXPECT_FALSE(done_);
+    switch (download_type_) {
+      case DownloadType::TO_STRING:
+        if (max_body_size < 0) {
+          simple_url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
+              resource_request, url_loader_factory,
+              TRAFFIC_ANNOTATION_FOR_TESTS,
+              base::BindOnce(&SimpleLoaderTestHelper::DownloadedToString,
+                             base::Unretained(this)));
+        } else {
+          simple_url_loader_->DownloadToString(
+              resource_request, url_loader_factory,
+              TRAFFIC_ANNOTATION_FOR_TESTS,
+              base::BindOnce(&SimpleLoaderTestHelper::DownloadedToString,
+                             base::Unretained(this)),
+              max_body_size);
+        }
+        break;
+      case DownloadType::TO_FILE:
+        if (max_body_size < 0) {
+          simple_url_loader_->DownloadToFile(
+              resource_request, url_loader_factory,
+              TRAFFIC_ANNOTATION_FOR_TESTS,
+              base::BindOnce(&SimpleLoaderTestHelper::DownloadedToFile,
+                             base::Unretained(this)),
+              dest_path_);
+        } else {
+          simple_url_loader_->DownloadToFile(
+              resource_request, url_loader_factory,
+              TRAFFIC_ANNOTATION_FOR_TESTS,
+              base::BindOnce(&SimpleLoaderTestHelper::DownloadedToFile,
+                             base::Unretained(this)),
+              dest_path_, max_body_size);
+        }
+        break;
+    }
+  }
 
   // Runs a SimpleURLLoader using the provided ResourceRequest and waits for
   // completion.
   void RunRequest(mojom::URLLoaderFactory* url_loader_factory,
-                  const ResourceRequest& resource_request) {
-    simple_url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
-        resource_request, url_loader_factory, TRAFFIC_ANNOTATION_FOR_TESTS,
-        GetCallback());
+                  const ResourceRequest& resource_request,
+                  int64_t max_body_size = -1) {
+    StartRequest(url_loader_factory, resource_request, max_body_size);
     Wait();
   }
 
@@ -87,11 +153,8 @@
   // provided max size and waits for completion.
   void RunRequestWithBoundedSize(mojom::URLLoaderFactory* url_loader_factory,
                                  const ResourceRequest& resource_request,
-                                 size_t max_size) {
-    simple_url_loader_->DownloadToString(resource_request, url_loader_factory,
-                                         TRAFFIC_ANNOTATION_FOR_TESTS,
-                                         GetCallback(), max_size);
-    Wait();
+                                 int64_t max_body_size) {
+    RunRequest(url_loader_factory, resource_request, max_body_size);
   }
 
   // Simpler version of RunRequestWithBoundedSize that takes a URL instead.
@@ -104,24 +167,35 @@
     RunRequestWithBoundedSize(url_loader_factory, resource_request, max_size);
   }
 
-  // Callback to be invoked once the SimpleURLLoader has received the response
-  // body. Exposed so that some tests can start the SimpleURLLoader directly.
-  SimpleURLLoader::BodyAsStringCallback GetCallback() {
-    return base::BindOnce(&WaitForStringHelper::BodyReceived,
-                          base::Unretained(this));
-  }
-
   // Waits until the request is completed. Automatically called by RunRequest
   // methods, but exposed so some tests can start the SimpleURLLoader directly.
   void Wait() { run_loop_.Run(); }
 
-  // Received response body, if any.
-  const std::string* response_body() const { return response_body_.get(); }
+  // Sets whether a file should still exists on download-to-file errors.
+  // Defaults to false.
+  void set_expect_path_exists_on_error(bool expect_path_exists_on_error) {
+    EXPECT_EQ(DownloadType::TO_FILE, download_type_);
+    expect_path_exists_on_error_ = expect_path_exists_on_error;
+  }
+
+  // Received response body, if any. Returns nullptr if no body was received
+  // (Which is different from a 0-length body). For DownloadType::TO_STRING,
+  // this is just the value passed to the callback. For DownloadType::TO_FILE,
+  // it is nullptr if an empty FilePath was passed to the callback, or the
+  // contents of the file, otherwise.
+  const std::string* response_body() const {
+    EXPECT_TRUE(done_);
+    return response_body_.get();
+  }
+
+  // Returns true if the callback has been invoked.
+  bool done() const { return done_; }
 
   SimpleURLLoader* simple_url_loader() { return simple_url_loader_.get(); }
 
   // Returns the HTTP response code. Fails if there isn't one.
   int GetResponseCode() const {
+    EXPECT_TRUE(done_);
     if (!simple_url_loader_->ResponseInfo()) {
       ADD_FAILURE() << "No response info.";
       return -1;
@@ -134,17 +208,55 @@
   }
 
  private:
-  void BodyReceived(std::unique_ptr<std::string> response_body) {
+  void DownloadedToString(std::unique_ptr<std::string> response_body) {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    EXPECT_FALSE(done_);
+    EXPECT_EQ(DownloadType::TO_STRING, download_type_);
+    EXPECT_FALSE(response_body_);
+
     response_body_ = std::move(response_body);
+
+    done_ = true;
     run_loop_.Quit();
   }
 
+  void DownloadedToFile(const base::FilePath& file_path) {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    EXPECT_FALSE(done_);
+    EXPECT_EQ(DownloadType::TO_FILE, download_type_);
+    EXPECT_FALSE(response_body_);
+
+    // Make sure the destination file exists if |file_path| is non-empty, or the
+    // file is expected to exist on error.
+    EXPECT_EQ(!file_path.empty() || expect_path_exists_on_error_,
+              base::PathExists(dest_path_));
+
+    if (!file_path.empty()) {
+      EXPECT_EQ(dest_path_, file_path);
+      response_body_ = std::make_unique<std::string>();
+      EXPECT_TRUE(base::ReadFileToString(dest_path_, response_body_.get()));
+    }
+
+    done_ = true;
+    run_loop_.Quit();
+  }
+
+  DownloadType download_type_;
+  bool done_ = false;
+
+  bool expect_path_exists_on_error_ = false;
+
   std::unique_ptr<SimpleURLLoader> simple_url_loader_;
   base::RunLoop run_loop_;
 
   std::unique_ptr<std::string> response_body_;
 
-  DISALLOW_COPY_AND_ASSIGN(WaitForStringHelper);
+  base::ScopedTempDir temp_dir_;
+  base::FilePath dest_path_;
+
+  SEQUENCE_CHECKER(sequence_checker_);
+
+  DISALLOW_COPY_AND_ASSIGN(SimpleLoaderTestHelper);
 };
 
 // Request handler for the embedded test server that returns a response body
@@ -199,9 +311,10 @@
   return std::move(response);
 }
 
-class SimpleURLLoaderTest : public testing::Test {
+// Base class with shared setup logic.
+class SimpleURLLoaderTestBase {
  public:
-  SimpleURLLoaderTest()
+  SimpleURLLoaderTestBase()
       : scoped_task_environment_(
             base::test::ScopedTaskEnvironment::MainThreadType::IO),
         network_service_(NetworkService::Create()) {
@@ -222,7 +335,7 @@
     EXPECT_TRUE(test_server_.Start());
   }
 
-  ~SimpleURLLoaderTest() override {}
+  virtual ~SimpleURLLoaderTestBase() {}
 
  protected:
   base::test::ScopedTaskEnvironment scoped_task_environment_;
@@ -234,341 +347,329 @@
   net::test_server::EmbeddedTestServer test_server_;
 };
 
-TEST_F(SimpleURLLoaderTest, BasicRequest) {
+class SimpleURLLoaderTest
+    : public SimpleURLLoaderTestBase,
+      public testing::TestWithParam<SimpleLoaderTestHelper::DownloadType> {
+ public:
+  SimpleURLLoaderTest() : test_helper_(GetParam()) {}
+
+  ~SimpleURLLoaderTest() override {}
+
+  SimpleLoaderTestHelper* test_helper() { return &test_helper_; }
+
+ private:
+  SimpleLoaderTestHelper test_helper_;
+};
+
+TEST_P(SimpleURLLoaderTest, BasicRequest) {
   ResourceRequest resource_request;
   // Use a more interesting request than "/echo", just to verify more than the
   // request URL is hooked up.
   resource_request.url = test_server_.GetURL("/echoheader?foo");
   resource_request.headers.SetHeader("foo", "Expected Response");
-  WaitForStringHelper string_helper;
-  string_helper.RunRequest(url_loader_factory_.get(), resource_request);
+  test_helper()->RunRequest(url_loader_factory_.get(), resource_request);
 
-  EXPECT_EQ(net::OK, string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(200, string_helper.GetResponseCode());
-  ASSERT_TRUE(string_helper.response_body());
-  EXPECT_EQ("Expected Response", *string_helper.response_body());
+  EXPECT_EQ(net::OK, test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(200, test_helper()->GetResponseCode());
+  ASSERT_TRUE(test_helper()->response_body());
+  EXPECT_EQ("Expected Response", *test_helper()->response_body());
 }
 
 // Test that SimpleURLLoader handles data URLs, which don't have headers.
-TEST_F(SimpleURLLoaderTest, DataURL) {
+TEST_P(SimpleURLLoaderTest, DataURL) {
   ResourceRequest resource_request;
-  // Use a more interesting request than "/echo", just to verify more than the
-  // request URL is hooked up.
   resource_request.url = GURL("data:text/plain,foo");
-  WaitForStringHelper string_helper;
-  string_helper.RunRequest(url_loader_factory_.get(), resource_request);
+  test_helper()->RunRequest(url_loader_factory_.get(), resource_request);
 
-  EXPECT_EQ(net::OK, string_helper.simple_url_loader()->NetError());
-  ASSERT_TRUE(string_helper.simple_url_loader()->ResponseInfo());
-  EXPECT_FALSE(string_helper.simple_url_loader()->ResponseInfo()->headers);
-  ASSERT_TRUE(string_helper.response_body());
-  EXPECT_EQ("foo", *string_helper.response_body());
+  EXPECT_EQ(net::OK, test_helper()->simple_url_loader()->NetError());
+  ASSERT_TRUE(test_helper()->simple_url_loader()->ResponseInfo());
+  EXPECT_FALSE(test_helper()->simple_url_loader()->ResponseInfo()->headers);
+  ASSERT_TRUE(test_helper()->response_body());
+  EXPECT_EQ("foo", *test_helper()->response_body());
 }
 
 // Make sure the class works when the size of the encoded and decoded bodies are
 // different.
-TEST_F(SimpleURLLoaderTest, GzipBody) {
+TEST_P(SimpleURLLoaderTest, GzipBody) {
   ResourceRequest resource_request;
   resource_request.url = test_server_.GetURL("/gzip-body?foo");
-  WaitForStringHelper string_helper;
-  string_helper.RunRequest(url_loader_factory_.get(), resource_request);
+  test_helper()->RunRequest(url_loader_factory_.get(), resource_request);
 
-  EXPECT_EQ(net::OK, string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(200, string_helper.GetResponseCode());
-  ASSERT_TRUE(string_helper.response_body());
-  EXPECT_EQ("foo", *string_helper.response_body());
+  EXPECT_EQ(net::OK, test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(200, test_helper()->GetResponseCode());
+  ASSERT_TRUE(test_helper()->response_body());
+  EXPECT_EQ("foo", *test_helper()->response_body());
 }
 
 // Make sure redirects are followed.
-TEST_F(SimpleURLLoaderTest, Redirect) {
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURL(
+TEST_P(SimpleURLLoaderTest, Redirect) {
+  test_helper()->RunRequestForURL(
       url_loader_factory_.get(),
       test_server_.GetURL("/server-redirect?" +
                           test_server_.GetURL("/echo").spec()));
 
-  EXPECT_EQ(net::OK, string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(200, string_helper.GetResponseCode());
-  ASSERT_TRUE(string_helper.response_body());
-  EXPECT_EQ("Echo", *string_helper.response_body());
+  EXPECT_EQ(net::OK, test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(200, test_helper()->GetResponseCode());
+  ASSERT_TRUE(test_helper()->response_body());
+  EXPECT_EQ("Echo", *test_helper()->response_body());
 }
 
 // Check that no body is returned with an HTTP error response.
-TEST_F(SimpleURLLoaderTest, HttpErrorStatusCodeResponse) {
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURL(url_loader_factory_.get(),
-                                 test_server_.GetURL("/echo?status=400"));
+TEST_P(SimpleURLLoaderTest, HttpErrorStatusCodeResponse) {
+  test_helper()->RunRequestForURL(url_loader_factory_.get(),
+                                  test_server_.GetURL("/echo?status=400"));
 
-  EXPECT_EQ(net::ERR_FAILED, string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(400, string_helper.GetResponseCode());
-  EXPECT_FALSE(string_helper.response_body());
+  EXPECT_EQ(net::ERR_FAILED, test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(400, test_helper()->GetResponseCode());
+  EXPECT_FALSE(test_helper()->response_body());
 }
 
 // Check that the body is returned with an HTTP error response, when
 // SetAllowHttpErrorResults(true) is called.
-TEST_F(SimpleURLLoaderTest, HttpErrorStatusCodeResponseAllowed) {
-  WaitForStringHelper string_helper;
-  string_helper.simple_url_loader()->SetAllowHttpErrorResults(true);
-  string_helper.RunRequestForURL(url_loader_factory_.get(),
-                                 test_server_.GetURL("/echo?status=400"));
+TEST_P(SimpleURLLoaderTest, HttpErrorStatusCodeResponseAllowed) {
+  test_helper()->simple_url_loader()->SetAllowHttpErrorResults(true);
+  test_helper()->RunRequestForURL(url_loader_factory_.get(),
+                                  test_server_.GetURL("/echo?status=400"));
 
-  EXPECT_EQ(net::OK, string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(400, string_helper.GetResponseCode());
-  ASSERT_TRUE(string_helper.response_body());
-  EXPECT_EQ("Echo", *string_helper.response_body());
+  EXPECT_EQ(net::OK, test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(400, test_helper()->GetResponseCode());
+  ASSERT_TRUE(test_helper()->response_body());
+  EXPECT_EQ("Echo", *test_helper()->response_body());
 }
 
-TEST_F(SimpleURLLoaderTest, EmptyResponseBody) {
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURL(url_loader_factory_.get(),
-                                 test_server_.GetURL("/nocontent"));
+TEST_P(SimpleURLLoaderTest, EmptyResponseBody) {
+  test_helper()->RunRequestForURL(url_loader_factory_.get(),
+                                  test_server_.GetURL("/nocontent"));
 
-  EXPECT_EQ(net::OK, string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(204, string_helper.GetResponseCode());
-  ASSERT_TRUE(string_helper.response_body());
+  EXPECT_EQ(net::OK, test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(204, test_helper()->GetResponseCode());
+  ASSERT_TRUE(test_helper()->response_body());
   // A response body is sent from the NetworkService, but it's empty.
-  EXPECT_EQ("", *string_helper.response_body());
+  EXPECT_EQ("", *test_helper()->response_body());
 }
 
-TEST_F(SimpleURLLoaderTest, BigResponseBody) {
-  WaitForStringHelper string_helper;
+TEST_P(SimpleURLLoaderTest, BigResponseBody) {
   // Big response that requires multiple reads, and exceeds the maximum size
   // limit of SimpleURLLoader::DownloadToString().  That is, this test make sure
   // that DownloadToStringOfUnboundedSizeUntilCrashAndDie() can receive strings
   // longer than DownloadToString() allows.
   const uint32_t kResponseSize = 2 * 1024 * 1024;
-  string_helper.RunRequestForURL(url_loader_factory_.get(),
-                                 test_server_.GetURL(base::StringPrintf(
-                                     "/response-size?%u", kResponseSize)));
+  test_helper()->RunRequestForURL(url_loader_factory_.get(),
+                                  test_server_.GetURL(base::StringPrintf(
+                                      "/response-size?%u", kResponseSize)));
 
-  EXPECT_EQ(net::OK, string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(200, string_helper.GetResponseCode());
-  ASSERT_TRUE(string_helper.response_body());
-  EXPECT_EQ(kResponseSize, string_helper.response_body()->length());
-  EXPECT_EQ(std::string(kResponseSize, 'a'), *string_helper.response_body());
+  EXPECT_EQ(net::OK, test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(200, test_helper()->GetResponseCode());
+  ASSERT_TRUE(test_helper()->response_body());
+  EXPECT_EQ(kResponseSize, test_helper()->response_body()->length());
+  EXPECT_EQ(std::string(kResponseSize, 'a'), *test_helper()->response_body());
 }
 
-TEST_F(SimpleURLLoaderTest, ResponseBodyWithSizeMatchingLimit) {
+TEST_P(SimpleURLLoaderTest, ResponseBodyWithSizeMatchingLimit) {
   const uint32_t kResponseSize = 16;
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURLWithBoundedSize(
+  test_helper()->RunRequestForURLWithBoundedSize(
       url_loader_factory_.get(),
       test_server_.GetURL(
           base::StringPrintf("/response-size?%u", kResponseSize)),
       kResponseSize);
 
-  EXPECT_EQ(net::OK, string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(200, string_helper.GetResponseCode());
-  ASSERT_TRUE(string_helper.response_body());
-  EXPECT_EQ(kResponseSize, string_helper.response_body()->length());
-  EXPECT_EQ(std::string(kResponseSize, 'a'), *string_helper.response_body());
+  EXPECT_EQ(net::OK, test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(200, test_helper()->GetResponseCode());
+  ASSERT_TRUE(test_helper()->response_body());
+  EXPECT_EQ(kResponseSize, test_helper()->response_body()->length());
+  EXPECT_EQ(std::string(kResponseSize, 'a'), *test_helper()->response_body());
 }
 
-TEST_F(SimpleURLLoaderTest, ResponseBodyWithSizeBelowLimit) {
-  WaitForStringHelper string_helper;
+TEST_P(SimpleURLLoaderTest, ResponseBodyWithSizeBelowLimit) {
   const uint32_t kResponseSize = 16;
   const uint32_t kMaxResponseSize = kResponseSize + 1;
-  string_helper.RunRequestForURLWithBoundedSize(
+  test_helper()->RunRequestForURLWithBoundedSize(
       url_loader_factory_.get(),
       test_server_.GetURL(
           base::StringPrintf("/response-size?%u", kResponseSize)),
       kMaxResponseSize);
 
-  EXPECT_EQ(net::OK, string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(200, string_helper.GetResponseCode());
-  ASSERT_TRUE(string_helper.response_body());
-  EXPECT_EQ(kResponseSize, string_helper.response_body()->length());
-  EXPECT_EQ(std::string(kResponseSize, 'a'), *string_helper.response_body());
+  EXPECT_EQ(net::OK, test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(200, test_helper()->GetResponseCode());
+  ASSERT_TRUE(test_helper()->response_body());
+  EXPECT_EQ(kResponseSize, test_helper()->response_body()->length());
+  EXPECT_EQ(std::string(kResponseSize, 'a'), *test_helper()->response_body());
 }
 
-TEST_F(SimpleURLLoaderTest, ResponseBodyWithSizeAboveLimit) {
+TEST_P(SimpleURLLoaderTest, ResponseBodyWithSizeAboveLimit) {
   const uint32_t kResponseSize = 16;
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURLWithBoundedSize(
+  test_helper()->RunRequestForURLWithBoundedSize(
       url_loader_factory_.get(),
       test_server_.GetURL(
           base::StringPrintf("/response-size?%u", kResponseSize)),
       kResponseSize - 1);
 
   EXPECT_EQ(net::ERR_INSUFFICIENT_RESOURCES,
-            string_helper.simple_url_loader()->NetError());
-  EXPECT_FALSE(string_helper.response_body());
+            test_helper()->simple_url_loader()->NetError());
+  EXPECT_FALSE(test_helper()->response_body());
 }
 
 // Same as above, but with setting allow_partial_results to true.
-TEST_F(SimpleURLLoaderTest, ResponseBodyWithSizeAboveLimitPartialResponse) {
-  WaitForStringHelper string_helper;
+TEST_P(SimpleURLLoaderTest, ResponseBodyWithSizeAboveLimitPartialResponse) {
   const uint32_t kResponseSize = 16;
   const uint32_t kMaxResponseSize = kResponseSize - 1;
-  string_helper.simple_url_loader()->SetAllowPartialResults(true);
-  string_helper.RunRequestForURLWithBoundedSize(
+  test_helper()->simple_url_loader()->SetAllowPartialResults(true);
+  test_helper()->RunRequestForURLWithBoundedSize(
       url_loader_factory_.get(),
       test_server_.GetURL(
           base::StringPrintf("/response-size?%u", kResponseSize)),
       kMaxResponseSize);
 
   EXPECT_EQ(net::ERR_INSUFFICIENT_RESOURCES,
-            string_helper.simple_url_loader()->NetError());
-  ASSERT_TRUE(string_helper.response_body());
-  EXPECT_EQ(std::string(kMaxResponseSize, 'a'), *string_helper.response_body());
-  EXPECT_EQ(kMaxResponseSize, string_helper.response_body()->length());
+            test_helper()->simple_url_loader()->NetError());
+  ASSERT_TRUE(test_helper()->response_body());
+  EXPECT_EQ(std::string(kMaxResponseSize, 'a'),
+            *test_helper()->response_body());
+  EXPECT_EQ(kMaxResponseSize, test_helper()->response_body()->length());
 }
 
 // The next 4 tests duplicate the above 4, but with larger response sizes. This
 // means the size limit will not be exceeded on the first read.
-TEST_F(SimpleURLLoaderTest, BigResponseBodyWithSizeMatchingLimit) {
+TEST_P(SimpleURLLoaderTest, BigResponseBodyWithSizeMatchingLimit) {
   const uint32_t kResponseSize = 512 * 1024;
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURLWithBoundedSize(
+  test_helper()->RunRequestForURLWithBoundedSize(
       url_loader_factory_.get(),
       test_server_.GetURL(
           base::StringPrintf("/response-size?%u", kResponseSize)),
       kResponseSize);
 
-  EXPECT_EQ(net::OK, string_helper.simple_url_loader()->NetError());
-  ASSERT_TRUE(string_helper.response_body());
-  EXPECT_EQ(kResponseSize, string_helper.response_body()->length());
-  EXPECT_EQ(std::string(kResponseSize, 'a'), *string_helper.response_body());
+  EXPECT_EQ(net::OK, test_helper()->simple_url_loader()->NetError());
+  ASSERT_TRUE(test_helper()->response_body());
+  EXPECT_EQ(kResponseSize, test_helper()->response_body()->length());
+  EXPECT_EQ(std::string(kResponseSize, 'a'), *test_helper()->response_body());
 }
 
-TEST_F(SimpleURLLoaderTest, BigResponseBodyWithSizeBelowLimit) {
+TEST_P(SimpleURLLoaderTest, BigResponseBodyWithSizeBelowLimit) {
   const uint32_t kResponseSize = 512 * 1024;
   const uint32_t kMaxResponseSize = kResponseSize + 1;
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURLWithBoundedSize(
+  test_helper()->RunRequestForURLWithBoundedSize(
       url_loader_factory_.get(),
       test_server_.GetURL(
           base::StringPrintf("/response-size?%u", kResponseSize)),
       kMaxResponseSize);
 
-  EXPECT_EQ(net::OK, string_helper.simple_url_loader()->NetError());
-  ASSERT_TRUE(string_helper.response_body());
-  EXPECT_EQ(kResponseSize, string_helper.response_body()->length());
-  EXPECT_EQ(std::string(kResponseSize, 'a'), *string_helper.response_body());
+  EXPECT_EQ(net::OK, test_helper()->simple_url_loader()->NetError());
+  ASSERT_TRUE(test_helper()->response_body());
+  EXPECT_EQ(kResponseSize, test_helper()->response_body()->length());
+  EXPECT_EQ(std::string(kResponseSize, 'a'), *test_helper()->response_body());
 }
 
-TEST_F(SimpleURLLoaderTest, BigResponseBodyWithSizeAboveLimit) {
-  WaitForStringHelper string_helper;
+TEST_P(SimpleURLLoaderTest, BigResponseBodyWithSizeAboveLimit) {
   const uint32_t kResponseSize = 512 * 1024;
-  string_helper.RunRequestForURLWithBoundedSize(
+  test_helper()->RunRequestForURLWithBoundedSize(
       url_loader_factory_.get(),
       test_server_.GetURL(
           base::StringPrintf("/response-size?%u", kResponseSize)),
       kResponseSize - 1);
 
   EXPECT_EQ(net::ERR_INSUFFICIENT_RESOURCES,
-            string_helper.simple_url_loader()->NetError());
-  EXPECT_FALSE(string_helper.response_body());
+            test_helper()->simple_url_loader()->NetError());
+  EXPECT_FALSE(test_helper()->response_body());
 }
 
-TEST_F(SimpleURLLoaderTest, BigResponseBodyWithSizeAboveLimitPartialResponse) {
+TEST_P(SimpleURLLoaderTest, BigResponseBodyWithSizeAboveLimitPartialResponse) {
   const uint32_t kResponseSize = 512 * 1024;
   const uint32_t kMaxResponseSize = kResponseSize - 1;
-  WaitForStringHelper string_helper;
-  string_helper.simple_url_loader()->SetAllowPartialResults(true);
-  string_helper.RunRequestForURLWithBoundedSize(
+  test_helper()->simple_url_loader()->SetAllowPartialResults(true);
+  test_helper()->RunRequestForURLWithBoundedSize(
       url_loader_factory_.get(),
       test_server_.GetURL(
           base::StringPrintf("/response-size?%u", kResponseSize)),
       kMaxResponseSize);
 
   EXPECT_EQ(net::ERR_INSUFFICIENT_RESOURCES,
-            string_helper.simple_url_loader()->NetError());
-  ASSERT_TRUE(string_helper.response_body());
-  EXPECT_EQ(std::string(kMaxResponseSize, 'a'), *string_helper.response_body());
-  EXPECT_EQ(kMaxResponseSize, string_helper.response_body()->length());
+            test_helper()->simple_url_loader()->NetError());
+  ASSERT_TRUE(test_helper()->response_body());
+  EXPECT_EQ(std::string(kMaxResponseSize, 'a'),
+            *test_helper()->response_body());
+  EXPECT_EQ(kMaxResponseSize, test_helper()->response_body()->length());
 }
 
-TEST_F(SimpleURLLoaderTest, NetErrorBeforeHeaders) {
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURL(url_loader_factory_.get(),
-                                 test_server_.GetURL("/close-socket"));
+TEST_P(SimpleURLLoaderTest, NetErrorBeforeHeaders) {
+  test_helper()->RunRequestForURL(url_loader_factory_.get(),
+                                  test_server_.GetURL("/close-socket"));
 
   EXPECT_EQ(net::ERR_EMPTY_RESPONSE,
-            string_helper.simple_url_loader()->NetError());
-  EXPECT_FALSE(string_helper.simple_url_loader()->ResponseInfo());
-  EXPECT_FALSE(string_helper.response_body());
+            test_helper()->simple_url_loader()->NetError());
+  EXPECT_FALSE(test_helper()->simple_url_loader()->ResponseInfo());
+  EXPECT_FALSE(test_helper()->response_body());
 }
 
-TEST_F(SimpleURLLoaderTest, NetErrorBeforeHeadersWithPartialResults) {
-  WaitForStringHelper string_helper;
+TEST_P(SimpleURLLoaderTest, NetErrorBeforeHeadersWithPartialResults) {
   // Allow response body on error. There should still be no response body, since
   // the error is before body reading starts.
-  string_helper.simple_url_loader()->SetAllowPartialResults(true);
-  string_helper.RunRequestForURL(url_loader_factory_.get(),
-                                 test_server_.GetURL("/close-socket"));
+  test_helper()->simple_url_loader()->SetAllowPartialResults(true);
+  test_helper()->RunRequestForURL(url_loader_factory_.get(),
+                                  test_server_.GetURL("/close-socket"));
 
-  EXPECT_FALSE(string_helper.response_body());
+  EXPECT_FALSE(test_helper()->response_body());
   EXPECT_EQ(net::ERR_EMPTY_RESPONSE,
-            string_helper.simple_url_loader()->NetError());
-  EXPECT_FALSE(string_helper.simple_url_loader()->ResponseInfo());
+            test_helper()->simple_url_loader()->NetError());
+  EXPECT_FALSE(test_helper()->simple_url_loader()->ResponseInfo());
 }
 
-TEST_F(SimpleURLLoaderTest, NetErrorAfterHeaders) {
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURL(url_loader_factory_.get(),
-                                 test_server_.GetURL(kInvalidGzipPath));
+TEST_P(SimpleURLLoaderTest, NetErrorAfterHeaders) {
+  test_helper()->RunRequestForURL(url_loader_factory_.get(),
+                                  test_server_.GetURL(kInvalidGzipPath));
 
   EXPECT_EQ(net::ERR_CONTENT_DECODING_FAILED,
-            string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(200, string_helper.GetResponseCode());
-  EXPECT_FALSE(string_helper.response_body());
+            test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(200, test_helper()->GetResponseCode());
+  EXPECT_FALSE(test_helper()->response_body());
 }
 
-TEST_F(SimpleURLLoaderTest, NetErrorAfterHeadersWithPartialResults) {
-  WaitForStringHelper string_helper;
+TEST_P(SimpleURLLoaderTest, NetErrorAfterHeadersWithPartialResults) {
   // Allow response body on error. This case results in a 0-byte response body.
-  string_helper.simple_url_loader()->SetAllowPartialResults(true);
-  string_helper.RunRequestForURL(url_loader_factory_.get(),
-                                 test_server_.GetURL(kInvalidGzipPath));
+  test_helper()->simple_url_loader()->SetAllowPartialResults(true);
+  test_helper()->RunRequestForURL(url_loader_factory_.get(),
+                                  test_server_.GetURL(kInvalidGzipPath));
 
   EXPECT_EQ(net::ERR_CONTENT_DECODING_FAILED,
-            string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(200, string_helper.GetResponseCode());
-  ASSERT_TRUE(string_helper.response_body());
-  EXPECT_EQ("", *string_helper.response_body());
+            test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(200, test_helper()->GetResponseCode());
+  ASSERT_TRUE(test_helper()->response_body());
+  EXPECT_EQ("", *test_helper()->response_body());
 }
 
-TEST_F(SimpleURLLoaderTest, TruncatedBody) {
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURL(url_loader_factory_.get(),
-                                 test_server_.GetURL(kTruncatedBodyPath));
+TEST_P(SimpleURLLoaderTest, TruncatedBody) {
+  test_helper()->RunRequestForURL(url_loader_factory_.get(),
+                                  test_server_.GetURL(kTruncatedBodyPath));
 
   EXPECT_EQ(net::ERR_CONTENT_LENGTH_MISMATCH,
-            string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(200, string_helper.GetResponseCode());
-  EXPECT_FALSE(string_helper.response_body());
+            test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(200, test_helper()->GetResponseCode());
+  EXPECT_FALSE(test_helper()->response_body());
 }
 
-TEST_F(SimpleURLLoaderTest, TruncatedBodyWithPartialResults) {
-  WaitForStringHelper string_helper;
-  string_helper.simple_url_loader()->SetAllowPartialResults(true);
-  string_helper.RunRequestForURL(url_loader_factory_.get(),
-                                 test_server_.GetURL(kTruncatedBodyPath));
+TEST_P(SimpleURLLoaderTest, TruncatedBodyWithPartialResults) {
+  test_helper()->simple_url_loader()->SetAllowPartialResults(true);
+  test_helper()->RunRequestForURL(url_loader_factory_.get(),
+                                  test_server_.GetURL(kTruncatedBodyPath));
 
   EXPECT_EQ(net::ERR_CONTENT_LENGTH_MISMATCH,
-            string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(200, string_helper.GetResponseCode());
-  ASSERT_TRUE(string_helper.response_body());
-  EXPECT_EQ(kTruncatedBody, *string_helper.response_body());
+            test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(200, test_helper()->GetResponseCode());
+  ASSERT_TRUE(test_helper()->response_body());
+  EXPECT_EQ(kTruncatedBody, *test_helper()->response_body());
 }
 
 // Test case where NetworkService is destroyed before headers are received (and
 // before the request is even made, for that matter).
-TEST_F(SimpleURLLoaderTest, DestroyServiceBeforeResponseStarts) {
+TEST_P(SimpleURLLoaderTest, DestroyServiceBeforeResponseStarts) {
   ResourceRequest resource_request;
   resource_request.url = test_server_.GetURL("/hung");
-  WaitForStringHelper string_helper;
-  string_helper.simple_url_loader()
-      ->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
-          resource_request, url_loader_factory_.get(),
-          TRAFFIC_ANNOTATION_FOR_TESTS, string_helper.GetCallback());
+  test_helper()->StartRequest(url_loader_factory_.get(), resource_request);
   network_service_ = nullptr;
-  string_helper.Wait();
+  test_helper()->Wait();
 
-  EXPECT_EQ(net::ERR_FAILED, string_helper.simple_url_loader()->NetError());
-  EXPECT_FALSE(string_helper.response_body());
-  ASSERT_FALSE(string_helper.simple_url_loader()->ResponseInfo());
+  EXPECT_EQ(net::ERR_FAILED, test_helper()->simple_url_loader()->NetError());
+  EXPECT_FALSE(test_helper()->response_body());
+  ASSERT_FALSE(test_helper()->simple_url_loader()->ResponseInfo());
 }
 
 enum class TestLoaderEvent {
@@ -702,8 +803,8 @@
                    int32_t intra_priority_value) override {
     NOTREACHED();
   }
-  void PauseCachingResponseBody() override {}
-  void ResumeCachingResponseBody() override {}
+  void PauseReadingBodyFromNet() override {}
+  void ResumeReadingBodyFromNet() override {}
 
   mojom::URLLoaderClient* client() const { return client_.get(); }
 
@@ -773,47 +874,46 @@
 };
 
 // Check that the request fails if OnComplete() is called before anything else.
-TEST_F(SimpleURLLoaderTest, ResponseCompleteBeforeReceivedResponse) {
+TEST_P(SimpleURLLoaderTest, ResponseCompleteBeforeReceivedResponse) {
   MockURLLoaderFactory loader_factory(&scoped_task_environment_);
   loader_factory.AddEvent(TestLoaderEvent::kResponseComplete);
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURL(&loader_factory, GURL("foo://bar/"));
+  test_helper()->RunRequestForURL(&loader_factory, GURL("foo://bar/"));
 
-  EXPECT_EQ(net::ERR_UNEXPECTED, string_helper.simple_url_loader()->NetError());
-  EXPECT_FALSE(string_helper.simple_url_loader()->ResponseInfo());
-  EXPECT_FALSE(string_helper.response_body());
+  EXPECT_EQ(net::ERR_UNEXPECTED,
+            test_helper()->simple_url_loader()->NetError());
+  EXPECT_FALSE(test_helper()->simple_url_loader()->ResponseInfo());
+  EXPECT_FALSE(test_helper()->response_body());
 }
 
 // Check that the request fails if OnComplete() is called before the body pipe
 // is received.
-TEST_F(SimpleURLLoaderTest, ResponseCompleteAfterReceivedResponse) {
+TEST_P(SimpleURLLoaderTest, ResponseCompleteAfterReceivedResponse) {
   MockURLLoaderFactory loader_factory(&scoped_task_environment_);
   loader_factory.AddEvent(TestLoaderEvent::kReceivedResponse);
   loader_factory.AddEvent(TestLoaderEvent::kResponseComplete);
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURL(&loader_factory, GURL("foo://bar/"));
+  test_helper()->RunRequestForURL(&loader_factory, GURL("foo://bar/"));
 
-  EXPECT_EQ(net::ERR_UNEXPECTED, string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(200, string_helper.GetResponseCode());
-  EXPECT_FALSE(string_helper.response_body());
+  EXPECT_EQ(net::ERR_UNEXPECTED,
+            test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(200, test_helper()->GetResponseCode());
+  EXPECT_FALSE(test_helper()->response_body());
 }
 
-TEST_F(SimpleURLLoaderTest, CloseClientPipeBeforeBodyStarts) {
+TEST_P(SimpleURLLoaderTest, CloseClientPipeBeforeBodyStarts) {
   MockURLLoaderFactory loader_factory(&scoped_task_environment_);
   loader_factory.AddEvent(TestLoaderEvent::kReceivedResponse);
   loader_factory.AddEvent(TestLoaderEvent::kClientPipeClosed);
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURL(&loader_factory, GURL("foo://bar/"));
+  test_helper()->RunRequestForURL(&loader_factory, GURL("foo://bar/"));
 
-  EXPECT_EQ(net::ERR_FAILED, string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(200, string_helper.GetResponseCode());
-  EXPECT_FALSE(string_helper.response_body());
+  EXPECT_EQ(net::ERR_FAILED, test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(200, test_helper()->GetResponseCode());
+  EXPECT_FALSE(test_helper()->response_body());
 }
 
 // This test tries closing the client pipe / completing the request in most
 // possible valid orders relative to read events (Which always occur in the same
 // order).
-TEST_F(SimpleURLLoaderTest, CloseClientPipeOrder) {
+TEST_P(SimpleURLLoaderTest, CloseClientPipeOrder) {
   enum class ClientCloseOrder {
     kBeforeData,
     kDuringData,
@@ -863,33 +963,33 @@
           if (close_client_order == ClientCloseOrder::kAfterBufferClosed)
             loader_factory.AddEvent(close_client_event);
 
-          WaitForStringHelper string_helper;
-          string_helper.simple_url_loader()->SetAllowPartialResults(
+          SimpleLoaderTestHelper test_helper(GetParam());
+          test_helper.simple_url_loader()->SetAllowPartialResults(
               allow_partial_results);
-          string_helper.RunRequestForURL(&loader_factory, GURL("foo://bar/"));
+          test_helper.RunRequestForURL(&loader_factory, GURL("foo://bar/"));
 
-          EXPECT_EQ(200, string_helper.GetResponseCode());
+          EXPECT_EQ(200, test_helper.GetResponseCode());
           if (close_client_event != TestLoaderEvent::kResponseComplete) {
             if (close_client_event ==
                 TestLoaderEvent::kResponseCompleteFailed) {
               EXPECT_EQ(net::ERR_TIMED_OUT,
-                        string_helper.simple_url_loader()->NetError());
+                        test_helper.simple_url_loader()->NetError());
             } else {
               EXPECT_EQ(net::ERR_FAILED,
-                        string_helper.simple_url_loader()->NetError());
+                        test_helper.simple_url_loader()->NetError());
             }
             if (!allow_partial_results) {
-              EXPECT_FALSE(string_helper.response_body());
+              EXPECT_FALSE(test_helper.response_body());
             } else {
-              ASSERT_TRUE(string_helper.response_body());
+              ASSERT_TRUE(test_helper.response_body());
               EXPECT_EQ(std::string(bytes_received, 'a'),
-                        *string_helper.response_body());
+                        *test_helper.response_body());
             }
           } else {
-            EXPECT_EQ(net::OK, string_helper.simple_url_loader()->NetError());
-            ASSERT_TRUE(string_helper.response_body());
+            EXPECT_EQ(net::OK, test_helper.simple_url_loader()->NetError());
+            ASSERT_TRUE(test_helper.response_body());
             EXPECT_EQ(std::string(bytes_received, 'a'),
-                      *string_helper.response_body());
+                      *test_helper.response_body());
           }
         }
       }
@@ -898,21 +998,20 @@
 }
 
 // Make sure the close client pipe message doesn't cause any issues.
-TEST_F(SimpleURLLoaderTest, ErrorAndCloseClientPipeBeforeBodyStarts) {
+TEST_P(SimpleURLLoaderTest, ErrorAndCloseClientPipeBeforeBodyStarts) {
   MockURLLoaderFactory loader_factory(&scoped_task_environment_);
   loader_factory.AddEvent(TestLoaderEvent::kReceivedResponse);
   loader_factory.AddEvent(TestLoaderEvent::kResponseCompleteFailed);
   loader_factory.AddEvent(TestLoaderEvent::kClientPipeClosed);
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURL(&loader_factory, GURL("foo://bar/"));
+  test_helper()->RunRequestForURL(&loader_factory, GURL("foo://bar/"));
 
-  EXPECT_EQ(net::ERR_TIMED_OUT, string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(200, string_helper.GetResponseCode());
-  EXPECT_FALSE(string_helper.response_body());
+  EXPECT_EQ(net::ERR_TIMED_OUT, test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(200, test_helper()->GetResponseCode());
+  EXPECT_FALSE(test_helper()->response_body());
 }
 
 // Make sure the close client pipe message doesn't cause any issues.
-TEST_F(SimpleURLLoaderTest, SuccessAndCloseClientPipeBeforeBodyComplete) {
+TEST_P(SimpleURLLoaderTest, SuccessAndCloseClientPipeBeforeBodyComplete) {
   MockURLLoaderFactory loader_factory(&scoped_task_environment_);
   loader_factory.AddEvent(TestLoaderEvent::kReceivedResponse);
   loader_factory.AddEvent(TestLoaderEvent::kBodyBufferReceived);
@@ -920,17 +1019,16 @@
   loader_factory.AddEvent(TestLoaderEvent::kClientPipeClosed);
   loader_factory.AddEvent(TestLoaderEvent::kBodyDataRead);
   loader_factory.AddEvent(TestLoaderEvent::kBodyBufferClosed);
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURL(&loader_factory, GURL("foo://bar/"));
+  test_helper()->RunRequestForURL(&loader_factory, GURL("foo://bar/"));
 
-  EXPECT_EQ(net::OK, string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(200, string_helper.GetResponseCode());
-  ASSERT_TRUE(string_helper.response_body());
-  EXPECT_EQ("a", *string_helper.response_body());
+  EXPECT_EQ(net::OK, test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(200, test_helper()->GetResponseCode());
+  ASSERT_TRUE(test_helper()->response_body());
+  EXPECT_EQ("a", *test_helper()->response_body());
 }
 
 // Make sure the close client pipe message doesn't cause any issues.
-TEST_F(SimpleURLLoaderTest, SuccessAndCloseClientPipeAfterBodyComplete) {
+TEST_P(SimpleURLLoaderTest, SuccessAndCloseClientPipeAfterBodyComplete) {
   MockURLLoaderFactory loader_factory(&scoped_task_environment_);
   loader_factory.AddEvent(TestLoaderEvent::kReceivedResponse);
   loader_factory.AddEvent(TestLoaderEvent::kBodyBufferReceived);
@@ -938,107 +1036,106 @@
   loader_factory.AddEvent(TestLoaderEvent::kBodyBufferClosed);
   loader_factory.AddEvent(TestLoaderEvent::kResponseComplete);
   loader_factory.AddEvent(TestLoaderEvent::kClientPipeClosed);
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURL(&loader_factory, GURL("foo://bar/"));
+  test_helper()->RunRequestForURL(&loader_factory, GURL("foo://bar/"));
 
-  EXPECT_EQ(net::OK, string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(200, string_helper.GetResponseCode());
-  ASSERT_TRUE(string_helper.response_body());
-  EXPECT_EQ("a", *string_helper.response_body());
+  EXPECT_EQ(net::OK, test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(200, test_helper()->GetResponseCode());
+  ASSERT_TRUE(test_helper()->response_body());
+  EXPECT_EQ("a", *test_helper()->response_body());
 }
 
-TEST_F(SimpleURLLoaderTest, DoubleReceivedResponse) {
+TEST_P(SimpleURLLoaderTest, DoubleReceivedResponse) {
   MockURLLoaderFactory loader_factory(&scoped_task_environment_);
   loader_factory.AddEvent(TestLoaderEvent::kReceivedResponse);
   loader_factory.AddEvent(TestLoaderEvent::kReceivedResponse);
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURL(&loader_factory, GURL("foo://bar/"));
+  test_helper()->RunRequestForURL(&loader_factory, GURL("foo://bar/"));
 
-  EXPECT_EQ(net::ERR_UNEXPECTED, string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(200, string_helper.GetResponseCode());
-  EXPECT_FALSE(string_helper.response_body());
+  EXPECT_EQ(net::ERR_UNEXPECTED,
+            test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(200, test_helper()->GetResponseCode());
+  EXPECT_FALSE(test_helper()->response_body());
 }
 
-TEST_F(SimpleURLLoaderTest, RedirectAfterReseivedResponse) {
+TEST_P(SimpleURLLoaderTest, RedirectAfterReseivedResponse) {
   MockURLLoaderFactory loader_factory(&scoped_task_environment_);
   loader_factory.AddEvent(TestLoaderEvent::kReceivedResponse);
   loader_factory.AddEvent(TestLoaderEvent::kReceivedRedirect);
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURL(&loader_factory, GURL("foo://bar/"));
+  test_helper()->RunRequestForURL(&loader_factory, GURL("foo://bar/"));
 
-  EXPECT_EQ(net::ERR_UNEXPECTED, string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(200, string_helper.GetResponseCode());
-  EXPECT_FALSE(string_helper.response_body());
+  EXPECT_EQ(net::ERR_UNEXPECTED,
+            test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(200, test_helper()->GetResponseCode());
+  EXPECT_FALSE(test_helper()->response_body());
 }
 
-TEST_F(SimpleURLLoaderTest, UnexpectedBodyBufferReceived) {
+TEST_P(SimpleURLLoaderTest, UnexpectedBodyBufferReceived) {
   MockURLLoaderFactory loader_factory(&scoped_task_environment_);
   loader_factory.AddEvent(TestLoaderEvent::kBodyBufferReceived);
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURL(&loader_factory, GURL("foo://bar/"));
+  test_helper()->RunRequestForURL(&loader_factory, GURL("foo://bar/"));
 
-  EXPECT_EQ(net::ERR_UNEXPECTED, string_helper.simple_url_loader()->NetError());
-  EXPECT_FALSE(string_helper.simple_url_loader()->ResponseInfo());
-  EXPECT_FALSE(string_helper.response_body());
+  EXPECT_EQ(net::ERR_UNEXPECTED,
+            test_helper()->simple_url_loader()->NetError());
+  EXPECT_FALSE(test_helper()->simple_url_loader()->ResponseInfo());
+  EXPECT_FALSE(test_helper()->response_body());
 }
 
-TEST_F(SimpleURLLoaderTest, DoubleBodyBufferReceived) {
+TEST_P(SimpleURLLoaderTest, DoubleBodyBufferReceived) {
   MockURLLoaderFactory loader_factory(&scoped_task_environment_);
   loader_factory.AddEvent(TestLoaderEvent::kReceivedResponse);
   loader_factory.AddEvent(TestLoaderEvent::kBodyBufferReceived);
   loader_factory.AddEvent(TestLoaderEvent::kBodyBufferReceived);
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURL(&loader_factory, GURL("foo://bar/"));
+  test_helper()->RunRequestForURL(&loader_factory, GURL("foo://bar/"));
 
-  EXPECT_EQ(net::ERR_UNEXPECTED, string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(200, string_helper.GetResponseCode());
-  EXPECT_FALSE(string_helper.response_body());
+  EXPECT_EQ(net::ERR_UNEXPECTED,
+            test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(200, test_helper()->GetResponseCode());
+  EXPECT_FALSE(test_helper()->response_body());
 }
 
-TEST_F(SimpleURLLoaderTest, UnexpectedMessageAfterBodyStarts) {
+TEST_P(SimpleURLLoaderTest, UnexpectedMessageAfterBodyStarts) {
   MockURLLoaderFactory loader_factory(&scoped_task_environment_);
   loader_factory.AddEvent(TestLoaderEvent::kReceivedResponse);
   loader_factory.AddEvent(TestLoaderEvent::kBodyBufferReceived);
   loader_factory.AddEvent(TestLoaderEvent::kBodyDataRead);
   loader_factory.AddEvent(TestLoaderEvent::kReceivedRedirect);
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURL(&loader_factory, GURL("foo://bar/"));
+  test_helper()->RunRequestForURL(&loader_factory, GURL("foo://bar/"));
 
-  EXPECT_EQ(net::ERR_UNEXPECTED, string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(200, string_helper.GetResponseCode());
-  EXPECT_FALSE(string_helper.response_body());
+  EXPECT_EQ(net::ERR_UNEXPECTED,
+            test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(200, test_helper()->GetResponseCode());
+  EXPECT_FALSE(test_helper()->response_body());
 }
 
-TEST_F(SimpleURLLoaderTest, UnexpectedMessageAfterBodyStarts2) {
+TEST_P(SimpleURLLoaderTest, UnexpectedMessageAfterBodyStarts2) {
   MockURLLoaderFactory loader_factory(&scoped_task_environment_);
   loader_factory.AddEvent(TestLoaderEvent::kReceivedResponse);
   loader_factory.AddEvent(TestLoaderEvent::kBodyBufferReceived);
   loader_factory.AddEvent(TestLoaderEvent::kBodyDataRead);
   loader_factory.AddEvent(TestLoaderEvent::kBodyBufferReceived);
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURL(&loader_factory, GURL("foo://bar/"));
+  test_helper()->RunRequestForURL(&loader_factory, GURL("foo://bar/"));
 
-  EXPECT_EQ(net::ERR_UNEXPECTED, string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(200, string_helper.GetResponseCode());
-  EXPECT_FALSE(string_helper.response_body());
+  EXPECT_EQ(net::ERR_UNEXPECTED,
+            test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(200, test_helper()->GetResponseCode());
+  EXPECT_FALSE(test_helper()->response_body());
 }
 
-TEST_F(SimpleURLLoaderTest, UnexpectedMessageAfterBodyComplete) {
+TEST_P(SimpleURLLoaderTest, UnexpectedMessageAfterBodyComplete) {
   MockURLLoaderFactory loader_factory(&scoped_task_environment_);
   loader_factory.AddEvent(TestLoaderEvent::kReceivedResponse);
   loader_factory.AddEvent(TestLoaderEvent::kBodyBufferReceived);
   loader_factory.AddEvent(TestLoaderEvent::kBodyDataRead);
   loader_factory.AddEvent(TestLoaderEvent::kBodyBufferClosed);
   loader_factory.AddEvent(TestLoaderEvent::kBodyBufferReceived);
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURL(&loader_factory, GURL("foo://bar/"));
+  test_helper()->RunRequestForURL(&loader_factory, GURL("foo://bar/"));
 
-  EXPECT_EQ(net::ERR_UNEXPECTED, string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(200, string_helper.GetResponseCode());
-  EXPECT_FALSE(string_helper.response_body());
+  EXPECT_EQ(net::ERR_UNEXPECTED,
+            test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(200, test_helper()->GetResponseCode());
+  EXPECT_FALSE(test_helper()->response_body());
 }
 
-TEST_F(SimpleURLLoaderTest, MoreDataThanExpected) {
+TEST_P(SimpleURLLoaderTest, MoreDataThanExpected) {
   MockURLLoaderFactory loader_factory(&scoped_task_environment_);
   loader_factory.AddEvent(TestLoaderEvent::kReceivedResponse);
   loader_factory.AddEvent(TestLoaderEvent::kBodyBufferReceived);
@@ -1046,12 +1143,114 @@
   loader_factory.AddEvent(TestLoaderEvent::kBodyDataRead);
   loader_factory.AddEvent(TestLoaderEvent::kBodyBufferClosed);
   loader_factory.AddEvent(TestLoaderEvent::kResponseCompleteWithExtraData);
-  WaitForStringHelper string_helper;
-  string_helper.RunRequestForURL(&loader_factory, GURL("foo://bar/"));
+  test_helper()->RunRequestForURL(&loader_factory, GURL("foo://bar/"));
 
-  EXPECT_EQ(net::ERR_UNEXPECTED, string_helper.simple_url_loader()->NetError());
-  EXPECT_EQ(200, string_helper.GetResponseCode());
-  EXPECT_FALSE(string_helper.response_body());
+  EXPECT_EQ(net::ERR_UNEXPECTED,
+            test_helper()->simple_url_loader()->NetError());
+  EXPECT_EQ(200, test_helper()->GetResponseCode());
+  EXPECT_FALSE(test_helper()->response_body());
+}
+
+INSTANTIATE_TEST_CASE_P(
+    /* No prefix */,
+    SimpleURLLoaderTest,
+    testing::Values(SimpleLoaderTestHelper::DownloadType::TO_STRING,
+                    SimpleLoaderTestHelper::DownloadType::TO_FILE));
+
+class SimpleURLLoaderFileTest : public SimpleURLLoaderTestBase,
+                                public testing::Test {
+ public:
+  SimpleURLLoaderFileTest()
+      : test_helper_(SimpleLoaderTestHelper::DownloadType::TO_FILE) {}
+  ~SimpleURLLoaderFileTest() override {}
+
+  SimpleLoaderTestHelper* test_helper() { return &test_helper_; }
+
+ private:
+  SimpleLoaderTestHelper test_helper_;
+};
+
+// Make sure that an existing file will be completely overwritten.
+TEST_F(SimpleURLLoaderFileTest, OverwriteFile) {
+  std::string junk_data(100, '!');
+  ASSERT_EQ(static_cast<int>(junk_data.size()),
+            base::WriteFile(test_helper()->dest_path(), junk_data.data(),
+                            junk_data.size()));
+  ASSERT_TRUE(base::PathExists(test_helper()->dest_path()));
+
+  ResourceRequest resource_request;
+  resource_request.url = GURL("data:text/plain,foo");
+  test_helper()->RunRequest(url_loader_factory_.get(), resource_request);
+
+  EXPECT_EQ(net::OK, test_helper()->simple_url_loader()->NetError());
+  ASSERT_TRUE(test_helper()->simple_url_loader()->ResponseInfo());
+  ASSERT_TRUE(test_helper()->response_body());
+  EXPECT_EQ("foo", *test_helper()->response_body());
+}
+
+// Make sure that file creation errors are handled correctly.
+TEST_F(SimpleURLLoaderFileTest, FileCreateError) {
+  ASSERT_TRUE(base::CreateDirectory(test_helper()->dest_path()));
+  ASSERT_TRUE(base::PathExists(test_helper()->dest_path()));
+
+  ResourceRequest resource_request;
+  resource_request.url = GURL("data:text/plain,foo");
+  // The directory should still exist after the download fails.
+  test_helper()->set_expect_path_exists_on_error(true);
+  test_helper()->RunRequest(url_loader_factory_.get(), resource_request);
+
+  EXPECT_EQ(net::ERR_ACCESS_DENIED,
+            test_helper()->simple_url_loader()->NetError());
+  EXPECT_TRUE(test_helper()->simple_url_loader()->ResponseInfo());
+  EXPECT_FALSE(test_helper()->response_body());
+}
+
+// Make sure that destroying the loader destroys a partially downloaded file.
+TEST_F(SimpleURLLoaderFileTest, DeleteLoaderDuringRequestDestroysFile) {
+  for (bool body_data_read : {false, true}) {
+    for (bool body_buffer_closed : {false, true}) {
+      for (bool client_pipe_closed : {false, true}) {
+        // If both pipes were closed cleanly, the file shouldn't be deleted, as
+        // that indicates success.
+        if (body_buffer_closed && client_pipe_closed)
+          continue;
+
+        MockURLLoaderFactory loader_factory(&scoped_task_environment_);
+        loader_factory.AddEvent(TestLoaderEvent::kReceivedResponse);
+        loader_factory.AddEvent(TestLoaderEvent::kBodyBufferReceived);
+        if (body_data_read)
+          loader_factory.AddEvent(TestLoaderEvent::kBodyDataRead);
+        if (body_buffer_closed)
+          loader_factory.AddEvent(TestLoaderEvent::kBodyBufferClosed);
+        if (client_pipe_closed)
+          loader_factory.AddEvent(TestLoaderEvent::kClientPipeClosed);
+
+        // The request just hangs after receiving some body data.
+        ResourceRequest resource_request;
+        resource_request.url = GURL("foo://bar/");
+
+        std::unique_ptr<SimpleLoaderTestHelper> test_helper =
+            std::make_unique<SimpleLoaderTestHelper>(
+                SimpleLoaderTestHelper::DownloadType::TO_FILE);
+        test_helper->StartRequest(&loader_factory, resource_request);
+
+        // Wait for the request to advance as far as it's going to.
+        scoped_task_environment_.RunUntilIdle();
+
+        // Destination file should have been created, and request should still
+        // be in progress.
+        base::FilePath dest_path = test_helper->dest_path();
+        EXPECT_TRUE(base::PathExists(dest_path));
+        EXPECT_FALSE(test_helper->done());
+
+        // Destroying the SimpleURLLoader now should post a task to destroy the
+        // file.
+        test_helper.reset();
+        scoped_task_environment_.RunUntilIdle();
+        EXPECT_FALSE(base::PathExists(dest_path));
+      }
+    }
+  }
 }
 
 }  // namespace
diff --git a/content/public/common/url_loader.mojom b/content/public/common/url_loader.mojom
index 6ea6d0b..b77d3e63 100644
--- a/content/public/common/url_loader.mojom
+++ b/content/public/common/url_loader.mojom
@@ -41,14 +41,14 @@
   // requests within a given priority level.
   SetPriority(RequestPriority priority, int32 intra_priority_value);
 
-  // If a URLLoader fetches the resource from network and support caching, it
-  // should handle these methods to pause/resume caching. Otherwise, these
-  // methods could be no-ops.
+  // If a URLLoader fetches the resource from network, it should handle these
+  // methods to pause/resume reading the response body from network. Otherwise,
+  // these methods could be no-ops.
   //
-  // It is allowed to call Pause/ResumeCachingResponseBody before response body
+  // It is allowed to call Pause/ResumeReadingBodyFromNet before response body
   // is available.
-  PauseCachingResponseBody();
-  ResumeCachingResponseBody();
+  PauseReadingBodyFromNet();
+  ResumeReadingBodyFromNet();
 };
 
 // Opaque handle passed from the browser process to a child process to manage
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index 706e146..c946bc89 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -1983,6 +1983,15 @@
   return WaitForDesiredState();
 }
 
+void TestNavigationManager::ResumeNavigation() {
+  DCHECK(current_state_ == NavigationState::STARTED ||
+         current_state_ == NavigationState::RESPONSE);
+  DCHECK_EQ(current_state_, desired_state_);
+  DCHECK(navigation_paused_);
+  navigation_paused_ = false;
+  handle_->CallResumeForTesting();
+}
+
 bool TestNavigationManager::WaitForResponse() {
   desired_state_ = NavigationState::RESPONSE;
   return WaitForDesiredState();
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h
index 6e98eaf..6a0a0cf 100644
--- a/content/public/test/browser_test_utils.h
+++ b/content/public/test/browser_test_utils.h
@@ -780,14 +780,19 @@
   // stack. Returns false if the request was aborted before starting.
   WARN_UNUSED_RESULT bool WaitForRequestStart();
 
-  // Waits until the navigation response has been sent received. Returns false
-  // if the request was aborted before getting a response.
+  // Waits until the navigation response's headers have been received. Returns
+  // false if the request was aborted before getting a response.
   WARN_UNUSED_RESULT bool WaitForResponse();
 
   // Waits until the navigation has been finished. Will automatically resume
   // navigations paused before this point.
   void WaitForNavigationFinished();
 
+  // Resume the navigation.
+  // * Called after |WaitForRequestStart|, it causes the request to be sent.
+  // * Called after |WaitForResponse|, it causes the response to be committed.
+  void ResumeNavigation();
+
  protected:
   // Derived classes can override if they want to filter out navigations. This
   // is called from DidStartNavigation.
diff --git a/content/public/test/test_browser_thread_bundle.cc b/content/public/test/test_browser_thread_bundle.cc
index 6f73ca7d..71eaf24 100644
--- a/content/public/test/test_browser_thread_bundle.cc
+++ b/content/public/test/test_browser_thread_bundle.cc
@@ -39,10 +39,16 @@
   base::RunLoop().RunUntilIdle();
   io_thread_->Stop();
   base::RunLoop().RunUntilIdle();
+  cache_thread_->Stop();
+  base::RunLoop().RunUntilIdle();
   process_launcher_thread_->Stop();
   base::RunLoop().RunUntilIdle();
+  file_user_blocking_thread_->Stop();
+  base::RunLoop().RunUntilIdle();
   file_thread_->Stop();
   base::RunLoop().RunUntilIdle();
+  db_thread_->Stop();
+  base::RunLoop().RunUntilIdle();
   ui_thread_->Stop();
   base::RunLoop().RunUntilIdle();
 
@@ -118,6 +124,14 @@
 void TestBrowserThreadBundle::CreateBrowserThreads() {
   CHECK(!threads_created_);
 
+  if (options_ & REAL_DB_THREAD) {
+    db_thread_ = base::MakeUnique<TestBrowserThread>(BrowserThread::DB);
+    db_thread_->Start();
+  } else {
+    db_thread_ = base::MakeUnique<TestBrowserThread>(
+        BrowserThread::DB, base::MessageLoop::current());
+  }
+
   if (options_ & REAL_FILE_THREAD) {
     file_thread_ = base::MakeUnique<TestBrowserThread>(BrowserThread::FILE);
     file_thread_->Start();
@@ -126,8 +140,12 @@
         BrowserThread::FILE, base::MessageLoop::current());
   }
 
+  file_user_blocking_thread_ = base::MakeUnique<TestBrowserThread>(
+      BrowserThread::FILE_USER_BLOCKING, base::MessageLoop::current());
   process_launcher_thread_ = base::MakeUnique<TestBrowserThread>(
       BrowserThread::PROCESS_LAUNCHER, base::MessageLoop::current());
+  cache_thread_ = base::MakeUnique<TestBrowserThread>(
+      BrowserThread::CACHE, base::MessageLoop::current());
 
   if (options_ & REAL_IO_THREAD) {
     io_thread_ = base::MakeUnique<TestBrowserThread>(BrowserThread::IO);
diff --git a/content/public/test/test_browser_thread_bundle.h b/content/public/test/test_browser_thread_bundle.h
index fc7cf2825..878f1ba 100644
--- a/content/public/test/test_browser_thread_bundle.h
+++ b/content/public/test/test_browser_thread_bundle.h
@@ -112,9 +112,10 @@
   enum Options {
     DEFAULT = 0,
     IO_MAINLOOP = 1 << 0,
-    REAL_FILE_THREAD = 1 << 1,
-    REAL_IO_THREAD = 1 << 2,
-    DONT_CREATE_BROWSER_THREADS = 1 << 3,
+    REAL_DB_THREAD = 1 << 1,
+    REAL_FILE_THREAD = 1 << 2,
+    REAL_IO_THREAD = 1 << 3,
+    DONT_CREATE_BROWSER_THREADS = 1 << 4,
   };
 
   TestBrowserThreadBundle();
@@ -131,8 +132,11 @@
 
   std::unique_ptr<base::test::ScopedTaskEnvironment> scoped_task_environment_;
   std::unique_ptr<TestBrowserThread> ui_thread_;
+  std::unique_ptr<TestBrowserThread> db_thread_;
   std::unique_ptr<TestBrowserThread> file_thread_;
+  std::unique_ptr<TestBrowserThread> file_user_blocking_thread_;
   std::unique_ptr<TestBrowserThread> process_launcher_thread_;
+  std::unique_ptr<TestBrowserThread> cache_thread_;
   std::unique_ptr<TestBrowserThread> io_thread_;
 
   int options_;
diff --git a/content/renderer/accessibility/blink_ax_enum_conversion.cc b/content/renderer/accessibility/blink_ax_enum_conversion.cc
index aecb796da..cc683647 100644
--- a/content/renderer/accessibility/blink_ax_enum_conversion.cc
+++ b/content/renderer/accessibility/blink_ax_enum_conversion.cc
@@ -40,9 +40,6 @@
   if (o.IsMultiSelectable())
     state |= (1 << ui::AX_STATE_MULTISELECTABLE);
 
-  if (o.IsOffScreen())
-    state |= (1 << ui::AX_STATE_OFFSCREEN);
-
   if (o.IsPasswordField())
     state |= (1 << ui::AX_STATE_PROTECTED);
 
diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc
index ebaca69..75218ea 100644
--- a/content/renderer/browser_plugin/browser_plugin.cc
+++ b/content/renderer/browser_plugin/browser_plugin.cc
@@ -104,9 +104,6 @@
 BrowserPlugin::~BrowserPlugin() {
   Detach();
 
-  if (compositing_helper_)
-    compositing_helper_->OnContainerDestroy();
-
   if (delegate_) {
     delegate_->DidDestroyElement();
     delegate_.reset();
@@ -139,26 +136,6 @@
   if (!attached())
     return;
 
-  if (!compositing_helper_) {
-    compositing_helper_.reset(
-        ChildFrameCompositingHelper::CreateForBrowserPlugin(
-            weak_ptr_factory_.GetWeakPtr()));
-    if (enable_surface_synchronization_) {
-      // We wait until there is a single CompositorFrame guaranteed to be
-      // available and ready for display in the display compositor before using
-      // surface synchronization. This guarantees that we will have something to
-      // display when the compositor goes to produce a display frame.
-      //
-      // Once there's an available fallback surface that can be employed, then
-      // the primary surface is updated as soon as the frame rect changes.
-      //
-      // The compositor will attempt to composite the primary surface within a
-      // give deadline (4 frames is the default). If the primary surface isn't
-      // available for four frames, then the fallback surface will be used.
-      compositing_helper_->SetPrimarySurfaceInfo(surface_info);
-    }
-  }
-
   if (!enable_surface_synchronization_)
     compositing_helper_->SetPrimarySurfaceInfo(surface_info);
   compositing_helper_->SetFallbackSurfaceInfo(surface_info, sequence);
@@ -226,10 +203,7 @@
 
   attached_ = false;
   guest_crashed_ = false;
-  if (compositing_helper_) {
-    compositing_helper_->OnContainerDestroy();
-    compositing_helper_.reset();
-  }
+  compositing_helper_->OnContainerDestroy();
 
   BrowserPluginManager::Get()->Send(
       new BrowserPluginHostMsg_Detach(browser_plugin_instance_id_));
@@ -250,12 +224,6 @@
 
 void BrowserPlugin::OnGuestGone(int browser_plugin_instance_id) {
   guest_crashed_ = true;
-
-  if (!compositing_helper_) {
-    compositing_helper_.reset(
-        ChildFrameCompositingHelper::CreateForBrowserPlugin(
-            weak_ptr_factory_.GetWeakPtr()));
-  }
   compositing_helper_->ChildFrameGone();
 }
 
@@ -327,8 +295,7 @@
       !view_rect_ || view_rect_->size() != view_rect.size();
   if (rect_size_changed || !local_surface_id_.is_valid()) {
     local_surface_id_ = local_surface_id_allocator_.GenerateId();
-    if (compositing_helper_ && enable_surface_synchronization_ &&
-        frame_sink_id_.is_valid()) {
+    if (enable_surface_synchronization_ && frame_sink_id_.is_valid()) {
       RenderWidget* render_widget =
           RenderFrameImpl::FromWebFrame(Container()->GetDocument().GetFrame())
               ->GetRenderWidget();
@@ -395,6 +362,10 @@
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(&BrowserPlugin::UpdateInternalInstanceId,
                                 weak_ptr_factory_.GetWeakPtr()));
+
+  compositing_helper_.reset(ChildFrameCompositingHelper::CreateForBrowserPlugin(
+      weak_ptr_factory_.GetWeakPtr()));
+
   return true;
 }
 
@@ -483,8 +454,7 @@
   if (!attached())
     return;
 
-  if (compositing_helper_)
-    compositing_helper_->UpdateVisibility(visible);
+  compositing_helper_->UpdateVisibility(visible);
 
   BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_SetVisibility(
       browser_plugin_instance_id_,
diff --git a/content/renderer/browser_render_view_browsertest.cc b/content/renderer/browser_render_view_browsertest.cc
index ee919d6a..88e3b0f9 100644
--- a/content/renderer/browser_render_view_browsertest.cc
+++ b/content/renderer/browser_render_view_browsertest.cc
@@ -205,8 +205,12 @@
   // Reload same URL after forcing an error from the the network layer;
   // confirm that the error page is told the cached copy exists.
   scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
-      shell()->web_contents()->GetRenderProcessHost()->GetStoragePartition()->
-          GetURLRequestContext();
+      shell()
+          ->web_contents()
+          ->GetMainFrame()
+          ->GetProcess()
+          ->GetStoragePartition()
+          ->GetURLRequestContext();
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
       base::BindOnce(&InterceptNetworkTransactions,
diff --git a/content/renderer/child_frame_compositing_helper.cc b/content/renderer/child_frame_compositing_helper.cc
index e7b34f0..1fbfdce 100644
--- a/content/renderer/child_frame_compositing_helper.cc
+++ b/content/renderer/child_frame_compositing_helper.cc
@@ -173,17 +173,19 @@
   enable_surface_references_ =
       !base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kDisableSurfaceReferences);
-  scoped_refptr<ThreadSafeSender> sender(
-      RenderThreadImpl::current()->thread_safe_sender());
   if (enable_surface_references_) {
     surface_reference_factory_ = new viz::StubSurfaceReferenceFactory();
-  } else if (render_frame_proxy_) {
-    surface_reference_factory_ =
-        new IframeSurfaceReferenceFactory(sender, host_routing_id_);
   } else {
-    surface_reference_factory_ = new BrowserPluginSurfaceReferenceFactory(
-        sender, host_routing_id_,
-        browser_plugin_->browser_plugin_instance_id());
+    scoped_refptr<ThreadSafeSender> sender(
+        RenderThreadImpl::current()->thread_safe_sender());
+    if (render_frame_proxy_) {
+      surface_reference_factory_ =
+          new IframeSurfaceReferenceFactory(sender, host_routing_id_);
+    } else {
+      surface_reference_factory_ = new BrowserPluginSurfaceReferenceFactory(
+          sender, host_routing_id_,
+          browser_plugin_->browser_plugin_instance_id());
+    }
   }
 }
 
@@ -271,6 +273,7 @@
 
   surface_layer_ = cc::SurfaceLayer::Create(surface_reference_factory_);
   surface_layer_->SetMasksToBounds(true);
+  surface_layer_->SetDefaultBackgroundColor(SK_ColorTRANSPARENT);
 
   viz::SurfaceInfo modified_surface_info(surface_info.id(), scale_factor,
                                          surface_info.size_in_pixels());
diff --git a/content/renderer/input/frame_input_handler_impl.cc b/content/renderer/input/frame_input_handler_impl.cc
index 53d5a43..9598926 100644
--- a/content/renderer/input/frame_input_handler_impl.cc
+++ b/content/renderer/input/frame_input_handler_impl.cc
@@ -271,7 +271,9 @@
   HandlingState handling_state(render_frame_.get(),
                                UpdateState::kIsSelectingRange);
   render_frame_->GetWebFrame()->SelectRange(
-      blink::WebRange(range.EndOffset(), 0));
+      blink::WebRange(range.EndOffset(), 0),
+      blink::WebLocalFrame::kHideSelectionHandle,
+      blink::mojom::SelectionMenuBehavior::kHide);
 }
 
 void FrameInputHandlerImpl::SelectRange(const gfx::Point& base,
@@ -295,12 +297,14 @@
       render_view->ConvertWindowPointToViewport(extent));
 }
 
-void FrameInputHandlerImpl::AdjustSelectionByCharacterOffset(int32_t start,
-                                                             int32_t end) {
+void FrameInputHandlerImpl::AdjustSelectionByCharacterOffset(
+    int32_t start,
+    int32_t end,
+    blink::mojom::SelectionMenuBehavior selection_menu_behavior) {
   if (!main_thread_task_runner_->BelongsToCurrentThread()) {
     RunOnMainThread(
         base::Bind(&FrameInputHandlerImpl::AdjustSelectionByCharacterOffset,
-                   weak_this_, start, end));
+                   weak_this_, start, end, selection_menu_behavior));
     return;
   }
 
@@ -324,7 +328,7 @@
   render_frame_->GetWebFrame()->SelectRange(
       blink::WebRange(range.StartOffset() + start,
                       range.length() + end - start),
-      blink::WebLocalFrame::kPreserveHandleVisibility);
+      blink::WebLocalFrame::kPreserveHandleVisibility, selection_menu_behavior);
 }
 
 void FrameInputHandlerImpl::MoveRangeSelectionExtent(const gfx::Point& extent) {
diff --git a/content/renderer/input/frame_input_handler_impl.h b/content/renderer/input/frame_input_handler_impl.h
index a27ac53..17742d0 100644
--- a/content/renderer/input/frame_input_handler_impl.h
+++ b/content/renderer/input/frame_input_handler_impl.h
@@ -65,7 +65,10 @@
   void SelectAll() override;
   void CollapseSelection() override;
   void SelectRange(const gfx::Point& base, const gfx::Point& extent) override;
-  void AdjustSelectionByCharacterOffset(int32_t start, int32_t end) override;
+  void AdjustSelectionByCharacterOffset(
+      int32_t start,
+      int32_t end,
+      blink::mojom::SelectionMenuBehavior selection_menu_behavior) override;
   void MoveRangeSelectionExtent(const gfx::Point& extent) override;
   void ScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect) override;
   void MoveCaret(const gfx::Point& point) override;
diff --git a/content/renderer/media/media_stream_center.cc b/content/renderer/media/media_stream_center.cc
index 98c0776..7e1f32d 100644
--- a/content/renderer/media/media_stream_center.cc
+++ b/content/renderer/media/media_stream_center.cc
@@ -199,4 +199,14 @@
     DidStopMediaStreamTrack(video_tracks[i]);
 }
 
+void MediaStreamCenter::DidStopMediaStreamSource(
+    const blink::WebMediaStreamSource& web_source) {
+  if (web_source.IsNull())
+    return;
+  MediaStreamSource* const source =
+      static_cast<MediaStreamSource*>(web_source.GetExtraData());
+  DCHECK(source);
+  source->StopSource();
+}
+
 }  // namespace content
diff --git a/content/renderer/media/media_stream_center.h b/content/renderer/media/media_stream_center.h
index 8365024..871dc84 100644
--- a/content/renderer/media/media_stream_center.h
+++ b/content/renderer/media/media_stream_center.h
@@ -54,6 +54,9 @@
   blink::WebAudioSourceProvider* CreateWebAudioSourceFromMediaStreamTrack(
       const blink::WebMediaStreamTrack& track) override;
 
+  void DidStopMediaStreamSource(
+      const blink::WebMediaStreamSource& web_source) override;
+
   DISALLOW_COPY_AND_ASSIGN(MediaStreamCenter);
 };
 
diff --git a/content/renderer/media/media_stream_dispatcher_unittest.cc b/content/renderer/media/media_stream_dispatcher_unittest.cc
index 7475c52..88c7fd3 100644
--- a/content/renderer/media/media_stream_dispatcher_unittest.cc
+++ b/content/renderer/media/media_stream_dispatcher_unittest.cc
@@ -368,7 +368,7 @@
   EXPECT_EQ(dispatcher_->video_session_id(stream_label1, 0),
             MediaStreamDevice::kNoId);
 
-  // Verify that the request has been completed.
+  // Verify that the request have been completed.
   EXPECT_EQ(dispatcher_->label_stream_map_.size(), 0u);
   EXPECT_EQ(dispatcher_->requests_.size(), 0u);
 }
diff --git a/content/renderer/media_capture_from_element/html_audio_element_capturer_source.cc b/content/renderer/media_capture_from_element/html_audio_element_capturer_source.cc
index fe9a41e..f6b4444 100644
--- a/content/renderer/media_capture_from_element/html_audio_element_capturer_source.cc
+++ b/content/renderer/media_capture_from_element/html_audio_element_capturer_source.cc
@@ -30,7 +30,8 @@
       is_started_(false),
       last_sample_rate_(0),
       last_num_channels_(0),
-      last_bus_frames_(0) {
+      last_bus_frames_(0),
+      weak_factory_(this) {
   DCHECK(audio_source_);
 }
 
@@ -42,13 +43,22 @@
 bool HtmlAudioElementCapturerSource::EnsureSourceIsStarted() {
   DCHECK(thread_checker_.CalledOnValidThread());
   if (audio_source_ && !is_started_) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::Bind(&HtmlAudioElementCapturerSource::SetAudioCallback,
+                              weak_factory_.GetWeakPtr()));
+    is_started_ = true;
+  }
+  return is_started_;
+}
+
+void HtmlAudioElementCapturerSource::SetAudioCallback() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (audio_source_ && is_started_) {
     // base:Unretained() is safe here since EnsureSourceIsStopped() guarantees
     // no more calls to OnAudioBus().
     audio_source_->SetCopyAudioCallback(base::Bind(
         &HtmlAudioElementCapturerSource::OnAudioBus, base::Unretained(this)));
-    is_started_ = true;
   }
-  return is_started_;
 }
 
 void HtmlAudioElementCapturerSource::EnsureSourceIsStopped() {
diff --git a/content/renderer/media_capture_from_element/html_audio_element_capturer_source.h b/content/renderer/media_capture_from_element/html_audio_element_capturer_source.h
index fd5e0ad..5ad7cd3 100644
--- a/content/renderer/media_capture_from_element/html_audio_element_capturer_source.h
+++ b/content/renderer/media_capture_from_element/html_audio_element_capturer_source.h
@@ -40,6 +40,7 @@
   // MediaStreamAudioSource implementation.
   bool EnsureSourceIsStarted() final;
   void EnsureSourceIsStopped() final;
+  void SetAudioCallback();
 
   // To act as an WebAudioSourceProviderImpl::CopyAudioCB.
   void OnAudioBus(std::unique_ptr<media::AudioBus> audio_bus,
@@ -55,6 +56,8 @@
 
   base::ThreadChecker thread_checker_;
 
+  base::WeakPtrFactory<HtmlAudioElementCapturerSource> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(HtmlAudioElementCapturerSource);
 };
 
diff --git a/content/renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc b/content/renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc
index 444fc3094..170683a 100644
--- a/content/renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc
+++ b/content/renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc
@@ -72,24 +72,8 @@
             &media_log_)) {}
 
   void SetUp() final {
-    const media::AudioParameters params(
-        media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
-        media::GuessChannelLayout(kNumChannelsForTest),
-        kAudioTrackSampleRate /* sample_rate */, 16 /* bits_per_sample */,
-        kAudioTrackSamplesPerBuffer /* frames_per_buffer */);
-    audio_source_->Initialize(params, &fake_callback_);
-
-    blink_audio_source_.Initialize(blink::WebString::FromUTF8("audio_id"),
-                                   blink::WebMediaStreamSource::kTypeAudio,
-                                   blink::WebString::FromUTF8("audio_track"),
-                                   false /* remote */);
-    blink_audio_track_.Initialize(blink_audio_source_.Id(),
-                                  blink_audio_source_);
-
-    // |blink_audio_source_| takes ownership of HtmlAudioElementCapturerSource.
-    blink_audio_source_.SetExtraData(
-        new HtmlAudioElementCapturerSource(audio_source_.get()));
-    ASSERT_TRUE(source()->ConnectToTrack(blink_audio_track_));
+    SetUpAudioTrack();
+    base::RunLoop().RunUntilIdle();
   }
 
   void TearDown() override {
@@ -112,6 +96,27 @@
   }
 
  protected:
+  void SetUpAudioTrack() {
+    const media::AudioParameters params(
+        media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+        media::GuessChannelLayout(kNumChannelsForTest),
+        kAudioTrackSampleRate /* sample_rate */, 16 /* bits_per_sample */,
+        kAudioTrackSamplesPerBuffer /* frames_per_buffer */);
+    audio_source_->Initialize(params, &fake_callback_);
+
+    blink_audio_source_.Initialize(blink::WebString::FromUTF8("audio_id"),
+                                   blink::WebMediaStreamSource::kTypeAudio,
+                                   blink::WebString::FromUTF8("audio_track"),
+                                   false /* remote */);
+    blink_audio_track_.Initialize(blink_audio_source_.Id(),
+                                  blink_audio_source_);
+
+    // |blink_audio_source_| takes ownership of HtmlAudioElementCapturerSource.
+    blink_audio_source_.SetExtraData(
+        new HtmlAudioElementCapturerSource(audio_source_.get()));
+    ASSERT_TRUE(source()->ConnectToTrack(blink_audio_track_));
+  }
+
   const base::test::ScopedTaskEnvironment scoped_task_environment_;
 
   blink::WebMediaStreamSource blink_audio_source_;
@@ -155,4 +160,36 @@
   track()->RemoveSink(&sink);
 }
 
+// When a new source is created and started, it is stopped in the same task
+// when cross-origin data is detected. This test checks that no data is
+// delivered in this case.
+TEST_F(HTMLAudioElementCapturerSourceTest,
+       StartAndStopInSameTaskCapturesZeroFrames) {
+  InSequence s;
+
+  // Stop the original track and start a new one so that it can be stopped in
+  // in the same task.
+  track()->Stop();
+  base::RunLoop().RunUntilIdle();
+  SetUpAudioTrack();
+
+  MockMediaStreamAudioSink sink;
+  track()->AddSink(&sink);
+  EXPECT_CALL(
+      sink,
+      OnData(AllOf(Property(&media::AudioBus::channels, kNumChannelsForTest),
+                   Property(&media::AudioBus::frames,
+                            kAudioTrackSamplesPerBuffer)),
+             _))
+      .Times(0);
+
+  std::unique_ptr<media::AudioBus> bus =
+      media::AudioBus::Create(kNumChannelsForTest, kAudioTrackSamplesPerBuffer);
+  InjectAudio(bus.get());
+
+  track()->Stop();
+  base::RunLoop().RunUntilIdle();
+  track()->RemoveSink(&sink);
+}
+
 }  // namespace content
diff --git a/content/renderer/media_capture_from_element/html_video_element_capturer_source.cc b/content/renderer/media_capture_from_element/html_video_element_capturer_source.cc
index 6cd27bf..1dfb24a 100644
--- a/content/renderer/media_capture_from_element/html_video_element_capturer_source.cc
+++ b/content/renderer/media_capture_from_element/html_video_element_capturer_source.cc
@@ -145,24 +145,23 @@
   scoped_refptr<media::VideoFrame> frame = frame_pool_.CreateFrame(
       media::PIXEL_FORMAT_I420, resolution, gfx::Rect(resolution), resolution,
       base::TimeTicks::Now() - base::TimeTicks());
-  DCHECK(frame);
 
   const uint32 source_pixel_format =
       (kN32_SkColorType == kRGBA_8888_SkColorType) ? libyuv::FOURCC_ABGR
                                                    : libyuv::FOURCC_ARGB;
 
-  if (libyuv::ConvertToI420(
-          static_cast<uint8*>(bitmap_.getPixels()), bitmap_.getSize(),
-          frame->visible_data(media::VideoFrame::kYPlane),
-          frame->stride(media::VideoFrame::kYPlane),
-          frame->visible_data(media::VideoFrame::kUPlane),
-          frame->stride(media::VideoFrame::kUPlane),
-          frame->visible_data(media::VideoFrame::kVPlane),
-          frame->stride(media::VideoFrame::kVPlane), 0 /* crop_x */,
-          0 /* crop_y */, frame->visible_rect().size().width(),
-          frame->visible_rect().size().height(), bitmap_.info().width(),
-          bitmap_.info().height(), libyuv::kRotate0,
-          source_pixel_format) == 0) {
+  if (frame && libyuv::ConvertToI420(
+                   static_cast<uint8*>(bitmap_.getPixels()), bitmap_.getSize(),
+                   frame->visible_data(media::VideoFrame::kYPlane),
+                   frame->stride(media::VideoFrame::kYPlane),
+                   frame->visible_data(media::VideoFrame::kUPlane),
+                   frame->stride(media::VideoFrame::kUPlane),
+                   frame->visible_data(media::VideoFrame::kVPlane),
+                   frame->stride(media::VideoFrame::kVPlane), 0 /* crop_x */,
+                   0 /* crop_y */, frame->visible_rect().size().width(),
+                   frame->visible_rect().size().height(),
+                   bitmap_.info().width(), bitmap_.info().height(),
+                   libyuv::kRotate0, source_pixel_format) == 0) {
     // Success!
     io_task_runner_->PostTask(
         FROM_HERE, base::BindOnce(new_frame_callback_, frame, current_time));
diff --git a/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc b/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc
index 696527e..750a1f3 100644
--- a/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc
+++ b/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc
@@ -118,7 +118,7 @@
 // and its inner object(s). This is a non trivial sequence.
 TEST_F(HTMLVideoElementCapturerSourceTest, ConstructAndDestruct) {}
 
-// Checks that the usual sequence of GetCurrentSupportedFormats() ->
+// Checks that the usual sequence of GetPreferredFormats() ->
 // StartCapture() -> StopCapture() works as expected and let it capture two
 // frames.
 TEST_F(HTMLVideoElementCapturerSourceTest, GetFormatsAndStartAndStop) {
@@ -155,4 +155,36 @@
   Mock::VerifyAndClearExpectations(this);
 }
 
+// When a new source is created and started, it is stopped in the same task
+// when cross-origin data is detected. This test checks that no data is
+// delivered in this case.
+TEST_F(HTMLVideoElementCapturerSourceTest,
+       StartAndStopInSameTaskCaptureZeroFrames) {
+  InSequence s;
+  media::VideoCaptureFormats formats =
+      html_video_capturer_->GetPreferredFormats();
+  ASSERT_EQ(1u, formats.size());
+  EXPECT_EQ(web_media_player_->NaturalSize().width,
+            formats[0].frame_size.width());
+  EXPECT_EQ(web_media_player_->NaturalSize().height,
+            formats[0].frame_size.height());
+
+  media::VideoCaptureParams params;
+  params.requested_format = formats[0];
+
+  EXPECT_CALL(*this, DoOnRunning(true)).Times(1);
+  EXPECT_CALL(*this, DoOnDeliverFrame(_, _)).Times(0);
+
+  html_video_capturer_->StartCapture(
+      params,
+      base::Bind(&HTMLVideoElementCapturerSourceTest::OnDeliverFrame,
+                 base::Unretained(this)),
+      base::Bind(&HTMLVideoElementCapturerSourceTest::OnRunning,
+                 base::Unretained(this)));
+  html_video_capturer_->StopCapture();
+  base::RunLoop().RunUntilIdle();
+
+  Mock::VerifyAndClearExpectations(this);
+}
+
 }  // namespace content
diff --git a/content/renderer/media_recorder/media_recorder_handler_unittest.cc b/content/renderer/media_recorder/media_recorder_handler_unittest.cc
index 59320413..6b5b6878 100644
--- a/content/renderer/media_recorder/media_recorder_handler_unittest.cc
+++ b/content/renderer/media_recorder/media_recorder_handler_unittest.cc
@@ -258,7 +258,7 @@
   Mock::VerifyAndClearExpectations(this);
 
   {
-    const size_t kEncodedSizeThreshold = 13;
+    const size_t kEncodedSizeThreshold = 12;
     base::RunLoop run_loop;
     base::Closure quit_closure = run_loop.QuitClosure();
     // The second time around writeData() is called a number of times to write
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 584ee75..a1d37953 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -294,6 +294,7 @@
 using blink::WebUserGestureIndicator;
 using blink::WebVector;
 using blink::WebView;
+using blink::mojom::SelectionMenuBehavior;
 
 #if defined(OS_ANDROID)
 using blink::WebFloatPoint;
@@ -2004,8 +2005,10 @@
                       render_view_->ConvertWindowPointToViewport(extent));
 }
 
-void RenderFrameImpl::OnAdjustSelectionByCharacterOffset(int start_adjust,
-                                                         int end_adjust) {
+void RenderFrameImpl::OnAdjustSelectionByCharacterOffset(
+    int start_adjust,
+    int end_adjust,
+    bool show_selection_menu) {
   WebRange range = frame_->GetInputMethodController()->GetSelectionOffsets();
   if (range.IsNull())
     return;
@@ -2023,7 +2026,9 @@
   // the document.
   frame_->SelectRange(WebRange(range.StartOffset() + start_adjust,
                                range.length() + end_adjust - start_adjust),
-                      WebLocalFrame::kPreserveHandleVisibility);
+                      WebLocalFrame::kPreserveHandleVisibility,
+                      show_selection_menu ? SelectionMenuBehavior::kShow
+                                          : SelectionMenuBehavior::kHide);
 }
 
 void RenderFrameImpl::OnCollapseSelection() {
@@ -2034,7 +2039,9 @@
 
   AutoResetMember<bool> handling_select_range(
       this, &RenderFrameImpl::handling_select_range_, true);
-  frame_->SelectRange(WebRange(range.EndOffset(), 0));
+  frame_->SelectRange(WebRange(range.EndOffset(), 0),
+                      WebLocalFrame::kHideSelectionHandle,
+                      SelectionMenuBehavior::kHide);
 }
 
 void RenderFrameImpl::OnMoveRangeSelectionExtent(const gfx::Point& point) {
@@ -2520,8 +2527,14 @@
   // TODO(alexmos, mkwst, arthursonzogni): This block can be removed once error
   // pages are refactored. See crbug.com/588314 and crbug.com/622385.
   if (error.reason == net::ERR_BLOCKED_BY_RESPONSE) {
+    // Do not preserve the history item for blocked navigations, since we will
+    // not attempt to reload it later.  Also, it is important that the document
+    // sequence number is not preserved, so that other navigations will not be
+    // considered same-document with this data URL.
+    const blink::WebHistoryItem& blank_history_item = blink::WebHistoryItem();
+    frame_load_type = blink::WebFrameLoadType::kStandard;
     LoadNavigationErrorPageInternal("", GURL("data:,"), WebURL(), replace,
-                                    frame_load_type, history_item);
+                                    frame_load_type, blank_history_item);
     return;
   }
 
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 858f11fe..dd921b6 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -923,7 +923,9 @@
   void OnDelete();
   void OnSelectAll();
   void OnSelectRange(const gfx::Point& base, const gfx::Point& extent);
-  void OnAdjustSelectionByCharacterOffset(int start_adjust, int end_adjust);
+  void OnAdjustSelectionByCharacterOffset(int start_adjust,
+                                          int end_adjust,
+                                          bool show_selection_menu);
   void OnCollapseSelection();
   void OnMoveRangeSelectionExtent(const gfx::Point& point);
   void OnReplace(const base::string16& text);
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc
index a5d43cb..c66bcbe 100644
--- a/content/renderer/render_frame_proxy.cc
+++ b/content/renderer/render_frame_proxy.cc
@@ -218,6 +218,8 @@
       *base::CommandLine::ForCurrentProcess();
   enable_surface_synchronization_ =
       command_line.HasSwitch(switches::kEnableSurfaceSynchronization);
+  compositing_helper_.reset(
+      ChildFrameCompositingHelper::CreateForRenderFrameProxy(this));
 }
 
 void RenderFrameProxy::ResendFrameRects() {
@@ -228,7 +230,7 @@
 }
 
 void RenderFrameProxy::WillBeginCompositorFrame() {
-  if (compositing_helper_ && compositing_helper_->surface_id().is_valid()) {
+  if (compositing_helper_->surface_id().is_valid()) {
     FrameHostMsg_HittestData_Params params;
     params.surface_id = compositing_helper_->surface_id();
     params.ignored_for_hittest = web_frame_->IsIgnoredForHitTest();
@@ -335,8 +337,7 @@
 }
 
 void RenderFrameProxy::OnChildFrameProcessGone() {
-  if (compositing_helper_)
-    compositing_helper_->ChildFrameGone();
+  compositing_helper_->ChildFrameGone();
 }
 
 void RenderFrameProxy::OnSetChildFrameSurface(
@@ -349,25 +350,6 @@
   if (!web_frame()->Parent())
     return;
 
-  if (!compositing_helper_) {
-    compositing_helper_.reset(
-        ChildFrameCompositingHelper::CreateForRenderFrameProxy(this));
-    if (enable_surface_synchronization_) {
-      // We wait until there is a single CompositorFrame guaranteed to be
-      // available and ready for display in the display compositor before using
-      // surface synchronization. This guarantees that we will have something to
-      // display when the compositor goes to produce a display frame.
-      //
-      // Once there's an available fallback surface that can be employed, then
-      // the primary surface is updated as soon as the frame rect changes.
-      //
-      // The compositor will attempt to composite the primary surface within a
-      // give deadline (4 frames is the default). If the primary surface isn't
-      // available for four frames, then the fallback surface will be used.
-      compositing_helper_->SetPrimarySurfaceInfo(surface_info);
-    }
-  }
-
   if (!enable_surface_synchronization_)
     compositing_helper_->SetPrimarySurfaceInfo(surface_info);
   compositing_helper_->SetFallbackSurfaceInfo(surface_info, sequence);
@@ -544,8 +526,7 @@
   gfx::Rect rect = frame_rect;
   if (frame_rect_.size() != rect.size() || !local_surface_id_.is_valid()) {
     local_surface_id_ = local_surface_id_allocator_.GenerateId();
-    if (compositing_helper_ && enable_surface_synchronization_ &&
-        frame_sink_id_.is_valid()) {
+    if (enable_surface_synchronization_ && frame_sink_id_.is_valid()) {
       float device_scale_factor =
           render_widget()->GetOriginalDeviceScaleFactor();
       viz::SurfaceInfo surface_info(
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc
index b8695ecd..365cedef8 100644
--- a/content/renderer/service_worker/service_worker_context_client.cc
+++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -25,7 +25,6 @@
 #include "content/child/service_worker/service_worker_handle_reference.h"
 #include "content/child/service_worker/service_worker_network_provider.h"
 #include "content/child/service_worker/service_worker_provider_context.h"
-#include "content/child/service_worker/service_worker_registration_handle_reference.h"
 #include "content/child/service_worker/web_service_worker_impl.h"
 #include "content/child/service_worker/web_service_worker_provider_impl.h"
 #include "content/child/service_worker/web_service_worker_registration_impl.h"
@@ -774,7 +773,8 @@
 
   blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration_info;
   ServiceWorkerVersionAttributes version_attrs;
-  provider_context_->GetRegistration(&registration_info, &version_attrs);
+  provider_context_->TakeRegistrationForServiceWorkerGlobalScope(
+      &registration_info, &version_attrs);
   DCHECK_NE(registration_info->registration_id,
             blink::mojom::kInvalidServiceWorkerRegistrationId);
 
diff --git a/content/shell/app/shell_main_delegate.cc b/content/shell/app/shell_main_delegate.cc
index 5880dc4..b5cba54b 100644
--- a/content/shell/app/shell_main_delegate.cc
+++ b/content/shell/app/shell_main_delegate.cc
@@ -103,10 +103,16 @@
         { 0x84, 0x13, 0xec, 0x94, 0xd8, 0xc2, 0xa4, 0xb6 } };
 #endif
 
-void InitLogging() {
+void InitLogging(const base::CommandLine& command_line) {
   base::FilePath log_filename;
-  PathService::Get(base::DIR_EXE, &log_filename);
-  log_filename = log_filename.AppendASCII("content_shell.log");
+  std::string filename = command_line.GetSwitchValueASCII(switches::kLogFile);
+  if (filename.empty()) {
+    PathService::Get(base::DIR_EXE, &log_filename);
+    log_filename = log_filename.AppendASCII("content_shell.log");
+  } else {
+    log_filename = base::FilePath::FromUTF8Unsafe(filename);
+  }
+
   logging::LoggingSettings settings;
   settings.logging_dest = logging::LOG_TO_ALL;
   settings.log_file = log_filename.value().c_str();
@@ -149,7 +155,7 @@
   EnsureCorrectResolutionSettings();
 #endif  // OS_MACOSX
 
-  InitLogging();
+  InitLogging(command_line);
   if (command_line.HasSwitch(switches::kCheckLayoutTestSysDeps)) {
     // If CheckLayoutSystemDeps succeeds, we don't exit early. Instead we
     // continue and try to load the fonts in BlinkTestPlatformInitialize
diff --git a/content/shell/test_runner/event_sender.cc b/content/shell/test_runner/event_sender.cc
index e4cb5d03..b5ad2166 100644
--- a/content/shell/test_runner/event_sender.cc
+++ b/content/shell/test_runner/event_sender.cc
@@ -2078,6 +2078,10 @@
 }
 
 void EventSender::AddTouchPoint(float x, float y, gin::Arguments* args) {
+  if (touch_points_.size() == WebTouchEvent::kTouchesLengthCap) {
+    args->ThrowError();
+    return;
+  }
   WebTouchPoint touch_point;
   touch_point.pointer_type = WebPointerProperties::PointerType::kTouch;
   touch_point.state = WebTouchPoint::kStatePressed;
@@ -2278,8 +2282,8 @@
                                         gin::Arguments* args) {
   uint32_t unique_touch_event_id = GetUniqueTouchEventId(args);
 
-  DCHECK_GT(static_cast<unsigned>(WebTouchEvent::kTouchesLengthCap),
-            touch_points_.size());
+  DCHECK_LE(touch_points_.size(),
+            static_cast<unsigned>(WebTouchEvent::kTouchesLengthCap));
   if (force_layout_on_events_)
     widget()->UpdateAllLifecyclePhases();
 
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index da04534..302c7f9 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1574,6 +1574,7 @@
     "//components/offline_pages/features:features",
     "//components/rappor:test_support",
     "//components/ukm:test_support",
+    "//components/viz/client",
     "//components/viz/common",
     "//components/viz/host",
     "//components/viz/service",
diff --git a/content/test/data/accessibility/aria/aria-heading-expected-android.txt b/content/test/data/accessibility/aria/aria-heading-expected-android.txt
index 1c07bf5..bac12840 100644
--- a/content/test/data/accessibility/aria/aria-heading-expected-android.txt
+++ b/content/test/data/accessibility/aria/aria-heading-expected-android.txt
@@ -6,4 +6,4 @@
 ++android.view.View role_description='heading 5' heading name='ARIA Heading 5'
 ++android.view.View role_description='heading 6' heading name='ARIA Heading 6'
 ++android.view.View
-++++android.view.View role_description='heading' heading name='Heading'
\ No newline at end of file
+++++android.view.View role_description='heading 2' heading name='Heading'
\ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-heading-expected-blink.txt b/content/test/data/accessibility/aria/aria-heading-expected-blink.txt
index 2633076c..4006449 100644
--- a/content/test/data/accessibility/aria/aria-heading-expected-blink.txt
+++ b/content/test/data/accessibility/aria/aria-heading-expected-blink.txt
@@ -18,6 +18,6 @@
 ++++staticText name='ARIA Heading 6'
 ++++++inlineTextBox name='ARIA Heading 6'
 ++genericContainer
-++++heading name='Heading'
+++++heading name='Heading' hierarchicalLevel=2
 ++++++staticText name='Heading'
 ++++++++inlineTextBox name='Heading'
\ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-heading-expected-mac.txt b/content/test/data/accessibility/aria/aria-heading-expected-mac.txt
index a8d8151..aab26d1f 100644
--- a/content/test/data/accessibility/aria/aria-heading-expected-mac.txt
+++ b/content/test/data/accessibility/aria/aria-heading-expected-mac.txt
@@ -12,5 +12,5 @@
 ++AXHeading AXTitle='ARIA Heading 6' AXValue='6'
 ++++AXStaticText AXValue='ARIA Heading 6'
 ++AXGroup
-++++AXHeading AXTitle='Heading'
+++++AXHeading AXTitle='Heading' AXValue='2'
 ++++++AXStaticText AXValue='Heading'
\ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-heading-expected-win.txt b/content/test/data/accessibility/aria/aria-heading-expected-win.txt
index 454e413..5aedd92 100644
--- a/content/test/data/accessibility/aria/aria-heading-expected-win.txt
+++ b/content/test/data/accessibility/aria/aria-heading-expected-win.txt
@@ -12,5 +12,5 @@
 ++IA2_ROLE_HEADING name='ARIA Heading 6' xml-roles:heading level:6
 ++++ROLE_SYSTEM_STATICTEXT name='ARIA Heading 6'
 ++IA2_ROLE_SECTION
-++++IA2_ROLE_HEADING name='Heading' xml-roles:heading
+++++IA2_ROLE_HEADING name='Heading' xml-roles:heading level:2
 ++++++ROLE_SYSTEM_STATICTEXT name='Heading'
diff --git a/content/test/data/accessibility/html/input-text-value.html b/content/test/data/accessibility/html/input-text-value.html
index cc211a8..9db750a 100644
--- a/content/test/data/accessibility/html/input-text-value.html
+++ b/content/test/data/accessibility/html/input-text-value.html
@@ -2,7 +2,7 @@
 @WIN-ALLOW:description*
 @WIN-ALLOW:IA2_STATE_MULTI_LINE
 @BLINK-ALLOW:description*
-@BLINK-ALLOW:focus*
+@BLINK-ALLOW:focusable*
 @BLINK-ALLOW:multiline
 -->
 <html>
diff --git a/content/test/data/accessibility/html/label-updates-expected-blink.txt b/content/test/data/accessibility/html/label-updates-expected-blink.txt
index 3dd86474..588b6a5 100644
--- a/content/test/data/accessibility/html/label-updates-expected-blink.txt
+++ b/content/test/data/accessibility/html/label-updates-expected-blink.txt
@@ -1,3 +1,4 @@
 rootWebArea
 ++genericContainer
 ++++textField name='oranges'
+++++textField name='bananas'
diff --git a/content/test/data/accessibility/html/label-updates.html b/content/test/data/accessibility/html/label-updates.html
index 112e05b..4cce4ff 100644
--- a/content/test/data/accessibility/html/label-updates.html
+++ b/content/test/data/accessibility/html/label-updates.html
@@ -1,18 +1,26 @@
 <!--
-@WAIT-FOR:oranges
+@WAIT-FOR:bananas
 @BLINK-DENY:nameFrom*
 -->
 <!DOCTYPE html>
 <html>
 <body>
-  <input id="input">
-  <label id="label" aria-hidden="true" for="input"><span><span>apples</span></span></label>
+  <input id="input1">
+  <label id="label1" aria-hidden="true" for="input1"><span><span>apples</span></span></label>
+
+  <input id="input2">
+  <label id="label2" aria-hidden="true" for="input2">grapes</label>
 </div>
 
 <script>
   setTimeout(() => {
-    const label = document.getElementById('label');
-    label.firstElementChild.firstElementChild.innerText = 'oranges';
+    const label1 = document.getElementById('label1');
+    label1.firstElementChild.firstElementChild.innerText = 'oranges';
+
+    const label2 = document.getElementById('label2');
+    const text2 = label2.firstChild;
+    text2.deleteData(0,5);  // Delete 'grape'
+    text2.insertData(0,'banana');  // Text should now be 'bananas'
   }, 100);
 </script>
 </body>
diff --git a/content/test/data/accessibility/html/replace-data-expected-blink.txt b/content/test/data/accessibility/html/replace-data-expected-blink.txt
new file mode 100644
index 0000000..66f88a4f
--- /dev/null
+++ b/content/test/data/accessibility/html/replace-data-expected-blink.txt
@@ -0,0 +1,7 @@
+rootWebArea
+++paragraph
+++++staticText name='apples'
+++++++inlineTextBox name='apples'
+++paragraph
+++++staticText name='bananas'
+++++++inlineTextBox name='bananas'
\ No newline at end of file
diff --git a/content/test/data/accessibility/html/replace-data.html b/content/test/data/accessibility/html/replace-data.html
new file mode 100644
index 0000000..dbd92551
--- /dev/null
+++ b/content/test/data/accessibility/html/replace-data.html
@@ -0,0 +1,23 @@
+<!--
+@WAIT-FOR:bananas
+@BLINK-DENY:nameFrom*
+-->
+<!DOCTYPE html>
+<html>
+<body>
+  <p id="text1">oranges</label>
+  <p id="text2"><span><span>grapes</span></span></label>
+</div>
+
+<script>
+  setTimeout(() => {
+    const text1 = document.getElementById('text1');
+    text1.firstChild.replaceData(0,5, 'appl'); // oranges -> apples
+
+    const text2 = document.getElementById('text2');
+    var text2data = text2.firstElementChild.firstElementChild.firstChild;
+    text2data.replaceData(0, 5, 'banana');  // grapes -> bananas
+  }, 100);
+</script>
+</body>
+</html>
diff --git a/content/test/fuzzer/BUILD.gn b/content/test/fuzzer/BUILD.gn
index 37db2da..63d8988 100644
--- a/content/test/fuzzer/BUILD.gn
+++ b/content/test/fuzzer/BUILD.gn
@@ -11,80 +11,77 @@
 group("fuzzer") {
 }
 
-# gn complains of private dependencies in component build.
-if (!is_component_build) {
-  source_set("fuzzer_support") {
-    sources = [
-      "fuzzer_support.cc",
-      "fuzzer_support.h",
-    ]
-    public_deps = [
-      "//base",
-      "//content/renderer:for_content_tests",
-      "//content/shell:content_shell_lib",
-      "//content/test:test_support",
-      "//gin",
-    ]
-    testonly = true
-  }
+source_set("fuzzer_support") {
+  sources = [
+    "fuzzer_support.cc",
+    "fuzzer_support.h",
+  ]
+  public_deps = [
+    "//base",
+    "//content/renderer:for_content_tests",
+    "//content/shell:content_shell_lib",
+    "//content/test:test_support",
+    "//gin",
+  ]
+  testonly = true
+}
 
-  fuzzer_test("origin_trial_token_fuzzer") {
-    sources = [
-      "origin_trial_token_fuzzer.cc",
-    ]
-    deps = [
-      ":fuzzer_support",
-    ]
-    dict =
-        "//content/test/data/fuzzer_dictionaries/origin_trial_token_fuzzer.dict"
-    seed_corpus = "//content/test/data/fuzzer_corpus/origin_trial_token_data/"
-  }
+fuzzer_test("origin_trial_token_fuzzer") {
+  sources = [
+    "origin_trial_token_fuzzer.cc",
+  ]
+  deps = [
+    ":fuzzer_support",
+  ]
+  dict =
+      "//content/test/data/fuzzer_dictionaries/origin_trial_token_fuzzer.dict"
+  seed_corpus = "//content/test/data/fuzzer_corpus/origin_trial_token_data/"
+}
 
-  fuzzer_test("renderer_fuzzer") {
-    sources = [
-      "renderer_fuzzer.cc",
-    ]
-    deps = [
-      ":fuzzer_support",
-    ]
-  }
+fuzzer_test("renderer_fuzzer") {
+  sources = [
+    "renderer_fuzzer.cc",
+  ]
+  deps = [
+    ":fuzzer_support",
+  ]
+}
 
-  fuzzer_test("renderer_tree_fuzzer") {
-    sources = [
-      "renderer_tree_fuzzer.cc",
-    ]
-    deps = [
-      ":fuzzer_support",
-    ]
-  }
+fuzzer_test("renderer_tree_fuzzer") {
+  sources = [
+    "renderer_tree_fuzzer.cc",
+  ]
+  deps = [
+    ":fuzzer_support",
+  ]
+}
 
-  fuzzer_test("clear_site_data_fuzzer") {
-    sources = [
-      "clear_site_data_fuzzer.cc",
-    ]
-    deps = [
-      ":fuzzer_support",
-      "//base",
-      "//content/browser:for_content_tests",
-    ]
-    seed_corpus = "//content/test/data/fuzzer_corpus/clear_site_data/"
-  }
+fuzzer_test("clear_site_data_fuzzer") {
+  sources = [
+    "clear_site_data_fuzzer.cc",
+  ]
+  deps = [
+    ":fuzzer_support",
+    "//base",
+    "//content/browser:for_content_tests",
+  ]
+  seed_corpus = "//content/test/data/fuzzer_corpus/clear_site_data/"
+}
 
-  fuzzer_test("renderer_proto_tree_fuzzer") {
-    sources = [
-      "renderer_proto_tree_fuzzer.cc",
-    ]
-    deps = [
-      ":fuzzer_support",
-      ":html_tree_proto",
-      "//third_party/libprotobuf-mutator",
-    ]
-  }
+fuzzer_test("renderer_proto_tree_fuzzer") {
+  sources = [
+    "renderer_proto_tree_fuzzer.cc",
+  ]
+  deps = [
+    ":fuzzer_support",
+    ":html_tree_proto",
+    "//third_party/libprotobuf-mutator",
+  ]
+}
 
-  proto_library("html_tree_proto") {
-    sources = [
-      "html_tree.proto",
-    ]
-    testonly = true
-  }
+proto_library("html_tree_proto") {
+  sources = [
+    "html_tree.proto",
+  ]
+  testonly = true
 }
diff --git a/content/test/fuzzer/clear_site_data_fuzzer.cc b/content/test/fuzzer/clear_site_data_fuzzer.cc
index 30847f3..d3134f2 100644
--- a/content/test/fuzzer/clear_site_data_fuzzer.cc
+++ b/content/test/fuzzer/clear_site_data_fuzzer.cc
@@ -6,7 +6,7 @@
 #include <stdint.h>
 #include <string>
 
-#include "content/browser/browsing_data/clear_site_data_throttle.h"
+#include "content/browser/browsing_data/clear_site_data_throttle.h"  // nogncheck
 
 namespace content {
 
diff --git a/content/test/test_web_contents.cc b/content/test/test_web_contents.cc
index a4c79dba..1cafe12 100644
--- a/content/test/test_web_contents.cc
+++ b/content/test/test_web_contents.cc
@@ -4,7 +4,9 @@
 
 #include "content/test/test_web_contents.h"
 
+#include <memory>
 #include <utility>
+#include <vector>
 
 #include "content/browser/browser_url_handler_impl.h"
 #include "content/browser/frame_host/cross_process_frame_connector.h"
@@ -51,7 +53,7 @@
   EXPECT_FALSE(expect_set_history_offset_and_length_);
 }
 
-TestRenderFrameHost* TestWebContents::GetMainFrame() {
+TestRenderFrameHost* TestWebContents::GetMainFrame() const {
   return static_cast<TestRenderFrameHost*>(WebContentsImpl::GetMainFrame());
 }
 
diff --git a/content/test/test_web_contents.h b/content/test/test_web_contents.h
index 899e5e3..0fc604e 100644
--- a/content/test/test_web_contents.h
+++ b/content/test/test_web_contents.h
@@ -10,6 +10,7 @@
 #include <list>
 #include <map>
 #include <string>
+#include <utility>
 
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/test/web_contents_tester.h"
@@ -47,7 +48,7 @@
                                  scoped_refptr<SiteInstance> instance);
 
   // WebContentsImpl overrides (returning the same values, but in Test* types)
-  TestRenderFrameHost* GetMainFrame() override;
+  TestRenderFrameHost* GetMainFrame() const override;
   TestRenderViewHost* GetRenderViewHost() const override;
   // Overrides to avoid establishing Mojo connection with renderer process.
   int DownloadImage(const GURL& url,
diff --git a/device/BUILD.gn b/device/BUILD.gn
index facbbe38..6a652203 100644
--- a/device/BUILD.gn
+++ b/device/BUILD.gn
@@ -71,6 +71,7 @@
     "sensors/sensor_manager_android_unittest.cc",
     "sensors/sensor_manager_chromeos_unittest.cc",
     "test/run_all_unittests.cc",
+    "u2f/u2f_ble_frames_unittest.cc",
   ]
 
   deps = [
@@ -90,6 +91,7 @@
     "//device/sensors",
     "//device/sensors/public/cpp:full",
     "//device/sensors/public/interfaces",
+    "//device/u2f",
     "//mojo/common",
     "//mojo/edk/system",
     "//mojo/public/cpp/bindings",
diff --git a/device/bluetooth/bluetooth_l2cap_channel_mac.mm b/device/bluetooth/bluetooth_l2cap_channel_mac.mm
index 77cf7e1..61c0be42 100644
--- a/device/bluetooth/bluetooth_l2cap_channel_mac.mm
+++ b/device/bluetooth/bluetooth_l2cap_channel_mac.mm
@@ -53,13 +53,6 @@
   channel_->OnChannelClosed(l2capChannel);
 }
 
-// These methods are marked as optional in the 10.8 SDK, but not in the 10.6
-// SDK. These empty implementations can be removed once we drop the 10.6 SDK.
-- (void)l2capChannelReconfigured:(IOBluetoothL2CAPChannel*)l2capChannel {
-}
-- (void)l2capChannelQueueSpaceAvailable:(IOBluetoothL2CAPChannel*)l2capChannel {
-}
-
 @end
 
 namespace device {
diff --git a/device/bluetooth/bluetooth_socket_mac.mm b/device/bluetooth/bluetooth_socket_mac.mm
index 9f24a8b..13e31cb 100644
--- a/device/bluetooth/bluetooth_socket_mac.mm
+++ b/device/bluetooth/bluetooth_socket_mac.mm
@@ -33,15 +33,6 @@
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
 
-#if !defined(MAC_OS_X_VERSION_10_7) || \
-    MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7
-
-@interface IOBluetoothDevice (LionSDKDeclarations)
-- (IOReturn)performSDPQuery:(id)target uuids:(NSArray*)uuids;
-@end
-
-#endif  // MAC_OS_X_VERSION_10_7
-
 using device::BluetoothSocket;
 
 // A simple helper class that forwards SDP query completed notifications to its
diff --git a/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom b/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom
index ddaf706a..2cefe4a6 100644
--- a/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom
+++ b/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom
@@ -28,6 +28,20 @@
 
   // Initializes a fake Central with |state| as the initial state.
   SimulateCentral(CentralState state) => (FakeCentral fake_central);
+
+  // Evaluates whether all responses set by this API have been consumed by this
+  // central or otherwise.  This includes responses set by:
+  // - SetNextGATTConnectionResponse
+  // - SetNextGATTDiscoveryResponse
+  // - SetNextReadCharacteristicResponse
+  // - SetNextWriteCharacteristicResponse
+  // - SetNextSubscribeToNotificationsResponse
+  // - SetNextUnsubscribeFromNotificationsResponse
+  // - SetNextReadDescriptorResponse
+  // - SetNextWriteDescriptorResponse
+  // The callback is called with |consumed| set to true if there are no pending
+  // responses.
+  AllResponsesConsumed() => (bool consumed);
 };
 
 // HCI Error Codes from BT 4.2 Vol 2 Part D 1.3 List Of Error Codes.
diff --git a/device/bluetooth/test/fake_bluetooth.cc b/device/bluetooth/test/fake_bluetooth.cc
index 0415676..ec6cb99 100644
--- a/device/bluetooth/test/fake_bluetooth.cc
+++ b/device/bluetooth/test/fake_bluetooth.cc
@@ -41,4 +41,9 @@
   std::move(callback).Run(std::move(fake_central_ptr));
 }
 
+void FakeBluetooth::AllResponsesConsumed(
+    AllResponsesConsumedCallback callback) {
+  std::move(callback).Run(fake_central_->AllResponsesConsumed());
+}
+
 }  // namespace bluetooth
diff --git a/device/bluetooth/test/fake_bluetooth.h b/device/bluetooth/test/fake_bluetooth.h
index 544e25f..ac208f24c 100644
--- a/device/bluetooth/test/fake_bluetooth.h
+++ b/device/bluetooth/test/fake_bluetooth.h
@@ -27,6 +27,7 @@
   void SetLESupported(bool available, SetLESupportedCallback callback) override;
   void SimulateCentral(mojom::CentralState state,
                        SimulateCentralCallback callback) override;
+  void AllResponsesConsumed(AllResponsesConsumedCallback callback) override;
 
  private:
   std::unique_ptr<device::BluetoothAdapterFactory::GlobalValuesForTesting>
diff --git a/device/bluetooth/test/fake_central.cc b/device/bluetooth/test/fake_central.cc
index b042c83..a7e9499 100644
--- a/device/bluetooth/test/fake_central.cc
+++ b/device/bluetooth/test/fake_central.cc
@@ -72,6 +72,16 @@
   std::move(callback).Run(true);
 }
 
+bool FakeCentral::AllResponsesConsumed() {
+  return std::all_of(devices_.begin(), devices_.end(), [](const auto& e) {
+    // static_cast is safe because the parent class's devices_ is only
+    // populated via this FakeCentral, and only with FakePeripherals.
+    FakePeripheral* fake_peripheral =
+        static_cast<FakePeripheral*>(e.second.get());
+    return fake_peripheral->AllResponsesConsumed();
+  });
+}
+
 void FakeCentral::SimulateGATTDisconnection(
     const std::string& address,
     SimulateGATTDisconnectionCallback callback) {
@@ -398,6 +408,8 @@
     return nullptr;
   }
 
+  // static_cast is safe because the parent class's devices_ is only
+  // populated via this FakeCentral, and only with FakePeripherals.
   return static_cast<FakePeripheral*>(device_iter->second.get());
 }
 
@@ -409,6 +421,8 @@
     return nullptr;
   }
 
+  // static_cast is safe because FakePeripheral is only populated with
+  // FakeRemoteGattServices.
   return static_cast<FakeRemoteGattService*>(
       fake_peripheral->GetGattService(service_id));
 }
@@ -423,6 +437,8 @@
     return nullptr;
   }
 
+  // static_cast is safe because FakeRemoteGattService is only populated with
+  // FakeRemoteGattCharacteristics.
   return static_cast<FakeRemoteGattCharacteristic*>(
       fake_remote_gatt_service->GetCharacteristic(characteristic_id));
 }
@@ -439,6 +455,8 @@
     return nullptr;
   }
 
+  // static_cast is safe because FakeRemoteGattCharacteristic is only populated
+  // with FakeRemoteGattDescriptors.
   return static_cast<FakeRemoteGattDescriptor*>(
       fake_remote_gatt_characteristic->GetDescriptor(descriptor_id));
 }
diff --git a/device/bluetooth/test/fake_central.h b/device/bluetooth/test/fake_central.h
index a6e5b92..4fdd3e6 100644
--- a/device/bluetooth/test/fake_central.h
+++ b/device/bluetooth/test/fake_central.h
@@ -42,6 +42,7 @@
       const std::string& address,
       uint16_t code,
       SetNextGATTDiscoveryResponseCallback callback) override;
+  bool AllResponsesConsumed();
   void SimulateGATTDisconnection(
       const std::string& address,
       SimulateGATTDisconnectionCallback callback) override;
diff --git a/device/bluetooth/test/fake_peripheral.cc b/device/bluetooth/test/fake_peripheral.cc
index 949b65f3..d8a197bb 100644
--- a/device/bluetooth/test/fake_peripheral.cc
+++ b/device/bluetooth/test/fake_peripheral.cc
@@ -49,6 +49,16 @@
   next_discovery_response_ = code;
 }
 
+bool FakePeripheral::AllResponsesConsumed() {
+  return !next_connection_response_ && !next_discovery_response_ &&
+         std::all_of(gatt_services_.begin(), gatt_services_.end(),
+                     [](const auto& e) {
+                       FakeRemoteGattService* fake_remote_gatt_service =
+                           static_cast<FakeRemoteGattService*>(e.second.get());
+                       return fake_remote_gatt_service->AllResponsesConsumed();
+                     });
+}
+
 void FakePeripheral::SimulateGATTDisconnection() {
   gatt_services_.clear();
   // TODO(crbug.com/728870): Only set get_connected_ to false once system
diff --git a/device/bluetooth/test/fake_peripheral.h b/device/bluetooth/test/fake_peripheral.h
index 3f3316b..6380708 100644
--- a/device/bluetooth/test/fake_peripheral.h
+++ b/device/bluetooth/test/fake_peripheral.h
@@ -46,6 +46,10 @@
   // after IsGattDiscoveryComplete is called.
   void SetNextGATTDiscoveryResponse(uint16_t code);
 
+  // Returns true if there are no pending responses for this peripheral or any
+  // of its GATT services.
+  bool AllResponsesConsumed();
+
   // Simulates a GATT disconnection from the peripheral.
   void SimulateGATTDisconnection();
 
diff --git a/device/bluetooth/test/fake_remote_gatt_characteristic.cc b/device/bluetooth/test/fake_remote_gatt_characteristic.cc
index 55facb8d..3db3126 100644
--- a/device/bluetooth/test/fake_remote_gatt_characteristic.cc
+++ b/device/bluetooth/test/fake_remote_gatt_characteristic.cc
@@ -80,6 +80,16 @@
   next_subscribe_to_notifications_response_.emplace(gatt_code);
 }
 
+bool FakeRemoteGattCharacteristic::AllResponsesConsumed() {
+  // TODO(crbug.com/569709): Update this when
+  // SetNextUnsubscribeFromNotificationsResponse is implemented.
+  return !next_read_response_ && !next_write_response_ &&
+         !next_subscribe_to_notifications_response_ &&
+         std::all_of(
+             fake_descriptors_.begin(), fake_descriptors_.end(),
+             [](const auto& e) { return e.second->AllResponsesConsumed(); });
+}
+
 std::string FakeRemoteGattCharacteristic::GetIdentifier() const {
   return characteristic_id_;
 }
diff --git a/device/bluetooth/test/fake_remote_gatt_characteristic.h b/device/bluetooth/test/fake_remote_gatt_characteristic.h
index 2c837a7..2367fe9 100644
--- a/device/bluetooth/test/fake_remote_gatt_characteristic.h
+++ b/device/bluetooth/test/fake_remote_gatt_characteristic.h
@@ -54,6 +54,10 @@
   // call its error callback.
   void SetNextSubscribeToNotificationsResponse(uint16_t gatt_code);
 
+  // Returns true if there are no pending responses for this characteristc or
+  // any of its descriptors.
+  bool AllResponsesConsumed();
+
   // Returns the last sucessfully written value to the characteristic. Returns
   // nullopt if no value has been written yet.
   const base::Optional<std::vector<uint8_t>>& last_written_value() {
diff --git a/device/bluetooth/test/fake_remote_gatt_descriptor.cc b/device/bluetooth/test/fake_remote_gatt_descriptor.cc
index b763a92..92f6508 100644
--- a/device/bluetooth/test/fake_remote_gatt_descriptor.cc
+++ b/device/bluetooth/test/fake_remote_gatt_descriptor.cc
@@ -29,6 +29,12 @@
   next_read_response_.emplace(gatt_code, value);
 }
 
+bool FakeRemoteGattDescriptor::AllResponsesConsumed() {
+  // TODO(crbug.com/569709): Update this when SetNextWriteResponse is
+  // implemented.
+  return !next_read_response_;
+}
+
 std::string FakeRemoteGattDescriptor::GetIdentifier() const {
   return descriptor_id_;
 }
diff --git a/device/bluetooth/test/fake_remote_gatt_descriptor.h b/device/bluetooth/test/fake_remote_gatt_descriptor.h
index 74a4881..f188beb 100644
--- a/device/bluetooth/test/fake_remote_gatt_descriptor.h
+++ b/device/bluetooth/test/fake_remote_gatt_descriptor.h
@@ -33,6 +33,9 @@
   void SetNextReadResponse(uint16_t gatt_code,
                            const base::Optional<std::vector<uint8_t>>& value);
 
+  // Returns true if there are no pending responses for this descriptor.
+  bool AllResponsesConsumed();
+
   // device::BluetoothGattDescriptor overrides:
   std::string GetIdentifier() const override;
   device::BluetoothUUID GetUUID() const override;
diff --git a/device/bluetooth/test/fake_remote_gatt_service.cc b/device/bluetooth/test/fake_remote_gatt_service.cc
index a0ff9b2..ef76f44 100644
--- a/device/bluetooth/test/fake_remote_gatt_service.cc
+++ b/device/bluetooth/test/fake_remote_gatt_service.cc
@@ -31,6 +31,12 @@
 
 FakeRemoteGattService::~FakeRemoteGattService() {}
 
+bool FakeRemoteGattService::AllResponsesConsumed() {
+  return std::all_of(
+      fake_characteristics_.begin(), fake_characteristics_.end(),
+      [](const auto& e) { return e.second->AllResponsesConsumed(); });
+}
+
 std::string FakeRemoteGattService::AddFakeCharacteristic(
     const device::BluetoothUUID& characteristic_uuid,
     mojom::CharacteristicPropertiesPtr properties) {
diff --git a/device/bluetooth/test/fake_remote_gatt_service.h b/device/bluetooth/test/fake_remote_gatt_service.h
index 08f60f00..a933ab7 100644
--- a/device/bluetooth/test/fake_remote_gatt_service.h
+++ b/device/bluetooth/test/fake_remote_gatt_service.h
@@ -32,6 +32,9 @@
                         device::BluetoothDevice* device);
   ~FakeRemoteGattService() override;
 
+  // Returns true if there are no pending responses for any characterstics.
+  bool AllResponsesConsumed();
+
   // Adds a fake characteristic with |characteristic_uuid| and |properties|
   // to this service. Returns the characteristic's Id.
   std::string AddFakeCharacteristic(
diff --git a/device/u2f/BUILD.gn b/device/u2f/BUILD.gn
index bc7213e..2d7c727b 100644
--- a/device/u2f/BUILD.gn
+++ b/device/u2f/BUILD.gn
@@ -11,6 +11,8 @@
     "u2f_apdu_command.h",
     "u2f_apdu_response.cc",
     "u2f_apdu_response.h",
+    "u2f_ble_frames.cc",
+    "u2f_ble_frames.h",
     "u2f_command_type.h",
     "u2f_device.cc",
     "u2f_device.h",
@@ -33,6 +35,7 @@
     "//base",
     "//crypto",
     "//device/base",
+    "//device/bluetooth",
     "//device/hid",
     "//net",
   ]
@@ -74,3 +77,14 @@
   ]
   libfuzzer_options = [ "max_len=2048" ]
 }
+
+fuzzer_test("u2f_ble_frames_fuzzer") {
+  sources = [
+    "u2f_ble_frames_fuzzer.cc",
+  ]
+  deps = [
+    ":u2f",
+    "//net",
+  ]
+  libfuzzer_options = [ "max_len=65535" ]
+}
diff --git a/device/u2f/u2f_ble_frames.cc b/device/u2f/u2f_ble_frames.cc
new file mode 100644
index 0000000..08de593
--- /dev/null
+++ b/device/u2f/u2f_ble_frames.cc
@@ -0,0 +1,149 @@
+// 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/u2f/u2f_ble_frames.h"
+
+#include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
+
+#include <algorithm>
+
+namespace device {
+
+U2fBleFrame::U2fBleFrame() = default;
+
+U2fBleFrame::U2fBleFrame(U2fCommandType command, std::vector<uint8_t> data)
+    : command_(command), data_(std::move(data)) {}
+
+U2fBleFrame::U2fBleFrame(U2fBleFrame&&) = default;
+U2fBleFrame& U2fBleFrame::operator=(U2fBleFrame&&) = default;
+
+U2fBleFrame::~U2fBleFrame() = default;
+
+bool U2fBleFrame::IsValid() const {
+  switch (command_) {
+    case U2fCommandType::CMD_PING:
+    case U2fCommandType::CMD_MSG:
+      return true;
+    case U2fCommandType::CMD_KEEPALIVE:
+    case U2fCommandType::CMD_ERROR:
+      return data_.size() == 1;
+    case U2fCommandType::UNDEFINED:
+    default:
+      return false;
+  }
+}
+
+U2fBleFrame::KeepaliveCode U2fBleFrame::GetKeepaliveCode() const {
+  DCHECK_EQ(command_, U2fCommandType::CMD_KEEPALIVE);
+  DCHECK_EQ(data_.size(), 1u);
+  return static_cast<KeepaliveCode>(data_[0]);
+}
+
+U2fBleFrame::ErrorCode U2fBleFrame::GetErrorCode() const {
+  DCHECK_EQ(command_, U2fCommandType::CMD_ERROR);
+  DCHECK_EQ(data_.size(), 1u);
+  return static_cast<ErrorCode>(data_[0]);
+}
+
+std::pair<U2fBleFrameInitializationFragment,
+          std::vector<U2fBleFrameContinuationFragment>>
+U2fBleFrame::ToFragments(size_t max_fragment_size) const {
+  DCHECK_LE(data_.size(), 0xFFFFu);
+  DCHECK_GE(max_fragment_size, 3u);
+
+  size_t data_fragment_size = std::min(max_fragment_size - 3, data_.size());
+  U2fBleFrameInitializationFragment initial_fragment(
+      command_, static_cast<uint16_t>(data_.size()), &data_[0],
+      data_fragment_size);
+
+  size_t num_continuation_fragments = 0;
+  std::vector<U2fBleFrameContinuationFragment> other_fragments;
+  for (size_t pos = data_fragment_size; pos < data_.size();
+       pos += max_fragment_size - 1) {
+    data_fragment_size = std::min(data_.size() - pos, max_fragment_size - 1);
+    other_fragments.push_back(
+        U2fBleFrameContinuationFragment(&data_[pos], data_fragment_size,
+                                        (num_continuation_fragments++) & 0x7F));
+  }
+
+  return std::make_pair(initial_fragment, std::move(other_fragments));
+}
+
+bool U2fBleFrameInitializationFragment::Parse(
+    const std::vector<uint8_t>& data,
+    U2fBleFrameInitializationFragment* fragment) {
+  if (data.size() < 3)
+    return false;
+
+  const auto command = static_cast<U2fCommandType>(data[0]);
+  const uint16_t data_length = (static_cast<uint16_t>(data[1]) << 8) + data[2];
+  if (static_cast<size_t>(data_length) + 3 < data.size())
+    return false;
+
+  *fragment = U2fBleFrameInitializationFragment(
+      command, data_length, data.data() + 3, data.size() - 3);
+  return true;
+}
+
+size_t U2fBleFrameInitializationFragment::Serialize(
+    std::vector<uint8_t>* buffer) const {
+  buffer->push_back(static_cast<uint8_t>(command_));
+  buffer->push_back((data_length_ >> 8) & 0xFF);
+  buffer->push_back(data_length_ & 0xFF);
+  buffer->insert(buffer->end(), data(), data() + size());
+  return size() + 3;
+}
+
+bool U2fBleFrameContinuationFragment::Parse(
+    const std::vector<uint8_t>& data,
+    U2fBleFrameContinuationFragment* fragment) {
+  if (data.empty())
+    return false;
+  const uint8_t sequence = data[0];
+  *fragment = U2fBleFrameContinuationFragment(data.data() + 1, data.size() - 1,
+                                              sequence);
+  return true;
+}
+
+size_t U2fBleFrameContinuationFragment::Serialize(
+    std::vector<uint8_t>* buffer) const {
+  buffer->push_back(sequence_);
+  buffer->insert(buffer->end(), data(), data() + size());
+  return size() + 1;
+}
+
+U2fBleFrameAssembler::U2fBleFrameAssembler(
+    const U2fBleFrameInitializationFragment& fragment)
+    : frame_(fragment.command(), std::vector<uint8_t>()) {
+  std::vector<uint8_t>& data = frame_.data();
+  data.reserve(fragment.data_length());
+  data.assign(fragment.data(), fragment.data() + fragment.size());
+}
+
+bool U2fBleFrameAssembler::AddFragment(
+    const U2fBleFrameContinuationFragment& fragment) {
+  if (fragment.sequence() != sequence_number_)
+    return false;
+  if (++sequence_number_ > 0x7F)
+    sequence_number_ = 0;
+
+  std::vector<uint8_t>& data = frame_.data();
+  if (data.size() + fragment.size() > data.capacity())
+    return false;
+  data.insert(data.end(), fragment.data(), fragment.data() + fragment.size());
+  return true;
+}
+
+bool U2fBleFrameAssembler::IsDone() const {
+  return frame_.data().size() == frame_.data().capacity();
+}
+
+U2fBleFrame* U2fBleFrameAssembler::GetFrame() {
+  return IsDone() ? &frame_ : nullptr;
+}
+
+U2fBleFrameAssembler::~U2fBleFrameAssembler() = default;
+
+}  // namespace device
diff --git a/device/u2f/u2f_ble_frames.h b/device/u2f/u2f_ble_frames.h
new file mode 100644
index 0000000..91a66a5
--- /dev/null
+++ b/device/u2f/u2f_ble_frames.h
@@ -0,0 +1,180 @@
+// 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_U2F_U2F_BLE_FRAMES_
+#define DEVICE_U2F_U2F_BLE_FRAMES_
+
+#include "base/macros.h"
+
+#include "device/u2f/u2f_command_type.h"
+
+#include <stdint.h>
+#include <utility>
+#include <vector>
+
+namespace device {
+
+class U2fBleFrameInitializationFragment;
+class U2fBleFrameContinuationFragment;
+
+// Encapsulates a frame, i.e., a single request to or response from a U2F
+// authenticator, designed to be transported via BLE. The frame is further split
+// into fragments (see U2fBleFrameFragment class).
+//
+// The specification of what constitues a frame can be found here:
+// https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-bt-protocol-v1.2-ps-20170411.html#h2_framing
+//
+// TODO(crbug/763303): Consider refactoring U2fMessage to support BLE frames.
+class U2fBleFrame {
+ public:
+  // The values which can be carried in the |data| section of a KEEPALIVE
+  // message sent from an authenticator.
+  enum class KeepaliveCode : uint8_t {
+    // The request is still being processed. The authenticator will be sending
+    // this message every |kKeepAliveMillis| milliseconds until completion.
+    PROCESSING = 0x01,
+    // The authenticator is waiting for the Test of User Presence to complete.
+    TUP_NEEDED = 0x02,
+  };
+
+  // The types of errors an authenticator can return to the client. Carried in
+  // the |data| section of an ERROR command.
+  enum class ErrorCode : uint8_t {
+    INVALID_CMD = 0x01,  // The command in the request is unknown/invalid.
+    INVALID_PAR = 0x02,  // The parameters of the command are invalid/missing.
+    INVALID_LEN = 0x03,  // The length of the request is invalid.
+    INVALID_SEQ = 0x04,  // The sequence number is invalid.
+    REQ_TIMEOUT = 0x05,  // The request timed out.
+    NA_1 = 0x06,         // Value reserved (HID).
+    NA_2 = 0x0A,         // Value reserved (HID).
+    NA_3 = 0x0B,         // Value reserved (HID).
+    OTHER = 0x7F,        // Other, unspecified error.
+  };
+
+  U2fBleFrame();
+  U2fBleFrame(U2fCommandType command, std::vector<uint8_t> data);
+
+  U2fBleFrame(U2fBleFrame&&);
+  U2fBleFrame& operator=(U2fBleFrame&&);
+
+  ~U2fBleFrame();
+
+  U2fCommandType command() const { return command_; }
+
+  bool IsValid() const;
+  KeepaliveCode GetKeepaliveCode() const;
+  ErrorCode GetErrorCode() const;
+
+  const std::vector<uint8_t>& data() const { return data_; }
+  std::vector<uint8_t>& data() { return data_; }
+
+  // Splits the frame into fragments suitable for sending over BLE. Returns the
+  // first fragment via |initial_fragment|, and pushes the remaining ones back
+  // to the |other_fragments| vector.
+  //
+  // The |max_fragment_size| parameter ought to be at least 3. The resulting
+  // fragments' binary sizes will not exceed this value.
+  std::pair<U2fBleFrameInitializationFragment,
+            std::vector<U2fBleFrameContinuationFragment>>
+  ToFragments(size_t max_fragment_size) const;
+
+ private:
+  U2fCommandType command_ = U2fCommandType::UNDEFINED;
+  std::vector<uint8_t> data_;
+
+  DISALLOW_COPY_AND_ASSIGN(U2fBleFrame);
+};
+
+// A single frame sent over BLE may be split over multiple writes and
+// notifications because the technology was not designed for large messages.
+// This class represents a single fragment. Not to be used directly.
+//
+// A frame is divided into an initialization fragment and zero, one or more
+// continuation fragments. See the below section of the spec for the details:
+// https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-bt-protocol-v1.2-ps-20170411.html#h2_framing-fragmentation
+//
+// Note: This class and its subclasses don't own the |data|.
+class U2fBleFrameFragment {
+ public:
+  U2fBleFrameFragment() = default;
+  ~U2fBleFrameFragment() = default;
+
+  const uint8_t* data() const { return data_; }
+  size_t size() const { return size_; }
+
+ protected:
+  U2fBleFrameFragment(const uint8_t* data, size_t size)
+      : data_(data), size_(size) {}
+
+ private:
+  const uint8_t* data_ = nullptr;
+  size_t size_ = 0;
+};
+
+// An initialization fragment of a frame.
+class U2fBleFrameInitializationFragment : public U2fBleFrameFragment {
+ public:
+  static bool Parse(const std::vector<uint8_t>& data,
+                    U2fBleFrameInitializationFragment* fragment);
+
+  U2fBleFrameInitializationFragment() = default;
+  U2fBleFrameInitializationFragment(U2fCommandType command,
+                                    uint16_t data_length,
+                                    const uint8_t* fragment_data,
+                                    size_t fragment_size)
+      : U2fBleFrameFragment(fragment_data, fragment_size),
+        command_(command),
+        data_length_(data_length) {}
+
+  U2fCommandType command() const { return command_; }
+  uint16_t data_length() const { return data_length_; }
+
+  size_t Serialize(std::vector<uint8_t>* buffer) const;
+
+ private:
+  U2fCommandType command_ = U2fCommandType::UNDEFINED;
+  uint16_t data_length_ = 0;
+};
+
+// A continuation fragment of a frame.
+class U2fBleFrameContinuationFragment : public U2fBleFrameFragment {
+ public:
+  static bool Parse(const std::vector<uint8_t>& data,
+                    U2fBleFrameContinuationFragment* fragment);
+
+  U2fBleFrameContinuationFragment() = default;
+  U2fBleFrameContinuationFragment(const uint8_t* data,
+                                  size_t size,
+                                  uint8_t sequence)
+      : U2fBleFrameFragment(data, size), sequence_(sequence) {}
+
+  uint8_t sequence() const { return sequence_; }
+
+  size_t Serialize(std::vector<uint8_t>* buffer) const;
+
+ private:
+  uint8_t sequence_ = 0;
+};
+
+// The helper used to construct a U2fBleFrame from a sequence of its fragments.
+class U2fBleFrameAssembler {
+ public:
+  U2fBleFrameAssembler(const U2fBleFrameInitializationFragment& fragment);
+  ~U2fBleFrameAssembler();
+
+  bool IsDone() const;
+
+  bool AddFragment(const U2fBleFrameContinuationFragment& fragment);
+  U2fBleFrame* GetFrame();
+
+ private:
+  uint8_t sequence_number_ = 0;
+  U2fBleFrame frame_;
+
+  DISALLOW_COPY_AND_ASSIGN(U2fBleFrameAssembler);
+};
+
+}  // namespace device
+
+#endif  // DEVICE_U2F_U2F_BLE_FRAMES_
diff --git a/device/u2f/u2f_ble_frames_fuzzer.cc b/device/u2f/u2f_ble_frames_fuzzer.cc
new file mode 100644
index 0000000..6af387b
--- /dev/null
+++ b/device/u2f/u2f_ble_frames_fuzzer.cc
@@ -0,0 +1,56 @@
+// 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 "u2f_ble_frames.h"
+#include "u2f_command_type.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* raw_data, size_t size) {
+  std::vector<uint8_t> data(raw_data, raw_data + size);
+
+  {
+    device::U2fBleFrameInitializationFragment fragment(
+        device::U2fCommandType::CMD_MSG, 21123, raw_data, size);
+    std::vector<uint8_t> buffer;
+    fragment.Serialize(&buffer);
+
+    device::U2fBleFrameInitializationFragment parsed_fragment;
+    device::U2fBleFrameInitializationFragment::Parse(data, &parsed_fragment);
+    device::U2fBleFrameInitializationFragment::Parse(buffer, &parsed_fragment);
+
+    buffer.clear();
+    parsed_fragment.Serialize(&buffer);
+  }
+
+  {
+    device::U2fBleFrameContinuationFragment fragment(raw_data, size, 61);
+    std::vector<uint8_t> buffer;
+    fragment.Serialize(&buffer);
+
+    device::U2fBleFrameContinuationFragment parsed_fragment;
+    device::U2fBleFrameContinuationFragment::Parse(data, &parsed_fragment);
+    device::U2fBleFrameContinuationFragment::Parse(buffer, &parsed_fragment);
+
+    buffer.clear();
+    parsed_fragment.Serialize(&buffer);
+  }
+
+  {
+    device::U2fBleFrame frame(device::U2fCommandType::CMD_PING, data);
+    auto fragments = frame.ToFragments(20);
+
+    device::U2fBleFrameAssembler assembler(fragments.first);
+    for (const auto& fragment : fragments.second) {
+      assembler.AddFragment(fragment);
+    }
+
+    auto result_frame = std::move(*assembler.GetFrame());
+    result_frame.command();
+  }
+
+  return 0;
+}
diff --git a/device/u2f/u2f_ble_frames_unittest.cc b/device/u2f/u2f_ble_frames_unittest.cc
new file mode 100644
index 0000000..9b7cc8c
--- /dev/null
+++ b/device/u2f/u2f_ble_frames_unittest.cc
@@ -0,0 +1,146 @@
+// 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/u2f/u2f_ble_frames.h"
+
+#include "device/u2f/u2f_command_type.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#include <vector>
+
+namespace {
+
+std::vector<uint8_t> GetSomeData(size_t size) {
+  std::vector<uint8_t> data(size);
+  for (size_t i = 0; i < size; ++i)
+    data[i] = static_cast<uint8_t>((i * i) & 0xFF);
+  return data;
+}
+
+}  // namespace
+
+namespace device {
+
+TEST(U2fBleFramesTest, InitializationFragment) {
+  std::vector<uint8_t> data = GetSomeData(25);
+  constexpr uint16_t kDataLength = 21123;
+
+  U2fBleFrameInitializationFragment fragment(
+      U2fCommandType::CMD_MSG, kDataLength, data.data(), data.size());
+
+  std::vector<uint8_t> buffer;
+  const size_t binary_size = fragment.Serialize(&buffer);
+  EXPECT_EQ(buffer.size(), binary_size);
+
+  EXPECT_EQ(data.size() + 3, binary_size);
+
+  U2fBleFrameInitializationFragment parsed_fragment;
+  ASSERT_TRUE(
+      U2fBleFrameInitializationFragment::Parse(buffer, &parsed_fragment));
+
+  EXPECT_EQ(kDataLength, parsed_fragment.data_length());
+  EXPECT_EQ(data, std::vector<uint8_t>(
+                      parsed_fragment.data(),
+                      parsed_fragment.data() + parsed_fragment.size()));
+  EXPECT_EQ(U2fCommandType::CMD_MSG, parsed_fragment.command());
+}
+
+TEST(U2fBleFramesTest, ContinuationFragment) {
+  auto data = GetSomeData(25);
+  constexpr uint8_t kSequence = 61;
+
+  U2fBleFrameContinuationFragment fragment(data.data(), data.size(), kSequence);
+
+  std::vector<uint8_t> buffer;
+  const size_t binary_size = fragment.Serialize(&buffer);
+  EXPECT_EQ(buffer.size(), binary_size);
+
+  EXPECT_EQ(data.size() + 1, binary_size);
+
+  U2fBleFrameContinuationFragment parsed_fragment;
+  ASSERT_TRUE(U2fBleFrameContinuationFragment::Parse(buffer, &parsed_fragment));
+
+  EXPECT_EQ(data, std::vector<uint8_t>(
+                      parsed_fragment.data(),
+                      parsed_fragment.data() + parsed_fragment.size()));
+  EXPECT_EQ(kSequence, parsed_fragment.sequence());
+}
+
+TEST(U2fBleFramesTest, SplitAndAssemble) {
+  for (size_t size : {0,  1,  16, 17, 18, 20, 21, 22, 35,  36,
+                      37, 39, 40, 41, 54, 55, 56, 60, 100, 65535}) {
+    SCOPED_TRACE(size);
+
+    U2fBleFrame frame(U2fCommandType::CMD_PING, GetSomeData(size));
+
+    auto fragments = frame.ToFragments(20);
+
+    EXPECT_EQ(frame.command(), fragments.first.command());
+    EXPECT_EQ(frame.data().size(),
+              static_cast<size_t>(fragments.first.data_length()));
+
+    U2fBleFrameAssembler assembler(fragments.first);
+    for (const auto& fragment : fragments.second) {
+      ASSERT_TRUE(assembler.AddFragment(fragment));
+    }
+
+    EXPECT_TRUE(assembler.IsDone());
+    ASSERT_TRUE(assembler.GetFrame());
+
+    auto result_frame = std::move(*assembler.GetFrame());
+    EXPECT_EQ(frame.command(), result_frame.command());
+    EXPECT_EQ(frame.data(), result_frame.data());
+  }
+}
+
+TEST(U2fBleFramesTest, FrameAssemblerError) {
+  U2fBleFrame frame(U2fCommandType::CMD_PING, GetSomeData(30));
+
+  auto fragments = frame.ToFragments(20);
+  ASSERT_EQ(1u, fragments.second.size());
+
+  fragments.second[0] = U2fBleFrameContinuationFragment(
+      fragments.second[0].data(), fragments.second[0].size(), 51);
+
+  U2fBleFrameAssembler assembler(fragments.first);
+  EXPECT_FALSE(assembler.IsDone());
+  EXPECT_FALSE(assembler.GetFrame());
+  EXPECT_FALSE(assembler.AddFragment(fragments.second[0]));
+  EXPECT_FALSE(assembler.IsDone());
+  EXPECT_FALSE(assembler.GetFrame());
+}
+
+TEST(U2fBleFramesTest, FrameGettersAndValidity) {
+  {
+    U2fBleFrame frame(U2fCommandType::CMD_KEEPALIVE, std::vector<uint8_t>(2));
+    EXPECT_FALSE(frame.IsValid());
+  }
+  {
+    U2fBleFrame frame(U2fCommandType::CMD_ERROR, {});
+    EXPECT_FALSE(frame.IsValid());
+  }
+
+  for (auto code : {U2fBleFrame::KeepaliveCode::TUP_NEEDED,
+                    U2fBleFrame::KeepaliveCode::PROCESSING}) {
+    U2fBleFrame frame(U2fCommandType::CMD_KEEPALIVE,
+                      std::vector<uint8_t>(1, static_cast<uint8_t>(code)));
+    EXPECT_TRUE(frame.IsValid());
+    EXPECT_EQ(code, frame.GetKeepaliveCode());
+  }
+
+  for (auto code : {
+           U2fBleFrame::ErrorCode::INVALID_CMD,
+           U2fBleFrame::ErrorCode::INVALID_PAR,
+           U2fBleFrame::ErrorCode::INVALID_SEQ,
+           U2fBleFrame::ErrorCode::INVALID_LEN,
+           U2fBleFrame::ErrorCode::REQ_TIMEOUT, U2fBleFrame::ErrorCode::NA_1,
+           U2fBleFrame::ErrorCode::NA_2, U2fBleFrame::ErrorCode::NA_3,
+       }) {
+    U2fBleFrame frame(U2fCommandType::CMD_ERROR, {static_cast<uint8_t>(code)});
+    EXPECT_TRUE(frame.IsValid());
+    EXPECT_EQ(code, frame.GetErrorCode());
+  }
+}
+
+}  // namespace device
diff --git a/device/u2f/u2f_command_type.h b/device/u2f/u2f_command_type.h
index 629ef5327..3148554 100644
--- a/device/u2f/u2f_command_type.h
+++ b/device/u2f/u2f_command_type.h
@@ -14,17 +14,27 @@
 //
 // Each request sent to a device results in a response of *the same* type sent
 // back, unless there was an error in which case a CMD_ERROR is returned.
-//
-// TODO(pkalinnikov): Merge BLE-specific commands to this type.
 enum class U2fCommandType : uint8_t {
+  UNDEFINED = 0x00,
+
   // Sends arbitrary data to the device which echoes the same data back.
   CMD_PING = 0x81,
+
+  // Authenticator sends this in response to requests that it could not process
+  // within a time limit. The client should take action appropriate to the
+  // message reason (e.g., notify the user to perform a test-of-user-presence),
+  // and wait for the next message.
+  CMD_KEEPALIVE = 0x82,
+
   // Encapsulates a U2F protocol raw message.
   CMD_MSG = 0x83,
+
   // Requests a unique channel from a USB/HID device.
   CMD_INIT = 0x86,
+
   // Instructs a USB/HID authenticator to show the user that it is active.
   CMD_WINK = 0x88,
+
   // Used as a response in case an error occurs during a request.
   CMD_ERROR = 0xBF,
 };
diff --git a/docs/android_test_instructions.md b/docs/android_test_instructions.md
index 714a229..ed8dcb4 100644
--- a/docs/android_test_instructions.md
+++ b/docs/android_test_instructions.md
@@ -34,12 +34,6 @@
 case, get another device or log in with a normal, unmanaged account (because the
 tests will break in exciting ways if stay awake is off).
 
-#### Enable Asserts
-
-```
-adb shell setprop debug.assert 1
-```
-
 #### Disable Verify Apps
 
 You may see a dialog like [this
diff --git a/docs/design/threading.md b/docs/design/threading.md
index 0f3b8ea..eb69f16e 100644
--- a/docs/design/threading.md
+++ b/docs/design/threading.md
@@ -1,4 +1,511 @@
 # Threading
 
-Superseded by new [`Threading and Tasks in Chrome`](../threading_and_tasks.md)
-and [`Callback<> and Bind()`](../callback.md) documentation.
+[TOC]
+
+## Overview
+
+Chromium is a very multithreaded product. We try to keep the UI as responsive as
+possible, and this means not blocking the UI thread with any blocking I/O or
+other expensive operations. Our approach is to use message passing as the way of
+communicating between threads. We discourage locking and threadsafe
+objects. Instead, objects live on only one thread, we pass messages between
+threads for communication, and we use callback interfaces (implemented by
+message passing) for most cross-thread requests.
+
+The `Thread` object is defined in
+[`base/threading/thread.h`](https://cs.chromium.org/chromium/src/base/threading/thread.h).
+In general you should probably use one of the existing threads described below
+rather than make new ones. We already have a lot of threads that are difficult
+to keep track of. Each thread has a `MessageLoop` (see
+[`base/message_loop/message_loop.h`](https://cs.chromium.org/chromium/src/base/message_loop/message_loop.h)
+that processes messages for that thread. You can get the message loop for a
+thread using the `Thread.message_loop()` function.  More details about
+`MessageLoop` can be found in
+[Anatomy of Chromium MessageLoop](https://docs.google.com/document/d/1_pJUHO3f3VyRSQjEhKVvUU7NzCyuTCQshZvbWeQiCXU/view#).
+
+## Existing threads
+
+Most threads are managed by the BrowserProcess object, which acts as the service
+manager for the main "browser" process. By default, everything happens on the UI
+thread. We have pushed certain classes of processing into these other
+threads. It has getters for the following threads:
+
+*  **ui_thread**: Main thread where the application starts up.
+*  **io_thread**: This thread is somewhat mis-named. It is the dispatcher thread
+   that handles communication between the browser process and all the
+   sub-processes. It is also where all resource requests (web page loads) are
+   dispatched from (see
+   [Multi-process Architecture](https://www.chromium.org/developers/design-documents/multi-process-architecture)).
+*  **file_thread**: A general process thread for file operations. When you want to
+   do blocking filesystem operations (for example, requesting an icon for a file
+   type, or writing downloaded files to disk), dispatch to this thread.
+*  **db_thread**: A thread for database operations. For example, the cookie
+   service does sqlite operations on this thread. Note that the history database
+   doesn't use this thread yet.
+*  **safe_browsing_thread**
+
+Several components have their own threads:
+
+*  **History**: The history service object has its own thread. This might be
+   merged with the db_thread above. However, we need to be sure that things
+   happen in the correct order -- for example, that cookies are loaded before
+   history since cookies are needed for the first load, and history
+   initialization is long and will block it.
+*  **Proxy service**: See
+   [`net/http/http_proxy_service.cc`](https://cs.chromium.org/chromium/src/net/http/http_proxy_service.cc).
+*  **Automation proxy**: This thread is used to communicate with the UI test
+   program driving the app.
+
+## Keeping the browser responsive
+
+As hinted in the overview, we avoid doing any blocking I/O on the UI thread to
+keep the UI responsive.  Less apparent is that we also need to avoid blocking
+I/O on the IO thread.  The reason is that if we block it for an expensive
+operation, say disk access, then IPC messages don't get processed.  The effect
+is that the user can't interact with a page.  Note that asynchronous/overlapped
+I/O are fine.
+
+Another thing to watch out for is to not block threads on one another.  Locks
+should only be used to swap in a shared data structure that can be accessed on
+multiple threads.  If one thread updates it based on expensive computation or
+through disk access, then that slow work should be done without holding on to
+the lock.  Only when the result is available should the lock be used to swap in
+the new data.  An example of this is in PluginList::LoadPlugins
+([`content/common/plugin_list.cc`](https://cs.chromium.org/chromium/src/content/common/plugin_list.cc). If
+you must use locks,
+[here](https://www.chromium.org/developers/lock-and-condition-variable)
+are some best practices and pitfalls to avoid.
+
+In order to write non-blocking code, many APIs in Chromium are
+asynchronous. Usually this means that they either need to be executed on a
+particular thread and will return results via a custom delegate interface, or
+they take a `base::Callback<>` object that is called when the requested
+operation is completed.  Executing work on a specific thread is covered in the
+PostTask section below.
+
+## Getting stuff to other threads
+
+### `base::Callback<>`, Async APIs and Currying
+
+
+A `base::Callback<>` (see the docs in
+[`base/callback.h`](https://cs.chromium.org/chromium/src/base/callback.h) is
+a templated class with a `Run()` method.  It is a generalization of a function
+pointer and is created by a call to `base::Bind`.  Async APIs often will take a
+`base::Callback<>` as a means to asynchronously return the results of an
+operation.  Here is an example of a hypothetical FileRead API.
+
+    void ReadToString(const std::string& filename, const base::Callback<void(const std::string&)>& on_read);
+
+    void DisplayString(const std::string& result) {
+      LOG(INFO) << result;
+    }
+
+    void SomeFunc(const std::string& file) {
+      ReadToString(file, base::Bind(&DisplayString));
+    };
+
+In the example above, `base::Bind` takes the function pointer `&DisplayString`
+and turns it into a `base::Callback<void(const std::string& result)>`. The type
+of the generated `base::Callback<>` is inferred from the arguments.  Why not
+just pass the function pointer directly?  The reason is `base::Bind` allows the
+caller to adapt function interfaces and/or attach extra context
+via [Currying](http://en.wikipedia.org/wiki/Currying).  For instance, if we had
+a utility function `DisplayStringWithPrefix` that took an extra argument with
+the prefix, we use `base::Bind` to adapt the interface as follows.
+
+    void DisplayStringWithPrefix(const std::string& prefix, const std::string& result) {
+        LOG(INFO) << prefix << result;
+    }
+
+    void AnotherFunc(const std::string& file) {
+      ReadToString(file, base::Bind(&DisplayStringWithPrefix, "MyPrefix: "));
+    };
+
+This can be used in lieu of creating an adapter functions a small classes that
+holds prefix as a member variable.  Notice also that the `"MyPrefix: "` argument
+is actually a `const char*`, while `DisplayStringWithPrefix` actually wants a
+`const std::string&`.  Like normal function dispatch, `base::Bind`, will coerce
+parameters types if possible.
+
+See [How arguments are handled by base::Bind()](#how_arguments_are_handled)
+below for more details about argument storage, copying, and special handling of
+references.
+
+### PostTask
+
+The lowest level of dispatching to another thread is to use the
+`MessageLoop.PostTask` and `MessageLoop.PostDelayedTask`
+(see
+[`base/message_loop/message_loop.h`](https://cs.chromium.org/chromium/src/base/message_loop/message_loop.h)).
+PostTask schedules a task to be run on a particular thread.  A task is defined
+as a `base::Closure`, which is a typedef for a
+`base::Callback<void(void)>`. `PostDelayedTask` schedules a task to be run after
+a delay on a particular thread. A task is represented by the `base::Closure`
+typedef, which contains a `Run()` function, and is created by calling
+`base::Bind()`.  To process a task, the message loop eventually calls
+`base::Closure`'s `Run` function, and then drops the reference to the task
+object. Both `PostTask` and `PostDelayedTask` take a `base::Location`
+parameter, which is used for lightweight debugging purposes (counts and
+primitive profiling of pending and completed tasks can be monitored in a debug
+build via the url about:objects). Generally the macro value `FROM_HERE` is the
+appropriate value to use in this parameter.
+
+Note that new tasks go on the message loop's queue, and any delay that is
+specified is subject to the operating system's timer resolutions. This means
+that under Windows, very small timeouts (under 10ms) will likely not be honored
+(and will be longer). Using a timeout of 0 in `PostDelayedTask` is equivalent to
+calling `PostTask`, and adds no delay beyond queuing delay. `PostTask` is also
+used to do something on the current thread "sometime after the current
+processing returns to the message loop." Such a continuation on the current
+thread can be used to assure that other time critical tasks are not starved on
+this thread.
+
+The following is an example of a creating a task for a function and posting it
+to another thread (in this example, the file thread):
+
+    void WriteToFile(const std::string& filename, const std::string& data);
+    BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+                            base::Bind(&WriteToFile, "foo.txt", "hello world!"));
+
+You should always use `BrowserThread` to post tasks between threads.  Never
+cache `MessageLoop` pointers as it can cause bugs such as the pointers being
+deleted while you're still holding on to them.  More information can be
+found
+[here](https://www.chromium.org/developers/design-documents/threading/suble-threading-bugs-and-patterns-to-avoid-them).
+
+
+### base::Bind() and class methods.
+
+The `base::Bind()` API also supports invoking class methods as well.  The syntax
+is very similar to calling `base::Bind()` on a function, except the first
+argument should be the object the method belongs to. By default, the object that
+`PostTask` uses must be a thread-safe reference-counted object. Reference
+counting ensures that the object invoked on another thread will stay alive until
+the task completes.
+
+    class MyObject : public base::RefCountedThreadSafe<MyObject> {
+     public:
+      void DoSomething(const std::string16& name) {
+        thread_->message_loop()->PostTask(
+           FROM_HERE, base::Bind(&MyObject::DoSomethingOnAnotherThread, this, name));
+      }
+
+      void DoSomethingOnAnotherThread(const std::string16& name) {
+        ...
+      }
+     private:
+      // Always good form to make the destructor private so that only RefCounted
+      // ThreadSafe can access it.
+      // This avoids bugs with double deletes.
+      friend class base::RefCountedThreadSafe<MyObject>;
+
+      ~MyObject();
+      Thread* thread_;
+    };
+
+If you have external synchronization structures that can completely ensure that
+an object will always be alive while the task is waiting to execute, you can
+wrap the object pointer with `base::Unretained()` when calling `base::Bind()` to
+disable the refcounting.  This will also allow using `base::Bind()` on classes
+that are not refcounted.  Be careful when doing this!
+
+
+
+### How arguments are handled by `base::Bind()`
+<a id="how_arguments_are_handled"></a>
+
+The arguments given to `base::Bind()` are copied into an internal
+`InvokerStorage` structure object (defined in
+[`base/bind_internal.h`](http://cs.chromium.org/chromium/src/base/bind_internal.h).
+When the function is finally executed, it will see copies of the arguments.  This is important if your target function or method takes a const reference; the
+reference will be to a copy of the argument.  If you need a reference to the
+original argument, you can wrap the argument with `base::ConstRef()`.  Use this
+carefully as it is likely dangerous if target of the reference cannot be
+guaranteed to live past when the task is executed.  In particular, it is almost
+never safe to use `base::ConstRef()` to a variable on the stack unless you can
+guarantee the stack frame will not be invalidated until the asynchronous task
+finishes.
+
+Sometimes, you will want to pass reference-counted objects as parameters (be
+sure to use `RefCountedThreadSafe` and not plain `RefCounted` as the base class
+for these objects). To ensure that the object lives throughout the entire
+request, the Closure generated by `base::Bind` must keep a reference to it. This
+can be done by passing scoped_refptr as the parameter type, or by wrapping the
+raw pointer with `make_scoped_refptr()`:
+
+    class SomeParamObject : public base::RefCountedThreadSafe<SomeParamObject> {
+     ...
+    };
+
+    class MyObject : public base::RefCountedThreadSafe<MyObject> {
+     public:
+      void DoSomething() {
+        scoped_refptr<SomeParamObject> param(new SomeParamObject);
+
+        // Without RetainedRef, the scoped_refptr would try to implicitly
+        // convert to a raw pointer and fail compilation.
+        thread_->message_loop()->PostTask(FROM_HERE,
+           base::Bind(&MyObject::DoSomethingOnAnotherThread, this,
+           base::RetainedRef(param)));
+      }
+
+      void DoSomething2() {
+        SomeParamObject* param = new SomeParamObject;
+        thread_->message_loop()->PostTask(FROM_HERE,
+           base::Bind(&MyObject::DoSomethingOnAnotherThread, this,
+                             base::RetainedRef(make_scoped_refptr(param))));
+      }
+
+      void DoSomething3() {
+        scoped_refptr<SomeParamObject> param(new SomeParamObject);
+
+        // Moving |param| prevents an extra AddRef()/Release() pair.
+        thread_->message_loop()->PostTask(FROM_HERE,
+           base::Bind(&MyObject::DoSomethingOnAnotherThread, this,
+           base::RetainedRef(std::move(param))));
+      }
+
+      // Note how this takes a raw pointer. The important part is that
+      // base::Bind() was passed a scoped_refptr; using a scoped_refptr
+      // here would result in an extra AddRef()/Release() pair.
+      void DoSomethingOnAnotherThread(SomeParamObject* param) {
+        ...
+      }
+    };
+
+If you want to pass the object without taking a reference on it, wrap the
+argument with `base::Unretained()`. Again, using this means there are external
+guarantees on the lifetime of the object, so tread carefully!
+
+If your object has a non-trivial destructor that needs to run on a specific
+thread, you can use the following trait. This is needed since timing races could
+lead to a task completing execution before the code that posted it has unwound
+the stack.
+
+    class MyObject : public base::RefCountedThreadSafe<MyObject, BrowserThread::DeleteOnIOThread> {
+
+## Callback cancellation
+
+There are 2 major reasons to cancel a task (in the form of a Callback):
+*  You want to do something later on your object, but at the time your callback
+   runs, your object may have been destroyed.
+*  When input changes (e.g. user input), old tasks become unnecessary. For
+   performance considerations, you should cancel them.
+See following about different approaches for cancellation.
+
+### Important notes about cancellation
+
+It's dangerous to cancel a task with owned parameters. See the following
+example. (The example uses `base::WeakPtr` for cancellation, but the problem
+applies to all approaches).
+
+    class MyClass {
+     public:
+      // Owns |p|.
+      void DoSomething(AnotherClass* p) {
+        ...
+      }
+      WeakPtr<MyClass> AsWeakPtr() {
+        return weak_factory_.GetWeakPtr();
+      }
+     private:
+      base::WeakPtrFactory<MyClass> weak_factory_;
+    };
+
+    ...
+    Closure cancelable_closure = Bind(&MyClass::DoSomething, object->AsWeakPtr(), p);
+    Callback<void(AnotherClass*)> cancelable_callback = Bind(&MyClass::DoSomething, object->AsWeakPtr());
+    ...
+
+    void FunctionRunLater(const Closure& cancelable_closure,
+                          const Callback<void(AnotherClass*)>& cancelable_callback) {
+      ...
+      // Leak memory!
+      cancelable_closure.Run();
+      cancelable_callback.Run(p);
+    }
+
+In `FunctionRunLater`, both `Run()` calls will leak `p` when object is already
+destructed. Using `scoped_ptr` can fix the bug:
+
+    class MyClass {
+     public:
+      void DoSomething(scoped_ptr<AnotherClass> p) {
+        ...
+      }
+      ...
+    };
+
+### base::WeakPtr and Cancellation __[NOT THREAD SAFE]__
+
+You can use a `base::WeakPtr` and `base::WeakPtrFactory`
+(in
+[base/memory/weak_ptr.h](https://cs.chromium.org/chromium/src/base/memory/weak_ptr.h))
+to ensure that any invokes can not outlive the object they are being invoked on,
+without using reference counting. The `base::Bind` mechanism has special
+understanding for `base::WeakPtr` that will disable the task's execution if the
+`base::WeakPtr` has been invalidated. The `base::WeakPtrFactory` object can be
+used to generate `base::WeakPtr` instances that know about the factory
+object. When the factory is destroyed, all the `base::WeakPtr` will have their
+internal "invalidated" flag set, which will make any tasks bound to them to not
+dispatch. By putting the factory as a member of the object being dispatched to,
+you can get automatic cancellation.
+
+__NOTE__: This only works when the task is posted to the same thread. Currently
+there is not a general solution that works for tasks posted to other
+threads. See
+the [next section about CancelableTaskTracker](#cancelable_task_tracker) for an
+alternative solution.
+
+    class MyObject {
+     public:
+      MyObject() : weak_factory_(this) {}
+
+      void DoSomething() {
+        const int kDelayMS = 100;
+        MessageLoop::current()->PostDelayedTask(FROM_HERE,
+            base::Bind(&MyObject::DoSomethingLater, weak_factory_.GetWeakPtr()),
+            kDelayMS);
+      }
+
+      void DoSomethingLater() {
+        ...
+      }
+
+     private:
+      base::WeakPtrFactory<MyObject> weak_factory_;
+    };
+
+### CancelableTaskTracker
+<a id="cancelable_task_tracker"></a>
+
+While `base::WeakPtr` is very helpful to cancel a task, it is not thread safe so
+can not be used to cancel tasks running on another thread. This is sometimes a
+performance critical requirement. E.g. We need to cancel database lookup task on
+DB thread when user changes inputed text. In this kind of situation
+`CancelableTaskTracker` is appropriate.
+
+With `CancelableTaskTracker` you can cancel a single task with returned
+`TaskId`. This is another reason to use `CancelableTaskTracker` instead of
+`base::WeakPtr`, even in a single thread context.
+
+`CancelableTaskTracker` has 2 `Post` methods doing the same thing as the ones in
+`base::TaskRunner`, with additional cancellation support.
+
+    class UserInputHandler : public base::RefCountedThreadSafe<UserInputHandler> {
+      // Runs on UI thread.
+      void OnUserInput(Input input) {
+        CancelPreviousTask();
+        DBResult* result = new DBResult();
+        task_id_ = tracker_->PostTaskAndReply(
+            BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB).get(),
+            FROM_HERE,
+            base::Bind(&LookupHistoryOnDBThread, this, input, result),
+            base::Bind(&ShowHistoryOnUIThread, this, base::Owned(result)));
+      }
+
+      void CancelPreviousTask() {
+        tracker_->TryCancel(task_id_);
+      }
+
+      ...
+
+     private:
+      CancelableTaskTracker tracker_;  // Cancels all pending tasks while destruction.
+      CancelableTaskTracker::TaskId task_id_;
+      ...
+    };
+
+Since task runs on other threads, there's no guarantee it can be successfully
+canceled.
+
+When `TryCancel()` is called:
+
+*  If neither task nor reply has started running, both will be canceled.
+*  If task is already running or has finished running, reply will be canceled.
+*  If reply is running or has finished running, cancelation is a noop.
+
+Like `base::WeakPtrFactory`, `CancelableTaskTracker` will cancel all tasks on
+destruction.
+
+### Cancelable request __(DEPRECATED)__
+
+Note. Cancelable request is deprecated. Please do not use it in new code. For
+canceling tasks running on the same thread, use WeakPtr. For canceling tasks
+running on a different thread, use `CancelableTaskTracker`.
+
+A cancelable request makes it easier to make requests to another thread with
+that thread returning some data to you asynchronously. Like the revokable store
+system, it uses objects that track whether the originating object is alive. When
+the calling object is deleted, the request will be canceled to prevent invalid
+callbacks.
+
+Like the revokable store system, a user of a cancelable request has
+an object (here, called a _Consumer_) that tracks whether it is alive and will
+auto-cancel any outstanding requests on deleting.
+
+    class MyClass {
+      void MakeRequest() {
+        frontend_service->StartRequest(some_input1, some_input2, this,
+            // Use base::Unretained(this) if this may cause a refcount cycle.
+            base::Bind(&MyClass:RequestComplete, this));
+      }
+      void RequestComplete(int status) {
+        ...
+      }
+
+     private:
+      CancelableRequestConsumer consumer_;
+    };
+
+Note that the `MyClass::RequestComplete`, is bounded with
+`base::Unretained(this)` here.
+
+The consumer also allows you to associate extra data with a request. Use
+`CancelableRequestConsumer` which will allow you to associate arbitrary data
+with the handle returned by the provider service when you invoke the
+request. The data will be automatically destroyed when the request is canceled.
+
+A service handling requests inherits from `CancelableRequestProvider`. This
+object provides methods for canceling in-flight requests, and will work with the
+consumers to make sure everything is cleaned up properly on cancel. This
+frontend service just tracks the request and sends it to a backend service on
+another thread for actual processing. It would look like this:
+
+    class FrontendService : public CancelableRequestProvider {
+      typedef base::Callback<void(int)> RequestCallbackType;
+
+      Handle StartRequest(int some_input1, int some_input2,
+          CallbackConsumer* consumer,
+          const RequestCallbackType& callback) {
+        scoped_refptr<CancelableRequest<FrontendService::RequestCallbackType>>
+            request(new CancelableRequest(callback));
+        AddRequest(request, consumer);
+
+        // Send the parameters and the request to the backend thread.
+        backend_thread_->PostTask(FROM_HERE,
+            base::Bind(&BackendService::DoRequest, backend_, request,
+                       some_input1, some_input2), 0);
+        // The handle will have been set by AddRequest.
+        return request->handle();
+      }
+    };
+
+The backend service runs on another thread. It does processing and forwards the
+result back to the original caller. It would look like this:
+
+    class BackendService : public base::RefCountedThreadSafe<BackendService> {
+      void DoRequest(
+          scoped_refptr<CancelableRequest<FrontendService::RequestCallbackType>>
+              request,
+          int some_input1, int some_input2) {
+        if (request->canceled())
+          return;
+
+        ... do your processing ...
+
+        // Execute ForwardResult() like you would do Run() on the base::Callback<>.
+        request->ForwardResult(return_value);
+      }
+    };
diff --git a/docs/windows_build_instructions.md b/docs/windows_build_instructions.md
index 0a8fb7bb..9a3207b 100644
--- a/docs/windows_build_instructions.md
+++ b/docs/windows_build_instructions.md
@@ -23,38 +23,23 @@
 
 ### Visual Studio
 
-As of September, 2017 Chromium requires Visual Studio 2015, with the 14393
-Windows SDK or later to build.
-
-Install Visual Studio 2015 Update 3 or later - Community Edition
-should work if its license is appropriate for you. Use the Custom Install option
-and select:
-
-- Visual C++, which will select three sub-categories including MFC
-- Universal Windows Apps Development Tools > Tools (1.4.1) and Windows 10 SDK
-
-You can also install Visual Studio 2017 Update 3 or later. You must install the
+As of September, 2017 Chromium requires Visual Studio 2017 update 3.2 with the
+15063 (Creators Update) Windows SDK or later to build. Visual Studio Community
+Edition should work if its license is appropriate for you. You must install the
 VC++ toolchain and MFC. This can be done from the command line like this:
 ```shell
 vs_professional.exe --add Microsoft.VisualStudio.Workload.NativeDesktop
     --add Microsoft.VisualStudio.Component.VC.ATLMFC --includeRecommended
 ```
-You must also set GYP_MSVS_VERSION=2017 to tell the Chrome build system to use
-this toolchain. This generally works but is not yet officially supported.
-
-You must have the Windows 10 SDK installed, version 10.0.14393 or
-10.0.15063. The 10.0.15063 SDK initially had errors but the 10.0.15063.468
-version works well.
-
-When installing the Windows 10 SDK choose Debugging Tools For Windows in
-order to get windbg and cdb. The latter is required for the build to succeed as
-some tests use it for symbolizing crash dumps.
+You must have the Windows 10 SDK installed, version 10.0.15063 or later.
+The 10.0.15063 SDK initially had errors but the 10.0.15063.468 version works
+well. Most of this will be installed by Visual Studio.
 
 If the Windows 10 SDK was installed via the Visual Studio installer, the Debugging
 Tools can be installed by going to: Control Panel → Programs →
 Programs and Features → Select the "Windows Software Development Kit" →
 Change → Change → Check "Debugging Tools For Windows" → Change. Or, you can
-download the standalone installer and use it to install the Debugging Tools.
+download the standalone SDK installer and use it to install the Debugging Tools.
 
 ## Install `depot_tools`
 
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn
index eba6de36..432ffff 100644
--- a/extensions/browser/BUILD.gn
+++ b/extensions/browser/BUILD.gn
@@ -149,6 +149,8 @@
     "extension_prefs_scope.h",
     "extension_protocols.cc",
     "extension_protocols.h",
+    "extension_registrar.cc",
+    "extension_registrar.h",
     "extension_registry.cc",
     "extension_registry.h",
     "extension_registry_factory.cc",
@@ -528,6 +530,7 @@
     "extension_api_frame_id_map_unittest.cc",
     "extension_icon_image_unittest.cc",
     "extension_pref_value_map_unittest.cc",
+    "extension_registrar_unittest.cc",
     "extension_registry_unittest.cc",
     "extension_throttle_simulation_unittest.cc",
     "extension_throttle_test_support.cc",
diff --git a/extensions/browser/api/extensions_api_client.cc b/extensions/browser/api/extensions_api_client.cc
index 3d8faf3..0a46302 100644
--- a/extensions/browser/api/extensions_api_client.cc
+++ b/extensions/browser/api/extensions_api_client.cc
@@ -96,7 +96,8 @@
 }
 
 std::unique_ptr<VirtualKeyboardDelegate>
-ExtensionsAPIClient::CreateVirtualKeyboardDelegate() const {
+ExtensionsAPIClient::CreateVirtualKeyboardDelegate(
+    content::BrowserContext* context) const {
   return nullptr;
 }
 
diff --git a/extensions/browser/api/extensions_api_client.h b/extensions/browser/api/extensions_api_client.h
index 8a02d78..6b49616 100644
--- a/extensions/browser/api/extensions_api_client.h
+++ b/extensions/browser/api/extensions_api_client.h
@@ -136,7 +136,7 @@
 
   // Returns a delegate for some of VirtualKeyboardAPI's behavior.
   virtual std::unique_ptr<VirtualKeyboardDelegate>
-  CreateVirtualKeyboardDelegate() const;
+  CreateVirtualKeyboardDelegate(content::BrowserContext* browser_context) const;
 
   // Creates a delegate for handling the management extension api.
   virtual ManagementAPIDelegate* CreateManagementAPIDelegate() const;
diff --git a/extensions/browser/api/system_display/display_info_provider.cc b/extensions/browser/api/system_display/display_info_provider.cc
index f57934e..567f3c4 100644
--- a/extensions/browser/api/system_display/display_info_provider.cc
+++ b/extensions/browser/api/system_display/display_info_provider.cc
@@ -127,7 +127,7 @@
 bool DisplayInfoProvider::ShowNativeTouchCalibration(
     const std::string& id,
     std::string* error,
-    const TouchCalibrationCallback& callback) {
+    TouchCalibrationCallback callback) {
   NOTREACHED();  // Implemented on Chrome OS only in override.
   return false;
 }
diff --git a/extensions/browser/api/system_display/display_info_provider.h b/extensions/browser/api/system_display/display_info_provider.h
index e6c4db5..2a70ae81 100644
--- a/extensions/browser/api/system_display/display_info_provider.h
+++ b/extensions/browser/api/system_display/display_info_provider.h
@@ -10,6 +10,7 @@
 #include <string>
 #include <vector>
 
+#include "base/callback.h"
 #include "base/callback_forward.h"
 #include "base/macros.h"
 
@@ -34,7 +35,7 @@
  public:
   using DisplayUnitInfoList = std::vector<api::system_display::DisplayUnitInfo>;
   using DisplayLayoutList = std::vector<api::system_display::DisplayLayout>;
-  using TouchCalibrationCallback = base::Callback<void(bool)>;
+  using TouchCalibrationCallback = base::OnceCallback<void(bool)>;
 
   virtual ~DisplayInfoProvider();
 
@@ -80,10 +81,9 @@
   // Implements touch calibration methods. See system_display.idl. This returns
   // false in case any error occurs. In such cases the |error| string will also
   // be set.
-  virtual bool ShowNativeTouchCalibration(
-      const std::string& id,
-      std::string* error,
-      const TouchCalibrationCallback& callback);
+  virtual bool ShowNativeTouchCalibration(const std::string& id,
+                                          std::string* error,
+                                          TouchCalibrationCallback callback);
   virtual bool StartCustomTouchCalibration(const std::string& id,
                                            std::string* error);
   virtual bool CompleteCustomTouchCalibration(
diff --git a/extensions/browser/api/system_display/system_display_api.cc b/extensions/browser/api/system_display/system_display_api.cc
index c81f958..1e35ee6 100644
--- a/extensions/browser/api/system_display/system_display_api.cc
+++ b/extensions/browser/api/system_display/system_display_api.cc
@@ -292,9 +292,9 @@
 
   if (!DisplayInfoProvider::Get()->ShowNativeTouchCalibration(
           params->id, &error,
-          base::Bind(&SystemDisplayShowNativeTouchCalibrationFunction::
-                         OnCalibrationComplete,
-                     this))) {
+          base::BindOnce(&SystemDisplayShowNativeTouchCalibrationFunction::
+                             OnCalibrationComplete,
+                         this))) {
     return RespondNow(Error(error));
   }
   return RespondLater();
diff --git a/extensions/browser/api/system_display/system_display_apitest.cc b/extensions/browser/api/system_display/system_display_apitest.cc
index 633903b..e7b1388 100644
--- a/extensions/browser/api/system_display/system_display_apitest.cc
+++ b/extensions/browser/api/system_display/system_display_apitest.cc
@@ -153,9 +153,10 @@
   bool ShowNativeTouchCalibration(
       const std::string& id,
       std::string* error,
-      const DisplayInfoProvider::TouchCalibrationCallback& callback) override {
+      DisplayInfoProvider::TouchCalibrationCallback callback) override {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(callback, native_touch_calibration_success_));
+        FROM_HERE,
+        base::BindOnce(std::move(callback), native_touch_calibration_success_));
     return true;
   }
 
diff --git a/extensions/browser/api/virtual_keyboard/virtual_keyboard_api.cc b/extensions/browser/api/virtual_keyboard/virtual_keyboard_api.cc
index de8d87f1..67bd41c3 100644
--- a/extensions/browser/api/virtual_keyboard/virtual_keyboard_api.cc
+++ b/extensions/browser/api/virtual_keyboard/virtual_keyboard_api.cc
@@ -12,6 +12,7 @@
 
 #if defined(OS_CHROMEOS)
 #include "ui/base/ime/chromeos/input_method_manager.h"
+
 using chromeos::input_method::InputMethodManager;
 #endif
 
@@ -22,34 +23,31 @@
 
 ExtensionFunction::ResponseAction
 VirtualKeyboardRestrictFeaturesFunction::Run() {
-  std::unique_ptr<api::virtual_keyboard::RestrictFeatures::Params> params(
-      api::virtual_keyboard::RestrictFeatures::Params::Create(*args_));
+  std::unique_ptr<api::virtual_keyboard::RestrictFeatures::Params> params =
+      api::virtual_keyboard::RestrictFeatures::Params::Create(*args_);
   EXTENSION_FUNCTION_VALIDATE(params);
-
-  bool features_enabled = params->restrictions.auto_correct_enabled;
-  if (params->restrictions.auto_complete_enabled != features_enabled ||
-      params->restrictions.spell_check_enabled != features_enabled ||
-      params->restrictions.voice_input_enabled != features_enabled ||
-      params->restrictions.handwriting_enabled != features_enabled) {
-    return RespondNow(
-        Error("All features are expected to have the same enabled state."));
-  }
-  VirtualKeyboardAPI* api =
-      BrowserContextKeyedAPIFactory<VirtualKeyboardAPI>::Get(browser_context());
-  api->delegate()->SetKeyboardRestricted(!features_enabled);
-
 #if defined(OS_CHROMEOS)
   InputMethodManager* input_method_manager = InputMethodManager::Get();
   if (input_method_manager) {
-    input_method_manager->SetImeMenuFeatureEnabled(
-        InputMethodManager::FEATURE_VOICE,
-        params->restrictions.voice_input_enabled);
-    input_method_manager->SetImeMenuFeatureEnabled(
-        InputMethodManager::FEATURE_HANDWRITING,
-        params->restrictions.handwriting_enabled);
+    if (params->restrictions.handwriting_enabled) {
+      input_method_manager->SetImeMenuFeatureEnabled(
+          InputMethodManager::FEATURE_HANDWRITING,
+          *params->restrictions.handwriting_enabled);
+    }
+    if (params->restrictions.voice_input_enabled) {
+      input_method_manager->SetImeMenuFeatureEnabled(
+          InputMethodManager::FEATURE_VOICE,
+          *params->restrictions.voice_input_enabled);
+    }
   }
 #endif
-  return RespondNow(NoArguments());
+
+  VirtualKeyboardAPI* api =
+      BrowserContextKeyedAPIFactory<VirtualKeyboardAPI>::Get(browser_context());
+  api::virtual_keyboard::FeatureRestrictions update =
+      api->delegate()->RestrictFeatures(*params);
+
+  return RespondNow(OneArgument(update.ToValue()));
 }
 
 }  // namespace extensions
diff --git a/extensions/browser/api/virtual_keyboard/virtual_keyboard_api.h b/extensions/browser/api/virtual_keyboard/virtual_keyboard_api.h
index 3bfd03f..2aa9825 100644
--- a/extensions/browser/api/virtual_keyboard/virtual_keyboard_api.h
+++ b/extensions/browser/api/virtual_keyboard/virtual_keyboard_api.h
@@ -7,6 +7,7 @@
 
 #include "base/macros.h"
 #include "extensions/browser/extension_function.h"
+#include "extensions/common/api/virtual_keyboard.h"
 
 namespace extensions {
 
diff --git a/extensions/browser/api/virtual_keyboard/virtual_keyboard_apitest.cc b/extensions/browser/api/virtual_keyboard/virtual_keyboard_apitest.cc
index b010268..c580c4c1 100644
--- a/extensions/browser/api/virtual_keyboard/virtual_keyboard_apitest.cc
+++ b/extensions/browser/api/virtual_keyboard/virtual_keyboard_apitest.cc
@@ -19,57 +19,6 @@
 
 namespace extensions {
 
-namespace {
-
-void ExtractIsRestrictedKeyboard(
-    bool* is_restricted,
-    std::unique_ptr<base::DictionaryValue> settings) {
-  ASSERT_TRUE(settings->GetBoolean("restricted", is_restricted));
-}
-
-// Handles "restrictedChanged" message from the test extension - the handler
-// responds to the the "restrictedChanged" message with a message indicating
-// whether advanced features are enabeled,
-class RestrictedChangedHandler : public content::NotificationObserver {
- public:
-  explicit RestrictedChangedHandler(VirtualKeyboardDelegate* delegate)
-      : delegate_(delegate) {
-    registrar_.Add(this, extensions::NOTIFICATION_EXTENSION_TEST_MESSAGE,
-                   content::NotificationService::AllSources());
-  }
-
-  void Observe(int type,
-               const content::NotificationSource& source,
-               const content::NotificationDetails& details) override {
-    DCHECK_EQ(extensions::NOTIFICATION_EXTENSION_TEST_MESSAGE, type);
-
-    std::pair<std::string, bool*>* message_details =
-        content::Details<std::pair<std::string, bool*>>(details).ptr();
-    if (message_details->first != "restrictedChanged")
-      return;
-
-    *message_details->second = true /* listener_will_respond */;
-
-    bool is_restricted = false;
-    delegate_->GetKeyboardConfig(
-        base::Bind(&ExtractIsRestrictedKeyboard, &is_restricted));
-
-    extensions::TestSendMessageFunction* function =
-        content::Source<extensions::TestSendMessageFunction>(source).ptr();
-    // The response should contain boolean indicating whether virtual keyboard
-    // advanced features are enabled.
-    function->Reply(is_restricted ? "false" : "true");
-  }
-
- private:
-  VirtualKeyboardDelegate* delegate_;
-  content::NotificationRegistrar registrar_;
-
-  DISALLOW_COPY_AND_ASSIGN(RestrictedChangedHandler);
-};
-
-}  // namespace
-
 class VirtualKeyboardApiTest : public ShellApiTest {
  public:
   VirtualKeyboardApiTest() {}
@@ -99,8 +48,6 @@
   ASSERT_TRUE(api);
   ASSERT_TRUE(api->delegate());
 
-  RestrictedChangedHandler restricted_changed_handler(api->delegate());
-
   EXPECT_TRUE(RunAppTest("api_test/virtual_keyboard"));
 }
 
diff --git a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h
index e940f16..db08ec278 100644
--- a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h
+++ b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h
@@ -13,6 +13,7 @@
 #include "base/strings/string16.h"
 #include "base/values.h"
 #include "content/public/browser/browser_thread.h"
+#include "extensions/common/api/virtual_keyboard.h"
 
 namespace extensions {
 
@@ -29,6 +30,10 @@
   virtual void GetKeyboardConfig(
       OnKeyboardSettingsCallback on_settings_callback) = 0;
 
+  // Notify keyboard config change through
+  // |chrome.virtualKeyboard.onKeyboardConfigChanged| event.
+  virtual void OnKeyboardConfigChanged() = 0;
+
   // Dismiss the virtual keyboard without changing input focus. Returns true if
   // successful.
   virtual bool HideKeyboard() = 0;
@@ -47,10 +52,6 @@
   // Sets the state of the hotrod virtual keyboad.
   virtual void SetHotrodKeyboard(bool enable) = 0;
 
-  // Sets the virtual keyboard in restricted state - i.e. state where advanced
-  // features like auto-correct, auto-complete, voice input are disabled.
-  virtual void SetKeyboardRestricted(bool restricted) = 0;
-
   // Activate and lock the virtual keyboad on screen or dismiss the keyboard
   // regardless of the state of text focus. Used in a11y mode to allow typing
   // hotkeys without the need for text focus. Returns true if successful.
@@ -76,6 +77,11 @@
 
   // Sets requested virtual keyboard state.
   virtual bool SetRequestedKeyboardState(int state_enum) = 0;
+
+  // Restricts the virtual keyboard IME features.
+  // Returns the values which were updated.
+  virtual api::virtual_keyboard::FeatureRestrictions RestrictFeatures(
+      const api::virtual_keyboard::RestrictFeatures::Params& params) = 0;
 };
 
 }  // namespace extensions
diff --git a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.cc b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.cc
index 5096c166d..f6ebe2a 100644
--- a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.cc
+++ b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.cc
@@ -144,7 +144,8 @@
 }
 
 VirtualKeyboardAPI::VirtualKeyboardAPI(content::BrowserContext* context) {
-  delegate_ = ExtensionsAPIClient::Get()->CreateVirtualKeyboardDelegate();
+  delegate_ =
+      ExtensionsAPIClient::Get()->CreateVirtualKeyboardDelegate(context);
 }
 
 VirtualKeyboardAPI::~VirtualKeyboardAPI() {
diff --git a/extensions/browser/extension_event_histogram_value.h b/extensions/browser/extension_event_histogram_value.h
index 8662d15c..86dd1be 100644
--- a/extensions/browser/extension_event_histogram_value.h
+++ b/extensions/browser/extension_event_histogram_value.h
@@ -429,7 +429,7 @@
   WEB_VIEW_INTERNAL_ON_AUDIO_STATE_CHANGED,
   AUTOMATION_INTERNAL_ON_ACTION_RESULT,
   OMNIBOX_ON_DELETE_SUGGESTION,
-  PASSWORDS_PRIVATE_ON_SHOW_IMPORT_EXPORT_BUTTONS,
+  VIRTUAL_KEYBOARD_PRIVATE_ON_KEYBOARD_CONFIG_CHANGED,
   // Last entry: Add new entries above, then run:
   // python tools/metrics/histograms/update_extension_histograms.py
   ENUM_BOUNDARY
diff --git a/extensions/browser/extension_host.cc b/extensions/browser/extension_host.cc
index 65dbedd..e85940e 100644
--- a/extensions/browser/extension_host.cc
+++ b/extensions/browser/extension_host.cc
@@ -13,6 +13,7 @@
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/native_web_keyboard_event.h"
 #include "content/public/browser/notification_service.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host_view.h"
@@ -249,7 +250,8 @@
   // During browser shutdown, we may use sudden termination on an extension
   // process, so it is expected to lose our connection to the render view.
   // Do nothing.
-  RenderProcessHost* process_host = host_contents_->GetRenderProcessHost();
+  RenderProcessHost* process_host =
+      host_contents_->GetMainFrame()->GetProcess();
   if (process_host && process_host->FastShutdownStarted())
     return;
 
diff --git a/extensions/browser/extension_protocols.cc b/extensions/browser/extension_protocols.cc
index 10cc848..9a3e73a 100644
--- a/extensions/browser/extension_protocols.cc
+++ b/extensions/browser/extension_protocols.cc
@@ -199,6 +199,16 @@
   }
 
   void GetResponseInfo(net::HttpResponseInfo* info) override {
+    // Set the mime type for the request. We do this here (rather than when we
+    // build the rest of the headers) because the mime type is retrieved only
+    // after URLRequestFileJob::Start() is called. Using an accurate mime type
+    // is necessary at least for modules, which enforce strict mime type
+    // requirements.
+    std::string mime_type;
+    bool found_mime_type = GetMimeType(&mime_type);
+    if (found_mime_type)
+      response_info_.headers->AddHeader("Content-Type: " + mime_type);
+
     *info = response_info_;
   }
 
diff --git a/extensions/browser/extension_registrar.cc b/extensions/browser/extension_registrar.cc
new file mode 100644
index 0000000..5967afa
--- /dev/null
+++ b/extensions/browser/extension_registrar.cc
@@ -0,0 +1,108 @@
+// 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 "extensions/browser/extension_registrar.h"
+
+#include "base/logging.h"
+#include "content/public/browser/browser_thread.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_system.h"
+#include "extensions/browser/renderer_startup_helper.h"
+
+namespace extensions {
+
+ExtensionRegistrar::ExtensionRegistrar(content::BrowserContext* browser_context)
+    : extension_system_(ExtensionSystem::Get(browser_context)),
+      registry_(ExtensionRegistry::Get(browser_context)),
+      renderer_helper_(
+          RendererStartupHelperFactory::GetForBrowserContext(browser_context)),
+      weak_factory_(this) {}
+
+ExtensionRegistrar::~ExtensionRegistrar() = default;
+
+void ExtensionRegistrar::EnableExtension(
+    scoped_refptr<const Extension> extension) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  registry_->RemoveDisabled(extension->id());
+  registry_->AddEnabled(extension);
+
+  // The URLRequestContexts need to be first to know that the extension
+  // was loaded. Otherwise a race can arise where a renderer that is created
+  // for the extension may try to load an extension URL with an extension id
+  // that the request context doesn't yet know about. The BrowserContext should
+  // ensure its URLRequestContexts appropriately discover the loaded extension.
+  extension_system_->RegisterExtensionWithRequestContexts(
+      extension.get(),
+      base::Bind(&ExtensionRegistrar::OnExtensionRegisteredWithRequestContexts,
+                 weak_factory_.GetWeakPtr(), extension));
+
+  renderer_helper_->OnExtensionLoaded(*extension);
+
+  // Tell subsystems that use the ExtensionRegistryObserver::OnExtensionLoaded
+  // about the new extension.
+  //
+  // NOTE: It is important that this happen after notifying the renderers about
+  // the new extensions so that if we navigate to an extension URL in
+  // ExtensionRegistryObserver::OnExtensionLoaded the renderer is guaranteed to
+  // know about it.
+  registry_->TriggerOnLoaded(extension.get());
+}
+
+void ExtensionRegistrar::DisableExtension(
+    scoped_refptr<const Extension> extension) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  // Move the extension to the disabled list.
+  registry_->RemoveEnabled(extension->id());
+  registry_->AddDisabled(extension);
+
+  DeactivateExtension(extension.get(), UnloadedExtensionReason::DISABLE);
+  NotifyExtensionDisabledOrRemoved(extension->id(),
+                                   UnloadedExtensionReason::DISABLE);
+}
+
+void ExtensionRegistrar::RemoveExtension(const ExtensionId& extension_id,
+                                         UnloadedExtensionReason reason) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  int include_mask =
+      ExtensionRegistry::EVERYTHING & ~ExtensionRegistry::TERMINATED;
+  scoped_refptr<const Extension> extension(
+      registry_->GetExtensionById(extension_id, include_mask));
+
+  if (registry_->disabled_extensions().Contains(extension_id)) {
+    registry_->RemoveDisabled(extension_id);
+    // The extension is already deactivated.
+  } else if (extension) {
+    registry_->RemoveEnabled(extension_id);
+    DeactivateExtension(extension.get(), reason);
+  }
+
+  NotifyExtensionDisabledOrRemoved(extension_id, reason);
+}
+
+void ExtensionRegistrar::DeactivateExtension(const Extension* extension,
+                                             UnloadedExtensionReason reason) {
+  registry_->TriggerOnUnloaded(extension, reason);
+  renderer_helper_->OnExtensionUnloaded(*extension);
+}
+
+void ExtensionRegistrar::NotifyExtensionDisabledOrRemoved(
+    const ExtensionId& extension_id,
+    UnloadedExtensionReason reason) {
+  extension_system_->UnregisterExtensionWithRequestContexts(extension_id,
+                                                            reason);
+}
+
+void ExtensionRegistrar::OnExtensionRegisteredWithRequestContexts(
+    scoped_refptr<const Extension> extension) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  registry_->AddReady(extension);
+  if (registry_->enabled_extensions().Contains(extension->id()))
+    registry_->TriggerOnReady(extension.get());
+}
+
+}  // namespace extensions
diff --git a/extensions/browser/extension_registrar.h b/extensions/browser/extension_registrar.h
new file mode 100644
index 0000000..b8b5015a
--- /dev/null
+++ b/extensions/browser/extension_registrar.h
@@ -0,0 +1,82 @@
+// 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 EXTENSIONS_BROWSER_EXTENSION_REGISTRAR_H_
+#define EXTENSIONS_BROWSER_EXTENSION_REGISTRAR_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "extensions/common/extension.h"
+
+namespace content {
+class BrowserContext;
+}  // namespace content
+
+namespace extensions {
+
+class Extension;
+class ExtensionRegistry;
+class ExtensionSystem;
+class RendererStartupHelper;
+
+// ExtensionRegistrar drives the stages of registering and unregistering
+// extensions for a BrowserContext.
+// TODO(michaelpg): Add functionality for reloading and terminating extensions.
+class ExtensionRegistrar {
+ public:
+  explicit ExtensionRegistrar(content::BrowserContext* browser_context);
+  virtual ~ExtensionRegistrar();
+
+  // Marks |extension| enabled and notifies other components about it.
+  // TODO(michaelpg): Move other steps and checks for enabling the extension
+  // from ExtensionService::EnableExtension into here.
+  void EnableExtension(scoped_refptr<const Extension> extension);
+
+  // Marks |extension| disabled and notifies other components that it is
+  // disabled. The ExtensionRegistry retains a reference to it in
+  // disabled_extensions().
+  // TODO(michaelpg): Move other steps for disabling the extension from
+  // ExtensionService::DisableExtension into here.
+  void DisableExtension(scoped_refptr<const Extension> extension);
+
+  // Removes |extension| from the extension system by deactivating it if it is
+  // enabled and removing references to it from the ExtensionRegistry's enabled
+  // or disabled sets.
+  // Note: Extensions will not be removed from other sets (terminated,
+  // blacklisted or blocked). ExtensionService handles that, since it also adds
+  // it to those sets. TODO(michaelpg): Make ExtensionRegistrar the sole mutator
+  // of ExtensionRegsitry to simplify this usage.
+  void RemoveExtension(const ExtensionId& extension_id,
+                       UnloadedExtensionReason reason);
+
+ private:
+  // Triggers the unloaded notifications to deactivate an extension.
+  void DeactivateExtension(const Extension* extension,
+                           UnloadedExtensionReason reason);
+
+  // Updates the ExtensionSystem when an extension is disabled or removed (even
+  // if it was already disabled or terminated). Necessary because
+  // ExtensionSystem tracks enabled and disabled extensions separately.
+  void NotifyExtensionDisabledOrRemoved(const ExtensionId& extension_id,
+                                        UnloadedExtensionReason reason);
+
+  // Marks the extension ready after URLRequestContexts have been updated on
+  // the IO thread.
+  void OnExtensionRegisteredWithRequestContexts(
+      scoped_refptr<const Extension> extension);
+
+  // These objects should outlive the service that owns us (ExtensionService).
+  ExtensionSystem* const extension_system_;
+  ExtensionRegistry* const registry_;
+  extensions::RendererStartupHelper* renderer_helper_;
+
+  base::WeakPtrFactory<ExtensionRegistrar> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExtensionRegistrar);
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_BROWSER_EXTENSION_REGISTRAR_H_
diff --git a/extensions/browser/extension_registrar_unittest.cc b/extensions/browser/extension_registrar_unittest.cc
new file mode 100644
index 0000000..290005c
--- /dev/null
+++ b/extensions/browser/extension_registrar_unittest.cc
@@ -0,0 +1,165 @@
+// 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 "extensions/browser/extension_registrar.h"
+
+#include <memory>
+
+#include "base/location.h"
+#include "base/macros.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 "extensions/browser/extension_registry.h"
+#include "extensions/browser/extensions_test.h"
+#include "extensions/browser/test_extension_registry_observer.h"
+#include "extensions/browser/test_extensions_browser_client.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/extension_builder.h"
+
+namespace extensions {
+
+namespace {
+
+class TestExtensionSystem : public MockExtensionSystem {
+ public:
+  explicit TestExtensionSystem(content::BrowserContext* context)
+      : MockExtensionSystem(context) {}
+
+  ~TestExtensionSystem() override {}
+
+  void RegisterExtensionWithRequestContexts(
+      const Extension* extension,
+      const base::Closure& callback) override {
+    base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestExtensionSystem);
+};
+
+}  // namespace
+
+class ExtensionRegistrarTest : public ExtensionsTest {
+ public:
+  ExtensionRegistrarTest()
+      : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>()) {}
+  ~ExtensionRegistrarTest() override = default;
+
+  void SetUp() override {
+    ExtensionsTest::SetUp();
+    extensions_browser_client()->set_extension_system_factory(&factory_);
+    extension_ = ExtensionBuilder("extension").Build();
+  }
+
+ protected:
+  // Verifies that the extension is in the given set in the ExtensionRegistry
+  // and not in other sets.
+  void ExpectInSet(ExtensionRegistry::IncludeFlag set_id) {
+    ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
+
+    EXPECT_EQ(set_id == ExtensionRegistry::ENABLED,
+              registry->enabled_extensions().Contains(extension_->id()));
+
+    EXPECT_EQ(set_id == ExtensionRegistry::DISABLED,
+              registry->disabled_extensions().Contains(extension_->id()));
+
+    EXPECT_EQ(set_id == ExtensionRegistry::TERMINATED,
+              registry->terminated_extensions().Contains(extension_->id()));
+
+    EXPECT_EQ(set_id == ExtensionRegistry::BLACKLISTED,
+              registry->blacklisted_extensions().Contains(extension_->id()));
+
+    EXPECT_EQ(set_id == ExtensionRegistry::BLOCKED,
+              registry->blocked_extensions().Contains(extension_->id()));
+  }
+
+  bool IsExtensionReady() {
+    return ExtensionRegistry::Get(browser_context())
+        ->ready_extensions()
+        .Contains(extension_->id());
+  }
+
+  scoped_refptr<const Extension> extension() const { return extension_; }
+
+ private:
+  MockExtensionSystemFactory<TestExtensionSystem> factory_;
+  scoped_refptr<const Extension> extension_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExtensionRegistrarTest);
+};
+
+// Adds and removes an extension.
+TEST_F(ExtensionRegistrarTest, EnableAndRemove) {
+  ExtensionRegistry* extension_registry =
+      ExtensionRegistry::Get(browser_context());
+  ExtensionRegistrar registrar(browser_context());
+
+  registrar.EnableExtension(extension());
+  ExpectInSet(ExtensionRegistry::ENABLED);
+  EXPECT_FALSE(IsExtensionReady());
+
+  TestExtensionRegistryObserver observer(extension_registry);
+  observer.WaitForExtensionReady();
+  EXPECT_TRUE(IsExtensionReady());
+
+  // Calling RemoveExtension removes its entry from the enabled list and then
+  // removes the extension.
+  registrar.RemoveExtension(extension()->id(),
+                            UnloadedExtensionReason::UNINSTALL);
+  ExpectInSet(ExtensionRegistry::NONE);
+}
+
+// Disables an extension before removing it.
+TEST_F(ExtensionRegistrarTest, EnableDisableAndRemove) {
+  ExtensionRegistry* extension_registry =
+      ExtensionRegistry::Get(browser_context());
+  ExtensionRegistrar registrar(browser_context());
+
+  registrar.EnableExtension(extension());
+  ExpectInSet(ExtensionRegistry::ENABLED);
+  EXPECT_FALSE(IsExtensionReady());
+
+  TestExtensionRegistryObserver observer(extension_registry);
+  observer.WaitForExtensionReady();
+  EXPECT_TRUE(IsExtensionReady());
+
+  // Disabling the extension deactivates it.
+  registrar.DisableExtension(extension());
+  ExpectInSet(ExtensionRegistry::DISABLED);
+  EXPECT_FALSE(IsExtensionReady());
+
+  // We can still call RemoveExtension to remove its entry from the disabled
+  // list and remove the extension.
+  registrar.RemoveExtension(extension()->id(),
+                            UnloadedExtensionReason::UNINSTALL);
+  ExpectInSet(ExtensionRegistry::NONE);
+  EXPECT_FALSE(IsExtensionReady());
+}
+
+// Enables a disabled extension.
+TEST_F(ExtensionRegistrarTest, EnableDisabled) {
+  ExtensionRegistry* extension_registry =
+      ExtensionRegistry::Get(browser_context());
+  ExtensionRegistrar registrar(browser_context());
+
+  registrar.EnableExtension(extension());
+  ExpectInSet(ExtensionRegistry::ENABLED);
+  EXPECT_FALSE(IsExtensionReady());
+  TestExtensionRegistryObserver(extension_registry).WaitForExtensionReady();
+
+  registrar.DisableExtension(extension());
+  ExpectInSet(ExtensionRegistry::DISABLED);
+  EXPECT_FALSE(IsExtensionReady());
+
+  registrar.EnableExtension(extension());
+  ExpectInSet(ExtensionRegistry::ENABLED);
+  TestExtensionRegistryObserver(extension_registry).WaitForExtensionReady();
+
+  registrar.RemoveExtension(extension()->id(),
+                            UnloadedExtensionReason::UNINSTALL);
+  ExpectInSet(ExtensionRegistry::NONE);
+}
+
+}  // namespace extensions
diff --git a/extensions/browser/extension_system.h b/extensions/browser/extension_system.h
index 49dc3116..fe42fc2 100644
--- a/extensions/browser/extension_system.h
+++ b/extensions/browser/extension_system.h
@@ -57,7 +57,8 @@
   // controlled by |extensions_enabled|.
   virtual void InitForRegularProfile(bool extensions_enabled) = 0;
 
-  // The ExtensionService is created at startup.
+  // The ExtensionService is created at startup. ExtensionService is only
+  // defined in Chrome.
   virtual ExtensionService* extension_service() = 0;
 
   // Per-extension data that can change during the life of the process but
diff --git a/extensions/browser/external_install_info.cc b/extensions/browser/external_install_info.cc
index d37c0f38..879e8379 100644
--- a/extensions/browser/external_install_info.cc
+++ b/extensions/browser/external_install_info.cc
@@ -4,9 +4,6 @@
 
 #include "extensions/browser/external_install_info.h"
 
-#include "base/version.h"
-#include "url/gurl.h"
-
 namespace extensions {
 
 ExternalInstallInfo::ExternalInstallInfo(const std::string& extension_id,
@@ -18,14 +15,14 @@
 
 ExternalInstallInfoFile::ExternalInstallInfoFile(
     const std::string& extension_id,
-    std::unique_ptr<base::Version> version,
+    const base::Version& version,
     const base::FilePath& path,
     Manifest::Location crx_location,
     int creation_flags,
     bool mark_acknowledged,
     bool install_immediately)
     : ExternalInstallInfo(extension_id, creation_flags, mark_acknowledged),
-      version(std::move(version)),
+      version(version),
       path(path),
       crx_location(crx_location),
       install_immediately(install_immediately) {}
@@ -35,7 +32,7 @@
 ExternalInstallInfoUpdateUrl::ExternalInstallInfoUpdateUrl(
     const std::string& extension_id,
     const std::string& install_parameter,
-    std::unique_ptr<GURL> update_url,
+    GURL update_url,
     Manifest::Location download_location,
     int creation_flags,
     bool mark_acknowledged)
diff --git a/extensions/browser/external_install_info.h b/extensions/browser/external_install_info.h
index 39b42a0..aeb103f 100644
--- a/extensions/browser/external_install_info.h
+++ b/extensions/browser/external_install_info.h
@@ -6,13 +6,9 @@
 #define EXTENSIONS_BROWSER_EXTERNAL_INSTALL_INFO_H_
 
 #include "base/files/file_path.h"
+#include "base/version.h"
 #include "extensions/common/manifest.h"
-
-class GURL;
-
-namespace base {
-class Version;
-}
+#include "url/gurl.h"
 
 namespace extensions {
 
@@ -34,7 +30,7 @@
 
 struct ExternalInstallInfoFile : public ExternalInstallInfo {
   ExternalInstallInfoFile(const std::string& extension_id,
-                          std::unique_ptr<base::Version> version,
+                          const base::Version& version,
                           const base::FilePath& path,
                           Manifest::Location crx_location,
                           int creation_flags,
@@ -42,7 +38,7 @@
                           bool install_immediately);
   ~ExternalInstallInfoFile() override;
 
-  std::unique_ptr<base::Version> version;
+  base::Version version;
   base::FilePath path;
   Manifest::Location crx_location;
   bool install_immediately;
@@ -51,14 +47,14 @@
 struct ExternalInstallInfoUpdateUrl : public ExternalInstallInfo {
   ExternalInstallInfoUpdateUrl(const std::string& extension_id,
                                const std::string& install_parameter,
-                               std::unique_ptr<GURL> update_url,
+                               GURL update_url,
                                Manifest::Location download_location,
                                int creation_flags,
                                bool mark_acknowledged);
   ~ExternalInstallInfoUpdateUrl() override;
 
   std::string install_parameter;
-  std::unique_ptr<GURL> update_url;
+  GURL update_url;
   Manifest::Location download_location;
 };
 
diff --git a/extensions/browser/guest_view/extension_options/extension_options_guest.cc b/extensions/browser/guest_view/extension_options/extension_options_guest.cc
index 586eee3..19fef02ef 100644
--- a/extensions/browser/guest_view/extension_options/extension_options_guest.cc
+++ b/extensions/browser/guest_view/extension_options/extension_options_guest.cc
@@ -4,6 +4,8 @@
 
 #include "extensions/browser/guest_view/extension_options/extension_options_guest.h"
 
+#include <memory>
+#include <string>
 #include <utility>
 
 #include "base/memory/ptr_util.h"
@@ -12,6 +14,7 @@
 #include "components/guest_view/browser/guest_view_event.h"
 #include "components/guest_view/browser/guest_view_manager.h"
 #include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/web_contents.h"
@@ -226,8 +229,9 @@
   SetGuestZoomLevelToMatchEmbedder();
 
   if (!url::IsSameOriginWith(navigation_handle->GetURL(), options_page_)) {
-    bad_message::ReceivedBadMessage(web_contents()->GetRenderProcessHost(),
-                                    bad_message::EOG_BAD_ORIGIN);
+    bad_message::ReceivedBadMessage(
+        web_contents()->GetMainFrame()->GetProcess(),
+        bad_message::EOG_BAD_ORIGIN);
   }
 }
 
diff --git a/extensions/browser/guest_view/extension_view/extension_view_guest.cc b/extensions/browser/guest_view/extension_view/extension_view_guest.cc
index d147808..4dbd7464 100644
--- a/extensions/browser/guest_view/extension_view/extension_view_guest.cc
+++ b/extensions/browser/guest_view/extension_view/extension_view_guest.cc
@@ -4,12 +4,15 @@
 
 #include "extensions/browser/guest_view/extension_view/extension_view_guest.h"
 
+#include <memory>
+#include <string>
 #include <utility>
 
 #include "base/memory/ptr_util.h"
 #include "components/crx_file/id_util.h"
 #include "components/guest_view/browser/guest_view_event.h"
 #include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/common/result_codes.h"
 #include "extensions/browser/api/extensions_api_client.h"
@@ -56,7 +59,7 @@
   if (!force_navigation && (url_ == url))
     return false;
 
-  web_contents()->GetRenderProcessHost()->FilterURL(false, &url);
+  web_contents()->GetMainFrame()->GetProcess()->FilterURL(false, &url);
   web_contents()->GetController().LoadURL(url, content::Referrer(),
                                           ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
                                           std::string());
diff --git a/extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc b/extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc
index 8ded24e..1661c0c 100644
--- a/extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc
+++ b/extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc
@@ -4,12 +4,14 @@
 
 #include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h"
 
+#include <memory>
 #include <utility>
 
 #include "components/guest_view/browser/guest_view_base.h"
 #include "components/guest_view/browser/guest_view_manager.h"
 #include "components/guest_view/common/guest_view_constants.h"
 #include "content/public/browser/browser_context.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "extensions/browser/api/extensions_api_client.h"
@@ -85,7 +87,7 @@
       owner_extension,
       process_map->GetMostLikelyContextType(
           owner_extension,
-          guest->owner_web_contents()->GetRenderProcessHost()->GetID()),
+          guest->owner_web_contents()->GetMainFrame()->GetProcess()->GetID()),
       guest->GetOwnerSiteURL());
 
   return availability.is_available();
diff --git a/extensions/browser/guest_view/web_view/web_view_apitest.cc b/extensions/browser/guest_view/web_view/web_view_apitest.cc
index f7ad7faf..abbdd6a 100644
--- a/extensions/browser/guest_view/web_view/web_view_apitest.cc
+++ b/extensions/browser/guest_view/web_view/web_view_apitest.cc
@@ -4,6 +4,8 @@
 
 #include "extensions/browser/guest_view/web_view/web_view_apitest.h"
 
+#include <memory>
+#include <string>
 #include <utility>
 
 #include "base/command_line.h"
@@ -17,6 +19,7 @@
 #include "components/guest_view/browser/guest_view_manager_delegate.h"
 #include "components/guest_view/browser/guest_view_manager_factory.h"
 #include "components/guest_view/browser/test_guest_view_manager.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
@@ -689,7 +692,8 @@
                                      "runTest('testRemoveWebviewOnExit')"));
 
   content::WebContents* guest_web_contents = GetGuestWebContents();
-  EXPECT_TRUE(guest_web_contents->GetRenderProcessHost()->IsForGuestsOnly());
+  EXPECT_TRUE(
+      guest_web_contents->GetMainFrame()->GetProcess()->IsForGuestsOnly());
   ASSERT_TRUE(guest_loaded_listener.WaitUntilSatisfied());
 
   content::WebContentsDestroyedWatcher destroyed_watcher(guest_web_contents);
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc
index 4b84823..c0513f04f 100644
--- a/extensions/browser/guest_view/web_view/web_view_guest.cc
+++ b/extensions/browser/guest_view/web_view/web_view_guest.cc
@@ -6,6 +6,9 @@
 
 #include <stddef.h>
 
+#include <map>
+#include <memory>
+#include <string>
 #include <utility>
 
 #include "base/lazy_instance.h"
@@ -25,6 +28,7 @@
 #include "content/public/browser/native_web_keyboard_event.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
@@ -320,7 +324,7 @@
     const base::DictionaryValue& create_params,
     const WebContentsCreatedCallback& callback) {
   RenderProcessHost* owner_render_process_host =
-      owner_web_contents()->GetRenderProcessHost();
+      owner_web_contents()->GetMainFrame()->GetProcess();
   std::string storage_partition_id;
   bool persist_storage = false;
   ParsePartitionParam(create_params, &storage_partition_id, &persist_storage);
@@ -393,7 +397,7 @@
   web_view_permission_helper_ = std::make_unique<WebViewPermissionHelper>(this);
 
   rules_registry_id_ = GetOrGenerateRulesRegistryID(
-      owner_web_contents()->GetRenderProcessHost()->GetID(),
+      owner_web_contents()->GetMainFrame()->GetProcess()->GetID(),
       view_instance_id());
 
   // We must install the mapping from guests to WebViews prior to resuming
@@ -484,7 +488,7 @@
 
 void WebViewGuest::GuestReady() {
   // The guest RenderView should always live in an isolated guest process.
-  CHECK(web_contents()->GetRenderProcessHost()->IsForGuestsOnly());
+  CHECK(web_contents()->GetMainFrame()->GetProcess()->IsForGuestsOnly());
   content::RenderFrameHost* main_frame = web_contents()->GetMainFrame();
   main_frame->Send(
       new ExtensionMsg_SetFrameName(main_frame->GetRoutingID(), name_));
@@ -666,7 +670,7 @@
 void WebViewGuest::RendererResponsive(WebContents* source) {
   auto args = std::make_unique<base::DictionaryValue>();
   args->SetInteger(webview::kProcessId,
-                   web_contents()->GetRenderProcessHost()->GetID());
+                   web_contents()->GetMainFrame()->GetProcess()->GetID());
   DispatchEventToView(std::make_unique<GuestViewEvent>(
       webview::kEventResponsive, std::move(args)));
 }
@@ -676,7 +680,7 @@
     const content::WebContentsUnresponsiveState& unresponsive_state) {
   auto args = std::make_unique<base::DictionaryValue>();
   args->SetInteger(webview::kProcessId,
-                   web_contents()->GetRenderProcessHost()->GetID());
+                   web_contents()->GetMainFrame()->GetProcess()->GetID());
   DispatchEventToView(std::make_unique<GuestViewEvent>(
       webview::kEventUnresponsive, std::move(args)));
 }
@@ -725,9 +729,9 @@
 void WebViewGuest::Terminate() {
   base::RecordAction(UserMetricsAction("WebView.Guest.Terminate"));
   base::ProcessHandle process_handle =
-      web_contents()->GetRenderProcessHost()->GetHandle();
+      web_contents()->GetMainFrame()->GetProcess()->GetHandle();
   if (process_handle)
-    web_contents()->GetRenderProcessHost()->Shutdown(
+    web_contents()->GetMainFrame()->GetProcess()->Shutdown(
         content::RESULT_CODE_KILLED, false);
 }
 
@@ -746,7 +750,8 @@
   if (removal_mask & webview::WEB_VIEW_REMOVE_DATA_MASK_CACHE) {
     // First clear http cache data and then clear the rest in
     // |ClearDataInternal|.
-    int render_process_id = web_contents()->GetRenderProcessHost()->GetID();
+    int render_process_id =
+        web_contents()->GetMainFrame()->GetProcess()->GetID();
     // We need to clear renderer cache separately for our process because
     // StoragePartitionHttpCacheDataRemover::ClearData() does not clear that.
     web_cache::WebCacheManager::GetInstance()->ClearCacheForProcess(
@@ -831,7 +836,7 @@
   args->SetInteger(webview::kInternalEntryCount,
                    web_contents()->GetController().GetEntryCount());
   args->SetInteger(webview::kInternalProcessId,
-                   web_contents()->GetRenderProcessHost()->GetID());
+                   web_contents()->GetMainFrame()->GetProcess()->GetID());
   DispatchEventToView(std::make_unique<GuestViewEvent>(
       webview::kEventLoadCommit, std::move(args)));
 
@@ -863,7 +868,7 @@
 
   auto args = std::make_unique<base::DictionaryValue>();
   args->SetInteger(webview::kProcessId,
-                   web_contents()->GetRenderProcessHost()->GetID());
+                   web_contents()->GetMainFrame()->GetProcess()->GetID());
   args->SetString(webview::kReason, TerminationStatusToString(status));
   DispatchEventToView(
       std::make_unique<GuestViewEvent>(webview::kEventExit, std::move(args)));
@@ -922,7 +927,7 @@
 
   WebViewRendererState::WebViewInfo web_view_info;
   web_view_info.embedder_process_id =
-      owner_web_contents()->GetRenderProcessHost()->GetID();
+      owner_web_contents()->GetMainFrame()->GetProcess()->GetID();
   web_view_info.instance_id = view_instance_id();
   web_view_info.partition_id = partition_id;
   web_view_info.owner_host = owner_host();
@@ -939,7 +944,7 @@
       content::BrowserThread::IO, FROM_HERE,
       base::Bind(&WebViewRendererState::AddGuest,
                  base::Unretained(WebViewRendererState::GetInstance()),
-                 web_contents()->GetRenderProcessHost()->GetID(),
+                 web_contents()->GetRenderViewHost()->GetProcess()->GetID(),
                  web_contents()->GetRenderViewHost()->GetRoutingID(),
                  web_view_info));
 }
@@ -951,7 +956,7 @@
       content::BrowserThread::IO, FROM_HERE,
       base::Bind(&WebViewRendererState::RemoveGuest,
                  base::Unretained(WebViewRendererState::GetInstance()),
-                 web_contents->GetRenderProcessHost()->GetID(),
+                 web_contents->GetRenderViewHost()->GetProcess()->GetID(),
                  web_contents->GetRenderViewHost()->GetRoutingID()));
 }
 
@@ -995,7 +1000,7 @@
 
 void WebViewGuest::WillAttachToEmbedder() {
   rules_registry_id_ = GetOrGenerateRulesRegistryID(
-      owner_web_contents()->GetRenderProcessHost()->GetID(),
+      owner_web_contents()->GetMainFrame()->GetProcess()->GetID(),
       view_instance_id());
 
   // We must install the mapping from guests to WebViews prior to resuming
@@ -1391,7 +1396,8 @@
     return;
 
   GURL validated_url(url);
-  web_contents()->GetRenderProcessHost()->FilterURL(false, &validated_url);
+  web_contents()->GetMainFrame()->GetProcess()->FilterURL(false,
+                                                          &validated_url);
   // As guests do not swap processes on navigation, only navigations to
   // normal web URLs are supported.  No protocol handlers are installed for
   // other schemes (e.g., WebUI or extensions), and no permissions or bindings
@@ -1463,9 +1469,9 @@
     int new_window_instance_id,
     bool allow,
     const std::string& user_input) {
-  auto* guest =
-      WebViewGuest::From(owner_web_contents()->GetRenderProcessHost()->GetID(),
-                         new_window_instance_id);
+  auto* guest = WebViewGuest::From(
+      owner_web_contents()->GetMainFrame()->GetProcess()->GetID(),
+      new_window_instance_id);
   if (!guest)
     return;
 
diff --git a/extensions/browser/mock_external_provider.cc b/extensions/browser/mock_external_provider.cc
index db82fcdd..988bdb2 100644
--- a/extensions/browser/mock_external_provider.cc
+++ b/extensions/browser/mock_external_provider.cc
@@ -4,7 +4,8 @@
 
 #include "extensions/browser/mock_external_provider.h"
 
-#include "base/memory/ptr_util.h"
+#include <memory>
+
 #include "base/version.h"
 #include "extensions/browser/external_install_info.h"
 #include "extensions/common/extension.h"
@@ -20,10 +21,9 @@
 void MockExternalProvider::UpdateOrAddExtension(const ExtensionId& id,
                                                 const std::string& version_str,
                                                 const base::FilePath& path) {
-  auto version = std::make_unique<base::Version>(version_str);
   auto info = std::make_unique<ExternalInstallInfoFile>(
-      id, std::move(version), path, location_, Extension::NO_FLAGS, false,
-      false);
+      id, base::Version(version_str), path, location_, Extension::NO_FLAGS,
+      false, false);
   extension_map_[id] = std::move(info);
 }
 
@@ -57,7 +57,7 @@
     return false;
 
   if (version)
-    version->reset(new base::Version(it->second->version->GetString()));
+    version->reset(new base::Version(it->second->version));
 
   if (location)
     *location = location_;
diff --git a/extensions/browser/test_extension_registry_observer.cc b/extensions/browser/test_extension_registry_observer.cc
index d97aff7..2a5ab70 100644
--- a/extensions/browser/test_extension_registry_observer.cc
+++ b/extensions/browser/test_extension_registry_observer.cc
@@ -46,6 +46,7 @@
     : will_be_installed_waiter_(new Waiter()),
       uninstalled_waiter_(new Waiter()),
       loaded_waiter_(new Waiter()),
+      ready_waiter_(new Waiter()),
       unloaded_waiter_(new Waiter()),
       extension_registry_observer_(this),
       extension_id_(extension_id) {
@@ -72,6 +73,10 @@
   return Wait(&unloaded_waiter_);
 }
 
+const Extension* TestExtensionRegistryObserver::WaitForExtensionReady() {
+  return Wait(&ready_waiter_);
+}
+
 void TestExtensionRegistryObserver::OnExtensionWillBeInstalled(
     content::BrowserContext* browser_context,
     const Extension* extension,
@@ -96,6 +101,13 @@
     loaded_waiter_->OnObserved(extension);
 }
 
+void TestExtensionRegistryObserver::OnExtensionReady(
+    content::BrowserContext* browser_context,
+    const Extension* extension) {
+  if (extension_id_.empty() || extension->id() == extension_id_)
+    ready_waiter_->OnObserved(extension);
+}
+
 void TestExtensionRegistryObserver::OnExtensionUnloaded(
     content::BrowserContext* browser_context,
     const Extension* extension,
diff --git a/extensions/browser/test_extension_registry_observer.h b/extensions/browser/test_extension_registry_observer.h
index 5676c04..a7f977a 100644
--- a/extensions/browser/test_extension_registry_observer.h
+++ b/extensions/browser/test_extension_registry_observer.h
@@ -30,6 +30,7 @@
   const Extension* WaitForExtensionWillBeInstalled();
   const Extension* WaitForExtensionUninstalled();
   const Extension* WaitForExtensionLoaded();
+  const Extension* WaitForExtensionReady();
   const Extension* WaitForExtensionUnloaded();
 
  private:
@@ -45,6 +46,8 @@
                               extensions::UninstallReason reason) override;
   void OnExtensionLoaded(content::BrowserContext* browser_context,
                          const Extension* extension) override;
+  void OnExtensionReady(content::BrowserContext* browser_context,
+                        const Extension* extension) override;
   void OnExtensionUnloaded(content::BrowserContext* browser_context,
                            const Extension* extension,
                            UnloadedExtensionReason reason) override;
@@ -54,6 +57,7 @@
   std::unique_ptr<Waiter> will_be_installed_waiter_;
   std::unique_ptr<Waiter> uninstalled_waiter_;
   std::unique_ptr<Waiter> loaded_waiter_;
+  std::unique_ptr<Waiter> ready_waiter_;
   std::unique_ptr<Waiter> unloaded_waiter_;
 
   ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
diff --git a/extensions/common/BUILD.gn b/extensions/common/BUILD.gn
index 52ecdc9..a46a85f4 100644
--- a/extensions/common/BUILD.gn
+++ b/extensions/common/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/config/features.gni")
+import("//components/nacl/features.gni")
 import("//extensions/features/features.gni")
 import("//mojo/public/tools/bindings/mojom.gni")
 
diff --git a/extensions/common/api/messaging/message.h b/extensions/common/api/messaging/message.h
index 64ecb82..3f34e66 100644
--- a/extensions/common/api/messaging/message.h
+++ b/extensions/common/api/messaging/message.h
@@ -15,6 +15,10 @@
   Message() : data(), user_gesture(false) {}
   Message(const std::string& data, bool user_gesture)
       : data(data), user_gesture(user_gesture) {}
+
+  bool operator==(const Message& other) const {
+    return data == other.data && user_gesture == other.user_gesture;
+  }
 };
 
 }  // namespace extensions
diff --git a/extensions/common/api/virtual_keyboard.idl b/extensions/common/api/virtual_keyboard.idl
index c3260567..7cd01178 100644
--- a/extensions/common/api/virtual_keyboard.idl
+++ b/extensions/common/api/virtual_keyboard.idl
@@ -6,31 +6,33 @@
 // configure virtual keyboard layout and behavior in kiosk sessions.
 [platforms=("chromeos")]
 namespace virtualKeyboard {
-  callback EmptyCallback = void();
-
   // <p>Determines whether advanced virtual keyboard features should be enabled
-  //     or not.</p>
+  //     or not. They are enabled by default.</p>
   // <p>On <b>Chrome 58</b> all properties are expected to have the same value.
-  //     </p>
+  // </p>
+  // <p>From <b>Chrome 63</b> the properties can be distinct and are optional.
+  // If omitted, the current value is preserved.</p>
   dictionary FeatureRestrictions {
     // Whether virtual keyboards can provide auto-complete.
-    boolean autoCompleteEnabled;
+    boolean? autoCompleteEnabled;
     // Whether virtual keyboards can provide auto-correct.
-    boolean autoCorrectEnabled;
+    boolean? autoCorrectEnabled;
+    // Whether virtual keyboards can provide input via handwriting recognition.
+    boolean? handwritingEnabled;
     // Whether virtual keyboards can provide spell-check.
-    boolean spellCheckEnabled;
+    boolean? spellCheckEnabled;
     // Whether virtual keyboards can provide voice input.
-    boolean voiceInputEnabled;
-    // Whether virtual keyboards can provide input via handwriting
-    // recognition.
-    boolean handwritingEnabled;
+    boolean? voiceInputEnabled;
   };
 
+  callback RestrictFeaturesCallback = void(FeatureRestrictions update);
+
   interface Functions {
     // Sets restrictions on features provided by the virtual keyboard.
-    // |restrictions|: Defines the set of enabled/disabled virtual keyboard
-    //     features.
+    // |restrictions|: the preferences to enabled/disabled virtual keyboard
+    // features.
+    // |callback|: Invoked with the values which were updated.
     void restrictFeatures(FeatureRestrictions restrictions,
-                          optional EmptyCallback callback);
+                          optional RestrictFeaturesCallback callback);
   };
 };
diff --git a/extensions/common/api/virtual_keyboard_private.json b/extensions/common/api/virtual_keyboard_private.json
index 90de6d4e..e3b2a1b 100644
--- a/extensions/common/api/virtual_keyboard_private.json
+++ b/extensions/common/api/virtual_keyboard_private.json
@@ -49,6 +49,30 @@
           "width": {"type": "integer", "description": "The width of the virtual keyboard window."},
           "height": {"type": "integer", "description": "The height of the virtual keyboard window."}
         }
+      },
+      {
+        "id": "KeyboardConfig",
+        "type": "object",
+        "properties": {
+          "layout": {
+            "type": "string",
+            "minLength": 1,
+            "description": "Virtual keyboard layout string."
+          },
+          "hotrodmode": {
+            "type": "boolean",
+            "description": "Virtual keyboard is in hotrod mode."
+          },
+          "a11ymode": {
+            "type": "boolean",
+            "description": "True if accessibility virtual keyboard is enabled."
+          },
+          "features": {
+            "type": "array",
+            "items": { "type": "string" },
+            "description": "List of experimental feature flags."
+          }
+        }
       }
     ],
     "functions": [
@@ -142,32 +166,11 @@
           {
             "type": "function",
             "name": "callback",
-            "optional": true,
             "description": "Called when querying virtual keyboard configuration is complete.",
             "parameters": [
               {
-                "type": "object",
-                "name": "config",
-                "properties": {
-                  "layout": {
-                    "type": "string",
-                    "minLength": 1,
-                    "description": "Virtual keyboard layout string."
-                  },
-                  "hotrodmode": {
-                    "type": "boolean",
-                    "description": "Virtual keyboard is in hotrod mode."
-                  },
-                  "a11ymode": {
-                    "type": "boolean",
-                    "description": "True if accessibility virtual keyboard is enabled."
-                  },
-                  "features": {
-                    "type": "array",
-                    "items": { "type": "string" },
-                    "description": "List of experimental feature flags."
-                  }
-                }
+                "$ref": "KeyboardConfig",
+                "name": "config"
               }
             ]
           }
@@ -223,6 +226,18 @@
         "name": "onKeyboardClosed",
         "type": "function",
         "description": "Fired when the virtual keyboard window has been closed. For example, this can happen when turning off on-screen keyboard or exiting tablet mode."
+      },
+      {
+        "name": "onKeyboardConfigChanged",
+        "type": "function",
+        "description": "Fired when a configuration for virtual keyboard IME has changed, e.g. auto complete disabled.",
+        "parameters": [
+          {
+            "name": "config",
+            "description": "The virtual keyboard config",
+            "$ref": "KeyboardConfig"
+          }
+        ]
       }
     ]
   }
diff --git a/extensions/common/extension_api.cc b/extensions/common/extension_api.cc
index 8dbf447..28cbdea 100644
--- a/extensions/common/extension_api.cc
+++ b/extensions/common/extension_api.cc
@@ -234,15 +234,13 @@
 
   ExtensionsClient* client = ExtensionsClient::Get();
   DCHECK(client);
-  if (default_configuration_initialized_ &&
-      client->IsAPISchemaGenerated(api_name)) {
-    base::StringPiece schema = client->GetAPISchema(api_name);
-    CHECK(!schema.empty());
-    schema_strings_[api_name] = schema;
-    return schema;
-  }
+  if (!default_configuration_initialized_)
+    return base::StringPiece();
 
-  return base::StringPiece();
+  base::StringPiece schema = client->GetAPISchema(api_name);
+  if (!schema.empty())
+    schema_strings_[api_name] = schema;
+  return schema;
 }
 
 const base::DictionaryValue* ExtensionAPI::GetSchema(
diff --git a/extensions/common/features/simple_feature.cc b/extensions/common/features/simple_feature.cc
index e599dd9..bbb3a565 100644
--- a/extensions/common/features/simple_feature.cc
+++ b/extensions/common/features/simple_feature.cc
@@ -210,11 +210,7 @@
 }
 
 SimpleFeature::SimpleFeature()
-    : location_(UNSPECIFIED_LOCATION),
-      min_manifest_version_(0),
-      max_manifest_version_(0),
-      component_extensions_auto_granted_(true),
-      is_internal_(false) {}
+    : component_extensions_auto_granted_(true), is_internal_(false) {}
 
 SimpleFeature::~SimpleFeature() {}
 
@@ -317,15 +313,15 @@
           "'%s' is not allowed for specified platform.",
           name().c_str());
     case INVALID_MIN_MANIFEST_VERSION:
+      DCHECK(min_manifest_version_);
       return base::StringPrintf(
-          "'%s' requires manifest version of at least %d.",
-          name().c_str(),
-          min_manifest_version_);
+          "'%s' requires manifest version of at least %d.", name().c_str(),
+          *min_manifest_version_);
     case INVALID_MAX_MANIFEST_VERSION:
+      DCHECK(max_manifest_version_);
       return base::StringPrintf(
-          "'%s' requires manifest version of %d or lower.",
-          name().c_str(),
-          max_manifest_version_);
+          "'%s' requires manifest version of %d or lower.", name().c_str(),
+          *max_manifest_version_);
     case INVALID_SESSION_TYPE:
       return base::StringPrintf(
           "'%s' is only allowed to run in %s sessions, but this is %s session.",
@@ -344,9 +340,10 @@
           name().c_str(), GetDisplayName(channel).c_str(),
           GetDisplayName(GetCurrentChannel()).c_str());
     case MISSING_COMMAND_LINE_SWITCH:
+      DCHECK(command_line_switch_);
       return base::StringPrintf(
           "'%s' requires the '%s' command line switch to be enabled.",
-          name().c_str(), command_line_switch_.c_str());
+          name().c_str(), command_line_switch_->c_str());
   }
 
   NOTREACHED();
@@ -442,9 +439,8 @@
 
 bool SimpleFeature::MatchesManifestLocation(
     Manifest::Location manifest_location) const {
-  switch (location_) {
-    case SimpleFeature::UNSPECIFIED_LOCATION:
-      return true;
+  DCHECK(location_);
+  switch (*location_) {
     case SimpleFeature::COMPONENT_LOCATION:
       return manifest_location == Manifest::COMPONENT;
     case SimpleFeature::EXTERNAL_COMPONENT_LOCATION:
@@ -566,8 +562,8 @@
       return CreateAvailability(UNSUPPORTED_CHANNEL, *channel_);
   }
 
-  if (!command_line_switch_.empty() &&
-      !IsCommandLineSwitchEnabled(command_line, command_line_switch_)) {
+  if (command_line_switch_ &&
+      !IsCommandLineSwitchEnabled(command_line, *command_line_switch_)) {
     return CreateAvailability(MISSING_COMMAND_LINE_SWITCH);
   }
 
@@ -608,13 +604,13 @@
     return CreateAvailability(NOT_FOUND_IN_WHITELIST);
   }
 
-  if (!MatchesManifestLocation(location))
+  if (location_ && !MatchesManifestLocation(location))
     return CreateAvailability(INVALID_LOCATION);
 
-  if (min_manifest_version_ != 0 && manifest_version < min_manifest_version_)
+  if (min_manifest_version_ && manifest_version < *min_manifest_version_)
     return CreateAvailability(INVALID_MIN_MANIFEST_VERSION);
 
-  if (max_manifest_version_ != 0 && manifest_version > max_manifest_version_)
+  if (max_manifest_version_ && manifest_version > *max_manifest_version_)
     return CreateAvailability(INVALID_MAX_MANIFEST_VERSION);
 
   return CreateAvailability(IS_AVAILABLE);
diff --git a/extensions/common/features/simple_feature.h b/extensions/common/features/simple_feature.h
index b56a5fa..69a33122 100644
--- a/extensions/common/features/simple_feature.h
+++ b/extensions/common/features/simple_feature.h
@@ -87,7 +87,6 @@
   // supported in feature files. These should only be used in this class and in
   // generated files.
   enum Location {
-    UNSPECIFIED_LOCATION,
     COMPONENT_LOCATION,
     EXTERNAL_COMPONENT_LOCATION,
     POLICY_LOCATION,
@@ -99,9 +98,7 @@
   // directly in the header means that code that doesn't already have that exact
   // type ends up triggering many implicit conversions which are all inlined.
   void set_blacklist(std::initializer_list<const char* const> blacklist);
-  void set_channel(version_info::Channel channel) {
-    channel_.reset(new version_info::Channel(channel));
-  }
+  void set_channel(version_info::Channel channel) { channel_ = channel; }
   void set_command_line_switch(base::StringPiece command_line_switch);
   void set_component_extensions_auto_granted(bool granted) {
     component_extensions_auto_granted_ = granted;
@@ -136,12 +133,17 @@
   const std::vector<Platform>& platforms() const { return platforms_; }
   const std::vector<Context>& contexts() const { return contexts_; }
   const std::vector<std::string>& dependencies() const { return dependencies_; }
-  bool has_channel() const { return channel_.get() != nullptr; }
-  version_info::Channel channel() const { return *channel_; }
-  Location location() const { return location_; }
-  int min_manifest_version() const { return min_manifest_version_; }
-  int max_manifest_version() const { return max_manifest_version_; }
-  const std::string& command_line_switch() const {
+  const base::Optional<version_info::Channel> channel() const {
+    return channel_;
+  }
+  const base::Optional<Location> location() const { return location_; }
+  const base::Optional<int> min_manifest_version() const {
+    return min_manifest_version_;
+  }
+  const base::Optional<int> max_manifest_version() const {
+    return max_manifest_version_;
+  }
+  const base::Optional<std::string>& command_line_switch() const {
     return command_line_switch_;
   }
   bool component_extensions_auto_granted() const {
@@ -223,18 +225,20 @@
   std::vector<Context> contexts_;
   std::vector<Platform> platforms_;
   URLPatternSet matches_;
-  Location location_;
-  int min_manifest_version_;
-  int max_manifest_version_;
-  bool component_extensions_auto_granted_;
-  bool is_internal_;
-  std::string command_line_switch_;
-  std::unique_ptr<version_info::Channel> channel_;
+
+  base::Optional<Location> location_;
+  base::Optional<int> min_manifest_version_;
+  base::Optional<int> max_manifest_version_;
+  base::Optional<std::string> command_line_switch_;
+  base::Optional<version_info::Channel> channel_;
   // Whether to ignore channel-based restrictions (such as because the user has
   // enabled experimental extension APIs). Note: this is lazily calculated, and
   // then cached.
   mutable base::Optional<bool> ignore_channel_;
 
+  bool component_extensions_auto_granted_;
+  bool is_internal_;
+
   DISALLOW_COPY_AND_ASSIGN(SimpleFeature);
 };
 
diff --git a/extensions/common/features/simple_feature_unittest.cc b/extensions/common/features/simple_feature_unittest.cc
index 113233a..1508844 100644
--- a/extensions/common/features/simple_feature_unittest.cc
+++ b/extensions/common/features/simple_feature_unittest.cc
@@ -374,13 +374,18 @@
               availability.message());
   }
 
-  feature.set_contexts({Feature::BLESSED_EXTENSION_CONTEXT});
-  feature.set_location(SimpleFeature::COMPONENT_LOCATION);
-  EXPECT_EQ(Feature::INVALID_LOCATION, feature.IsAvailableToContext(
-      extension.get(), Feature::BLESSED_EXTENSION_CONTEXT,
-      Feature::CHROMEOS_PLATFORM).result());
-  feature.set_location(SimpleFeature::UNSPECIFIED_LOCATION);
+  {
+    SimpleFeature feature;
+    feature.set_location(SimpleFeature::COMPONENT_LOCATION);
+    EXPECT_EQ(Feature::INVALID_LOCATION,
+              feature
+                  .IsAvailableToContext(extension.get(),
+                                        Feature::BLESSED_EXTENSION_CONTEXT,
+                                        Feature::CHROMEOS_PLATFORM)
+                  .result());
+  }
 
+  feature.set_contexts({Feature::BLESSED_EXTENSION_CONTEXT});
   EXPECT_EQ(Feature::INVALID_PLATFORM, feature.IsAvailableToContext(
       extension.get(), Feature::BLESSED_EXTENSION_CONTEXT,
       Feature::UNSPECIFIED_PLATFORM).result());
@@ -540,8 +545,6 @@
                                   Manifest::COMPONENT));
   EXPECT_TRUE(
       LocationIsAvailable(SimpleFeature::POLICY_LOCATION, Manifest::COMPONENT));
-  EXPECT_TRUE(LocationIsAvailable(SimpleFeature::UNSPECIFIED_LOCATION,
-                                  Manifest::COMPONENT));
 
   // Only component extensions can access the "component" location.
   EXPECT_FALSE(LocationIsAvailable(SimpleFeature::COMPONENT_LOCATION,
diff --git a/extensions/renderer/BUILD.gn b/extensions/renderer/BUILD.gn
index 9067c0db..1893d021 100644
--- a/extensions/renderer/BUILD.gn
+++ b/extensions/renderer/BUILD.gn
@@ -150,6 +150,8 @@
     "native_extension_bindings_system.h",
     "native_handler.cc",
     "native_handler.h",
+    "native_renderer_messaging_service.cc",
+    "native_renderer_messaging_service.h",
     "object_backed_native_handler.cc",
     "object_backed_native_handler.h",
     "process_info_native_handler.cc",
@@ -365,6 +367,7 @@
     "mojo/keep_alive_client_unittest.cc",
     "native_extension_bindings_system_unittest.cc",
     "native_extension_bindings_system_unittest.h",
+    "native_renderer_messaging_service_unittest.cc",
     "safe_builtins_unittest.cc",
     "scoped_web_frame.cc",
     "scoped_web_frame.h",
diff --git a/extensions/renderer/bindings/api_event_handler.cc b/extensions/renderer/bindings/api_event_handler.cc
index 0679e994..ca6cf31 100644
--- a/extensions/renderer/bindings/api_event_handler.cc
+++ b/extensions/renderer/bindings/api_event_handler.cc
@@ -206,21 +206,11 @@
                                          v8::Local<v8::Context> context,
                                          const base::ListValue& args,
                                          const EventFilteringInfo* filter) {
-  APIEventPerContextData* data = GetContextData(context, false);
-  if (!data)
-    return;
-
-  auto emitter_iter = data->emitters.find(event_name);
-  if (emitter_iter == data->emitters.end())
-    return;
-
-  EventEmitter* emitter = nullptr;
-  gin::Converter<EventEmitter*>::FromV8(
-      context->GetIsolate(), emitter_iter->second.Get(context->GetIsolate()),
-      &emitter);
-  CHECK(emitter);
-
-  if (emitter->GetNumListeners() == 0u)
+  // Don't bother converting arguments if there are no listeners.
+  // NOTE(devlin): This causes a double data and EventEmitter lookup, since
+  // the v8 version below also checks for listeners. This should be very cheap,
+  // but if we were really worried we could refactor.
+  if (!HasListenerForEvent(event_name, context))
     return;
 
   // Note: since we only convert the arguments once, if a listener modifies an
@@ -229,20 +219,51 @@
   std::unique_ptr<content::V8ValueConverter> converter =
       content::V8ValueConverter::Create();
 
+  std::vector<v8::Local<v8::Value>> v8_args;
+  v8_args.reserve(args.GetSize());
+  for (const auto& arg : args)
+    v8_args.push_back(converter->ToV8Value(&arg, context));
+
+  FireEventInContext(event_name, context, &v8_args, filter);
+}
+
+void APIEventHandler::FireEventInContext(
+    const std::string& event_name,
+    v8::Local<v8::Context> context,
+    std::vector<v8::Local<v8::Value>>* arguments,
+    const EventFilteringInfo* filter) {
+  APIEventPerContextData* data = GetContextData(context, false);
+  if (!data)
+    return;
+
+  auto iter = data->emitters.find(event_name);
+  if (iter == data->emitters.end())
+    return;
+  EventEmitter* emitter = nullptr;
+  gin::Converter<EventEmitter*>::FromV8(
+      context->GetIsolate(), iter->second.Get(context->GetIsolate()), &emitter);
+  CHECK(emitter);
+
   auto massager_iter = data->massagers.find(event_name);
   if (massager_iter == data->massagers.end()) {
-    std::vector<v8::Local<v8::Value>> v8_args;
-    v8_args.reserve(args.GetSize());
-    for (const auto& arg : args)
-      v8_args.push_back(converter->ToV8Value(&arg, context));
-    emitter->Fire(context, &v8_args, filter);
+    emitter->Fire(context, arguments, filter);
   } else {
     v8::Isolate* isolate = context->GetIsolate();
     v8::HandleScope handle_scope(isolate);
     v8::Local<v8::Function> massager = massager_iter->second.Get(isolate);
-    v8::Local<v8::Value> v8_args = converter->ToV8Value(&args, context);
-    DCHECK(!v8_args.IsEmpty());
-    DCHECK(v8_args->IsArray());
+
+    v8::Local<v8::Array> args_array =
+        v8::Array::New(isolate, arguments->size());
+    {
+      // Massagers expect an array of v8 values. Since this is a newly-
+      // constructed array and we're assigning data properties, this shouldn't
+      // be able to fail or be visible by other script.
+      for (size_t i = 0; i < arguments->size(); ++i) {
+        v8::Maybe<bool> success = args_array->CreateDataProperty(
+            context, static_cast<uint32_t>(i), arguments->at(i));
+        CHECK(success.ToChecked());
+      }
+    }
 
     // Curry in the native dispatch function. Some argument massagers take
     // extra liberties and call this asynchronously, so we can't just have the
@@ -253,7 +274,7 @@
     v8::Local<v8::Function> dispatch_event = v8::Function::New(
         isolate, &DispatchEvent, gin::StringToSymbol(isolate, event_name));
 
-    v8::Local<v8::Value> massager_args[] = {v8_args, dispatch_event};
+    v8::Local<v8::Value> massager_args[] = {args_array, dispatch_event};
     call_js_.Run(massager, context, arraysize(massager_args), massager_args);
   }
 }
diff --git a/extensions/renderer/bindings/api_event_handler.h b/extensions/renderer/bindings/api_event_handler.h
index 2e48fe84..268614a9 100644
--- a/extensions/renderer/bindings/api_event_handler.h
+++ b/extensions/renderer/bindings/api_event_handler.h
@@ -75,6 +75,10 @@
                           v8::Local<v8::Context> context,
                           const base::ListValue& arguments,
                           const EventFilteringInfo* filter);
+  void FireEventInContext(const std::string& event_name,
+                          v8::Local<v8::Context> context,
+                          std::vector<v8::Local<v8::Value>>* arguments,
+                          const EventFilteringInfo* filter);
 
   // Registers a |function| to serve as an "argument massager" for the given
   // |event_name|, mutating the original arguments.
diff --git a/extensions/renderer/gin_port.cc b/extensions/renderer/gin_port.cc
index 2ee5183..97bf8f5 100644
--- a/extensions/renderer/gin_port.cc
+++ b/extensions/renderer/gin_port.cc
@@ -26,10 +26,12 @@
 }  // namespace
 
 GinPort::GinPort(const PortId& port_id,
+                 int routing_id,
                  const std::string& name,
                  APIEventHandler* event_handler,
                  Delegate* delegate)
     : port_id_(port_id),
+      routing_id_(routing_id),
       name_(name),
       event_handler_(event_handler),
       delegate_(delegate) {}
@@ -70,7 +72,7 @@
   DispatchEvent(context, &args, kOnMessageEvent);
 }
 
-void GinPort::Disconnect(v8::Local<v8::Context> context) {
+void GinPort::DispatchOnDisconnect(v8::Local<v8::Context> context) {
   DCHECK(!is_closed_);
 
   v8::Isolate* isolate = context->GetIsolate();
@@ -102,11 +104,14 @@
 
   v8::Local<v8::Context> context = arguments->GetHolderCreationContext();
   Invalidate(context);
+
+  delegate_->ClosePort(context, port_id_, routing_id_);
 }
 
 void GinPort::PostMessageHandler(gin::Arguments* arguments,
                                  v8::Local<v8::Value> v8_message) {
   v8::Isolate* isolate = arguments->isolate();
+  v8::Local<v8::Context> context = arguments->GetHolderCreationContext();
   if (is_closed_) {
     ThrowError(isolate, "Attempting to use a disconnected port object");
     return;
@@ -128,9 +133,7 @@
   v8::Local<v8::String> stringified;
   {
     v8::TryCatch try_catch(isolate);
-    success =
-        v8::JSON::Stringify(arguments->GetHolderCreationContext(), v8_message)
-            .ToLocal(&stringified);
+    success = v8::JSON::Stringify(context, v8_message).ToLocal(&stringified);
   }
 
   std::string message;
@@ -149,7 +152,7 @@
   }
 
   delegate_->PostMessageToPort(
-      port_id_,
+      context, port_id_, routing_id_,
       std::make_unique<Message>(
           message, blink::WebUserGestureIndicator::IsProcessingUserGesture()));
 }
@@ -228,7 +231,6 @@
                                         GetEvent(context, kOnMessageEvent));
   event_handler_->InvalidateCustomEvent(context,
                                         GetEvent(context, kOnDisconnectEvent));
-  delegate_->ClosePort(port_id_);
 }
 
 void GinPort::ThrowError(v8::Isolate* isolate, base::StringPiece error) {
diff --git a/extensions/renderer/gin_port.h b/extensions/renderer/gin_port.h
index 7c36a17e..e71720fb4 100644
--- a/extensions/renderer/gin_port.h
+++ b/extensions/renderer/gin_port.h
@@ -24,9 +24,8 @@
 // A gin::Wrappable implementation of runtime.Port exposed to extensions. This
 // provides a means for extensions to communicate with themselves and each
 // other. This message-passing usually involves IPCs to the browser; we delegate
-// out this responsibility. This class only handles the JS interface.
-// TODO(devlin): Expose this class through a native implementation for the
-// messaging custom bindings.
+// out this responsibility. This class only handles the JS interface (both calls
+// from JS and forward events to JS).
 class GinPort final : public gin::Wrappable<GinPort> {
  public:
   class Delegate {
@@ -34,14 +33,19 @@
     virtual ~Delegate() {}
 
     // Posts a message to the port.
-    virtual void PostMessageToPort(const PortId& port_id,
+    virtual void PostMessageToPort(v8::Local<v8::Context> context,
+                                   const PortId& port_id,
+                                   int routing_id,
                                    std::unique_ptr<Message> message) = 0;
 
     // Closes the port.
-    virtual void ClosePort(const PortId& port_id) = 0;
+    virtual void ClosePort(v8::Local<v8::Context> context,
+                           const PortId& port_id,
+                           int routing_id) = 0;
   };
 
   GinPort(const PortId& port_id,
+          int routing_id,
           const std::string& name,
           APIEventHandler* event_handler,
           Delegate* delegate);
@@ -59,12 +63,15 @@
 
   // Dispatches an event to any listeners of the onDisconnect event and closes
   // the port.
-  void Disconnect(v8::Local<v8::Context> context);
+  void DispatchOnDisconnect(v8::Local<v8::Context> context);
 
   // Sets the |sender| property on the port.
   void SetSender(v8::Local<v8::Context> context, v8::Local<v8::Value> sender);
 
   bool is_closed() const { return is_closed_; }
+  const PortId& port_id() const { return port_id_; }
+  int routing_id() const { return routing_id_; }
+  const std::string& name() const { return name_; }
 
  private:
   // Handlers for the gin::Wrappable.
@@ -105,6 +112,10 @@
   // The associated port id.
   PortId port_id_;
 
+  // The routing id associated with the port's context's render frame.
+  // TODO(devlin/lazyboy): This won't work with service workers.
+  int routing_id_;
+
   // The port's name.
   std::string name_;
 
diff --git a/extensions/renderer/gin_port_unittest.cc b/extensions/renderer/gin_port_unittest.cc
index 61322ec..3a69356 100644
--- a/extensions/renderer/gin_port_unittest.cc
+++ b/extensions/renderer/gin_port_unittest.cc
@@ -21,6 +21,9 @@
 
 namespace {
 
+const int kDefaultRoutingId = 42;
+const char kDefaultPortName[] = "port name";
+
 void DoNothingOnEventListenersChanged(const std::string& event_name,
                                       binding::EventListenersChanged change,
                                       const base::DictionaryValue* value,
@@ -33,12 +36,17 @@
   TestPortDelegate() {}
   ~TestPortDelegate() override {}
 
-  void PostMessageToPort(const PortId& port_id,
+  void PostMessageToPort(v8::Local<v8::Context> context,
+                         const PortId& port_id,
+                         int routing_id,
                          std::unique_ptr<Message> message) override {
     last_port_id_ = port_id;
     last_message_ = std::move(message);
   }
-  MOCK_METHOD1(ClosePort, void(const PortId&));
+  MOCK_METHOD3(ClosePort,
+               void(v8::Local<v8::Context> context,
+                    const PortId&,
+                    int routing_id));
 
   void ResetLastMessage() {
     last_port_id_.reset();
@@ -66,7 +74,7 @@
         base::Bind(&RunFunctionOnGlobalAndIgnoreResult),
         base::Bind(&RunFunctionOnGlobalAndReturnHandle),
         base::Bind(&DoNothingOnEventListenersChanged), nullptr);
-    delegate_ = std::make_unique<TestPortDelegate>();
+    delegate_ = std::make_unique<testing::StrictMock<TestPortDelegate>>();
   }
 
   void TearDown() override {
@@ -78,12 +86,19 @@
     event_handler_->InvalidateContext(context);
   }
 
+  gin::Handle<GinPort> CreatePort(const PortId& port_id,
+                                  const char* name = kDefaultPortName) {
+    return gin::CreateHandle(isolate(),
+                             new GinPort(port_id, kDefaultRoutingId, name,
+                                         event_handler(), delegate()));
+  }
+
   APIEventHandler* event_handler() { return event_handler_.get(); }
   TestPortDelegate* delegate() { return delegate_.get(); }
 
  private:
   std::unique_ptr<APIEventHandler> event_handler_;
-  std::unique_ptr<TestPortDelegate> delegate_;
+  std::unique_ptr<testing::StrictMock<TestPortDelegate>> delegate_;
 
   DISALLOW_COPY_AND_ASSIGN(GinPortTest);
 };
@@ -96,9 +111,7 @@
   v8::Local<v8::Context> context = MainContext();
 
   PortId port_id(base::UnguessableToken::Create(), 0, true);
-  std::string name = "port name";
-  gin::Handle<GinPort> port = gin::CreateHandle(
-      isolate(), new GinPort(port_id, name, event_handler(), delegate()));
+  gin::Handle<GinPort> port = CreatePort(port_id);
 
   v8::Local<v8::Object> port_obj = port.ToV8().As<v8::Object>();
 
@@ -112,9 +125,7 @@
   v8::Local<v8::Context> context = MainContext();
 
   PortId port_id(base::UnguessableToken::Create(), 0, true);
-  std::string name = "port name";
-  gin::Handle<GinPort> port = gin::CreateHandle(
-      isolate(), new GinPort(port_id, name, event_handler(), delegate()));
+  gin::Handle<GinPort> port = CreatePort(port_id);
 
   v8::Local<v8::Object> port_obj = port.ToV8().As<v8::Object>();
 
@@ -148,9 +159,7 @@
   v8::Local<v8::Context> context = MainContext();
 
   PortId port_id(base::UnguessableToken::Create(), 0, true);
-  std::string name = "port name";
-  gin::Handle<GinPort> port = gin::CreateHandle(
-      isolate(), new GinPort(port_id, name, event_handler(), delegate()));
+  gin::Handle<GinPort> port = CreatePort(port_id);
 
   v8::Local<v8::Object> port_obj = port.ToV8().As<v8::Object>();
 
@@ -232,9 +241,7 @@
 
   {
     // Disconnect the port and send a message. Should fail.
-    EXPECT_CALL(*delegate(), ClosePort(port_id)).Times(1);
-    port->Disconnect(context);
-    ::testing::Mock::VerifyAndClearExpectations(delegate());
+    port->DispatchOnDisconnect(context);
     EXPECT_TRUE(port->is_closed());
     const char kFunction[] =
         "(function(port) { port.postMessage({data: [42]}); })";
@@ -257,9 +264,7 @@
   v8::Local<v8::Context> context = MainContext();
 
   PortId port_id(base::UnguessableToken::Create(), 0, true);
-  std::string name = "port name";
-  gin::Handle<GinPort> port = gin::CreateHandle(
-      isolate(), new GinPort(port_id, name, event_handler(), delegate()));
+  gin::Handle<GinPort> port = CreatePort(port_id);
 
   v8::Local<v8::Object> port_obj = port.ToV8().As<v8::Object>();
 
@@ -275,9 +280,7 @@
   v8::Local<v8::Value> args[] = {port_obj};
   RunFunctionOnGlobal(test_function, context, arraysize(args), args);
 
-  EXPECT_CALL(*delegate(), ClosePort(port_id)).Times(1);
-  port->Disconnect(context);
-  ::testing::Mock::VerifyAndClearExpectations(delegate());
+  port->DispatchOnDisconnect(context);
   EXPECT_EQ("true", GetStringPropertyFromObject(context->Global(), context,
                                                 "onDisconnectPortValid"));
   EXPECT_TRUE(port->is_closed());
@@ -289,13 +292,12 @@
   v8::Local<v8::Context> context = MainContext();
 
   PortId port_id(base::UnguessableToken::Create(), 0, true);
-  std::string name = "port name";
-  gin::Handle<GinPort> port = gin::CreateHandle(
-      isolate(), new GinPort(port_id, name, event_handler(), delegate()));
+  gin::Handle<GinPort> port = CreatePort(port_id);
 
   v8::Local<v8::Object> port_obj = port.ToV8().As<v8::Object>();
 
-  EXPECT_CALL(*delegate(), ClosePort(port_id)).Times(1);
+  EXPECT_CALL(*delegate(), ClosePort(context, port_id, kDefaultRoutingId))
+      .Times(1);
   const char kFunction[] = "(function(port) { port.disconnect(); })";
   v8::Local<v8::Function> function = FunctionFromString(context, kFunction);
   v8::Local<v8::Value> args[] = {port_obj};
@@ -310,9 +312,7 @@
   v8::Local<v8::Context> context = MainContext();
 
   PortId port_id(base::UnguessableToken::Create(), 0, true);
-  std::string name = "port name";
-  gin::Handle<GinPort> port = gin::CreateHandle(
-      isolate(), new GinPort(port_id, name, event_handler(), delegate()));
+  gin::Handle<GinPort> port = CreatePort(port_id);
 
   v8::Local<v8::Object> port_obj = port.ToV8().As<v8::Object>();
 
diff --git a/extensions/renderer/ipc_message_sender.cc b/extensions/renderer/ipc_message_sender.cc
index c56539d..aeaa12bb 100644
--- a/extensions/renderer/ipc_message_sender.cc
+++ b/extensions/renderer/ipc_message_sender.cc
@@ -109,6 +109,45 @@
         remove_lazy_listener));
   }
 
+  void SendOpenChannelToExtension(ScriptContext* script_context,
+                                  const PortId& port_id,
+                                  const std::string& target_id,
+                                  const std::string& channel_name,
+                                  bool include_tls_channel_id) override {
+    content::RenderFrame* render_frame = script_context->GetRenderFrame();
+    DCHECK(render_frame);
+
+    ExtensionMsg_ExternalConnectionInfo info;
+    const Extension* extension = script_context->extension();
+    if (extension && !extension->is_hosted_app())
+      info.source_id = extension->id();
+    info.target_id = target_id;
+    info.source_url = script_context->url();
+
+    render_thread_->Send(new ExtensionHostMsg_OpenChannelToExtension(
+        render_frame->GetRoutingID(), info, channel_name,
+        include_tls_channel_id, port_id));
+  }
+
+  void SendOpenMessagePort(int routing_id, const PortId& port_id) override {
+    render_thread_->Send(
+        new ExtensionHostMsg_OpenMessagePort(routing_id, port_id));
+  }
+
+  void SendCloseMessagePort(int routing_id,
+                            const PortId& port_id,
+                            bool close_channel) override {
+    render_thread_->Send(new ExtensionHostMsg_CloseMessagePort(
+        routing_id, port_id, close_channel));
+  }
+
+  void SendPostMessageToPort(int routing_id,
+                             const PortId& port_id,
+                             const Message& message) override {
+    render_thread_->Send(
+        new ExtensionHostMsg_PostMessage(routing_id, port_id, message));
+  }
+
  private:
   content::RenderThread* const render_thread_;
 
@@ -226,6 +265,30 @@
         remove_lazy_listener));
   }
 
+  void SendOpenChannelToExtension(ScriptContext* script_context,
+                                  const PortId& port_id,
+                                  const std::string& target_id,
+                                  const std::string& channel_name,
+                                  bool include_tls_channel_id) override {
+    NOTIMPLEMENTED();
+  }
+
+  void SendOpenMessagePort(int routing_id, const PortId& port_id) override {
+    NOTIMPLEMENTED();
+  }
+
+  void SendCloseMessagePort(int routing_id,
+                            const PortId& port_id,
+                            bool close_channel) override {
+    NOTIMPLEMENTED();
+  }
+
+  void SendPostMessageToPort(int routing_id,
+                             const PortId& port_id,
+                             const Message& message) override {
+    NOTIMPLEMENTED();
+  }
+
  private:
   WorkerThreadDispatcher* const dispatcher_;
   const int64_t service_worker_version_id_;
diff --git a/extensions/renderer/ipc_message_sender.h b/extensions/renderer/ipc_message_sender.h
index 0ac8b0c..6dc2311 100644
--- a/extensions/renderer/ipc_message_sender.h
+++ b/extensions/renderer/ipc_message_sender.h
@@ -21,6 +21,8 @@
 namespace extensions {
 class ScriptContext;
 class WorkerThreadDispatcher;
+struct Message;
+struct PortId;
 
 // A class to handle sending bindings-related messages to the browser. Different
 // versions handle main thread vs. service worker threads.
@@ -38,7 +40,7 @@
   // to a request.
   virtual void SendOnRequestResponseReceivedIPC(int request_id) = 0;
 
-  // Send a message to add/remove an unfiltered listener.
+  // Sends a message to add/remove an unfiltered listener.
   virtual void SendAddUnfilteredEventListenerIPC(
       ScriptContext* context,
       const std::string& event_name) = 0;
@@ -46,7 +48,7 @@
       ScriptContext* context,
       const std::string& event_name) = 0;
 
-  // Send a message to add/remove a lazy unfiltered listener.
+  // Sends a message to add/remove a lazy unfiltered listener.
   virtual void SendAddUnfilteredLazyEventListenerIPC(
       ScriptContext* context,
       const std::string& event_name) = 0;
@@ -54,7 +56,7 @@
       ScriptContext* context,
       const std::string& event_name) = 0;
 
-  // Send a message to add/remove a filtered listener.
+  // Sends a message to add/remove a filtered listener.
   virtual void SendAddFilteredEventListenerIPC(
       ScriptContext* context,
       const std::string& event_name,
@@ -66,6 +68,23 @@
       const base::DictionaryValue& filter,
       bool remove_lazy_listener) = 0;
 
+  // Opens a channel to the specified extension.
+  virtual void SendOpenChannelToExtension(ScriptContext* script_context,
+                                          const PortId& port_id,
+                                          const std::string& target_id,
+                                          const std::string& channel_name,
+                                          bool include_tls_channel_id) = 0;
+
+  // Sends a message to open/close a mesage port or send a message to an
+  // existing port.
+  virtual void SendOpenMessagePort(int routing_id, const PortId& port_id) = 0;
+  virtual void SendCloseMessagePort(int routing_id,
+                                    const PortId& port_id,
+                                    bool close_channel) = 0;
+  virtual void SendPostMessageToPort(int routing_id,
+                                     const PortId& port_id,
+                                     const Message& message) = 0;
+
   // Creates an IPCMessageSender for use on the main thread.
   static std::unique_ptr<IPCMessageSender> CreateMainThreadIPCMessageSender();
 
diff --git a/extensions/renderer/messaging_bindings.cc b/extensions/renderer/messaging_bindings.cc
index 74f2bdd..0bb29261 100644
--- a/extensions/renderer/messaging_bindings.cc
+++ b/extensions/renderer/messaging_bindings.cc
@@ -27,6 +27,7 @@
 #include "extensions/renderer/script_context.h"
 #include "extensions/renderer/script_context_set.h"
 #include "extensions/renderer/v8_helpers.h"
+#include "gin/converter.h"
 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
 #include "v8/include/v8.h"
 
@@ -109,11 +110,36 @@
 
   int js_port_id = args[0].As<v8::Int32>()->Value();
   auto iter = ports_.find(js_port_id);
-  if (iter != ports_.end()) {
-    iter->second->PostExtensionMessage(std::make_unique<Message>(
-        *v8::String::Utf8Value(args[1]),
-        blink::WebUserGestureIndicator::IsProcessingUserGesture()));
+
+  if (iter == ports_.end())
+    return;
+
+  ExtensionPort& port = *iter->second;
+
+  auto message = std::make_unique<Message>(
+      *v8::String::Utf8Value(args[1]),
+      blink::WebUserGestureIndicator::IsProcessingUserGesture());
+
+  size_t message_length = message->data.length();
+
+  // Max bucket at 512 MB - anything over that, and we don't care.
+  static constexpr int kMaxUmaLength = 1024 * 1024 * 512;
+  static constexpr int kMinUmaLength = 1;
+  static constexpr int kBucketCount = 50;
+  UMA_HISTOGRAM_CUSTOM_COUNTS("Extensions.Messaging.MessageSize",
+                              message_length, kMinUmaLength, kMaxUmaLength,
+                              kBucketCount);
+
+  // IPC messages will fail at > 128 MB. Restrict extension messages to 64 MB.
+  // A 64 MB JSON-ifiable object is scary enough as is.
+  static constexpr size_t kMaxMessageLength = 1024 * 1024 * 64;
+  if (message_length > kMaxMessageLength) {
+    args.GetReturnValue().Set(gin::StringToV8(
+        args.GetIsolate(), "Message length exceeded maximum allowed length."));
+    return;
   }
+
+  port.PostExtensionMessage(std::move(message));
 }
 
 void MessagingBindings::CloseChannel(
diff --git a/extensions/renderer/messaging_bindings.h b/extensions/renderer/messaging_bindings.h
index f566103..11b87128 100644
--- a/extensions/renderer/messaging_bindings.h
+++ b/extensions/renderer/messaging_bindings.h
@@ -35,7 +35,8 @@
  private:
   using PortMap = std::map<int, std::unique_ptr<ExtensionPort>>;
 
-  // JS Exposed Function: Sends a message along the given channel.
+  // JS Exposed Function: Sends a message along the given channel. If an error
+  // occurs, returns the error, else returns nothing.
   void PostMessage(const v8::FunctionCallbackInfo<v8::Value>& args);
 
   // JS Exposed Function: Close a port, optionally forcefully (i.e. close the
diff --git a/extensions/renderer/native_extension_bindings_system_unittest.cc b/extensions/renderer/native_extension_bindings_system_unittest.cc
index ac46979..46544b7b 100644
--- a/extensions/renderer/native_extension_bindings_system_unittest.cc
+++ b/extensions/renderer/native_extension_bindings_system_unittest.cc
@@ -115,6 +115,10 @@
   RendererExtensionRegistry::Get()->Insert(extension);
 }
 
+bool NativeExtensionBindingsSystemUnittest::UseStrictIPCMessageSender() {
+  return false;
+}
+
 TEST_F(NativeExtensionBindingsSystemUnittest, Basic) {
   scoped_refptr<Extension> extension =
       ExtensionBuilder("foo")
diff --git a/extensions/renderer/native_extension_bindings_system_unittest.h b/extensions/renderer/native_extension_bindings_system_unittest.h
index 7280266..4d5a39c 100644
--- a/extensions/renderer/native_extension_bindings_system_unittest.h
+++ b/extensions/renderer/native_extension_bindings_system_unittest.h
@@ -75,6 +75,13 @@
                     const std::string& event_name,
                     const base::DictionaryValue& filter,
                     bool remove_lazy_listener));
+
+  MOCK_METHOD5(SendOpenChannelToExtension,
+               void(ScriptContext* script_context,
+                    const PortId& port_id,
+                    const std::string& target_id,
+                    const std::string& channel_name,
+                    bool include_tls_channel_id));
   MOCK_METHOD2(SendOpenMessagePort,
                void(int routing_id, const PortId& port_id));
   MOCK_METHOD3(SendCloseMessagePort,
@@ -115,6 +122,10 @@
 
   void RegisterExtension(scoped_refptr<const Extension> extension);
 
+  // Returns whether or not a StrictMock should be used for the
+  // IPCMessageSender. The default is to return false.
+  virtual bool UseStrictIPCMessageSender();
+
   NativeExtensionBindingsSystem* bindings_system() {
     return bindings_system_.get();
   }
diff --git a/extensions/renderer/native_renderer_messaging_service.cc b/extensions/renderer/native_renderer_messaging_service.cc
new file mode 100644
index 0000000..b890ae5
--- /dev/null
+++ b/extensions/renderer/native_renderer_messaging_service.cc
@@ -0,0 +1,323 @@
+// 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 "extensions/renderer/native_renderer_messaging_service.h"
+
+#include <map>
+#include <string>
+
+#include "base/supports_user_data.h"
+#include "content/public/child/v8_value_converter.h"
+#include "content/public/common/child_process_host.h"
+#include "content/public/renderer/render_frame.h"
+#include "extensions/common/api/messaging/message.h"
+#include "extensions/common/api/messaging/port_id.h"
+#include "extensions/common/extension_messages.h"
+#include "extensions/common/manifest_handlers/externally_connectable.h"
+#include "extensions/renderer/ipc_message_sender.h"
+#include "extensions/renderer/native_extension_bindings_system.h"
+#include "extensions/renderer/script_context.h"
+#include "extensions/renderer/script_context_set.h"
+#include "gin/data_object_builder.h"
+#include "gin/handle.h"
+#include "gin/per_context_data.h"
+#include "v8/include/v8.h"
+
+namespace extensions {
+
+namespace {
+
+struct MessagingPerContextData : public base::SupportsUserData::Data {
+  // All the port objects that exist in this context.
+  std::map<PortId, v8::Global<v8::Object>> ports;
+
+  // The next available context-specific port id.
+  int next_port_id = 0;
+};
+
+constexpr char kExtensionMessagingPerContextData[] =
+    "extension_messaging_per_context_data";
+
+MessagingPerContextData* GetPerContextData(v8::Local<v8::Context> context,
+                                           bool should_create) {
+  gin::PerContextData* per_context_data = gin::PerContextData::From(context);
+  if (!per_context_data)
+    return nullptr;
+  auto* data = static_cast<MessagingPerContextData*>(
+      per_context_data->GetUserData(kExtensionMessagingPerContextData));
+
+  if (!data && should_create) {
+    auto messaging_data = std::make_unique<MessagingPerContextData>();
+    data = messaging_data.get();
+    per_context_data->SetUserData(kExtensionMessagingPerContextData,
+                                  std::move(messaging_data));
+  }
+
+  return data;
+}
+
+bool ScriptContextIsValid(ScriptContext* script_context) {
+  // TODO(devlin): This is in lieu of a similar check in the JS bindings that
+  // null-checks ScriptContext::GetRenderFrame(). This is good because it
+  // removes the reliance on RenderFrames (which make testing very difficult),
+  // but is it fully analogous? It should be close enough, since the browser
+  // has to deal with frames potentially disappearing before the IPC arrives
+  // anyway.
+  return script_context->is_valid();
+}
+
+}  // namespace
+
+NativeRendererMessagingService::NativeRendererMessagingService(
+    NativeExtensionBindingsSystem* bindings_system)
+    : RendererMessagingService(bindings_system),
+      bindings_system_(bindings_system) {}
+NativeRendererMessagingService::~NativeRendererMessagingService() {}
+
+gin::Handle<GinPort> NativeRendererMessagingService::Connect(
+    ScriptContext* script_context,
+    const std::string& target_id,
+    const std::string& channel_name,
+    bool include_tls_channel_id) {
+  if (!ScriptContextIsValid(script_context))
+    return gin::Handle<GinPort>();
+
+  MessagingPerContextData* data =
+      GetPerContextData(script_context->v8_context(), true);
+  if (!data)
+    return gin::Handle<GinPort>();
+
+  bool is_opener = true;
+  gin::Handle<GinPort> port = CreatePort(
+      script_context, channel_name,
+      PortId(script_context->context_id(), data->next_port_id++, is_opener));
+
+  bindings_system_->GetIPCMessageSender()->SendOpenChannelToExtension(
+      script_context, port->port_id(), target_id, channel_name,
+      include_tls_channel_id);
+  return port;
+}
+
+void NativeRendererMessagingService::PostMessageToPort(
+    v8::Local<v8::Context> context,
+    const PortId& port_id,
+    int routing_id,
+    std::unique_ptr<Message> message) {
+  ScriptContext* script_context =
+      ScriptContextSet::GetContextByV8Context(context);
+  CHECK(script_context);
+  if (!ScriptContextIsValid(script_context))
+    return;
+
+  bindings_system_->GetIPCMessageSender()->SendPostMessageToPort(
+      routing_id, port_id, *message);
+}
+
+void NativeRendererMessagingService::ClosePort(v8::Local<v8::Context> context,
+                                               const PortId& port_id,
+                                               int routing_id) {
+  ScriptContext* script_context =
+      ScriptContextSet::GetContextByV8Context(context);
+  CHECK(script_context);
+
+  MessagingPerContextData* data =
+      GetPerContextData(script_context->v8_context(), false);
+  if (!data)
+    return;
+
+  size_t erased = data->ports.erase(port_id);
+  DCHECK_GT(erased, 0u);
+
+  if (!ScriptContextIsValid(script_context))
+    return;
+
+  bool close_channel = true;
+  bindings_system_->GetIPCMessageSender()->SendCloseMessagePort(
+      routing_id, port_id, close_channel);
+}
+
+gin::Handle<GinPort> NativeRendererMessagingService::CreatePortForTesting(
+    ScriptContext* script_context,
+    const std::string& channel_name,
+    const PortId& port_id) {
+  return CreatePort(script_context, channel_name, port_id);
+}
+
+gin::Handle<GinPort> NativeRendererMessagingService::GetPortForTesting(
+    ScriptContext* script_context,
+    const PortId& port_id) {
+  return GetPort(script_context, port_id);
+}
+
+bool NativeRendererMessagingService::HasPortForTesting(
+    ScriptContext* script_context,
+    const PortId& port_id) {
+  return ContextHasMessagePort(script_context, port_id);
+}
+
+bool NativeRendererMessagingService::ContextHasMessagePort(
+    ScriptContext* script_context,
+    const PortId& port_id) {
+  MessagingPerContextData* data =
+      GetPerContextData(script_context->v8_context(), false);
+  return data && base::ContainsKey(data->ports, port_id);
+}
+
+void NativeRendererMessagingService::DispatchOnConnectToListeners(
+    ScriptContext* script_context,
+    const PortId& target_port_id,
+    const std::string& target_extension_id,
+    const std::string& channel_name,
+    const ExtensionMsg_TabConnectionInfo* source,
+    const ExtensionMsg_ExternalConnectionInfo& info,
+    const std::string& tls_channel_id,
+    const std::string& event_name) {
+  v8::Isolate* isolate = script_context->isolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Local<v8::Context> v8_context = script_context->v8_context();
+
+  if (channel_name == "chrome.extension.sendRequest" ||
+      channel_name == "chrome.runtime.sendMessage") {
+    // TODO(devlin): Handle sendMessage/sendRequest.
+    return;
+  }
+
+  gin::DataObjectBuilder sender_builder(isolate);
+  if (!info.source_id.empty())
+    sender_builder.Set("id", info.source_id);
+  if (!info.source_url.is_empty())
+    sender_builder.Set("url", info.source_url.spec());
+  sender_builder.Set("frameId", source->frame_id);
+
+  const Extension* extension = script_context->extension();
+  if (extension) {
+    if (!source->tab.empty() && !extension->is_platform_app()) {
+      sender_builder.Set("tab", content::V8ValueConverter::Create()->ToV8Value(
+                                    &source->tab, v8_context));
+    }
+
+    ExternallyConnectableInfo* externally_connectable =
+        ExternallyConnectableInfo::Get(extension);
+    if (externally_connectable &&
+        externally_connectable->accepts_tls_channel_id) {
+      sender_builder.Set("tlsChannelId", tls_channel_id);
+    }
+
+    if (info.guest_process_id != content::ChildProcessHost::kInvalidUniqueID) {
+      CHECK(Manifest::IsComponentLocation(extension->location()))
+          << "GuestProcessId can only be exposed to component extensions.";
+      sender_builder.Set("guestProcessId", info.guest_process_id)
+          .Set("guestRenderFrameRoutingId", info.guest_render_frame_routing_id);
+    }
+  }
+
+  v8::Local<v8::Value> sender = sender_builder.Build();
+  gin::Handle<GinPort> port =
+      CreatePort(script_context, channel_name, target_port_id);
+  port->SetSender(v8_context, sender);
+  std::vector<v8::Local<v8::Value>> args = {port.ToV8()};
+  bindings_system_->api_system()->event_handler()->FireEventInContext(
+      event_name, v8_context, &args, nullptr);
+}
+
+void NativeRendererMessagingService::DispatchOnMessageToListeners(
+    ScriptContext* script_context,
+    const Message& message,
+    const PortId& target_port_id) {
+  v8::Isolate* isolate = script_context->isolate();
+  v8::HandleScope handle_scope(isolate);
+
+  // TODO(devlin): Handle special casing for the sendMessage/sendRequest
+  // versions.
+  gin::Handle<GinPort> port = GetPort(script_context, target_port_id);
+  DCHECK(!port.IsEmpty());
+
+  port->DispatchOnMessage(script_context->v8_context(), message);
+}
+
+void NativeRendererMessagingService::DispatchOnDisconnectToListeners(
+    ScriptContext* script_context,
+    const PortId& port_id,
+    const std::string& error_message) {
+  v8::Isolate* isolate = script_context->isolate();
+  v8::HandleScope handle_scope(isolate);
+
+  // TODO(devlin): Handle special casing for the sendMessage/sendRequest
+  // versions.
+  v8::Local<v8::Context> context = script_context->v8_context();
+  gin::Handle<GinPort> port = GetPort(script_context, port_id);
+  DCHECK(!port.IsEmpty());
+  if (!error_message.empty()) {
+    bindings_system_->api_system()->request_handler()->last_error()->SetError(
+        context, error_message);
+  }
+  port->DispatchOnDisconnect(context);
+  if (!error_message.empty()) {
+    bindings_system_->api_system()->request_handler()->last_error()->ClearError(
+        context, true);
+  }
+
+  MessagingPerContextData* data = GetPerContextData(context, false);
+  data->ports.erase(port_id);
+}
+
+gin::Handle<GinPort> NativeRendererMessagingService::CreatePort(
+    ScriptContext* script_context,
+    const std::string& channel_name,
+    const PortId& port_id) {
+  // Note: no HandleScope because it would invalidate the gin::Handle::wrapper_.
+  v8::Isolate* isolate = script_context->isolate();
+  v8::Local<v8::Context> context = script_context->v8_context();
+  // Note: needed because gin::CreateHandle infers the context from the active
+  // context on the isolate.
+  v8::Context::Scope context_scope(context);
+
+  // If this port is an opener, then it should have been created in this
+  // context. Otherwise, it should have been created in another context, because
+  // we don't support intra-context message passing.
+  if (port_id.is_opener)
+    DCHECK_EQ(port_id.context_id, script_context->context_id());
+  else
+    DCHECK_NE(port_id.context_id, script_context->context_id());
+
+  content::RenderFrame* render_frame = script_context->GetRenderFrame();
+  int routing_id =
+      render_frame ? render_frame->GetRoutingID() : MSG_ROUTING_NONE;
+
+  MessagingPerContextData* data = GetPerContextData(context, true);
+  DCHECK(data);
+  DCHECK(!base::ContainsKey(data->ports, port_id));
+
+  gin::Handle<GinPort> port_handle = gin::CreateHandle(
+      isolate,
+      new GinPort(port_id, routing_id, channel_name,
+                  bindings_system_->api_system()->event_handler(), this));
+
+  v8::Local<v8::Object> port_object = port_handle.ToV8().As<v8::Object>();
+  data->ports[port_id].Reset(isolate, port_object);
+
+  return port_handle;
+}
+
+gin::Handle<GinPort> NativeRendererMessagingService::GetPort(
+    ScriptContext* script_context,
+    const PortId& port_id) {
+  // Note: no HandleScope because it would invalidate the gin::Handle::wrapper_.
+  v8::Isolate* isolate = script_context->isolate();
+  v8::Local<v8::Context> context = script_context->v8_context();
+
+  MessagingPerContextData* data =
+      GetPerContextData(script_context->v8_context(), false);
+  DCHECK(data);
+  DCHECK(base::ContainsKey(data->ports, port_id));
+
+  GinPort* port = nullptr;
+  gin::Converter<GinPort*>::FromV8(context->GetIsolate(),
+                                   data->ports[port_id].Get(isolate), &port);
+  CHECK(port);
+
+  return gin::CreateHandle(isolate, port);
+}
+
+}  // namespace extensions
diff --git a/extensions/renderer/native_renderer_messaging_service.h b/extensions/renderer/native_renderer_messaging_service.h
new file mode 100644
index 0000000..d23affd1
--- /dev/null
+++ b/extensions/renderer/native_renderer_messaging_service.h
@@ -0,0 +1,127 @@
+// 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 EXTENSIONS_RENDERER_NATIVE_RENDERER_MESSAGING_SERVICE_H_
+#define EXTENSIONS_RENDERER_NATIVE_RENDERER_MESSAGING_SERVICE_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "extensions/renderer/gin_port.h"
+#include "extensions/renderer/renderer_messaging_service.h"
+#include "gin/handle.h"
+
+struct ExtensionMsg_ExternalConnectionInfo;
+struct ExtensionMsg_TabConnectionInfo;
+
+namespace extensions {
+class NativeExtensionBindingsSystem;
+struct Message;
+struct PortId;
+
+// The messaging service to handle dispatching extension messages and connection
+// events to different contexts.
+// This primarily handles long-lived port-based communications (like
+// runtime.connect). A basic flow will create an "opener" port and one ore more
+// "receiver" ports in different contexts (and possibly processes). This class
+// manages the communication with the browser to forward these messages along.
+// From JavaScript, a basic flow would be:
+// // page1.js
+// var port = chrome.runtime.connect();
+// port.onMessage.addListener(function() { <handle message> });
+// port.postMessage('hi!');
+// <eventually> port.disconnect();
+// // page2.js
+// chrome.runtime.onConnect.addListener(function(port) {
+//   port.onMessage.addListener(function() { <handle message> });
+//   port.postMessage('hey!');
+// });
+// This causes the following steps in the messaging service:
+// Connection:
+// * connect() triggers OpenChannelToExtension, which notifies the browser of
+//   a new connection.
+// * The browser dispatches OnConnect messages to different renderers. If a
+//   renderer has a listener, it will respond with an OpenMessagePort message.
+//   If no renderer has a listener, the browser will close the port.
+// Message Posting
+// * Calls to postMessage() trigger a PostMessageToPort messge to the browser.
+// * The browser sends a DeliverMessage message to listening renderers. These
+//   then dispatch the onMessage event to listeners.
+// Disconnecting
+// * disconnect() calls result in sending a CloseMessagePort message to the
+//   browser.
+// * The browser then sends a DispatchOnDisconnect message to other renderers,
+//   which triggers the onDisconnect() event.
+// TODO(devlin): This is a pretty large comment for a class, and it documents
+// browser/renderer interaction. I wonder if this would be better in a
+// messaging.md document?
+class NativeRendererMessagingService : public RendererMessagingService,
+                                       public GinPort::Delegate {
+ public:
+  explicit NativeRendererMessagingService(
+      NativeExtensionBindingsSystem* bindings_system);
+  ~NativeRendererMessagingService() override;
+
+  // Creates and opens a new message port in the specified context.
+  gin::Handle<GinPort> Connect(ScriptContext* script_context,
+                               const std::string& target_id,
+                               const std::string& name,
+                               bool include_tls_channel_id);
+
+  // GinPort::Delegate:
+  void PostMessageToPort(v8::Local<v8::Context> context,
+                         const PortId& port_id,
+                         int routing_id,
+                         std::unique_ptr<Message> message) override;
+  void ClosePort(v8::Local<v8::Context> context,
+                 const PortId& port_id,
+                 int routing_id) override;
+
+  gin::Handle<GinPort> CreatePortForTesting(ScriptContext* script_context,
+                                            const std::string& channel_name,
+                                            const PortId& port_id);
+  gin::Handle<GinPort> GetPortForTesting(ScriptContext* script_context,
+                                         const PortId& port_id);
+  bool HasPortForTesting(ScriptContext* script_context, const PortId& port_id);
+
+ private:
+  // RendererMessagingService:
+  bool ContextHasMessagePort(ScriptContext* script_context,
+                             const PortId& port_id) override;
+  void DispatchOnConnectToListeners(
+      ScriptContext* script_context,
+      const PortId& target_port_id,
+      const std::string& target_extension_id,
+      const std::string& channel_name,
+      const ExtensionMsg_TabConnectionInfo* source,
+      const ExtensionMsg_ExternalConnectionInfo& info,
+      const std::string& tls_channel_id,
+      const std::string& event_name) override;
+  void DispatchOnMessageToListeners(ScriptContext* script_context,
+                                    const Message& message,
+                                    const PortId& target_port_id) override;
+  void DispatchOnDisconnectToListeners(ScriptContext* script_context,
+                                       const PortId& port_id,
+                                       const std::string& error) override;
+
+  // Creates a new port in the given context, with the specified |channel_name|
+  // and |port_id|. Assumes no such port exists.
+  gin::Handle<GinPort> CreatePort(ScriptContext* script_context,
+                                  const std::string& channel_name,
+                                  const PortId& port_id);
+
+  // Returns the port with the given |port_id| in the given |script_context|;
+  // requires that such a port exists.
+  gin::Handle<GinPort> GetPort(ScriptContext* script_context,
+                               const PortId& port_id);
+
+  // The associated bindings system; guaranteed to outlive this object.
+  NativeExtensionBindingsSystem* const bindings_system_;
+
+  DISALLOW_COPY_AND_ASSIGN(NativeRendererMessagingService);
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_RENDERER_NATIVE_RENDERER_MESSAGING_SERVICE_H_
diff --git a/extensions/renderer/native_renderer_messaging_service_unittest.cc b/extensions/renderer/native_renderer_messaging_service_unittest.cc
new file mode 100644
index 0000000..1ef7253
--- /dev/null
+++ b/extensions/renderer/native_renderer_messaging_service_unittest.cc
@@ -0,0 +1,331 @@
+// 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 "extensions/renderer/native_renderer_messaging_service.h"
+
+#include <memory>
+
+#include "content/public/common/child_process_host.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/extension_builder.h"
+#include "extensions/common/extension_messages.h"
+#include "extensions/common/value_builder.h"
+#include "extensions/renderer/bindings/api_binding_test_util.h"
+#include "extensions/renderer/native_extension_bindings_system.h"
+#include "extensions/renderer/native_extension_bindings_system_unittest.h"
+#include "extensions/renderer/script_context.h"
+#include "extensions/renderer/script_context_set.h"
+
+namespace extensions {
+
+class NativeRendererMessagingServiceTest
+    : public NativeExtensionBindingsSystemUnittest {
+ public:
+  NativeRendererMessagingServiceTest() {}
+  ~NativeRendererMessagingServiceTest() override {}
+
+  // NativeExtensionBindingsSystemUnittest:
+  void SetUp() override {
+    NativeExtensionBindingsSystemUnittest::SetUp();
+    messaging_service_ =
+        std::make_unique<NativeRendererMessagingService>(bindings_system());
+
+    scoped_refptr<Extension> mutable_extension =
+        ExtensionBuilder("foo").Build();
+    RegisterExtension(mutable_extension);
+    extension_ = mutable_extension;
+
+    v8::HandleScope handle_scope(isolate());
+    v8::Local<v8::Context> context = MainContext();
+
+    script_context_ = CreateScriptContext(context, mutable_extension.get(),
+                                          Feature::BLESSED_EXTENSION_CONTEXT);
+    script_context_->set_url(extension_->url());
+    bindings_system()->UpdateBindingsForContext(script_context_);
+  }
+  void TearDown() override {
+    script_context_ = nullptr;
+    extension_ = nullptr;
+    messaging_service_.reset();
+    NativeExtensionBindingsSystemUnittest::TearDown();
+  }
+  bool UseStrictIPCMessageSender() override { return true; }
+
+  NativeRendererMessagingService* messaging_service() {
+    return messaging_service_.get();
+  }
+  ScriptContext* script_context() { return script_context_; }
+  const Extension* extension() { return extension_.get(); }
+
+ private:
+  std::unique_ptr<NativeRendererMessagingService> messaging_service_;
+
+  ScriptContext* script_context_ = nullptr;
+  scoped_refptr<const Extension> extension_;
+
+  DISALLOW_COPY_AND_ASSIGN(NativeRendererMessagingServiceTest);
+};
+
+TEST_F(NativeRendererMessagingServiceTest, ValidateMessagePort) {
+  v8::HandleScope handle_scope(isolate());
+
+  base::UnguessableToken other_context_id = base::UnguessableToken::Create();
+  const PortId port_id(other_context_id, 0, false);
+
+  EXPECT_FALSE(
+      messaging_service()->HasPortForTesting(script_context(), port_id));
+  EXPECT_CALL(*ipc_message_sender(),
+              SendCloseMessagePort(MSG_ROUTING_NONE, port_id, false));
+  messaging_service()->ValidateMessagePort(*script_context_set(), port_id,
+                                           nullptr);
+  ::testing::Mock::VerifyAndClearExpectations(ipc_message_sender());
+
+  messaging_service()->CreatePortForTesting(script_context(), "channel",
+                                            port_id);
+  EXPECT_TRUE(
+      messaging_service()->HasPortForTesting(script_context(), port_id));
+
+  // With a valid port, we shouldn't dispatch a message to close it.
+  messaging_service()->ValidateMessagePort(*script_context_set(), port_id,
+                                           nullptr);
+}
+
+TEST_F(NativeRendererMessagingServiceTest, OpenMessagePort) {
+  v8::HandleScope handle_scope(isolate());
+  v8::Local<v8::Context> context = MainContext();
+
+  base::UnguessableToken other_context_id = base::UnguessableToken::Create();
+  const PortId port_id(other_context_id, 0, false);
+  EXPECT_FALSE(
+      messaging_service()->HasPortForTesting(script_context(), port_id));
+
+  const std::string channel_name = "some channel";
+  ExtensionMsg_TabConnectionInfo tab_connection_info;
+  tab_connection_info.frame_id = 0;
+  const int tab_id = 10;
+  GURL source_url("http://example.com");
+  tab_connection_info.tab.Swap(
+      DictionaryBuilder().Set("tabId", tab_id).Build().get());
+  ExtensionMsg_ExternalConnectionInfo external_connection_info;
+  external_connection_info.target_id = extension()->id();
+  external_connection_info.source_id = extension()->id();
+  external_connection_info.source_url = source_url;
+  external_connection_info.guest_process_id =
+      content::ChildProcessHost::kInvalidUniqueID;
+  external_connection_info.guest_render_frame_routing_id = 0;
+
+  const char kAddListener[] =
+      "(function() {\n"
+      "  chrome.runtime.onConnect.addListener(function(port) {\n"
+      "    this.eventFired = true;\n"
+      "    this.sender = port.sender\n"
+      "  });\n"
+      "})";
+  v8::Local<v8::Function> add_listener =
+      FunctionFromString(context, kAddListener);
+  RunFunctionOnGlobal(add_listener, context, 0, nullptr);
+
+  EXPECT_CALL(*ipc_message_sender(),
+              SendOpenMessagePort(MSG_ROUTING_NONE, port_id));
+  messaging_service()->DispatchOnConnect(
+      *script_context_set(), port_id, channel_name, tab_connection_info,
+      external_connection_info, std::string(), nullptr);
+  ::testing::Mock::VerifyAndClearExpectations(ipc_message_sender());
+
+  ASSERT_TRUE(
+      messaging_service()->HasPortForTesting(script_context(), port_id));
+
+  EXPECT_EQ("true", GetStringPropertyFromObject(context->Global(), context,
+                                                "eventFired"));
+  std::unique_ptr<base::DictionaryValue> expected_sender =
+      DictionaryBuilder()
+          .Set("frameId", 0)
+          .Set("tab", DictionaryBuilder().Set("tabId", tab_id).Build())
+          .Set("url", source_url.spec())
+          .Set("id", extension()->id())
+          .Build();
+  EXPECT_EQ(ValueToString(*expected_sender),
+            GetStringPropertyFromObject(context->Global(), context, "sender"));
+}
+
+TEST_F(NativeRendererMessagingServiceTest, DeliverMessageToPort) {
+  v8::HandleScope handle_scope(isolate());
+  v8::Local<v8::Context> context = MainContext();
+
+  base::UnguessableToken other_context_id = base::UnguessableToken::Create();
+  const PortId port_id1(other_context_id, 0, false);
+  const PortId port_id2(other_context_id, 1, false);
+
+  gin::Handle<GinPort> port1 = messaging_service()->CreatePortForTesting(
+      script_context(), "channel1", port_id1);
+  gin::Handle<GinPort> port2 = messaging_service()->CreatePortForTesting(
+      script_context(), "channel2", port_id2);
+  ASSERT_FALSE(port1.IsEmpty());
+
+  const char kOnMessageListenerTemplate[] =
+      "(function(port) {\n"
+      "  port.onMessage.addListener((message) => {\n"
+      "    this.%s = message;\n"
+      "  });\n"
+      "})";
+  const char kPort1Message[] = "port1Message";
+  const char kPort2Message[] = "port2Message";
+  {
+    v8::Local<v8::Function> add_on_message_listener = FunctionFromString(
+        context, base::StringPrintf(kOnMessageListenerTemplate, kPort1Message));
+    v8::Local<v8::Value> args[] = {port1.ToV8()};
+    RunFunctionOnGlobal(add_on_message_listener, context, arraysize(args),
+                        args);
+  }
+  {
+    v8::Local<v8::Function> add_on_message_listener = FunctionFromString(
+        context, base::StringPrintf(kOnMessageListenerTemplate, kPort2Message));
+    v8::Local<v8::Value> args[] = {port2.ToV8()};
+    RunFunctionOnGlobal(add_on_message_listener, context, arraysize(args),
+                        args);
+  }
+
+  // We've only added listeners (not dispatched any messages), so neither
+  // listener should have been triggered.
+  v8::Local<v8::Object> global = context->Global();
+  EXPECT_EQ("undefined",
+            GetStringPropertyFromObject(global, context, kPort1Message));
+  EXPECT_EQ("undefined",
+            GetStringPropertyFromObject(global, context, kPort2Message));
+
+  const char kMessageString[] = R"({"data":"hello"})";
+  messaging_service()->DeliverMessage(*script_context_set(), port_id1,
+                                      Message(kMessageString, false), nullptr);
+
+  // Only port1 should have been notified of the message (ports only receive
+  // messages directed to themselves).
+  EXPECT_EQ(kMessageString,
+            GetStringPropertyFromObject(global, context, kPort1Message));
+  EXPECT_EQ("undefined",
+            GetStringPropertyFromObject(global, context, kPort2Message));
+}
+
+TEST_F(NativeRendererMessagingServiceTest, DisconnectMessagePort) {
+  v8::HandleScope handle_scope(isolate());
+  v8::Local<v8::Context> context = MainContext();
+
+  base::UnguessableToken other_context_id = base::UnguessableToken::Create();
+  const PortId port_id1(other_context_id, 0, false);
+  const PortId port_id2(other_context_id, 1, false);
+
+  gin::Handle<GinPort> port1 = messaging_service()->CreatePortForTesting(
+      script_context(), "channel1", port_id1);
+  gin::Handle<GinPort> port2 = messaging_service()->CreatePortForTesting(
+      script_context(), "channel2", port_id2);
+
+  const char kOnDisconnectListenerTemplate[] =
+      "(function(port) {\n"
+      "  port.onDisconnect.addListener(() => {\n"
+      "    this.%s = true;\n"
+      "  });\n"
+      "})";
+  const char kPort1Disconnect[] = "port1Disconnect";
+  const char kPort2Disconnect[] = "port2Disconnect";
+  {
+    v8::Local<v8::Function> add_on_disconnect_listener = FunctionFromString(
+        context,
+        base::StringPrintf(kOnDisconnectListenerTemplate, kPort1Disconnect));
+    v8::Local<v8::Value> args[] = {port1.ToV8()};
+    RunFunctionOnGlobal(add_on_disconnect_listener, context, arraysize(args),
+                        args);
+  }
+  {
+    v8::Local<v8::Function> add_on_disconnect_listener = FunctionFromString(
+        context,
+        base::StringPrintf(kOnDisconnectListenerTemplate, kPort2Disconnect));
+    v8::Local<v8::Value> args[] = {port2.ToV8()};
+    RunFunctionOnGlobal(add_on_disconnect_listener, context, arraysize(args),
+                        args);
+  }
+
+  v8::Local<v8::Object> global = context->Global();
+  EXPECT_EQ("undefined",
+            GetStringPropertyFromObject(global, context, kPort1Disconnect));
+  EXPECT_EQ("undefined",
+            GetStringPropertyFromObject(global, context, kPort2Disconnect));
+
+  messaging_service()->DispatchOnDisconnect(*script_context_set(), port_id1,
+                                            std::string(), nullptr);
+
+  EXPECT_EQ("true",
+            GetStringPropertyFromObject(global, context, kPort1Disconnect));
+  EXPECT_EQ("undefined",
+            GetStringPropertyFromObject(global, context, kPort2Disconnect));
+}
+
+TEST_F(NativeRendererMessagingServiceTest, PostMessageFromJS) {
+  v8::HandleScope handle_scope(isolate());
+  v8::Local<v8::Context> context = MainContext();
+
+  base::UnguessableToken other_context_id = base::UnguessableToken::Create();
+  const PortId port_id(other_context_id, 0, false);
+
+  gin::Handle<GinPort> port = messaging_service()->CreatePortForTesting(
+      script_context(), "channel", port_id);
+  v8::Local<v8::Object> port_object = port.ToV8().As<v8::Object>();
+
+  const char kDispatchMessage[] =
+      "(function(port) {\n"
+      "  port.postMessage({data: 'hello'});\n"
+      "})";
+  v8::Local<v8::Function> post_message =
+      FunctionFromString(context, kDispatchMessage);
+  v8::Local<v8::Value> args[] = {port_object};
+
+  EXPECT_CALL(*ipc_message_sender(),
+              SendPostMessageToPort(MSG_ROUTING_NONE, port_id,
+                                    Message(R"({"data":"hello"})", false)));
+  RunFunctionOnGlobal(post_message, context, arraysize(args), args);
+  ::testing::Mock::VerifyAndClearExpectations(ipc_message_sender());
+}
+
+TEST_F(NativeRendererMessagingServiceTest, DisconnectFromJS) {
+  v8::HandleScope handle_scope(isolate());
+  v8::Local<v8::Context> context = MainContext();
+
+  base::UnguessableToken other_context_id = base::UnguessableToken::Create();
+  const PortId port_id(other_context_id, 0, false);
+
+  gin::Handle<GinPort> port = messaging_service()->CreatePortForTesting(
+      script_context(), "channel", port_id);
+  v8::Local<v8::Object> port_object = port.ToV8().As<v8::Object>();
+
+  const char kDispatchMessage[] =
+      "(function(port) {\n"
+      "  port.disconnect();\n"
+      "})";
+  v8::Local<v8::Function> post_message =
+      FunctionFromString(context, kDispatchMessage);
+  v8::Local<v8::Value> args[] = {port_object};
+
+  EXPECT_CALL(*ipc_message_sender(),
+              SendCloseMessagePort(MSG_ROUTING_NONE, port_id, true));
+  RunFunctionOnGlobal(post_message, context, arraysize(args), args);
+  ::testing::Mock::VerifyAndClearExpectations(ipc_message_sender());
+}
+
+TEST_F(NativeRendererMessagingServiceTest, Connect) {
+  v8::HandleScope handle_scope(isolate());
+
+  const std::string kChannel = "channel";
+  PortId expected_port_id(script_context()->context_id(), 0, true);
+  EXPECT_CALL(*ipc_message_sender(),
+              SendOpenChannelToExtension(script_context(), expected_port_id,
+                                         extension()->id(), kChannel, false));
+  gin::Handle<GinPort> new_port = messaging_service()->Connect(
+      script_context(), extension()->id(), "channel", false);
+  ::testing::Mock::VerifyAndClearExpectations(ipc_message_sender());
+  ASSERT_FALSE(new_port.IsEmpty());
+
+  EXPECT_EQ(expected_port_id, new_port->port_id());
+  EXPECT_EQ(kChannel, new_port->name());
+  EXPECT_FALSE(new_port->is_closed());
+}
+
+}  // namespace extensions
diff --git a/extensions/renderer/renderer_messaging_service.cc b/extensions/renderer/renderer_messaging_service.cc
index 2ef7829e..d80a1c2 100644
--- a/extensions/renderer/renderer_messaging_service.cc
+++ b/extensions/renderer/renderer_messaging_service.cc
@@ -20,6 +20,7 @@
 #include "extensions/common/extension_messages.h"
 #include "extensions/renderer/extension_bindings_system.h"
 #include "extensions/renderer/extension_port.h"
+#include "extensions/renderer/ipc_message_sender.h"
 #include "extensions/renderer/script_context.h"
 #include "extensions/renderer/script_context_set.h"
 #include "third_party/WebKit/public/web/WebDocument.h"
@@ -40,7 +41,12 @@
     const ScriptContextSet& context_set,
     const PortId& port_id,
     content::RenderFrame* render_frame) {
-  int routing_id = render_frame->GetRoutingID();
+  // TODO(devlin): In practice, |render_frame| should never be null here (unlike
+  // in other methods, where it legitimately can), but it can be in testing. It
+  // would be better to fake it somehow, but unfortunately, there's no good way
+  // to have a RenderFrame in a unittest. :(
+  int routing_id =
+      render_frame ? render_frame->GetRoutingID() : MSG_ROUTING_NONE;
 
   bool has_port = false;
   // The base::Unretained() below is safe since ScriptContextSet::ForEach is
@@ -53,8 +59,8 @@
   // A reply is only sent if the port is missing, because the port is assumed to
   // exist unless stated otherwise.
   if (!has_port) {
-    content::RenderThread::Get()->Send(
-        new ExtensionHostMsg_CloseMessagePort(routing_id, port_id, false));
+    bindings_system_->GetIPCMessageSender()->SendCloseMessagePort(
+        routing_id, port_id, false);
   }
 }
 
@@ -78,12 +84,11 @@
                  info, tls_channel_id, &port_created));
   // Note: |restrict_to_render_frame| may have been deleted at this point!
 
+  IPCMessageSender* ipc_sender = bindings_system_->GetIPCMessageSender();
   if (port_created) {
-    content::RenderThread::Get()->Send(
-        new ExtensionHostMsg_OpenMessagePort(routing_id, target_port_id));
+    ipc_sender->SendOpenMessagePort(routing_id, target_port_id);
   } else {
-    content::RenderThread::Get()->Send(new ExtensionHostMsg_CloseMessagePort(
-        routing_id, target_port_id, false));
+    ipc_sender->SendCloseMessagePort(routing_id, target_port_id, false);
   }
 }
 
diff --git a/extensions/renderer/resources/messaging.js b/extensions/renderer/resources/messaging.js
index d684890..f32ddadd 100644
--- a/extensions/renderer/resources/messaging.js
+++ b/extensions/renderer/resources/messaging.js
@@ -116,7 +116,9 @@
       console.error('Illegal argument to Port.postMessage');
       return;
     }
-    messagingNatives.PostMessage(this.portId_, msg);
+    var error = messagingNatives.PostMessage(this.portId_, msg);
+    if (error)
+      throw new Error(error);
   };
 
   // Disconnects the port from the other end.
diff --git a/extensions/renderer/script_context_set.cc b/extensions/renderer/script_context_set.cc
index b1e5cca4..cbf6292 100644
--- a/extensions/renderer/script_context_set.cc
+++ b/extensions/renderer/script_context_set.cc
@@ -111,9 +111,6 @@
     }
 
     content::RenderFrame* context_render_frame = context->GetRenderFrame();
-    if (!context_render_frame)
-      continue;
-
     if (render_frame && render_frame != context_render_frame)
       continue;
 
diff --git a/extensions/shell/BUILD.gn b/extensions/shell/BUILD.gn
index 08feb083..b7bc6f5 100644
--- a/extensions/shell/BUILD.gn
+++ b/extensions/shell/BUILD.gn
@@ -5,6 +5,7 @@
 import("//build/config/features.gni")
 import("//build/config/ui.gni")
 import("//build/util/process_version.gni")
+import("//components/nacl/features.gni")
 import("//extensions/features/features.gni")
 import("//testing/test.gni")
 import("//tools/grit/grit_rule.gni")
diff --git a/extensions/shell/browser/shell_extensions_api_client.cc b/extensions/shell/browser/shell_extensions_api_client.cc
index 3da96e0..e93e9b8 100644
--- a/extensions/shell/browser/shell_extensions_api_client.cc
+++ b/extensions/shell/browser/shell_extensions_api_client.cc
@@ -4,7 +4,10 @@
 
 #include "extensions/shell/browser/shell_extensions_api_client.h"
 
+#include <utility>
+
 #include "base/memory/ptr_util.h"
+#include "content/public/browser/browser_context.h"
 #include "extensions/browser/api/messaging/messaging_delegate.h"
 #include "extensions/shell/browser/api/feedback_private/shell_feedback_private_delegate.h"
 #include "extensions/shell/browser/delegates/shell_kiosk_delegate.h"
@@ -33,7 +36,8 @@
 }
 
 std::unique_ptr<VirtualKeyboardDelegate>
-ShellExtensionsAPIClient::CreateVirtualKeyboardDelegate() const {
+ShellExtensionsAPIClient::CreateVirtualKeyboardDelegate(
+    content::BrowserContext* browser_context) const {
   return std::make_unique<ShellVirtualKeyboardDelegate>();
 }
 
diff --git a/extensions/shell/browser/shell_extensions_api_client.h b/extensions/shell/browser/shell_extensions_api_client.h
index ce4acf7..a460279 100644
--- a/extensions/shell/browser/shell_extensions_api_client.h
+++ b/extensions/shell/browser/shell_extensions_api_client.h
@@ -26,8 +26,8 @@
   void AttachWebContentsHelpers(content::WebContents* web_contents) const
       override;
   AppViewGuestDelegate* CreateAppViewGuestDelegate() const override;
-  std::unique_ptr<VirtualKeyboardDelegate> CreateVirtualKeyboardDelegate()
-      const override;
+  std::unique_ptr<VirtualKeyboardDelegate> CreateVirtualKeyboardDelegate(
+      content::BrowserContext* browser_context) const override;
 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
   FileSystemDelegate* GetFileSystemDelegate() override;
 #endif
diff --git a/extensions/shell/browser/shell_virtual_keyboard_delegate.cc b/extensions/shell/browser/shell_virtual_keyboard_delegate.cc
index b7361305..a80adf5 100644
--- a/extensions/shell/browser/shell_virtual_keyboard_delegate.cc
+++ b/extensions/shell/browser/shell_virtual_keyboard_delegate.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <utility>
 
+#include "base/logging.h"
 #include "base/values.h"
 
 namespace extensions {
@@ -17,10 +18,13 @@
     OnKeyboardSettingsCallback on_settings_callback) {
   std::unique_ptr<base::DictionaryValue> settings(new base::DictionaryValue());
   settings->SetBoolean("hotrodmode", is_hotrod_keyboard_);
-  settings->SetBoolean("restricted", is_keyboard_restricted_);
   on_settings_callback.Run(std::move(settings));
 }
 
+void ShellVirtualKeyboardDelegate::OnKeyboardConfigChanged() {
+  NOTIMPLEMENTED();
+}
+
 bool ShellVirtualKeyboardDelegate::HideKeyboard() {
   return false;
 }
@@ -37,10 +41,6 @@
   is_hotrod_keyboard_ = enable;
 }
 
-void ShellVirtualKeyboardDelegate::SetKeyboardRestricted(bool restricted) {
-  is_keyboard_restricted_ = restricted;
-}
-
 bool ShellVirtualKeyboardDelegate::LockKeyboard(bool state) {
   return false;
 }
@@ -69,4 +69,32 @@
   return false;
 }
 
+api::virtual_keyboard::FeatureRestrictions
+ShellVirtualKeyboardDelegate::RestrictFeatures(
+    const api::virtual_keyboard::RestrictFeatures::Params& params) {
+  // Return the given parameter as is, since there's no stored values.
+  api::virtual_keyboard::FeatureRestrictions update;
+  if (params.restrictions.spell_check_enabled) {
+    update.spell_check_enabled =
+        std::make_unique<bool>(*params.restrictions.spell_check_enabled);
+  }
+  if (params.restrictions.auto_complete_enabled) {
+    update.auto_complete_enabled =
+        std::make_unique<bool>(*params.restrictions.auto_complete_enabled);
+  }
+  if (params.restrictions.auto_correct_enabled) {
+    update.auto_correct_enabled =
+        std::make_unique<bool>(*params.restrictions.auto_correct_enabled);
+  }
+  if (params.restrictions.voice_input_enabled) {
+    update.voice_input_enabled =
+        std::make_unique<bool>(*params.restrictions.voice_input_enabled);
+  }
+  if (params.restrictions.handwriting_enabled) {
+    update.handwriting_enabled =
+        std::make_unique<bool>(*params.restrictions.handwriting_enabled);
+  }
+  return update;
+}
+
 }  // namespace extensions
diff --git a/extensions/shell/browser/shell_virtual_keyboard_delegate.h b/extensions/shell/browser/shell_virtual_keyboard_delegate.h
index 15e403b..c51efd21 100644
--- a/extensions/shell/browser/shell_virtual_keyboard_delegate.h
+++ b/extensions/shell/browser/shell_virtual_keyboard_delegate.h
@@ -9,6 +9,7 @@
 
 #include "base/macros.h"
 #include "extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h"
+#include "extensions/common/api/virtual_keyboard.h"
 
 namespace extensions {
 
@@ -21,11 +22,11 @@
   // VirtualKeyboardDelegate impl:
   void GetKeyboardConfig(
       OnKeyboardSettingsCallback on_settings_callback) override;
+  void OnKeyboardConfigChanged() override;
   bool HideKeyboard() override;
   bool InsertText(const base::string16& text) override;
   bool OnKeyboardLoaded() override;
   void SetHotrodKeyboard(bool enable) override;
-  void SetKeyboardRestricted(bool restricted) override;
   bool LockKeyboard(bool state) override;
   bool SendKeyEvent(const std::string& type,
                     int char_value,
@@ -37,9 +38,11 @@
   bool SetVirtualKeyboardMode(int mode_enum) override;
   bool SetRequestedKeyboardState(int state_enum) override;
 
+  api::virtual_keyboard::FeatureRestrictions RestrictFeatures(
+      const api::virtual_keyboard::RestrictFeatures::Params& params) override;
+
  private:
   bool is_hotrod_keyboard_ = false;
-  bool is_keyboard_restricted_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(ShellVirtualKeyboardDelegate);
 };
diff --git a/extensions/shell/installer/linux/BUILD.gn b/extensions/shell/installer/linux/BUILD.gn
index f73353f..748dafc 100644
--- a/extensions/shell/installer/linux/BUILD.gn
+++ b/extensions/shell/installer/linux/BUILD.gn
@@ -11,6 +11,7 @@
 import("//build/config/sysroot.gni")
 import("//build/util/version.gni")
 import("//chrome/process_version_rc_template.gni")  # For branding_file_path.
+import("//components/nacl/features.gni")
 import("//extensions/features/features.gni")
 
 assert(is_desktop_linux)
diff --git a/extensions/shell/installer/linux/common/installer.include b/extensions/shell/installer/linux/common/installer.include
index bc29b66..6c6e14d 100644
--- a/extensions/shell/installer/linux/common/installer.include
+++ b/extensions/shell/installer/linux/common/installer.include
@@ -104,11 +104,12 @@
 stage_install_common() {
   echo "Staging common install files in '${STAGEDIR}'..."
 
-  # TODO(mmoss) This assumes we built the static binaries. To support shared
-  # builds, we probably want an install target in scons so it can give us all
-  # the right files. See also:
-  # http://code.google.com/p/chromium/issues/detail?id=4451
-  #
+  # Note: Changes here may also need to be applied to ChromeOS's
+  # chromite/lib/chrome_util.py.
+
+  # Note: This only supports static binaries and does not work when the GN
+  # is_component_build flag is true.
+
   # app
   STRIPPEDFILE="${BUILDDIR}/${PROGNAME}.stripped"
   install -m 755 "${STRIPPEDFILE}" "${STAGEDIR}/${INSTALLDIR}/${PROGNAME}"
@@ -118,13 +119,11 @@
     "${BUILDDIR}/extensions_shell_and_test.pak" \
     "${STAGEDIR}/${INSTALLDIR}/"
 
-
-  # ICU data file; only necessary when icu_use_data_file_flag is set to 1
-  # in build/common.gypi.
+  # ICU data file; Necessary when the GN icu_use_data_file flag is true.
   install -m 644 "${BUILDDIR}/icudtl.dat" "${STAGEDIR}/${INSTALLDIR}/"
 
-  # V8 snapshot files; only necessary when v8_use_external_startup_data is
-  # set to 1 in build/common.gypi.
+  # V8 snapshot files; Necessary when the GN v8_use_external_startup_data flag
+  # is true.
   if [ -f "${BUILDDIR}/natives_blob.bin" ]; then
     install -m 644 "${BUILDDIR}/natives_blob.bin" "${STAGEDIR}/${INSTALLDIR}/"
     install -m 644 "${BUILDDIR}/snapshot_blob.bin" "${STAGEDIR}/${INSTALLDIR}/"
@@ -150,7 +149,6 @@
     install -m 644 -s "${BUILDDIR}/lib/libc++.so" "${STAGEDIR}/${INSTALLDIR}/lib/"
   fi
 
-
   # nacl_helper and nacl_helper_bootstrap
   # Don't use "-s" (strip) because this runs binutils "strip", which
   # mangles the special ELF program headers of nacl_helper_bootstrap.
diff --git a/extensions/test/background_page_watcher.cc b/extensions/test/background_page_watcher.cc
index 4d80515..efa3719e 100644
--- a/extensions/test/background_page_watcher.cc
+++ b/extensions/test/background_page_watcher.cc
@@ -8,6 +8,7 @@
 #include "base/logging.h"
 #include "base/run_loop.h"
 #include "base/scoped_observer.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
@@ -54,7 +55,7 @@
   if (!host)
     return false;
   content::RenderProcessHost* rph =
-      host->host_contents()->GetRenderProcessHost();
+      host->host_contents()->GetMainFrame()->GetProcess();
   return rph && rph->HasConnection();
 }
 
diff --git a/extensions/test/data/api_test/virtual_keyboard/test.js b/extensions/test/data/api_test/virtual_keyboard/test.js
index cd4dec2..73906b5 100644
--- a/extensions/test/data/api_test/virtual_keyboard/test.js
+++ b/extensions/test/data/api_test/virtual_keyboard/test.js
@@ -3,44 +3,57 @@
 // found in the LICENSE file.
 
 chrome.test.runTests([
-    function setRestrictedKeyboard() {
-      chrome.virtualKeyboard.restrictFeatures({
-        autoCompleteEnabled: true,
-        autoCorrectEnabled: true,
-        spellCheckEnabled: true,
-        voiceInputEnabled: true,
-        handwritingEnabled: true
-      }, chrome.test.callbackPass(function() {
-          chrome.test.sendMessage('restrictedChanged',
-              function(featuresEnabled) {
-                chrome.test.assertEq('true', featuresEnabled);
-                chrome.test.succeed();
-              });
-          }));
-    },
-    function setNotRestrictedKeyboard() {
-      chrome.virtualKeyboard.restrictFeatures({
-        autoCompleteEnabled: false,
-        autoCorrectEnabled: false,
-        spellCheckEnabled: false,
-        voiceInputEnabled: false,
-        handwritingEnabled: false
-      }, chrome.test.callbackPass(function() {
-        chrome.test.sendMessage('restrictedChanged',
-            function(featuresEnabled) {
-              chrome.test.assertEq('false', featuresEnabled);
-              chrome.test.succeed();
-            });
+  function setRestrictedKeyboard() {
+    chrome.virtualKeyboard.restrictFeatures(
+        {
+          autoCompleteEnabled: true,
+          autoCorrectEnabled: true,
+          spellCheckEnabled: true,
+          voiceInputEnabled: true,
+          handwritingEnabled: true
+        },
+        chrome.test.callbackPass(function(update) {
+          chrome.test.assertEq(
+              {
+                autoCompleteEnabled: true,
+                autoCorrectEnabled: true,
+                spellCheckEnabled: true,
+                voiceInputEnabled: true,
+                handwritingEnabled: true
+              },
+              update);
         }));
-    },
-    function differentEnabledStates() {
-      var kError = 'All features are expected to have the same enabled state.';
-      chrome.virtualKeyboard.restrictFeatures({
-        autoCompleteEnabled: true,
-        autoCorrectEnabled: false,
-        spellCheckEnabled: true,
-        voiceInputEnabled: false,
-        handwritingEnabled: true
-      }, chrome.test.callbackFail(kError));
-    },
+  },
+  function setNotRestrictedKeyboard() {
+    chrome.virtualKeyboard.restrictFeatures(
+        {
+          autoCompleteEnabled: false,
+          autoCorrectEnabled: false,
+          spellCheckEnabled: false,
+          voiceInputEnabled: false,
+          handwritingEnabled: false
+        },
+        chrome.test.callbackPass(function(update) {
+          chrome.test.assertEq(
+              {
+                autoCompleteEnabled: false,
+                autoCorrectEnabled: false,
+                spellCheckEnabled: false,
+                voiceInputEnabled: false,
+                handwritingEnabled: false
+              },
+              update);
+        }));
+  },
+  function differentAndPartialEnabledStates() {
+    chrome.virtualKeyboard.restrictFeatures(
+        {
+          autoCompleteEnabled: true,
+          autoCorrectEnabled: false,
+          spellCheckEnabled: true,
+          voiceInputEnabled: false,
+          // handwritingEnabled is omitted.
+        },
+        chrome.test.callbackPass());
+  },
 ]);
diff --git a/google_apis/gaia/fake_gaia.cc b/google_apis/gaia/fake_gaia.cc
index f2290795..8221da8 100644
--- a/google_apis/gaia/fake_gaia.cc
+++ b/google_apis/gaia/fake_gaia.cc
@@ -125,19 +125,16 @@
 
 }  // namespace
 
-FakeGaia::AccessTokenInfo::AccessTokenInfo()
-  : expires_in(3600) {}
+FakeGaia::AccessTokenInfo::AccessTokenInfo() = default;
 
 FakeGaia::AccessTokenInfo::AccessTokenInfo(const AccessTokenInfo& other) =
     default;
 
-FakeGaia::AccessTokenInfo::~AccessTokenInfo() {}
+FakeGaia::AccessTokenInfo::~AccessTokenInfo() = default;
 
-FakeGaia::MergeSessionParams::MergeSessionParams() {
-}
+FakeGaia::MergeSessionParams::MergeSessionParams() = default;
 
-FakeGaia::MergeSessionParams::~MergeSessionParams() {
-}
+FakeGaia::MergeSessionParams::~MergeSessionParams() = default;
 
 void FakeGaia::MergeSessionParams::Update(const MergeSessionParams& update) {
   // This lambda uses a pointer to data member to merge attributes.
@@ -476,7 +473,8 @@
        entry != access_token_info_map_.upper_bound(auth_token);
        ++entry) {
     if (entry->second.audience == client_id &&
-        (scope_string.empty() || entry->second.scopes == scopes)) {
+        (scope_string.empty() || entry->second.any_scope ||
+         entry->second.scopes == scopes)) {
       return &(entry->second);
     }
   }
diff --git a/google_apis/gaia/fake_gaia.h b/google_apis/gaia/fake_gaia.h
index b2f0183..9909539 100644
--- a/google_apis/gaia/fake_gaia.h
+++ b/google_apis/gaia/fake_gaia.h
@@ -45,8 +45,10 @@
     std::string audience;
     std::string user_id;
     ScopeSet scopes;
-    int expires_in;
+    int expires_in = 3600;
     std::string email;
+    // When set to true, any scope set for issue token request matches |this|.
+    bool any_scope = false;
   };
 
   // Cookies and tokens for /MergeSession call seqeunce.
diff --git a/google_apis/gcm/tools/mcs_probe.cc b/google_apis/gcm/tools/mcs_probe.cc
index 3bec597..f14c52f6 100644
--- a/google_apis/gcm/tools/mcs_probe.cc
+++ b/google_apis/gcm/tools/mcs_probe.cc
@@ -192,7 +192,7 @@
  public:
   MCSProbeAuthPreferences()
       : HttpAuthPreferences(std::vector<std::string>()
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
                                 ,
                             std::string()
 #endif
diff --git a/gpu/command_buffer/tests/gl_texture_mailbox_unittest.cc b/gpu/command_buffer/tests/gl_texture_mailbox_unittest.cc
index 1cb88ce..e950fd186 100644
--- a/gpu/command_buffer/tests/gl_texture_mailbox_unittest.cc
+++ b/gpu/command_buffer/tests/gl_texture_mailbox_unittest.cc
@@ -8,6 +8,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include "gpu/command_buffer/client/gles2_implementation.h"
 #include "gpu/command_buffer/client/gles2_lib.h"
 #include "gpu/command_buffer/common/mailbox.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
@@ -91,6 +92,23 @@
     return mailbox;
   }
 
+  void AllocateTextureBackedFramebuffer(GLuint* tex, GLuint* fbo) {
+    glGenTextures(1, tex);
+    glBindTexture(GL_TEXTURE_2D, *tex);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 nullptr);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glGenFramebuffers(1, fbo);
+    glBindFramebuffer(GL_FRAMEBUFFER, *fbo);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+                           *tex, 0);
+    ASSERT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
+              glCheckFramebufferStatus(GL_FRAMEBUFFER));
+  }
+
   GLManager gl1_;
   GLManager gl2_;
 };
@@ -355,6 +373,87 @@
   EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
 }
 
+TEST_F(GLTextureMailboxTest, OrderingBarrierImpliesFlush) {
+  SetUpContexts();
+  gl2_.MakeCurrent();
+
+  // If the current platform requires the use of virtualized GL contexts
+  // for correctness, this harness does not respect that flag, so skip
+  // this test.
+  if (gl2_.workarounds().use_virtualized_gl_contexts) {
+    SUCCEED() << "Platform requires virtualized GL contexts; skipping.";
+    return;
+  }
+
+  GLuint fbo2 = 0;
+  glGenFramebuffers(1, &fbo2);
+  glBindFramebuffer(GL_FRAMEBUFFER, fbo2);
+  GLuint tex2 = 0;
+  glGenTextures(1, &tex2);
+  glBindTexture(GL_TEXTURE_2D, tex2);
+  gl1_.MakeCurrent();
+  GLuint tex1 = 0;
+  GLuint fbo1 = 0;
+  AllocateTextureBackedFramebuffer(&tex1, &fbo1);
+
+  // Many times:
+  //  - Set the texture to one color in context 1
+  //  - Mailbox the texture to context 2
+  //  - Set the texture to another color in context 2
+  //  - Mailbox the texture to context 1
+  //  - Read back the framebuffer in context 1
+  //  - Assert it's the color set by context 2
+
+  GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM];
+  glGenMailboxCHROMIUM(mailbox);
+  glProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox);
+
+  for (int i = 0; i < 1000; ++i) {
+    // Assume context 1 is current.
+    // Clear to red
+    glClearColor(1.0, 0.0, 0.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+    // Enforce ordering with respect to context 2.
+    gl1_.gles2_implementation()->OrderingBarrierCHROMIUM();
+    // Consume texture in context 2.
+    gl2_.MakeCurrent();
+    glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox);
+    EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+    // Set up framebuffer in context 2 (strictly, not necessary, could
+    // do this just once).
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+                           tex2, 0);
+    EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
+              glCheckFramebufferStatus(GL_FRAMEBUFFER));
+    // Clear to green.
+    glClearColor(0.0, 1.0, 0.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+    // Enforce ordering with respect to context 2.
+    gl2_.gles2_implementation()->OrderingBarrierCHROMIUM();
+    // Consume texture in context 1.
+    gl1_.MakeCurrent();
+    // Read back framebuffer.
+    GLubyte pixel[4];
+    glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel[0]);
+    EXPECT_EQ(0, pixel[0]);
+    EXPECT_EQ(255, pixel[1]);
+    EXPECT_EQ(0, pixel[2]);
+    EXPECT_EQ(255, pixel[3]);
+  }
+
+  glBindFramebuffer(GL_FRAMEBUFFER, 0);
+  glDeleteFramebuffers(1, &fbo1);
+  glBindTexture(GL_TEXTURE_2D, 0);
+  glDeleteTextures(1, &tex1);
+  EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+  gl2_.MakeCurrent();
+  glBindFramebuffer(GL_FRAMEBUFFER, 0);
+  glDeleteFramebuffers(1, &fbo2);
+  glBindTexture(GL_TEXTURE_2D, 0);
+  glDeleteTextures(1, &tex2);
+  EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+}
+
 TEST_F(GLTextureMailboxTest, TakeFrontBuffer) {
   SetUpContexts();
   gl1_.MakeCurrent();
diff --git a/headless/lib/browser/headless_web_contents_impl.cc b/headless/lib/browser/headless_web_contents_impl.cc
index b2161c5..86f4716 100644
--- a/headless/lib/browser/headless_web_contents_impl.cc
+++ b/headless/lib/browser/headless_web_contents_impl.cc
@@ -279,7 +279,7 @@
       agent_host_(content::DevToolsAgentHost::GetOrCreateFor(web_contents)),
       inject_mojo_services_into_isolated_world_(false),
       browser_context_(browser_context),
-      render_process_host_(web_contents->GetRenderProcessHost()),
+      render_process_host_(web_contents->GetMainFrame()->GetProcess()),
       weak_ptr_factory_(this) {
 #if BUILDFLAG(ENABLE_BASIC_PRINTING) && !defined(CHROME_MULTIPLE_DLL_CHILD)
   HeadlessPrintManager::CreateForWebContents(web_contents);
diff --git a/infra/config/cq.cfg b/infra/config/cq.cfg
index 66848b1..0e5f2ff 100644
--- a/infra/config/cq.cfg
+++ b/infra/config/cq.cfg
@@ -95,18 +95,12 @@
     }
     buckets {
       name: "master.tryserver.chromium.win"
+      builders { name: "win7_chromium_rel_ng" }
       builders { name: "win_chromium_compile_dbg_ng" }
-      builders {
-        name: "win_chromium_rel_ng"
-      }
       # crbug.com/753184 - take out of the CQ temporarily.
       # builders { name: "win_chromium_x64_rel_ng" }
       builders { name: "win_clang" }
       builders {
-        name: "win7_chromium_rel_ng"
-        experiment_percentage: 80
-      }
-      builders {
         name: "win10_chromium_x64_rel_ng"
         experiment_percentage: 20
       }
diff --git a/ios/build/bots/chromium.fyi/EarlGreyiOS.json b/ios/build/bots/chromium.fyi/EarlGreyiOS.json
index a059a2d..255d02b 100644
--- a/ios/build/bots/chromium.fyi/EarlGreyiOS.json
+++ b/ios/build/bots/chromium.fyi/EarlGreyiOS.json
@@ -16,6 +16,9 @@
   "tests": [
     {
       "app": "ios_chrome_integration_egtests",
+      "test args": [
+        "--enable-features=CredentialManager"
+      ],
       "device type": "iPhone 6s",
       "os": "11.0",
       "xcode version": "9.0",
@@ -85,6 +88,9 @@
     },
     {
       "app": "ios_chrome_integration_egtests",
+      "test args": [
+        "--enable-features=CredentialManager"
+      ],
       "device type": "iPad Air 2",
       "os": "11.0",
       "xcode version": "9.0",
diff --git a/ios/build/bots/chromium.mac/ios-simulator-eg.json b/ios/build/bots/chromium.mac/ios-simulator-eg.json
index 502ff7e..9490c2a0 100644
--- a/ios/build/bots/chromium.mac/ios-simulator-eg.json
+++ b/ios/build/bots/chromium.mac/ios-simulator-eg.json
@@ -16,6 +16,9 @@
   "tests": [
     {
       "app": "ios_chrome_integration_egtests",
+      "test args": [
+        "--enable-features=CredentialManager"
+      ],
       "device type": "iPhone 6s",
       "os": "11.0",
       "xcode version": "9.0",
@@ -85,6 +88,9 @@
     },
     {
       "app": "ios_chrome_integration_egtests",
+      "test args": [
+        "--enable-features=CredentialManager"
+      ],
       "device type": "iPad Air 2",
       "os": "11.0",
       "xcode version": "9.0",
diff --git a/ios/chrome/app/application_delegate/mock_tab_opener.mm b/ios/chrome/app/application_delegate/mock_tab_opener.mm
index 139d0fbd..02ba520 100644
--- a/ios/chrome/app/application_delegate/mock_tab_opener.mm
+++ b/ios/chrome/app/application_delegate/mock_tab_opener.mm
@@ -22,6 +22,7 @@
 
 - (void)dismissModalsAndOpenSelectedTabInMode:(ApplicationMode)targetMode
                                       withURL:(const GURL&)url
+                               dismissOmnibox:(BOOL)dismissOmnibox
                                    transition:(ui::PageTransition)transition
                                    completion:(ProceduralBlock)completion {
   _url = url;
diff --git a/ios/chrome/app/application_delegate/tab_opening.h b/ios/chrome/app/application_delegate/tab_opening.h
index fb369102..e8233d5 100644
--- a/ios/chrome/app/application_delegate/tab_opening.h
+++ b/ios/chrome/app/application_delegate/tab_opening.h
@@ -18,10 +18,12 @@
 // Protocol for object that can open new tabs during application launch.
 @protocol TabOpening<NSObject>
 
-// Dismisses any modal view then opens either a normal or incognito tab with
-// |url|. After opening |url|, run completion |handler| if it is not nil.
+// Dismisses any modal view, excluding the omnibox if |dismissOmnibox| is NO,
+// then opens either a normal or incognito tab with |url|. After opening |url|,
+// run completion |handler| if it is not nil.
 - (void)dismissModalsAndOpenSelectedTabInMode:(ApplicationMode)targetMode
                                       withURL:(const GURL&)url
+                               dismissOmnibox:(BOOL)dismissOmnibox
                                    transition:(ui::PageTransition)transition
                                    completion:(ProceduralBlock)completion;
 
diff --git a/ios/chrome/app/application_delegate/url_opener.mm b/ios/chrome/app/application_delegate/url_opener.mm
index 85eefae..5424575 100644
--- a/ios/chrome/app/application_delegate/url_opener.mm
+++ b/ios/chrome/app/application_delegate/url_opener.mm
@@ -72,6 +72,8 @@
                                                     ? ApplicationMode::INCOGNITO
                                                     : ApplicationMode::NORMAL
                                         withURL:[params externalURL]
+                                 dismissOmnibox:[params postOpeningAction] !=
+                                                FOCUS_OMNIBOX
                                      transition:ui::PAGE_TRANSITION_LINK
                                      completion:tabOpenedCompletion];
       return YES;
diff --git a/ios/chrome/app/application_delegate/user_activity_handler.mm b/ios/chrome/app/application_delegate/user_activity_handler.mm
index 0db6234..d880e42b9 100644
--- a/ios/chrome/app/application_delegate/user_activity_handler.mm
+++ b/ios/chrome/app/application_delegate/user_activity_handler.mm
@@ -166,6 +166,7 @@
             : ApplicationMode::NORMAL;
     [tabOpener dismissModalsAndOpenSelectedTabInMode:targetMode
                                              withURL:webpageGURL
+                                      dismissOmnibox:YES
                                           transition:ui::PAGE_TRANSITION_LINK
                                           completion:^{
                                             [startupInformation
@@ -253,6 +254,7 @@
                                              withURL:[[startupInformation
                                                          startupParameters]
                                                          externalURL]
+                                      dismissOmnibox:YES
                                           transition:ui::PAGE_TRANSITION_LINK
                                           completion:^{
                                             [startupInformation
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index f67772bb..84e2576 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -762,6 +762,7 @@
   if (_startupParameters) {
     [self dismissModalsAndOpenSelectedTabInMode:ApplicationMode::NORMAL
                                         withURL:[_startupParameters externalURL]
+                                 dismissOmnibox:YES
                                      transition:ui::PAGE_TRANSITION_LINK
                                      completion:^{
                                        [self setStartupParameters:nil];
@@ -1337,7 +1338,7 @@
 #pragma mark - ApplicationCommands
 
 - (void)dismissModalDialogs {
-  [self dismissModalDialogsWithCompletion:nil];
+  [self dismissModalDialogsWithCompletion:nil dismissOmnibox:YES];
 }
 
 - (void)switchModesAndOpenNewTab:(OpenNewTabCommand*)command {
@@ -1459,6 +1460,7 @@
   if ([command fromChrome]) {
     [self dismissModalsAndOpenSelectedTabInMode:ApplicationMode::NORMAL
                                         withURL:[command url]
+                                 dismissOmnibox:YES
                                      transition:ui::PAGE_TRANSITION_TYPED
                                      completion:nil];
   } else {
@@ -1468,7 +1470,8 @@
                                  referrer:[command referrer]
                              inBackground:[command inBackground]
                                  appendTo:[command appendTo]];
-    }];
+    }
+                             dismissOmnibox:YES];
   }
 }
 
@@ -1580,6 +1583,7 @@
   ProceduralBlock completion = ^{
     [self dismissModalsAndOpenSelectedTabInMode:ApplicationMode::NORMAL
                                         withURL:[command url]
+                                 dismissOmnibox:YES
                                      transition:ui::PAGE_TRANSITION_TYPED
                                      completion:nil];
   };
@@ -1865,7 +1869,7 @@
   if ([_tabSwitcherController
           respondsToSelector:@selector(tabSwitcherDismissWithModel:
                                                           animated:)]) {
-    [self dismissModalDialogsWithCompletion:nil];
+    [self dismissModalDialogsWithCompletion:nil dismissOmnibox:YES];
     [_tabSwitcherController tabSwitcherDismissWithModel:tabModel animated:NO];
   } else {
     [self beginDismissingStackViewWithCurrentModel:tabModel];
@@ -2266,7 +2270,8 @@
   return tab;
 }
 
-- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion {
+- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion
+                           dismissOmnibox:(BOOL)dismissOmnibox {
   // Immediately hide modals from the provider (alert views, action sheets,
   // popovers). They will be ultimately dismissed by their owners, but at least,
   // they are not visible.
@@ -2284,7 +2289,8 @@
   // it.
   ProceduralBlock completionWithBVC = ^{
     // This will dismiss the SSO view controller.
-    [self.currentBVC clearPresentedStateWithCompletion:completion];
+    [self.currentBVC clearPresentedStateWithCompletion:completion
+                                        dismissOmnibox:dismissOmnibox];
   };
   ProceduralBlock completionWithoutBVC = ^{
     // This will dismiss the SSO view controller.
@@ -2371,6 +2377,7 @@
 
 - (void)dismissModalsAndOpenSelectedTabInMode:(ApplicationMode)targetMode
                                       withURL:(const GURL&)url
+                               dismissOmnibox:(BOOL)dismissOmnibox
                                    transition:(ui::PageTransition)transition
                                    completion:(ProceduralBlock)completion {
   GURL copyOfURL = url;
@@ -2379,7 +2386,8 @@
                         withURL:copyOfURL
                      transition:transition
                      completion:completion];
-  }];
+  }
+                           dismissOmnibox:dismissOmnibox];
 }
 
 - (void)openTabFromLaunchOptions:(NSDictionary*)launchOptions
diff --git a/ios/chrome/app/main_controller_private.h b/ios/chrome/app/main_controller_private.h
index 90cc9151..01b1910 100644
--- a/ios/chrome/app/main_controller_private.h
+++ b/ios/chrome/app/main_controller_private.h
@@ -40,8 +40,10 @@
                                 timePeriod:(browsing_data::TimePeriod)timePeriod
                          completionHandler:(ProceduralBlock)completionHandler;
 
-// Dismisses all modal dialogs then call |completion|.
-- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion;
+// Dismisses all modal dialogs, excluding the omnibox if |dismissOmnibox| is
+// NO, then call |completion|.
+- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion
+                           dismissOmnibox:(BOOL)dismissOmnibox;
 
 @end
 
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm b/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm
index a94a908..dfd22a7 100644
--- a/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm
+++ b/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm
@@ -57,8 +57,6 @@
 
 ChromeBrowserStateImplIOData::Handle::~Handle() {
   DCHECK_CURRENTLY_ON(web::WebThread::UI);
-  if (io_data_->http_server_properties_manager_)
-    io_data_->http_server_properties_manager_->ShutdownOnPrefSequence();
 
   io_data_->ShutdownOnUIThread(GetAllContextGetters());
 }
@@ -151,13 +149,6 @@
   // Set initialized_ to true at the beginning in case any of the objects
   // below try to get the ResourceContext pointer.
   initialized_ = true;
-  PrefService* pref_service = browser_state_->GetPrefs();
-  io_data_->http_server_properties_manager_ =
-      HttpServerPropertiesManagerFactory::CreateManager(
-          pref_service,
-          GetApplicationContext()->GetIOSChromeIOThread()->net_log());
-  io_data_->set_http_server_properties(
-      base::WrapUnique(io_data_->http_server_properties_manager_));
   io_data_->InitializeOnUIThread(browser_state_);
 }
 
@@ -188,7 +179,10 @@
       http_server_properties_manager_(nullptr),
       app_cache_max_size_(0) {}
 
-ChromeBrowserStateImplIOData::~ChromeBrowserStateImplIOData() {}
+ChromeBrowserStateImplIOData::~ChromeBrowserStateImplIOData() {
+  if (http_server_properties_manager_)
+    http_server_properties_manager_->ShutdownOnPrefSequence();
+}
 
 void ChromeBrowserStateImplIOData::InitializeInternal(
     std::unique_ptr<IOSChromeNetworkDelegate> chrome_network_delegate,
@@ -212,8 +206,11 @@
 
   ApplyProfileParamsToContext(main_context);
 
-  if (http_server_properties_manager_)
-    http_server_properties_manager_->InitializeOnNetworkSequence();
+  http_server_properties_manager_ =
+      HttpServerPropertiesManagerFactory::CreateManager(network_json_store_,
+                                                        io_thread->net_log());
+  set_http_server_properties(base::WrapUnique(http_server_properties_manager_));
+  http_server_properties_manager_->InitializeOnNetworkSequence();
 
   main_context->set_transport_security_state(transport_security_state());
 
@@ -357,5 +354,7 @@
   // Completes synchronously.
   transport_security_state()->DeleteAllDynamicDataSince(time);
   DCHECK(http_server_properties_manager_);
-  http_server_properties_manager_->Clear(completion);
+  http_server_properties_manager_->Clear(
+      base::BindOnce(base::IgnoreResult(&web::WebThread::PostTask),
+                     web::WebThread::UI, FROM_HERE, completion));
 }
diff --git a/ios/chrome/browser/content_suggestions/content_suggestions_favicon_mediator.mm b/ios/chrome/browser/content_suggestions/content_suggestions_favicon_mediator.mm
index 96b769e..f8ca429 100644
--- a/ios/chrome/browser/content_suggestions/content_suggestions_favicon_mediator.mm
+++ b/ios/chrome/browser/content_suggestions/content_suggestions_favicon_mediator.mm
@@ -181,7 +181,7 @@
     ntp_tiles::NTPTile& ntpTile = _mostVisitedDataForLogging[i];
     if (ntpTile.url == item.URL) {
       ntp_tiles::metrics::RecordTileImpression(
-          i, ntpTile.source, [item tileType], item.URL,
+          i, ntpTile.title_source, ntpTile.source, [item tileType], item.URL,
           GetApplicationContext()->GetRapporServiceImpl());
       // Reset the URL to be sure to log the impression only once.
       ntpTile.url = GURL();
diff --git a/ios/chrome/browser/content_suggestions/mediator_util.mm b/ios/chrome/browser/content_suggestions/mediator_util.mm
index 9c973f7..19f07e1ad 100644
--- a/ios/chrome/browser/content_suggestions/mediator_util.mm
+++ b/ios/chrome/browser/content_suggestions/mediator_util.mm
@@ -148,6 +148,7 @@
   suggestion.title = base::SysUTF16ToNSString(tile.title);
   suggestion.URL = tile.url;
   suggestion.source = tile.source;
+  suggestion.titleSource = tile.title_source;
 
   suggestion.suggestionIdentifier = [[ContentSuggestionIdentifier alloc] init];
   suggestion.suggestionIdentifier.IDInSection = tile.url.spec();
diff --git a/ios/chrome/browser/content_suggestions/ntp_home_mediator.mm b/ios/chrome/browser/content_suggestions/ntp_home_mediator.mm
index 47556caf..404a2416 100644
--- a/ios/chrome/browser/content_suggestions/ntp_home_mediator.mm
+++ b/ios/chrome/browser/content_suggestions/ntp_home_mediator.mm
@@ -347,8 +347,8 @@
       recordAction:new_tab_page_uma::ACTION_OPENED_MOST_VISITED_ENTRY];
   base::RecordAction(base::UserMetricsAction("MobileNTPMostVisited"));
 
-  ntp_tiles::metrics::RecordTileClick(mostVisitedIndex, item.source,
-                                      [item tileType]);
+  ntp_tiles::metrics::RecordTileClick(mostVisitedIndex, item.titleSource,
+                                      item.source, [item tileType]);
 }
 
 // Shows a snackbar with an action to undo the removal of the most visited item
diff --git a/ios/chrome/browser/google/google_logo_service.h b/ios/chrome/browser/google/google_logo_service.h
index 197648d..2e6f450 100644
--- a/ios/chrome/browser/google/google_logo_service.h
+++ b/ios/chrome/browser/google/google_logo_service.h
@@ -8,7 +8,7 @@
 #include <memory>
 
 #include "components/search_provider_logos/logo_common.h"
-#include "components/search_provider_logos/logo_service.h"
+#include "components/search_provider_logos/logo_service_impl.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
 // Provides the logo if a BrowserState's default search provider is Google.
@@ -20,14 +20,14 @@
 //       GoogleLogoServiceFactory::GetForBrowserState(browser_state);
 //   logo_service->GetLogo(...);
 //
-class GoogleLogoService : public search_provider_logos::LogoService {
+class GoogleLogoService : public search_provider_logos::LogoServiceImpl {
  public:
   explicit GoogleLogoService(
       TemplateURLService* template_url_service,
       scoped_refptr<net::URLRequestContextGetter> request_context_getter);
   ~GoogleLogoService() override;
 
-  using LogoService::GetLogo;
+  using LogoServiceImpl::GetLogo;
 
   // |LogoService::GetLogo| does everything on callbacks, and iOS needs to load
   // the logo immediately on page load. This caches the SkBitmap so we can
diff --git a/ios/chrome/browser/google/google_logo_service.mm b/ios/chrome/browser/google/google_logo_service.mm
index c6b44a2..399c7c56 100644
--- a/ios/chrome/browser/google/google_logo_service.mm
+++ b/ios/chrome/browser/google/google_logo_service.mm
@@ -35,11 +35,11 @@
 GoogleLogoService::GoogleLogoService(
     TemplateURLService* template_url_service,
     scoped_refptr<net::URLRequestContextGetter> request_context_getter)
-    : LogoService(DoodleDirectory(),
-                  template_url_service,
-                  image_fetcher::CreateIOSImageDecoder(),
-                  request_context_getter,
-                  /*use_gray_background=*/false) {}
+    : LogoServiceImpl(DoodleDirectory(),
+                      template_url_service,
+                      image_fetcher::CreateIOSImageDecoder(),
+                      request_context_getter,
+                      /*use_gray_background=*/false) {}
 
 GoogleLogoService::~GoogleLogoService() {}
 
diff --git a/ios/chrome/browser/metrics/ios_chrome_metrics_services_manager_client.h b/ios/chrome/browser/metrics/ios_chrome_metrics_services_manager_client.h
index 1f4e92fd..4fe080c4 100644
--- a/ios/chrome/browser/metrics/ios_chrome_metrics_services_manager_client.h
+++ b/ios/chrome/browser/metrics/ios_chrome_metrics_services_manager_client.h
@@ -44,6 +44,8 @@
 
   net::URLRequestContextGetter* GetURLRequestContext() override;
   bool IsMetricsReportingEnabled() override;
+  bool IsMetricsConsentGiven() override;
+
   bool IsIncognitoSessionActive() override;
 
   // Gets the MetricsStateManager, creating it if it has not already been
diff --git a/ios/chrome/browser/metrics/ios_chrome_metrics_services_manager_client.mm b/ios/chrome/browser/metrics/ios_chrome_metrics_services_manager_client.mm
index 86529b30..53e016d 100644
--- a/ios/chrome/browser/metrics/ios_chrome_metrics_services_manager_client.mm
+++ b/ios/chrome/browser/metrics/ios_chrome_metrics_services_manager_client.mm
@@ -99,6 +99,10 @@
   return enabled_state_provider_->IsReportingEnabled();
 }
 
+bool IOSChromeMetricsServicesManagerClient::IsMetricsConsentGiven() {
+  return enabled_state_provider_->IsConsentGiven();
+}
+
 metrics::MetricsStateManager*
 IOSChromeMetricsServicesManagerClient::GetMetricsStateManager() {
   DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/ios/chrome/browser/net/http_server_properties_manager_factory.cc b/ios/chrome/browser/net/http_server_properties_manager_factory.cc
index 0180eab5..360a481 100644
--- a/ios/chrome/browser/net/http_server_properties_manager_factory.cc
+++ b/ios/chrome/browser/net/http_server_properties_manager_factory.cc
@@ -4,10 +4,10 @@
 
 #include "ios/chrome/browser/net/http_server_properties_manager_factory.h"
 
-#include "base/threading/thread_task_runner_handle.h"
+#include <memory>
+
+#include "base/values.h"
 #include "components/pref_registry/pref_registry_syncable.h"
-#include "components/prefs/pref_change_registrar.h"
-#include "components/prefs/pref_service.h"
 #include "ios/chrome/browser/pref_names.h"
 #include "ios/web/public/web_thread.h"
 #include "net/http/http_server_properties_manager.h"
@@ -15,38 +15,61 @@
 namespace {
 
 class PrefServiceAdapter
-    : public net::HttpServerPropertiesManager::PrefDelegate {
+    : public net::HttpServerPropertiesManager::PrefDelegate,
+      public PrefStore::Observer {
  public:
-  explicit PrefServiceAdapter(PrefService* pref_service)
-      : pref_service_(pref_service), path_(prefs::kHttpServerProperties) {
-    pref_change_registrar_.Init(pref_service_);
+  explicit PrefServiceAdapter(scoped_refptr<WriteablePrefStore> pref_store)
+      : pref_store_(std::move(pref_store)),
+        path_(prefs::kHttpServerProperties) {
+    pref_store_->AddObserver(this);
   }
 
-  ~PrefServiceAdapter() override {}
+  ~PrefServiceAdapter() override { pref_store_->RemoveObserver(this); }
 
   // PrefDelegate implementation.
   bool HasServerProperties() override {
-    return pref_service_->HasPrefPath(path_);
+    return pref_store_->GetValue(path_, nullptr);
   }
   const base::DictionaryValue& GetServerProperties() const override {
-    // Guaranteed not to return null when the pref is registered
-    // (RegisterProfilePrefs was called).
-    return *pref_service_->GetDictionary(path_);
+    const base::Value* value;
+    if (pref_store_->GetValue(path_, &value)) {
+      const base::DictionaryValue* dict;
+      if (value->GetAsDictionary(&dict))
+        return *dict;
+    }
+
+    return empty_dictionary_;
   }
   void SetServerProperties(const base::DictionaryValue& value) override {
-    return pref_service_->Set(path_, value);
+    return pref_store_->SetValue(path_, value.CreateDeepCopy(),
+                                 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
   }
   void StartListeningForUpdates(const base::Closure& callback) override {
-    pref_change_registrar_.Add(path_, callback);
+    on_changed_callback_ = callback;
   }
   void StopListeningForUpdates() override {
-    pref_change_registrar_.RemoveAll();
+    on_changed_callback_ = base::Closure();
+  }
+
+  // PrefStore::Observer implementation.
+  void OnPrefValueChanged(const std::string& key) override {
+    if (key == path_ && on_changed_callback_)
+      on_changed_callback_.Run();
+  }
+  void OnInitializationCompleted(bool succeeded) override {
+    if (succeeded && on_changed_callback_ && HasServerProperties())
+      on_changed_callback_.Run();
   }
 
  private:
-  PrefService* pref_service_;
+  scoped_refptr<WriteablePrefStore> pref_store_;
   const std::string path_;
-  PrefChangeRegistrar pref_change_registrar_;
+
+  // Returned when the pref is not set. Since the method returns a const
+  // net::DictionaryValue&, can't just create one on the stack.
+  base::DictionaryValue empty_dictionary_;
+
+  base::Closure on_changed_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(PrefServiceAdapter);
 };
@@ -55,16 +78,12 @@
 
 // static
 net::HttpServerPropertiesManager*
-HttpServerPropertiesManagerFactory::CreateManager(PrefService* pref_service,
-                                                  net::NetLog* net_log) {
+HttpServerPropertiesManagerFactory::CreateManager(
+    scoped_refptr<WriteablePrefStore> pref_store,
+    net::NetLog* net_log) {
+  DCHECK_CURRENTLY_ON(web::WebThread::IO);
   return new net::HttpServerPropertiesManager(
-      new PrefServiceAdapter(pref_service),  // Transfers ownership.
-      base::ThreadTaskRunnerHandle::Get(),
+      new PrefServiceAdapter(std::move(pref_store)),
+      web::WebThread::GetTaskRunnerForThread(web::WebThread::IO),
       web::WebThread::GetTaskRunnerForThread(web::WebThread::IO), net_log);
 }
-
-// static
-void HttpServerPropertiesManagerFactory::RegisterProfilePrefs(
-    user_prefs::PrefRegistrySyncable* registry) {
-  registry->RegisterDictionaryPref(prefs::kHttpServerProperties);
-}
diff --git a/ios/chrome/browser/net/http_server_properties_manager_factory.h b/ios/chrome/browser/net/http_server_properties_manager_factory.h
index 40f8dfd..0fc1bd1 100644
--- a/ios/chrome/browser/net/http_server_properties_manager_factory.h
+++ b/ios/chrome/browser/net/http_server_properties_manager_factory.h
@@ -6,29 +6,22 @@
 #define IOS_CHROME_BROWSER_NET_HTTP_SERVER_PROPERTIES_MANAGER_FACTORY_H_
 
 #include "base/macros.h"
-
-class PrefService;
+#include "base/memory/ref_counted.h"
+#include "components/prefs/writeable_pref_store.h"
 
 namespace net {
 class HttpServerPropertiesManager;
 class NetLog;
 }
 
-namespace user_prefs {
-class PrefRegistrySyncable;
-}
-
 // Class for registration and creation of HttpServerPropertiesManager
 class HttpServerPropertiesManagerFactory {
  public:
   // Create an instance of HttpServerPropertiesManager.
   static net::HttpServerPropertiesManager* CreateManager(
-      PrefService* pref_service,
+      scoped_refptr<WriteablePrefStore> pref_store,
       net::NetLog* net_log);
 
-  // Register prefs for properties managed by HttpServerPropertiesManager.
-  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
-
  private:
   DISALLOW_COPY_AND_ASSIGN(HttpServerPropertiesManagerFactory);
 };
diff --git a/ios/chrome/browser/passwords/BUILD.gn b/ios/chrome/browser/passwords/BUILD.gn
index 9ace7590..b83b2ba 100644
--- a/ios/chrome/browser/passwords/BUILD.gn
+++ b/ios/chrome/browser/passwords/BUILD.gn
@@ -29,6 +29,8 @@
     "js_credential_manager.mm",
     "js_password_manager.h",
     "js_password_manager.mm",
+    "notify_auto_signin_view_controller.h",
+    "notify_auto_signin_view_controller.mm",
     "password_controller.h",
     "password_controller.mm",
     "password_form_filler.h",
@@ -53,6 +55,8 @@
     "//components/autofill/core/common",
     "//components/autofill/ios/browser",
     "//components/browser_sync",
+    "//components/image_fetcher/core",
+    "//components/image_fetcher/ios",
     "//components/infobars/core",
     "//components/keyed_service/core",
     "//components/keyed_service/ios",
@@ -79,9 +83,12 @@
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/elements",
     "//ios/chrome/browser/ui/infobars",
+    "//ios/chrome/browser/web",
     "//ios/public/provider/chrome/browser",
     "//ios/public/provider/chrome/browser/ui",
+    "//ios/third_party/material_components_ios:material_components_ios",
     "//ios/web",
+    "//third_party/material_design_icons:ic_account_circle",
     "//ui/base",
     "//url",
   ]
@@ -144,6 +151,36 @@
   ]
 }
 
+source_set("eg_tests") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  testonly = true
+  sources = [
+    "credential_manager_egtest.mm",
+  ]
+
+  deps = [
+    ":passwords",
+    "//base",
+    "//base/test:test_support",
+    "//components/autofill/core/common",
+    "//components/autofill/ios/browser",
+    "//components/keyed_service/core",
+    "//components/password_manager/core/browser",
+    "//components/password_manager/core/browser:test_support",
+    "//components/password_manager/core/common",
+    "//components/prefs",
+    "//components/prefs:test_support",
+    "//ios/chrome/test/app:test_support",
+    "//ios/chrome/test/earl_grey:test_support",
+    "//ios/testing:ios_test_support",
+    "//ios/web/public/test/http_server",
+  ]
+  libs = [
+    "UIKit.framework",
+    "XCTest.framework",
+  ]
+}
+
 # TODO(crbug.com/487804): use js_compile_checked instead once the errors have
 # been fixed.
 js_compile_unchecked("injected_js") {
diff --git a/ios/chrome/browser/passwords/credential_manager_egtest.mm b/ios/chrome/browser/passwords/credential_manager_egtest.mm
new file mode 100644
index 0000000..fd03630
--- /dev/null
+++ b/ios/chrome/browser/passwords/credential_manager_egtest.mm
@@ -0,0 +1,210 @@
+// 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 "ios/chrome/browser/passwords/credential_manager.h"
+
+#import <EarlGrey/EarlGrey.h>
+#import <UIKit/UIKit.h>
+#import <XCTest/XCTest.h>
+
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
+#include "components/keyed_service/core/service_access_type.h"
+#include "components/password_manager/core/common/password_manager_pref_names.h"
+#include "ios/chrome/browser/passwords/credential_manager_features.h"
+#include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h"
+#import "ios/chrome/test/app/chrome_test_util.h"
+#import "ios/chrome/test/app/tab_test_util.h"
+#import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
+#import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
+#import "ios/chrome/test/earl_grey/chrome_matchers.h"
+#import "ios/chrome/test/earl_grey/chrome_test_case.h"
+#import "ios/testing/wait_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+
+// Notification should be displayed for 3 seconds. 4 should be safe to check.
+constexpr CFTimeInterval kDisappearanceTimeout = 4;
+// Provides basic response for example page.
+std::unique_ptr<net::test_server::HttpResponse> StandardResponse(
+    const net::test_server::HttpRequest& request) {
+  std::unique_ptr<net::test_server::BasicHttpResponse> http_response =
+      base::MakeUnique<net::test_server::BasicHttpResponse>();
+  http_response->set_code(net::HTTP_OK);
+  http_response->set_content(
+      "<head><title>Example website</title></head>"
+      "<body>You are here.</body>");
+  return std::move(http_response);
+}
+
+}  // namespace
+
+// This class tests UI behavior for Credential Manager.
+// TODO(crbug.com/435048): Add EG test for save/update password prompt.
+// TODO(crbug.com/435048): When account chooser and first run experience dialog
+// are implemented, test them too.
+@interface CredentialManagerEGTest : ChromeTestCase
+
+@end
+
+@implementation CredentialManagerEGTest {
+  base::test::ScopedFeatureList _featureList;
+}
+
+- (void)setUp {
+  _featureList.InitAndEnableFeature(features::kCredentialManager);
+  [super setUp];
+
+  // Set up server.
+  self.testServer->RegisterRequestHandler(base::Bind(&StandardResponse));
+  GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
+}
+
+- (void)tearDown {
+  scoped_refptr<password_manager::PasswordStore> passwordStore =
+      IOSChromePasswordStoreFactory::GetForBrowserState(
+          chrome_test_util::GetOriginalBrowserState(),
+          ServiceAccessType::IMPLICIT_ACCESS)
+          .get();
+  // Remove Credentials stored during executing the test.
+  passwordStore->RemoveLoginsCreatedBetween(base::Time(), base::Time::Now(),
+                                            base::Closure());
+  [super tearDown];
+}
+
+#pragma mark - Utils
+
+// Sets preferences required for autosign-in to true.
+- (void)setAutosigninPreferences {
+  chrome_test_util::SetBooleanUserPref(
+      chrome_test_util::GetOriginalBrowserState(),
+      password_manager::prefs::kWasAutoSignInFirstRunExperienceShown, true);
+  chrome_test_util::SetBooleanUserPref(
+      chrome_test_util::GetOriginalBrowserState(),
+      password_manager::prefs::kCredentialsEnableAutosignin, true);
+}
+
+// Loads simple page on localhost and stores an example PasswordCredential.
+- (void)loadSimplePageAndStoreACredential {
+  // Loads simple page. It is on localhost so it is considered a secure context.
+  const GURL URL = self.testServer->GetURL("/example");
+  [ChromeEarlGrey loadURL:URL];
+  [ChromeEarlGrey waitForWebViewContainingText:"You are here."];
+
+  // Obtain a PasswordStore.
+  scoped_refptr<password_manager::PasswordStore> passwordStore =
+      IOSChromePasswordStoreFactory::GetForBrowserState(
+          chrome_test_util::GetOriginalBrowserState(),
+          ServiceAccessType::IMPLICIT_ACCESS)
+          .get();
+  GREYAssertTrue(passwordStore != nullptr,
+                 @"PasswordStore is unexpectedly null for BrowserState");
+
+  // Store a PasswordForm representing a PasswordCredential.
+  autofill::PasswordForm passwordCredentialForm;
+  passwordCredentialForm.username_value =
+      base::ASCIIToUTF16("johndoe@example.com");
+  passwordCredentialForm.password_value = base::ASCIIToUTF16("ilovejanedoe123");
+  passwordCredentialForm.origin =
+      chrome_test_util::GetCurrentWebState()->GetLastCommittedURL().GetOrigin();
+  passwordCredentialForm.signon_realm = passwordCredentialForm.origin.spec();
+  passwordCredentialForm.scheme = autofill::PasswordForm::SCHEME_HTML;
+  passwordStore->AddLogin(passwordCredentialForm);
+}
+
+#pragma mark - Tests
+
+// Tests that notification saying "Signing is as ..." appears on auto sign-in.
+- (void)testNotificationAppearsOnAutoSignIn {
+  [self setAutosigninPreferences];
+  [self loadSimplePageAndStoreACredential];
+
+  // Call get() from JavaScript.
+  NSError* error = nil;
+  NSString* result = chrome_test_util::ExecuteJavaScript(
+      @"typeof navigator.credentials.get({password: true})", &error);
+  GREYAssertTrue([result isEqual:@"object"],
+                 @"Unexpected error occurred when executing JavaScript.");
+  GREYAssertTrue(!error,
+                 @"Unexpected error occurred when executing JavaScript.");
+
+  // Matches the UILabel by its accessibilityLabel.
+  id<GREYMatcher> matcher =
+      grey_allOf(grey_accessibilityLabel(@"Signing in as johndoe@example.com"),
+                 grey_accessibilityTrait(UIAccessibilityTraitStaticText), nil);
+  // Wait for notification to appear.
+  ConditionBlock waitForAppearance = ^{
+    NSError* error = nil;
+    [[EarlGrey selectElementWithMatcher:matcher] assertWithMatcher:grey_notNil()
+                                                             error:&error];
+    return error == nil;
+  };
+  // Gives some time for the notification to appear.
+  GREYAssert(testing::WaitUntilConditionOrTimeout(
+                 testing::kWaitForUIElementTimeout, waitForAppearance),
+             @"Notification did not appear");
+  // Wait for the notification to disappear.
+  ConditionBlock waitForDisappearance = ^{
+    NSError* error = nil;
+    [[EarlGrey selectElementWithMatcher:matcher]
+        assertWithMatcher:grey_sufficientlyVisible()
+                    error:&error];
+    return error == nil;
+  };
+  // Ensures that notification disappears after time limit.
+  GREYAssert(testing::WaitUntilConditionOrTimeout(kDisappearanceTimeout,
+                                                  waitForDisappearance),
+             @"Notification did not disappear");
+}
+
+// Tests that when navigator.credentials.get() was called from inactive tab, the
+// autosign-in notification appears once tab becomes active.
+- (void)testNotificationAppearsWhenTabIsActive {
+  [self setAutosigninPreferences];
+  [self loadSimplePageAndStoreACredential];
+
+  // Get WebState before switching the tab.
+  web::WebState* webState = chrome_test_util::GetCurrentWebState();
+
+  // Open new tab.
+  [ChromeEarlGreyUI openNewTab];
+  [ChromeEarlGrey waitForMainTabCount:2];
+
+  // Execute JavaScript from inactive tab.
+  webState->ExecuteJavaScript(
+      base::UTF8ToUTF16("typeof navigator.credentials.get({password: true})"));
+
+  // Matches the UILabel by its accessibilityLabel.
+  id<GREYMatcher> matcher = chrome_test_util::StaticTextWithAccessibilityLabel(
+      @"Signing in as johndoe@example.com");
+  // Wait for notification to appear.
+  ConditionBlock waitForAppearance = ^{
+    NSError* error = nil;
+    [[EarlGrey selectElementWithMatcher:matcher]
+        assertWithMatcher:grey_sufficientlyVisible()
+                    error:&error];
+    return error == nil;
+  };
+
+  // Check that notification doesn't appear in current tab.
+  GREYAssertFalse(testing::WaitUntilConditionOrTimeout(
+                      testing::kWaitForUIElementTimeout, waitForAppearance),
+                  @"Notification appeared in wrong tab");
+
+  // Switch to previous tab.
+  chrome_test_util::SelectTabAtIndexInCurrentMode(0);
+
+  // Check that the notification has appeared.
+  GREYAssert(testing::WaitUntilConditionOrTimeout(
+                 testing::kWaitForUIElementTimeout, waitForAppearance),
+             @"Notification did not appear");
+}
+
+@end
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h
index 2415bb39..1a355ff 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h
+++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h
@@ -30,6 +30,10 @@
 - (void)showUpdatePasswordInfoBar:
     (std::unique_ptr<password_manager::PasswordFormManager>)formToUpdate;
 
+// Shows UI to notify the user about auto sign in.
+- (void)showAutosigninNotification:
+    (std::unique_ptr<autofill::PasswordForm>)formSignedIn;
+
 @property(readonly, nonatomic) ios::ChromeBrowserState* browserState;
 
 @property(readonly) password_manager::PasswordManager* passwordManager;
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm
index 51e9a75..1da77457 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm
+++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm
@@ -133,7 +133,7 @@
     const GURL& origin) {
   DCHECK(!local_forms.empty());
   helper_.NotifyUserAutoSignin();
-  // TODO(crbug.com/435048): Show dialog to inform user about auto sign-in.
+  [delegate_ showAutosigninNotification:std::move(local_forms[0])];
 }
 
 void IOSChromePasswordManagerClient::NotifyUserCouldBeAutoSignedIn(
diff --git a/ios/chrome/browser/passwords/notify_auto_signin_view_controller.h b/ios/chrome/browser/passwords/notify_auto_signin_view_controller.h
new file mode 100644
index 0000000..7d95ab4
--- /dev/null
+++ b/ios/chrome/browser/passwords/notify_auto_signin_view_controller.h
@@ -0,0 +1,31 @@
+// 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 IOS_CHROME_BROWSER_PASSWORDS_NOTIFY_AUTO_SIGNIN_VIEW_CONTROLLER_H_
+#define IOS_CHROME_BROWSER_PASSWORDS_NOTIFY_AUTO_SIGNIN_VIEW_CONTROLLER_H_
+
+#import <UIKit/UIKit.h>
+
+namespace net {
+class URLRequestContextGetter;
+}  // namespace net
+
+class GURL;
+
+// UIViewController for the notification about auto sign-in.
+@interface NotifyUserAutoSigninViewController : UIViewController
+
+- (instancetype)initWithUsername:(NSString*)username
+                         iconURL:(GURL)iconURL
+                   contextGetter:(net::URLRequestContextGetter*)contextGetter
+    NS_DESIGNATED_INITIALIZER;
+
+- (instancetype)initWithNibName:(NSString*)nibNameOrNil
+                         bundle:(NSBundle*)nibBundleOrNil NS_UNAVAILABLE;
+- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
+- (instancetype)init NS_UNAVAILABLE;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_PASSWORDS_NOTIFY_AUTO_SIGNIN_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/passwords/notify_auto_signin_view_controller.mm b/ios/chrome/browser/passwords/notify_auto_signin_view_controller.mm
new file mode 100644
index 0000000..036196cf
--- /dev/null
+++ b/ios/chrome/browser/passwords/notify_auto_signin_view_controller.mm
@@ -0,0 +1,174 @@
+// 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 "ios/chrome/browser/passwords/notify_auto_signin_view_controller.h"
+
+#import "base/mac/bind_objc_block.h"
+#include "base/strings/sys_string_conversions.h"
+#include "components/image_fetcher/core/image_fetcher_impl.h"
+#include "components/image_fetcher/ios/ios_image_decoder_impl.h"
+#include "components/strings/grit/components_strings.h"
+#import "ios/chrome/browser/ui/rtl_geometry.h"
+#include "ios/chrome/browser/ui/uikit_ui_util.h"
+#import "ios/chrome/browser/ui/util/constraints_ui_util.h"
+#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/image/image.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+
+constexpr int kBackgroundColor = 0x4285F4;
+
+// NetworkTrafficAnnotationTag for fetching avatar.
+const net::NetworkTrafficAnnotationTag kTrafficAnnotation =
+    net::DefineNetworkTrafficAnnotation("credential_avatar",
+                                        R"(
+        semantics {
+          sender: "Chrome Password Manager"
+          description:
+            "Every credential saved in Chromium via the Credential Management "
+            "API can have an avatar URL. The URL is essentially provided by "
+            "the site calling the API. The avatar is used in the account "
+            "chooser UI and auto signin toast which appear when a site calls "
+            "navigator.credentials.get(). The avatar is retrieved before "
+            "showing the UI."
+          trigger:
+            "User visits a site that calls navigator.credentials.get(). "
+            "Assuming there are matching credentials in the Chromium password "
+            "store, the avatars are retrieved."
+          data: "Only avatar URL, no user data."
+          destination: WEBSITE
+        }
+        policy {
+          cookies_allowed: NO
+          setting:
+            "One can disable saving new credentials in the settings (see "
+            "'Passwords and forms'). There is no setting to disable the API."
+          chrome_policy {
+            PasswordManagerEnabled {
+              PasswordManagerEnabled: false
+            }
+          }
+        })");
+
+}  // namespace
+
+@interface NotifyUserAutoSigninViewController () {
+  std::unique_ptr<image_fetcher::ImageFetcher> _imageFetcher;
+}
+
+// Username, corresponding to Credential.id field in JS.
+@property(copy, nonatomic) NSString* username;
+// URL to user's avatar, corresponding to Credential.iconURL field in JS.
+@property(assign, nonatomic) GURL iconURL;
+// Image view displaying user's avatar (if fetched) or placeholder icon.
+@property(nonatomic, strong) UIImageView* avatarView;
+
+@end
+
+@implementation NotifyUserAutoSigninViewController
+
+@synthesize avatarView = _avatarView;
+@synthesize iconURL = _iconURL;
+@synthesize username = _username;
+
+- (instancetype)initWithUsername:(NSString*)username
+                         iconURL:(GURL)iconURL
+                   contextGetter:(net::URLRequestContextGetter*)contextGetter {
+  self = [super initWithNibName:nil bundle:nil];
+  if (self) {
+    _username = username;
+    _iconURL = iconURL;
+    _imageFetcher = std::make_unique<image_fetcher::ImageFetcherImpl>(
+        image_fetcher::CreateIOSImageDecoder(), contextGetter);
+  }
+  return self;
+}
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+
+  self.view.backgroundColor = UIColorFromRGB(kBackgroundColor);
+  self.view.translatesAutoresizingMaskIntoConstraints = NO;
+
+  // Blue background view for notification.
+  UIView* contentView = [[UIView alloc] init];
+  contentView.translatesAutoresizingMaskIntoConstraints = NO;
+  contentView.userInteractionEnabled = NO;
+
+  // View containing "Signing in as ..." text.
+  UILabel* textView = [[UILabel alloc] init];
+  textView.translatesAutoresizingMaskIntoConstraints = NO;
+  UIFont* font = [MDCTypography body1Font];
+  textView.text =
+      l10n_util::GetNSStringF(IDS_MANAGE_PASSWORDS_AUTO_SIGNIN_TITLE,
+                              base::SysNSStringToUTF16(_username));
+  textView.font = font;
+  textView.textColor = [UIColor whiteColor];
+  textView.userInteractionEnabled = NO;
+
+  // Load the placeholder user's avatar.
+  UIImage* placeholderAvatar = [UIImage imageNamed:@"ic_account_circle"];
+  // View containing user's avatar.
+  self.avatarView = [[UIImageView alloc] initWithImage:placeholderAvatar];
+  self.avatarView.translatesAutoresizingMaskIntoConstraints = NO;
+  self.avatarView.userInteractionEnabled = NO;
+
+  // Add subiews.
+  [contentView addSubview:textView];
+  [contentView addSubview:self.avatarView];
+  [self.view addSubview:contentView];
+
+  // Text view must leave 48pt on the left for user's avatar. Set the
+  // constraints.
+  NSDictionary* childrenViewsDictionary = @{
+    @"text" : textView,
+    @"avatar" : self.avatarView,
+  };
+  NSArray* childrenConstraints = @[
+    @"V:|[text]|",
+    @"V:|-12-[avatar(==24)]-12-|",
+    @"H:|-12-[avatar(==24)]-12-[text]-12-|",
+  ];
+  ApplyVisualConstraints(childrenConstraints, childrenViewsDictionary);
+
+  PinToSafeArea(contentView, self.view);
+
+  // Fetch user's avatar and update displayed image.
+  if (self.iconURL.is_valid()) {
+    __weak NotifyUserAutoSigninViewController* weakSelf = self;
+    _imageFetcher->StartOrQueueNetworkRequest(
+        _iconURL.spec(), _iconURL,
+        base::BindBlockArc(^(const std::string& id, const gfx::Image& image,
+                             const image_fetcher::RequestMetadata& metadata) {
+          if (!image.IsEmpty()) {
+            weakSelf.avatarView.image = [image.ToUIImage() copy];
+          }
+        }),
+        kTrafficAnnotation);
+  }
+}
+
+- (void)didMoveToParentViewController:(UIViewController*)parent {
+  [super didMoveToParentViewController:parent];
+  if (parent == nil) {
+    return;
+  }
+
+  // Set constraints for blue background.
+  [NSLayoutConstraint activateConstraints:@[
+    [self.view.bottomAnchor
+        constraintEqualToAnchor:self.view.superview.bottomAnchor],
+    [self.view.leadingAnchor
+        constraintEqualToAnchor:self.view.superview.leadingAnchor],
+    [self.view.trailingAnchor
+        constraintEqualToAnchor:self.view.superview.trailingAnchor],
+  ]];
+}
+
+@end
diff --git a/ios/chrome/browser/passwords/password_controller.h b/ios/chrome/browser/passwords/password_controller.h
index ce24523c..7fd5705 100644
--- a/ios/chrome/browser/passwords/password_controller.h
+++ b/ios/chrome/browser/passwords/password_controller.h
@@ -15,9 +15,11 @@
 
 @protocol ApplicationCommands;
 @protocol FormInputAccessoryViewProvider;
+@class NotifyUserAutoSigninViewController;
 @protocol PasswordFormFiller;
 @class PasswordGenerationAgent;
 @protocol PasswordsUiDelegate;
+@class UIViewController;
 
 namespace password_manager {
 class PasswordGenerationManager;
@@ -25,6 +27,17 @@
 class PasswordManagerDriver;
 }  // namespace password_manager
 
+// Delegate for registering view controller and displaying its view. Used to
+// add views to BVC.
+@protocol PasswordControllerDelegate
+
+// Adds |viewController| as child controller in order to display auto sign-in
+// notification. Returns YES if view was displayed, NO otherwise.
+- (BOOL)displaySignInNotification:(UIViewController*)viewController
+                        fromTabId:(NSString*)tabId;
+
+@end
+
 // Per-tab password controller. Handles password autofill and saving.
 @interface PasswordController : NSObject<CRWWebStateObserver,
                                          PasswordManagerClientDelegate,
@@ -57,6 +70,9 @@
 // even after being set to a non-nil object.
 @property(nonatomic, weak) id<ApplicationCommands> dispatcher;
 
+// Delegate used by this PasswordController to show UI on BVC.
+@property(weak, nonatomic) id<PasswordControllerDelegate> delegate;
+
 // |webState| should not be nil.
 - (instancetype)initWithWebState:(web::WebState*)webState
              passwordsUiDelegate:(id<PasswordsUiDelegate>)delegate;
diff --git a/ios/chrome/browser/passwords/password_controller.mm b/ios/chrome/browser/passwords/password_controller.mm
index 83654051..5e3ffac 100644
--- a/ios/chrome/browser/passwords/password_controller.mm
+++ b/ios/chrome/browser/passwords/password_controller.mm
@@ -20,6 +20,8 @@
 #include "base/strings/string16.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "base/values.h"
 #include "components/autofill/core/common/password_form.h"
 #include "components/autofill/core/common/password_form_fill_data.h"
@@ -39,10 +41,12 @@
 #import "ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h"
 #import "ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.h"
 #import "ios/chrome/browser/passwords/js_password_manager.h"
+#import "ios/chrome/browser/passwords/notify_auto_signin_view_controller.h"
 #import "ios/chrome/browser/passwords/password_form_filler.h"
 #import "ios/chrome/browser/passwords/password_generation_agent.h"
 #include "ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.h"
 #import "ios/chrome/browser/ui/commands/application_commands.h"
+#include "ios/chrome/browser/web/tab_id_tab_helper.h"
 #import "ios/web/public/origin_util.h"
 #include "ios/web/public/url_scheme_util.h"
 #import "ios/web/public/web_state/js/crw_js_injection_receiver.h"
@@ -63,6 +67,9 @@
 // Types of password infobars to display.
 enum class PasswordInfoBarType { SAVE, UPDATE };
 
+// Duration for notify user auto-sign in dialog being displayed.
+constexpr int kNotifyAutoSigninDuration = 3;  // seconds
+
 // Script command prefix for form changes. Possible command to be sent from
 // injected JS is 'form.buttonClicked'.
 constexpr char kCommandPrefix[] = "passwordForm";
@@ -73,6 +80,11 @@
 // This is set to YES as soon as the associated WebState is destroyed.
 @property(readonly) BOOL isWebStateDestroyed;
 
+// View controller for auto sign-in notification, owned by this
+// PasswordController.
+@property(nonatomic, strong)
+    NotifyUserAutoSigninViewController* notifyAutoSigninViewController;
+
 @end
 
 @interface PasswordController ()<FormSuggestionProvider, PasswordFormFiller>
@@ -283,12 +295,23 @@
   // Bridge to observe WebState from Objective-C.
   std::unique_ptr<web::WebStateObserverBridge> webStateObserverBridge_;
 
+  // Timer for hiding "Signing in as ..." notification.
+  base::OneShotTimer notifyAutoSigninTimer_;
+
   // True indicates that a request for credentials has been sent to the password
   // store.
   BOOL sent_request_to_store_;
+
+  // User credential waiting to be displayed in autosign-in snackbar, once tab
+  // becomes active.
+  std::unique_ptr<autofill::PasswordForm> pendingAutoSigninPasswordForm_;
 }
 
-@synthesize isWebStateDestroyed = isWebStateDestroyed_;
+@synthesize isWebStateDestroyed = _isWebStateDestroyed;
+
+@synthesize delegate = _delegate;
+
+@synthesize notifyAutoSigninViewController = _notifyAutoSigninViewController;
 
 - (instancetype)initWithWebState:(web::WebState*)webState
              passwordsUiDelegate:(id<PasswordsUiDelegate>)delegate {
@@ -424,6 +447,20 @@
 #pragma mark -
 #pragma mark CRWWebStateObserver
 
+// If Tab was shown, and there is a pending PasswordForm, display autosign-in
+// notification.
+- (void)webStateWasShown:(web::WebState*)webState {
+  if (pendingAutoSigninPasswordForm_) {
+    [self showAutosigninNotification:std::move(pendingAutoSigninPasswordForm_)];
+    pendingAutoSigninPasswordForm_.reset();
+  }
+}
+
+// If Tab was hidden, hide auto sign-in notification.
+- (void)webStateWasHidden:(web::WebState*)webState {
+  [self hideAutosigninNotification];
+}
+
 - (void)webState:(web::WebState*)webState didLoadPageWithSuccess:(BOOL)success {
   // Clear per-page state.
   formData_.reset();
@@ -471,7 +508,7 @@
 }
 
 - (void)webStateDestroyed:(web::WebState*)webState {
-  isWebStateDestroyed_ = YES;
+  _isWebStateDestroyed = YES;
   [self detach];
 }
 
@@ -724,6 +761,55 @@
                infoBarType:PasswordInfoBarType::UPDATE];
 }
 
+// Hides auto sign-in notification. Removes the view from superview and destroys
+// the controller.
+// TODO(crbug.com/435048): Animate disappearance.
+- (void)hideAutosigninNotification {
+  [self.notifyAutoSigninViewController willMoveToParentViewController:nil];
+  [self.notifyAutoSigninViewController.view removeFromSuperview];
+  [self.notifyAutoSigninViewController removeFromParentViewController];
+  self.notifyAutoSigninViewController = nil;
+}
+
+// Shows auto sign-in notification and schedules hiding it after 3 seconds.
+// TODO(crbug.com/435048): Animate appearance.
+- (void)showAutosigninNotification:
+    (std::unique_ptr<autofill::PasswordForm>)formSignedIn {
+  if (!webStateObserverBridge_ || !webStateObserverBridge_->web_state())
+    return;
+
+  // If a notification is already being displayed, hides the old one, then shows
+  // the new one.
+  if (self.notifyAutoSigninViewController) {
+    notifyAutoSigninTimer_.Stop();
+    [self hideAutosigninNotification];
+  }
+
+  // Creates view controller then shows the subview.
+  self.notifyAutoSigninViewController = [
+      [NotifyUserAutoSigninViewController alloc]
+      initWithUsername:base::SysUTF16ToNSString(formSignedIn->username_value)
+               iconURL:formSignedIn->icon_url
+         contextGetter:webState_->GetBrowserState()->GetRequestContext()];
+  TabIdTabHelper* tabIdHelper = TabIdTabHelper::FromWebState(webState_);
+  if (![_delegate displaySignInNotification:self.notifyAutoSigninViewController
+                                  fromTabId:tabIdHelper->tab_id()]) {
+    // The notification was not shown. Store the password form in
+    // |pendingAutoSigninPasswordForm_| to show the notification later.
+    pendingAutoSigninPasswordForm_ = std::move(formSignedIn);
+    self.notifyAutoSigninViewController = nil;
+    return;
+  }
+
+  // Hides notification after 3 seconds.
+  __weak PasswordController* weakSelf = self;
+  notifyAutoSigninTimer_.Start(
+      FROM_HERE, base::TimeDelta::FromSeconds(kNotifyAutoSigninDuration),
+      base::BindBlockArc(^{
+        [weakSelf hideAutosigninNotification];
+      }));
+}
+
 #pragma mark -
 #pragma mark WebPasswordFormData Adaptation
 
diff --git a/ios/chrome/browser/passwords/password_tab_helper.h b/ios/chrome/browser/passwords/password_tab_helper.h
index 9e927a5..165cb7a 100644
--- a/ios/chrome/browser/passwords/password_tab_helper.h
+++ b/ios/chrome/browser/passwords/password_tab_helper.h
@@ -13,6 +13,7 @@
 @protocol FormInputAccessoryViewProvider;
 @protocol FormSuggestionProvider;
 @class PasswordController;
+@protocol PasswordControllerDelegate;
 @protocol PasswordFormFiller;
 @protocol PasswordsUiDelegate;
 
@@ -34,6 +35,9 @@
   // Sets the PasswordController dispatcher.
   void SetDispatcher(id<ApplicationCommands> dispatcher);
 
+  // Sets the PasswordController delegate.
+  void SetPasswordControllerDelegate(id<PasswordControllerDelegate> delegate);
+
   // Returns an object that can provide suggestions from the PasswordController.
   // May return nil.
   id<FormSuggestionProvider> GetSuggestionProvider();
diff --git a/ios/chrome/browser/passwords/password_tab_helper.mm b/ios/chrome/browser/passwords/password_tab_helper.mm
index 8ff60ef5..769ced5 100644
--- a/ios/chrome/browser/passwords/password_tab_helper.mm
+++ b/ios/chrome/browser/passwords/password_tab_helper.mm
@@ -30,6 +30,11 @@
   controller_.dispatcher = dispatcher;
 }
 
+void PasswordTabHelper::SetPasswordControllerDelegate(
+    id<PasswordControllerDelegate> delegate) {
+  controller_.delegate = delegate;
+}
+
 id<FormSuggestionProvider> PasswordTabHelper::GetSuggestionProvider() {
   return controller_.suggestionProvider;
 }
diff --git a/ios/chrome/browser/payments/payment_request.h b/ios/chrome/browser/payments/payment_request.h
index d3c4d83..9b4d990 100644
--- a/ios/chrome/browser/payments/payment_request.h
+++ b/ios/chrome/browser/payments/payment_request.h
@@ -13,9 +13,9 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "components/autofill/core/browser/address_normalizer_impl.h"
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/payments/core/address_normalization_manager.h"
-#include "components/payments/core/address_normalizer_impl.h"
 #include "components/payments/core/journey_logger.h"
 #include "components/payments/core/payment_instrument.h"
 #include "components/payments/core/payment_options_provider.h"
@@ -27,13 +27,13 @@
 #include "url/gurl.h"
 
 namespace autofill {
+class AddressNormalizer;
 class AutofillProfile;
 class PersonalDataManager;
 class RegionDataLoader;
 }  // namespace autofill
 
 namespace payments {
-class AddressNormalizer;
 class AutofillPaymentInstrument;
 class CurrencyFormatter;
 class PaymentDetails;
@@ -118,7 +118,7 @@
       const autofill::CreditCard& credit_card,
       base::WeakPtr<autofill::payments::FullCardRequest::ResultDelegate>
           result_delegate) override;
-  AddressNormalizer* GetAddressNormalizer() override;
+  autofill::AddressNormalizer* GetAddressNormalizer() override;
   autofill::RegionDataLoader* GetRegionDataLoader() override;
   ukm::UkmRecorder* GetUkmRecorder() override;
   std::string GetAuthenticatedEmail() const override;
@@ -354,7 +354,7 @@
   __weak id<PaymentRequestUIDelegate> payment_request_ui_delegate_;
 
   // The address normalizer to use for the duration of the Payment Request.
-  AddressNormalizerImpl address_normalizer_;
+  autofill::AddressNormalizerImpl address_normalizer_;
 
   // Used to normalize the shipping address and the contact info.
   AddressNormalizationManager address_normalization_manager_;
diff --git a/ios/chrome/browser/payments/payment_request.mm b/ios/chrome/browser/payments/payment_request.mm
index 16f50a47..6156757 100644
--- a/ios/chrome/browser/payments/payment_request.mm
+++ b/ios/chrome/browser/payments/payment_request.mm
@@ -171,7 +171,7 @@
                                 resultDelegate:result_delegate];
 }
 
-AddressNormalizer* PaymentRequest::GetAddressNormalizer() {
+autofill::AddressNormalizer* PaymentRequest::GetAddressNormalizer() {
   return &address_normalizer_;
 }
 
diff --git a/ios/chrome/browser/payments/payment_request_util.mm b/ios/chrome/browser/payments/payment_request_util.mm
index fcb81f1..d9a8d34 100644
--- a/ios/chrome/browser/payments/payment_request_util.mm
+++ b/ios/chrome/browser/payments/payment_request_util.mm
@@ -12,6 +12,7 @@
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/phone_number_i18n.h"
 #include "components/autofill/core/browser/validation.h"
 #include "components/payments/core/payment_instrument.h"
 #include "components/payments/core/payment_request_data_util.h"
@@ -52,7 +53,7 @@
 
 NSString* GetPhoneNumberLabelFromAutofillProfile(
     const autofill::AutofillProfile& profile) {
-  base::string16 label = payments::data_util::GetFormattedPhoneNumberForDisplay(
+  base::string16 label = autofill::i18n::GetFormattedPhoneNumberForDisplay(
       profile, GetApplicationContext()->GetApplicationLocale());
   return !label.empty() ? base::SysUTF16ToNSString(label) : nil;
 }
diff --git a/ios/chrome/browser/payments/payment_response_helper.mm b/ios/chrome/browser/payments/payment_response_helper.mm
index 5d267bd..39e28b3 100644
--- a/ios/chrome/browser/payments/payment_response_helper.mm
+++ b/ios/chrome/browser/payments/payment_response_helper.mm
@@ -9,6 +9,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "components/autofill/core/browser/autofill_country.h"
 #include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/browser/phone_number_i18n.h"
 #include "components/payments/core/address_normalization_manager.h"
 #include "components/payments/core/journey_logger.h"
 #include "components/payments/core/payment_request_data_util.h"
@@ -103,8 +104,9 @@
     const std::string default_region_code =
         autofill::AutofillCountry::CountryCodeForLocale(
             payment_request_->GetApplicationLocale());
-    response.payer_phone = base::UTF8ToUTF16(data_util::FormatPhoneForResponse(
-        original_number, default_region_code));
+    response.payer_phone =
+        base::UTF8ToUTF16(autofill::i18n::FormatPhoneForResponse(
+            original_number, default_region_code));
   }
 
   [consumer_ paymentResponseHelperDidCompleteWithPaymentResponse:response];
diff --git a/ios/chrome/browser/payments/test_payment_request.h b/ios/chrome/browser/payments/test_payment_request.h
index 0d4f539..c7b4205 100644
--- a/ios/chrome/browser/payments/test_payment_request.h
+++ b/ios/chrome/browser/payments/test_payment_request.h
@@ -6,8 +6,8 @@
 #define IOS_CHROME_BROWSER_PAYMENTS_TEST_PAYMENT_REQUEST_H_
 
 #include "base/macros.h"
+#include "components/autofill/core/browser/test_address_normalizer.h"
 #include "components/payments/core/address_normalization_manager.h"
-#include "components/payments/core/test_address_normalizer.h"
 #include "ios/chrome/browser/payments/payment_request.h"
 
 namespace autofill {
@@ -101,14 +101,14 @@
   }
 
   // PaymentRequest
-  AddressNormalizer* GetAddressNormalizer() override;
+  autofill::AddressNormalizer* GetAddressNormalizer() override;
   AddressNormalizationManager* GetAddressNormalizationManager() override;
   autofill::RegionDataLoader* GetRegionDataLoader() override;
   PrefService* GetPrefService() override;
   PaymentsProfileComparator* profile_comparator() override;
 
  private:
-  TestAddressNormalizer address_normalizer_;
+  autofill::TestAddressNormalizer address_normalizer_;
   AddressNormalizationManager address_normalization_manager_;
 
   // Not owned and must outlive this object.
diff --git a/ios/chrome/browser/payments/test_payment_request.mm b/ios/chrome/browser/payments/test_payment_request.mm
index 0e22e27f..b8abc2b 100644
--- a/ios/chrome/browser/payments/test_payment_request.mm
+++ b/ios/chrome/browser/payments/test_payment_request.mm
@@ -37,7 +37,7 @@
   PaymentRequest::ParsePaymentMethodData();
 }
 
-AddressNormalizer* TestPaymentRequest::GetAddressNormalizer() {
+autofill::AddressNormalizer* TestPaymentRequest::GetAddressNormalizer() {
   return &address_normalizer_;
 }
 
diff --git a/ios/chrome/browser/prefs/browser_prefs.mm b/ios/chrome/browser/prefs/browser_prefs.mm
index 1fe3434e4..9123390 100644
--- a/ios/chrome/browser/prefs/browser_prefs.mm
+++ b/ios/chrome/browser/prefs/browser_prefs.mm
@@ -46,7 +46,6 @@
 #import "ios/chrome/browser/geolocation/omnibox_geolocation_local_state.h"
 #import "ios/chrome/browser/memory/memory_debugger_manager.h"
 #import "ios/chrome/browser/metrics/ios_chrome_metrics_service_client.h"
-#include "ios/chrome/browser/net/http_server_properties_manager_factory.h"
 #include "ios/chrome/browser/notification_promo.h"
 #include "ios/chrome/browser/physical_web/physical_web_prefs_registration.h"
 #include "ios/chrome/browser/pref_names.h"
@@ -104,7 +103,6 @@
   FirstRun::RegisterProfilePrefs(registry);
   gcm::GCMChannelStatusSyncer::RegisterProfilePrefs(registry);
   HostContentSettingsMap::RegisterProfilePrefs(registry);
-  HttpServerPropertiesManagerFactory::RegisterProfilePrefs(registry);
   language::UrlLanguageHistogram::RegisterProfilePrefs(registry);
   ntp_snippets::ClickBasedCategoryRanker::RegisterProfilePrefs(registry);
   ntp_snippets::ContentSuggestionsService::RegisterProfilePrefs(registry);
diff --git a/ios/chrome/browser/tabs/tab.mm b/ios/chrome/browser/tabs/tab.mm
index 83ee6eb..5de9aca8a 100644
--- a/ios/chrome/browser/tabs/tab.mm
+++ b/ios/chrome/browser/tabs/tab.mm
@@ -470,8 +470,8 @@
 
   _isPrerenderTab = isPrerender;
 
-  self.webController.shouldSuppressDialogs =
-      (isPrerender && !isLinkLoadingPrerenderTab_);
+  self.webState->SetShouldSuppressDialogs(isPrerender &&
+                                          !isLinkLoadingPrerenderTab_);
 
   if (_isPrerenderTab)
     return;
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn
index aef7f3da..d2a4252f 100644
--- a/ios/chrome/browser/ui/BUILD.gn
+++ b/ios/chrome/browser/ui/BUILD.gn
@@ -327,6 +327,7 @@
     "//ios/chrome/browser/ui/reading_list",
     "//ios/chrome/browser/ui/sad_tab:coordinator",
     "//ios/chrome/browser/ui/settings/sync_utils",
+    "//ios/chrome/browser/ui/snackbar",
     "//ios/chrome/browser/ui/stack_view",
     "//ios/chrome/browser/ui/static_content",
     "//ios/chrome/browser/ui/tab_switcher",
diff --git a/ios/chrome/browser/ui/activity_services/BUILD.gn b/ios/chrome/browser/ui/activity_services/BUILD.gn
index 3891b31..bec9812 100644
--- a/ios/chrome/browser/ui/activity_services/BUILD.gn
+++ b/ios/chrome/browser/ui/activity_services/BUILD.gn
@@ -82,6 +82,7 @@
     "//ios/chrome/browser/passwords",
     "//ios/chrome/browser/tabs",
     "//ios/chrome/browser/ui/activity_services/requirements",
+    "//ios/chrome/browser/ui/commands",
     "//ios/testing:ocmock_support",
     "//ios/web",
     "//ios/web/public/test",
diff --git a/ios/chrome/browser/ui/activity_services/activity_service_controller.mm b/ios/chrome/browser/ui/activity_services/activity_service_controller.mm
index d6f8660..18423911 100644
--- a/ios/chrome/browser/ui/activity_services/activity_service_controller.mm
+++ b/ios/chrome/browser/ui/activity_services/activity_service_controller.mm
@@ -17,9 +17,9 @@
 #import "ios/chrome/browser/ui/activity_services/requirements/activity_service_password.h"
 #import "ios/chrome/browser/ui/activity_services/requirements/activity_service_positioner.h"
 #import "ios/chrome/browser/ui/activity_services/requirements/activity_service_presentation.h"
-#import "ios/chrome/browser/ui/activity_services/requirements/activity_service_snackbar.h"
 #import "ios/chrome/browser/ui/activity_services/share_protocol.h"
 #import "ios/chrome/browser/ui/activity_services/share_to_data.h"
+#import "ios/chrome/browser/ui/commands/snackbar_commands.h"
 #include "ios/chrome/browser/ui/ui_util.h"
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
 #include "ios/chrome/grit/ios_strings.h"
@@ -33,8 +33,8 @@
   BOOL active_;
   __weak id<ActivityServicePassword> passwordProvider_;
   __weak id<ActivityServicePresentation> presentationProvider_;
-  __weak id<ActivityServiceSnackbar> snackbarProvider_;
   UIActivityViewController* activityViewController_;
+  __weak id<SnackbarCommands> dispatcher_;
 }
 
 // Resets the controller's user interface and delegate.
@@ -100,11 +100,10 @@
 
 - (void)shareWithData:(ShareToData*)data
             browserState:(ios::ChromeBrowserState*)browserState
-              dispatcher:(id<BrowserCommands>)dispatcher
+              dispatcher:(id<BrowserCommands, SnackbarCommands>)dispatcher
         passwordProvider:(id<ActivityServicePassword>)passwordProvider
         positionProvider:(id<ActivityServicePositioner>)positionProvider
-    presentationProvider:(id<ActivityServicePresentation>)presentationProvider
-        snackbarProvider:(id<ActivityServiceSnackbar>)snackbarProvider {
+    presentationProvider:(id<ActivityServicePresentation>)presentationProvider {
   DCHECK(data);
   DCHECK(!active_);
 
@@ -121,10 +120,10 @@
 
   DCHECK(!passwordProvider_);
   DCHECK(!presentationProvider_);
-  DCHECK(!snackbarProvider_);
   passwordProvider_ = passwordProvider;
   presentationProvider_ = presentationProvider;
-  snackbarProvider_ = snackbarProvider;
+
+  dispatcher_ = dispatcher;
 
   DCHECK(!activityViewController_);
   activityViewController_ = [[UIActivityViewController alloc]
@@ -164,7 +163,6 @@
 - (void)resetUserInterface {
   passwordProvider_ = nil;
   presentationProvider_ = nil;
-  snackbarProvider_ = nil;
   activityViewController_ = nil;
   active_ = NO;
 }
@@ -176,7 +174,6 @@
   DCHECK(active_);
   DCHECK(passwordProvider_);
   DCHECK(presentationProvider_);
-  DCHECK(snackbarProvider_);
 
   BOOL shouldResetUI = YES;
   if (activityType) {
@@ -322,9 +319,6 @@
              completionMessage:(NSString*)message {
   switch (shareStatus) {
     case ShareTo::SHARE_SUCCESS: {
-      // Captures this provider for use in the asynchronously executed
-      // completion block.
-      __weak id<ActivityServiceSnackbar> snackbarProvider = snackbarProvider_;
       // Flag to limit user feedback after form filled to just once.
       __block BOOL shown = NO;
       id<PasswordFormFiller> passwordFormFiller =
@@ -336,7 +330,8 @@
                                      return;
                                    TriggerHapticFeedbackForNotification(
                                        UINotificationFeedbackTypeSuccess);
-                                   [snackbarProvider showSnackbar:message];
+                                   [dispatcher_
+                                       showSnackbarWithMessage:message];
                                    shown = YES;
                                  }];
       break;
@@ -357,7 +352,7 @@
     case ShareTo::SHARE_SUCCESS:
       if ([message length]) {
         TriggerHapticFeedbackForNotification(UINotificationFeedbackTypeSuccess);
-        [snackbarProvider_ showSnackbar:message];
+        [dispatcher_ showSnackbarWithMessage:message];
       }
       break;
     case ShareTo::SHARE_ERROR:
@@ -386,12 +381,12 @@
 
 #pragma mark - For Testing
 
-- (void)setProvidersForTesting:(id<ActivityServicePassword,
-                                   ActivityServicePresentation,
-                                   ActivityServiceSnackbar>)provider {
+- (void)setProvidersForTesting:
+            (id<ActivityServicePassword, ActivityServicePresentation>)provider
+                    dispatcher:(id<SnackbarCommands>)dispatcher {
   passwordProvider_ = provider;
   presentationProvider_ = provider;
-  snackbarProvider_ = provider;
+  dispatcher_ = dispatcher;
 }
 
 @end
diff --git a/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm b/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm
index 113f10566..54ab5fa 100644
--- a/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm
+++ b/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm
@@ -96,9 +96,8 @@
                                           @"This page cannot be printed.")]
       assertWithMatcher:grey_interactable()];
 
-  // Dismiss the snackbar.
-  [MDCSnackbarManager dismissAndCallCompletionBlocksWithCategory:
-                          kBrowserViewControllerSnackbarCategory];
+  // Dismiss the snackbar (nil dismisses all snackbar messages).
+  [MDCSnackbarManager dismissAndCallCompletionBlocksWithCategory:nil];
 }
 
 - (void)testActivityServiceControllerCantPrintUnprintablePages {
diff --git a/ios/chrome/browser/ui/activity_services/activity_service_controller_unittest.mm b/ios/chrome/browser/ui/activity_services/activity_service_controller_unittest.mm
index 7be8fd0..4e5d5aa 100644
--- a/ios/chrome/browser/ui/activity_services/activity_service_controller_unittest.mm
+++ b/ios/chrome/browser/ui/activity_services/activity_service_controller_unittest.mm
@@ -15,8 +15,8 @@
 #import "ios/chrome/browser/ui/activity_services/requirements/activity_service_password.h"
 #import "ios/chrome/browser/ui/activity_services/requirements/activity_service_positioner.h"
 #import "ios/chrome/browser/ui/activity_services/requirements/activity_service_presentation.h"
-#import "ios/chrome/browser/ui/activity_services/requirements/activity_service_snackbar.h"
 #import "ios/chrome/browser/ui/activity_services/share_to_data.h"
+#import "ios/chrome/browser/ui/commands/snackbar_commands.h"
 #include "ios/chrome/grit/ios_strings.h"
 #include "ios/web/public/test/test_web_thread_bundle.h"
 #include "testing/gtest_mac.h"
@@ -73,16 +73,16 @@
        completionMessage:(NSString*)message;
 
 // Setter function for mocking during testing
-- (void)setProvidersForTesting:(id<ActivityServicePassword,
-                                   ActivityServicePresentation,
-                                   ActivityServiceSnackbar>)provider;
+- (void)setProvidersForTesting:
+            (id<ActivityServicePassword, ActivityServicePresentation>)provider
+                    dispatcher:(id<SnackbarCommands>)dispatcher;
 @end
 
 @interface FakeActivityServiceControllerTestProvider
     : NSObject<ActivityServicePassword,
                ActivityServicePositioner,
                ActivityServicePresentation,
-               ActivityServiceSnackbar>
+               SnackbarCommands>
 
 @property(nonatomic, readonly, strong) UIViewController* parentViewController;
 @property(nonatomic, readonly, strong)
@@ -159,7 +159,7 @@
   return self.parentViewController.view;
 }
 
-- (void)showSnackbar:(NSString*)message {
+- (void)showSnackbarWithMessage:(NSString*)message {
   _latestSnackbarMessage = [message copy];
 }
 
@@ -272,7 +272,7 @@
     FakeActivityServiceControllerTestProvider* provider =
         [[FakeActivityServiceControllerTestProvider alloc]
             initWithParentViewController:nil];
-    [activityController setProvidersForTesting:provider];
+    [activityController setProvidersForTesting:provider dispatcher:provider];
 
     // The following call to |processItemsReturnedFromActivity| should not
     // trigger any calls to the PasswordFormFiller.
@@ -314,8 +314,7 @@
                          dispatcher:nil
                    passwordProvider:provider
                    positionProvider:provider
-               presentationProvider:provider
-                   snackbarProvider:provider];
+               presentationProvider:provider];
   EXPECT_TRUE(provider.presentActivityServiceViewControllerWasCalled);
   EXPECT_FALSE(provider.activityServiceDidEndPresentingWasCalled);
   EXPECT_TRUE([activityController isActive]);
@@ -448,7 +447,7 @@
       [[FakeActivityServiceControllerTestProvider alloc]
           initWithParentViewController:nil];
   ASSERT_TRUE([provider currentPasswordFormFiller]);
-  [activityController setProvidersForTesting:provider];
+  [activityController setProvidersForTesting:provider dispatcher:nil];
 
   EXPECT_TRUE(provider.fakePasswordFormFiller);
   EXPECT_FALSE(provider.fakePasswordFormFiller.methodCalled);
@@ -580,7 +579,7 @@
   FakeActivityServiceControllerTestProvider* provider =
       [[FakeActivityServiceControllerTestProvider alloc]
           initWithParentViewController:nil];
-  [controller setProvidersForTesting:provider];
+  [controller setProvidersForTesting:provider dispatcher:provider];
 
   NSString* completion_message = @"Completion!";
   [controller shareDidComplete:ShareTo::SHARE_SUCCESS
@@ -598,7 +597,7 @@
   FakeActivityServiceControllerTestProvider* provider =
       [[FakeActivityServiceControllerTestProvider alloc]
           initWithParentViewController:nil];
-  [controller setProvidersForTesting:provider];
+  [controller setProvidersForTesting:provider dispatcher:provider];
 
   [controller shareDidComplete:ShareTo::SHARE_CANCEL
              completionMessage:@"dummy"];
@@ -616,7 +615,7 @@
   FakeActivityServiceControllerTestProvider* provider =
       [[FakeActivityServiceControllerTestProvider alloc]
           initWithParentViewController:nil];
-  [controller setProvidersForTesting:provider];
+  [controller setProvidersForTesting:provider dispatcher:provider];
 
   [controller shareDidComplete:ShareTo::SHARE_ERROR completionMessage:@"dummy"];
 
diff --git a/ios/chrome/browser/ui/activity_services/activity_service_legacy_coordinator.h b/ios/chrome/browser/ui/activity_services/activity_service_legacy_coordinator.h
index accfe5e..dbf8540 100644
--- a/ios/chrome/browser/ui/activity_services/activity_service_legacy_coordinator.h
+++ b/ios/chrome/browser/ui/activity_services/activity_service_legacy_coordinator.h
@@ -9,7 +9,6 @@
 
 @protocol ActivityServicePositioner;
 @protocol ActivityServicePresentation;
-@protocol ActivityServiceSnackbar;
 @class CommandDispatcher;
 @class TabModel;
 
@@ -31,8 +30,6 @@
     positionProvider;
 @property(nonatomic, readwrite, weak) id<ActivityServicePresentation>
     presentationProvider;
-@property(nonatomic, readwrite, weak) id<ActivityServiceSnackbar>
-    snackbarProvider;
 
 // Removes references to any weak objects that this coordinator holds pointers
 // to.
diff --git a/ios/chrome/browser/ui/activity_services/activity_service_legacy_coordinator.mm b/ios/chrome/browser/ui/activity_services/activity_service_legacy_coordinator.mm
index afe6ed7..f1bcdc7 100644
--- a/ios/chrome/browser/ui/activity_services/activity_service_legacy_coordinator.mm
+++ b/ios/chrome/browser/ui/activity_services/activity_service_legacy_coordinator.mm
@@ -12,7 +12,6 @@
 #import "ios/chrome/browser/ui/activity_services/requirements/activity_service_password.h"
 #import "ios/chrome/browser/ui/activity_services/requirements/activity_service_positioner.h"
 #import "ios/chrome/browser/ui/activity_services/requirements/activity_service_presentation.h"
-#import "ios/chrome/browser/ui/activity_services/requirements/activity_service_snackbar.h"
 #import "ios/chrome/browser/ui/activity_services/share_protocol.h"
 #import "ios/chrome/browser/ui/activity_services/share_to_data.h"
 #import "ios/chrome/browser/ui/activity_services/share_to_data_builder.h"
@@ -34,7 +33,6 @@
 
 @synthesize positionProvider = _positionProvider;
 @synthesize presentationProvider = _presentationProvider;
-@synthesize snackbarProvider = _snackbarProvider;
 
 #pragma mark - Public methods
 
@@ -77,11 +75,11 @@
 
   [controller shareWithData:data
                browserState:self.browserState
-                 dispatcher:static_cast<id<BrowserCommands>>(self.dispatcher)
+                 dispatcher:static_cast<id<BrowserCommands, SnackbarCommands>>(
+                                self.dispatcher)
            passwordProvider:self
            positionProvider:self.positionProvider
-       presentationProvider:self.presentationProvider
-           snackbarProvider:self.snackbarProvider];
+       presentationProvider:self.presentationProvider];
 }
 
 #pragma mark - Providers
diff --git a/ios/chrome/browser/ui/activity_services/requirements/BUILD.gn b/ios/chrome/browser/ui/activity_services/requirements/BUILD.gn
index 2307fdc..f6079ea 100644
--- a/ios/chrome/browser/ui/activity_services/requirements/BUILD.gn
+++ b/ios/chrome/browser/ui/activity_services/requirements/BUILD.gn
@@ -7,6 +7,5 @@
     "activity_service_password.h",
     "activity_service_positioner.h",
     "activity_service_presentation.h",
-    "activity_service_snackbar.h",
   ]
 }
diff --git a/ios/chrome/browser/ui/activity_services/requirements/activity_service_snackbar.h b/ios/chrome/browser/ui/activity_services/requirements/activity_service_snackbar.h
deleted file mode 100644
index 1b42936..0000000
--- a/ios/chrome/browser/ui/activity_services/requirements/activity_service_snackbar.h
+++ /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.
-
-#ifndef IOS_CHROME_BROWSER_UI_ACTIVITY_SERVICES_REQUIREMENTS_ACTIVITY_SERVICE_SNACKBAR_H_
-#define IOS_CHROME_BROWSER_UI_ACTIVITY_SERVICES_REQUIREMENTS_ACTIVITY_SERVICE_SNACKBAR_H_
-
-// ActivityServiceSnackback contains methods for showing MDC snackbars.
-@protocol ActivityServiceSnackbar
-
-// Asks the implementor to show a snackbar with the given |message|.
-- (void)showSnackbar:(NSString*)message;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_ACTIVITY_SERVICES_REQUIREMENTS_ACTIVITY_SERVICE_SNACKBAR_H_
diff --git a/ios/chrome/browser/ui/activity_services/share_protocol.h b/ios/chrome/browser/ui/activity_services/share_protocol.h
index 59113196..6073daf 100644
--- a/ios/chrome/browser/ui/activity_services/share_protocol.h
+++ b/ios/chrome/browser/ui/activity_services/share_protocol.h
@@ -11,9 +11,9 @@
 @protocol ActivityServicePassword;
 @protocol ActivityServicePositioner;
 @protocol ActivityServicePresentation;
-@protocol ActivityServiceSnackbar;
 @protocol BrowserCommands;
 @class ShareToData;
+@protocol SnackbarCommands;
 
 namespace ios {
 class ChromeBrowserState;
@@ -51,11 +51,10 @@
 // |positionProvider| must return a non-nil view and a non-zero size.
 - (void)shareWithData:(ShareToData*)data
             browserState:(ios::ChromeBrowserState*)browserState
-              dispatcher:(id<BrowserCommands>)dispatcher
+              dispatcher:(id<BrowserCommands, SnackbarCommands>)dispatcher
         passwordProvider:(id<ActivityServicePassword>)passwordProvider
         positionProvider:(id<ActivityServicePositioner>)positionProvider
-    presentationProvider:(id<ActivityServicePresentation>)presentationProvider
-        snackbarProvider:(id<ActivityServiceSnackbar>)snackbarProvider;
+    presentationProvider:(id<ActivityServicePresentation>)presentationProvider;
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_ACTIVITY_SERVICES_SHARE_PROTOCOL_H_
diff --git a/ios/chrome/browser/ui/browser_view_controller.h b/ios/chrome/browser/ui/browser_view_controller.h
index b25de169..aa7284f 100644
--- a/ios/chrome/browser/ui/browser_view_controller.h
+++ b/ios/chrome/browser/ui/browser_view_controller.h
@@ -21,6 +21,7 @@
 @class BrowserContainerView;
 @class BrowserViewControllerDependencyFactory;
 class GURL;
+@protocol SnackbarCommands;
 @class Tab;
 @class TabModel;
 @protocol TabStripFoldAnimation;
@@ -61,6 +62,7 @@
 @property(nonatomic, readonly) id<ApplicationCommands,
                                   BrowserCommands,
                                   OmniboxFocuser,
+                                  SnackbarCommands,
                                   UrlLoader,
                                   WebToolbarDelegate>
     dispatcher;
@@ -140,8 +142,10 @@
 // Focuses the omnibox.
 - (void)focusOmnibox;
 
-// Dismisses all presented views then calls |completion|.
-- (void)clearPresentedStateWithCompletion:(ProceduralBlock)completion;
+// Dismisses all presented views, excluding the omnibox if |dismissOmnibox| is
+// NO, then calls |completion|.
+- (void)clearPresentedStateWithCompletion:(ProceduralBlock)completion
+                           dismissOmnibox:(BOOL)dismissOmnibox;
 
 // Returns a tab strip placeholder view created from the current state of the
 // tab strip. It is used to animate the transition from the browser view
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index 4f91041..5174bb67 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -76,6 +76,7 @@
 #include "ios/chrome/browser/metrics/tab_usage_recorder.h"
 #import "ios/chrome/browser/open_url_util.h"
 #import "ios/chrome/browser/passwords/password_controller.h"
+#include "ios/chrome/browser/passwords/password_tab_helper.h"
 #include "ios/chrome/browser/pref_names.h"
 #import "ios/chrome/browser/prerender/preload_controller_delegate.h"
 #import "ios/chrome/browser/prerender/prerender_service.h"
@@ -102,7 +103,6 @@
 #import "ios/chrome/browser/tabs/tab_snapshotting_delegate.h"
 #import "ios/chrome/browser/ui/activity_services/activity_service_legacy_coordinator.h"
 #import "ios/chrome/browser/ui/activity_services/requirements/activity_service_presentation.h"
-#import "ios/chrome/browser/ui/activity_services/requirements/activity_service_snackbar.h"
 #import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h"
 #import "ios/chrome/browser/ui/alert_coordinator/repost_form_coordinator.h"
 #import "ios/chrome/browser/ui/authentication/re_signin_infobar_delegate.h"
@@ -119,6 +119,7 @@
 #import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
 #import "ios/chrome/browser/ui/commands/open_url_command.h"
 #import "ios/chrome/browser/ui/commands/reading_list_add_command.h"
+#import "ios/chrome/browser/ui/commands/snackbar_commands.h"
 #import "ios/chrome/browser/ui/commands/start_voice_search_command.h"
 #import "ios/chrome/browser/ui/content_suggestions/ntp_home_constant.h"
 #import "ios/chrome/browser/ui/context_menu/context_menu_coordinator.h"
@@ -151,6 +152,7 @@
 #import "ios/chrome/browser/ui/sad_tab/sad_tab_legacy_coordinator.h"
 #import "ios/chrome/browser/ui/settings/sync_utils/sync_util.h"
 #import "ios/chrome/browser/ui/side_swipe/side_swipe_controller.h"
+#import "ios/chrome/browser/ui/snackbar/snackbar_coordinator.h"
 #import "ios/chrome/browser/ui/stack_view/card_view.h"
 #import "ios/chrome/browser/ui/stack_view/page_animation_util.h"
 #import "ios/chrome/browser/ui/static_content/static_html_native_content.h"
@@ -357,7 +359,6 @@
 #pragma mark - BVC
 
 @interface BrowserViewController ()<ActivityServicePresentation,
-                                    ActivityServiceSnackbar,
                                     AppRatingPromptDelegate,
                                     CRWNativeContentProvider,
                                     CRWWebStateDelegate,
@@ -372,6 +373,7 @@
                                     OverscrollActionsControllerDelegate,
                                     PageInfoPresentation,
                                     PassKitDialogProvider,
+                                    PasswordControllerDelegate,
                                     PreloadControllerDelegate,
                                     QRScannerPresenting,
                                     RepostFormTabHelperDelegate,
@@ -549,6 +551,9 @@
   // Coordinator for displaying Repost Form dialog.
   RepostFormCoordinator* _repostFormCoordinator;
 
+  // Coordinator for displaying snackbars.
+  SnackbarCoordinator* _snackbarCoordinator;
+
   // Fake status bar view used to blend the toolbar into the status bar.
   UIView* _fakeStatusBarView;
 }
@@ -757,8 +762,6 @@
 - (void)tabLoadComplete:(Tab*)tab withSuccess:(BOOL)success;
 // Evaluates Javascript asynchronously using the current page context.
 - (void)openJavascript:(NSString*)javascript;
-// Shows a self-dismissing snackbar displaying |message|.
-- (void)showSnackbar:(NSString*)message;
 // Induces an intentional crash in the browser process.
 - (void)induceBrowserCrash;
 // Saves the image or display error message, based on privacy settings.
@@ -1005,6 +1008,10 @@
         startDispatchingToTarget:applicationCommandEndpoint
                      forProtocol:@protocol(ApplicationSettingsCommands)];
 
+    _snackbarCoordinator = [[SnackbarCoordinator alloc] init];
+    _snackbarCoordinator.dispatcher = _dispatcher;
+    [_snackbarCoordinator start];
+
     _javaScriptDialogPresenter.reset(
         new JavaScriptDialogPresenterImpl(_dialogPresenter));
     _webStateDelegate.reset(new web::WebStateDelegateBridge(self));
@@ -1049,10 +1056,12 @@
 - (id<ApplicationCommands,
       BrowserCommands,
       OmniboxFocuser,
+      SnackbarCommands,
       UrlLoader,
       WebToolbarDelegate>)dispatcher {
   return static_cast<id<ApplicationCommands, BrowserCommands, OmniboxFocuser,
-                        UrlLoader, WebToolbarDelegate>>(_dispatcher);
+                        SnackbarCommands, UrlLoader, WebToolbarDelegate>>(
+      _dispatcher);
 }
 
 - (void)setActive:(BOOL)active {
@@ -1887,7 +1896,6 @@
   _activityServiceCoordinator.browserState = _browserState;
   _activityServiceCoordinator.positionProvider = _toolbarController;
   _activityServiceCoordinator.presentationProvider = self;
-  _activityServiceCoordinator.snackbarProvider = self;
 
   _qrScannerCoordinator =
       [[QRScannerLegacyCoordinator alloc] initWithBaseViewController:self];
@@ -2387,6 +2395,11 @@
   PrintTabHelper::CreateForWebState(tab.webState, self);
   RepostFormTabHelper::CreateForWebState(tab.webState, self);
   NetExportTabHelper::CreateForWebState(tab.webState, self);
+  PasswordTabHelper* passwordTabHelper =
+      PasswordTabHelper::FromWebState(tab.webState);
+  if (passwordTabHelper) {
+    passwordTabHelper->SetPasswordControllerDelegate(self);
+  }
 }
 
 - (void)uninstallDelegatesForTab:(Tab*)tab {
@@ -2644,6 +2657,21 @@
                                             : UIStatusBarStyleDefault;
 }
 
+#pragma mark - PasswordControllerDelegate methods
+
+- (BOOL)displaySignInNotification:(UIViewController*)viewController
+                        fromTabId:(NSString*)tabId {
+  // Check if the call comes from currently visible tab.
+  if ([tabId isEqual:[_model currentTab].tabId]) {
+    [self addChildViewController:viewController];
+    [self.view addSubview:viewController.view];
+    [viewController didMoveToParentViewController:self];
+    return YES;
+  } else {
+    return NO;
+  }
+}
+
 #pragma mark - CRWWebStateDelegate methods.
 
 - (web::WebState*)webState:(web::WebState*)webState
@@ -3267,6 +3295,13 @@
   std::string url_host = url.host();
   if (url_host == kChromeUINewTabHost ||
       (IsIPadIdiom() && url_host == kChromeUIBookmarksHost)) {
+    CGFloat fakeStatusBarHeight = _fakeStatusBarView.frame.size.height;
+    UIEdgeInsets safeAreaInset = UIEdgeInsetsZero;
+    if (@available(iOS 11.0, *)) {
+      safeAreaInset = self.view.safeAreaInsets;
+    }
+    safeAreaInset.top = MAX(safeAreaInset.top - fakeStatusBarHeight, 0);
+
     NewTabPageController* pageController =
         [[NewTabPageController alloc] initWithUrl:url
                                            loader:self
@@ -3277,7 +3312,8 @@
                                   toolbarDelegate:self
                                          tabModel:_model
                              parentViewController:self
-                                       dispatcher:self.dispatcher];
+                                       dispatcher:self.dispatcher
+                                    safeAreaInset:safeAreaInset];
     pageController.swipeRecognizerProvider = self.sideSwipeController;
 
     // Panel is always NTP for iPhone.
@@ -3637,8 +3673,9 @@
                          reading_list::ADDED_VIA_CURRENT_APP);
 
   TriggerHapticFeedbackForNotification(UINotificationFeedbackTypeSuccess);
-  [self showSnackbar:l10n_util::GetNSString(
-                         IDS_IOS_READING_LIST_SNACKBAR_MESSAGE)];
+  [self.dispatcher
+      showSnackbarWithMessage:l10n_util::GetNSString(
+                                  IDS_IOS_READING_LIST_SNACKBAR_MESSAGE)];
 }
 
 #pragma mark - Keyboard commands management
@@ -4172,7 +4209,9 @@
   // the UI.
   if (![currentTab viewForPrinting]) {
     TriggerHapticFeedbackForNotification(UINotificationFeedbackTypeError);
-    [self showSnackbar:l10n_util::GetNSString(IDS_IOS_CANNOT_PRINT_PAGE_ERROR)];
+    [self.dispatcher
+        showSnackbarWithMessage:l10n_util::GetNSString(
+                                    IDS_IOS_CANNOT_PRINT_PAGE_ERROR)];
     return;
   }
   DCHECK(_browserState);
@@ -4257,7 +4296,7 @@
                             @"535886823&pt=9008&ct=rating")];
 
   base::RecordAction(base::UserMetricsAction("IOSRateThisAppDialogShown"));
-  [self clearPresentedStateWithCompletion:nil];
+  [self clearPresentedStateWithCompletion:nil dismissOmnibox:YES];
 
   _rateThisAppDialog = ios::GetChromeBrowserProvider()->CreateAppRatingPrompt();
   [_rateThisAppDialog setAppStoreURL:storeURL];
@@ -4397,11 +4436,14 @@
   }
 }
 
-- (void)clearPresentedStateWithCompletion:(ProceduralBlock)completion {
+- (void)clearPresentedStateWithCompletion:(ProceduralBlock)completion
+                           dismissOmnibox:(BOOL)dismissOmnibox {
   [_activityServiceCoordinator cancelShare];
   [_bookmarkInteractionController dismissBookmarkModalControllerAnimated:NO];
   [_bookmarkInteractionController dismissSnackbar];
-  [_toolbarController cancelOmniboxEdit];
+  if (dismissOmnibox) {
+    [_toolbarController cancelOmniboxEdit];
+  }
   [_dialogPresenter cancelAllDialogs];
   [self.dispatcher hidePageInfo];
   [self.tabTipBubblePresenter dismissAnimated:NO];
@@ -4898,10 +4940,6 @@
   [_alertCoordinator start];
 }
 
-- (void)showSnackbar:(NSString*)message {
-  [_dependencyFactory showSnackbarWithMessage:message];
-}
-
 #pragma mark - Show Mail Composer methods
 
 - (void)netExportTabHelper:(NetExportTabHelper*)tabHelper
diff --git a/ios/chrome/browser/ui/browser_view_controller_dependency_factory.h b/ios/chrome/browser/ui/browser_view_controller_dependency_factory.h
index b96841d..fc6c9a46 100644
--- a/ios/chrome/browser/ui/browser_view_controller_dependency_factory.h
+++ b/ios/chrome/browser/ui/browser_view_controller_dependency_factory.h
@@ -29,10 +29,6 @@
 class ChromeBrowserState;
 }
 
-// The category for all messages presented by the
-// BrowserViewControllerDependencyFactory via |showSnackbarWithMessage:|.
-extern NSString* const kBrowserViewControllerSnackbarCategory;
-
 // Creates helper objects needed by BrowserViewController.
 @interface BrowserViewControllerDependencyFactory : NSObject
 
@@ -60,8 +56,6 @@
 // Returns a new keyboard commands coordinator to handle keyboard commands.
 - (KeyCommandsProvider*)newKeyCommandsProvider;
 
-- (void)showSnackbarWithMessage:(NSString*)message;
-
 - (AlertCoordinator*)alertCoordinatorWithTitle:(NSString*)title
                                        message:(NSString*)message
                                 viewController:
diff --git a/ios/chrome/browser/ui/browser_view_controller_dependency_factory.mm b/ios/chrome/browser/ui/browser_view_controller_dependency_factory.mm
index 87436d2..08f8df7 100644
--- a/ios/chrome/browser/ui/browser_view_controller_dependency_factory.mm
+++ b/ios/chrome/browser/ui/browser_view_controller_dependency_factory.mm
@@ -19,7 +19,6 @@
 #include "ios/chrome/browser/ui/toolbar/toolbar_model_impl_ios.h"
 #import "ios/chrome/browser/ui/toolbar/web_toolbar_controller.h"
 #include "ios/chrome/grit/ios_strings.h"
-#import "ios/third_party/material_components_ios/src/components/Snackbar/src/MaterialSnackbar.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 
@@ -27,9 +26,6 @@
 #error "This file requires ARC support."
 #endif
 
-NSString* const kBrowserViewControllerSnackbarCategory =
-    @"BrowserViewControllerSnackbarCategory";
-
 @implementation BrowserViewControllerDependencyFactory {
   ios::ChromeBrowserState* browserState_;
 }
@@ -75,14 +71,6 @@
   return [[KeyCommandsProvider alloc] init];
 }
 
-- (void)showSnackbarWithMessage:(NSString*)text {
-  MDCSnackbarMessage* message = [MDCSnackbarMessage messageWithText:text];
-  message.accessibilityLabel = text;
-  message.duration = 2.0;
-  message.category = kBrowserViewControllerSnackbarCategory;
-  [MDCSnackbarManager showMessage:message];
-}
-
 - (AlertCoordinator*)alertCoordinatorWithTitle:(NSString*)title
                                        message:(NSString*)message
                                 viewController:
diff --git a/ios/chrome/browser/ui/browser_view_controller_unittest.mm b/ios/chrome/browser/ui/browser_view_controller_unittest.mm
index 9f61ec07..c1fb9ee 100644
--- a/ios/chrome/browser/ui/browser_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/browser_view_controller_unittest.mm
@@ -458,7 +458,8 @@
   EXPECT_CALL(*this, OnCompletionCalled());
   [bvc_ clearPresentedStateWithCompletion:^{
     this->OnCompletionCalled();
-  }];
+  }
+                           dismissOmnibox:YES];
 }
 
 // Tests for the browser view controller when Payment Request is enabled.
diff --git a/ios/chrome/browser/ui/chrome_web_view_factory.mm b/ios/chrome/browser/ui/chrome_web_view_factory.mm
index cbd7be9..c80e1c9 100644
--- a/ios/chrome/browser/ui/chrome_web_view_factory.mm
+++ b/ios/chrome/browser/ui/chrome_web_view_factory.mm
@@ -160,7 +160,7 @@
     DCHECK(g_external_browser_state);
     g_request_tracker = web::RequestTrackerImpl::CreateTrackerForRequestGroupID(
         ChromeWebView::kExternalRequestGroupID, g_external_browser_state,
-        [self requestContextForExternalService:externalService], nil);
+        [self requestContextForExternalService:externalService]);
   }
   return [[UIWebView alloc] initWithFrame:CGRectZero];
 }
diff --git a/ios/chrome/browser/ui/commands/BUILD.gn b/ios/chrome/browser/ui/commands/BUILD.gn
index a2c08b7..da0c01b 100644
--- a/ios/chrome/browser/ui/commands/BUILD.gn
+++ b/ios/chrome/browser/ui/commands/BUILD.gn
@@ -28,6 +28,7 @@
     "reading_list_add_command.mm",
     "show_signin_command.h",
     "show_signin_command.mm",
+    "snackbar_commands.h",
     "start_voice_search_command.h",
     "start_voice_search_command.mm",
   ]
diff --git a/ios/chrome/browser/ui/commands/snackbar_commands.h b/ios/chrome/browser/ui/commands/snackbar_commands.h
new file mode 100644
index 0000000..8d8ff79
--- /dev/null
+++ b/ios/chrome/browser/ui/commands/snackbar_commands.h
@@ -0,0 +1,18 @@
+// 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 IOS_CHROME_BROWSER_UI_COMMANDS_SNACKBAR_COMMANDS_H_
+#define IOS_CHROME_BROWSER_UI_COMMANDS_SNACKBAR_COMMANDS_H_
+
+#import <Foundation/Foundation.h>
+
+// Commands related to Snackbar.
+@protocol SnackbarCommands
+// Shows a snackbar with |message|. This method uses a default category. Only
+// the last message of the default category will be shown. Any currently showing
+// or pending message of the default category will be dismissed.
+- (void)showSnackbarWithMessage:(NSString*)message;
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_COMMANDS_SNACKBAR_COMMANDS_H_
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.h b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.h
index 1ebca56..e2e3d67 100644
--- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.h
+++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.h
@@ -6,6 +6,7 @@
 #define IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CELLS_CONTENT_SUGGESTIONS_MOST_VISITED_ITEM_H_
 
 #include "components/ntp_tiles/tile_source.h"
+#include "components/ntp_tiles/tile_title_source.h"
 #include "components/ntp_tiles/tile_visual_type.h"
 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h"
 #import "ios/chrome/browser/ui/content_suggestions/cells/suggested_content.h"
@@ -23,6 +24,8 @@
 
 // URL of the Most Visited.
 @property(nonatomic, assign) GURL URL;
+// Source of the Most Visited tile's name.
+@property(nonatomic, assign) ntp_tiles::TileTitleSource titleSource;
 // Source of the Most Visited tile.
 @property(nonatomic, assign) ntp_tiles::TileSource source;
 // Attributes for favicon.
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.mm b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.mm
index b644250..8f570cf 100644
--- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.mm
+++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.mm
@@ -23,6 +23,7 @@
 @synthesize attributes = _attributes;
 @synthesize title = _title;
 @synthesize URL = _URL;
+@synthesize titleSource = _titleSource;
 @synthesize source = _source;
 @synthesize commandHandler = _commandHandler;
 @synthesize metricsRecorded = _metricsRecorded;
diff --git a/ios/chrome/browser/ui/infobars/infobar_view.mm b/ios/chrome/browser/ui/infobars/infobar_view.mm
index 7d8cf21b..d42b847 100644
--- a/ios/chrome/browser/ui/infobars/infobar_view.mm
+++ b/ios/chrome/browser/ui/infobars/infobar_view.mm
@@ -51,6 +51,7 @@
 const CGFloat kExtraMarginBetweenLabelAndButton = 8.0;
 const CGFloat kLabelMarginTop = kButtonsTopMargin + 5.0;  // Baseline lowered.
 const CGFloat kMinimumInfobarHeight = 68.0;
+const CGFloat kHorizontalSpaceBetweenIconAndText = 16.0;
 
 const int kButton2TitleColor = 0x4285f4;
 
@@ -223,8 +224,6 @@
   CGFloat visibleHeight_;
   // The height of this infobar when fully visible.
   CGFloat targetHeight_;
-  // View containing |imageView_|. Exists to apply drop shadows to the view.
-  UIView* imageViewContainer_;
   // View containing the icon.
   UIImageView* imageView_;
   // Close button.
@@ -280,21 +279,20 @@
 // Returns the width reserved for the icon.
 - (CGFloat)leftMarginOnFirstLine {
   CGFloat leftMargin = 0;
-  if (imageViewContainer_) {
-    leftMargin += [self frameOfIcon].size.width;
-    // The margin between the label and the icon is the same as the margin
-    // between the edge of the screen and the icon.
-    leftMargin += 2 * [self frameOfIcon].origin.x;
+  if (imageView_) {
+    leftMargin += CGRectGetMaxX([self frameOfIcon]);
+    leftMargin += kHorizontalSpaceBetweenIconAndText;
   } else {
     leftMargin += kLeftMarginOnFirstLineWhenIconAbsent;
+    leftMargin += SafeAreaInsetsForView(self).left;
   }
   return leftMargin;
 }
 
 // Returns the width reserved for the close button.
 - (CGFloat)rightMarginOnFirstLine {
-  return
-      [closeButton_ imageView].image.size.width + kCloseButtonInnerPadding * 2;
+  return [closeButton_ imageView].image.size.width +
+         kCloseButtonInnerPadding * 2 + SafeAreaInsetsForView(self).right;
 }
 
 // Returns the horizontal space available between the icon and the close
@@ -427,7 +425,8 @@
         CGFloat leftOfRightmostButton =
             [self layoutWideButtonAlignRight:button1_
                                    rightEdge:CGRectGetWidth(self.bounds) -
-                                             kButtonMargin
+                                             kButtonMargin -
+                                             SafeAreaInsetsForView(self).right
                                            y:heightOfFirstLine];
         [self layoutWideButtonAlignRight:button2_
                                rightEdge:leftOfRightmostButton - kButtonSpacing
@@ -452,10 +451,11 @@
     if (layout) {
       // Where is there is just one button it is positioned aligned right in the
       // available space.
-      [self
-          layoutWideButtonAlignRight:button
-                           rightEdge:CGRectGetWidth(self.bounds) - kButtonMargin
-                                   y:heightOfFirstLine];
+      [self layoutWideButtonAlignRight:button
+                             rightEdge:CGRectGetWidth(self.bounds) -
+                                       kButtonMargin -
+                                       SafeAreaInsetsForView(self).right
+                                     y:heightOfFirstLine];
     }
     return kButtonHeight;
   }
@@ -613,6 +613,13 @@
     if (heightOfButtons > 0)
       requiredHeight += heightOfButtons + kButtonMargin;
   }
+  // Take into account the account the bottom safe area.
+  // The top inset should be 0 because the infobar is bottom aligned and does
+  // not reach anywhere near the top of the screen.
+  DCHECK(SafeAreaInsetsForView(self).top == 0);
+  CGFloat bottomSafeAreaInset = SafeAreaInsetsForView(self).bottom;
+  requiredHeight += bottomSafeAreaInset;
+
   return requiredHeight;
 }
 
@@ -623,7 +630,7 @@
 
 - (void)layoutSubviews {
   // Lays out the position of the icon.
-  [imageViewContainer_ setFrame:[self frameOfIcon]];
+  [imageView_ setFrame:[self frameOfIcon]];
   targetHeight_ = [self computeRequiredHeightAndLayoutSubviews:YES];
 
   if (delegate_)
@@ -674,12 +681,11 @@
 }
 
 - (void)addLeftIcon:(UIImage*)image {
-  if (!imageViewContainer_) {
-    imageViewContainer_ = [[UIView alloc] init];
-    [self addSubview:imageViewContainer_];
+  if (imageView_) {
+    [imageView_ removeFromSuperview];
   }
   imageView_ = [[UIImageView alloc] initWithImage:image];
-  [imageViewContainer_ addSubview:imageView_];
+  [self addSubview:imageView_];
 }
 
 - (NSString*)stripMarkersFromString:(NSString*)string {
@@ -863,7 +869,8 @@
   CGSize closeButtonSize = [closeButton_ imageView].image.size;
   closeButtonSize.width += kCloseButtonInnerPadding * 2;
   closeButtonSize.height += kCloseButtonInnerPadding * 2;
-  CGFloat x = CGRectGetMaxX(self.frame) - closeButtonSize.width;
+  CGFloat x = CGRectGetMaxX(self.frame) - closeButtonSize.width -
+              SafeAreaInsetsForView(self).right;
   // Aligns the close button at the top (height includes touch padding).
   CGFloat y = 0;
   if (singleLineMode) {
@@ -877,7 +884,7 @@
 - (CGRect)frameOfIcon {
   CGSize iconSize = [imageView_ image].size;
   CGFloat y = kButtonsTopMargin;
-  CGFloat x = kCloseButtonLeftMargin;
+  CGFloat x = kCloseButtonLeftMargin + SafeAreaInsetsForView(self).left;
   return CGRectMake(AlignValueToPixel(x), AlignValueToPixel(y), iconSize.width,
                     iconSize.height);
 }
diff --git a/ios/chrome/browser/ui/ntp/google_landing_mediator.mm b/ios/chrome/browser/ui/ntp/google_landing_mediator.mm
index 73a2cd48..617b161 100644
--- a/ios/chrome/browser/ui/ntp/google_landing_mediator.mm
+++ b/ios/chrome/browser/ui/ntp/google_landing_mediator.mm
@@ -402,7 +402,8 @@
       _browserState, new_tab_page_uma::ACTION_OPENED_MOST_VISITED_ENTRY);
   base::RecordAction(UserMetricsAction("MobileNTPMostVisited"));
   const ntp_tiles::NTPTile& tile = _mostVisitedData[visitedIndex];
-  ntp_tiles::metrics::RecordTileClick(visitedIndex, tile.source, tileType);
+  ntp_tiles::metrics::RecordTileClick(visitedIndex, tile.title_source,
+                                      tile.source, tileType);
 }
 
 - (ReadingListModel*)readingListModel {
@@ -468,7 +469,7 @@
     ntp_tiles::NTPTile& ntpTile = _mostVisitedDataForLogging[i];
     if (ntpTile.url == URL) {
       ntp_tiles::metrics::RecordTileImpression(
-          i, ntpTile.source, tileType, URL,
+          i, ntpTile.title_source, ntpTile.source, tileType, URL,
           GetApplicationContext()->GetRapporServiceImpl());
       // Reset the URL to be sure to log the impression only once.
       ntpTile.url = GURL();
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_bar.h b/ios/chrome/browser/ui/ntp/new_tab_page_bar.h
index 1326231..5a719fe 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_bar.h
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_bar.h
@@ -24,11 +24,17 @@
 @interface NewTabPageBar : UIView<UIGestureRecognizerDelegate>
 
 @property(nonatomic, strong) NSArray* items;
+// Which button is currently selected.
 @property(nonatomic, assign) NSUInteger selectedIndex;
+// Percentage of the overlay that sits over the tab bar buttons.
 @property(nonatomic, assign) CGFloat overlayPercentage;
 @property(nonatomic, readonly, strong) NSArray* buttons;
 @property(nonatomic, weak) id<NewTabPageBarDelegate> delegate;
 
+// Safe area set by the NTP view. This is used as the safeAreaInsets of this
+// view as it needs to be used before the safeAreaInsets is set up.
+@property(nonatomic, assign) UIEdgeInsets safeAreaInsetFromNTPView;
+
 // Changes the colors of the buttons and overlay depending on the content offset
 // of the scroll view. Tablet Incognito only.
 - (void)updateColorsForScrollView:(UIScrollView*)scrollView;
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_bar.mm b/ios/chrome/browser/ui/ntp/new_tab_page_bar.mm
index f281217..8679306 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_bar.mm
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_bar.mm
@@ -40,7 +40,9 @@
 }
 
 @property(nonatomic, readwrite, strong) NSArray* buttons;
-@property(nonatomic, readwrite, strong) UIButton* popupButton;
+
+// View containing the content and respecting the safe area.
+@property(nonatomic, strong) UIView* contentView;
 
 - (void)setup;
 - (void)calculateButtonWidth;
@@ -50,29 +52,23 @@
 @end
 
 @implementation NewTabPageBar {
-  // Which button is currently selected.
-  NSUInteger selectedIndex_;
   // Don't allow tabbar animations on startup, only after first tap.
   BOOL canAnimate_;
-  __weak id<NewTabPageBarDelegate> delegate_;
-  // Logo view, used to center the tab buttons.
-  UIImageView* logoView_;
   // Overlay view, used to highlight the selected button.
   UIImageView* overlayView_;
   // Overlay view, used to highlight the selected button.
   UIView* overlayColorView_;
   // Width of a button.
   CGFloat buttonWidth_;
-  // Percentage overlay sits over tab bar buttons.
-  CGFloat overlayPercentage_;
 }
 
 @synthesize items = items_;
 @synthesize selectedIndex = selectedIndex_;
-@synthesize popupButton = popupButton_;
 @synthesize buttons = buttons_;
 @synthesize delegate = delegate_;
 @synthesize overlayPercentage = overlayPercentage_;
+@synthesize contentView = _contentView;
+@synthesize safeAreaInsetFromNTPView = _safeAreaInsetFromNTPView;
 
 - (id)initWithFrame:(CGRect)frame {
   self = [super initWithFrame:frame];
@@ -93,10 +89,10 @@
 - (void)setup {
   self.selectedIndex = NSNotFound;
   canAnimate_ = NO;
-  self.autoresizingMask =
-      UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
-  self.autoresizesSubviews = YES;
-  self.backgroundColor = [UIColor clearColor];
+  self.backgroundColor = [UIColor whiteColor];
+
+  _contentView = [[UIView alloc] initWithFrame:CGRectZero];
+  [self addSubview:_contentView];
 
   if ([self showOverlay]) {
     overlayView_ =
@@ -113,7 +109,7 @@
         setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin |
                             UIViewAutoresizingFlexibleRightMargin];
     [overlayView_ addSubview:overlayColorView_];
-    [self addSubview:overlayView_];
+    [_contentView addSubview:overlayView_];
   }
 
   // Make the drop shadow.
@@ -132,22 +128,25 @@
 - (void)layoutSubviews {
   [super layoutSubviews];
 
+  CGRect contentViewFrame =
+      UIEdgeInsetsInsetRect(self.frame, self.safeAreaInsetFromNTPView);
+  contentViewFrame.origin.y = 0;
+  self.contentView.frame = contentViewFrame;
+
   // |buttonWidth_| changes with the screen orientation when the NTP button bar
   // is enabled.
   [self calculateButtonWidth];
 
-  CGFloat logoWidth = logoView_.image.size.width;
-  CGFloat padding = [self useIconsInButtons] ? logoWidth : 0;
-  CGFloat buttonPadding = floor((CGRectGetWidth(self.bounds) - padding -
+  CGFloat buttonPadding = floor((CGRectGetWidth(self.contentView.bounds) -
                                  buttonWidth_ * self.buttons.count) /
-                                    2 +
-                                padding);
+                                2);
 
   for (NSUInteger i = 0; i < self.buttons.count; ++i) {
     NewTabPageBarButton* button = [self.buttons objectAtIndex:i];
-    LayoutRect layout = LayoutRectMake(
-        buttonPadding + (i * buttonWidth_), CGRectGetWidth(self.bounds), 0,
-        buttonWidth_, CGRectGetHeight(self.bounds));
+    LayoutRect layout =
+        LayoutRectMake(buttonPadding + (i * buttonWidth_),
+                       CGRectGetWidth(self.contentView.bounds), 0, buttonWidth_,
+                       CGRectGetHeight(self.contentView.bounds));
     button.frame = LayoutRectGetRect(layout);
     [button
         setContentToDisplay:[self useIconsInButtons]
@@ -166,13 +165,14 @@
 }
 
 - (CGSize)sizeThatFits:(CGSize)size {
-  return CGSizeMake(size.width, kBarHeight);
+  return CGSizeMake(size.width,
+                    kBarHeight + self.safeAreaInsetFromNTPView.bottom);
 }
 
 - (void)calculateButtonWidth {
   if (IsCompact()) {
     if ([items_ count] > 0) {
-      buttonWidth_ = self.bounds.size.width / [items_ count];
+      buttonWidth_ = self.contentView.bounds.size.width / [items_ count];
     } else {
       // In incognito on phones, there are no items shown.
       buttonWidth_ = 0;
@@ -202,10 +202,10 @@
     for (NSUInteger i = 0; i < newItems.count; ++i) {
       NewTabPageBarItem* item = [newItems objectAtIndex:i];
       NewTabPageBarButton* button = [NewTabPageBarButton buttonWithItem:item];
-      button.frame = CGRectIntegral(CGRectMake(
-          i * buttonWidth_, 0, buttonWidth_, self.bounds.size.height));
+      button.frame = CGRectIntegral(
+          CGRectMake(i * buttonWidth_, 0, buttonWidth_, kBarHeight));
       [self setupButton:button];
-      [self addSubview:button];
+      [self.contentView addSubview:button];
       [newButtons addObject:button];
     }
     self.buttons = newButtons;
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_controller.h b/ios/chrome/browser/ui/ntp/new_tab_page_controller.h
index 9d88e24f8..e0e7eae1 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_controller.h
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_controller.h
@@ -89,7 +89,8 @@
               dispatcher:(id<ApplicationCommands,
                              BrowserCommands,
                              OmniboxFocuser,
-                             UrlLoader>)dispatcher;
+                             UrlLoader>)dispatcher
+           safeAreaInset:(UIEdgeInsets)safeAreaInset;
 
 // Select a panel based on the given |panelType|.
 - (void)selectPanel:(ntp_home::PanelIdentifier)panelType;
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_controller.mm b/ios/chrome/browser/ui/ntp/new_tab_page_controller.mm
index 5eecf77..0c2c8bc 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_controller.mm
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_controller.mm
@@ -220,7 +220,8 @@
               dispatcher:(id<ApplicationCommands,
                              BrowserCommands,
                              OmniboxFocuser,
-                             UrlLoader>)dispatcher {
+                             UrlLoader>)dispatcher
+           safeAreaInset:(UIEdgeInsets)safeAreaInset {
   self = [super initWithNibName:nil url:url];
   if (self) {
     DCHECK(browserState);
@@ -236,6 +237,9 @@
     self.title = l10n_util::GetNSString(IDS_NEW_TAB_TITLE);
     _scrollInitialized = NO;
 
+    // It is necessary to initialize the view with a non-empty frame so the NTP
+    // can be scrolled when the Bookmarks/Recent Tabs are opened from the
+    // toolmenu.
     UIScrollView* scrollView =
         [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 412)];
     [scrollView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth |
@@ -245,6 +249,7 @@
     _view = [[NewTabPageView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)
                                     andScrollView:scrollView
                                         andTabBar:tabBar];
+    _view.safeAreaInsetForToolbar = safeAreaInset;
     [tabBar setDelegate:self];
 
     bool isIncognito = _browserState->IsOffTheRecord();
@@ -476,7 +481,7 @@
 
 // Update selectedIndex and scroll position as the scroll view moves.
 - (void)scrollViewDidScroll:(UIScrollView*)scrollView {
-  if (!_scrollInitialized)
+  if (!_scrollInitialized || PresentNTPPanelModally())
     return;
 
   // Position is used to track the exact X position of the scroll view, whereas
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_controller_unittest.mm b/ios/chrome/browser/ui/ntp/new_tab_page_controller_unittest.mm
index 69e7e96..bfa82ff 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_controller_unittest.mm
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_controller_unittest.mm
@@ -20,6 +20,7 @@
 #include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h"
 #import "ios/chrome/browser/sessions/test_session_service.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
+#import "ios/chrome/browser/ui/ntp/modal_ntp.h"
 #import "ios/chrome/browser/ui/ntp/new_tab_page_view.h"
 #include "ios/chrome/browser/ui/ui_util.h"
 #include "ios/chrome/test/block_cleanup_test.h"
@@ -79,7 +80,8 @@
                                   toolbarDelegate:nil
                                          tabModel:tabModel_
                              parentViewController:parentViewController_
-                                       dispatcher:nil];
+                                       dispatcher:nil
+                                    safeAreaInset:UIEdgeInsetsZero];
 
     incognitoController_ = [[NewTabPageController alloc]
                  initWithUrl:url
@@ -92,7 +94,8 @@
              toolbarDelegate:nil
                     tabModel:nil
         parentViewController:parentViewController_
-                  dispatcher:nil];
+                  dispatcher:nil
+               safeAreaInset:UIEdgeInsetsZero];
   };
 
   void TearDown() override {
@@ -126,14 +129,15 @@
   NewTabPageBar* bar = [NTPView tabBar];
   NSUInteger bookmarkIndex = 0;
   UIButton* button = [[bar buttons] objectAtIndex:bookmarkIndex];
-  UIControlEvents event =
-      IsIPadIdiom() ? UIControlEventTouchDown : UIControlEventTouchUpInside;
+  UIControlEvents event = !PresentNTPPanelModally()
+                              ? UIControlEventTouchDown
+                              : UIControlEventTouchUpInside;
   [button sendActionsForControlEvents:event];
 
   // Expecting bookmarks panel to be loaded now and to be the current controller
   // on iPad but not iPhone.
   // Deliberately comparing pointers.
-  if (IsIPadIdiom()) {
+  if (!PresentNTPPanelModally()) {
     EXPECT_EQ([controller_ currentController],
               (id<NewTabPagePanelProtocol>)[controller_ bookmarkController]);
   } else {
@@ -154,7 +158,7 @@
   // Expecting bookmarks panel to be loaded now and to be the current controller
   // on iPad but not iPhone.
   // Deliberately comparing pointers.
-  if (IsIPadIdiom()) {
+  if (!PresentNTPPanelModally()) {
     EXPECT_EQ([controller_ currentController],
               (id<NewTabPagePanelProtocol>)[controller_ bookmarkController]);
   } else {
@@ -175,7 +179,7 @@
   // Expecting bookmarks panel to be loaded now and to be the current controller
   // on iPad but not iPhone.
   // Deliberately comparing pointers.
-  if (IsIPadIdiom()) {
+  if (!PresentNTPPanelModally()) {
     EXPECT_EQ(
         [incognitoController_ currentController],
         (id<NewTabPagePanelProtocol>)[incognitoController_ bookmarkController]);
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_view.h b/ios/chrome/browser/ui/ntp/new_tab_page_view.h
index 9c38c4b..a0c7cac8 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_view.h
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_view.h
@@ -14,6 +14,12 @@
 @interface NewTabPageView : UIView
 @property(nonatomic, weak, readonly) UIScrollView* scrollView;
 @property(nonatomic, weak, readonly) NewTabPageBar* tabBar;
+// Safe area to be used for toolbar. Once the view is part of the view hierarchy
+// and has its own safe area set, this is equal to safeAreaInsets. But as a
+// snapshot of the view is taken before it is inserted in the view hierarchy,
+// this property needs to be set to what would be the safe area after being
+// inserted in the view hierarchy, before the snapshot is taken.
+@property(nonatomic, assign) UIEdgeInsets safeAreaInsetForToolbar;
 
 - (instancetype)initWithFrame:(CGRect)frame
                 andScrollView:(UIScrollView*)scrollView
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_view.mm b/ios/chrome/browser/ui/ntp/new_tab_page_view.mm
index 0d0455df..c5a5b0d 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_view.mm
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_view.mm
@@ -19,6 +19,7 @@
 
 @synthesize scrollView = scrollView_;
 @synthesize tabBar = tabBar_;
+@synthesize safeAreaInsetForToolbar = _safeAreaInsetForToolbar;
 
 - (instancetype)initWithFrame:(CGRect)frame
                 andScrollView:(UIScrollView*)scrollView
@@ -33,6 +34,11 @@
   return self;
 }
 
+- (void)safeAreaInsetsDidChange {
+  self.safeAreaInsetForToolbar = self.safeAreaInsets;
+  [super safeAreaInsetsDidChange];
+}
+
 - (instancetype)initWithFrame:(CGRect)frame {
   NOTREACHED();
   return nil;
@@ -43,6 +49,13 @@
   return nil;
 }
 
+#pragma mark - Properties
+
+- (void)setSafeAreaInsetForToolbar:(UIEdgeInsets)safeAreaInsetForToolbar {
+  _safeAreaInsetForToolbar = safeAreaInsetForToolbar;
+  self.tabBar.safeAreaInsetFromNTPView = safeAreaInsetForToolbar;
+}
+
 - (void)setFrame:(CGRect)frame {
   // When transitioning the iPhone xib to an iPad idiom, the setFrame call below
   // can sometimes fire a scrollViewDidScroll event which changes the
@@ -101,6 +114,7 @@
         CGRectGetMinX(self.bounds), CGRectGetMinY(self.bounds),
         CGRectGetWidth(self.bounds), CGRectGetMinY(self.tabBar.frame));
   }
+  [self updateScrollViewContentSize];
 
   // When using a new_tab_page_view in autolayout -setFrame is never called,
   // which means all the logic to keep the selected scroll index set is never
diff --git a/ios/chrome/browser/ui/ntp/recent_tabs/BUILD.gn b/ios/chrome/browser/ui/ntp/recent_tabs/BUILD.gn
index 58971c2..cc7f59b 100644
--- a/ios/chrome/browser/ui/ntp/recent_tabs/BUILD.gn
+++ b/ios/chrome/browser/ui/ntp/recent_tabs/BUILD.gn
@@ -90,6 +90,7 @@
     "//ios/chrome/test/earl_grey:test_support",
     "//ios/third_party/earl_grey",
     "//ios/web/public/test/http_server",
+    "//ui/base",
   ]
   libs = [ "XCTest.framework" ]
 }
diff --git a/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_handset_coordinator.mm b/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_handset_coordinator.mm
index 9626afa..42ef6bf 100644
--- a/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_handset_coordinator.mm
+++ b/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_handset_coordinator.mm
@@ -4,6 +4,7 @@
 
 #import "ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_handset_coordinator.h"
 
+#include "base/ios/block_types.h"
 #include "base/logging.h"
 #import "ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_handset_view_controller.h"
 #import "ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_table_coordinator.h"
@@ -18,6 +19,8 @@
 @property(nonatomic, strong)
     RecentTabsHandsetViewController* recentTabsViewController;
 @property(nonatomic, strong) RecentTabsTableCoordinator* tableCoordinator;
+// Completion block called once the recentTabsViewController is dismissed.
+@property(nonatomic, assign) ProceduralBlock completion;
 
 @end
 
@@ -28,6 +31,7 @@
 @synthesize browserState = _browserState;
 @synthesize dispatcher = _dispatcher;
 @synthesize loader = _loader;
+@synthesize completion = _completion;
 
 - (void)start {
   DCHECK(self.browserState);
@@ -53,7 +57,8 @@
 
 - (void)stop {
   [self.recentTabsViewController dismissViewControllerAnimated:YES
-                                                    completion:nil];
+                                                    completion:self.completion];
+  self.completion = nil;
   [self.tableCoordinator dismissKeyboard];
   [self.tableCoordinator dismissModals];
   [self.tableCoordinator stop];
@@ -63,7 +68,8 @@
 
 #pragma mark - RecentTabsHandsetViewControllerCommand
 
-- (void)dismissRecentTabs {
+- (void)dismissRecentTabsWithCompletion:(void (^)())completion {
+  self.completion = completion;
   [self stop];
 }
 
diff --git a/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_handset_view_controller.h b/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_handset_view_controller.h
index 7061619d..53792ca8 100644
--- a/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_handset_view_controller.h
+++ b/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_handset_view_controller.h
@@ -10,8 +10,8 @@
 // Command protocol for the RecentTabsHandsetViewController.
 @protocol RecentTabsHandsetViewControllerCommand
 
-// Dismisses the recent tabs panel.
-- (void)dismissRecentTabs;
+// Dismisses the recent tabs panel and calls |completion| once it is done.
+- (void)dismissRecentTabsWithCompletion:(void (^)())completion;
 
 @end
 
diff --git a/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_handset_view_controller.mm b/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_handset_view_controller.mm
index 9bd5929..382176a 100644
--- a/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_handset_view_controller.mm
+++ b/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_handset_view_controller.mm
@@ -91,7 +91,7 @@
 }
 
 - (void)didFinish {
-  [self.commandHandler dismissRecentTabs];
+  [self.commandHandler dismissRecentTabsWithCompletion:nil];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_table_egtest.mm b/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_table_egtest.mm
index 0b1ebd9..8af6dca 100644
--- a/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_table_egtest.mm
+++ b/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_table_egtest.mm
@@ -19,6 +19,7 @@
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/web/public/test/http_server/http_server.h"
 #include "ios/web/public/test/http_server/http_server_util.h"
+#import "ui/base/l10n/l10n_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -147,4 +148,32 @@
                             testPageURL.GetContent())];
 }
 
+// Tests that tapping "Show Full History" open the history.
+- (void)testOpenHistory {
+  OpenRecentTabsPanel();
+
+  // Tap "Show Full History"
+  [[EarlGrey
+      selectElementWithMatcher:chrome_test_util::ButtonWithAccessibilityLabel(
+                                   l10n_util::GetNSString(
+                                       IDS_HISTORY_SHOWFULLHISTORY_LINK))]
+      performAction:grey_tap()];
+
+  // Make sure history is opened.
+  [[EarlGrey
+      selectElementWithMatcher:grey_accessibilityLabel(
+                                   l10n_util::GetNSString(IDS_HISTORY_TITLE))]
+      assertWithMatcher:grey_sufficientlyVisible()];
+
+  // Close History.
+  [[EarlGrey
+      selectElementWithMatcher:chrome_test_util::ButtonWithAccessibilityLabel(
+                                   l10n_util::GetNSString(
+                                       IDS_IOS_NAVIGATION_BAR_DONE_BUTTON))]
+      performAction:grey_tap()];
+
+  // Close tab.
+  chrome_test_util::CloseCurrentTab();
+}
+
 @end
diff --git a/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_table_view_controller.mm b/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_table_view_controller.mm
index 41a81f00..8818078 100644
--- a/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_table_view_controller.mm
+++ b/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_table_view_controller.mm
@@ -115,9 +115,6 @@
 - (NSInteger)numberOfSectionsBeforeSessionOrOtherDevicesSections;
 // Dismisses the modal containing the Recent Tabs panel (iPhone only).
 - (void)dismissRecentTabsModal;
-// Dismisses the modal containing the Recent Tabs panel, with completion
-// handler (iPhone only).
-- (void)dismissRecentTabsModalWithCompletion:(ProceduralBlock)completion;
 // Opens a new tab with the content of |distantTab|.
 - (void)openTabWithContentOfDistantTab:
     (synced_sessions::DistantTab const*)distantTab;
@@ -353,11 +350,7 @@
 #pragma mark - Helpers to open tabs, or show the full history view.
 
 - (void)dismissRecentTabsModal {
-  [self dismissRecentTabsModalWithCompletion:nil];
-}
-
-- (void)dismissRecentTabsModalWithCompletion:(ProceduralBlock)completion {
-  [self.handsetCommandHandler dismissRecentTabs];
+  [self.handsetCommandHandler dismissRecentTabsWithCompletion:nil];
 }
 
 - (void)openTabWithContentOfDistantTab:
@@ -413,10 +406,10 @@
     [weakSelf.dispatcher showHistory];
   };
   // Dismiss modal, if shown, and open history.
-  if (IsIPadIdiom()) {
-    openHistory();
+  if (self.handsetCommandHandler) {
+    [self.handsetCommandHandler dismissRecentTabsWithCompletion:openHistory];
   } else {
-    [self dismissRecentTabsModalWithCompletion:openHistory];
+    openHistory();
   }
 }
 
diff --git a/ios/chrome/browser/ui/ntp/recent_tabs/views/show_full_history_view.mm b/ios/chrome/browser/ui/ntp/recent_tabs/views/show_full_history_view.mm
index aebbce6..a9c7abf3 100644
--- a/ios/chrome/browser/ui/ntp/recent_tabs/views/show_full_history_view.mm
+++ b/ios/chrome/browser/ui/ntp/recent_tabs/views/show_full_history_view.mm
@@ -43,7 +43,7 @@
     [self addSubview:label];
 
     self.isAccessibilityElement = YES;
-    self.accessibilityLabel = [label accessibilityLabel];
+    self.accessibilityLabel = label.text;
     self.accessibilityTraits |= UIAccessibilityTraitButton;
 
     NSDictionary* viewsDictionary = @{
diff --git a/ios/chrome/browser/ui/payments/address_edit_mediator.mm b/ios/chrome/browser/ui/payments/address_edit_mediator.mm
index aced131..151b914 100644
--- a/ios/chrome/browser/ui/payments/address_edit_mediator.mm
+++ b/ios/chrome/browser/ui/payments/address_edit_mediator.mm
@@ -22,6 +22,7 @@
 #include "components/autofill/core/browser/country_combobox_model.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/phone_number_i18n.h"
 #include "components/payments/core/payment_request_data_util.h"
 #include "components/strings/grit/components_strings.h"
 #include "ios/chrome/browser/payments/payment_request.h"
@@ -136,10 +137,9 @@
 
 - (void)formatValueForEditorField:(EditorField*)field {
   if (field.autofillUIType == AutofillUITypeProfileHomePhoneWholeNumber) {
-    field.value =
-        base::SysUTF8ToNSString(payments::data_util::FormatPhoneForDisplay(
-            base::SysNSStringToUTF8(field.value),
-            base::SysNSStringToUTF8(self.selectedCountryCode)));
+    field.value = base::SysUTF8ToNSString(autofill::i18n::FormatPhoneForDisplay(
+        base::SysNSStringToUTF8(field.value),
+        base::SysNSStringToUTF8(self.selectedCountryCode)));
   }
 }
 
@@ -175,7 +175,15 @@
   // Notify the view controller asynchronously to allow for the view to update.
   __weak AddressEditMediator* weakSelf = self;
   dispatch_async(dispatch_get_main_queue(), ^{
-    [weakSelf.consumer setOptions:@[ [regions allKeys] ]
+    NSMutableArray<NSString*>* values =
+        [[NSMutableArray alloc] initWithArray:[regions allKeys]];
+    // If the field contains no value, insert an empty value at the beginning
+    // of the list of options, as the first option is selected when the UI
+    // opens. Otherwise, it would be impossible for the user to select the first
+    // option without selecting another option first.
+    if (!weakSelf.regionField.value)
+      [values insertObject:@"" atIndex:0];
+    [weakSelf.consumer setOptions:@[ values ]
                    forEditorField:weakSelf.regionField];
   });
 }
@@ -342,7 +350,7 @@
     NSString* value =
         self.address
             ? base::SysUTF16ToNSString(
-                  payments::data_util::GetFormattedPhoneNumberForDisplay(
+                  autofill::i18n::GetFormattedPhoneNumberForDisplay(
                       *self.address, _paymentRequest->GetApplicationLocale()))
             : nil;
     field = [[EditorField alloc]
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm b/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm
index 44bf9d4..7bc41d0 100644
--- a/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm
+++ b/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm
@@ -10,6 +10,7 @@
 #include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/field_types.h"
+#include "components/autofill/core/browser/phone_number_i18n.h"
 #include "components/payments/core/payment_request_data_util.h"
 #include "components/strings/grit/components_strings.h"
 #include "ios/chrome/browser/payments/payment_request.h"
@@ -94,9 +95,8 @@
     const std::string countryCode =
         autofill::AutofillCountry::CountryCodeForLocale(
             _paymentRequest->GetApplicationLocale());
-    field.value =
-        base::SysUTF8ToNSString(payments::data_util::FormatPhoneForDisplay(
-            base::SysNSStringToUTF8(field.value), countryCode));
+    field.value = base::SysUTF8ToNSString(autofill::i18n::FormatPhoneForDisplay(
+        base::SysNSStringToUTF8(field.value), countryCode));
   }
 }
 
@@ -131,7 +131,7 @@
     NSString* phone =
         self.profile
             ? base::SysUTF16ToNSString(
-                  payments::data_util::GetFormattedPhoneNumberForDisplay(
+                  autofill::i18n::GetFormattedPhoneNumberForDisplay(
                       *self.profile, _paymentRequest->GetApplicationLocale()))
             : nil;
     EditorField* phoneField = [[EditorField alloc]
diff --git a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm
index 5ed5f30..3beb26a 100644
--- a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm
+++ b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm
@@ -422,10 +422,16 @@
   AutofillEditItem* item = base::mac::ObjCCastStrict<AutofillEditItem>(
       [model itemAtIndexPath:indexPath]);
 
-  // Find the respective editor field and update its value to the proposed text.
+  // Find the respective editor field and update its value to the proposed text
+  // only if the editor field does not have an associated UIPickerView. This
+  // prevents users from altering the text unless it is via the UIPickerView.
   NSNumber* key = [NSNumber numberWithInt:sectionIdentifier];
   EditorField* field = self.fieldsMap[key];
   DCHECK(field);
+  key = [NSNumber numberWithInt:field.autofillUIType];
+  if ([self.pickerViews objectForKey:key])
+    return NO;
+
   field.value = [textField.text stringByReplacingCharactersInRange:range
                                                         withString:newText];
 
diff --git a/ios/chrome/browser/ui/payments/payment_request_manager.mm b/ios/chrome/browser/ui/payments/payment_request_manager.mm
index 17c091c..572a9e2 100644
--- a/ios/chrome/browser/ui/payments/payment_request_manager.mm
+++ b/ios/chrome/browser/ui/payments/payment_request_manager.mm
@@ -114,10 +114,6 @@
   // PersonalDataManager used to manage user credit cards and addresses.
   autofill::PersonalDataManager* _personalDataManager;
 
-  // Maintains a map of web::WebState to a list of payments::PaymentRequest
-  // instances maintained for that WebState.
-  payments::PaymentRequestCache* _paymentRequestCache;
-
   // The observer for |_activeWebState|.
   std::unique_ptr<web::WebStateObserverBridge> _activeWebStateObserver;
 
@@ -154,6 +150,10 @@
 // Object that manages JavaScript injection into the web view.
 @property(nonatomic, weak) JSPaymentRequestManager* paymentRequestJsManager;
 
+// Maintains a map of web::WebState to a list of payments::PaymentRequest
+// instances maintained for that WebState.
+@property(nonatomic, assign) payments::PaymentRequestCache* paymentRequestCache;
+
 // The payments::PaymentRequest instance currently showing, if any.
 @property(nonatomic, assign) payments::PaymentRequest* pendingPaymentRequest;
 
@@ -256,6 +256,7 @@
 @synthesize activeWebState = _activeWebState;
 @synthesize paymentRequestCoordinator = _paymentRequestCoordinator;
 @synthesize paymentRequestJsManager = _paymentRequestJsManager;
+@synthesize paymentRequestCache = _paymentRequestCache;
 @synthesize pendingPaymentRequest = _pendingPaymentRequest;
 @synthesize dispatcher = _dispatcher;
 @synthesize coordinatorDidStopCallback = _coordinatorDidStopCallback;
@@ -288,7 +289,6 @@
 }
 
 - (void)setActiveWebState:(web::WebState*)webState {
-  [self cancelRequest];
   [self disableActiveWebState];
 
   _paymentRequestJsManager = nil;
@@ -307,19 +307,32 @@
 }
 
 - (void)stopTrackingWebState:(web::WebState*)webState {
-  for (const auto& paymentRequest :
-       _paymentRequestCache->GetPaymentRequests(_activeWebState)) {
-    if (paymentRequest->state() != payments::PaymentRequest::State::CLOSED) {
-      paymentRequest->journey_logger().SetAborted(
-          payments::JourneyLogger::ABORT_REASON_USER_NAVIGATION);
-      paymentRequest->set_updating(false);
-      paymentRequest->set_state(payments::PaymentRequest::State::CLOSED);
+  __weak PaymentRequestManager* weakSelf = self;
+  ProceduralBlockWithBool callback = ^(BOOL) {
+    for (const auto& paymentRequest :
+         weakSelf.paymentRequestCache->GetPaymentRequests(webState)) {
+      if (paymentRequest->state() != payments::PaymentRequest::State::CLOSED) {
+        paymentRequest->journey_logger().SetAborted(
+            payments::JourneyLogger::ABORT_REASON_USER_NAVIGATION);
+        paymentRequest->set_updating(false);
+        paymentRequest->set_state(payments::PaymentRequest::State::CLOSED);
+      }
     }
+    // The lifetime of a PaymentRequest is tied to the WebState it is associated
+    // with and the current URL. Therefore, PaymentRequest instances should get
+    // destroyed when the WebState goes away.
+    weakSelf.paymentRequestCache->ClearPaymentRequests(webState);
+  };
+
+  // Abort any pending request.
+  if (_pendingPaymentRequest) {
+    [self abortPendingRequestWithReason:payments::JourneyLogger::
+                                            ABORT_REASON_MERCHANT_NAVIGATION
+                           errorMessage:kCancelErrorMessage
+                               callback:callback];
+  } else {
+    callback(YES);
   }
-  // The lifetime of a PaymentRequest is tied to the WebState it is associated
-  // with and the current URL. Therefore, PaymentRequest instances should get
-  // destroyed when the WebState goes away.
-  _paymentRequestCache->ClearPaymentRequests(webState);
 }
 
 - (void)enablePaymentRequest:(BOOL)enabled {
@@ -1087,30 +1100,36 @@
 
 - (void)webState:(web::WebState*)webState
     didStartNavigation:(web::NavigationContext*)navigation {
-  // Reset any pending request.
-  if (_pendingPaymentRequest) {
-    _pendingPaymentRequest = nullptr;
-    [self resetIOSPaymentInstrumentLauncherDelegate];
-  }
+  payments::JourneyLogger::AbortReason abortReason =
+      navigation->IsRendererInitiated()
+          ? payments::JourneyLogger::ABORT_REASON_MERCHANT_NAVIGATION
+          : payments::JourneyLogger::ABORT_REASON_USER_NAVIGATION;
 
-  [self dismissUIWithCallback:nil];
-
-  for (const auto& paymentRequest :
-       _paymentRequestCache->GetPaymentRequests(_activeWebState)) {
-    if (paymentRequest->state() != payments::PaymentRequest::State::CLOSED) {
-      paymentRequest->journey_logger().SetAborted(
-          navigation->IsRendererInitiated()
-              ? payments::JourneyLogger::ABORT_REASON_MERCHANT_NAVIGATION
-              : payments::JourneyLogger::ABORT_REASON_USER_NAVIGATION);
-      paymentRequest->set_updating(false);
-      paymentRequest->set_state(payments::PaymentRequest::State::CLOSED);
+  __weak PaymentRequestManager* weakSelf = self;
+  ProceduralBlockWithBool callback = ^(BOOL) {
+    for (const auto& paymentRequest :
+         weakSelf.paymentRequestCache->GetPaymentRequests(
+             weakSelf.activeWebState)) {
+      if (paymentRequest->state() != payments::PaymentRequest::State::CLOSED) {
+        paymentRequest->journey_logger().SetAborted(abortReason);
+        paymentRequest->set_updating(false);
+        paymentRequest->set_state(payments::PaymentRequest::State::CLOSED);
+      }
     }
-  }
+    // The lifetime of a PaymentRequest is tied to the WebState it is associated
+    // with and the current URL. Therefore, PaymentRequest instances should get
+    // destroyed when the user navigates to a URL.
+    weakSelf.paymentRequestCache->ClearPaymentRequests(weakSelf.activeWebState);
+  };
 
-  // The lifetime of a PaymentRequest is tied to the WebState it is associated
-  // with and the current URL. Therefore, PaymentRequest instances should get
-  // destroyed when the WebState goes away or the user navigates to a URL.
-  _paymentRequestCache->ClearPaymentRequests(_activeWebState);
+  // Abort any pending request.
+  if (_pendingPaymentRequest) {
+    [self abortPendingRequestWithReason:abortReason
+                           errorMessage:kCancelErrorMessage
+                               callback:callback];
+  } else {
+    callback(YES);
+  }
 
   // Set the JS isContextSecure global variable at the earliest opportunity.
   [_paymentRequestJsManager
diff --git a/ios/chrome/browser/ui/payments/payment_request_picker_view_controller.mm b/ios/chrome/browser/ui/payments/payment_request_picker_view_controller.mm
index 9560c08b..d55accb4 100644
--- a/ios/chrome/browser/ui/payments/payment_request_picker_view_controller.mm
+++ b/ios/chrome/browser/ui/payments/payment_request_picker_view_controller.mm
@@ -245,6 +245,7 @@
       UITableViewCell* cell =
           [self.tableView cellForRowAtIndexPath:oldSelectedIndexPath];
       cell.accessoryType = UITableViewCellAccessoryNone;
+      cell.accessibilityTraits &= ~UIAccessibilityTraitSelected;
     }
   }
 
@@ -253,6 +254,7 @@
 
   UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexPath];
   cell.accessoryType = UITableViewCellAccessoryCheckmark;
+  cell.accessibilityTraits |= UIAccessibilityTraitSelected;
 
   [_delegate paymentRequestPickerViewController:self
                                    didSelectRow:self.selectedRow];
diff --git a/ios/chrome/browser/ui/settings/password_details_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/password_details_collection_view_controller_unittest.mm
index 1aa3bf5..1d975f9 100644
--- a/ios/chrome/browser/ui/settings/password_details_collection_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/password_details_collection_view_controller_unittest.mm
@@ -86,7 +86,8 @@
 class PasswordDetailsCollectionViewControllerTest
     : public CollectionViewControllerTest {
  protected:
-  PasswordDetailsCollectionViewControllerTest() {
+  PasswordDetailsCollectionViewControllerTest()
+      : thread_bundle_(web::TestWebThreadBundle::REAL_DB_THREAD) {
     origin_ = kSite;
     form_.username_value = base::SysNSStringToUTF16(kUsername);
     form_.password_value = base::SysNSStringToUTF16(kPassword);
diff --git a/ios/chrome/browser/ui/settings/save_passwords_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/save_passwords_collection_view_controller_unittest.mm
index 8317db8..a6581138 100644
--- a/ios/chrome/browser/ui/settings/save_passwords_collection_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/save_passwords_collection_view_controller_unittest.mm
@@ -34,7 +34,8 @@
 class SavePasswordsCollectionViewControllerTest
     : public CollectionViewControllerTest {
  protected:
-  SavePasswordsCollectionViewControllerTest() = default;
+  SavePasswordsCollectionViewControllerTest()
+      : thread_bundle_(web::TestWebThreadBundle::REAL_DB_THREAD) {}
 
   void SetUp() override {
     TestChromeBrowserState::Builder test_cbs_builder;
diff --git a/ios/chrome/browser/ui/snackbar/BUILD.gn b/ios/chrome/browser/ui/snackbar/BUILD.gn
new file mode 100644
index 0000000..6c34a29c1
--- /dev/null
+++ b/ios/chrome/browser/ui/snackbar/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.
+
+source_set("snackbar") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  sources = [
+    "snackbar_coordinator.h",
+    "snackbar_coordinator.mm",
+  ]
+  deps = [
+    "//ios/chrome/browser/ui/commands",
+    "//ios/third_party/material_components_ios",
+  ]
+  libs = [ "UIKit.framework" ]
+}
+
+source_set("unit_tests") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  testonly = true
+  sources = [
+    "snackbar_coordinator_unittest.mm",
+  ]
+  deps = [
+    ":snackbar",
+    "//ios/chrome/browser/ui/commands",
+    "//testing/gtest",
+    "//third_party/ocmock",
+  ]
+}
diff --git a/ios/chrome/browser/ui/snackbar/OWNERS b/ios/chrome/browser/ui/snackbar/OWNERS
new file mode 100644
index 0000000..f72b1e5
--- /dev/null
+++ b/ios/chrome/browser/ui/snackbar/OWNERS
@@ -0,0 +1,4 @@
+edchin@chromium.org
+
+# TEAM: ios-directory-owners@chromium.org
+# OS: iOS
diff --git a/ios/chrome/browser/ui/snackbar/snackbar_coordinator.h b/ios/chrome/browser/ui/snackbar/snackbar_coordinator.h
new file mode 100644
index 0000000..1e3594f
--- /dev/null
+++ b/ios/chrome/browser/ui/snackbar/snackbar_coordinator.h
@@ -0,0 +1,26 @@
+// 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 IOS_CHROME_BROWSER_UI_SNACKBAR_SNACKBAR_COORDINATOR_H_
+#define IOS_CHROME_BROWSER_UI_SNACKBAR_SNACKBAR_COORDINATOR_H_
+
+#import <Foundation/Foundation.h>
+
+@class CommandDispatcher;
+
+// Coodinator that handles commands to show snackbars.
+@interface SnackbarCoordinator : NSObject
+
+// The dispatcher used to register commands.
+@property(nonatomic, weak) CommandDispatcher* dispatcher;
+
+// Starts the coordinator.
+- (void)start;
+
+// Stops the coordinator.
+- (void)stop;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_SNACKBAR_SNACKBAR_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/snackbar/snackbar_coordinator.mm b/ios/chrome/browser/ui/snackbar/snackbar_coordinator.mm
new file mode 100644
index 0000000..03cbdc2
--- /dev/null
+++ b/ios/chrome/browser/ui/snackbar/snackbar_coordinator.mm
@@ -0,0 +1,43 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/snackbar/snackbar_coordinator.h"
+
+#import "ios/chrome/browser/ui/commands/command_dispatcher.h"
+#import "ios/chrome/browser/ui/commands/snackbar_commands.h"
+#import "ios/third_party/material_components_ios/src/components/Snackbar/src/MaterialSnackbar.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+// The default category for all messages.
+NSString* const kDefaultSnackbarCategory = @"DefaultSnackbarCategory";
+}  // namespace
+
+@implementation SnackbarCoordinator
+@synthesize dispatcher = _dispatcher;
+
+- (void)start {
+  [self.dispatcher startDispatchingToTarget:self
+                                forProtocol:@protocol(SnackbarCommands)];
+}
+
+- (void)stop {
+  [self.dispatcher stopDispatchingToTarget:self];
+}
+
+#pragma mark - SnackbarCommands
+
+- (void)showSnackbarWithMessage:(NSString*)message {
+  MDCSnackbarMessage* snackbarMessage =
+      [MDCSnackbarMessage messageWithText:message];
+  snackbarMessage.accessibilityLabel = message;
+  snackbarMessage.duration = 2.0;
+  snackbarMessage.category = kDefaultSnackbarCategory;
+  [MDCSnackbarManager showMessage:snackbarMessage];
+}
+
+@end
diff --git a/ios/chrome/browser/ui/snackbar/snackbar_coordinator_unittest.mm b/ios/chrome/browser/ui/snackbar/snackbar_coordinator_unittest.mm
new file mode 100644
index 0000000..a5eabce9
--- /dev/null
+++ b/ios/chrome/browser/ui/snackbar/snackbar_coordinator_unittest.mm
@@ -0,0 +1,28 @@
+// 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 "ios/chrome/browser/ui/snackbar/snackbar_coordinator.h"
+
+#import "ios/chrome/browser/ui/commands/command_dispatcher.h"
+#import "ios/chrome/browser/ui/commands/snackbar_commands.h"
+#include "testing/gtest/include/gtest/gtest.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
+
+// Tests that the coordinator handles snackbar commands.
+TEST(SnackbarCoordinatorTest, RegistersDispatching) {
+  id dispatcher = OCMClassMock([CommandDispatcher class]);
+  SnackbarCoordinator* coordinator = [[SnackbarCoordinator alloc] init];
+  coordinator.dispatcher = dispatcher;
+  [[dispatcher expect] startDispatchingToTarget:coordinator
+                                    forProtocol:@protocol(SnackbarCommands)];
+  [coordinator start];
+  EXPECT_OCMOCK_VERIFY(dispatcher);
+  EXPECT_TRUE(
+      [coordinator respondsToSelector:@selector(showSnackbarWithMessage:)]);
+}
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller_egtest.mm b/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller_egtest.mm
index 1e41651..6a47e507 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller_egtest.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller_egtest.mm
@@ -310,6 +310,10 @@
   // The TabSwitcherController is only used on iPhones.
   if (!IsIPadIdiom())
     EARL_GREY_TEST_SKIPPED(@"TabSwitcherController is only used on iPads.");
+  // TODO(crbug.com/769708): reenable on iOS11.
+  if (@available(iOS 11, *)) {
+    EARL_GREY_TEST_SKIPPED(@"Test failing on iOS11.");
+  }
 
   // Load the blank test page so that JavaScript can be executed.
   const GURL kBlankPageURL = HttpServer::MakeUrl("http://blank-page");
diff --git a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
index 97d713b4..d0bafd4a 100644
--- a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
+++ b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
@@ -2126,6 +2126,11 @@
 }
 
 - (void)fadeInOmniboxTrailingView {
+  UIView* trailingView = [_omniBox rightView];
+  trailingView.alpha = 0;
+  [_cancelButton setAlpha:0];
+  [_cancelButton setHidden:NO];
+
   // Instead of passing a delay into -fadeInView:, wait to call -fadeInView:.
   // The CABasicAnimation's start and end positions are calculated immediately
   // instead of after the animation's delay, but the omnibox's layer isn't set
@@ -2134,11 +2139,6 @@
   dispatch_time_t delay = dispatch_time(
       DISPATCH_TIME_NOW, ios::material::kDuration6 * NSEC_PER_SEC);
   dispatch_after(delay, dispatch_get_main_queue(), ^(void) {
-    UIView* trailingView = [_omniBox rightView];
-    trailingView.alpha = 0;
-    [_cancelButton setAlpha:0];
-    [_cancelButton setHidden:NO];
-
     [self fadeInView:trailingView
         fromLeadingOffset:kPositionAnimationLeadingOffset
              withDuration:ios::material::kDuration1
diff --git a/ios/chrome/browser/ui/uikit_ui_util.h b/ios/chrome/browser/ui/uikit_ui_util.h
index c90c8c20..932cccee 100644
--- a/ios/chrome/browser/ui/uikit_ui_util.h
+++ b/ios/chrome/browser/ui/uikit_ui_util.h
@@ -207,4 +207,7 @@
 void TriggerHapticFeedbackForSelectionChange();
 void TriggerHapticFeedbackForNotification(UINotificationFeedbackType type);
 
+// Returns the safeAreaInsets for a given view.
+UIEdgeInsets SafeAreaInsetsForView(UIView* view);
+
 #endif  // IOS_CHROME_BROWSER_UI_UIKIT_UI_UTIL_H_
diff --git a/ios/chrome/browser/ui/uikit_ui_util.mm b/ios/chrome/browser/ui/uikit_ui_util.mm
index 72717c59..48901d9 100644
--- a/ios/chrome/browser/ui/uikit_ui_util.mm
+++ b/ios/chrome/browser/ui/uikit_ui_util.mm
@@ -588,3 +588,11 @@
     [generator notificationOccurred:type];
   }
 }
+
+UIEdgeInsets SafeAreaInsetsForView(UIView* view) {
+  if (@available(iOS 11, *)) {
+    return view.safeAreaInsets;
+  } else {
+    return UIEdgeInsetsZero;
+  }
+}
diff --git a/ios/chrome/browser/web/sad_tab_tab_helper.h b/ios/chrome/browser/web/sad_tab_tab_helper.h
index 4aa9ed4..fec82bd 100644
--- a/ios/chrome/browser/web/sad_tab_tab_helper.h
+++ b/ios/chrome/browser/web/sad_tab_tab_helper.h
@@ -69,7 +69,6 @@
 
   // WebStateObserver:
   void WasShown() override;
-  void WasHidden() override;
   void RenderProcessGone() override;
   void DidFinishNavigation(web::NavigationContext* navigation_context) override;
   void WebStateDestroyed() override;
@@ -90,9 +89,6 @@
   // RenderProcessGone failure will be considered a repeat failure.
   double repeat_failure_interval_ = kDefaultRepeatFailureInterval;
 
-  // Whether or not WebState is currently being displayed.
-  bool is_visible_ = false;
-
   // true if the WebState needs to be reloaded after web state becomes visible.
   bool requires_reload_on_becoming_visible_ = false;
 
diff --git a/ios/chrome/browser/web/sad_tab_tab_helper.mm b/ios/chrome/browser/web/sad_tab_tab_helper.mm
index 8b47e71..2d03c232 100644
--- a/ios/chrome/browser/web/sad_tab_tab_helper.mm
+++ b/ios/chrome/browser/web/sad_tab_tab_helper.mm
@@ -73,20 +73,14 @@
 }
 
 void SadTabTabHelper::WasShown() {
-  is_visible_ = true;
-
   if (requires_reload_on_becoming_visible_) {
     ReloadTab();
     requires_reload_on_becoming_visible_ = false;
   }
 }
 
-void SadTabTabHelper::WasHidden() {
-  is_visible_ = false;
-}
-
 void SadTabTabHelper::RenderProcessGone() {
-  if (!is_visible_) {
+  if (!web_state()->IsVisible()) {
     requires_reload_on_becoming_visible_ = true;
     return;
   }
@@ -139,7 +133,7 @@
 void SadTabTabHelper::OnAppDidBecomeActive() {
   if (!requires_reload_on_becoming_active_)
     return;
-  if (is_visible_) {
+  if (web_state()->IsVisible()) {
     ReloadTab();
   } else {
     requires_reload_on_becoming_visible_ = true;
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn
index 34b55604..ee1eeb5 100644
--- a/ios/chrome/test/BUILD.gn
+++ b/ios/chrome/test/BUILD.gn
@@ -206,6 +206,7 @@
     "//ios/chrome/browser/ui/settings:unit_tests",
     "//ios/chrome/browser/ui/settings/cells:unit_tests",
     "//ios/chrome/browser/ui/side_swipe:unit_tests",
+    "//ios/chrome/browser/ui/snackbar:unit_tests",
     "//ios/chrome/browser/ui/stack_view:unit_tests",
     "//ios/chrome/browser/ui/static_content:unit_tests",
     "//ios/chrome/browser/ui/tab_switcher:unit_tests",
diff --git a/ios/chrome/test/app/chrome_test_util.mm b/ios/chrome/test/app/chrome_test_util.mm
index 1c44cbe..48b4e59 100644
--- a/ios/chrome/test/app/chrome_test_util.mm
+++ b/ios/chrome/test/app/chrome_test_util.mm
@@ -170,7 +170,8 @@
 }
 
 void ClearPresentedState() {
-  [GetMainController() dismissModalDialogsWithCompletion:nil];
+  [GetMainController() dismissModalDialogsWithCompletion:nil
+                                          dismissOmnibox:YES];
 }
 
 void SetBooleanLocalStatePref(const char* pref_name, bool value) {
diff --git a/ios/chrome/test/earl_grey/BUILD.gn b/ios/chrome/test/earl_grey/BUILD.gn
index aa53f14..4adb122 100644
--- a/ios/chrome/test/earl_grey/BUILD.gn
+++ b/ios/chrome/test/earl_grey/BUILD.gn
@@ -29,9 +29,9 @@
     "//ios/chrome/browser/metrics:eg_tests",
     "//ios/chrome/browser/net:eg_tests",
     "//ios/chrome/browser/ntp_tiles:eg_tests",
+    "//ios/chrome/browser/passwords:eg_tests",
   ]
 }
-
 chrome_ios_eg_test("ios_chrome_payments_egtests") {
   deps = [
     ":test_support",
diff --git a/ios/clean/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.mm b/ios/clean/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.mm
index 40d2d0df..f0f71162 100644
--- a/ios/clean/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.mm
+++ b/ios/clean/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.mm
@@ -122,7 +122,7 @@
 
 #pragma mark - RecentTabsHandsetViewControllerCommand
 
-- (void)dismissRecentTabs {
+- (void)dismissRecentTabsWithCompletion:(void (^)())completion {
   [self stop];
 }
 
diff --git a/ios/net/cookies/cookie_store_ios.mm b/ios/net/cookies/cookie_store_ios.mm
index a51408b9..d8e021c 100644
--- a/ios/net/cookies/cookie_store_ios.mm
+++ b/ios/net/cookies/cookie_store_ios.mm
@@ -44,6 +44,22 @@
 
 namespace {
 
+class CookieStoreIOSCookieChangedSubscription
+    : public CookieStore::CookieChangedSubscription {
+ public:
+  CookieStoreIOSCookieChangedSubscription(
+      std::unique_ptr<CookieStore::CookieChangedCallbackList::Subscription>
+          subscription)
+      : subscription_(std::move(subscription)) {}
+  ~CookieStoreIOSCookieChangedSubscription() override {}
+
+ private:
+  std::unique_ptr<CookieStore::CookieChangedCallbackList::Subscription>
+      subscription_;
+
+  DISALLOW_COPY_AND_ASSIGN(CookieStoreIOSCookieChangedSubscription);
+};
+
 #pragma mark NotificationTrampoline
 
 // NotificationTrampoline dispatches cookie notifications to all the existing
@@ -690,12 +706,12 @@
   std::pair<GURL, std::string> key(gurl, name);
   if (hook_map_.count(key) == 0) {
     UpdateCacheForCookieFromSystem(gurl, name, nullptr, nullptr);
-    if (hook_map_.count(key) == 0)
-      hook_map_[key] = base::MakeUnique<CookieChangedCallbackList>();
+    hook_map_[key] = std::make_unique<CookieChangedCallbackList>();
   }
 
   DCHECK(hook_map_.find(key) != hook_map_.end());
-  return hook_map_[key]->Add(callback);
+  return std::make_unique<CookieStoreIOSCookieChangedSubscription>(
+      hook_map_[key]->Add(callback));
 }
 
 std::unique_ptr<net::CookieStore::CookieChangedSubscription>
diff --git a/ios/net/crn_http_protocol_handler.mm b/ios/net/crn_http_protocol_handler.mm
index 03e86b2..91da5bf 100644
--- a/ios/net/crn_http_protocol_handler.mm
+++ b/ios/net/crn_http_protocol_handler.mm
@@ -500,7 +500,6 @@
 #endif  // !defined(NDEBUG)
 
   if (tracker_) {
-    tracker_->CaptureHeaders(net_request_);
     long long expectedContentLength = [response expectedContentLength];
     if (expectedContentLength > 0)
       tracker_->CaptureExpectedLength(net_request_, expectedContentLength);
diff --git a/ios/net/request_tracker.h b/ios/net/request_tracker.h
index c172fefa..e8709cf5a 100644
--- a/ios/net/request_tracker.h
+++ b/ios/net/request_tracker.h
@@ -67,9 +67,6 @@
   // Informs the tracker that a request has started.
   virtual void StartRequest(URLRequest* request) = 0;
 
-  // Informs the tracker that the headers for the request are available.
-  virtual void CaptureHeaders(URLRequest* request) = 0;
-
   // Informs the tracker the expected length of the result, if known.
   virtual void CaptureExpectedLength(const URLRequest* request,
                                      uint64_t length) = 0;
diff --git a/ios/tools/coverage/coverage.py b/ios/tools/coverage/coverage.py
index c1bdb1a..3bb3bf5d 100755
--- a/ios/tools/coverage/coverage.py
+++ b/ios/tools/coverage/coverage.py
@@ -14,17 +14,18 @@
         suggested to start with 'url_unittests'.
 
   Example usages:
-  ios/tools/coverage/coverage.py url_unittests -t url/
-  # Generate code coverage report for url_unittests for directory url/.
+  ios/tools/coverage/coverage.py url_unittests -t url/ -o out/html
+  # Generate code coverage report for url_unittests for directory url/ and all
+  # generated artifacts are stored in out/html
 
-  ios/tools/coverage/coverage.py url_unittests -t url/ -i url/third_party
-  # Only include files under url/third_party.
+  ios/tools/coverage/coverage.py url_unittests -t url/ -i url/mojo -o out/html
+  # Only include files under url/mojo.
 
-  ios/tools/coverage/coverage.py url_unittests -t url/ -i url/third_party
+  ios/tools/coverage/coverage.py url_unittests -t url/ -i url/mojo -o out/html
   -r coverage.profdata
   # Skip running tests and reuse the specified profile data file.
 
-  ios/tools/coverage/coverage.py url_unittests -t url/ -i url/third_party
+  ios/tools/coverage/coverage.py url_unittests -t url/ -i url/mojo -o out/html
   -e //url/ipc:url_ipc -r coverage.profdata
   # Exclude the 'sources' of //url/ipc:url_ipc build target.
 
@@ -224,7 +225,8 @@
     target: A string representing the name of the target to be tested.
     profdata_path: A string representing the path to the profdata file.
     file_line_coverage_report: A FileLineCoverageReport object.
-    output_dir: output directory for generated html files.
+    output_dir: output directory for generated html files, the path needs to be
+                absolute or relative to the root of checkout.
   """
   application_path = _GetApplicationBundlePath(target)
   binary_path = os.path.join(application_path, target)
@@ -236,12 +238,14 @@
   subprocess.check_call(cmd)
 
 
-def _CreateCoverageProfileDataForTarget(target, jobs_count=None,
+def _CreateCoverageProfileDataForTarget(target, output_dir, jobs_count=None,
                                         gtest_filter=None):
   """Builds and runs target to generate the coverage profile data.
 
   Args:
     target: A string representing the name of the target to be tested.
+    output_dir: A directory to store created coverage profile data file, the
+                path needs to be absolute or relative to the root of checkout.
     jobs_count: Number of jobs to run in parallel for building. If None, a
                 default value is derived based on CPUs availability.
     gtest_filter: If present, only run unit tests whose full name matches the
@@ -252,7 +256,8 @@
   """
   _BuildTargetWithCoverageConfiguration(target, jobs_count)
   profraw_path = _GetProfileRawDataPathByRunningTarget(target, gtest_filter)
-  profdata_path = _CreateCoverageProfileDataFromProfRawData(profraw_path)
+  profdata_path = _CreateCoverageProfileDataFromProfRawData(profraw_path,
+                                                            output_dir)
 
   print 'Code coverage profile data is created as: ' + profdata_path
   return profdata_path
@@ -430,12 +435,14 @@
   return ''.join(logs_chracters).split('\n')
 
 
-def _CreateCoverageProfileDataFromProfRawData(profraw_path):
+def _CreateCoverageProfileDataFromProfRawData(profraw_path, output_dir):
   """Returns the path to the profdata file by merging profraw data file.
 
   Args:
     profraw_path: A string representing the absolute path to the profraw data
                   file that is to be merged.
+    output_dir: A directory to store created coverage profile data file, the
+                path needs to be absolute or relative to the root of checkout.
 
   Returns:
     A string representing the absolute path to the generated profdata file.
@@ -445,9 +452,9 @@
   """
   print 'Creating the profile data file'
 
-  src_root = _GetSrcRootPath()
-  profdata_path = os.path.join(src_root, BUILD_DIRECTORY,
-                               PROFDATA_FILE_NAME)
+  if not os.path.exists(output_dir):
+    os.makedirs(output_dir)
+  profdata_path = os.path.join(output_dir, PROFDATA_FILE_NAME)
   try:
     cmd = ['xcrun', 'llvm-profdata', 'merge', '-o', profdata_path, profraw_path]
     subprocess.check_call(cmd)
@@ -739,10 +746,14 @@
 
   arg_parser.add_argument('-r', '--reuse-profdata', type=str,
                           help='Skip building test target and running tests '
-                               'and re-use the specified profile data file.')
+                               'and re-use the specified profile data file, '
+                               'the path needs to be absolute or relative to '
+                               'the root of checkout.')
 
   arg_parser.add_argument('-o', '--output-dir', type=str, required=True,
-                          help='Output directory for html report.')
+                          help='Output directory for generated artifacts, the'
+                               'path needs to be absolute or relative to the '
+                               'root of checkout.')
 
   arg_parser.add_argument('--gtest_filter', type=str,
                           help='Only run unit tests whose full name matches '
@@ -803,8 +814,8 @@
                                            'doesn\'t exist.').format(
                                                profdata_path)
   else:
-    profdata_path = _CreateCoverageProfileDataForTarget(target, jobs,
-                                                        args.gtest_filter)
+    profdata_path = _CreateCoverageProfileDataForTarget(target, args.output_dir,
+                                                        jobs, args.gtest_filter)
 
   print 'Generating code coverge report'
   file_line_coverage_report = _GeneratePerFileLineCoverageReport(
@@ -828,6 +839,9 @@
 
   html_index_file_path = 'file://' + os.path.abspath(
       os.path.join(args.output_dir, 'index.html'))
+  print 'index file for html report is generated as: {}'.format(
+      html_index_file_path)
+
   webbrowser.open(html_index_file_path)
 
 
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn
index bb547db..77484bf 100644
--- a/ios/web/BUILD.gn
+++ b/ios/web/BUILD.gn
@@ -99,12 +99,10 @@
     "net/cookie_notification_bridge.mm",
     "net/crw_cert_verification_controller.h",
     "net/crw_cert_verification_controller.mm",
-    "net/crw_request_tracker_delegate.h",
     "net/crw_ssl_status_updater.h",
     "net/crw_ssl_status_updater.mm",
     "net/request_group_util.h",
     "net/request_group_util.mm",
-    "net/request_tracker_data_memoizing_store.h",
     "net/request_tracker_factory_impl.h",
     "net/request_tracker_factory_impl.mm",
     "net/request_tracker_impl.h",
diff --git a/ios/web/app/web_main_loop.h b/ios/web/app/web_main_loop.h
index 89882be..ca18981 100644
--- a/ios/web/app/web_main_loop.h
+++ b/ios/web/app/web_main_loop.h
@@ -85,6 +85,7 @@
   std::unique_ptr<WebThreadImpl> main_thread_;
 
   // Members initialized in |RunMainMessageLoopParts()| ------------------------
+  std::unique_ptr<WebThreadImpl> db_thread_;
   std::unique_ptr<WebThreadImpl> io_thread_;
 
   // Members initialized in |WebThreadsStarted()| --------------------------
diff --git a/ios/web/app/web_main_loop.mm b/ios/web/app/web_main_loop.mm
index 7d9c08d..779fcbf1 100644
--- a/ios/web/app/web_main_loop.mm
+++ b/ios/web/app/web_main_loop.mm
@@ -133,13 +133,44 @@
 
   base::Thread::Options io_message_loop_options;
   io_message_loop_options.message_loop_type = base::MessageLoop::TYPE_IO;
-  io_thread_ = std::make_unique<WebThreadImpl>(WebThread::IO);
-  io_thread_->StartWithOptions(io_message_loop_options);
 
-  // Only start IO thread above as this is the only WebThread besides UI (which
-  // is the main thread).
-  static_assert(WebThread::ID_COUNT == 2, "Unhandled WebThread");
+  // Start threads in the order they occur in the WebThread::ID
+  // enumeration, except for WebThread::UI which is the main
+  // thread.
+  //
+  // Must be size_t so we can increment it.
+  for (size_t thread_id = WebThread::UI + 1; thread_id < WebThread::ID_COUNT;
+       ++thread_id) {
+    std::unique_ptr<WebThreadImpl>* thread_to_start = nullptr;
+    base::Thread::Options options;
 
+    switch (thread_id) {
+      // TODO(rohitrao): We probably do not need all of these threads.  Remove
+      // the ones that serve no purpose.  http://crbug.com/365909
+      case WebThread::DB:
+        thread_to_start = &db_thread_;
+        options.timer_slack = base::TIMER_SLACK_MAXIMUM;
+        break;
+      case WebThread::IO:
+        thread_to_start = &io_thread_;
+        options = io_message_loop_options;
+        break;
+      case WebThread::UI:
+      case WebThread::ID_COUNT:
+      default:
+        NOTREACHED();
+        break;
+    }
+
+    WebThread::ID id = static_cast<WebThread::ID>(thread_id);
+
+    if (thread_to_start) {
+      (*thread_to_start).reset(new WebThreadImpl(id));
+      (*thread_to_start)->StartWithOptions(options);
+    } else {
+      NOTREACHED();
+    }
+  }
   created_threads_ = true;
   return result_code_;
 }
@@ -176,11 +207,34 @@
 
   service_manager_context_.reset();
 
-  io_thread_.reset();
-
-  // Only stop IO thread above as this is the only WebThread besides UI (which
-  // is the main thread).
-  static_assert(WebThread::ID_COUNT == 2, "Unhandled WebThread");
+  // Must be size_t so we can subtract from it.
+  for (size_t thread_id = WebThread::ID_COUNT - 1;
+       thread_id >= (WebThread::UI + 1); --thread_id) {
+    // Find the thread object we want to stop. Looping over all valid
+    // WebThread IDs and DCHECKing on a missing case in the switch
+    // statement helps avoid a mismatch between this code and the
+    // WebThread::ID enumeration.
+    //
+    // The destruction order is the reverse order of occurrence in the
+    // WebThread::ID list. The rationale for the order is as
+    // follows (need to be filled in a bit):
+    //
+    //
+    // - (Not sure why DB stops last.)
+    switch (thread_id) {
+      case WebThread::DB:
+        db_thread_.reset();
+        break;
+      case WebThread::IO:
+        io_thread_.reset();
+        break;
+      case WebThread::UI:
+      case WebThread::ID_COUNT:
+      default:
+        NOTREACHED();
+        break;
+    }
+  }
 
   // Shutdown TaskScheduler after the other threads. Other threads such as the
   // I/O thread may need to schedule work like closing files or flushing data
diff --git a/ios/web/net/crw_request_tracker_delegate.h b/ios/web/net/crw_request_tracker_delegate.h
deleted file mode 100644
index 7ac472f..0000000
--- a/ios/web/net/crw_request_tracker_delegate.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_WEB_NET_CRW_REQUEST_TRACKER_DELEGATE_H_
-#define IOS_WEB_NET_CRW_REQUEST_TRACKER_DELEGATE_H_
-
-#include <vector>
-
-#include "net/cert/cert_status_flags.h"
-
-class GURL;
-
-namespace net {
-class HttpResponseHeaders;
-class SSLInfo;
-class X509Certificate;
-}
-
-namespace web {
-struct SSLStatus;
-}
-
-// All the methods in this protocol must be sent on the main thread.
-@protocol CRWRequestTrackerDelegate
-
-// The tracker calls this method every time there is a change in the SSL status
-// of a page. The info is whatever object was passed to TrimToURL().
-- (void)updatedSSLStatus:(const web::SSLStatus&)sslStatus
-              forPageUrl:(const GURL&)url
-                userInfo:(id)userInfo;
-
-// The tracker calls this method when it receives response headers.
-- (void)handleResponseHeaders:(net::HttpResponseHeaders*)headers
-                   requestUrl:(const GURL&)requestUrl;
-
-// Update the progress.
-- (void)updatedProgress:(float)progress;
-
-// This method is called when a certificate with an error is in use.
-- (void)certificateUsed:(net::X509Certificate*)certificate
-                forHost:(const std::string&)host
-                 status:(net::CertStatus)status;
-
-// Called when all the active allowed certificates need to be cleared. This
-// happens during the TrimToURL(), which corresponds to a navigation.
-- (void)clearCertificates;
-@end
-
-#endif  // IOS_WEB_NET_CRW_REQUEST_TRACKER_DELEGATE_H_
diff --git a/ios/web/net/request_tracker_data_memoizing_store.h b/ios/web/net/request_tracker_data_memoizing_store.h
deleted file mode 100644
index 7ec3e32..0000000
--- a/ios/web/net/request_tracker_data_memoizing_store.h
+++ /dev/null
@@ -1,182 +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 IOS_WEB_NET_REQUEST_TRACKER_DATA_MEMOIZING_STORE_H_
-#define IOS_WEB_NET_REQUEST_TRACKER_DATA_MEMOIZING_STORE_H_
-
-#include <map>
-
-#include "base/bind.h"
-#include "base/synchronization/lock.h"
-#include "ios/web/public/web_thread.h"
-
-namespace web {
-
-// RequestTrackerDataMemoizingStore is a thread-safe container that retains
-// reference counted objects that are associated with one or more request
-// trackers. Objects are identified by an int and only a single reference to a
-// given object is retained.
-template <typename T>
-class RequestTrackerDataMemoizingStore {
- public:
-  RequestTrackerDataMemoizingStore() : next_item_id_(1) {}
-
-  ~RequestTrackerDataMemoizingStore() {
-    DCHECK_EQ(0U, id_to_item_.size()) << "Failed to outlive request tracker";
-  }
-
-  // Store adds |item| to this collection, associates it with the given request
-  // tracker id and returns an opaque identifier for it. If |item| is already
-  // known, the same identifier will be returned.
-  int Store(T* item, int request_tracker_id) {
-    DCHECK(item);
-    base::AutoLock auto_lock(lock_);
-
-    int item_id = 0;
-
-    // Is this item alread known?
-    typename ReverseItemMap::iterator item_iter = item_to_id_.find(item);
-    if (item_iter == item_to_id_.end()) {
-      item_id = next_item_id_++;
-      // Use 0 as an invalid item_id value.  In the unlikely event that
-      // next_item_id_ wraps around, reset it to 1.
-      if (next_item_id_ == 0)
-        next_item_id_ = 1;
-      id_to_item_[item_id] = item;
-      item_to_id_[item] = item_id;
-    } else {
-      item_id = item_iter->second;
-    }
-
-    // Update the bidirection request_tracker_id and item_id mappings.
-    UpdateMap(&request_tracker_id_to_item_id_, request_tracker_id, item_id);
-    UpdateMap(&item_id_to_request_tracker_id_, item_id, request_tracker_id);
-
-    DCHECK(item_id);
-    return item_id;
-  }
-
-  // Retrieves a previously Stored() item, identified by |item_id|.
-  // If |item_id| is recognized, |item| will be updated and Retrieve() will
-  // return true.
-  bool Retrieve(int item_id, scoped_refptr<T>* item) {
-    base::AutoLock auto_lock(lock_);
-
-    typename ItemMap::iterator iter = id_to_item_.find(item_id);
-    if (iter == id_to_item_.end())
-      return false;
-    if (item)
-      *item = iter->second;
-    return true;
-  }
-
-  // Removes any items associtated only with |request_tracker_id|.
-  void RemoveForRequestTracker(int request_tracker_id) {
-    RemoveRequestTrackerItems(request_tracker_id);
-  }
-
- private:
-  typedef std::multimap<int, int> IDMap;
-  typedef std::map<int, scoped_refptr<T>> ItemMap;
-  typedef std::map<T*, int, typename T::LessThan> ReverseItemMap;
-
-  template <typename M>
-  struct MatchSecond {
-    explicit MatchSecond(const M& t) : value(t) {}
-
-    template <typename Pair>
-    bool operator()(const Pair& p) const {
-      return (value == p.second);
-    }
-
-    M value;
-  };
-
-  // Updates |map| to contain a key_id->value_id pair, ensuring that a duplicate
-  // pair is not added if it was already present.
-  static void UpdateMap(IDMap* map, int key_id, int value_id) {
-    auto matching_key_range = map->equal_range(key_id);
-    if (std::find_if(matching_key_range.first, matching_key_range.second,
-                     MatchSecond<int>(value_id)) == matching_key_range.second) {
-      map->insert(std::make_pair(key_id, value_id));
-    }
-  }
-
-  // Remove the item specified by |item_id| from id_to_item_ and item_to_id_.
-  // NOTE: the caller (RemoveRequestTrackerItems) must hold lock_.
-  void RemoveInternal(int item_id) {
-    typename ItemMap::iterator item_iter = id_to_item_.find(item_id);
-    DCHECK(item_iter != id_to_item_.end());
-
-    typename ReverseItemMap::iterator id_iter =
-        item_to_id_.find(item_iter->second.get());
-    DCHECK(id_iter != item_to_id_.end());
-    item_to_id_.erase(id_iter);
-
-    id_to_item_.erase(item_iter);
-  }
-
-  // Removes all the items associated with the specified request tracker from
-  // the store.
-  void RemoveRequestTrackerItems(int request_tracker_id) {
-    base::AutoLock auto_lock(lock_);
-
-    // Iterate through all the item ids for that request tracker.
-    auto request_tracker_ids =
-        request_tracker_id_to_item_id_.equal_range(request_tracker_id);
-    for (IDMap::iterator ids_iter = request_tracker_ids.first;
-         ids_iter != request_tracker_ids.second; ++ids_iter) {
-      int item_id = ids_iter->second;
-      // Find all the request trackers referring to this item id in
-      // item_id_to_request_tracker_id_, then locate the request tracker being
-      // removed within that range.
-      auto item_ids = item_id_to_request_tracker_id_.equal_range(item_id);
-      IDMap::iterator proc_iter =
-          std::find_if(item_ids.first, item_ids.second,
-                       MatchSecond<int>(request_tracker_id));
-      DCHECK(proc_iter != item_ids.second);
-
-      // Before removing, determine if no other request trackers refer to the
-      // current item id. If |proc_iter| (the current request tracker) is the
-      // lower bound of request trackers containing the current item id and if
-      // |next_proc_iter| is the upper bound (the first request tracker that
-      // does not), then only one request tracker, the one being removed, refers
-      // to the item id.
-      IDMap::iterator next_proc_iter = proc_iter;
-      ++next_proc_iter;
-      bool last_request_tracker_for_item_id =
-          (proc_iter == item_ids.first && next_proc_iter == item_ids.second);
-      item_id_to_request_tracker_id_.erase(proc_iter);
-
-      if (last_request_tracker_for_item_id) {
-        // The current item id is not referenced by any other request trackers,
-        // so remove it from id_to_item_ and item_to_id_.
-        RemoveInternal(item_id);
-      }
-    }
-    if (request_tracker_ids.first != request_tracker_ids.second)
-      request_tracker_id_to_item_id_.erase(request_tracker_ids.first,
-                                           request_tracker_ids.second);
-  }
-
-  // Bidirectional mapping between items and the request trackers they are
-  // associated with.
-  IDMap request_tracker_id_to_item_id_;
-  IDMap item_id_to_request_tracker_id_;
-  // Bidirectional mappings between items and the item-level identifiers that
-  // have been assigned to them.
-  ItemMap id_to_item_;
-  ReverseItemMap item_to_id_;
-
-  // The ID to assign to the next item stored.
-  int next_item_id_;
-
-  // This lock protects: request_tracker_id_to_item_id_,
-  // item_id_to_request_tracker_id_, id_to_item_, and item_to_id_.
-  base::Lock lock_;
-};
-
-}  // namespace web
-
-#endif  // IOS_WEB_NET_REQUEST_TRACKER_DATA_MEMOIZING_STORE_H_
diff --git a/ios/web/net/request_tracker_impl.h b/ios/web/net/request_tracker_impl.h
index c7b4321..a99443790 100644
--- a/ios/web/net/request_tracker_impl.h
+++ b/ios/web/net/request_tracker_impl.h
@@ -18,21 +18,18 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #import "ios/net/request_tracker.h"
-#import "ios/web/net/crw_request_tracker_delegate.h"
 #include "ios/web/public/web_thread.h"
+#include "net/cert/cert_status_flags.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "url/gurl.h"
 
 @class SSLCarrier;
-@class CRWSSLCarrier;
 struct TrackerCounts;
 
 namespace net {
-class HttpResponseHeaders;
 class URLRequest;
 class URLRequestContext;
 class SSLInfo;
-class X509Certificate;
 }
 
 namespace web {
@@ -116,8 +113,7 @@
   static scoped_refptr<RequestTrackerImpl> CreateTrackerForRequestGroupID(
       NSString* request_group_id,
       BrowserState* browser_state,
-      net::URLRequestContextGetter* context_getter,
-      id<CRWRequestTrackerDelegate> delegate);
+      net::URLRequestContextGetter* context_getter);
 
   // The network layer has no way to know which network request is the primary
   // one for a page load. The tab knows, either because it initiated the page
@@ -189,7 +185,6 @@
 
   // RequestTracker implementation.
   void StartRequest(net::URLRequest* request) override;
-  void CaptureHeaders(net::URLRequest* request) override;
   void CaptureExpectedLength(const net::URLRequest* request,
                              uint64_t length) override;
   void CaptureReceivedBytes(const net::URLRequest* request,
@@ -213,8 +208,7 @@
   // Private. RequestTrackerImpls are created through
   // CreateTrackerForRequestGroupID().
   RequestTrackerImpl(NSString* request_group_id,
-                     net::URLRequestContextGetter* context_getter,
-                     id<CRWRequestTrackerDelegate> delegate);
+                     net::URLRequestContextGetter* context_getter);
 
   void InitOnIOThread(
       const scoped_refptr<web::CertificatePolicyCache>& policy_cache);
@@ -242,9 +236,6 @@
   // and load progress.
   void StackNotification();
 
-  // Notify the consumer about the SSL status of this tracker's page load.
-  void SSLNotify();
-
   // If the counts is for a request currently waiting for the user to approve it
   // will reevaluate the approval.
   void EvaluateSSLCallbackForCounts(TrackerCounts* counts);
@@ -264,7 +255,6 @@
   // The URL change notification is often late, therefore the mixed content
   // status and the certificate policies may need to be recomputed.
   void RecomputeMixedContent(const TrackerCounts* split_position);
-  void RecomputeCertificatePolicy(const TrackerCounts* split_position);
 
   // Remove all finished request up to the last instance of |url|. If url is not
   // found, this will clear all the requests.
@@ -278,30 +268,6 @@
   // |load_success| indicates if the page successfully loaded.
   void StopPageLoad(const GURL& url, bool load_success);
 
-#pragma mark Private Consumer API
-  // Private methods that call into delegate methods.
-
-  // Notify* methods are posted to the UI thread by the provider API
-  // methods.
-
-  // Has the delegate handle |headers| for |request_url|.
-  void NotifyResponseHeaders(net::HttpResponseHeaders* headers,
-                             const GURL& request_url);
-
-  // Notifies the deleage of certificate use.
-  void NotifyCertificateUsed(net::X509Certificate* certificate,
-                             const std::string& host,
-                             net::CertStatus status);
-
-  // Notifies the deleate of a load completion estimate.
-  void NotifyUpdatedProgress(float estimate);
-
-  // Has the delegate clear SSL certificates.
-  void NotifyClearCertificates();
-
-  // Notifies the delegate of an SSL status update.
-  void NotifyUpdatedSSLStatus(base::scoped_nsobject<CRWSSLCarrier> carrier);
-
 #pragma mark Internal utilities for task posting
   // Posts |task| to |thread|. Must not be called from |thread|. If |thread| is
   // the IO thread, silently returns if |is_closing_| is true.
@@ -318,11 +284,6 @@
   // only from the IO thread.
   NSString* UnsafeDescription();
 
-#pragma mark Non thread-safe fields, only accessed from the main thread.
-  // The RequestTrackerImpl delegate. All changes and access to this object
-  // should be done on the main thread.
-  id<CRWRequestTrackerDelegate> delegate_;  // Weak.
-
 #pragma mark Non thread-safe fields, only accessed from the IO thread.
   // All the tracked requests for the page, indexed by net::URLRequest (Cast as
   // a void* to avoid the temptation of accessing it from the wrong thread).
diff --git a/ios/web/net/request_tracker_impl.mm b/ios/web/net/request_tracker_impl.mm
index 639100e0..9644c38 100644
--- a/ios/web/net/request_tracker_impl.mm
+++ b/ios/web/net/request_tracker_impl.mm
@@ -8,27 +8,19 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "base/bind_helpers.h"
-#include "base/containers/hash_tables.h"
-#include "base/location.h"
 #include "base/logging.h"
 #import "base/mac/bind_objc_block.h"
 #import "base/mac/scoped_nsobject.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/synchronization/lock.h"
 #include "ios/web/history_state_util.h"
-#import "ios/web/net/crw_request_tracker_delegate.h"
 #include "ios/web/public/browser_state.h"
 #include "ios/web/public/certificate_policy_cache.h"
-#include "ios/web/public/ssl_status.h"
 #include "ios/web/public/url_util.h"
 #include "ios/web/public/web_thread.h"
 #import "net/base/mac/url_conversions.h"
-#include "net/base/net_errors.h"
-#include "net/http/http_response_headers.h"
 #include "net/url_request/url_request.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -93,16 +85,6 @@
 // identifier is needed for tracker (e.g. storing certs).
 int g_next_request_tracker_id = 0;
 
-// IsIntranetHost logic and its associated kDot constant are lifted directly
-// from content/browser/ssl/ssl_policy.cc. Unfortunately that particular file
-// has way too many dependencies on content to be used on iOS.
-static const char kDot = '.';
-
-static bool IsIntranetHost(const std::string& host) {
-  const size_t dot = host.find(kDot);
-  return dot == std::string::npos || dot == host.length() - 1;
-}
-
 // Add |tracker| to |g_trackers| under |key|.
 static void RegisterTracker(web::RequestTrackerImpl* tracker, NSString* key) {
   DCHECK_CURRENTLY_ON(web::WebThread::UI);
@@ -201,131 +183,6 @@
   DISALLOW_COPY_AND_ASSIGN(TrackerCounts);
 };
 
-// A SSL carrier is used to transport SSL information to the UI via its
-// encapsulation in a block. Once the object is constructed all public methods
-// can be called from any thread safely. This object is designed so it is
-// instantiated on the IO thread but may be accessed from the UI thread.
-@interface CRWSSLCarrier : NSObject {
- @private
-  scoped_refptr<web::RequestTrackerImpl> tracker_;
-  net::SSLInfo sslInfo_;
-  GURL url_;
-  web::SSLStatus status_;
-}
-
-// Designated initializer.
-- (id)initWithTracker:(web::RequestTrackerImpl*)tracker
-               counts:(const TrackerCounts*)counts;
-// URL of the request.
-- (const GURL&)url;
-// Returns a SSLStatus representing the state of the page. This assumes the
-// target carrier is the main page request.
-- (const web::SSLStatus&)sslStatus;
-// Returns a SSLInfo with a reference to the certificate and SSL information.
-- (const net::SSLInfo&)sslInfo;
-// Internal method used to build the SSLStatus object. Called from the
-// initializer to make sure it is invoked on the network thread.
-- (void)buildSSLStatus;
-@end
-
-@implementation CRWSSLCarrier
-
-- (id)initWithTracker:(web::RequestTrackerImpl*)tracker
-               counts:(const TrackerCounts*)counts {
-  self = [super init];
-  if (self) {
-    tracker_ = tracker;
-    url_ = counts->url;
-    sslInfo_ = counts->ssl_info;
-    [self buildSSLStatus];
-  }
-  return self;
-}
-
-- (const GURL&)url {
-  return url_;
-}
-
-- (const net::SSLInfo&)sslInfo {
-  return sslInfo_;
-}
-
-- (const web::SSLStatus&)sslStatus {
-  return status_;
-}
-
-- (void)buildSSLStatus {
-  DCHECK_CURRENTLY_ON(web::WebThread::IO);
-  if (!sslInfo_.is_valid())
-    return;
-
-  status_.certificate = sslInfo_.cert;
-
-  status_.cert_status = sslInfo_.cert_status;
-  if (status_.cert_status & net::CERT_STATUS_COMMON_NAME_INVALID) {
-    // CAs issue certificates for intranet hosts to everyone.  Therefore, we
-    // mark intranet hosts as being non-unique.
-    if (IsIntranetHost(url_.host())) {
-      status_.cert_status |= net::CERT_STATUS_NON_UNIQUE_NAME;
-    }
-  }
-
-  status_.connection_status = sslInfo_.connection_status;
-
-  if (tracker_->has_mixed_content()) {
-    // TODO(noyau): In iOS there is no notion of resource type. The insecure
-    // content could be an image (DISPLAYED_INSECURE_CONTENT) or a script
-    // (RAN_INSECURE_CONTENT). The status of the page is different for both, but
-    // there is not enough information from UIWebView to differentiate the two
-    // cases.
-    status_.content_status = web::SSLStatus::DISPLAYED_INSECURE_CONTENT;
-  } else {
-    status_.content_status = web::SSLStatus::NORMAL_CONTENT;
-  }
-
-  if (!url_.SchemeIsCryptographic()) {
-    // Should not happen as the sslInfo is valid.
-    NOTREACHED();
-    status_.security_style = web::SECURITY_STYLE_UNAUTHENTICATED;
-  } else if (net::IsCertStatusError(status_.cert_status) &&
-             !net::IsCertStatusMinorError(status_.cert_status)) {
-    // Minor errors don't lower the security style to
-    // SECURITY_STYLE_AUTHENTICATION_BROKEN.
-    status_.security_style = web::SECURITY_STYLE_AUTHENTICATION_BROKEN;
-  } else {
-    // This page is secure.
-    status_.security_style = web::SECURITY_STYLE_AUTHENTICATED;
-  }
-}
-
-- (NSString*)description {
-  NSString* sslInfo = @"";
-  if (sslInfo_.is_valid()) {
-    switch (status_.security_style) {
-      case web::SECURITY_STYLE_UNKNOWN:
-      case web::SECURITY_STYLE_UNAUTHENTICATED:
-        sslInfo = @"Unexpected SSL state ";
-        break;
-      case web::SECURITY_STYLE_AUTHENTICATION_BROKEN:
-        sslInfo = @"Not secure ";
-        break;
-      case web::SECURITY_STYLE_AUTHENTICATED:
-        if (status_.content_status ==
-            web::SSLStatus::DISPLAYED_INSECURE_CONTENT)
-          sslInfo = @"Mixed ";
-        else
-          sslInfo = @"Secure ";
-        break;
-    }
-  }
-
-  NSURL* url = net::NSURLWithGURL(url_);
-
-  return [NSString stringWithFormat:@"<%@%@>", sslInfo, url];
-}
-
-@end
-
 namespace web {
 
 #pragma mark Consumer API
@@ -335,13 +192,12 @@
 RequestTrackerImpl::CreateTrackerForRequestGroupID(
     NSString* request_group_id,
     BrowserState* browser_state,
-    net::URLRequestContextGetter* context_getter,
-    id<CRWRequestTrackerDelegate> delegate) {
+    net::URLRequestContextGetter* context_getter) {
   DCHECK_CURRENTLY_ON(web::WebThread::UI);
   DCHECK(request_group_id);
 
   scoped_refptr<RequestTrackerImpl> tracker =
-      new RequestTrackerImpl(request_group_id, context_getter, delegate);
+      new RequestTrackerImpl(request_group_id, context_getter);
 
   scoped_refptr<CertificatePolicyCache> policy_cache =
       BrowserState::GetCertificatePolicyCache(browser_state);
@@ -394,8 +250,6 @@
                                },
                                base::RetainedRef(this)));
 
-  // Disable the delegate.
-  delegate_ = nil;
   // The user_info is no longer needed.
   user_info_.reset();
 }
@@ -492,21 +346,6 @@
   Notify();
 }
 
-void RequestTrackerImpl::CaptureHeaders(net::URLRequest* request) {
-  DCHECK_CURRENTLY_ON(web::WebThread::IO);
-  if (is_closing_)
-    return;
-
-  if (!request->response_headers())
-    return;
-
-  scoped_refptr<net::HttpResponseHeaders> headers(request->response_headers());
-  web::WebThread::PostTask(
-      web::WebThread::UI, FROM_HERE,
-      base::Bind(&RequestTrackerImpl::NotifyResponseHeaders, this,
-                 base::RetainedRef(headers), request->url()));
-}
-
 void RequestTrackerImpl::CaptureExpectedLength(const net::URLRequest* request,
                                                uint64_t length) {
   DCHECK_CURRENTLY_ON(web::WebThread::IO);
@@ -581,18 +420,6 @@
 
   // Notify the  delegate that a judgment has been used.
   DCHECK(judgment == CertPolicy::ALLOWED);
-  if (counts_by_request_.count(request)) {
-    const net::SSLInfo& ssl_info = request->ssl_info();
-    TrackerCounts* counts = counts_by_request_[request];
-    counts->allowed_by_user = true;
-    if (ssl_info.is_valid())
-      counts->ssl_info = ssl_info;
-    web::WebThread::PostTask(
-        web::WebThread::UI, FROM_HERE,
-        base::Bind(&RequestTrackerImpl::NotifyCertificateUsed, this,
-                   base::RetainedRef(ssl_info.cert), host,
-                   ssl_info.cert_status));
-  }
   should_continue.Run(true);
 }
 
@@ -647,10 +474,8 @@
 
 RequestTrackerImpl::RequestTrackerImpl(
     NSString* request_group_id,
-    net::URLRequestContextGetter* context_getter,
-    id<CRWRequestTrackerDelegate> delegate)
-    : delegate_(delegate),
-      previous_estimate_(0.0f),  // Not active by default.
+    net::URLRequestContextGetter* context_getter)
+    : previous_estimate_(0.0f),  // Not active by default.
       estimate_start_index_(0),
       notification_depth_(0),
       has_mixed_content_(false),
@@ -735,80 +560,6 @@
   --notification_depth_;
   if (notification_depth_)
     return;
-
-  SSLNotify();
-  if (is_loading_) {
-    float estimate = EstimatedProgress();
-    if (estimate != -1.0f) {
-      web::WebThread::PostTask(
-          web::WebThread::UI, FROM_HERE,
-          base::Bind(&RequestTrackerImpl::NotifyUpdatedProgress, this,
-                     estimate));
-    }
-  }
-}
-
-void RequestTrackerImpl::SSLNotify() {
-  DCHECK_CURRENTLY_ON(web::WebThread::IO);
-  if (is_closing_)
-    return;
-
-  if (counts_.empty())
-    return;  // Nothing yet to notify.
-
-  if (!page_url_.SchemeIsCryptographic())
-    return;
-
-  const GURL page_origin = page_url_.GetOrigin();
-  for (const auto& tracker_count : counts_) {
-    if (!tracker_count->ssl_info.is_valid())
-      continue;  // No SSL info at this point in time on this tracker.
-
-    GURL request_origin = tracker_count->url.GetOrigin();
-    if (request_origin != page_origin)
-      continue;  // Not interesting in the context of the page.
-
-    base::scoped_nsobject<CRWSSLCarrier> carrier([[CRWSSLCarrier alloc]
-        initWithTracker:this
-                 counts:tracker_count.get()]);
-    web::WebThread::PostTask(
-        web::WebThread::UI, FROM_HERE,
-        base::Bind(&RequestTrackerImpl::NotifyUpdatedSSLStatus, this, carrier));
-    break;
-  }
-}
-
-void RequestTrackerImpl::NotifyResponseHeaders(
-    net::HttpResponseHeaders* headers,
-    const GURL& request_url) {
-  DCHECK_CURRENTLY_ON(web::WebThread::UI);
-  [delegate_ handleResponseHeaders:headers requestUrl:request_url];
-}
-
-void RequestTrackerImpl::NotifyCertificateUsed(
-    net::X509Certificate* certificate,
-    const std::string& host,
-    net::CertStatus status) {
-  DCHECK_CURRENTLY_ON(web::WebThread::UI);
-  [delegate_ certificateUsed:certificate forHost:host status:status];
-}
-
-void RequestTrackerImpl::NotifyUpdatedProgress(float estimate) {
-  DCHECK_CURRENTLY_ON(web::WebThread::UI);
-  [delegate_ updatedProgress:estimate];
-}
-
-void RequestTrackerImpl::NotifyClearCertificates() {
-  DCHECK_CURRENTLY_ON(web::WebThread::UI);
-  [delegate_ clearCertificates];
-}
-
-void RequestTrackerImpl::NotifyUpdatedSSLStatus(
-    base::scoped_nsobject<CRWSSLCarrier> carrier) {
-  DCHECK_CURRENTLY_ON(web::WebThread::UI);
-  [delegate_ updatedSSLStatus:[carrier sslStatus]
-                   forPageUrl:[carrier url]
-                     userInfo:user_info_];
 }
 
 void RequestTrackerImpl::EvaluateSSLCallbackForCounts(TrackerCounts* counts) {
@@ -1033,34 +784,10 @@
       // Resend a notification for the |page_url_| informing the upper layer
       // that the mixed content was a red herring.
       has_mixed_content_ = false;
-      SSLNotify();
     }
   }
 }
 
-void RequestTrackerImpl::RecomputeCertificatePolicy(
-    const TrackerCounts* splitPosition) {
-  DCHECK_CURRENTLY_ON(web::WebThread::IO);
-  // Clear the judgments for the old URL.
-  web::WebThread::PostTask(
-      web::WebThread::UI, FROM_HERE,
-      base::Bind(&RequestTrackerImpl::NotifyClearCertificates, this));
-  // Report judgements for the new URL.
-  for (auto it = counts_.rbegin(); it != counts_.rend(); ++it) {
-    TrackerCounts* counts = it->get();
-    if (counts->allowed_by_user) {
-      std::string host = counts->url.host();
-      web::WebThread::PostTask(
-          web::WebThread::UI, FROM_HERE,
-          base::Bind(&RequestTrackerImpl::NotifyCertificateUsed, this,
-                     base::RetainedRef(counts->ssl_info.cert), host,
-                     counts->ssl_info.cert_status));
-    }
-    if (counts == splitPosition)
-      break;
-  }
-}
-
 void RequestTrackerImpl::HistoryStateChangeToURL(const GURL& full_url) {
   DCHECK_CURRENTLY_ON(web::WebThread::IO);
   GURL url = GURLByRemovingRefFromGURL(full_url);
@@ -1113,7 +840,6 @@
     }
   }
   RecomputeMixedContent(split_position);
-  RecomputeCertificatePolicy(split_position);
 
   // Trim up to that element.
   auto it = counts_.begin();
diff --git a/ios/web/net/request_tracker_impl_unittest.mm b/ios/web/net/request_tracker_impl_unittest.mm
index 7e9a741..e0893bc 100644
--- a/ios/web/net/request_tracker_impl_unittest.mm
+++ b/ios/web/net/request_tracker_impl_unittest.mm
@@ -40,8 +40,7 @@
 #error "This file requires ARC support."
 #endif
 
-@interface RequestTrackerNotificationReceiverTest
-    : NSObject<CRWRequestTrackerDelegate> {
+@interface RequestTrackerNotificationReceiverTest : NSObject {
  @public
   float value_;
   float max_;
@@ -65,50 +64,14 @@
   return self;
 }
 
-- (void)updatedProgress:(float)progress {
-  if (progress > 0.0f) {
-    if (progress < value_) {
-      error_ = [NSString
-          stringWithFormat:@"going down from %f to %f", value_, progress];
-    }
-    value_ = progress;
-  } else {
-    value_ = 0.0f;
-  }
-  if (value_ > max_) {
-    max_ = value_;
-  }
-}
-
 - (NSString*)error {
   return error_;
 }
 
-- (void)handleResponseHeaders:(net::HttpResponseHeaders*)headers
-                   requestUrl:(const GURL&)requestUrl {
-  headers_ = headers;
-}
-
 - (net::HttpResponseHeaders*)headers {
   return headers_.get();
 }
 
-- (void)updatedSSLStatus:(const web::SSLStatus&)sslStatus
-              forPageUrl:(const GURL&)url
-                userInfo:(id)userInfo {
-  // Nothing. yet.
-}
-
-- (void)certificateUsed:(net::X509Certificate*)certificate
-                forHost:(const std::string&)host
-                 status:(net::CertStatus)status {
-  // Nothing, yet.
-}
-
-- (void)clearCertificates {
-  // Nothing, yet.
-}
-
 @end
 
 namespace {
@@ -142,12 +105,8 @@
     DCHECK_CURRENTLY_ON(web::WebThread::UI);
     request_group_id_ = [NSString stringWithFormat:@"test%d", g_count++];
 
-    receiver_ = [[RequestTrackerNotificationReceiverTest alloc] init];
     tracker_ = web::RequestTrackerImpl::CreateTrackerForRequestGroupID(
-        request_group_id_,
-        &browser_state_,
-        browser_state_.GetRequestContext(),
-        receiver_);
+        request_group_id_, &browser_state_, browser_state_.GetRequestContext());
   }
 
   void TearDown() override {
@@ -159,7 +118,6 @@
   web::TestWebThread ui_thread_;
   web::TestWebThread io_thread_;
 
-  RequestTrackerNotificationReceiverTest* receiver_;
   scoped_refptr<web::RequestTrackerImpl> tracker_;
   NSString* request_group_id_;
   web::TestBrowserState browser_state_;
@@ -193,8 +151,6 @@
     DCHECK_CURRENTLY_ON(web::WebThread::UI);
     base::Time maxDate = base::Time::Now() + base::TimeDelta::FromSeconds(10);
     while (!condition()) {
-      if ([receiver_ error])
-        return [receiver_ error];
       if (base::Time::Now() > maxDate)
         return @"Time is up, too slow to go";
       base::RunLoop().RunUntilIdle();
@@ -203,28 +159,14 @@
     return nil;
   }
 
-  NSString* CheckActive() {
-    NSString* message = WaitUntilLoop(^{
-      return (receiver_->value_ > 0.0f);
-    });
-
-    if (!message && (receiver_->max_ == 0.0f))
-      message = @"Max should be greater than 0.0";
-    return message;
-  }
-
   void TrimRequest(NSString* tab_id, const GURL& url) {
     DCHECK_CURRENTLY_ON(web::WebThread::UI);
-    receiver_->value_ = 0.0f;
-    receiver_->max_ = 0.0f;
     tracker_->StartPageLoad(url, nil);
   }
 
   void EndPage(NSString* tab_id, const GURL& url) {
     DCHECK_CURRENTLY_ON(web::WebThread::UI);
     tracker_->FinishPageLoad(url, false);
-    receiver_->value_ = 0.0f;
-    receiver_->max_ = 0.0f;
     base::RunLoop().RunUntilIdle();
   }
 
@@ -276,7 +218,6 @@
   tracker_->StartRequest(GetRequest(0));
   // Start page load.
   TrimRequest(request_group_id_, GetURL(0));
-  EXPECT_NSEQ(nil, CheckActive());
 
   // Stop the request.
   tracker_->StopRequest(GetRequest(0));
@@ -293,7 +234,6 @@
   // Start a request.
   tracker_->StartRequest(request);
   tracker_->CaptureReceivedBytes(request, 42);
-  EXPECT_NSEQ(nil, CheckActive());
 
   // Stop the request.
   tracker_->StopRequest(request);
@@ -307,18 +247,14 @@
   // Start two requests.
   tracker_->StartRequest(GetRequest(0));
   tracker_->StartRequest(GetRequest(1));
-  EXPECT_NSEQ(nil, CheckActive());
 
   tracker_->StopRequest(GetRequest(0));
   tracker_->StartRequest(GetRequest(2));
-  EXPECT_NSEQ(nil, CheckActive());
   tracker_->StopRequest(GetRequest(1));
   tracker_->StartRequest(GetRequest(3));
-  EXPECT_NSEQ(nil, CheckActive());
 
   tracker_->StopRequest(GetRequest(2));
   tracker_->StartRequest(GetRequest(4));
-  EXPECT_NSEQ(nil, CheckActive());
 
   tracker_->StopRequest(GetRequest(3));
   tracker_->StopRequest(GetRequest(4));
@@ -331,7 +267,6 @@
   tracker_->StartRequest(GetRequest(0));
   tracker_->StopRequest(GetRequest(0));
   tracker_->StartRequest(GetRequest(1));
-  EXPECT_NSEQ(nil, CheckActive());
 
   tracker_->CaptureReceivedBytes(GetRequest(1), 10);
   tracker_->CaptureExpectedLength(GetRequest(1), 100);
@@ -339,7 +274,6 @@
   tracker_->CaptureReceivedBytes(GetRequest(1), 10);
   tracker_->CaptureReceivedBytes(GetRequest(1), 10);
   tracker_->CaptureReceivedBytes(GetRequest(1), 10);
-  EXPECT_NSEQ(nil, CheckActive());
 
   tracker_->CaptureReceivedBytes(GetRequest(1), 10);
   tracker_->CaptureReceivedBytes(GetRequest(1), 10);
@@ -354,10 +288,8 @@
   tracker_->StartRequest(GetRequest(0));
 
   TrimRequest(request_group_id_, GetURL(0));
-  EXPECT_NSEQ(nil, CheckActive());
   tracker_->StartRequest(GetRequest(1));
   tracker_->StartRequest(GetRequest(2));
-  EXPECT_NSEQ(nil, CheckActive());
 
   tracker_->StopRequest(GetRequest(0));
   tracker_->StopRequest(GetRequest(1));
@@ -367,7 +299,6 @@
   tracker_->StartRequest(GetRequest(3));
 
   TrimRequest(request_group_id_, GetURL(3));
-  EXPECT_NSEQ(nil, CheckActive());
 
   tracker_->StopRequest(GetRequest(3));
   EndPage(request_group_id_, GetURL(3));
@@ -377,10 +308,8 @@
   tracker_->StartRequest(GetRequest(0));
 
   TrimRequest(request_group_id_, GetURL(0));
-  EXPECT_NSEQ(nil, CheckActive());
   tracker_->StartRequest(GetRequest(1));
   tracker_->StartRequest(GetRequest(2));
-  EXPECT_NSEQ(nil, CheckActive());
 
   tracker_->StopRequest(GetRequest(0));
   tracker_->StopRequest(GetRequest(1));
@@ -397,58 +326,21 @@
   tracker_->StartRequest(GetRequest(0));
 
   TrimRequest(request_group_id_, GetURL(0));
-  EXPECT_NSEQ(nil, CheckActive());
   tracker_->StartRequest(GetRequest(1));
   tracker_->StartRequest(GetRequest(2));
-  EXPECT_NSEQ(nil, CheckActive());
 
   tracker_->StopRequest(GetRequest(0));
   tracker_->StopRequest(GetRequest(1));
   tracker_->StopRequest(GetRequest(2));
-  EXPECT_NSEQ(nil, CheckActive());
 
   TrimRequest(request_group_id_, GetURL(3));
   tracker_->StartRequest(GetRequest(3));
-  EXPECT_NSEQ(nil, CheckActive());
 
   tracker_->StopRequest(GetRequest(3));
-  EXPECT_NSEQ(nil, CheckActive());
 
   EndPage(request_group_id_, GetURL(3));
 }
 
-TEST_F(RequestTrackerTest, CaptureHeaders) {
-  std::string headers =
-      "HTTP/1.1 200 OK\n"
-      "content-type: multipart/mixed; boundary=inner\n"
-      "content-disposition: attachment; filename=\"name.pdf\"\n"
-      "X-Auto-Login: Hello World\n\n";
-  for (size_t i = 0; i < headers.length(); i++) {
-    if (headers.data()[i] == '\n')
-      const_cast<char*>(headers.data())[i] = '\0';
-  }
-  net::URLRequest* request = GetRequest(0);
-  // TODO(mmenke):  This is really bizarre. Do something more reasonable.
-  const_cast<net::HttpResponseInfo&>(request->response_info()).headers =
-      new net::HttpResponseHeaders(headers);
-  std::unique_ptr<net::URLRequestTestJob> job(new net::URLRequestTestJob(
-      request, request->context()->network_delegate(), headers, "", false));
-  AddInterceptorToRequest(0)->set_main_intercept_job(std::move(job));
-  request->Start();
-
-  tracker_->StartRequest(request);
-  tracker_->CaptureHeaders(request);
-  tracker_->StopRequest(request);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE([receiver_ headers]->HasHeaderValue("X-Auto-Login",
-                                                  "Hello World"));
-  std::string mimeType;
-  EXPECT_TRUE([receiver_ headers]->GetMimeType(&mimeType));
-  EXPECT_EQ("multipart/mixed", mimeType);
-  EXPECT_TRUE([receiver_ headers]->HasHeaderValue(
-      "Content-Disposition", "attachment; filename=\"name.pdf\""));
-}
-
 // Do-nothing mock CertificatePolicyCache. Allows all certs for all hosts.
 class MockCertificatePolicyCache : public web::CertificatePolicyCache {
  public:
diff --git a/ios/web/public/test/test_web_thread_bundle.h b/ios/web/public/test/test_web_thread_bundle.h
index 11173102..1785dd7 100644
--- a/ios/web/public/test/test_web_thread_bundle.h
+++ b/ios/web/public/test/test_web_thread_bundle.h
@@ -49,7 +49,8 @@
   enum Options {
     DEFAULT = 0,
     IO_MAINLOOP = 1 << 0,
-    REAL_IO_THREAD = 1 << 1,
+    REAL_DB_THREAD = 1 << 1,
+    REAL_IO_THREAD = 1 << 2,
   };
 
   TestWebThreadBundle();
@@ -62,6 +63,7 @@
 
   std::unique_ptr<base::test::ScopedTaskEnvironment> scoped_task_environment_;
   std::unique_ptr<TestWebThread> ui_thread_;
+  std::unique_ptr<TestWebThread> db_thread_;
   std::unique_ptr<TestWebThread> io_thread_;
 
   DISALLOW_COPY_AND_ASSIGN(TestWebThreadBundle);
diff --git a/ios/web/public/web_thread.h b/ios/web/public/web_thread.h
index 60c2642..c2b8684 100644
--- a/ios/web/public/web_thread.h
+++ b/ios/web/public/web_thread.h
@@ -65,6 +65,9 @@
     // The main thread in the browser.
     UI,
 
+    // This is the thread that interacts with the database.
+    DB,
+
     // This is the thread that processes non-blocking IO, i.e. IPC and network.
     // Blocking IO should happen in TaskScheduler.
     IO,
@@ -202,6 +205,7 @@
   // std::unique_ptr<Foo, web::WebThread::DeleteOnIOThread> ptr;
   struct DeleteOnUIThread : public DeleteOnThread<UI> {};
   struct DeleteOnIOThread : public DeleteOnThread<IO> {};
+  struct DeleteOnDBThread : public DeleteOnThread<DB> {};
 
  private:
   friend class WebThreadImpl;
diff --git a/ios/web/test/test_web_thread_bundle.cc b/ios/web/test/test_web_thread_bundle.cc
index 22883ff..0a36aa9 100644
--- a/ios/web/test/test_web_thread_bundle.cc
+++ b/ios/web/test/test_web_thread_bundle.cc
@@ -36,6 +36,8 @@
   base::RunLoop().RunUntilIdle();
   io_thread_.reset();
   base::RunLoop().RunUntilIdle();
+  db_thread_.reset();
+  base::RunLoop().RunUntilIdle();
   // This is the point at which the cache pool is normally shut down. So flush
   // it again in case any shutdown tasks have been posted to the pool from the
   // threads above.
@@ -57,6 +59,14 @@
   ui_thread_.reset(
       new TestWebThread(WebThread::UI, base::MessageLoop::current()));
 
+  if (options & TestWebThreadBundle::REAL_DB_THREAD) {
+    db_thread_.reset(new TestWebThread(WebThread::DB));
+    db_thread_->Start();
+  } else {
+    db_thread_.reset(
+        new TestWebThread(WebThread::DB, base::MessageLoop::current()));
+  }
+
   if (options & TestWebThreadBundle::REAL_IO_THREAD) {
     io_thread_.reset(new TestWebThread(WebThread::IO));
     io_thread_->StartIOThread();
diff --git a/ios/web/web_state/js/context_menu_js_unittest.mm b/ios/web/web_state/js/context_menu_js_unittest.mm
index 44f0203..9810640 100644
--- a/ios/web/web_state/js/context_menu_js_unittest.mm
+++ b/ios/web/web_state/js/context_menu_js_unittest.mm
@@ -240,6 +240,7 @@
 
   // Load the invalid meta tag
   LoadHtml(kInvalidReferrerTag);
+  ExecuteJavaScript(@"document.getElementsByTagName('img')");  // Force layout
   id result = ExecuteGetElementFromPointJavaScript(20, 20);
   ASSERT_TRUE([result isKindOfClass:[NSDictionary class]]);
   EXPECT_NSEQ(@"never", result[kContextMenuElementReferrerPolicy]);
diff --git a/ios/web/web_state/ui/crw_web_controller.h b/ios/web/web_state/ui/crw_web_controller.h
index 6050fd63..72c239e 100644
--- a/ios/web/web_state/ui/crw_web_controller.h
+++ b/ios/web/web_state/ui/crw_web_controller.h
@@ -7,7 +7,6 @@
 
 #import <UIKit/UIKit.h>
 
-#import "ios/web/net/crw_request_tracker_delegate.h"
 #import "ios/web/public/web_state/js/crw_js_injection_evaluator.h"
 #import "ios/web/public/web_state/ui/crw_web_delegate.h"
 #include "ios/web/public/web_state/url_verification_constants.h"
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index e68d1fd9..f6a9d36 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -36,7 +36,6 @@
 #include "base/time/time.h"
 #include "base/values.h"
 #import "ios/net/http_response_headers_util.h"
-#import "ios/net/nsurlrequest_util.h"
 #include "ios/web/history_state_util.h"
 #import "ios/web/interstitials/web_interstitial_impl.h"
 #import "ios/web/navigation/crw_placeholder_navigation_info.h"
diff --git a/ios/web/web_thread_impl.cc b/ios/web/web_thread_impl.cc
index a5175f9..d42f6a7f 100644
--- a/ios/web/web_thread_impl.cc
+++ b/ios/web/web_thread_impl.cc
@@ -26,6 +26,7 @@
 // Friendly names for the well-known threads.
 const char* const g_web_thread_names[WebThread::ID_COUNT] = {
     "Web_UIThread",                // UI
+    "Web_DBThread",                // DB
     "Web_IOThread",                // IO
 };
 
@@ -148,6 +149,12 @@
   CHECK_GT(line_number, 0);
 }
 
+NOINLINE void WebThreadImpl::DBThreadRun(base::RunLoop* run_loop) {
+  volatile int line_number = __LINE__;
+  Thread::Run(run_loop);
+  CHECK_GT(line_number, 0);
+}
+
 NOINLINE void WebThreadImpl::IOThreadRun(base::RunLoop* run_loop) {
   volatile int line_number = __LINE__;
   Thread::Run(run_loop);
@@ -162,6 +169,8 @@
   switch (thread_id) {
     case WebThread::UI:
       return UIThreadRun(run_loop);
+    case WebThread::DB:
+      return DBThreadRun(run_loop);
     case WebThread::IO:
       return IOThreadRun(run_loop);
     case WebThread::ID_COUNT:
diff --git a/ios/web/web_thread_impl.h b/ios/web/web_thread_impl.h
index 002f3ba6..ee383766 100644
--- a/ios/web/web_thread_impl.h
+++ b/ios/web/web_thread_impl.h
@@ -39,6 +39,7 @@
   // 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 DBThreadRun(base::RunLoop* run_loop);
   void IOThreadRun(base::RunLoop* run_loop);
 
   static bool PostTaskHelper(WebThread::ID identifier,
diff --git a/mash/BUILD.gn b/mash/BUILD.gn
index cbbfaa2c..f2c43c5b 100644
--- a/mash/BUILD.gn
+++ b/mash/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/config/nacl/config.gni")
+import("//components/nacl/features.gni")
 import("//services/catalog/public/tools/catalog.gni")
 import("//services/service_manager/public/service_manifest.gni")
 import("//testing/test.gni")
diff --git a/mash/quick_launch/manifest.json b/mash/quick_launch/manifest.json
index d379543..8dfbf4a 100644
--- a/mash/quick_launch/manifest.json
+++ b/mash/quick_launch/manifest.json
@@ -1,6 +1,7 @@
 {
   "name": "quick_launch",
   "display_name": "Quick Launch Bar",
+  "sandbox_type": "none",
   "interface_provider_specs": {
     "service_manager:connector": {
       "provides": { "mash:launchable": [ "mash::mojom::Launchable" ] },
diff --git a/mash/quick_launch/public/interfaces/BUILD.gn b/mash/quick_launch/public/interfaces/BUILD.gn
index b1ea7722..90cfa94e 100644
--- a/mash/quick_launch/public/interfaces/BUILD.gn
+++ b/mash/quick_launch/public/interfaces/BUILD.gn
@@ -5,7 +5,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 group("interfaces") {
-  deps = [
+  public_deps = [
     ":constants",
   ]
 }
diff --git a/media/audio/cras/audio_manager_cras.cc b/media/audio/cras/audio_manager_cras.cc
index 8f0edb9..3221531 100644
--- a/media/audio/cras/audio_manager_cras.cc
+++ b/media/audio/cras/audio_manager_cras.cc
@@ -204,7 +204,7 @@
 
   uint64_t device_id = 0;
   if (input_device_id == AudioDeviceDescription::kDefaultDeviceId) {
-    device_id = GetPrimaryActiveInputNode();
+    return AudioDeviceDescription::kDefaultDeviceId;
   } else {
     // At this point, we know we have an ordinary input device id, so we parse
     // the string for its device_id.
diff --git a/media/base/android_overlay_mojo_factory.h b/media/base/android_overlay_mojo_factory.h
index eddf7820..5457c19 100644
--- a/media/base/android_overlay_mojo_factory.h
+++ b/media/base/android_overlay_mojo_factory.h
@@ -10,11 +10,18 @@
 #include "base/unguessable_token.h"
 #include "media/base/android_overlay_config.h"
 
+namespace service_manager {
+class ServiceContextRef;
+}
+
 namespace media {
 
 // Note that this compiles on non-android too.
-using AndroidOverlayMojoFactoryCB = base::RepeatingCallback<std::unique_ptr<
-    AndroidOverlay>(const base::UnguessableToken&, AndroidOverlayConfig)>;
+using AndroidOverlayMojoFactoryCB =
+    base::RepeatingCallback<std::unique_ptr<AndroidOverlay>(
+        std::unique_ptr<service_manager::ServiceContextRef>,
+        const base::UnguessableToken&,
+        AndroidOverlayConfig)>;
 
 }  // namespace media
 
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index 0856afd0d..0d8c66f 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -356,4 +356,8 @@
 const base::Feature kOverflowIconsForMediaControls{
     "OverflowIconsForMediaControls", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Enables the new redesigned media controls.
+const base::Feature kUseModernMediaControls{"UseModernMediaControls",
+                                            base::FEATURE_DISABLED_BY_DEFAULT};
+
 }  // namespace media
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index 81c2417..92cff87 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -131,6 +131,7 @@
 MEDIA_EXPORT extern const base::Feature kVideoBlitColorAccuracy;
 MEDIA_EXPORT extern const base::Feature kVideoColorManagement;
 MEDIA_EXPORT extern const base::Feature kUseSurfaceLayerForVideo;
+MEDIA_EXPORT extern const base::Feature kUseModernMediaControls;
 
 #if defined(OS_ANDROID)
 MEDIA_EXPORT extern const base::Feature kVideoFullscreenOrientationLock;
diff --git a/media/base/test_helpers.h b/media/base/test_helpers.h
index 7587730..4bfb291 100644
--- a/media/base/test_helpers.h
+++ b/media/base/test_helpers.h
@@ -353,6 +353,11 @@
                                   base::IntToString(splice_time_us));
 }
 
+MATCHER_P(BufferingByPtsDts, by_pts_bool, "") {
+  return CONTAINS_STRING(arg, std::string("ChunkDemuxer: buffering by ") +
+                                  (by_pts_bool ? "PTS" : "DTS"));
+}
+
 }  // namespace media
 
 #endif  // MEDIA_BASE_TEST_HELPERS_H_
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc
index 30934d06..26ebed7 100644
--- a/media/blink/webmediaplayer_impl.cc
+++ b/media/blink/webmediaplayer_impl.cc
@@ -652,6 +652,8 @@
 
 void WebMediaPlayerImpl::DoSeek(base::TimeDelta time, bool time_updated) {
   DCHECK(main_task_runner_->BelongsToCurrentThread());
+  TRACE_EVENT1("media", "WebMediaPlayerImpl::DoSeek", "target",
+               time.InSecondsF());
 
 #if defined(OS_ANDROID)  // WMPI_CAST
   if (IsRemote()) {
@@ -1301,6 +1303,8 @@
 }
 
 void WebMediaPlayerImpl::OnPipelineSeeked(bool time_updated) {
+  TRACE_EVENT1("media", "WebMediaPlayerImpl::OnPipelineSeeked", "target",
+               seek_time_.InSecondsF());
   seeking_ = false;
   seek_time_ = base::TimeDelta();
 
@@ -1443,6 +1447,7 @@
 }
 
 void WebMediaPlayerImpl::OnEnded() {
+  TRACE_EVENT1("media", "WebMediaPlayerImpl::OnEnded", "duration", Duration());
   DVLOG(1) << __func__;
   DCHECK(main_task_runner_->BelongsToCurrentThread());
 
diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc
index 6f25524..d72f99a 100644
--- a/media/filters/chunk_demuxer.cc
+++ b/media/filters/chunk_demuxer.cc
@@ -468,6 +468,9 @@
       buffering_by_pts_(base::FeatureList::IsEnabled(kMseBufferByPts)) {
   DCHECK(!open_cb_.is_null());
   DCHECK(!encrypted_media_init_data_cb_.is_null());
+  MEDIA_LOG(INFO, media_log_)
+      << GetDisplayName()
+      << (buffering_by_pts_ ? ": buffering by PTS" : ": buffering by DTS");
 }
 
 std::string ChunkDemuxer::GetDisplayName() const {
diff --git a/media/filters/chunk_demuxer_unittest.cc b/media/filters/chunk_demuxer_unittest.cc
index 2b99249..c3dcf5a 100644
--- a/media/filters/chunk_demuxer_unittest.cc
+++ b/media/filters/chunk_demuxer_unittest.cc
@@ -215,6 +215,8 @@
         base::Bind(&ChunkDemuxerTest::OnProgress, base::Unretained(this));
     Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb = base::Bind(
         &ChunkDemuxerTest::OnEncryptedMediaInitData, base::Unretained(this));
+    EXPECT_MEDIA_LOG(
+        BufferingByPtsDts(buffering_api_ == BufferingApi::kNewByPts));
     demuxer_.reset(new ChunkDemuxer(open_cb, progress_cb,
                                     encrypted_media_init_data_cb, &media_log_));
   }
diff --git a/media/formats/mp2t/descriptors.cc b/media/formats/mp2t/descriptors.cc
index ecfee575..859ec84d4 100644
--- a/media/formats/mp2t/descriptors.cc
+++ b/media/formats/mp2t/descriptors.cc
@@ -8,6 +8,7 @@
 
 #include "base/logging.h"
 #include "media/base/bit_reader.h"
+#include "media/base/encryption_scheme.h"
 #include "media/formats/mp2t/mp2t_common.h"
 
 namespace media {
@@ -24,6 +25,7 @@
 };
 
 const int kCASystemIdCenc = 0x6365;  // 'ce'
+const uint32_t kFourccCbcs = 0x63626373;  // 'cbcs'
 
 class StringBitReader : public BitReader {
  public:
@@ -110,7 +112,9 @@
   return true;
 }
 
-bool Descriptors::HasCADescriptorCenc(int* ca_pid, int* pssh_pid) const {
+bool Descriptors::HasCADescriptorCenc(int* ca_pid,
+                                      int* pssh_pid,
+                                      EncryptionScheme* scheme) const {
   DCHECK(ca_pid);
   DCHECK(pssh_pid);
   int system_id;
@@ -125,10 +129,12 @@
   int num_systems;
   int encryption_algorithm;
   char pssh_system_id[16];
-  // TODO(dougsteed). Currently we don't check many of the following values.
+  // TODO(dougsteed). Currently we don't check many of the following values,
+  // and we only support the 'cbcs' scheme (which involves AES-CBC encryption).
   // When we flesh out this implementation to cover all of ISO/IEC 23001-9 we
-  // will need to use and check these values.
+  // will need to use and check these values more comprehensively.
   RCHECK(reader.ReadBits(32, &scheme_type));
+  RCHECK(scheme_type == kFourccCbcs);
   RCHECK(reader.ReadBits(32, &scheme_version));
   RCHECK(reader.ReadBits(8, &num_systems));
   RCHECK(num_systems == 1);
@@ -137,6 +143,10 @@
     RCHECK(reader.ReadBits(8, &pssh_system_id[i]));
   }
   RCHECK(reader.ReadBits(13, pssh_pid));
+  // The pattern is actually set differently for audio and video, so OK not to
+  // set it here. Important thing is to set the cipher mode.
+  *scheme = EncryptionScheme(EncryptionScheme::CIPHER_MODE_AES_CBC,
+                             EncryptionScheme::Pattern());
   return true;
 }
 
diff --git a/media/formats/mp2t/descriptors.h b/media/formats/mp2t/descriptors.h
index cfbca63..6737d09 100644
--- a/media/formats/mp2t/descriptors.h
+++ b/media/formats/mp2t/descriptors.h
@@ -13,6 +13,7 @@
 namespace media {
 
 class BitReader;
+class EncryptionScheme;
 
 namespace mp2t {
 
@@ -46,9 +47,11 @@
 
   // Indicates whether a CA descriptor is present, and if so, whether it is
   // of the type defined by ISO/IEC 23001-9:2014 (i.e. with a specific
-  // system_id value and layout of the private_data). If so, the |ca_pid| and
-  // |pssh_pid| are populated with the contents of the descriptor.
-  bool HasCADescriptorCenc(int* ca_pid, int* pssh_pid) const;
+  // system_id value and layout of the private_data). If so, the |ca_pid|,
+  // |pssh_pid| and |scheme| are populated with the contents of the descriptor.
+  bool HasCADescriptorCenc(int* ca_pid,
+                           int* pssh_pid,
+                           EncryptionScheme* scheme) const;
 
   // Indicates whether a Private Data Indicator descriptor is present with a
   // particular |value|.
diff --git a/media/formats/mp2t/es_parser.cc b/media/formats/mp2t/es_parser.cc
index 713d50c..b54df62 100644
--- a/media/formats/mp2t/es_parser.cc
+++ b/media/formats/mp2t/es_parser.cc
@@ -31,7 +31,10 @@
                      base::TimeDelta pts,
                      DecodeTimestamp dts) {
   DCHECK(buf);
-  DCHECK_GT(size, 0);
+  DCHECK_GE(size, 0);
+  // TS parser may try to give us zero-size data.
+  if (size == 0)
+    return false;
 
   if (pts != kNoTimestamp) {
     // Link the end of the byte queue with the incoming timing descriptor.
diff --git a/media/formats/mp2t/es_parser_adts.cc b/media/formats/mp2t/es_parser_adts.cc
index 2ba520c..7d251c38 100644
--- a/media/formats/mp2t/es_parser_adts.cc
+++ b/media/formats/mp2t/es_parser_adts.cc
@@ -210,13 +210,14 @@
 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
     if (use_hls_sample_aes_) {
       const DecryptConfig* base_decrypt_config = get_decrypt_config_cb_.Run();
-      RCHECK(base_decrypt_config);
-      std::vector<SubsampleEntry> subsamples;
-      CalculateSubsamplesForAdtsFrame(adts_frame, &subsamples);
-      std::unique_ptr<DecryptConfig> decrypt_config(
-          new DecryptConfig(base_decrypt_config->key_id(),
-                            base_decrypt_config->iv(), subsamples));
-      stream_parser_buffer->set_decrypt_config(std::move(decrypt_config));
+      if (base_decrypt_config) {
+        std::vector<SubsampleEntry> subsamples;
+        CalculateSubsamplesForAdtsFrame(adts_frame, &subsamples);
+        std::unique_ptr<DecryptConfig> decrypt_config(
+            new DecryptConfig(base_decrypt_config->key_id(),
+                              base_decrypt_config->iv(), subsamples));
+        stream_parser_buffer->set_decrypt_config(std::move(decrypt_config));
+      }
     }
 #endif
     emit_buffer_cb_.Run(stream_parser_buffer);
diff --git a/media/formats/mp2t/es_parser_h264.cc b/media/formats/mp2t/es_parser_h264.cc
index 340153de..1e06d3f 100644
--- a/media/formats/mp2t/es_parser_h264.cc
+++ b/media/formats/mp2t/es_parser_h264.cc
@@ -436,9 +436,15 @@
   CHECK_GE(es_size, access_unit_size);
 
 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
+  const DecryptConfig* base_decrypt_config = nullptr;
+  if (use_hls_sample_aes_) {
+    DCHECK(!get_decrypt_config_cb_.is_null());
+    base_decrypt_config = get_decrypt_config_cb_.Run();
+  }
+
   std::unique_ptr<uint8_t[]> adjusted_au;
   std::vector<SubsampleEntry> subsamples;
-  if (use_hls_sample_aes_) {
+  if (use_hls_sample_aes_ && base_decrypt_config) {
     adjusted_au = AdjustAUForSampleAES(es, &access_unit_size, protected_blocks_,
                                        &subsamples);
     protected_blocks_.clear();
@@ -455,10 +461,7 @@
   stream_parser_buffer->SetDecodeTimestamp(current_timing_desc.dts);
   stream_parser_buffer->set_timestamp(current_timing_desc.pts);
 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
-  if (use_hls_sample_aes_) {
-    DCHECK(!get_decrypt_config_cb_.is_null());
-    const DecryptConfig* base_decrypt_config = get_decrypt_config_cb_.Run();
-    RCHECK(base_decrypt_config);
+  if (use_hls_sample_aes_ && base_decrypt_config) {
     std::unique_ptr<DecryptConfig> decrypt_config(new DecryptConfig(
         base_decrypt_config->key_id(), base_decrypt_config->iv(), subsamples));
     stream_parser_buffer->set_decrypt_config(std::move(decrypt_config));
diff --git a/media/formats/mp2t/mp2t_stream_parser.cc b/media/formats/mp2t/mp2t_stream_parser.cc
index d0392de..1fcc86a 100644
--- a/media/formats/mp2t/mp2t_stream_parser.cc
+++ b/media/formats/mp2t/mp2t_stream_parser.cc
@@ -9,10 +9,12 @@
 
 #include "base/bind.h"
 #include "base/callback_helpers.h"
+#include "base/memory/ptr_util.h"
 #include "media/base/media_tracks.h"
 #include "media/base/stream_parser_buffer.h"
 #include "media/base/text_track_config.h"
 #include "media/base/timestamp_constants.h"
+#include "media/formats/mp2t/descriptors.h"
 #include "media/formats/mp2t/es_parser.h"
 #include "media/formats/mp2t/es_parser_adts.h"
 #include "media/formats/mp2t/es_parser_h264.h"
@@ -370,8 +372,8 @@
 
   // Create the PMT state here if needed.
   DVLOG(1) << "Create a new PMT parser";
-  std::unique_ptr<TsSection> pmt_section_parser(new TsSectionPmt(base::Bind(
-      &Mp2tStreamParser::RegisterPes, base::Unretained(this), pmt_pid)));
+  std::unique_ptr<TsSection> pmt_section_parser(new TsSectionPmt(
+      base::Bind(&Mp2tStreamParser::RegisterPes, base::Unretained(this))));
   std::unique_ptr<PidState> pmt_pid_state(
       new PidState(pmt_pid, PidState::kPidPmt, std::move(pmt_section_parser)));
   pmt_pid_state->Enable();
@@ -388,8 +390,71 @@
 #endif
 }
 
-void Mp2tStreamParser::RegisterPes(int pmt_pid,
-                                   int pes_pid,
+std::unique_ptr<EsParser> Mp2tStreamParser::CreateH264Parser(int pes_pid) {
+  auto on_video_config_changed = base::Bind(
+      &Mp2tStreamParser::OnVideoConfigChanged, base::Unretained(this), pes_pid);
+  auto on_emit_video_buffer = base::Bind(&Mp2tStreamParser::OnEmitVideoBuffer,
+                                         base::Unretained(this), pes_pid);
+
+  return base::MakeUnique<EsParserH264>(on_video_config_changed,
+                                        on_emit_video_buffer);
+}
+
+std::unique_ptr<EsParser> Mp2tStreamParser::CreateAacParser(int pes_pid) {
+  auto on_audio_config_changed = base::Bind(
+      &Mp2tStreamParser::OnAudioConfigChanged, base::Unretained(this), pes_pid);
+  auto on_emit_audio_buffer = base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer,
+                                         base::Unretained(this), pes_pid);
+  return base::MakeUnique<EsParserAdts>(on_audio_config_changed,
+                                        on_emit_audio_buffer, sbr_in_mimetype_);
+}
+
+std::unique_ptr<EsParser> Mp2tStreamParser::CreateMpeg1AudioParser(
+    int pes_pid) {
+  auto on_audio_config_changed = base::Bind(
+      &Mp2tStreamParser::OnAudioConfigChanged, base::Unretained(this), pes_pid);
+  auto on_emit_audio_buffer = base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer,
+                                         base::Unretained(this), pes_pid);
+  return base::MakeUnique<EsParserMpeg1Audio>(on_audio_config_changed,
+                                              on_emit_audio_buffer, media_log_);
+}
+
+#if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
+bool Mp2tStreamParser::ShouldForceEncryptedParser() {
+  // If we expect to handle encrypted data later in the stream, then force the
+  // use of the encrypted parser variant so that the initial configuration
+  // reflects the intended encryption scheme (even if the initial segment itself
+  // is not encrypted).
+  return initial_scheme_.is_encrypted();
+}
+
+std::unique_ptr<EsParser> Mp2tStreamParser::CreateEncryptedH264Parser(
+    int pes_pid) {
+  auto on_video_config_changed = base::Bind(
+      &Mp2tStreamParser::OnVideoConfigChanged, base::Unretained(this), pes_pid);
+  auto on_emit_video_buffer = base::Bind(&Mp2tStreamParser::OnEmitVideoBuffer,
+                                         base::Unretained(this), pes_pid);
+  auto get_decrypt_config =
+      base::Bind(&Mp2tStreamParser::GetDecryptConfig, base::Unretained(this));
+  return base::MakeUnique<EsParserH264>(
+      on_video_config_changed, on_emit_video_buffer, true, get_decrypt_config);
+}
+
+std::unique_ptr<EsParser> Mp2tStreamParser::CreateEncryptedAacParser(
+    int pes_pid) {
+  auto on_audio_config_changed = base::Bind(
+      &Mp2tStreamParser::OnAudioConfigChanged, base::Unretained(this), pes_pid);
+  auto on_emit_audio_buffer = base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer,
+                                         base::Unretained(this), pes_pid);
+  auto get_decrypt_config =
+      base::Bind(&Mp2tStreamParser::GetDecryptConfig, base::Unretained(this));
+  return base::MakeUnique<EsParserAdts>(
+      on_audio_config_changed, on_emit_audio_buffer, get_decrypt_config, true,
+      sbr_in_mimetype_);
+}
+#endif
+
+void Mp2tStreamParser::RegisterPes(int pes_pid,
                                    int stream_type,
                                    const Descriptors& descriptors) {
   // TODO(damienv): check there is no mismatch if the entry already exists.
@@ -401,61 +466,66 @@
     return;
 
   // Create a stream parser corresponding to the stream type.
-  bool is_audio = false;
+  bool is_audio = true;
   std::unique_ptr<EsParser> es_parser;
-  if (stream_type == kStreamTypeAVC) {
-    es_parser.reset(
-        new EsParserH264(
-            base::Bind(&Mp2tStreamParser::OnVideoConfigChanged,
-                       base::Unretained(this),
-                       pes_pid),
-            base::Bind(&Mp2tStreamParser::OnEmitVideoBuffer,
-                       base::Unretained(this),
-                       pes_pid)));
-  } else if (stream_type == kStreamTypeAAC) {
-    es_parser.reset(
-        new EsParserAdts(
-            base::Bind(&Mp2tStreamParser::OnAudioConfigChanged,
-                       base::Unretained(this),
-                       pes_pid),
-            base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer,
-                       base::Unretained(this),
-                       pes_pid),
-            sbr_in_mimetype_));
-    is_audio = true;
-  } else if (stream_type == kStreamTypeMpeg1Audio ||
-             stream_type == kStreamTypeMpeg2Audio) {
-    es_parser.reset(new EsParserMpeg1Audio(
-        base::Bind(&Mp2tStreamParser::OnAudioConfigChanged,
-                   base::Unretained(this), pes_pid),
-        base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer, base::Unretained(this),
-                   pes_pid),
-        media_log_));
-    is_audio = true;
+
+  switch (stream_type) {
+    case kStreamTypeAVC:
 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
-  } else if (stream_type == kStreamTypeAVCWithSampleAES &&
-             descriptors.HasPrivateDataIndicator(
-                 kSampleAESPrivateDataIndicatorAVC)) {
-    es_parser.reset(
-        new EsParserH264(base::Bind(&Mp2tStreamParser::OnVideoConfigChanged,
-                                    base::Unretained(this), pes_pid),
-                         base::Bind(&Mp2tStreamParser::OnEmitVideoBuffer,
-                                    base::Unretained(this), pes_pid),
-                         true, base::Bind(&Mp2tStreamParser::GetDecryptConfig,
-                                          base::Unretained(this))));
-  } else if (stream_type == kStreamTypeAACWithSampleAES &&
-             descriptors.HasPrivateDataIndicator(
-                 kSampleAESPrivateDataIndicatorAAC)) {
-    es_parser.reset(new EsParserAdts(
-        base::Bind(&Mp2tStreamParser::OnAudioConfigChanged,
-                   base::Unretained(this), pes_pid),
-        base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer, base::Unretained(this),
-                   pes_pid),
-        base::Bind(&Mp2tStreamParser::GetDecryptConfig, base::Unretained(this)),
-        true, sbr_in_mimetype_));
-    is_audio = true;
+      is_audio = false;
+      if (ShouldForceEncryptedParser()) {
+        es_parser = CreateEncryptedH264Parser(pes_pid);
+        break;
+      }
 #endif
-  } else {
+      es_parser = CreateH264Parser(pes_pid);
+      break;
+
+    case kStreamTypeAAC:
+#if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
+      if (ShouldForceEncryptedParser()) {
+        es_parser = CreateEncryptedAacParser(pes_pid);
+        break;
+      }
+#endif
+      es_parser = CreateAacParser(pes_pid);
+      break;
+
+    case kStreamTypeMpeg1Audio:
+    case kStreamTypeMpeg2Audio:
+      es_parser = CreateMpeg1AudioParser(pes_pid);
+      break;
+
+#if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
+    case kStreamTypeAVCWithSampleAES:
+      if (descriptors.HasPrivateDataIndicator(
+              kSampleAESPrivateDataIndicatorAVC)) {
+        is_audio = false;
+        es_parser = CreateEncryptedH264Parser(pes_pid);
+      } else {
+        VLOG(2) << "HLS: stream_type in PMT indicates AVC with Sample-AES, but "
+                << "corresponding private data indicator is not present.";
+      }
+      break;
+
+    case kStreamTypeAACWithSampleAES:
+      if (descriptors.HasPrivateDataIndicator(
+              kSampleAESPrivateDataIndicatorAAC)) {
+        es_parser = CreateEncryptedAacParser(pes_pid);
+      } else {
+        VLOG(2) << "HLS: stream_type in PMT indicates AAC with Sample-AES, but "
+                << "corresponding private data indicator is not present.";
+      }
+      break;
+#endif
+
+    default:
+      // Unknown stream_type, so can't create a parser. Logged below.
+      break;
+  }
+
+  if (!es_parser) {
+    VLOG(1) << "Parser could not be created for stream_type: " << stream_type;
     return;
   }
 
@@ -755,7 +825,9 @@
 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
 std::unique_ptr<PidState> Mp2tStreamParser::MakeCatPidState() {
   std::unique_ptr<TsSection> cat_section_parser(new TsSectionCat(
-      base::Bind(&Mp2tStreamParser::RegisterCencPids, base::Unretained(this))));
+      base::Bind(&Mp2tStreamParser::RegisterCencPids, base::Unretained(this)),
+      base::Bind(&Mp2tStreamParser::RegisterEncryptionScheme,
+                 base::Unretained(this))));
   std::unique_ptr<PidState> cat_pid_state(new PidState(
       TsSection::kPidCat, PidState::kPidCat, std::move(cat_section_parser)));
   cat_pid_state->Enable();
@@ -803,6 +875,18 @@
   }
 }
 
+void Mp2tStreamParser::RegisterEncryptionScheme(
+    const EncryptionScheme& scheme) {
+  // We only need to record this for the initial decoder config.
+  if (!is_initialized_) {
+    initial_scheme_ = scheme;
+  }
+  // Reset the DecryptConfig, so that unless and until a CENC-ECM (containing
+  // key id and IV) is seen, media data will be considered unencrypted. This is
+  // similar to the way clear leaders can occur in MP4 containers.
+  decrypt_config_.reset(nullptr);
+}
+
 void Mp2tStreamParser::RegisterDecryptConfig(const DecryptConfig& config) {
   decrypt_config_.reset(
       new DecryptConfig(config.key_id(), config.iv(), config.subsamples()));
diff --git a/media/formats/mp2t/mp2t_stream_parser.h b/media/formats/mp2t/mp2t_stream_parser.h
index 6557756..548270be 100644
--- a/media/formats/mp2t/mp2t_stream_parser.h
+++ b/media/formats/mp2t/mp2t_stream_parser.h
@@ -16,6 +16,7 @@
 #include "media/base/audio_decoder_config.h"
 #include "media/base/byte_queue.h"
 #include "media/base/decrypt_config.h"
+#include "media/base/encryption_scheme.h"
 #include "media/base/media_export.h"
 #include "media/base/stream_parser.h"
 #include "media/base/video_decoder_config.h"
@@ -30,6 +31,7 @@
 namespace mp2t {
 
 class Descriptors;
+class EsParser;
 class PidState;
 
 class MEDIA_EXPORT Mp2tStreamParser : public StreamParser {
@@ -71,10 +73,9 @@
   // Callback invoked to register a PES pid.
   // Possible values for |stream_type| are defined in:
   // ISO-13818.1 / ITU H.222 Table 2.34 "Stream type assignments".
-  // |pes_pid| is part of the Program Map Table refered by |pmt_pid|.
+  // |pes_pid| is part of the Program Map Table.
   // Some stream types are qualified by additional |descriptors|.
-  void RegisterPes(int pmt_pid,
-                   int pes_pid,
+  void RegisterPes(int pes_pid,
                    int stream_type,
                    const Descriptors& descriptors);
 
@@ -103,7 +104,15 @@
       scoped_refptr<StreamParserBuffer> stream_parser_buffer);
   bool EmitRemainingBuffers();
 
+  std::unique_ptr<EsParser> CreateH264Parser(int pes_pid);
+  std::unique_ptr<EsParser> CreateAacParser(int pes_pid);
+  std::unique_ptr<EsParser> CreateMpeg1AudioParser(int pes_pid);
+
 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
+  bool ShouldForceEncryptedParser();
+  std::unique_ptr<EsParser> CreateEncryptedH264Parser(int pes_pid);
+  std::unique_ptr<EsParser> CreateEncryptedAacParser(int pes_pid);
+
   std::unique_ptr<PidState> MakeCatPidState();
   void UnregisterCat();
 
@@ -111,6 +120,11 @@
   void RegisterCencPids(int ca_pid, int pssh_pid);
   void UnregisterCencPids();
 
+  // Register a default encryption scheme to be used for decoder configs. This
+  // value is only used in the absence of explicit encryption metadata, as might
+  // be the case during an unencrypted portion of a live stream.
+  void RegisterEncryptionScheme(const EncryptionScheme& scheme);
+
   // Register the DecryptConfig (parsed from CENC-ECM).
   void RegisterDecryptConfig(const DecryptConfig& config);
 
@@ -158,6 +172,7 @@
   TimestampUnroller timestamp_unroller_;
 
 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
+  EncryptionScheme initial_scheme_;
   std::unique_ptr<DecryptConfig> decrypt_config_;
 #endif
 
diff --git a/media/formats/mp2t/mp2t_stream_parser_unittest.cc b/media/formats/mp2t/mp2t_stream_parser_unittest.cc
index 3555b91..64080eec 100644
--- a/media/formats/mp2t/mp2t_stream_parser_unittest.cc
+++ b/media/formats/mp2t/mp2t_stream_parser_unittest.cc
@@ -504,6 +504,19 @@
     EXPECT_EQ(decrypted_audio_buffers[i], unencrypted_audio_buffer);
   }
 }
+
+TEST_F(Mp2tStreamParserTest, PrepareForHLSSampleAES) {
+  InitializeParser();
+  ParseMpeg2TsFile("bear-1280x720-hls-with-CAT.bin", 2048);
+  parser_->Flush();
+  EncryptionScheme video_encryption_scheme =
+      current_video_config_.encryption_scheme();
+  EXPECT_TRUE(video_encryption_scheme.is_encrypted());
+  EncryptionScheme audio_encryption_scheme =
+      current_audio_config_.encryption_scheme();
+  EXPECT_TRUE(audio_encryption_scheme.is_encrypted());
+}
+
 #endif
 
 }  // namespace mp2t
diff --git a/media/formats/mp2t/ts_section_cat.cc b/media/formats/mp2t/ts_section_cat.cc
index 0f491fb1..3513ec6 100644
--- a/media/formats/mp2t/ts_section_cat.cc
+++ b/media/formats/mp2t/ts_section_cat.cc
@@ -8,14 +8,19 @@
 
 #include "base/logging.h"
 #include "media/base/bit_reader.h"
+#include "media/base/encryption_scheme.h"
 #include "media/formats/mp2t/descriptors.h"
 #include "media/formats/mp2t/mp2t_common.h"
 
 namespace media {
 namespace mp2t {
 
-TsSectionCat::TsSectionCat(const RegisterCencPidsCb& register_cenc_ids_cb)
-    : register_cenc_ids_cb_(register_cenc_ids_cb), version_number_(-1) {}
+TsSectionCat::TsSectionCat(
+    const RegisterCencPidsCb& register_cenc_ids_cb,
+    const RegisterEncryptionSchemeCb& register_encryption_scheme_cb)
+    : register_cenc_ids_cb_(register_cenc_ids_cb),
+      register_encryption_scheme_cb_(register_encryption_scheme_cb),
+      version_number_(-1) {}
 
 TsSectionCat::~TsSectionCat() {}
 
@@ -54,8 +59,9 @@
 
   Descriptors descriptors;
   int ca_pid, pssh_pid;
+  EncryptionScheme scheme;
   RCHECK(descriptors.Read(bit_reader, section_length - 4));
-  RCHECK(descriptors.HasCADescriptorCenc(&ca_pid, &pssh_pid));
+  RCHECK(descriptors.HasCADescriptorCenc(&ca_pid, &pssh_pid, &scheme));
   int crc32;
   RCHECK(bit_reader->ReadBits(32, &crc32));
 
@@ -69,8 +75,9 @@
   if (version_number == version_number_)
     return true;
 
-  // Can now register the PIDs.
+  // Can now register the PIDs and scheme.
   register_cenc_ids_cb_.Run(ca_pid, pssh_pid);
+  register_encryption_scheme_cb_.Run(scheme);
 
   version_number_ = version_number;
 
diff --git a/media/formats/mp2t/ts_section_cat.h b/media/formats/mp2t/ts_section_cat.h
index dbeb505..27922de 100644
--- a/media/formats/mp2t/ts_section_cat.h
+++ b/media/formats/mp2t/ts_section_cat.h
@@ -10,13 +10,20 @@
 #include "media/formats/mp2t/ts_section_psi.h"
 
 namespace media {
+
+class EncryptionScheme;
+
 namespace mp2t {
 
 class TsSectionCat : public TsSectionPsi {
  public:
   // RegisterCencPidsCb::Run(int ca_pid, int pssh_pid);
   using RegisterCencPidsCb = base::Callback<void(int, int)>;
-  explicit TsSectionCat(const RegisterCencPidsCb& register_cenc_ids_cb);
+  // RegisterEncryptionScheme::Run(const EncryptionScheme& scheme);
+  using RegisterEncryptionSchemeCb =
+      base::Callback<void(const EncryptionScheme&)>;
+  TsSectionCat(const RegisterCencPidsCb& register_cenc_ids_cb,
+               const RegisterEncryptionSchemeCb& register_encryption_scheme_cb);
   ~TsSectionCat() override;
 
   // TsSectionPsi implementation.
@@ -25,6 +32,7 @@
 
  private:
   RegisterCencPidsCb register_cenc_ids_cb_;
+  RegisterEncryptionSchemeCb register_encryption_scheme_cb_;
 
   // Parameters from the CAT.
   int version_number_;
diff --git a/media/gpu/android/android_video_decode_accelerator.cc b/media/gpu/android/android_video_decode_accelerator.cc
index 2fb8072..53aa5e2 100644
--- a/media/gpu/android/android_video_decode_accelerator.cc
+++ b/media/gpu/android/android_video_decode_accelerator.cc
@@ -44,6 +44,7 @@
 #include "media/gpu/shared_memory_region.h"
 #include "media/mojo/features.h"
 #include "media/video/picture.h"
+#include "services/service_manager/public/cpp/service_context_ref.h"
 #include "ui/gl/android/scoped_java_surface.h"
 #include "ui/gl/android/surface_texture.h"
 #include "ui/gl/gl_bindings.h"
@@ -441,8 +442,8 @@
                          config_.overlay_info.surface_id);
   } else if (config_.overlay_info.HasValidRoutingToken() &&
              overlay_factory_cb_) {
-    factory =
-        base::Bind(overlay_factory_cb_, *config_.overlay_info.routing_token);
+    factory = base::Bind(overlay_factory_cb_, nullptr,
+                         *config_.overlay_info.routing_token);
   }
 
   // Notify |surface_chooser_| that we've started.  This guarantees that we'll
@@ -1342,7 +1343,7 @@
   if (surface_id != previous_info.surface_id ||
       routing_token != previous_info.routing_token) {
     if (routing_token && overlay_factory_cb_)
-      new_factory = base::Bind(overlay_factory_cb_, *routing_token);
+      new_factory = base::Bind(overlay_factory_cb_, nullptr, *routing_token);
     else if (surface_id != SurfaceManager::kNoSurfaceID)
       new_factory = base::Bind(&ContentVideoViewOverlay::Create, surface_id);
   }
diff --git a/media/gpu/android/media_codec_video_decoder.cc b/media/gpu/android/media_codec_video_decoder.cc
index f20c3734..522c389 100644
--- a/media/gpu/android/media_codec_video_decoder.cc
+++ b/media/gpu/android/media_codec_video_decoder.cc
@@ -637,10 +637,22 @@
 
 AndroidOverlayFactoryCB MediaCodecVideoDecoder::CreateOverlayFactoryCb() {
   DCHECK(!overlay_info_.HasValidSurfaceId());
-  if (overlay_info_.HasValidRoutingToken() && overlay_factory_cb_) {
-    return base::Bind(overlay_factory_cb_, *overlay_info_.routing_token);
-  }
-  return AndroidOverlayFactoryCB();
+  if (!overlay_factory_cb_ || !overlay_info_.HasValidRoutingToken())
+    return AndroidOverlayFactoryCB();
+
+  // This wrapper forwards its arguments and clones a context ref on each call.
+  auto wrapper = [](AndroidOverlayMojoFactoryCB overlay_factory_cb,
+                    service_manager::ServiceContextRef* context_ref,
+                    base::UnguessableToken routing_token,
+                    AndroidOverlayConfig config) {
+    return overlay_factory_cb.Run(context_ref->Clone(),
+                                  std::move(routing_token), std::move(config));
+  };
+
+  // Pass ownership of a new context ref into the callback.
+  return base::Bind(wrapper, overlay_factory_cb_,
+                    base::Owned(context_ref_->Clone().release()),
+                    *overlay_info_.routing_token);
 }
 
 std::string MediaCodecVideoDecoder::GetDisplayName() const {
diff --git a/media/gpu/android/media_codec_video_decoder_unittest.cc b/media/gpu/android/media_codec_video_decoder_unittest.cc
index 87ffa30f..1126c5b 100644
--- a/media/gpu/android/media_codec_video_decoder_unittest.cc
+++ b/media/gpu/android/media_codec_video_decoder_unittest.cc
@@ -38,6 +38,7 @@
 void RequestOverlayInfoCb(bool, const ProvideOverlayInfoCB&) {}
 
 std::unique_ptr<AndroidOverlay> CreateAndroidOverlayCb(
+    std::unique_ptr<service_manager::ServiceContextRef>,
     const base::UnguessableToken&,
     AndroidOverlayConfig) {
   return nullptr;
@@ -53,6 +54,13 @@
   using MediaCodecVideoDecoder::MediaCodecVideoDecoder;
 };
 
+class MockServiceContextRef : public service_manager::ServiceContextRef {
+ public:
+  std::unique_ptr<ServiceContextRef> Clone() override {
+    return base::MakeUnique<MockServiceContextRef>();
+  }
+};
+
 }  // namespace
 
 class MockVideoFrameFactory : public VideoFrameFactory {
@@ -109,7 +117,8 @@
         base::Bind(&OutputWithReleaseMailboxCb), device_info_.get(),
         codec_allocator_.get(), std::move(surface_chooser),
         base::Bind(&CreateAndroidOverlayCb), base::Bind(&RequestOverlayInfoCb),
-        std::move(video_frame_factory), nullptr);
+        std::move(video_frame_factory),
+        base::MakeUnique<MockServiceContextRef>());
     mcvd_.reset(observable_mcvd);
     mcvd_raw_ = observable_mcvd;
     destruction_observer_ = observable_mcvd->CreateDestructionObserver();
diff --git a/media/midi/midi_manager_android.cc b/media/midi/midi_manager_android.cc
index 46dbd447..1acd5273 100644
--- a/media/midi/midi_manager_android.cc
+++ b/media/midi/midi_manager_android.cc
@@ -68,9 +68,6 @@
     : MidiManager(service) {}
 
 MidiManagerAndroid::~MidiManagerAndroid() {
-  bool result = service()->task_service()->UnbindInstance();
-  DCHECK(result);
-
   // TODO(toyoshim): Remove following code once the dynamic instantiation mode
   // is enabled by default.
   base::AutoLock lock(lock_);
diff --git a/media/midi/midi_switches.cc b/media/midi/midi_switches.cc
index 96e7974b..ced7809 100644
--- a/media/midi/midi_switches.cc
+++ b/media/midi/midi_switches.cc
@@ -10,7 +10,7 @@
 
 #if defined(OS_ANDROID)
 const base::Feature kMidiManagerAndroid{"MidiManagerAndroid",
-                                        base::FEATURE_DISABLED_BY_DEFAULT};
+                                        base::FEATURE_ENABLED_BY_DEFAULT};
 #endif
 
 #if defined(OS_WIN)
diff --git a/media/mojo/clients/mojo_android_overlay.cc b/media/mojo/clients/mojo_android_overlay.cc
index d3d2a89..b013a9e5 100644
--- a/media/mojo/clients/mojo_android_overlay.cc
+++ b/media/mojo/clients/mojo_android_overlay.cc
@@ -12,8 +12,11 @@
 MojoAndroidOverlay::MojoAndroidOverlay(
     mojom::AndroidOverlayProviderPtr provider_ptr,
     AndroidOverlayConfig config,
-    const base::UnguessableToken& routing_token)
-    : config_(std::move(config)), binding_(this) {
+    const base::UnguessableToken& routing_token,
+    std::unique_ptr<service_manager::ServiceContextRef> context_ref)
+    : config_(std::move(config)),
+      binding_(this),
+      context_ref_(std::move(context_ref)) {
   // Fill in details of |config| into |mojo_config|.  Our caller could do this
   // too, but since we want to retain |config_| anyway, we do it here.
   mojom::AndroidOverlayConfigPtr mojo_config =
diff --git a/media/mojo/clients/mojo_android_overlay.h b/media/mojo/clients/mojo_android_overlay.h
index 27065a5..58f962b0 100644
--- a/media/mojo/clients/mojo_android_overlay.h
+++ b/media/mojo/clients/mojo_android_overlay.h
@@ -10,6 +10,7 @@
 #include "media/base/android/android_overlay.h"
 #include "media/mojo/interfaces/android_overlay.mojom.h"
 #include "mojo/public/cpp/bindings/binding.h"
+#include "services/service_manager/public/cpp/service_context_ref.h"
 
 namespace media {
 
@@ -17,9 +18,12 @@
 class MojoAndroidOverlay : public AndroidOverlay,
                            public mojom::AndroidOverlayClient {
  public:
-  MojoAndroidOverlay(mojom::AndroidOverlayProviderPtr provider_ptr,
-                     AndroidOverlayConfig config,
-                     const base::UnguessableToken& routing_token);
+  // |context_ref| may be null.
+  MojoAndroidOverlay(
+      mojom::AndroidOverlayProviderPtr provider_ptr,
+      AndroidOverlayConfig config,
+      const base::UnguessableToken& routing_token,
+      std::unique_ptr<service_manager::ServiceContextRef> context_ref);
 
   ~MojoAndroidOverlay() override;
 
@@ -37,6 +41,7 @@
   mojom::AndroidOverlayPtr overlay_ptr_;
   mojo::Binding<mojom::AndroidOverlayClient> binding_;
   gl::ScopedJavaSurface surface_;
+  std::unique_ptr<service_manager::ServiceContextRef> context_ref_;
 
   // Have we received OnSurfaceReady yet?
   bool received_surface_ = false;
diff --git a/media/mojo/clients/mojo_android_overlay_unittest.cc b/media/mojo/clients/mojo_android_overlay_unittest.cc
index eedb67a5..7066c00 100644
--- a/media/mojo/clients/mojo_android_overlay_unittest.cc
+++ b/media/mojo/clients/mojo_android_overlay_unittest.cc
@@ -20,8 +20,8 @@
 #include "ui/gl/android/scoped_java_surface.h"
 #include "ui/gl/android/surface_texture.h"
 
-using ::testing::_;
 using ::testing::StrictMock;
+using ::testing::_;
 
 namespace media {
 
@@ -111,7 +111,7 @@
     provider_binding_.Bind(mojo::MakeRequest(&provider_ptr));
 
     overlay_client_.reset(new MojoAndroidOverlay(
-        std::move(provider_ptr), std::move(config_), routing_token));
+        std::move(provider_ptr), std::move(config_), routing_token, nullptr));
     overlay_client_->AddSurfaceDestroyedCallback(base::Bind(
         &MockClientCallbacks::OnDestroyed, base::Unretained(&callbacks_)));
     base::RunLoop().RunUntilIdle();
diff --git a/media/mojo/clients/mojo_decryptor_unittest.cc b/media/mojo/clients/mojo_decryptor_unittest.cc
index 6698326..e257548 100644
--- a/media/mojo/clients/mojo_decryptor_unittest.cc
+++ b/media/mojo/clients/mojo_decryptor_unittest.cc
@@ -123,12 +123,9 @@
 TEST_F(MojoDecryptorTest, VideoDecodeFreesMultipleBuffers) {
   // Call DecryptAndDecodeVideo() multiple times.
   const int TIMES = 5;
-  {
-    InSequence seq;
-    EXPECT_CALL(*this, VideoDecoded(Decryptor::Status::kSuccess, NotNull()))
-        .Times(TIMES);
-    EXPECT_CALL(*this, OnFrameDestroyed()).Times(TIMES);
-  }
+  EXPECT_CALL(*this, VideoDecoded(Decryptor::Status::kSuccess, NotNull()))
+      .Times(TIMES);
+  EXPECT_CALL(*this, OnFrameDestroyed()).Times(TIMES);
   EXPECT_CALL(*decryptor_, DecryptAndDecodeVideo(_, _))
       .WillRepeatedly(Invoke(this, &MojoDecryptorTest::ReturnSimpleVideoFrame));
 
diff --git a/media/mojo/common/mojo_decoder_buffer_converter.cc b/media/mojo/common/mojo_decoder_buffer_converter.cc
index 449ae6a0..b790a39 100644
--- a/media/mojo/common/mojo_decoder_buffer_converter.cc
+++ b/media/mojo/common/mojo_decoder_buffer_converter.cc
@@ -62,19 +62,19 @@
     mojo::ScopedDataPipeConsumerHandle consumer_handle)
     : consumer_handle_(std::move(consumer_handle)),
       pipe_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL),
+      armed_(false),
       bytes_read_(0) {
   DVLOG(1) << __func__;
 
   MojoResult result =
       pipe_watcher_.Watch(consumer_handle_.get(), MOJO_HANDLE_SIGNAL_READABLE,
+                          MOJO_WATCH_CONDITION_SATISFIED,
                           base::Bind(&MojoDecoderBufferReader::OnPipeReadable,
                                      base::Unretained(this)));
   if (result != MOJO_RESULT_OK) {
     DVLOG(1) << __func__
              << ": Failed to start watching the pipe. result=" << result;
     consumer_handle_.reset();
-  } else {
-    pipe_watcher_.ArmOrNotify();
   }
 }
 
@@ -82,92 +82,132 @@
   DVLOG(1) << __func__;
 }
 
+void MojoDecoderBufferReader::CancelReadCB(ReadCB read_cb) {
+  DVLOG(1) << "Failed to read DecoderBuffer becuase the pipe is already closed";
+  std::move(read_cb).Run(nullptr);
+}
+
+void MojoDecoderBufferReader::CompleteCurrentRead() {
+  DVLOG(4) << __func__;
+  bytes_read_ = 0;
+  ReadCB read_cb = std::move(pending_read_cbs_.front());
+  pending_read_cbs_.pop_front();
+  scoped_refptr<DecoderBuffer> buffer = std::move(pending_buffers_.front());
+  pending_buffers_.pop_front();
+  std::move(read_cb).Run(std::move(buffer));
+}
+
+void MojoDecoderBufferReader::ScheduleNextRead() {
+  DVLOG(4) << __func__;
+
+  // Do nothing if a read is already scheduled.
+  if (armed_)
+    return;
+
+  // Immediately complete empty reads.
+  // A non-EOS buffer can have zero size. See http://crbug.com/663438
+  while (!pending_buffers_.empty() &&
+         (pending_buffers_.front()->end_of_stream() ||
+          pending_buffers_.front()->data_size() == 0)) {
+    // TODO(sandersd): Make sure there are no possible re-entrancy issues here.
+    // Perhaps read callbacks should be posted?
+    CompleteCurrentRead();
+  }
+
+  // Request a callback to issue the DataPipe read.
+  if (!pending_buffers_.empty()) {
+    armed_ = true;
+    pipe_watcher_.ArmOrNotify();
+  }
+}
+
 void MojoDecoderBufferReader::ReadDecoderBuffer(
     mojom::DecoderBufferPtr mojo_buffer,
     ReadCB read_cb) {
   DVLOG(3) << __func__;
 
-  // DecoderBuffer cannot be read if the pipe is already closed.
   if (!consumer_handle_.is_valid()) {
-    DVLOG(1)
-        << __func__
-        << ": Failed to read DecoderBuffer becuase the pipe is already closed";
-    std::move(read_cb).Run(nullptr);
+    DCHECK(pending_read_cbs_.empty());
+    CancelReadCB(std::move(read_cb));
     return;
   }
 
-  DCHECK(!read_cb_);
-  DCHECK(!media_buffer_);
-  DCHECK_EQ(bytes_read_, 0u);
-
   scoped_refptr<DecoderBuffer> media_buffer(
       mojo_buffer.To<scoped_refptr<DecoderBuffer>>());
   DCHECK(media_buffer);
 
-  // A non-EOS buffer can have zero size. See http://crbug.com/663438
-  if (media_buffer->end_of_stream() || media_buffer->data_size() == 0) {
-    std::move(read_cb).Run(media_buffer);
+  // We don't want reads to complete out of order, so we queue them even if they
+  // are zero-sized.
+  pending_read_cbs_.push_back(std::move(read_cb));
+  pending_buffers_.push_back(std::move(media_buffer));
+  ScheduleNextRead();
+}
+
+void MojoDecoderBufferReader::OnPipeReadable(
+    MojoResult result,
+    const mojo::HandleSignalsState& state) {
+  DVLOG(4) << __func__ << "(" << result << ", " << state.readable() << ")";
+
+  armed_ = false;
+
+  if (result != MOJO_RESULT_OK) {
+    OnPipeError(result);
     return;
   }
 
-  // Read the data section of |media_buffer| from the pipe.
-  read_cb_ = std::move(read_cb);
-  media_buffer_ = std::move(media_buffer);
+  DCHECK(state.readable());
   ReadDecoderBufferData();
 }
 
-void MojoDecoderBufferReader::OnPipeError(MojoResult result) {
-  DVLOG(1) << __func__ << "(" << result << ")";
-  DCHECK(IsPipeReadWriteError(result));
-
-  if (media_buffer_) {
-    DVLOG(1) << __func__ << ": reading from data pipe failed. result=" << result
-             << ", buffer size=" << media_buffer_->data_size()
-             << ", num_bytes(read)=" << bytes_read_;
-    DCHECK(read_cb_);
-    bytes_read_ = 0;
-    media_buffer_ = nullptr;
-    std::move(read_cb_).Run(nullptr);
-  }
-  consumer_handle_.reset();
-}
-
-void MojoDecoderBufferReader::OnPipeReadable(MojoResult result) {
-  DVLOG(4) << __func__ << "(" << result << ")";
-
-  if (result != MOJO_RESULT_OK)
-    OnPipeError(result);
-  else if (media_buffer_)
-    ReadDecoderBufferData();
-}
-
 void MojoDecoderBufferReader::ReadDecoderBufferData() {
   DVLOG(4) << __func__;
-  DCHECK(media_buffer_);
 
-  uint32_t buffer_size =
-      base::checked_cast<uint32_t>(media_buffer_->data_size());
+  DCHECK(!pending_buffers_.empty());
+  DecoderBuffer* buffer = pending_buffers_.front().get();
+  uint32_t buffer_size = base::checked_cast<uint32_t>(buffer->data_size());
   DCHECK_GT(buffer_size, 0u);
 
   uint32_t num_bytes = buffer_size - bytes_read_;
   DCHECK_GT(num_bytes, 0u);
 
   MojoResult result =
-      consumer_handle_->ReadData(media_buffer_->writable_data() + bytes_read_,
+      consumer_handle_->ReadData(buffer->writable_data() + bytes_read_,
                                  &num_bytes, MOJO_WRITE_DATA_FLAG_NONE);
 
   if (IsPipeReadWriteError(result)) {
     OnPipeError(result);
   } else {
-    pipe_watcher_.ArmOrNotify();
     if (result == MOJO_RESULT_OK) {
       DCHECK_GT(num_bytes, 0u);
       bytes_read_ += num_bytes;
-      if (bytes_read_ == buffer_size) {
-        DCHECK(read_cb_);
-        bytes_read_ = 0;
-        std::move(read_cb_).Run(std::move(media_buffer_));
-      }
+      // TODO(sandersd): Make sure there are no possible re-entrancy issues
+      // here.
+      if (bytes_read_ == buffer_size)
+        CompleteCurrentRead();
+    }
+    ScheduleNextRead();
+  }
+}
+
+void MojoDecoderBufferReader::OnPipeError(MojoResult result) {
+  DVLOG(1) << __func__ << "(" << result << ")";
+  DCHECK(IsPipeReadWriteError(result));
+
+  consumer_handle_.reset();
+
+  if (!pending_buffers_.empty()) {
+    DVLOG(1) << __func__ << ": reading from data pipe failed. result=" << result
+             << ", buffer size=" << pending_buffers_.front()->data_size()
+             << ", num_bytes(read)=" << bytes_read_;
+    bytes_read_ = 0;
+    pending_buffers_.clear();
+    while (!pending_read_cbs_.empty()) {
+      ReadCB read_cb = std::move(pending_read_cbs_.front());
+      pending_read_cbs_.pop_front();
+      // TODO(sandersd): Make sure there are no possible re-entrancy issues
+      // here. Perhaps these should be posted, or merged into a single error
+      // callback?
+      CancelReadCB(std::move(read_cb));
     }
   }
 }
@@ -189,19 +229,19 @@
     mojo::ScopedDataPipeProducerHandle producer_handle)
     : producer_handle_(std::move(producer_handle)),
       pipe_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL),
+      armed_(false),
       bytes_written_(0) {
   DVLOG(1) << __func__;
 
   MojoResult result =
       pipe_watcher_.Watch(producer_handle_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
+                          MOJO_WATCH_CONDITION_SATISFIED,
                           base::Bind(&MojoDecoderBufferWriter::OnPipeWritable,
                                      base::Unretained(this)));
   if (result != MOJO_RESULT_OK) {
     DVLOG(1) << __func__
              << ": Failed to start watching the pipe. result=" << result;
     producer_handle_.reset();
-  } else {
-    pipe_watcher_.ArmOrNotify();
   }
 }
 
@@ -209,6 +249,20 @@
   DVLOG(1) << __func__;
 }
 
+void MojoDecoderBufferWriter::ScheduleNextWrite() {
+  DVLOG(4) << __func__;
+
+  // Do nothing if a write is already scheduled.
+  if (armed_)
+    return;
+
+  // Request a callback to issue the DataPipe write.
+  if (!pending_buffers_.empty()) {
+    armed_ = true;
+    pipe_watcher_.ArmOrNotify();
+  }
+}
+
 mojom::DecoderBufferPtr MojoDecoderBufferWriter::WriteDecoderBuffer(
     const scoped_refptr<DecoderBuffer>& media_buffer) {
   DVLOG(3) << __func__;
@@ -221,9 +275,6 @@
     return nullptr;
   }
 
-  DCHECK(!media_buffer_);
-  DCHECK_EQ(bytes_written_, 0u);
-
   mojom::DecoderBufferPtr mojo_buffer =
       mojom::DecoderBuffer::From(media_buffer);
 
@@ -231,65 +282,70 @@
   if (media_buffer->end_of_stream() || media_buffer->data_size() == 0)
     return mojo_buffer;
 
-  // Serialize the data section of the DecoderBuffer into our pipe.
-  media_buffer_ = media_buffer;
-  MojoResult result = WriteDecoderBufferData();
-  return IsPipeReadWriteError(result) ? nullptr : std::move(mojo_buffer);
+  // Queue writing the buffer's data into our DataPipe.
+  pending_buffers_.push_back(media_buffer);
+  ScheduleNextWrite();
+  return mojo_buffer;
+}
+
+void MojoDecoderBufferWriter::OnPipeWritable(
+    MojoResult result,
+    const mojo::HandleSignalsState& state) {
+  DVLOG(4) << __func__ << "(" << result << ", " << state.writable() << ")";
+
+  armed_ = false;
+
+  if (result != MOJO_RESULT_OK) {
+    OnPipeError(result);
+    return;
+  }
+
+  DCHECK(state.writable());
+  WriteDecoderBufferData();
+}
+
+void MojoDecoderBufferWriter::WriteDecoderBufferData() {
+  DVLOG(4) << __func__;
+
+  DCHECK(!pending_buffers_.empty());
+  DecoderBuffer* buffer = pending_buffers_.front().get();
+  uint32_t buffer_size = base::checked_cast<uint32_t>(buffer->data_size());
+  DCHECK_GT(buffer_size, 0u);
+
+  uint32_t num_bytes = buffer_size - bytes_written_;
+  DCHECK_GT(num_bytes, 0u);
+
+  MojoResult result = producer_handle_->WriteData(
+      buffer->data() + bytes_written_, &num_bytes, MOJO_WRITE_DATA_FLAG_NONE);
+
+  if (IsPipeReadWriteError(result)) {
+    OnPipeError(result);
+  } else {
+    if (result == MOJO_RESULT_OK) {
+      DCHECK_GT(num_bytes, 0u);
+      bytes_written_ += num_bytes;
+      if (bytes_written_ == buffer_size) {
+        pending_buffers_.pop_front();
+        bytes_written_ = 0;
+      }
+    }
+    ScheduleNextWrite();
+  }
 }
 
 void MojoDecoderBufferWriter::OnPipeError(MojoResult result) {
   DVLOG(1) << __func__ << "(" << result << ")";
   DCHECK(IsPipeReadWriteError(result));
 
-  if (media_buffer_) {
+  producer_handle_.reset();
+
+  if (!pending_buffers_.empty()) {
     DVLOG(1) << __func__ << ": writing to data pipe failed. result=" << result
-             << ", buffer size=" << media_buffer_->data_size()
+             << ", buffer size=" << pending_buffers_.front()->data_size()
              << ", num_bytes(written)=" << bytes_written_;
-    media_buffer_ = nullptr;
+    pending_buffers_.clear();
     bytes_written_ = 0;
   }
-  producer_handle_.reset();
-}
-
-void MojoDecoderBufferWriter::OnPipeWritable(MojoResult result) {
-  DVLOG(4) << __func__ << "(" << result << ")";
-
-  if (result != MOJO_RESULT_OK)
-    OnPipeError(result);
-  else if (media_buffer_)
-    WriteDecoderBufferData();
-}
-
-MojoResult MojoDecoderBufferWriter::WriteDecoderBufferData() {
-  DVLOG(4) << __func__;
-  DCHECK(media_buffer_);
-
-  uint32_t buffer_size =
-      base::checked_cast<uint32_t>(media_buffer_->data_size());
-  DCHECK_GT(buffer_size, 0u);
-
-  uint32_t num_bytes = buffer_size - bytes_written_;
-  DCHECK_GT(num_bytes, 0u);
-
-  MojoResult result =
-      producer_handle_->WriteData(media_buffer_->data() + bytes_written_,
-                                  &num_bytes, MOJO_WRITE_DATA_FLAG_NONE);
-
-  if (IsPipeReadWriteError(result)) {
-    OnPipeError(result);
-  } else {
-    pipe_watcher_.ArmOrNotify();
-    if (result == MOJO_RESULT_OK) {
-      DCHECK_GT(num_bytes, 0u);
-      bytes_written_ += num_bytes;
-      if (bytes_written_ == buffer_size) {
-        media_buffer_ = nullptr;
-        bytes_written_ = 0;
-      }
-    }
-  }
-
-  return result;
 }
 
 }  // namespace media
diff --git a/media/mojo/common/mojo_decoder_buffer_converter.h b/media/mojo/common/mojo_decoder_buffer_converter.h
index 10940f3..0b417e2 100644
--- a/media/mojo/common/mojo_decoder_buffer_converter.h
+++ b/media/mojo/common/mojo_decoder_buffer_converter.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "base/containers/circular_deque.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "media/base/demuxer_stream.h"
@@ -18,8 +19,8 @@
 
 class DecoderBuffer;
 
-// A helper class that converts mojom::DecoderBuffer to media::DecoderBuffer.
-// The data part of the DecoderBuffer is read from a DataPipe.
+// Combines mojom::DecoderBuffers with data read from a DataPipe to produce
+// media::DecoderBuffers (counterpart of MojoDecoderBufferWriter).
 class MojoDecoderBufferReader {
  public:
   using ReadCB = base::OnceCallback<void(scoped_refptr<DecoderBuffer>)>;
@@ -35,30 +36,56 @@
 
   ~MojoDecoderBufferReader();
 
-  // Converts |buffer| into a DecoderBuffer (read data from DataPipe if needed).
-  // |read_cb| is called with the result DecoderBuffer.
-  // Reports a null DecoderBuffer in case of an error.
+  // Enqueues conversion of and reading data for a mojom::DecoderBuffer. Once
+  // the data has been read, |read_cb| will be called with the converted
+  // media::DecoderBuffer.
+  //
+  // |read_cb| will be called in the same order as ReadDecoderBuffer(). This
+  // order must match the order that the data was written into the DataPipe!
+  // Callbacks may run on the original stack, on a Mojo stack, or on a future
+  // ReadDecoderBuffer() stack.
+  //
+  // If reading fails (for example, if the DataPipe is closed), |read_cb| will
+  // be called with nullptr.
   void ReadDecoderBuffer(mojom::DecoderBufferPtr buffer, ReadCB read_cb);
 
  private:
-  void OnPipeError(MojoResult result);
-  void OnPipeReadable(MojoResult result);
+  void CancelReadCB(ReadCB read_cb);
+  void CompleteCurrentRead();
+  void ScheduleNextRead();
+  void OnPipeReadable(MojoResult result, const mojo::HandleSignalsState& state);
   void ReadDecoderBufferData();
+  void OnPipeError(MojoResult result);
 
-  // For reading the data section of a DecoderBuffer.
+  // Read side of the DataPipe for receiving DecoderBuffer data.
   mojo::ScopedDataPipeConsumerHandle consumer_handle_;
-  mojo::SimpleWatcher pipe_watcher_;
 
-  // Only valid during pending read.
-  ReadCB read_cb_;
-  scoped_refptr<DecoderBuffer> media_buffer_;
+  // Provides notification about |consumer_handle_| readiness.
+  mojo::SimpleWatcher pipe_watcher_;
+  bool armed_;
+
+  // Buffers waiting to be read in sequence.
+  base::circular_deque<scoped_refptr<DecoderBuffer>> pending_buffers_;
+
+  // Callbacks for pending buffers.
+  base::circular_deque<ReadCB> pending_read_cbs_;
+
+  // Number of bytes already read into the current buffer.
   uint32_t bytes_read_;
 
   DISALLOW_COPY_AND_ASSIGN(MojoDecoderBufferReader);
 };
 
-// A helper class that converts media::DecoderBuffer to mojom::DecoderBuffer.
-// The data part of the DecoderBuffer is written into a DataPipe.
+// Converts media::DecoderBuffers to mojom::DecoderBuffers, writing the data
+// part to a DataPipe (counterpart of MojoDecoderBufferReader).
+//
+// If necessary, writes to the DataPipe will be chunked to fit.
+// MojoDecoderBufferWriter maintains an internal queue of buffers to enable
+// this asynchronous process.
+//
+// On DataPipe closure, future calls to WriteDecoderBuffer() will return
+// nullptr. There is no mechanism to determine which past writes were
+// successful prior to the closure.
 class MojoDecoderBufferWriter {
  public:
   // Creates a MojoDecoderBufferWriter of |type| and set the |consumer_handle|.
@@ -72,23 +99,30 @@
 
   ~MojoDecoderBufferWriter();
 
-  // Converts a DecoderBuffer into mojo DecoderBuffer.
-  // DecoderBuffer data is asynchronously written into DataPipe if needed.
-  // Returns null if conversion failed or if the data pipe is already closed.
+  // Converts a media::DecoderBuffer to a mojom::DecoderBuffer and enqueues the
+  // data to be written to the DataPipe.
+  //
+  // Returns nullptr if the DataPipe is already closed.
   mojom::DecoderBufferPtr WriteDecoderBuffer(
       const scoped_refptr<DecoderBuffer>& media_buffer);
 
  private:
+  void ScheduleNextWrite();
+  void OnPipeWritable(MojoResult result, const mojo::HandleSignalsState& state);
+  void WriteDecoderBufferData();
   void OnPipeError(MojoResult result);
-  void OnPipeWritable(MojoResult result);
-  MojoResult WriteDecoderBufferData();
 
-  // For writing the data section of DecoderBuffer into DataPipe.
+  // Write side of the DataPipe for sending DecoderBuffer data.
   mojo::ScopedDataPipeProducerHandle producer_handle_;
-  mojo::SimpleWatcher pipe_watcher_;
 
-  // Only valid when data is being written to the pipe.
-  scoped_refptr<DecoderBuffer> media_buffer_;
+  // Provides notifications about |producer_handle_| readiness.
+  mojo::SimpleWatcher pipe_watcher_;
+  bool armed_;
+
+  // Buffers waiting to be written in sequence.
+  base::circular_deque<scoped_refptr<DecoderBuffer>> pending_buffers_;
+
+  // Number of bytes already written from the current buffer.
   uint32_t bytes_written_;
 
   DISALLOW_COPY_AND_ASSIGN(MojoDecoderBufferWriter);
diff --git a/media/mojo/common/mojo_decoder_buffer_converter_unittest.cc b/media/mojo/common/mojo_decoder_buffer_converter_unittest.cc
index 033c40c..a0fd834 100644
--- a/media/mojo/common/mojo_decoder_buffer_converter_unittest.cc
+++ b/media/mojo/common/mojo_decoder_buffer_converter_unittest.cc
@@ -153,23 +153,6 @@
   converter.ConvertAndVerify(buffer);
 }
 
-// This test verifies that MojoDecoderBufferWriter returns NULL if data pipe
-// is already closed.
-TEST(MojoDecoderBufferConverterTest, ReaderSidePipeError) {
-  base::MessageLoop message_loop;
-  const uint8_t kData[] = "Hello, world";
-  const size_t kDataSize = arraysize(kData);
-  scoped_refptr<DecoderBuffer> media_buffer =
-      DecoderBuffer::CopyFrom(kData, kDataSize);
-
-  MojoDecoderBufferConverter converter;
-  // Before sending the buffer, close the handle on reader side.
-  converter.reader.reset();
-  mojom::DecoderBufferPtr mojo_buffer =
-      converter.writer->WriteDecoderBuffer(media_buffer);
-  EXPECT_TRUE(mojo_buffer.is_null());
-}
-
 // This test verifies that MojoDecoderBufferReader::ReadCB is called with a
 // NULL DecoderBuffer if data pipe is closed during transmission.
 TEST(MojoDecoderBufferConverterTest, WriterSidePipeError) {
@@ -198,4 +181,52 @@
   run_loop.Run();
 }
 
+// This test verifies that MojoDecoderBuffer supports concurrent writes and
+// reads.
+TEST(MojoDecoderBufferConverterTest, ConcurrentDecoderBuffers) {
+  base::MessageLoop message_loop;
+  base::RunLoop run_loop;
+
+  // Prevent all of the buffers from fitting at once to exercise the chunking
+  // logic.
+  MojoDecoderBufferConverter converter(4);
+
+  // Three buffers: normal, EOS, normal.
+  const uint8_t kData[] = "Hello, world";
+  const size_t kDataSize = arraysize(kData);
+  scoped_refptr<DecoderBuffer> media_buffer1 =
+      DecoderBuffer::CopyFrom(kData, kDataSize);
+  scoped_refptr<DecoderBuffer> media_buffer2(DecoderBuffer::CreateEOSBuffer());
+  scoped_refptr<DecoderBuffer> media_buffer3 =
+      DecoderBuffer::CopyFrom(kData, kDataSize);
+
+  // Expect the read callbacks to be issued in the same order.
+  ::testing::InSequence scoper;
+  base::MockCallback<MojoDecoderBufferReader::ReadCB> mock_cb1;
+  base::MockCallback<MojoDecoderBufferReader::ReadCB> mock_cb2;
+  base::MockCallback<MojoDecoderBufferReader::ReadCB> mock_cb3;
+  EXPECT_CALL(mock_cb1, Run(MatchesDecoderBuffer(media_buffer1)));
+  EXPECT_CALL(mock_cb2, Run(MatchesDecoderBuffer(media_buffer2)));
+  EXPECT_CALL(mock_cb3, Run(MatchesDecoderBuffer(media_buffer3)))
+      .WillOnce(testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
+
+  // Write all of the buffers at once.
+  mojom::DecoderBufferPtr mojo_buffer1 =
+      converter.writer->WriteDecoderBuffer(media_buffer1);
+  mojom::DecoderBufferPtr mojo_buffer2 =
+      converter.writer->WriteDecoderBuffer(media_buffer2);
+  mojom::DecoderBufferPtr mojo_buffer3 =
+      converter.writer->WriteDecoderBuffer(media_buffer3);
+
+  // Read all of the buffers at once.
+  // Technically could be satisfied by ReadDecoderBuffer() blocking, but that's
+  // actually a valid implementation. (Quitting the |run_loop| won't work
+  // properly with that setup though.)
+  converter.reader->ReadDecoderBuffer(std::move(mojo_buffer1), mock_cb1.Get());
+  converter.reader->ReadDecoderBuffer(std::move(mojo_buffer2), mock_cb2.Get());
+  converter.reader->ReadDecoderBuffer(std::move(mojo_buffer3), mock_cb3.Get());
+
+  run_loop.Run();
+}
+
 }  // namespace media
diff --git a/media/mojo/services/gpu_mojo_media_client.cc b/media/mojo/services/gpu_mojo_media_client.cc
index 1011122..f85f996 100644
--- a/media/mojo/services/gpu_mojo_media_client.cc
+++ b/media/mojo/services/gpu_mojo_media_client.cc
@@ -69,18 +69,6 @@
 
   return channel->LookupCommandBuffer(route_id);
 }
-
-std::unique_ptr<AndroidOverlay> CreateAndroidOverlay(
-    base::WeakPtr<MediaGpuChannelManager> media_gpu_channel_manager,
-    const base::UnguessableToken& routing_token,
-    media::AndroidOverlayConfig config) {
-  if (!media_gpu_channel_manager)
-    return nullptr;
-  AndroidOverlayMojoFactoryCB factory_cb =
-      media_gpu_channel_manager->GetOverlayFactory();
-  DCHECK(factory_cb);
-  return factory_cb.Run(routing_token, std::move(config));
-}
 #endif  // BUILDFLAG(ENABLE_MEDIA_CODEC_VIDEO_DECODER)
 #endif  // defined(OS_ANDROID)
 
@@ -88,9 +76,11 @@
 
 GpuMojoMediaClient::GpuMojoMediaClient(
     scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
-    base::WeakPtr<MediaGpuChannelManager> media_gpu_channel_manager)
+    base::WeakPtr<MediaGpuChannelManager> media_gpu_channel_manager,
+    AndroidOverlayMojoFactoryCB android_overlay_factory_cb)
     : gpu_task_runner_(std::move(gpu_task_runner)),
-      media_gpu_channel_manager_(std::move(media_gpu_channel_manager)) {}
+      media_gpu_channel_manager_(std::move(media_gpu_channel_manager)),
+      android_overlay_factory_cb_(std::move(android_overlay_factory_cb)) {}
 
 GpuMojoMediaClient::~GpuMojoMediaClient() {}
 
@@ -125,8 +115,7 @@
       AVDACodecAllocator::GetInstance(),
       base::MakeUnique<AndroidVideoSurfaceChooserImpl>(
           DeviceInfo::GetInstance()->IsSetOutputSurfaceSupported()),
-      base::Bind(&CreateAndroidOverlay, media_gpu_channel_manager_),
-      std::move(request_overlay_info_cb),
+      android_overlay_factory_cb_, std::move(request_overlay_info_cb),
       base::MakeUnique<VideoFrameFactoryImpl>(),
       context_ref_factory_->CreateRef());
 #else
diff --git a/media/mojo/services/gpu_mojo_media_client.h b/media/mojo/services/gpu_mojo_media_client.h
index 0b1375d3..e40c936 100644
--- a/media/mojo/services/gpu_mojo_media_client.h
+++ b/media/mojo/services/gpu_mojo_media_client.h
@@ -11,6 +11,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/single_thread_task_runner.h"
+#include "media/base/android_overlay_mojo_factory.h"
 #include "media/mojo/services/mojo_media_client.h"
 
 namespace media {
@@ -23,7 +24,8 @@
   // is expected to be the GPU main thread task runner.
   GpuMojoMediaClient(
       scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
-      base::WeakPtr<MediaGpuChannelManager> media_gpu_channel_manager);
+      base::WeakPtr<MediaGpuChannelManager> media_gpu_channel_manager,
+      AndroidOverlayMojoFactoryCB android_overlay_factory_cb);
   ~GpuMojoMediaClient() final;
 
   // MojoMediaClient implementation.
@@ -45,6 +47,7 @@
   scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_;
   base::WeakPtr<MediaGpuChannelManager> media_gpu_channel_manager_;
   service_manager::ServiceContextRefFactory* context_ref_factory_;
+  AndroidOverlayMojoFactoryCB android_overlay_factory_cb_;
 
   DISALLOW_COPY_AND_ASSIGN(GpuMojoMediaClient);
 };
diff --git a/media/mojo/services/media_service_factory.cc b/media/mojo/services/media_service_factory.cc
index ef8d61c..79809c4 100644
--- a/media/mojo/services/media_service_factory.cc
+++ b/media/mojo/services/media_service_factory.cc
@@ -30,10 +30,12 @@
 
 std::unique_ptr<service_manager::Service> CreateGpuMediaService(
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-    base::WeakPtr<MediaGpuChannelManager> media_gpu_channel_manager) {
+    base::WeakPtr<MediaGpuChannelManager> media_gpu_channel_manager,
+    AndroidOverlayMojoFactoryCB android_overlay_factory_cb) {
   return std::unique_ptr<service_manager::Service>(
       new MediaService(base::MakeUnique<GpuMojoMediaClient>(
-          task_runner, media_gpu_channel_manager)));
+          task_runner, media_gpu_channel_manager,
+          std::move(android_overlay_factory_cb))));
 }
 
 std::unique_ptr<service_manager::Service> CreateMediaServiceForTesting() {
diff --git a/media/mojo/services/media_service_factory.h b/media/mojo/services/media_service_factory.h
index 40e34a3..4151508 100644
--- a/media/mojo/services/media_service_factory.h
+++ b/media/mojo/services/media_service_factory.h
@@ -10,6 +10,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/single_thread_task_runner.h"
+#include "media/base/android_overlay_mojo_factory.h"
 #include "media/mojo/services/media_mojo_export.h"
 #include "services/service_manager/public/cpp/service.h"
 
@@ -29,7 +30,8 @@
 std::unique_ptr<service_manager::Service> MEDIA_MOJO_EXPORT
 CreateGpuMediaService(
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-    base::WeakPtr<MediaGpuChannelManager> media_gpu_channel_manager);
+    base::WeakPtr<MediaGpuChannelManager> media_gpu_channel_manager,
+    AndroidOverlayMojoFactoryCB android_overlay_factory_cb);
 
 // Creates a MediaService instance using the TestMojoMediaClient.
 std::unique_ptr<service_manager::Service> MEDIA_MOJO_EXPORT
diff --git a/media/remoting/metrics.cc b/media/remoting/metrics.cc
index b7914cd..ffdc450 100644
--- a/media/remoting/metrics.cc
+++ b/media/remoting/metrics.cc
@@ -81,6 +81,40 @@
                              base::TimeDelta::FromSeconds(15),
                              base::TimeDelta::FromHours(12), 50);
 
+  if (session_duration <= base::TimeDelta::FromSeconds(15)) {
+    // Record the session duration in finer scale for short sessions
+    UMA_HISTOGRAM_CUSTOM_TIMES("Media.Remoting.ShortSessionDuration",
+                               session_duration,
+                               base::TimeDelta::FromSecondsD(0.1),
+                               base::TimeDelta::FromSeconds(15), 60);
+
+    if (session_duration <= base::TimeDelta::FromSecondsD(0.1)) {
+      UMA_HISTOGRAM_ENUMERATION(
+          "Media.Remoting.SessionStopTrigger.Duration0To100MilliSec", trigger,
+          STOP_TRIGGER_MAX + 1);
+    } else if (session_duration <= base::TimeDelta::FromSeconds(1)) {
+      UMA_HISTOGRAM_ENUMERATION(
+          "Media.Remoting.SessionStopTrigger.Duration100MilliSecTo1Sec",
+          trigger, STOP_TRIGGER_MAX + 1);
+    } else if (session_duration <= base::TimeDelta::FromSeconds(3)) {
+      UMA_HISTOGRAM_ENUMERATION(
+          "Media.Remoting.SessionStopTrigger.Duration1To3Sec", trigger,
+          STOP_TRIGGER_MAX + 1);
+    } else if (session_duration <= base::TimeDelta::FromSeconds(5)) {
+      UMA_HISTOGRAM_ENUMERATION(
+          "Media.Remoting.SessionStopTrigger.Duration3To5Sec", trigger,
+          STOP_TRIGGER_MAX + 1);
+    } else if (session_duration <= base::TimeDelta::FromSeconds(10)) {
+      UMA_HISTOGRAM_ENUMERATION(
+          "Media.Remoting.SessionStopTrigger.Duration5To10Sec", trigger,
+          STOP_TRIGGER_MAX + 1);
+    } else {
+      UMA_HISTOGRAM_ENUMERATION(
+          "Media.Remoting.SessionStopTrigger.Duration10To15Sec", trigger,
+          STOP_TRIGGER_MAX + 1);
+    }
+  }
+
   // Reset |start_trigger_| since metrics recording of the current remoting
   // session has now completed.
   start_trigger_ = base::nullopt;
diff --git a/media/renderers/video_renderer_impl.cc b/media/renderers/video_renderer_impl.cc
index fde818a..956ba68 100644
--- a/media/renderers/video_renderer_impl.cc
+++ b/media/renderers/video_renderer_impl.cc
@@ -740,6 +740,9 @@
   DCHECK_GE(frames_dropped_, 0);
 
   if (frames_decoded_ || frames_dropped_) {
+    if (frames_dropped_)
+      TRACE_EVENT_INSTANT1("media", "VideoFramesDropped",
+                           TRACE_EVENT_SCOPE_THREAD, "count", frames_dropped_);
     PipelineStatistics statistics;
     statistics.video_frames_decoded = frames_decoded_;
     statistics.video_frames_dropped = frames_dropped_;
diff --git a/media/test/BUILD.gn b/media/test/BUILD.gn
index ca2f3d9a..581ee2b 100644
--- a/media/test/BUILD.gn
+++ b/media/test/BUILD.gn
@@ -211,9 +211,6 @@
     ]
 
     libfuzzer_options = [
-      # This is done to avoid DEATH of ASan with "Thread limit exceeded" error.
-      "runs=500000",
-
       # This is done to suppress tons of log messages generated by gmock asserts.
       "close_fd_mask=1",
     ]
diff --git a/media/test/data/README b/media/test/data/README
index d02bf06..a5b488a 100644
--- a/media/test/data/README
+++ b/media/test/data/README
@@ -125,6 +125,11 @@
   (Additional TS packets were constructed manually and prepended to convey the encryption metadata, notably key id and IV).
   mediafilesegmenter -S -P -k 'key_iv.bin' -t 10 -start-segments-with-iframe -f 'output/' bear-1280x720.ts
 
+bear-1280x720-hls-with-CAT.ts: same as bear-1280x720-hls.ts but with an extra TS packet prepended. This is the same as the first of the metadata packets in
+  bear-1280x720-hls-sample-aes.ts. Its presence indicates that SAMPLE_AES encryption may occur later in the stream, and causes the initial audio and video configs
+  to have an encryption_scheme (of AES-CBC). The actual data is unencrypted, which is indicated by the lack of key ID and IV. This ends up very similar to how
+  clear leader of an otherwise encrypted stream can occur in MP4.
+
 [1] 30313233343536373839303132333435
 [2] ebdd62f16814d27b68ef122afce4ae3c
 [3] KeyIds and Keys are created by left rotating key ID [1] and key [2] using
diff --git a/media/test/data/bear-1280x720-hls-with-CAT.bin b/media/test/data/bear-1280x720-hls-with-CAT.bin
new file mode 100644
index 0000000..09239d3
--- /dev/null
+++ b/media/test/data/bear-1280x720-hls-with-CAT.bin
Binary files differ
diff --git a/media/test/pipeline_integration_fuzzertest.cc b/media/test/pipeline_integration_fuzzertest.cc
index c1ea3fde..8e3e1612 100644
--- a/media/test/pipeline_integration_fuzzertest.cc
+++ b/media/test/pipeline_integration_fuzzertest.cc
@@ -218,8 +218,22 @@
     media::ProgressivePipelineIntegrationFuzzerTest test;
     test.RunTest(data, size);
   } else {
-    media::MediaSourcePipelineIntegrationFuzzerTest test;
-    test.RunTest(data, size, MseFuzzerVariantEnumToMimeTypeString(variant));
+    // Sequentially fuzz with new and old MSE buffering APIs.  See
+    // https://crbug.com/718641.
+    {
+      base::test::ScopedFeatureList features_with_buffering_api_forced;
+      features_with_buffering_api_forced.InitAndEnableFeature(
+          media::kMseBufferByPts);
+      media::MediaSourcePipelineIntegrationFuzzerTest test;
+      test.RunTest(data, size, MseFuzzerVariantEnumToMimeTypeString(variant));
+    }
+    {
+      base::test::ScopedFeatureList features_with_buffering_api_forced;
+      features_with_buffering_api_forced.InitAndDisableFeature(
+          media::kMseBufferByPts);
+      media::MediaSourcePipelineIntegrationFuzzerTest test;
+      test.RunTest(data, size, MseFuzzerVariantEnumToMimeTypeString(variant));
+    }
   }
 
   return 0;
diff --git a/media/test/pipeline_integration_test_base.cc b/media/test/pipeline_integration_test_base.cc
index 28c3de7b..ce9719f8 100644
--- a/media/test/pipeline_integration_test_base.cc
+++ b/media/test/pipeline_integration_test_base.cc
@@ -233,7 +233,7 @@
   // that it's called at least once. Such streams may repeatedly update their
   // duration as new packets are demuxed.
   if (test_type & kUnreliableDuration) {
-    EXPECT_CALL(*this, OnDurationChange()).Times(AtLeast(1));
+    EXPECT_CALL(*this, OnDurationChange()).Times(AnyNumber());
   } else {
     EXPECT_CALL(*this, OnDurationChange())
         .Times(AtMost(2))
diff --git a/mojo/edk/system/ports/node.cc b/mojo/edk/system/ports/node.cc
index a35190e3..68620d1 100644
--- a/mojo/edk/system/ports/node.cc
+++ b/mojo/edk/system/ports/node.cc
@@ -114,10 +114,8 @@
 #if DCHECK_IS_ON()
     for (auto& entry : ports_) {
       DVLOG(2) << "Port " << entry.first << " referencing node "
-               << entry.second.port->peer_node_name
-               << " is blocking shutdown of "
-               << "node " << name_ << " (state=" << entry.second.port->state
-               << ")";
+               << entry.second->peer_node_name << " is blocking shutdown of "
+               << "node " << name_ << " (state=" << entry.second->state << ")";
     }
 #endif
     return ports_.empty();
@@ -130,7 +128,7 @@
   // need to be blazingly fast.
   bool can_shutdown = true;
   for (auto& entry : ports_) {
-    PortRef port_ref(entry.first, entry.second.port);
+    PortRef port_ref(entry.first, entry.second);
     SinglePortLocker locker(&port_ref);
     auto* port = locker.port();
     if (port->peer_node_name != name_ && port->state != Port::kReceiving) {
@@ -161,7 +159,7 @@
   base::subtle::MemoryBarrier();
 #endif
 
-  *port_ref = PortRef(port_name, iter->second.port);
+  *port_ref = PortRef(port_name, iter->second);
   return OK;
 }
 
@@ -783,7 +781,7 @@
 int Node::AddPortWithName(const PortName& port_name, scoped_refptr<Port> port) {
   PortLocker::AssertNoPortsLockedOnCurrentThread();
   base::AutoLock lock(ports_lock_);
-  if (!ports_.emplace(port_name, PortTableEntry(std::move(port))).second)
+  if (!ports_.emplace(port_name, std::move(port)).second)
     return OOPS(ERROR_PORT_EXISTS);  // Suggests a bad UUID generator.
   DVLOG(2) << "Created port " << port_name << "@" << name_;
   return OK;
@@ -797,7 +795,7 @@
     auto it = ports_.find(port_name);
     if (it == ports_.end())
       return;
-    port = std::move(it->second.port);
+    port = std::move(it->second);
     ports_.erase(it);
   }
   // NOTE: We are careful not to release the port's messages while holding any
@@ -1293,7 +1291,7 @@
     base::AutoLock ports_lock(ports_lock_);
 
     for (auto iter = ports_.begin(); iter != ports_.end(); ++iter) {
-      PortRef port_ref(iter->first, iter->second.port);
+      PortRef port_ref(iter->first, iter->second);
       {
         SinglePortLocker locker(&port_ref);
         auto* port = locker.port();
@@ -1323,7 +1321,7 @@
           if (port->state != Port::kReceiving) {
             dead_proxies_to_broadcast.push_back(iter->first);
             std::vector<std::unique_ptr<UserMessageEvent>> messages;
-            iter->second.port->message_queue.TakeAllMessages(&messages);
+            iter->second->message_queue.TakeAllMessages(&messages);
             for (auto& message : messages)
               undelivered_messages.emplace_back(std::move(message));
           }
@@ -1378,23 +1376,6 @@
 }
 #endif
 
-Node::PortTableEntry::PortTableEntry(scoped_refptr<Port> port)
-    : port(std::move(port)) {}
-
-Node::PortTableEntry::PortTableEntry(PortTableEntry&& other) = default;
-
-Node::PortTableEntry::~PortTableEntry() {
-  // We don't really anticipate hitting this CHECK given that we should be
-  // effectively working around memory corruption. Still it's a potentially
-  // useful signal if anything continues to go wrong, and it forces the value to
-  // be used.
-  CHECK_EQ(0x1827364554637281ULL, sentinel_value_);
-  sentinel_value_ = 0x8127364554637281ULL;
-}
-
-Node::PortTableEntry& Node::PortTableEntry::operator=(PortTableEntry&& other) =
-    default;
-
 }  // namespace ports
 }  // namespace edk
 }  // namespace mojo
diff --git a/mojo/edk/system/ports/node.h b/mojo/edk/system/ports/node.h
index 3032d7b..5bc8a12 100644
--- a/mojo/edk/system/ports/node.h
+++ b/mojo/edk/system/ports/node.h
@@ -227,24 +227,6 @@
   const NodeName name_;
   const DelegateHolder delegate_;
 
-  // A wrapper structure for Port table entries. https://crbug.com/725605 likely
-  // indicates memory corruption stomping on the Port table, and there is no
-  // clue as to where the corruption is coming from. Changing the size of the
-  // map entry allocations should effectively work around the bug, as it did for
-  // https://crbug.com/740044.
-  struct PortTableEntry {
-    explicit PortTableEntry(scoped_refptr<Port> port);
-    PortTableEntry(const PortTableEntry&) = delete;
-    PortTableEntry(PortTableEntry&& other);
-    ~PortTableEntry();
-
-    PortTableEntry& operator=(const PortTableEntry&) = delete;
-    PortTableEntry& operator=(PortTableEntry&& other);
-
-    uint64_t sentinel_value_ = 0x1827364554637281ULL;
-    scoped_refptr<Port> port;
-  };
-
   // Guards |ports_|. This must never be acquired while an individual port's
   // lock is held on the same thread. Conversely, individual port locks may be
   // acquired while this one is held.
@@ -253,7 +235,7 @@
   // destruction, it is also important to ensure that such events are never
   // destroyed while this (or any individual Port) lock is held.
   base::Lock ports_lock_;
-  std::unordered_map<PortName, PortTableEntry> ports_;
+  std::unordered_map<PortName, scoped_refptr<Port>> ports_;
 
   DISALLOW_COPY_AND_ASSIGN(Node);
 };
diff --git a/mojo/public/cpp/system/simple_watcher.h b/mojo/public/cpp/system/simple_watcher.h
index d9f7251..d329038d 100644
--- a/mojo/public/cpp/system/simple_watcher.h
+++ b/mojo/public/cpp/system/simple_watcher.h
@@ -159,8 +159,8 @@
   // state of the handle is placed in |*ready_state| if |ready_state| is
   // non-null.
   //
-  // If the watcher is successfully armed, this returns |MOJO_RESULT_OK| and
-  // |ready_result| and |ready_state| are ignored.
+  // If the watcher is successfully armed (or was already armed), this returns
+  // |MOJO_RESULT_OK| and |ready_result| and |ready_state| are ignored.
   MojoResult Arm(MojoResult* ready_result = nullptr,
                  HandleSignalsState* ready_state = nullptr);
 
diff --git a/native_client_sdk/src/BUILD.gn b/native_client_sdk/src/BUILD.gn
index 5c9fa1215..ff31576 100644
--- a/native_client_sdk/src/BUILD.gn
+++ b/native_client_sdk/src/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/features.gni")
+import("//components/nacl/features.gni")
 
 declare_args() {
   # Set to true if cross compiling trusted (e.g. building sel_ldr_arm on x86)
diff --git a/net/BUILD.gn b/net/BUILD.gn
index c71c414..bda4db0b 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1028,10 +1028,6 @@
       "nqe/throughput_analyzer.cc",
       "nqe/throughput_analyzer.h",
       "nqe/weighted_observation.h",
-      "ntlm/des.cc",
-      "ntlm/des.h",
-      "ntlm/md4.cc",
-      "ntlm/md4.h",
       "ntlm/ntlm.cc",
       "ntlm/ntlm.h",
       "ntlm/ntlm_buffer_reader.cc",
@@ -1786,10 +1782,6 @@
 
     if (is_win) {
       sources -= [
-        "ntlm/des.cc",
-        "ntlm/des.h",
-        "ntlm/md4.cc",
-        "ntlm/md4.h",
         "ntlm/ntlm.cc",
         "ntlm/ntlm.h",
         "ntlm/ntlm_buffer_reader.cc",
@@ -4919,8 +4911,6 @@
     "nqe/observation_buffer_unittest.cc",
     "nqe/socket_watcher_unittest.cc",
     "nqe/throughput_analyzer_unittest.cc",
-    "ntlm/des_unittest.cc",
-    "ntlm/md4_unittest.cc",
     "ntlm/ntlm_buffer_reader_unittest.cc",
     "ntlm/ntlm_buffer_writer_unittest.cc",
     "ntlm/ntlm_client_unittest.cc",
@@ -5179,6 +5169,7 @@
     "tools/content_decoder_tool/content_decoder_tool_unittest.cc",
     "tools/quic/quic_simple_client_test.cc",
     "tools/tld_cleanup/tld_cleanup_util_unittest.cc",
+    "url_request/redirect_info_unittest.cc",
     "url_request/report_sender_unittest.cc",
     "url_request/url_fetcher_impl_unittest.cc",
     "url_request/url_fetcher_response_writer_unittest.cc",
@@ -5338,8 +5329,6 @@
   if (is_win) {
     sources -= [
       "http/http_auth_handler_ntlm_portable_unittest.cc",
-      "ntlm/des_unittest.cc",
-      "ntlm/md4_unittest.cc",
       "ntlm/ntlm_buffer_reader_unittest.cc",
       "ntlm/ntlm_buffer_writer_unittest.cc",
       "ntlm/ntlm_client_unittest.cc",
diff --git a/net/cert/cert_verify_proc_builtin.cc b/net/cert/cert_verify_proc_builtin.cc
index 3292d47..30097f3a 100644
--- a/net/cert/cert_verify_proc_builtin.cc
+++ b/net/cert/cert_verify_proc_builtin.cc
@@ -17,6 +17,7 @@
 #include "net/cert/cert_status_flags.h"
 #include "net/cert/cert_verify_proc.h"
 #include "net/cert/cert_verify_result.h"
+#include "net/cert/crl_set.h"
 #include "net/cert/internal/cert_errors.h"
 #include "net/cert/internal/cert_issuer_source_static.h"
 #include "net/cert/internal/common_cert_errors.h"
@@ -32,6 +33,117 @@
 
 namespace {
 
+DEFINE_CERT_ERROR_ID(kCertificateRevoked, "Certificate is revoked");
+
+// Enum to indicate whether the revocation status for a certificate is
+// known. When the status is "known" it means it was either revoked, or
+// affirmatively unrevoked.
+enum class CertRevocationStatus {
+  kUnknown,
+  kKnown,
+};
+
+// TODO(eroman): The path building code in this file enforces its idea of weak
+// keys, and separately cert_verify_proc.cc also checks the chains with its
+// own policy. These policies should be aligned, to give path building the
+// best chance of finding a good path.
+class PathBuilderDelegateImpl : public SimplePathBuilderDelegate {
+ public:
+  // Uses the default policy from SimplePathBuilderDelegate, which requires RSA
+  // keys to be at least 1024-bits large, and accepts SHA1 certificates.
+  PathBuilderDelegateImpl(CRLSet* crl_set)
+      : SimplePathBuilderDelegate(1024), crl_set_(crl_set) {}
+
+  // This is called for each built chain, including ones which failed. It is
+  // responsible for adding errors to the built chain if it is not acceptable.
+  void CheckPathAfterVerification(const CertPath& path,
+                                  CertPathErrors* errors) override {
+    CheckRevocation(path, errors);
+  }
+
+ private:
+  // This method checks whether a certificate chain has been revoked, and if
+  // so adds errors to the affected certificates.
+  CertRevocationStatus CheckRevocation(const CertPath& path,
+                                       CertPathErrors* errors) const {
+    // First check for revocations using the CRLSet. This does not require
+    // any network activity.
+    if (crl_set_) {
+      CertRevocationStatus status = CheckRevocationUsingCRLSet(path, errors);
+      if (status == CertRevocationStatus::kKnown)
+        return status;
+    }
+
+    // TODO(eroman): Next check revocation using OCSP and CRL.
+    return CertRevocationStatus::kUnknown;
+  }
+
+  // Checks the revocation status of the certificate chain using the CRLSet. If
+  // any certificate is revoked, the kCertificateRevoked high-severity error is
+  // added.
+  CertRevocationStatus CheckRevocationUsingCRLSet(
+      const CertPath& path,
+      CertPathErrors* errors) const {
+    // Iterate from root certificate towards the leaf (the root certificate is
+    // also checked for revocation by CRLSet).
+    std::string issuer_spki_hash;
+    for (size_t reverse_i = 0; reverse_i < path.certs.size(); ++reverse_i) {
+      size_t i = path.certs.size() - reverse_i - 1;
+      const scoped_refptr<ParsedCertificate>& cert = path.certs[i];
+
+      // True if |cert| is the root of the chain.
+      const bool is_root = reverse_i == 0;
+      // True if |cert| is the leaf certificate of the chain.
+      const bool is_target = i == 0;
+
+      // Check for revocation using the certificate's SPKI.
+      std::string spki_hash =
+          crypto::SHA256HashString(cert->tbs().spki_tlv.AsStringPiece());
+      CRLSet::Result result = crl_set_->CheckSPKI(spki_hash);
+
+      // Check for revocation using the certificate's serial number and issuer's
+      // SPKI.
+      if (result != CRLSet::REVOKED && !is_root) {
+        result = crl_set_->CheckSerial(
+            cert->tbs().serial_number.AsStringPiece(), issuer_spki_hash);
+      }
+
+      // Prepare for the next iteration.
+      issuer_spki_hash = std::move(spki_hash);
+
+      switch (result) {
+        case CRLSet::REVOKED:
+          // If any certificate was revoked, add an error to the chain and
+          // return (no need to check the remaining certificates).
+          errors->GetErrorsForCert(i)->AddError(kCertificateRevoked);
+          return CertRevocationStatus::kKnown;
+        case CRLSet::UNKNOWN:
+          // If the status is unknown, advance to the subordinate certificate.
+          break;
+        case CRLSet::GOOD:
+          if (is_target && !crl_set_->IsExpired()) {
+            // If the target is covered by the CRLSet and known good, consider
+            // the entire chain to be valid (even though the revocation status
+            // of the intermediates may have been UNKNOWN).
+            //
+            // Only the leaf certificate is considered for coverage because some
+            // intermediates have CRLs with no revocations (after filtering) and
+            // those CRLs are pruned from the CRLSet at generation time.
+            return CertRevocationStatus::kKnown;
+          }
+          break;
+      }
+    }
+
+    // If no certificate was revoked, and the target was not known good, then
+    // the revocation status is still unknown.
+    return CertRevocationStatus::kUnknown;
+  }
+
+  // The CRLSet may be null.
+  CRLSet* crl_set_;
+};
+
 class CertVerifyProcBuiltin : public CertVerifyProc {
  public:
   CertVerifyProcBuiltin();
@@ -115,6 +227,9 @@
   if (!errors.ContainsHighSeverityErrors())
     return;
 
+  if (errors.ContainsError(kCertificateRevoked))
+    *cert_status |= CERT_STATUS_REVOKED;
+
   if (errors.ContainsError(cert_errors::kUnacceptablePublicKey))
     *cert_status |= CERT_STATUS_WEAK_KEY;
 
@@ -197,11 +312,7 @@
     // TODO(eroman): Surface parsing errors of additional trust anchor.
   }
 
-  // TODO(eroman): The path building code in this file enforces its idea of weak
-  // keys, and separately cert_verify_proc.cc also checks the chains with its
-  // own policy. These policies should be aligned, to give path building the
-  // best chance of finding a good path.
-  SimplePathBuilderDelegate path_builder_delegate(1024);
+  PathBuilderDelegateImpl path_builder_delegate(crl_set);
 
   // Use the current time.
   der::GeneralizedTime verification_time;
diff --git a/net/cert/cert_verify_proc_unittest.cc b/net/cert/cert_verify_proc_unittest.cc
index bae8ea26..38221b2 100644
--- a/net/cert/cert_verify_proc_unittest.cc
+++ b/net/cert/cert_verify_proc_unittest.cc
@@ -273,16 +273,16 @@
   }
 
   bool SupportsCRLSet() const {
-    // TODO(crbug.com/649017): Return true for CERT_VERIFY_PROC_BUILTIN.
     return verify_proc_type() == CERT_VERIFY_PROC_NSS ||
            verify_proc_type() == CERT_VERIFY_PROC_WIN ||
-           verify_proc_type() == CERT_VERIFY_PROC_MAC;
+           verify_proc_type() == CERT_VERIFY_PROC_MAC ||
+           verify_proc_type() == CERT_VERIFY_PROC_BUILTIN;
   }
 
   bool SupportsCRLSetsInPathBuilding() const {
-    // TODO(crbug.com/649017): Return true for CERT_VERIFY_PROC_BUILTIN.
     return verify_proc_type() == CERT_VERIFY_PROC_WIN ||
-           verify_proc_type() == CERT_VERIFY_PROC_NSS;
+           verify_proc_type() == CERT_VERIFY_PROC_NSS ||
+           verify_proc_type() == CERT_VERIFY_PROC_BUILTIN;
   }
 
   bool SupportsEV() const {
diff --git a/net/cert/internal/system_trust_store.cc b/net/cert/internal/system_trust_store.cc
index 64a5225..2dc31f7 100644
--- a/net/cert/internal/system_trust_store.cc
+++ b/net/cert/internal/system_trust_store.cc
@@ -34,7 +34,6 @@
 #include "net/cert/x509_util_mac.h"
 #elif defined(OS_FUCHSIA)
 #include "third_party/boringssl/src/include/openssl/pool.h"
-#include "third_party/boringssl/src/include/openssl/x509.h"
 #endif
 
 namespace net {
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc
index 05c3667d..3ec92c7 100644
--- a/net/cookies/cookie_monster.cc
+++ b/net/cookies/cookie_monster.cc
@@ -147,6 +147,47 @@
 
 namespace {
 
+// This class owns the CookieStore::CookieChangedCallbackList::Subscription,
+// thus guaranteeing destruction when it is destroyed.  In addition, it
+// wraps the callback for a particular subscription, guaranteeing that it
+// won't be run even if a PostTask completes after the subscription has
+// been destroyed.
+class CookieMonsterCookieChangedSubscription
+    : public CookieStore::CookieChangedSubscription {
+ public:
+  CookieMonsterCookieChangedSubscription(
+      const CookieStore::CookieChangedCallback& callback)
+      : callback_(callback), weak_ptr_factory_(this) {}
+  ~CookieMonsterCookieChangedSubscription() override {}
+
+  void SetCallbackSubscription(
+      std::unique_ptr<CookieStore::CookieChangedCallbackList::Subscription>
+          subscription) {
+    subscription_ = std::move(subscription);
+  }
+
+  // The returned callback runs the callback passed to the constructor
+  // directly as long as this object hasn't been destroyed.
+  CookieStore::CookieChangedCallback WeakCallback() {
+    return base::Bind(&CookieMonsterCookieChangedSubscription::RunCallback,
+                      weak_ptr_factory_.GetWeakPtr());
+  }
+
+ private:
+  void RunCallback(const CanonicalCookie& cookie,
+                   CookieStore::ChangeCause cause) {
+    callback_.Run(cookie, cause);
+  }
+
+  const CookieStore::CookieChangedCallback callback_;
+  std::unique_ptr<CookieStore::CookieChangedCallbackList::Subscription>
+      subscription_;
+  base::WeakPtrFactory<CookieMonsterCookieChangedSubscription>
+      weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(CookieMonsterCookieChangedSubscription);
+};
+
 bool ContainsControlCharacter(const std::string& s) {
   for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) {
     if ((*i >= 0) && (*i <= 31))
@@ -382,7 +423,7 @@
       channel_id_service_(channel_id_service),
       last_statistic_record_time_(base::Time::Now()),
       persist_session_cookies_(false),
-      global_hook_map_(base::MakeUnique<CookieChangedCallbackList>()),
+      global_hook_map_(std::make_unique<CookieChangedCallbackList>()),
       weak_ptr_factory_(this) {
   InitializeHistograms();
   cookieable_schemes_.insert(
@@ -628,16 +669,24 @@
   std::pair<GURL, std::string> key(gurl, name);
   if (hook_map_.count(key) == 0)
     hook_map_[key] = std::make_unique<CookieChangedCallbackList>();
-  return hook_map_[key]->Add(
-      base::Bind(&RunAsync, base::ThreadTaskRunnerHandle::Get(), callback));
+
+  std::unique_ptr<CookieMonsterCookieChangedSubscription> sub(
+      std::make_unique<CookieMonsterCookieChangedSubscription>(callback));
+  sub->SetCallbackSubscription(hook_map_[key]->Add(base::Bind(
+      &RunAsync, base::ThreadTaskRunnerHandle::Get(), sub->WeakCallback())));
+
+  return std::move(sub);
 }
 
 std::unique_ptr<CookieStore::CookieChangedSubscription>
 CookieMonster::AddCallbackForAllChanges(const CookieChangedCallback& callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  return global_hook_map_->Add(
-      base::Bind(&RunAsync, base::ThreadTaskRunnerHandle::Get(), callback));
+  std::unique_ptr<CookieMonsterCookieChangedSubscription> sub(
+      std::make_unique<CookieMonsterCookieChangedSubscription>(callback));
+  sub->SetCallbackSubscription(global_hook_map_->Add(base::Bind(
+      &RunAsync, base::ThreadTaskRunnerHandle::Get(), sub->WeakCallback())));
+  return std::move(sub);
 }
 
 bool CookieMonster::IsEphemeral() {
diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc
index 0b1b2b8..6681a452 100644
--- a/net/cookies/cookie_monster_unittest.cc
+++ b/net/cookies/cookie_monster_unittest.cc
@@ -3216,6 +3216,30 @@
   EXPECT_EQ(CookieStore::ChangeCause::INSERTED, causes[2]);
 }
 
+TEST_F(CookieMonsterNotificationTest, NotifyDestroyRace) {
+  std::vector<CanonicalCookie> cookies;
+  std::unique_ptr<CookieStore::CookieChangedSubscription> sub(
+      monster()->AddCallbackForCookie(
+          test_url_, "abc",
+          base::Bind(&RecordCookieChanges, &cookies, nullptr)));
+  SetCookie(monster(), test_url_, "abc=def");
+
+  // If the notification is synchronous, there's nothing to test.
+  if (1u == cookies.size())
+    return;
+
+  // At this point a task has been posted to execute the callback,
+  // but the callback has not yet been executed.  If the subscription was
+  // alive when the callback was executed, that would also be valid
+  // behavior.  If the subscription is destroyed, and the posted task is
+  // let run, and the callback actually happens, that is invalid behavior.
+  sub.reset();
+  base::RunLoop().RunUntilIdle();
+
+  // Subscription reset should have blocked delivery.
+  EXPECT_EQ(0u, cookies.size());
+}
+
 TEST_F(CookieMonsterNotificationTest, MultipleNotifies) {
   std::vector<CanonicalCookie> cookies0;
   std::vector<CanonicalCookie> cookies1;
diff --git a/net/cookies/cookie_store.h b/net/cookies/cookie_store.h
index e9bf8cb..b9fcf74 100644
--- a/net/cookies/cookie_store.h
+++ b/net/cookies/cookie_store.h
@@ -78,9 +78,13 @@
   typedef base::CallbackList<void(const CanonicalCookie& cookie,
                                   ChangeCause cause)>
       CookieChangedCallbackList;
-  typedef CookieChangedCallbackList::Subscription CookieChangedSubscription;
   typedef base::Callback<bool(const CanonicalCookie& cookie)> CookiePredicate;
 
+  class CookieChangedSubscription {
+   public:
+    virtual ~CookieChangedSubscription(){};
+  };
+
   virtual ~CookieStore();
 
   // Returns the cookie line (e.g. "cookie1=value1; cookie2=value2") represented
@@ -235,6 +239,8 @@
   // |callback| will be called when a cookie is added or removed. |callback| is
   // passed the respective |cookie| which was added to or removed from the
   // cookies and a boolean indicating if the cookies was removed or not.
+  // |callback| is guaranteed not to be called after the return handled is
+  // destroyed.
   //
   // Note that |callback| is called twice when a cookie is updated: once for
   // the removal of the existing cookie and once for the adding the new cookie.
@@ -253,7 +259,8 @@
 
   // Add a callback to be notified on all cookie changes (with a few
   // bookkeeping exceptions; see kChangeCauseMapping in
-  // cookie_monster.cc).
+  // cookie_monster.cc).  See the comment on AddCallbackForCookie for details
+  // on callback behavior.
   virtual std::unique_ptr<CookieChangedSubscription> AddCallbackForAllChanges(
       const CookieChangedCallback& callback) = 0;
 
diff --git a/net/cookies/cookie_store_unittest.h b/net/cookies/cookie_store_unittest.h
index 37fc541..292278b 100644
--- a/net/cookies/cookie_store_unittest.h
+++ b/net/cookies/cookie_store_unittest.h
@@ -1835,6 +1835,60 @@
   ASSERT_EQ(0u, cookie_changes_2.size());
 }
 
+// Confirm that deregistering a subscription blocks the notification
+// if the deregistration happened after the change but before the
+// notification was received.
+TYPED_TEST_P(CookieStoreTest, GlobalChangeTracking_DeregisterRace) {
+  if (!TypeParam::supports_global_cookie_tracking)
+    return;
+
+  CookieStore* cs = this->GetCookieStore();
+
+  // Register two notifiers.
+  std::vector<CookieNotification> cookie_changes_1;
+  std::unique_ptr<CookieStore::CookieChangedSubscription> subscription1(
+      cs->AddCallbackForAllChanges(
+          base::Bind(&OnCookieChanged, base::Unretained(&cookie_changes_1))));
+
+  std::vector<CookieNotification> cookie_changes_2;
+  std::unique_ptr<CookieStore::CookieChangedSubscription> subscription2(
+      cs->AddCallbackForAllChanges(
+          base::Bind(&OnCookieChanged, base::Unretained(&cookie_changes_2))));
+  base::RunLoop().RunUntilIdle();
+  ASSERT_EQ(0u, cookie_changes_1.size());
+  ASSERT_EQ(0u, cookie_changes_2.size());
+
+  // De-register the second registration.
+
+  // Insert a cookie, confirm not seen, dergister, run until idle,
+  // and confirm still not seen.
+  ASSERT_EQ(0u, cookie_changes_2.size());
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "C=D"));
+
+  // Note that by the API contract it's perfectly valid to have
+  // received the notification immediately, i.e. synchrnously with the cookie
+  // change.  In that case, there's nothing to test.
+  if (1u == cookie_changes_2.size()) {
+    LOG(ERROR) << "Nothing to test.";
+    return;
+  }
+
+  // A task was posted by the SetCookie() above, but has not yet
+  // arrived.  If it arrived before the subscription is destroyed,
+  // callback execution would be valid.  Destroy one of the
+  // subscriptions so as to lose the race and make sure the task
+  // posted arrives after the subscription was destroyed.
+  subscription2.reset();
+  base::RunLoop().RunUntilIdle();
+  ASSERT_EQ(1u, cookie_changes_1.size());
+  EXPECT_EQ("C", cookie_changes_1[0].first.Name());
+  EXPECT_EQ("D", cookie_changes_1[0].first.Value());
+  cookie_changes_1.clear();
+
+  // No late notification was received.
+  ASSERT_EQ(0u, cookie_changes_2.size());
+}
+
 REGISTER_TYPED_TEST_CASE_P(CookieStoreTest,
                            SetCookieWithDetailsAsync,
                            SetCanonicalCookieTest,
@@ -1879,7 +1933,8 @@
                            GlobalChangeTracking_Insert,
                            GlobalChangeTracking_Delete,
                            GlobalChangeTracking_Overwrite,
-                           GlobalChangeTracking_Deregister);
+                           GlobalChangeTracking_Deregister,
+                           GlobalChangeTracking_DeregisterRace);
 
 }  // namespace net
 
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/01203e2ff7f2a628bce6a5abf01e45a9b65a2e3d b/net/data/fuzzer_data/ntlm_client_fuzzer/01203e2ff7f2a628bce6a5abf01e45a9b65a2e3d
new file mode 100644
index 0000000..778309d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/01203e2ff7f2a628bce6a5abf01e45a9b65a2e3d
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/01f23d6e8afac727dda9fc22bbbc8f20a8859673 b/net/data/fuzzer_data/ntlm_client_fuzzer/01f23d6e8afac727dda9fc22bbbc8f20a8859673
new file mode 100644
index 0000000..2e38a0e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/01f23d6e8afac727dda9fc22bbbc8f20a8859673
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/0244efc4be5c51b0505e50de5e47daf3e8ae8742 b/net/data/fuzzer_data/ntlm_client_fuzzer/0244efc4be5c51b0505e50de5e47daf3e8ae8742
new file mode 100644
index 0000000..46729f2
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/0244efc4be5c51b0505e50de5e47daf3e8ae8742
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/026cd7d12bea861f2b7baebc50be69be1b72fefe b/net/data/fuzzer_data/ntlm_client_fuzzer/026cd7d12bea861f2b7baebc50be69be1b72fefe
new file mode 100644
index 0000000..5701346
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/026cd7d12bea861f2b7baebc50be69be1b72fefe
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/02d80cc4f69dd2a551260c40d166b79cdfa4c838 b/net/data/fuzzer_data/ntlm_client_fuzzer/02d80cc4f69dd2a551260c40d166b79cdfa4c838
new file mode 100644
index 0000000..7abec65
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/02d80cc4f69dd2a551260c40d166b79cdfa4c838
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/0302fa512febc55193ce6540e764571f9facf813 b/net/data/fuzzer_data/ntlm_client_fuzzer/0302fa512febc55193ce6540e764571f9facf813
new file mode 100644
index 0000000..6950a82
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/0302fa512febc55193ce6540e764571f9facf813
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/034701a8073fe971199e7ed4e6cab470ee8a2fe4 b/net/data/fuzzer_data/ntlm_client_fuzzer/034701a8073fe971199e7ed4e6cab470ee8a2fe4
new file mode 100644
index 0000000..ed3b53c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/034701a8073fe971199e7ed4e6cab470ee8a2fe4
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/037f9ac35de20158ea386c19269991ed33d6a951 b/net/data/fuzzer_data/ntlm_client_fuzzer/037f9ac35de20158ea386c19269991ed33d6a951
new file mode 100644
index 0000000..7a6f34e1
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/037f9ac35de20158ea386c19269991ed33d6a951
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/03a3f03e4a4d9de0d367225b603cb3c5fb635f61 b/net/data/fuzzer_data/ntlm_client_fuzzer/03a3f03e4a4d9de0d367225b603cb3c5fb635f61
new file mode 100644
index 0000000..a55eba0
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/03a3f03e4a4d9de0d367225b603cb3c5fb635f61
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/03c22fdc462d8b54a1fd24a5c4b4661eb51d76a7 b/net/data/fuzzer_data/ntlm_client_fuzzer/03c22fdc462d8b54a1fd24a5c4b4661eb51d76a7
new file mode 100644
index 0000000..336d180
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/03c22fdc462d8b54a1fd24a5c4b4661eb51d76a7
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/03e0c068a82dafd93073f08edd1c8f97347485dc b/net/data/fuzzer_data/ntlm_client_fuzzer/03e0c068a82dafd93073f08edd1c8f97347485dc
new file mode 100644
index 0000000..84d6d90
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/03e0c068a82dafd93073f08edd1c8f97347485dc
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/044ac82504b0dda496fdf3456a27ff136e39048f b/net/data/fuzzer_data/ntlm_client_fuzzer/044ac82504b0dda496fdf3456a27ff136e39048f
new file mode 100644
index 0000000..6eddb8cb
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/044ac82504b0dda496fdf3456a27ff136e39048f
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/0647d364263be75a106c2293dddb2997d82bc1ea b/net/data/fuzzer_data/ntlm_client_fuzzer/0647d364263be75a106c2293dddb2997d82bc1ea
new file mode 100644
index 0000000..a177a557
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/0647d364263be75a106c2293dddb2997d82bc1ea
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/0803b67bce74b3b876cc1d8ca047c3c6525bb2f2 b/net/data/fuzzer_data/ntlm_client_fuzzer/0803b67bce74b3b876cc1d8ca047c3c6525bb2f2
new file mode 100644
index 0000000..bb37a45
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/0803b67bce74b3b876cc1d8ca047c3c6525bb2f2
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/08bc64a82929e407eea458a3c0e4fa3e1b7c1398 b/net/data/fuzzer_data/ntlm_client_fuzzer/08bc64a82929e407eea458a3c0e4fa3e1b7c1398
new file mode 100644
index 0000000..4a6d662
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/08bc64a82929e407eea458a3c0e4fa3e1b7c1398
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/0942e6e953337a57ac73a2f2e703351254f87359 b/net/data/fuzzer_data/ntlm_client_fuzzer/0942e6e953337a57ac73a2f2e703351254f87359
new file mode 100644
index 0000000..a9a9f5d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/0942e6e953337a57ac73a2f2e703351254f87359
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/09f7b28ea6955d2f87e9f1e55a6765a2aa269e10 b/net/data/fuzzer_data/ntlm_client_fuzzer/09f7b28ea6955d2f87e9f1e55a6765a2aa269e10
new file mode 100644
index 0000000..871d8a30
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/09f7b28ea6955d2f87e9f1e55a6765a2aa269e10
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/0ab346eeba99eacb19cb4d63dd12a6b5e169a587 b/net/data/fuzzer_data/ntlm_client_fuzzer/0ab346eeba99eacb19cb4d63dd12a6b5e169a587
new file mode 100644
index 0000000..5a514de
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/0ab346eeba99eacb19cb4d63dd12a6b5e169a587
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/0abe5d060e437a1f618f3f9ec5420a374d648b21 b/net/data/fuzzer_data/ntlm_client_fuzzer/0abe5d060e437a1f618f3f9ec5420a374d648b21
new file mode 100644
index 0000000..d3aa533
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/0abe5d060e437a1f618f3f9ec5420a374d648b21
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/0c46616e57abbd4e89bb6cf2bb19df2a809a5c91 b/net/data/fuzzer_data/ntlm_client_fuzzer/0c46616e57abbd4e89bb6cf2bb19df2a809a5c91
new file mode 100644
index 0000000..fe54344
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/0c46616e57abbd4e89bb6cf2bb19df2a809a5c91
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/0c6cc056a72ebf716857512876078d9ffe917a81 b/net/data/fuzzer_data/ntlm_client_fuzzer/0c6cc056a72ebf716857512876078d9ffe917a81
new file mode 100644
index 0000000..7b83642d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/0c6cc056a72ebf716857512876078d9ffe917a81
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/0dc7622b02da50407f79a73d2909e65a09d17b85 b/net/data/fuzzer_data/ntlm_client_fuzzer/0dc7622b02da50407f79a73d2909e65a09d17b85
new file mode 100644
index 0000000..65101a8b
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/0dc7622b02da50407f79a73d2909e65a09d17b85
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0002.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/0e355d86c93728d6263cd51f726e0230fe7931ba
similarity index 100%
rename from net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0002.bin
rename to net/data/fuzzer_data/ntlm_client_fuzzer/0e355d86c93728d6263cd51f726e0230fe7931ba
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/0e4cee87b556bfba2fd1239f1ad1b457f8105f39 b/net/data/fuzzer_data/ntlm_client_fuzzer/0e4cee87b556bfba2fd1239f1ad1b457f8105f39
new file mode 100644
index 0000000..ac0ec2e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/0e4cee87b556bfba2fd1239f1ad1b457f8105f39
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/0e4dc539d5dfa67f4facdf141572e08c978d6fe0 b/net/data/fuzzer_data/ntlm_client_fuzzer/0e4dc539d5dfa67f4facdf141572e08c978d6fe0
new file mode 100644
index 0000000..eec80db0
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/0e4dc539d5dfa67f4facdf141572e08c978d6fe0
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/0e4ff4575f703c940a9c6e5acd839d9216b3ca0d b/net/data/fuzzer_data/ntlm_client_fuzzer/0e4ff4575f703c940a9c6e5acd839d9216b3ca0d
new file mode 100644
index 0000000..bf2bf5be
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/0e4ff4575f703c940a9c6e5acd839d9216b3ca0d
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/0e588cbf738d34b2f13e95c546a064f5b7bd8848 b/net/data/fuzzer_data/ntlm_client_fuzzer/0e588cbf738d34b2f13e95c546a064f5b7bd8848
new file mode 100644
index 0000000..21df4f4
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/0e588cbf738d34b2f13e95c546a064f5b7bd8848
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/0f9afcd39a061b3e776a51e423306858c5b9e11e b/net/data/fuzzer_data/ntlm_client_fuzzer/0f9afcd39a061b3e776a51e423306858c5b9e11e
new file mode 100644
index 0000000..f4b4fb7c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/0f9afcd39a061b3e776a51e423306858c5b9e11e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/0fa22dad896b1f0ae887081a0e77294f07291300 b/net/data/fuzzer_data/ntlm_client_fuzzer/0fa22dad896b1f0ae887081a0e77294f07291300
new file mode 100644
index 0000000..90407e2
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/0fa22dad896b1f0ae887081a0e77294f07291300
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/102f00bacea338af33b5f23d1d01ded0ebdcf369 b/net/data/fuzzer_data/ntlm_client_fuzzer/102f00bacea338af33b5f23d1d01ded0ebdcf369
new file mode 100644
index 0000000..3651dfc
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/102f00bacea338af33b5f23d1d01ded0ebdcf369
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/10460aff1bc6b2c32c93aeac43c8e3bb8ccc4b63 b/net/data/fuzzer_data/ntlm_client_fuzzer/10460aff1bc6b2c32c93aeac43c8e3bb8ccc4b63
new file mode 100644
index 0000000..2c3e581c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/10460aff1bc6b2c32c93aeac43c8e3bb8ccc4b63
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/1075494403238466401ba7e98528a1c93fd03c75 b/net/data/fuzzer_data/ntlm_client_fuzzer/1075494403238466401ba7e98528a1c93fd03c75
new file mode 100644
index 0000000..f52f51c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/1075494403238466401ba7e98528a1c93fd03c75
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/11409704564523f357bc2501299f0560e6d2ba1b b/net/data/fuzzer_data/ntlm_client_fuzzer/11409704564523f357bc2501299f0560e6d2ba1b
new file mode 100644
index 0000000..1f1b129f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/11409704564523f357bc2501299f0560e6d2ba1b
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/122fea9881e7db62509b3804fb6ce865fa495f7f b/net/data/fuzzer_data/ntlm_client_fuzzer/122fea9881e7db62509b3804fb6ce865fa495f7f
new file mode 100644
index 0000000..5c6b1ec
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/122fea9881e7db62509b3804fb6ce865fa495f7f
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/1333ad6d4f1f1fd8cc078ead0dd88f04d367e7a8 b/net/data/fuzzer_data/ntlm_client_fuzzer/1333ad6d4f1f1fd8cc078ead0dd88f04d367e7a8
new file mode 100644
index 0000000..095eb43c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/1333ad6d4f1f1fd8cc078ead0dd88f04d367e7a8
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/134b19a1ea68b60334f69096ca22b6176c44b403 b/net/data/fuzzer_data/ntlm_client_fuzzer/134b19a1ea68b60334f69096ca22b6176c44b403
new file mode 100644
index 0000000..1f0bccd
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/134b19a1ea68b60334f69096ca22b6176c44b403
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/1388e8e8b4566c421add09bee7ebb5c41e2d7e34 b/net/data/fuzzer_data/ntlm_client_fuzzer/1388e8e8b4566c421add09bee7ebb5c41e2d7e34
new file mode 100644
index 0000000..be7a6770
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/1388e8e8b4566c421add09bee7ebb5c41e2d7e34
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/138fc3f74a48b5baa8df9d713356325d166b1388 b/net/data/fuzzer_data/ntlm_client_fuzzer/138fc3f74a48b5baa8df9d713356325d166b1388
new file mode 100644
index 0000000..67c6d067
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/138fc3f74a48b5baa8df9d713356325d166b1388
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/143bc2719dea6729691e0fc34f64dad32bcc62ff b/net/data/fuzzer_data/ntlm_client_fuzzer/143bc2719dea6729691e0fc34f64dad32bcc62ff
new file mode 100644
index 0000000..e49062d1
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/143bc2719dea6729691e0fc34f64dad32bcc62ff
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/14615b09db0e4e37be85e03a7179b8b0c2a5cb15 b/net/data/fuzzer_data/ntlm_client_fuzzer/14615b09db0e4e37be85e03a7179b8b0c2a5cb15
new file mode 100644
index 0000000..f5f0eed9
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/14615b09db0e4e37be85e03a7179b8b0c2a5cb15
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/147766dd358533ebd6c1c283c5e37a8cf6c4da73 b/net/data/fuzzer_data/ntlm_client_fuzzer/147766dd358533ebd6c1c283c5e37a8cf6c4da73
new file mode 100644
index 0000000..3905cea
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/147766dd358533ebd6c1c283c5e37a8cf6c4da73
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/151a43bfed2bd5f11026493da3e16c035157cb11 b/net/data/fuzzer_data/ntlm_client_fuzzer/151a43bfed2bd5f11026493da3e16c035157cb11
new file mode 100644
index 0000000..88c4f8b0
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/151a43bfed2bd5f11026493da3e16c035157cb11
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/153179bcb467be5095364f3d2f0be07e155d5c58 b/net/data/fuzzer_data/ntlm_client_fuzzer/153179bcb467be5095364f3d2f0be07e155d5c58
new file mode 100644
index 0000000..716a4a1
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/153179bcb467be5095364f3d2f0be07e155d5c58
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/15c5f5babd0528ad65ba28305e9e865356bb38a0 b/net/data/fuzzer_data/ntlm_client_fuzzer/15c5f5babd0528ad65ba28305e9e865356bb38a0
new file mode 100644
index 0000000..22f89bb
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/15c5f5babd0528ad65ba28305e9e865356bb38a0
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/16a3ee53bb0725521e75183c330098ed8e7f99cf b/net/data/fuzzer_data/ntlm_client_fuzzer/16a3ee53bb0725521e75183c330098ed8e7f99cf
new file mode 100644
index 0000000..7540ac688
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/16a3ee53bb0725521e75183c330098ed8e7f99cf
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/16c35aa3576f6ffbb06da2768b5ca1486b15a40b b/net/data/fuzzer_data/ntlm_client_fuzzer/16c35aa3576f6ffbb06da2768b5ca1486b15a40b
new file mode 100644
index 0000000..c020d3e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/16c35aa3576f6ffbb06da2768b5ca1486b15a40b
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/16fed049249f5aa3832bf429eab206cf4689d3b5 b/net/data/fuzzer_data/ntlm_client_fuzzer/16fed049249f5aa3832bf429eab206cf4689d3b5
new file mode 100644
index 0000000..7231b7a1
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/16fed049249f5aa3832bf429eab206cf4689d3b5
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/197fad1cea9da68b123babf1e8df9e83255c22c9 b/net/data/fuzzer_data/ntlm_client_fuzzer/197fad1cea9da68b123babf1e8df9e83255c22c9
new file mode 100644
index 0000000..50cbbf4
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/197fad1cea9da68b123babf1e8df9e83255c22c9
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/1a82584c47daae274bfe1cea1cb081d1fb228d70 b/net/data/fuzzer_data/ntlm_client_fuzzer/1a82584c47daae274bfe1cea1cb081d1fb228d70
new file mode 100644
index 0000000..6ab637b9
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/1a82584c47daae274bfe1cea1cb081d1fb228d70
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/1ca5e9d227530ce08d8e2d42c0447ef45a0f25a1 b/net/data/fuzzer_data/ntlm_client_fuzzer/1ca5e9d227530ce08d8e2d42c0447ef45a0f25a1
new file mode 100644
index 0000000..f13c0c8
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/1ca5e9d227530ce08d8e2d42c0447ef45a0f25a1
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/1d67261ebda07ceefb06bb713b1d25dd99a33589 b/net/data/fuzzer_data/ntlm_client_fuzzer/1d67261ebda07ceefb06bb713b1d25dd99a33589
new file mode 100644
index 0000000..5308580
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/1d67261ebda07ceefb06bb713b1d25dd99a33589
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/1d6c196cf8c3efefddcd999ab1e4878f8a19ef16 b/net/data/fuzzer_data/ntlm_client_fuzzer/1d6c196cf8c3efefddcd999ab1e4878f8a19ef16
new file mode 100644
index 0000000..ee14a38
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/1d6c196cf8c3efefddcd999ab1e4878f8a19ef16
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/1da4ef3ac2215168f21e0c0307c8ff1a378db066 b/net/data/fuzzer_data/ntlm_client_fuzzer/1da4ef3ac2215168f21e0c0307c8ff1a378db066
new file mode 100644
index 0000000..283527b
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/1da4ef3ac2215168f21e0c0307c8ff1a378db066
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/1ede738afa5e205400219fc1a5769d3a606f040f b/net/data/fuzzer_data/ntlm_client_fuzzer/1ede738afa5e205400219fc1a5769d3a606f040f
new file mode 100644
index 0000000..b844cd95
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/1ede738afa5e205400219fc1a5769d3a606f040f
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/1f11c0ad6d9a757fa3c8f0a61ac5e395b742c61a b/net/data/fuzzer_data/ntlm_client_fuzzer/1f11c0ad6d9a757fa3c8f0a61ac5e395b742c61a
new file mode 100644
index 0000000..8f01030
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/1f11c0ad6d9a757fa3c8f0a61ac5e395b742c61a
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/1f1e86892d346d74c799aab61ee6af49da9d00c4 b/net/data/fuzzer_data/ntlm_client_fuzzer/1f1e86892d346d74c799aab61ee6af49da9d00c4
new file mode 100644
index 0000000..5c18aa3
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/1f1e86892d346d74c799aab61ee6af49da9d00c4
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/1f54d6736191a548c84f237055c2fbd4a86e7c21 b/net/data/fuzzer_data/ntlm_client_fuzzer/1f54d6736191a548c84f237055c2fbd4a86e7c21
new file mode 100644
index 0000000..46496e08
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/1f54d6736191a548c84f237055c2fbd4a86e7c21
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/2033f396b944bca17f9cb3313bb90ecd610cab36 b/net/data/fuzzer_data/ntlm_client_fuzzer/2033f396b944bca17f9cb3313bb90ecd610cab36
new file mode 100644
index 0000000..ffd7b416
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/2033f396b944bca17f9cb3313bb90ecd610cab36
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/20f504bd29e29812774ce457f767e47e73f23023 b/net/data/fuzzer_data/ntlm_client_fuzzer/20f504bd29e29812774ce457f767e47e73f23023
new file mode 100644
index 0000000..61ac53a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/20f504bd29e29812774ce457f767e47e73f23023
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/215780324cbaef6ca393b024a1e6778e2ab15072 b/net/data/fuzzer_data/ntlm_client_fuzzer/215780324cbaef6ca393b024a1e6778e2ab15072
new file mode 100644
index 0000000..3895d1a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/215780324cbaef6ca393b024a1e6778e2ab15072
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/220e4450d385f928529bbf2bc9d2e36489fb369f b/net/data/fuzzer_data/ntlm_client_fuzzer/220e4450d385f928529bbf2bc9d2e36489fb369f
new file mode 100644
index 0000000..066af10e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/220e4450d385f928529bbf2bc9d2e36489fb369f
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/2211b57efb1c063d990f622d76b1a4cd05442f98 b/net/data/fuzzer_data/ntlm_client_fuzzer/2211b57efb1c063d990f622d76b1a4cd05442f98
new file mode 100644
index 0000000..e38dbbd
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/2211b57efb1c063d990f622d76b1a4cd05442f98
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/22409d9dcb3237237fb6b7c13ea20a4e6894b5e8 b/net/data/fuzzer_data/ntlm_client_fuzzer/22409d9dcb3237237fb6b7c13ea20a4e6894b5e8
new file mode 100644
index 0000000..a3f2feb
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/22409d9dcb3237237fb6b7c13ea20a4e6894b5e8
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/23366157f225b7ea1db0cdb727e0fdaa99e44c74 b/net/data/fuzzer_data/ntlm_client_fuzzer/23366157f225b7ea1db0cdb727e0fdaa99e44c74
new file mode 100644
index 0000000..8dffc6c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/23366157f225b7ea1db0cdb727e0fdaa99e44c74
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/24762da37ca2c2c37a0dc25cafc0e5bb4a6baeea b/net/data/fuzzer_data/ntlm_client_fuzzer/24762da37ca2c2c37a0dc25cafc0e5bb4a6baeea
new file mode 100644
index 0000000..e78f502e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/24762da37ca2c2c37a0dc25cafc0e5bb4a6baeea
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/24c362559e0b8ddfcacdfde00c62f31b3677c329 b/net/data/fuzzer_data/ntlm_client_fuzzer/24c362559e0b8ddfcacdfde00c62f31b3677c329
new file mode 100644
index 0000000..998fdbde
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/24c362559e0b8ddfcacdfde00c62f31b3677c329
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/2554d02e4f60ab78a3fba0520662741b982e1851 b/net/data/fuzzer_data/ntlm_client_fuzzer/2554d02e4f60ab78a3fba0520662741b982e1851
new file mode 100644
index 0000000..cdfa512
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/2554d02e4f60ab78a3fba0520662741b982e1851
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/2589babca729ea1abbe68c105e3177ac1c5d2432 b/net/data/fuzzer_data/ntlm_client_fuzzer/2589babca729ea1abbe68c105e3177ac1c5d2432
new file mode 100644
index 0000000..ba5cd1a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/2589babca729ea1abbe68c105e3177ac1c5d2432
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/266787fc74d850fb0f78ea7f008e90a3c56412ce b/net/data/fuzzer_data/ntlm_client_fuzzer/266787fc74d850fb0f78ea7f008e90a3c56412ce
new file mode 100644
index 0000000..e9b09ad
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/266787fc74d850fb0f78ea7f008e90a3c56412ce
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/267ef194f9e4145a90d7b846993781da09b494d0 b/net/data/fuzzer_data/ntlm_client_fuzzer/267ef194f9e4145a90d7b846993781da09b494d0
new file mode 100644
index 0000000..362abd02
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/267ef194f9e4145a90d7b846993781da09b494d0
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/26a712e13ee958b1af178ab3e3319550fb09bce2 b/net/data/fuzzer_data/ntlm_client_fuzzer/26a712e13ee958b1af178ab3e3319550fb09bce2
new file mode 100644
index 0000000..a80c0a0
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/26a712e13ee958b1af178ab3e3319550fb09bce2
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/26a932f75448fbfd9f32cd85e3869a4ddfe9526f b/net/data/fuzzer_data/ntlm_client_fuzzer/26a932f75448fbfd9f32cd85e3869a4ddfe9526f
new file mode 100644
index 0000000..fd78859
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/26a932f75448fbfd9f32cd85e3869a4ddfe9526f
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/26d8d0453bd16b11cef27c7fa344a865b4902c52 b/net/data/fuzzer_data/ntlm_client_fuzzer/26d8d0453bd16b11cef27c7fa344a865b4902c52
new file mode 100644
index 0000000..9a45610
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/26d8d0453bd16b11cef27c7fa344a865b4902c52
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/273c3ae344606fab9ab385ebfc4fec1af5c40fac b/net/data/fuzzer_data/ntlm_client_fuzzer/273c3ae344606fab9ab385ebfc4fec1af5c40fac
new file mode 100644
index 0000000..6490f2a9
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/273c3ae344606fab9ab385ebfc4fec1af5c40fac
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/27437a66831be2253ffebaeb8b3aeeeeb34cc702 b/net/data/fuzzer_data/ntlm_client_fuzzer/27437a66831be2253ffebaeb8b3aeeeeb34cc702
new file mode 100644
index 0000000..5780072
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/27437a66831be2253ffebaeb8b3aeeeeb34cc702
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/2a2d31ca1382a96f19f00f439d5900717f5c32ff b/net/data/fuzzer_data/ntlm_client_fuzzer/2a2d31ca1382a96f19f00f439d5900717f5c32ff
new file mode 100644
index 0000000..de07e55
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/2a2d31ca1382a96f19f00f439d5900717f5c32ff
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/2a7dde1617badfb1a1d8f41fc3dbf08fb85c7c6e b/net/data/fuzzer_data/ntlm_client_fuzzer/2a7dde1617badfb1a1d8f41fc3dbf08fb85c7c6e
new file mode 100644
index 0000000..051f09f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/2a7dde1617badfb1a1d8f41fc3dbf08fb85c7c6e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/2af98a9142d0e51d8cd95297242fbf429b2b68ad b/net/data/fuzzer_data/ntlm_client_fuzzer/2af98a9142d0e51d8cd95297242fbf429b2b68ad
new file mode 100644
index 0000000..05bd281
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/2af98a9142d0e51d8cd95297242fbf429b2b68ad
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/2b25090625df6361aff5c9e637e2af08b09ec082 b/net/data/fuzzer_data/ntlm_client_fuzzer/2b25090625df6361aff5c9e637e2af08b09ec082
new file mode 100644
index 0000000..077e4e6
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/2b25090625df6361aff5c9e637e2af08b09ec082
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/2c4c3327238b9495410fb2d025617ed70b2d973b b/net/data/fuzzer_data/ntlm_client_fuzzer/2c4c3327238b9495410fb2d025617ed70b2d973b
new file mode 100644
index 0000000..5ec9b27
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/2c4c3327238b9495410fb2d025617ed70b2d973b
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/2eb76b0adcfb49d58808ecfaac80a4882eaa04ba b/net/data/fuzzer_data/ntlm_client_fuzzer/2eb76b0adcfb49d58808ecfaac80a4882eaa04ba
new file mode 100644
index 0000000..a03ce35
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/2eb76b0adcfb49d58808ecfaac80a4882eaa04ba
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/2f84de286bc51be4712614b46404d480983282ba b/net/data/fuzzer_data/ntlm_client_fuzzer/2f84de286bc51be4712614b46404d480983282ba
new file mode 100644
index 0000000..7b8e638
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/2f84de286bc51be4712614b46404d480983282ba
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/2fbfc85495d271f6acc9d56339178b9dafc80c08 b/net/data/fuzzer_data/ntlm_client_fuzzer/2fbfc85495d271f6acc9d56339178b9dafc80c08
new file mode 100644
index 0000000..dbba92f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/2fbfc85495d271f6acc9d56339178b9dafc80c08
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/2fd928ca177dd0f63284f8758d891d49d3b9c1fe b/net/data/fuzzer_data/ntlm_client_fuzzer/2fd928ca177dd0f63284f8758d891d49d3b9c1fe
new file mode 100644
index 0000000..4e3aace
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/2fd928ca177dd0f63284f8758d891d49d3b9c1fe
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/30332da3231bb7fe2983f01d81640233b4eb09fe b/net/data/fuzzer_data/ntlm_client_fuzzer/30332da3231bb7fe2983f01d81640233b4eb09fe
new file mode 100644
index 0000000..5f4dbcb
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/30332da3231bb7fe2983f01d81640233b4eb09fe
@@ -0,0 +1 @@
+½¼¼ÀCCCCCCCCCCCCCCCCCCCf(fffffffff
\ No newline at end of file
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/31204bc02172537018ca871fc063094deffa087f b/net/data/fuzzer_data/ntlm_client_fuzzer/31204bc02172537018ca871fc063094deffa087f
new file mode 100644
index 0000000..f6b8c45
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/31204bc02172537018ca871fc063094deffa087f
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/312255687cbfd1f59610c9a4fd84fdffb68d0e2f b/net/data/fuzzer_data/ntlm_client_fuzzer/312255687cbfd1f59610c9a4fd84fdffb68d0e2f
new file mode 100644
index 0000000..1c6ab72
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/312255687cbfd1f59610c9a4fd84fdffb68d0e2f
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/31babfd80b855094c9ff302b60e60d68f1cff66a b/net/data/fuzzer_data/ntlm_client_fuzzer/31babfd80b855094c9ff302b60e60d68f1cff66a
new file mode 100644
index 0000000..49e9fce
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/31babfd80b855094c9ff302b60e60d68f1cff66a
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/321e2ef916072995869393fbceb636adad46aa52 b/net/data/fuzzer_data/ntlm_client_fuzzer/321e2ef916072995869393fbceb636adad46aa52
new file mode 100644
index 0000000..cf84b61
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/321e2ef916072995869393fbceb636adad46aa52
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/32aa2c0b375c536cf52c7ae669795e02731bb227 b/net/data/fuzzer_data/ntlm_client_fuzzer/32aa2c0b375c536cf52c7ae669795e02731bb227
new file mode 100644
index 0000000..095a457b
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/32aa2c0b375c536cf52c7ae669795e02731bb227
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/32b39ab481f9c4a59ed3ca66bdbd679e1f7274ef b/net/data/fuzzer_data/ntlm_client_fuzzer/32b39ab481f9c4a59ed3ca66bdbd679e1f7274ef
new file mode 100644
index 0000000..0a505a1
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/32b39ab481f9c4a59ed3ca66bdbd679e1f7274ef
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/33ec7a2180fd0dc47712e8b14b9168a92dba6f6e b/net/data/fuzzer_data/ntlm_client_fuzzer/33ec7a2180fd0dc47712e8b14b9168a92dba6f6e
new file mode 100644
index 0000000..0654513
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/33ec7a2180fd0dc47712e8b14b9168a92dba6f6e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/33fa33abe18a38dd7c207a0eb0915b76b04101e2 b/net/data/fuzzer_data/ntlm_client_fuzzer/33fa33abe18a38dd7c207a0eb0915b76b04101e2
new file mode 100644
index 0000000..28ebd932
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/33fa33abe18a38dd7c207a0eb0915b76b04101e2
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/348c20a78906cc8a89b19d836534a6f53a0d1dbf b/net/data/fuzzer_data/ntlm_client_fuzzer/348c20a78906cc8a89b19d836534a6f53a0d1dbf
new file mode 100644
index 0000000..c295bf8
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/348c20a78906cc8a89b19d836534a6f53a0d1dbf
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/34b471cfcbc4c877b96d6f2278cf44c83809f17b b/net/data/fuzzer_data/ntlm_client_fuzzer/34b471cfcbc4c877b96d6f2278cf44c83809f17b
new file mode 100644
index 0000000..d1d4718e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/34b471cfcbc4c877b96d6f2278cf44c83809f17b
@@ -0,0 +1 @@
+½¼¼ÀC\CCCCCN\CCCCCC•CCCCCfCCC(dfffffffßfffffß
\ No newline at end of file
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/34b9de31b3eff794d636960d227e72a4d69d7ef8 b/net/data/fuzzer_data/ntlm_client_fuzzer/34b9de31b3eff794d636960d227e72a4d69d7ef8
new file mode 100644
index 0000000..84434c7
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/34b9de31b3eff794d636960d227e72a4d69d7ef8
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/34cf64e613815c88a9f2a69c22eca7bc86cd3143 b/net/data/fuzzer_data/ntlm_client_fuzzer/34cf64e613815c88a9f2a69c22eca7bc86cd3143
new file mode 100644
index 0000000..0bb6555
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/34cf64e613815c88a9f2a69c22eca7bc86cd3143
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/34da12197c43c2a62349ddd48f22b2b5ba069b81 b/net/data/fuzzer_data/ntlm_client_fuzzer/34da12197c43c2a62349ddd48f22b2b5ba069b81
new file mode 100644
index 0000000..5237d5e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/34da12197c43c2a62349ddd48f22b2b5ba069b81
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/353feac8478bb385cf500ab0a624619d9711c3c8 b/net/data/fuzzer_data/ntlm_client_fuzzer/353feac8478bb385cf500ab0a624619d9711c3c8
new file mode 100644
index 0000000..a756b7d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/353feac8478bb385cf500ab0a624619d9711c3c8
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/35af0dac1a32f3dc007da0c212089f8e9e120271 b/net/data/fuzzer_data/ntlm_client_fuzzer/35af0dac1a32f3dc007da0c212089f8e9e120271
new file mode 100644
index 0000000..b79b87d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/35af0dac1a32f3dc007da0c212089f8e9e120271
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/362c4b825a79714ac59f969993af13e1a26ed84e b/net/data/fuzzer_data/ntlm_client_fuzzer/362c4b825a79714ac59f969993af13e1a26ed84e
new file mode 100644
index 0000000..63186b4
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/362c4b825a79714ac59f969993af13e1a26ed84e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/364962f503fd9b075bac6c1f1f7543a1f7f094bf b/net/data/fuzzer_data/ntlm_client_fuzzer/364962f503fd9b075bac6c1f1f7543a1f7f094bf
new file mode 100644
index 0000000..693e780
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/364962f503fd9b075bac6c1f1f7543a1f7f094bf
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/3690198b41eb4949afd16b2c9c174668efaa07d5 b/net/data/fuzzer_data/ntlm_client_fuzzer/3690198b41eb4949afd16b2c9c174668efaa07d5
new file mode 100644
index 0000000..0aec3bd2
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/3690198b41eb4949afd16b2c9c174668efaa07d5
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/36b7fed46b5794d28914113c9670b66665575b85 b/net/data/fuzzer_data/ntlm_client_fuzzer/36b7fed46b5794d28914113c9670b66665575b85
new file mode 100644
index 0000000..c47450ac
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/36b7fed46b5794d28914113c9670b66665575b85
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/36d8c0a5828f9eda8df33190d2424d679b5d5205 b/net/data/fuzzer_data/ntlm_client_fuzzer/36d8c0a5828f9eda8df33190d2424d679b5d5205
new file mode 100644
index 0000000..a07cf3fa
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/36d8c0a5828f9eda8df33190d2424d679b5d5205
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/373a6282fbabd2ed60800ae50e36389311e7d612 b/net/data/fuzzer_data/ntlm_client_fuzzer/373a6282fbabd2ed60800ae50e36389311e7d612
new file mode 100644
index 0000000..72d4289
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/373a6282fbabd2ed60800ae50e36389311e7d612
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/3755ae24dbf626bbf77ca60fbe5ab2a11a8c9831 b/net/data/fuzzer_data/ntlm_client_fuzzer/3755ae24dbf626bbf77ca60fbe5ab2a11a8c9831
new file mode 100644
index 0000000..2d7adb2
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/3755ae24dbf626bbf77ca60fbe5ab2a11a8c9831
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/37c7af8530037907d2327239ee5c313595ed5299 b/net/data/fuzzer_data/ntlm_client_fuzzer/37c7af8530037907d2327239ee5c313595ed5299
new file mode 100644
index 0000000..2d09e51
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/37c7af8530037907d2327239ee5c313595ed5299
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/3813525f79440dd91eac585b8de07b5c6a6538c5 b/net/data/fuzzer_data/ntlm_client_fuzzer/3813525f79440dd91eac585b8de07b5c6a6538c5
new file mode 100644
index 0000000..fe7aa6de
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/3813525f79440dd91eac585b8de07b5c6a6538c5
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/38506a9862aafcbda1c33f42733177d58912733d b/net/data/fuzzer_data/ntlm_client_fuzzer/38506a9862aafcbda1c33f42733177d58912733d
new file mode 100644
index 0000000..15973735
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/38506a9862aafcbda1c33f42733177d58912733d
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/386919d84a155b6e5701705be58a007e7d91298e b/net/data/fuzzer_data/ntlm_client_fuzzer/386919d84a155b6e5701705be58a007e7d91298e
new file mode 100644
index 0000000..6a0356e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/386919d84a155b6e5701705be58a007e7d91298e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/38e945e236a0f55bf2758bc9534ec2f74259dfb4 b/net/data/fuzzer_data/ntlm_client_fuzzer/38e945e236a0f55bf2758bc9534ec2f74259dfb4
new file mode 100644
index 0000000..e066d69
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/38e945e236a0f55bf2758bc9534ec2f74259dfb4
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/39091b1bebe41ce22eeb005d254a115c6a4c3250 b/net/data/fuzzer_data/ntlm_client_fuzzer/39091b1bebe41ce22eeb005d254a115c6a4c3250
new file mode 100644
index 0000000..d663620
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/39091b1bebe41ce22eeb005d254a115c6a4c3250
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/3984d370bb04e3196779f570742fb8fd58e9be2d b/net/data/fuzzer_data/ntlm_client_fuzzer/3984d370bb04e3196779f570742fb8fd58e9be2d
new file mode 100644
index 0000000..23c1b75
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/3984d370bb04e3196779f570742fb8fd58e9be2d
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/3990007fc6cd6fba0a63e7da5f0e3283797f0c0f b/net/data/fuzzer_data/ntlm_client_fuzzer/3990007fc6cd6fba0a63e7da5f0e3283797f0c0f
new file mode 100644
index 0000000..de50f13
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/3990007fc6cd6fba0a63e7da5f0e3283797f0c0f
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/39c6880be883fc8bc6d7ec9902f70692da922a47 b/net/data/fuzzer_data/ntlm_client_fuzzer/39c6880be883fc8bc6d7ec9902f70692da922a47
new file mode 100644
index 0000000..1277108
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/39c6880be883fc8bc6d7ec9902f70692da922a47
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/3a1144eb97283d1304b63107eb2b742d1354cf57 b/net/data/fuzzer_data/ntlm_client_fuzzer/3a1144eb97283d1304b63107eb2b742d1354cf57
new file mode 100644
index 0000000..f8bd21a6
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/3a1144eb97283d1304b63107eb2b742d1354cf57
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/3a70a24d916361cf20bb40dac75a8f2c2ec72046 b/net/data/fuzzer_data/ntlm_client_fuzzer/3a70a24d916361cf20bb40dac75a8f2c2ec72046
new file mode 100644
index 0000000..b486e1a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/3a70a24d916361cf20bb40dac75a8f2c2ec72046
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/3aa1c5947c9cc58ae5e67172c95e54fb23804aca b/net/data/fuzzer_data/ntlm_client_fuzzer/3aa1c5947c9cc58ae5e67172c95e54fb23804aca
new file mode 100644
index 0000000..a07211d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/3aa1c5947c9cc58ae5e67172c95e54fb23804aca
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/3b041869485fd8f880a22ffbbb7a268808eab066 b/net/data/fuzzer_data/ntlm_client_fuzzer/3b041869485fd8f880a22ffbbb7a268808eab066
new file mode 100644
index 0000000..cd73751
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/3b041869485fd8f880a22ffbbb7a268808eab066
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/3b79596df741c6c5d76a250e717eaa1a72ef5131 b/net/data/fuzzer_data/ntlm_client_fuzzer/3b79596df741c6c5d76a250e717eaa1a72ef5131
new file mode 100644
index 0000000..38cbb11
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/3b79596df741c6c5d76a250e717eaa1a72ef5131
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/3bb1f5530d505b639ca7ba26761c255f0c856ff2 b/net/data/fuzzer_data/ntlm_client_fuzzer/3bb1f5530d505b639ca7ba26761c255f0c856ff2
new file mode 100644
index 0000000..8a4ba8b
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/3bb1f5530d505b639ca7ba26761c255f0c856ff2
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/challenge_too_short.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/3bce3cc96b0f520d1ec5a98d82827fd905c58bd9
similarity index 100%
rename from net/data/fuzzer_data/ntlm_client_fuzzer/challenge_too_short.bin
rename to net/data/fuzzer_data/ntlm_client_fuzzer/3bce3cc96b0f520d1ec5a98d82827fd905c58bd9
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/3bf5027c3a1794ab4c7b33340260763cc24e7eb7 b/net/data/fuzzer_data/ntlm_client_fuzzer/3bf5027c3a1794ab4c7b33340260763cc24e7eb7
new file mode 100644
index 0000000..80fb6915
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/3bf5027c3a1794ab4c7b33340260763cc24e7eb7
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/3cfcad418543de01597ed4b3f4103a24c73a455c b/net/data/fuzzer_data/ntlm_client_fuzzer/3cfcad418543de01597ed4b3f4103a24c73a455c
new file mode 100644
index 0000000..44a7653
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/3cfcad418543de01597ed4b3f4103a24c73a455c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/40574e590d9ae70852fa385b8b166820b4449e4a b/net/data/fuzzer_data/ntlm_client_fuzzer/40574e590d9ae70852fa385b8b166820b4449e4a
new file mode 100644
index 0000000..1d85130
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/40574e590d9ae70852fa385b8b166820b4449e4a
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/40fd824496cc1a63219645b0c8a709c2d955ae32 b/net/data/fuzzer_data/ntlm_client_fuzzer/40fd824496cc1a63219645b0c8a709c2d955ae32
new file mode 100644
index 0000000..2d208c9d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/40fd824496cc1a63219645b0c8a709c2d955ae32
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/4131d602d18f8e3c36c3e426d791e48432dd6eb4 b/net/data/fuzzer_data/ntlm_client_fuzzer/4131d602d18f8e3c36c3e426d791e48432dd6eb4
new file mode 100644
index 0000000..da887e92
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/4131d602d18f8e3c36c3e426d791e48432dd6eb4
@@ -0,0 +1,2 @@
+fffffff!fffffffffffÿûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿffffffffffffffffff
+
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/415820aff1e579d4233e95b1064d5a702fb5cc3e b/net/data/fuzzer_data/ntlm_client_fuzzer/415820aff1e579d4233e95b1064d5a702fb5cc3e
new file mode 100644
index 0000000..10451d3
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/415820aff1e579d4233e95b1064d5a702fb5cc3e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0003.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/416533a1c9823a15e1852131c4b4ae78b3439ce0
similarity index 100%
rename from net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0003.bin
rename to net/data/fuzzer_data/ntlm_client_fuzzer/416533a1c9823a15e1852131c4b4ae78b3439ce0
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/41a9b5b4736291e2c5802c045e6599342979de7e b/net/data/fuzzer_data/ntlm_client_fuzzer/41a9b5b4736291e2c5802c045e6599342979de7e
new file mode 100644
index 0000000..ffedcac
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/41a9b5b4736291e2c5802c045e6599342979de7e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/4277344c4d7e962c5da31c208e3caafc54fd6f2f b/net/data/fuzzer_data/ntlm_client_fuzzer/4277344c4d7e962c5da31c208e3caafc54fd6f2f
new file mode 100644
index 0000000..c72e10b
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/4277344c4d7e962c5da31c208e3caafc54fd6f2f
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/42f61ce40687b6eca86e268db27cb16ab125c009 b/net/data/fuzzer_data/ntlm_client_fuzzer/42f61ce40687b6eca86e268db27cb16ab125c009
new file mode 100644
index 0000000..bcfcd87
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/42f61ce40687b6eca86e268db27cb16ab125c009
@@ -0,0 +1 @@
+ff\\\\\\\\\\\\'\\\\
\ No newline at end of file
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/4358615edd88724d6c292d021a876a4e4d31a0a3 b/net/data/fuzzer_data/ntlm_client_fuzzer/4358615edd88724d6c292d021a876a4e4d31a0a3
new file mode 100644
index 0000000..d2a8dea8
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/4358615edd88724d6c292d021a876a4e4d31a0a3
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/4401ce39720e9f4fcb12fc800836a5f6a8a670fc b/net/data/fuzzer_data/ntlm_client_fuzzer/4401ce39720e9f4fcb12fc800836a5f6a8a670fc
new file mode 100644
index 0000000..a183ced
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/4401ce39720e9f4fcb12fc800836a5f6a8a670fc
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/440bb880bd0ece4cd5db8feda5bbff03ad5bc716 b/net/data/fuzzer_data/ntlm_client_fuzzer/440bb880bd0ece4cd5db8feda5bbff03ad5bc716
new file mode 100644
index 0000000..4a750d4
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/440bb880bd0ece4cd5db8feda5bbff03ad5bc716
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/44c34ff159b0843d1438972149f359c0bf31adf0 b/net/data/fuzzer_data/ntlm_client_fuzzer/44c34ff159b0843d1438972149f359c0bf31adf0
new file mode 100644
index 0000000..01281cd
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/44c34ff159b0843d1438972149f359c0bf31adf0
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/44d738098c3f3cb1b507bef0e7f835d8e145f114 b/net/data/fuzzer_data/ntlm_client_fuzzer/44d738098c3f3cb1b507bef0e7f835d8e145f114
new file mode 100644
index 0000000..e3089c42
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/44d738098c3f3cb1b507bef0e7f835d8e145f114
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/44f63db67e34491f0ff6bc302012bdb6e8924a2d b/net/data/fuzzer_data/ntlm_client_fuzzer/44f63db67e34491f0ff6bc302012bdb6e8924a2d
new file mode 100644
index 0000000..6f49d09
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/44f63db67e34491f0ff6bc302012bdb6e8924a2d
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/45016e41e1be021bfa0208e75fc3be91a5681a24 b/net/data/fuzzer_data/ntlm_client_fuzzer/45016e41e1be021bfa0208e75fc3be91a5681a24
new file mode 100644
index 0000000..997ce8a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/45016e41e1be021bfa0208e75fc3be91a5681a24
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/462cd061eb0da5ae01df2231bf9ef057f0b16ce7 b/net/data/fuzzer_data/ntlm_client_fuzzer/462cd061eb0da5ae01df2231bf9ef057f0b16ce7
new file mode 100644
index 0000000..874c754
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/462cd061eb0da5ae01df2231bf9ef057f0b16ce7
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/4638b9c9226c0d7318691774395fa426b67edb44 b/net/data/fuzzer_data/ntlm_client_fuzzer/4638b9c9226c0d7318691774395fa426b67edb44
new file mode 100644
index 0000000..a4a7463
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/4638b9c9226c0d7318691774395fa426b67edb44
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/46c4e8664d3ed0b896a295585c2d17413c6b82bc b/net/data/fuzzer_data/ntlm_client_fuzzer/46c4e8664d3ed0b896a295585c2d17413c6b82bc
new file mode 100644
index 0000000..bfcf9b7
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/46c4e8664d3ed0b896a295585c2d17413c6b82bc
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/473eeb8bebe027687e27405ee2cdb6f818df40be b/net/data/fuzzer_data/ntlm_client_fuzzer/473eeb8bebe027687e27405ee2cdb6f818df40be
new file mode 100644
index 0000000..f9db18a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/473eeb8bebe027687e27405ee2cdb6f818df40be
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/477d1afd114da66653d291d5e5eaad9c3a81aaf9 b/net/data/fuzzer_data/ntlm_client_fuzzer/477d1afd114da66653d291d5e5eaad9c3a81aaf9
new file mode 100644
index 0000000..c806a502
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/477d1afd114da66653d291d5e5eaad9c3a81aaf9
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/47f1eb5ffdfe6fcc0f91b132653519d1e763b737 b/net/data/fuzzer_data/ntlm_client_fuzzer/47f1eb5ffdfe6fcc0f91b132653519d1e763b737
new file mode 100644
index 0000000..926e1de6
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/47f1eb5ffdfe6fcc0f91b132653519d1e763b737
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/4817356482f275b4ba11b6a3aec9981c9b9274a7 b/net/data/fuzzer_data/ntlm_client_fuzzer/4817356482f275b4ba11b6a3aec9981c9b9274a7
new file mode 100644
index 0000000..6d324b79
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/4817356482f275b4ba11b6a3aec9981c9b9274a7
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/493fe3d7d6b226e856110c4dc7e43b3d70a8d495 b/net/data/fuzzer_data/ntlm_client_fuzzer/493fe3d7d6b226e856110c4dc7e43b3d70a8d495
new file mode 100644
index 0000000..b4a48b5
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/493fe3d7d6b226e856110c4dc7e43b3d70a8d495
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/49eb7a9b49aafd02214461539ba357b3e0f0c4ed b/net/data/fuzzer_data/ntlm_client_fuzzer/49eb7a9b49aafd02214461539ba357b3e0f0c4ed
new file mode 100644
index 0000000..ed08bd5
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/49eb7a9b49aafd02214461539ba357b3e0f0c4ed
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/4ac57949e8fdd712828f0219982362cf4e3da09c b/net/data/fuzzer_data/ntlm_client_fuzzer/4ac57949e8fdd712828f0219982362cf4e3da09c
new file mode 100644
index 0000000..380a4a5
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/4ac57949e8fdd712828f0219982362cf4e3da09c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/4bafe5887ee175229331745771a40379df2a83eb b/net/data/fuzzer_data/ntlm_client_fuzzer/4bafe5887ee175229331745771a40379df2a83eb
new file mode 100644
index 0000000..59a1580
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/4bafe5887ee175229331745771a40379df2a83eb
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/4c1bc402c18d9114e035e6c2dcf61ccfbc2d7bea b/net/data/fuzzer_data/ntlm_client_fuzzer/4c1bc402c18d9114e035e6c2dcf61ccfbc2d7bea
new file mode 100644
index 0000000..af8f23b
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/4c1bc402c18d9114e035e6c2dcf61ccfbc2d7bea
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_no_unicode.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/4cbf7d943c4113ec85044fecf8bf8c9caecd8a90
similarity index 100%
rename from net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_no_unicode.bin
rename to net/data/fuzzer_data/ntlm_client_fuzzer/4cbf7d943c4113ec85044fecf8bf8c9caecd8a90
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/4cd86b7365a94443034fa395773ff1b5653f8346 b/net/data/fuzzer_data/ntlm_client_fuzzer/4cd86b7365a94443034fa395773ff1b5653f8346
new file mode 100644
index 0000000..223565de
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/4cd86b7365a94443034fa395773ff1b5653f8346
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/4d0881fcd258b9c525b8cfd214f1a363b4cfcb4e b/net/data/fuzzer_data/ntlm_client_fuzzer/4d0881fcd258b9c525b8cfd214f1a363b4cfcb4e
new file mode 100644
index 0000000..2f803610
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/4d0881fcd258b9c525b8cfd214f1a363b4cfcb4e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/4e18d65af3be71989b0ce100566de21e5a0c3eca b/net/data/fuzzer_data/ntlm_client_fuzzer/4e18d65af3be71989b0ce100566de21e5a0c3eca
new file mode 100644
index 0000000..1ac099a7
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/4e18d65af3be71989b0ce100566de21e5a0c3eca
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/4e5dc701d5f4e4b11b3e2e0913392326904cbe5e b/net/data/fuzzer_data/ntlm_client_fuzzer/4e5dc701d5f4e4b11b3e2e0913392326904cbe5e
new file mode 100644
index 0000000..d0bb394
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/4e5dc701d5f4e4b11b3e2e0913392326904cbe5e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/4eb54412546fe215a3200fb0b9d9077caa2a483f b/net/data/fuzzer_data/ntlm_client_fuzzer/4eb54412546fe215a3200fb0b9d9077caa2a483f
new file mode 100644
index 0000000..e5457dac
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/4eb54412546fe215a3200fb0b9d9077caa2a483f
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/4ee6b8267b5220878be10eec11dc20bf88ed15a0 b/net/data/fuzzer_data/ntlm_client_fuzzer/4ee6b8267b5220878be10eec11dc20bf88ed15a0
new file mode 100644
index 0000000..dea732f9
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/4ee6b8267b5220878be10eec11dc20bf88ed15a0
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/4f1655819ecad55399a24f87b9df38939331346f b/net/data/fuzzer_data/ntlm_client_fuzzer/4f1655819ecad55399a24f87b9df38939331346f
new file mode 100644
index 0000000..8d7d298
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/4f1655819ecad55399a24f87b9df38939331346f
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/4f982983e14cbda9982ce247d8597522f62253b2 b/net/data/fuzzer_data/ntlm_client_fuzzer/4f982983e14cbda9982ce247d8597522f62253b2
new file mode 100644
index 0000000..9e07091c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/4f982983e14cbda9982ce247d8597522f62253b2
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/4fb282e139098c885a701d31e504662345dddcc6 b/net/data/fuzzer_data/ntlm_client_fuzzer/4fb282e139098c885a701d31e504662345dddcc6
new file mode 100644
index 0000000..4aee40f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/4fb282e139098c885a701d31e504662345dddcc6
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/50067881cd622b0b31bb2b7705e18bcd86aa97bd b/net/data/fuzzer_data/ntlm_client_fuzzer/50067881cd622b0b31bb2b7705e18bcd86aa97bd
new file mode 100644
index 0000000..1358f17
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/50067881cd622b0b31bb2b7705e18bcd86aa97bd
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/526caf9a280760db91ff169f93966bf083d028d5 b/net/data/fuzzer_data/ntlm_client_fuzzer/526caf9a280760db91ff169f93966bf083d028d5
new file mode 100644
index 0000000..351257a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/526caf9a280760db91ff169f93966bf083d028d5
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/55720b68df57b3feffc8bb097f053de8feae4407 b/net/data/fuzzer_data/ntlm_client_fuzzer/55720b68df57b3feffc8bb097f053de8feae4407
new file mode 100644
index 0000000..177ab6b
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/55720b68df57b3feffc8bb097f053de8feae4407
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/5587a45c0b63aa96976d040530d1447defe61992 b/net/data/fuzzer_data/ntlm_client_fuzzer/5587a45c0b63aa96976d040530d1447defe61992
new file mode 100644
index 0000000..ef98b4c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/5587a45c0b63aa96976d040530d1447defe61992
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/567e576eefbc73eaca887ea4240abd492f24a1d5 b/net/data/fuzzer_data/ntlm_client_fuzzer/567e576eefbc73eaca887ea4240abd492f24a1d5
new file mode 100644
index 0000000..4a673f0
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/567e576eefbc73eaca887ea4240abd492f24a1d5
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/568b3ff8f416f2734a2d423f358329dcd560570a b/net/data/fuzzer_data/ntlm_client_fuzzer/568b3ff8f416f2734a2d423f358329dcd560570a
new file mode 100644
index 0000000..4fcd7e8
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/568b3ff8f416f2734a2d423f358329dcd560570a
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/56c071138e249ab56c81a505908fe1b835e5a5e5 b/net/data/fuzzer_data/ntlm_client_fuzzer/56c071138e249ab56c81a505908fe1b835e5a5e5
new file mode 100644
index 0000000..112f4d4
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/56c071138e249ab56c81a505908fe1b835e5a5e5
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/56c8232e39d77533edcd1f0802959bd8320fd25a b/net/data/fuzzer_data/ntlm_client_fuzzer/56c8232e39d77533edcd1f0802959bd8320fd25a
new file mode 100644
index 0000000..9161628d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/56c8232e39d77533edcd1f0802959bd8320fd25a
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/56fa211e1a2f3e50d9dd39296478a6238bfad500 b/net/data/fuzzer_data/ntlm_client_fuzzer/56fa211e1a2f3e50d9dd39296478a6238bfad500
new file mode 100644
index 0000000..a0f512cc
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/56fa211e1a2f3e50d9dd39296478a6238bfad500
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/57012c4956d99bccbe3ab342aa42c40d1b5d3f34 b/net/data/fuzzer_data/ntlm_client_fuzzer/57012c4956d99bccbe3ab342aa42c40d1b5d3f34
new file mode 100644
index 0000000..db1bd9c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/57012c4956d99bccbe3ab342aa42c40d1b5d3f34
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/575e25abdaf0d107bfc1f3c783c814bb2cdcd77b b/net/data/fuzzer_data/ntlm_client_fuzzer/575e25abdaf0d107bfc1f3c783c814bb2cdcd77b
new file mode 100644
index 0000000..0fc7e15
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/575e25abdaf0d107bfc1f3c783c814bb2cdcd77b
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/576e8415a9ba4f2c7e9ce849c5b5b4111bd987be b/net/data/fuzzer_data/ntlm_client_fuzzer/576e8415a9ba4f2c7e9ce849c5b5b4111bd987be
new file mode 100644
index 0000000..9356162f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/576e8415a9ba4f2c7e9ce849c5b5b4111bd987be
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/577c9ccd9a8b4498d5ce518a94d3376d9799f81c b/net/data/fuzzer_data/ntlm_client_fuzzer/577c9ccd9a8b4498d5ce518a94d3376d9799f81c
new file mode 100644
index 0000000..2e8d5d8
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/577c9ccd9a8b4498d5ce518a94d3376d9799f81c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/5804b019ce878d8fbef2575671411b8cba1194d1 b/net/data/fuzzer_data/ntlm_client_fuzzer/5804b019ce878d8fbef2575671411b8cba1194d1
new file mode 100644
index 0000000..22c0f00
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/5804b019ce878d8fbef2575671411b8cba1194d1
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/5845bafa28d304f6df43813275c1113bc3853d0e b/net/data/fuzzer_data/ntlm_client_fuzzer/5845bafa28d304f6df43813275c1113bc3853d0e
new file mode 100644
index 0000000..c8f6e08f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/5845bafa28d304f6df43813275c1113bc3853d0e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/5891b41117c6e0922fb99431ceb6b5970b2347cc b/net/data/fuzzer_data/ntlm_client_fuzzer/5891b41117c6e0922fb99431ceb6b5970b2347cc
new file mode 100644
index 0000000..99eb33cb
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/5891b41117c6e0922fb99431ceb6b5970b2347cc
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/58ca38b988e01589efaf4bb2be1c528671c1e5ce b/net/data/fuzzer_data/ntlm_client_fuzzer/58ca38b988e01589efaf4bb2be1c528671c1e5ce
new file mode 100644
index 0000000..188adf5
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/58ca38b988e01589efaf4bb2be1c528671c1e5ce
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/58dddb1690e9d3c573524cac8c2644911fbf11bc b/net/data/fuzzer_data/ntlm_client_fuzzer/58dddb1690e9d3c573524cac8c2644911fbf11bc
new file mode 100644
index 0000000..15b972e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/58dddb1690e9d3c573524cac8c2644911fbf11bc
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/593f92e35e7fdadd38e9b8476c62ab26a3bb7a62 b/net/data/fuzzer_data/ntlm_client_fuzzer/593f92e35e7fdadd38e9b8476c62ab26a3bb7a62
new file mode 100644
index 0000000..cbb9edc
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/593f92e35e7fdadd38e9b8476c62ab26a3bb7a62
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/59a5a58500aa60100fffea3903e8a44ab523b222 b/net/data/fuzzer_data/ntlm_client_fuzzer/59a5a58500aa60100fffea3903e8a44ab523b222
new file mode 100644
index 0000000..ecf4125
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/59a5a58500aa60100fffea3903e8a44ab523b222
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/59b41af166db05b5603afde448958cadbeaa5b63 b/net/data/fuzzer_data/ntlm_client_fuzzer/59b41af166db05b5603afde448958cadbeaa5b63
new file mode 100644
index 0000000..589de36
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/59b41af166db05b5603afde448958cadbeaa5b63
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/5a09c77783d7d41bc95f3012d1f8ea5f8fd88f51 b/net/data/fuzzer_data/ntlm_client_fuzzer/5a09c77783d7d41bc95f3012d1f8ea5f8fd88f51
new file mode 100644
index 0000000..3f64fb29
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/5a09c77783d7d41bc95f3012d1f8ea5f8fd88f51
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/5a3e9cc4ee42a28f776c98fbe63cef9d1ae0b015 b/net/data/fuzzer_data/ntlm_client_fuzzer/5a3e9cc4ee42a28f776c98fbe63cef9d1ae0b015
new file mode 100644
index 0000000..9f93b630
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/5a3e9cc4ee42a28f776c98fbe63cef9d1ae0b015
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/5a50274bc0eb4759fd7916cb1b5c3223e71ec5a5 b/net/data/fuzzer_data/ntlm_client_fuzzer/5a50274bc0eb4759fd7916cb1b5c3223e71ec5a5
new file mode 100644
index 0000000..4ba9d30
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/5a50274bc0eb4759fd7916cb1b5c3223e71ec5a5
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/5a56aa6192499714a90449a66eaed3c682117231 b/net/data/fuzzer_data/ntlm_client_fuzzer/5a56aa6192499714a90449a66eaed3c682117231
new file mode 100644
index 0000000..b329cf0
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/5a56aa6192499714a90449a66eaed3c682117231
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/5a840579124fd0516820cec69449357abf7b2357 b/net/data/fuzzer_data/ntlm_client_fuzzer/5a840579124fd0516820cec69449357abf7b2357
new file mode 100644
index 0000000..4680b8d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/5a840579124fd0516820cec69449357abf7b2357
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0158.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/5ba93c9db0cff93f52b521d7420e43f6eda2784f
similarity index 100%
rename from net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0158.bin
rename to net/data/fuzzer_data/ntlm_client_fuzzer/5ba93c9db0cff93f52b521d7420e43f6eda2784f
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/5bfb53f8ebe5fe6da5e8f33c0670700587729e07 b/net/data/fuzzer_data/ntlm_client_fuzzer/5bfb53f8ebe5fe6da5e8f33c0670700587729e07
new file mode 100644
index 0000000..b4d10d0
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/5bfb53f8ebe5fe6da5e8f33c0670700587729e07
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/5c08e8aac87f7542379063f3e2e66248a04aa6d6 b/net/data/fuzzer_data/ntlm_client_fuzzer/5c08e8aac87f7542379063f3e2e66248a04aa6d6
new file mode 100644
index 0000000..830a0ea
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/5c08e8aac87f7542379063f3e2e66248a04aa6d6
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/5c85457bb787a1c199aa77bec1b6edb6f4e06136 b/net/data/fuzzer_data/ntlm_client_fuzzer/5c85457bb787a1c199aa77bec1b6edb6f4e06136
new file mode 100644
index 0000000..072621b
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/5c85457bb787a1c199aa77bec1b6edb6f4e06136
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/5df302227c6c2b2d5c14b7a80889d6e63dd5be38 b/net/data/fuzzer_data/ntlm_client_fuzzer/5df302227c6c2b2d5c14b7a80889d6e63dd5be38
new file mode 100644
index 0000000..4a0b7f1
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/5df302227c6c2b2d5c14b7a80889d6e63dd5be38
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/5e3ba895ed51e467e1763275d606e4ddc7be684a b/net/data/fuzzer_data/ntlm_client_fuzzer/5e3ba895ed51e467e1763275d606e4ddc7be684a
new file mode 100644
index 0000000..2fe3207
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/5e3ba895ed51e467e1763275d606e4ddc7be684a
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/5f919e0f4e997f155aa561fcaac6fc80374a53b9 b/net/data/fuzzer_data/ntlm_client_fuzzer/5f919e0f4e997f155aa561fcaac6fc80374a53b9
new file mode 100644
index 0000000..84ef1dd
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/5f919e0f4e997f155aa561fcaac6fc80374a53b9
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/600e0571b19df56c92f2084ff8d965bb4f721095 b/net/data/fuzzer_data/ntlm_client_fuzzer/600e0571b19df56c92f2084ff8d965bb4f721095
new file mode 100644
index 0000000..53bb1c2
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/600e0571b19df56c92f2084ff8d965bb4f721095
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/60bffce12135b14c5f0ce096c7e9ad195dff6f25 b/net/data/fuzzer_data/ntlm_client_fuzzer/60bffce12135b14c5f0ce096c7e9ad195dff6f25
new file mode 100644
index 0000000..c64f77a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/60bffce12135b14c5f0ce096c7e9ad195dff6f25
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/60f03c266e6f924456e141a865b92769ab06e555 b/net/data/fuzzer_data/ntlm_client_fuzzer/60f03c266e6f924456e141a865b92769ab06e555
new file mode 100644
index 0000000..c949326
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/60f03c266e6f924456e141a865b92769ab06e555
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/614fcac2e1fdfc30ec78a33be7fe0ba18251f687 b/net/data/fuzzer_data/ntlm_client_fuzzer/614fcac2e1fdfc30ec78a33be7fe0ba18251f687
new file mode 100644
index 0000000..f8ae614
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/614fcac2e1fdfc30ec78a33be7fe0ba18251f687
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/615c949d65d779179be139f1c94a8bf0b4ffa194 b/net/data/fuzzer_data/ntlm_client_fuzzer/615c949d65d779179be139f1c94a8bf0b4ffa194
new file mode 100644
index 0000000..2d23b247
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/615c949d65d779179be139f1c94a8bf0b4ffa194
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/618ec092a528e2e768346e9375ce2a4f9f9f62ab b/net/data/fuzzer_data/ntlm_client_fuzzer/618ec092a528e2e768346e9375ce2a4f9f9f62ab
new file mode 100644
index 0000000..3f271f1
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/618ec092a528e2e768346e9375ce2a4f9f9f62ab
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/622cb42c7c8816291b209bfd9defc64929bd7dd6 b/net/data/fuzzer_data/ntlm_client_fuzzer/622cb42c7c8816291b209bfd9defc64929bd7dd6
new file mode 100644
index 0000000..907baea
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/622cb42c7c8816291b209bfd9defc64929bd7dd6
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/63212c997e147bf6d6feb940e6a9d65b3425af42 b/net/data/fuzzer_data/ntlm_client_fuzzer/63212c997e147bf6d6feb940e6a9d65b3425af42
new file mode 100644
index 0000000..9a81f3f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/63212c997e147bf6d6feb940e6a9d65b3425af42
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/633303056902ed214fe5f95c5bdce3f35be93ec2 b/net/data/fuzzer_data/ntlm_client_fuzzer/633303056902ed214fe5f95c5bdce3f35be93ec2
new file mode 100644
index 0000000..1854ab9
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/633303056902ed214fe5f95c5bdce3f35be93ec2
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/638253f2efdc5d333061d8a579c2cfd6fa3b9877 b/net/data/fuzzer_data/ntlm_client_fuzzer/638253f2efdc5d333061d8a579c2cfd6fa3b9877
new file mode 100644
index 0000000..49c1132
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/638253f2efdc5d333061d8a579c2cfd6fa3b9877
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/641b51c08d2295723b706d440238fe64f8959c6e b/net/data/fuzzer_data/ntlm_client_fuzzer/641b51c08d2295723b706d440238fe64f8959c6e
new file mode 100644
index 0000000..77e4ba8
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/641b51c08d2295723b706d440238fe64f8959c6e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/64936cab6c7e8cc80a5a72c0548eac418e13e508 b/net/data/fuzzer_data/ntlm_client_fuzzer/64936cab6c7e8cc80a5a72c0548eac418e13e508
new file mode 100644
index 0000000..dbab871
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/64936cab6c7e8cc80a5a72c0548eac418e13e508
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/6495599518907f2e8e1909674a49e1b4305896aa b/net/data/fuzzer_data/ntlm_client_fuzzer/6495599518907f2e8e1909674a49e1b4305896aa
new file mode 100644
index 0000000..6c1f48d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/6495599518907f2e8e1909674a49e1b4305896aa
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/64f79af2c26f69369b871a44565c6d40f1569b4c b/net/data/fuzzer_data/ntlm_client_fuzzer/64f79af2c26f69369b871a44565c6d40f1569b4c
new file mode 100644
index 0000000..4337d88
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/64f79af2c26f69369b871a44565c6d40f1569b4c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/65034434e6e61345d9691dafb3ecad1b53a7059b b/net/data/fuzzer_data/ntlm_client_fuzzer/65034434e6e61345d9691dafb3ecad1b53a7059b
new file mode 100644
index 0000000..8eb5172
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/65034434e6e61345d9691dafb3ecad1b53a7059b
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/650e94100a020805125154c821a4fa85a0d53909 b/net/data/fuzzer_data/ntlm_client_fuzzer/650e94100a020805125154c821a4fa85a0d53909
new file mode 100644
index 0000000..750cd3f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/650e94100a020805125154c821a4fa85a0d53909
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/675edc469e6646fe95702dd2c823be68452d805b b/net/data/fuzzer_data/ntlm_client_fuzzer/675edc469e6646fe95702dd2c823be68452d805b
new file mode 100644
index 0000000..9f908ba1
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/675edc469e6646fe95702dd2c823be68452d805b
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/685543a5189189d64ff5824a4a07cd2f9e857f3c b/net/data/fuzzer_data/ntlm_client_fuzzer/685543a5189189d64ff5824a4a07cd2f9e857f3c
new file mode 100644
index 0000000..3868b1db
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/685543a5189189d64ff5824a4a07cd2f9e857f3c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/690632e6036af7e1a470890612facecf6743d58e b/net/data/fuzzer_data/ntlm_client_fuzzer/690632e6036af7e1a470890612facecf6743d58e
new file mode 100644
index 0000000..8b595ea
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/690632e6036af7e1a470890612facecf6743d58e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/693025a0676fce74564a05828a57e214ed860d11 b/net/data/fuzzer_data/ntlm_client_fuzzer/693025a0676fce74564a05828a57e214ed860d11
new file mode 100644
index 0000000..0a5bef6
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/693025a0676fce74564a05828a57e214ed860d11
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/6aadba8c6047701c73bdda75b25c72c4d3d41351 b/net/data/fuzzer_data/ntlm_client_fuzzer/6aadba8c6047701c73bdda75b25c72c4d3d41351
new file mode 100644
index 0000000..d978b3c8
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/6aadba8c6047701c73bdda75b25c72c4d3d41351
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/6ad35072ce217980419f870415f10ac71c36fb4f b/net/data/fuzzer_data/ntlm_client_fuzzer/6ad35072ce217980419f870415f10ac71c36fb4f
new file mode 100644
index 0000000..e5d4a21
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/6ad35072ce217980419f870415f10ac71c36fb4f
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/6b0d9cc96e46bb7f32a9181d399f26eef066066f b/net/data/fuzzer_data/ntlm_client_fuzzer/6b0d9cc96e46bb7f32a9181d399f26eef066066f
new file mode 100644
index 0000000..f70c1d7
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/6b0d9cc96e46bb7f32a9181d399f26eef066066f
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/6b33271de9f836544dc4196498b0b2bda489889e b/net/data/fuzzer_data/ntlm_client_fuzzer/6b33271de9f836544dc4196498b0b2bda489889e
new file mode 100644
index 0000000..7f7711c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/6b33271de9f836544dc4196498b0b2bda489889e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/6b759856cddafff465d8d2f0af6fca03a18dd2bb b/net/data/fuzzer_data/ntlm_client_fuzzer/6b759856cddafff465d8d2f0af6fca03a18dd2bb
new file mode 100644
index 0000000..9735b27
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/6b759856cddafff465d8d2f0af6fca03a18dd2bb
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/6d6caa6a9d0f596f830c13c852c6c235bf3e4d63 b/net/data/fuzzer_data/ntlm_client_fuzzer/6d6caa6a9d0f596f830c13c852c6c235bf3e4d63
new file mode 100644
index 0000000..74066f62
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/6d6caa6a9d0f596f830c13c852c6c235bf3e4d63
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/6d7395dd15392dbd484dc85307aff52a177ca8c1 b/net/data/fuzzer_data/ntlm_client_fuzzer/6d7395dd15392dbd484dc85307aff52a177ca8c1
new file mode 100644
index 0000000..c595ad94
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/6d7395dd15392dbd484dc85307aff52a177ca8c1
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/6f0d6d31873fb232dcd1603b9c5b854f650ace00 b/net/data/fuzzer_data/ntlm_client_fuzzer/6f0d6d31873fb232dcd1603b9c5b854f650ace00
new file mode 100644
index 0000000..8b852bd
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/6f0d6d31873fb232dcd1603b9c5b854f650ace00
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/6fe2d2beb05247ba66d9ff7d44064234e8c9294c b/net/data/fuzzer_data/ntlm_client_fuzzer/6fe2d2beb05247ba66d9ff7d44064234e8c9294c
new file mode 100644
index 0000000..35cf7cc
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/6fe2d2beb05247ba66d9ff7d44064234e8c9294c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/71a60aa31a68ac373c826f3c485e62cfd0fe77e0 b/net/data/fuzzer_data/ntlm_client_fuzzer/71a60aa31a68ac373c826f3c485e62cfd0fe77e0
new file mode 100644
index 0000000..42fe626
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/71a60aa31a68ac373c826f3c485e62cfd0fe77e0
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/71a9dd0a381abd94714a52ce3b6b1b192aa7a7cd b/net/data/fuzzer_data/ntlm_client_fuzzer/71a9dd0a381abd94714a52ce3b6b1b192aa7a7cd
new file mode 100644
index 0000000..29d459b4
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/71a9dd0a381abd94714a52ce3b6b1b192aa7a7cd
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/71c213ad9c8d6dec46f094c247342babad351024 b/net/data/fuzzer_data/ntlm_client_fuzzer/71c213ad9c8d6dec46f094c247342babad351024
new file mode 100644
index 0000000..8ddbff34
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/71c213ad9c8d6dec46f094c247342babad351024
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/7487876d32d3f61ecbca5126d212e64c4cf703be b/net/data/fuzzer_data/ntlm_client_fuzzer/7487876d32d3f61ecbca5126d212e64c4cf703be
new file mode 100644
index 0000000..862a43d5
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/7487876d32d3f61ecbca5126d212e64c4cf703be
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/74cb4db06de9a66d6ffb8b7c429b9c1d0699dd8d b/net/data/fuzzer_data/ntlm_client_fuzzer/74cb4db06de9a66d6ffb8b7c429b9c1d0699dd8d
new file mode 100644
index 0000000..0d0881f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/74cb4db06de9a66d6ffb8b7c429b9c1d0699dd8d
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/754b6b1d003eafa337752c38780f874ebeb068ca b/net/data/fuzzer_data/ntlm_client_fuzzer/754b6b1d003eafa337752c38780f874ebeb068ca
new file mode 100644
index 0000000..1de8d90
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/754b6b1d003eafa337752c38780f874ebeb068ca
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/7577ee17f31e3fe647703f4eccfc117008800d8e b/net/data/fuzzer_data/ntlm_client_fuzzer/7577ee17f31e3fe647703f4eccfc117008800d8e
new file mode 100644
index 0000000..100c7bf
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/7577ee17f31e3fe647703f4eccfc117008800d8e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/76375f6ec383cf3a2a86faf6362f351edc58417d b/net/data/fuzzer_data/ntlm_client_fuzzer/76375f6ec383cf3a2a86faf6362f351edc58417d
new file mode 100644
index 0000000..5e9281e6
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/76375f6ec383cf3a2a86faf6362f351edc58417d
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/7647e144ccbdb304d06101ddedb4f311c2db50f5 b/net/data/fuzzer_data/ntlm_client_fuzzer/7647e144ccbdb304d06101ddedb4f311c2db50f5
new file mode 100644
index 0000000..38b38f2f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/7647e144ccbdb304d06101ddedb4f311c2db50f5
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/783030e7692b6e37c23a027475992b1da00cb039 b/net/data/fuzzer_data/ntlm_client_fuzzer/783030e7692b6e37c23a027475992b1da00cb039
new file mode 100644
index 0000000..f1e2634
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/783030e7692b6e37c23a027475992b1da00cb039
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/78795bcbbcef92aebc631ee87af4c85c518a0f4d b/net/data/fuzzer_data/ntlm_client_fuzzer/78795bcbbcef92aebc631ee87af4c85c518a0f4d
new file mode 100644
index 0000000..1501934
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/78795bcbbcef92aebc631ee87af4c85c518a0f4d
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/799033f462e819a4c57fb5adf8ef40600d6acc3c b/net/data/fuzzer_data/ntlm_client_fuzzer/799033f462e819a4c57fb5adf8ef40600d6acc3c
new file mode 100644
index 0000000..fd27cd3
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/799033f462e819a4c57fb5adf8ef40600d6acc3c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/79d602a3e5a2b59b8c75ee3211306cbddd9147e3 b/net/data/fuzzer_data/ntlm_client_fuzzer/79d602a3e5a2b59b8c75ee3211306cbddd9147e3
new file mode 100644
index 0000000..61af46c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/79d602a3e5a2b59b8c75ee3211306cbddd9147e3
@@ -0,0 +1,2 @@
+fffffffffffffffffffffffffffffffffffffff
+
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/79f6fd3a2d087c5e855e09a2af702c42b4652d70 b/net/data/fuzzer_data/ntlm_client_fuzzer/79f6fd3a2d087c5e855e09a2af702c42b4652d70
new file mode 100644
index 0000000..b0ec302
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/79f6fd3a2d087c5e855e09a2af702c42b4652d70
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/7a197001bfadcacdbd6c447706182229388be528 b/net/data/fuzzer_data/ntlm_client_fuzzer/7a197001bfadcacdbd6c447706182229388be528
new file mode 100644
index 0000000..44323918
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/7a197001bfadcacdbd6c447706182229388be528
@@ -0,0 +1 @@
+½¼¼ÀCCCCCCCCCCCCCCCCCCCf(fffffffffý
\ No newline at end of file
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/7ba4dc20740c07afcd4be12bb8713f89e1052a02 b/net/data/fuzzer_data/ntlm_client_fuzzer/7ba4dc20740c07afcd4be12bb8713f89e1052a02
new file mode 100644
index 0000000..eb72ac8
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/7ba4dc20740c07afcd4be12bb8713f89e1052a02
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/7bf8429612765ddd367c119d53813b3d81fca867 b/net/data/fuzzer_data/ntlm_client_fuzzer/7bf8429612765ddd367c119d53813b3d81fca867
new file mode 100644
index 0000000..2ef7900
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/7bf8429612765ddd367c119d53813b3d81fca867
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/7dbb6ebac8f4e300fa73abe02bbc44c4ea7b59ae b/net/data/fuzzer_data/ntlm_client_fuzzer/7dbb6ebac8f4e300fa73abe02bbc44c4ea7b59ae
new file mode 100644
index 0000000..ecc65a6
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/7dbb6ebac8f4e300fa73abe02bbc44c4ea7b59ae
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/7df88cb302187fd60f2048a057d2a471e621187e b/net/data/fuzzer_data/ntlm_client_fuzzer/7df88cb302187fd60f2048a057d2a471e621187e
new file mode 100644
index 0000000..3b53ce2
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/7df88cb302187fd60f2048a057d2a471e621187e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/7e72e38998f3feb33e71d2a2f665079a71e5e440 b/net/data/fuzzer_data/ntlm_client_fuzzer/7e72e38998f3feb33e71d2a2f665079a71e5e440
new file mode 100644
index 0000000..eca2fffa
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/7e72e38998f3feb33e71d2a2f665079a71e5e440
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/7faf23cc5aff196bf40c1fa1c478ec148fce6062 b/net/data/fuzzer_data/ntlm_client_fuzzer/7faf23cc5aff196bf40c1fa1c478ec148fce6062
new file mode 100644
index 0000000..e21ab5f2
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/7faf23cc5aff196bf40c1fa1c478ec148fce6062
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/815787ccac1f6555ebb6d333551ace2ea7002479 b/net/data/fuzzer_data/ntlm_client_fuzzer/815787ccac1f6555ebb6d333551ace2ea7002479
new file mode 100644
index 0000000..46b29ccd
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/815787ccac1f6555ebb6d333551ace2ea7002479
@@ -0,0 +1 @@
+\MSSllu_summarygmarrage_;s:umm‰«Í
\ No newline at end of file
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/81b7c983f4ae6d00edb9875202dcbe57d6df6e63 b/net/data/fuzzer_data/ntlm_client_fuzzer/81b7c983f4ae6d00edb9875202dcbe57d6df6e63
new file mode 100644
index 0000000..4517e5c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/81b7c983f4ae6d00edb9875202dcbe57d6df6e63
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/8264ce274122fcab5ad3e106c1f41e790cfcc15a b/net/data/fuzzer_data/ntlm_client_fuzzer/8264ce274122fcab5ad3e106c1f41e790cfcc15a
new file mode 100644
index 0000000..a72d4677
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/8264ce274122fcab5ad3e106c1f41e790cfcc15a
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/82c493f0f74e9f04e2329b53d08dbdb69954fc16 b/net/data/fuzzer_data/ntlm_client_fuzzer/82c493f0f74e9f04e2329b53d08dbdb69954fc16
new file mode 100644
index 0000000..e7546ef8
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/82c493f0f74e9f04e2329b53d08dbdb69954fc16
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/833dbecc1ae9d0976c82cecef3c7f0d8fd48dc1b b/net/data/fuzzer_data/ntlm_client_fuzzer/833dbecc1ae9d0976c82cecef3c7f0d8fd48dc1b
new file mode 100644
index 0000000..1fcf9ed6
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/833dbecc1ae9d0976c82cecef3c7f0d8fd48dc1b
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/834b63787ecac7393f0f0b17604ee0f43744f47f b/net/data/fuzzer_data/ntlm_client_fuzzer/834b63787ecac7393f0f0b17604ee0f43744f47f
new file mode 100644
index 0000000..28b3e32
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/834b63787ecac7393f0f0b17604ee0f43744f47f
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/83d06c2015c21b19eb8773914a7577c1f429bdcf b/net/data/fuzzer_data/ntlm_client_fuzzer/83d06c2015c21b19eb8773914a7577c1f429bdcf
new file mode 100644
index 0000000..bb03a73
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/83d06c2015c21b19eb8773914a7577c1f429bdcf
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/840bf6d5f4d0aa32b3b419c7d56aa9aff7dc0152 b/net/data/fuzzer_data/ntlm_client_fuzzer/840bf6d5f4d0aa32b3b419c7d56aa9aff7dc0152
new file mode 100644
index 0000000..8fd08fc
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/840bf6d5f4d0aa32b3b419c7d56aa9aff7dc0152
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/8461d888f7896cd17e0bc25179ba67fc5e9f37c6 b/net/data/fuzzer_data/ntlm_client_fuzzer/8461d888f7896cd17e0bc25179ba67fc5e9f37c6
new file mode 100644
index 0000000..2296cd92
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/8461d888f7896cd17e0bc25179ba67fc5e9f37c6
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/846358e31580f0907388c0023ad374389d231dce b/net/data/fuzzer_data/ntlm_client_fuzzer/846358e31580f0907388c0023ad374389d231dce
new file mode 100644
index 0000000..88bacf12
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/846358e31580f0907388c0023ad374389d231dce
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/847cb4ed8f90ffa3d9c38c4ebe3dbecf6ed14c33 b/net/data/fuzzer_data/ntlm_client_fuzzer/847cb4ed8f90ffa3d9c38c4ebe3dbecf6ed14c33
new file mode 100644
index 0000000..9a07ce1
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/847cb4ed8f90ffa3d9c38c4ebe3dbecf6ed14c33
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/8497b928eb2b1e4710a4561f15fe0f6518229f8c b/net/data/fuzzer_data/ntlm_client_fuzzer/8497b928eb2b1e4710a4561f15fe0f6518229f8c
new file mode 100644
index 0000000..68ac40f6
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/8497b928eb2b1e4710a4561f15fe0f6518229f8c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/85d1f354721f48a688731a47249ec90f82d82ced b/net/data/fuzzer_data/ntlm_client_fuzzer/85d1f354721f48a688731a47249ec90f82d82ced
new file mode 100644
index 0000000..24d6090
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/85d1f354721f48a688731a47249ec90f82d82ced
@@ -0,0 +1 @@
+)\C2\2ffffCCffß
\ No newline at end of file
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/85f9b971e641a8e5a82c80fe254654b7a235f536 b/net/data/fuzzer_data/ntlm_client_fuzzer/85f9b971e641a8e5a82c80fe254654b7a235f536
new file mode 100644
index 0000000..751cb085
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/85f9b971e641a8e5a82c80fe254654b7a235f536
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/86676876ca91731ac0c75b7663cf00ae44ab3475 b/net/data/fuzzer_data/ntlm_client_fuzzer/86676876ca91731ac0c75b7663cf00ae44ab3475
new file mode 100644
index 0000000..4d5e74af
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/86676876ca91731ac0c75b7663cf00ae44ab3475
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/87248bc265d6789695da999bb68cd0b640ba9f44 b/net/data/fuzzer_data/ntlm_client_fuzzer/87248bc265d6789695da999bb68cd0b640ba9f44
new file mode 100644
index 0000000..50e7eb25
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/87248bc265d6789695da999bb68cd0b640ba9f44
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/872fd2db7b75a45db29222d60720539bb9d167de b/net/data/fuzzer_data/ntlm_client_fuzzer/872fd2db7b75a45db29222d60720539bb9d167de
new file mode 100644
index 0000000..e01b9fc
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/872fd2db7b75a45db29222d60720539bb9d167de
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/874f47b24d53fa9cacd7a60a91517b5ceec1eef8 b/net/data/fuzzer_data/ntlm_client_fuzzer/874f47b24d53fa9cacd7a60a91517b5ceec1eef8
new file mode 100644
index 0000000..17f2b02c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/874f47b24d53fa9cacd7a60a91517b5ceec1eef8
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/8781f3365623be39e22627ac8d70eaa7eb608b95 b/net/data/fuzzer_data/ntlm_client_fuzzer/8781f3365623be39e22627ac8d70eaa7eb608b95
new file mode 100644
index 0000000..f414021
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/8781f3365623be39e22627ac8d70eaa7eb608b95
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/87ab5771ee145369a8967ae66e0d8015750a7b4c b/net/data/fuzzer_data/ntlm_client_fuzzer/87ab5771ee145369a8967ae66e0d8015750a7b4c
new file mode 100644
index 0000000..61a507d0
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/87ab5771ee145369a8967ae66e0d8015750a7b4c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/87f1494f43ac58a759572df97903f60f8421ea44 b/net/data/fuzzer_data/ntlm_client_fuzzer/87f1494f43ac58a759572df97903f60f8421ea44
new file mode 100644
index 0000000..3f6e611
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/87f1494f43ac58a759572df97903f60f8421ea44
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/880e1e6c845aa06836aec6ab92ed349628eafb8e b/net/data/fuzzer_data/ntlm_client_fuzzer/880e1e6c845aa06836aec6ab92ed349628eafb8e
new file mode 100644
index 0000000..3481d39d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/880e1e6c845aa06836aec6ab92ed349628eafb8e
@@ -0,0 +1,2 @@
+fffff
+fffff
\ No newline at end of file
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/889f25bb4e4f15393ae5d3c0faba00f1c3e9b745 b/net/data/fuzzer_data/ntlm_client_fuzzer/889f25bb4e4f15393ae5d3c0faba00f1c3e9b745
new file mode 100644
index 0000000..09a764f58
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/889f25bb4e4f15393ae5d3c0faba00f1c3e9b745
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/88b550b5831325d07a7794f60a579ac6a850ed00 b/net/data/fuzzer_data/ntlm_client_fuzzer/88b550b5831325d07a7794f60a579ac6a850ed00
new file mode 100644
index 0000000..561e762
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/88b550b5831325d07a7794f60a579ac6a850ed00
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/890b75c52add868bdaccb76bcad7c816c0cc23dd b/net/data/fuzzer_data/ntlm_client_fuzzer/890b75c52add868bdaccb76bcad7c816c0cc23dd
new file mode 100644
index 0000000..baae5c0
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/890b75c52add868bdaccb76bcad7c816c0cc23dd
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/8980f1d8282634083f80e33779d1b3868997e6ba b/net/data/fuzzer_data/ntlm_client_fuzzer/8980f1d8282634083f80e33779d1b3868997e6ba
new file mode 100644
index 0000000..6423e201
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/8980f1d8282634083f80e33779d1b3868997e6ba
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/8b82cc65b8586d9e0059392e3653a96e95f3354b b/net/data/fuzzer_data/ntlm_client_fuzzer/8b82cc65b8586d9e0059392e3653a96e95f3354b
new file mode 100644
index 0000000..eb80f22
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/8b82cc65b8586d9e0059392e3653a96e95f3354b
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/8c0b1029274a14d019f2e1b05b56022b47746dd0 b/net/data/fuzzer_data/ntlm_client_fuzzer/8c0b1029274a14d019f2e1b05b56022b47746dd0
new file mode 100644
index 0000000..6c198f2
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/8c0b1029274a14d019f2e1b05b56022b47746dd0
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/8e9ceeef1a9426bf6dfffe701764c1c7a149d3b6 b/net/data/fuzzer_data/ntlm_client_fuzzer/8e9ceeef1a9426bf6dfffe701764c1c7a149d3b6
new file mode 100644
index 0000000..7d35370
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/8e9ceeef1a9426bf6dfffe701764c1c7a149d3b6
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/8e9d35c4f21bca8ccba033100d4b71ec71250f1d b/net/data/fuzzer_data/ntlm_client_fuzzer/8e9d35c4f21bca8ccba033100d4b71ec71250f1d
new file mode 100644
index 0000000..5c4f7e7f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/8e9d35c4f21bca8ccba033100d4b71ec71250f1d
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/8ed905e3321bb41bcc565a0b3592fa38f386fbdd b/net/data/fuzzer_data/ntlm_client_fuzzer/8ed905e3321bb41bcc565a0b3592fa38f386fbdd
new file mode 100644
index 0000000..6236c6e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/8ed905e3321bb41bcc565a0b3592fa38f386fbdd
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/8eeba836ce0e08ba695d6e578645ff8d19fb9ee9 b/net/data/fuzzer_data/ntlm_client_fuzzer/8eeba836ce0e08ba695d6e578645ff8d19fb9ee9
new file mode 100644
index 0000000..672ec11
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/8eeba836ce0e08ba695d6e578645ff8d19fb9ee9
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/8f01ea13c723e56651370f3d3c037ebacdcb3116 b/net/data/fuzzer_data/ntlm_client_fuzzer/8f01ea13c723e56651370f3d3c037ebacdcb3116
new file mode 100644
index 0000000..98f8731
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/8f01ea13c723e56651370f3d3c037ebacdcb3116
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/8f169ab3df777790293c4321f2bd08fb63af254b b/net/data/fuzzer_data/ntlm_client_fuzzer/8f169ab3df777790293c4321f2bd08fb63af254b
new file mode 100644
index 0000000..33cc01c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/8f169ab3df777790293c4321f2bd08fb63af254b
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/8fffc593ab4a73bd024041ad7b1272a45ce6ed2c b/net/data/fuzzer_data/ntlm_client_fuzzer/8fffc593ab4a73bd024041ad7b1272a45ce6ed2c
new file mode 100644
index 0000000..b8bc001
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/8fffc593ab4a73bd024041ad7b1272a45ce6ed2c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/914c2a920097c7d083fe4d776e2ad4d02c811826 b/net/data/fuzzer_data/ntlm_client_fuzzer/914c2a920097c7d083fe4d776e2ad4d02c811826
new file mode 100644
index 0000000..84ecc1c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/914c2a920097c7d083fe4d776e2ad4d02c811826
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/9175475a1f8d4cb064997c682b01622f9e563b6e b/net/data/fuzzer_data/ntlm_client_fuzzer/9175475a1f8d4cb064997c682b01622f9e563b6e
new file mode 100644
index 0000000..e2a0faf
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/9175475a1f8d4cb064997c682b01622f9e563b6e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/91b6d23c815999a5e46827268d022542b9b6e0f5 b/net/data/fuzzer_data/ntlm_client_fuzzer/91b6d23c815999a5e46827268d022542b9b6e0f5
new file mode 100644
index 0000000..3bb966f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/91b6d23c815999a5e46827268d022542b9b6e0f5
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/92121ed6b3f167e1ef9f2a9a9ef2663a6e26ab55 b/net/data/fuzzer_data/ntlm_client_fuzzer/92121ed6b3f167e1ef9f2a9a9ef2663a6e26ab55
new file mode 100644
index 0000000..8f0b322c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/92121ed6b3f167e1ef9f2a9a9ef2663a6e26ab55
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/9238b5243b0d5d3c38b1afc42c9a71fca5005741 b/net/data/fuzzer_data/ntlm_client_fuzzer/9238b5243b0d5d3c38b1afc42c9a71fca5005741
new file mode 100644
index 0000000..5e2c3ec
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/9238b5243b0d5d3c38b1afc42c9a71fca5005741
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/9242f8e2cf8410a3e5b0a3602aff7e0731bd19c8 b/net/data/fuzzer_data/ntlm_client_fuzzer/9242f8e2cf8410a3e5b0a3602aff7e0731bd19c8
new file mode 100644
index 0000000..f4d79aa
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/9242f8e2cf8410a3e5b0a3602aff7e0731bd19c8
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/9263137058b184fa15a6de31c6871ab789fca5ad b/net/data/fuzzer_data/ntlm_client_fuzzer/9263137058b184fa15a6de31c6871ab789fca5ad
new file mode 100644
index 0000000..3c734ca
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/9263137058b184fa15a6de31c6871ab789fca5ad
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/92be6c67c26dd6c7f6b99286d1663fed8156ca3d b/net/data/fuzzer_data/ntlm_client_fuzzer/92be6c67c26dd6c7f6b99286d1663fed8156ca3d
new file mode 100644
index 0000000..d2a8a94
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/92be6c67c26dd6c7f6b99286d1663fed8156ca3d
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/936d5755fa7368f5a90922c6ecaf534156a43027 b/net/data/fuzzer_data/ntlm_client_fuzzer/936d5755fa7368f5a90922c6ecaf534156a43027
new file mode 100644
index 0000000..702d190
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/936d5755fa7368f5a90922c6ecaf534156a43027
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/93c3f5e7b7544bdb2a6cfdf5dccd669fe1e0ea7e b/net/data/fuzzer_data/ntlm_client_fuzzer/93c3f5e7b7544bdb2a6cfdf5dccd669fe1e0ea7e
new file mode 100644
index 0000000..26aa47a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/93c3f5e7b7544bdb2a6cfdf5dccd669fe1e0ea7e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/93d2164ed967cd4093a49d1a18f60b141a4e0ebb b/net/data/fuzzer_data/ntlm_client_fuzzer/93d2164ed967cd4093a49d1a18f60b141a4e0ebb
new file mode 100644
index 0000000..59f88d1
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/93d2164ed967cd4093a49d1a18f60b141a4e0ebb
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/940dc8e05fb31137d6c624aaa9621508dbfaeb83 b/net/data/fuzzer_data/ntlm_client_fuzzer/940dc8e05fb31137d6c624aaa9621508dbfaeb83
new file mode 100644
index 0000000..4f1ba95
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/940dc8e05fb31137d6c624aaa9621508dbfaeb83
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/9478d73d94e84e64bacf947d0cd1b7640e3ba9d4 b/net/data/fuzzer_data/ntlm_client_fuzzer/9478d73d94e84e64bacf947d0cd1b7640e3ba9d4
new file mode 100644
index 0000000..71eb3ab
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/9478d73d94e84e64bacf947d0cd1b7640e3ba9d4
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/95b8cca06afb05f39d56b2b693dbffd98795a6b7 b/net/data/fuzzer_data/ntlm_client_fuzzer/95b8cca06afb05f39d56b2b693dbffd98795a6b7
new file mode 100644
index 0000000..ae22538
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/95b8cca06afb05f39d56b2b693dbffd98795a6b7
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/95eca3c6e8feb6d734432d193e6179558721e510 b/net/data/fuzzer_data/ntlm_client_fuzzer/95eca3c6e8feb6d734432d193e6179558721e510
new file mode 100644
index 0000000..26d42ad
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/95eca3c6e8feb6d734432d193e6179558721e510
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/95fde91612ef6c02b3bc37aa0d736770fd610c5a b/net/data/fuzzer_data/ntlm_client_fuzzer/95fde91612ef6c02b3bc37aa0d736770fd610c5a
new file mode 100644
index 0000000..5dae40e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/95fde91612ef6c02b3bc37aa0d736770fd610c5a
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/96af9716cc8c9b6fa4fb96766422c1241775be8d b/net/data/fuzzer_data/ntlm_client_fuzzer/96af9716cc8c9b6fa4fb96766422c1241775be8d
new file mode 100644
index 0000000..464dabf
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/96af9716cc8c9b6fa4fb96766422c1241775be8d
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/98b506c9bf7055559c920c0ab1d885d97587a78d b/net/data/fuzzer_data/ntlm_client_fuzzer/98b506c9bf7055559c920c0ab1d885d97587a78d
new file mode 100644
index 0000000..b8601f2
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/98b506c9bf7055559c920c0ab1d885d97587a78d
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/98bdea7f81a7873d7308d0c65baea869d2a93cfd b/net/data/fuzzer_data/ntlm_client_fuzzer/98bdea7f81a7873d7308d0c65baea869d2a93cfd
new file mode 100644
index 0000000..7b4c458
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/98bdea7f81a7873d7308d0c65baea869d2a93cfd
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/99384dc1a282d03b0079894ec5ff4d1b387795ad b/net/data/fuzzer_data/ntlm_client_fuzzer/99384dc1a282d03b0079894ec5ff4d1b387795ad
new file mode 100644
index 0000000..c905f81
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/99384dc1a282d03b0079894ec5ff4d1b387795ad
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/9968364427682a442dfb60bfb2d92c888bf1ba59 b/net/data/fuzzer_data/ntlm_client_fuzzer/9968364427682a442dfb60bfb2d92c888bf1ba59
new file mode 100644
index 0000000..f592529
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/9968364427682a442dfb60bfb2d92c888bf1ba59
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/996bf84c2a0ad9f095b6971c402f3b31c2f10a7f b/net/data/fuzzer_data/ntlm_client_fuzzer/996bf84c2a0ad9f095b6971c402f3b31c2f10a7f
new file mode 100644
index 0000000..b674a28
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/996bf84c2a0ad9f095b6971c402f3b31c2f10a7f
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/9a4907e06db360a02c075928e8fc655e5267be2e b/net/data/fuzzer_data/ntlm_client_fuzzer/9a4907e06db360a02c075928e8fc655e5267be2e
new file mode 100644
index 0000000..9ef7e56
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/9a4907e06db360a02c075928e8fc655e5267be2e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/9a9452704ed6ad79bc88f150371a5e9e1d84ccee b/net/data/fuzzer_data/ntlm_client_fuzzer/9a9452704ed6ad79bc88f150371a5e9e1d84ccee
new file mode 100644
index 0000000..6862396
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/9a9452704ed6ad79bc88f150371a5e9e1d84ccee
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/9c4265f818c48f986f35c93f808abe11f8df9d52 b/net/data/fuzzer_data/ntlm_client_fuzzer/9c4265f818c48f986f35c93f808abe11f8df9d52
new file mode 100644
index 0000000..7ac801e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/9c4265f818c48f986f35c93f808abe11f8df9d52
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/9db439bc5b2421dc3e294ea7db968e1bbacd0b21 b/net/data/fuzzer_data/ntlm_client_fuzzer/9db439bc5b2421dc3e294ea7db968e1bbacd0b21
new file mode 100644
index 0000000..d9b47b6
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/9db439bc5b2421dc3e294ea7db968e1bbacd0b21
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/9e557663f6cc7fdef6e4c65843b67185841537ca b/net/data/fuzzer_data/ntlm_client_fuzzer/9e557663f6cc7fdef6e4c65843b67185841537ca
new file mode 100644
index 0000000..614bca8
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/9e557663f6cc7fdef6e4c65843b67185841537ca
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/a00646609b369580d8bed592d8287e4daf4cdacc b/net/data/fuzzer_data/ntlm_client_fuzzer/a00646609b369580d8bed592d8287e4daf4cdacc
new file mode 100644
index 0000000..0ae648f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/a00646609b369580d8bed592d8287e4daf4cdacc
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/a038077637563b084b4d49370f63cc2bcde9a742 b/net/data/fuzzer_data/ntlm_client_fuzzer/a038077637563b084b4d49370f63cc2bcde9a742
new file mode 100644
index 0000000..565c725
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/a038077637563b084b4d49370f63cc2bcde9a742
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/a0a4758923f0623b8b7f3ac9eb3cb692cbba4e14 b/net/data/fuzzer_data/ntlm_client_fuzzer/a0a4758923f0623b8b7f3ac9eb3cb692cbba4e14
new file mode 100644
index 0000000..aa25299
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/a0a4758923f0623b8b7f3ac9eb3cb692cbba4e14
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/a1bd01abdcc5bcebb14d05b080de464ae20131ed b/net/data/fuzzer_data/ntlm_client_fuzzer/a1bd01abdcc5bcebb14d05b080de464ae20131ed
new file mode 100644
index 0000000..d159746
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/a1bd01abdcc5bcebb14d05b080de464ae20131ed
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/a1d291a2353df598639e4bccb5dcc6094ffaf5fb b/net/data/fuzzer_data/ntlm_client_fuzzer/a1d291a2353df598639e4bccb5dcc6094ffaf5fb
new file mode 100644
index 0000000..e1240be
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/a1d291a2353df598639e4bccb5dcc6094ffaf5fb
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/a20ef461e6060cda1ba9da8a02942198e4269346 b/net/data/fuzzer_data/ntlm_client_fuzzer/a20ef461e6060cda1ba9da8a02942198e4269346
new file mode 100644
index 0000000..f185c703
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/a20ef461e6060cda1ba9da8a02942198e4269346
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/a25f4d27b2ec2e71996006587055310e808d0904 b/net/data/fuzzer_data/ntlm_client_fuzzer/a25f4d27b2ec2e71996006587055310e808d0904
new file mode 100644
index 0000000..f6c162f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/a25f4d27b2ec2e71996006587055310e808d0904
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/a3e0d1813bbe35f8a15f209f78a087da7d613a2c b/net/data/fuzzer_data/ntlm_client_fuzzer/a3e0d1813bbe35f8a15f209f78a087da7d613a2c
new file mode 100644
index 0000000..9dff5ea
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/a3e0d1813bbe35f8a15f209f78a087da7d613a2c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/a45152c21a3673b22e67709b8ba527377cdba983 b/net/data/fuzzer_data/ntlm_client_fuzzer/a45152c21a3673b22e67709b8ba527377cdba983
new file mode 100644
index 0000000..68d8f14e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/a45152c21a3673b22e67709b8ba527377cdba983
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/a474a77ccafcad49fb17b861ccd5e7854a219cbb b/net/data/fuzzer_data/ntlm_client_fuzzer/a474a77ccafcad49fb17b861ccd5e7854a219cbb
new file mode 100644
index 0000000..8e2c4d6
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/a474a77ccafcad49fb17b861ccd5e7854a219cbb
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/a4adc35a8c7b269d0ec6878ecbe254f543fcc988 b/net/data/fuzzer_data/ntlm_client_fuzzer/a4adc35a8c7b269d0ec6878ecbe254f543fcc988
new file mode 100644
index 0000000..b435366
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/a4adc35a8c7b269d0ec6878ecbe254f543fcc988
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/a4b1b73c2178e1b968a328f3b7f77863a077390e b/net/data/fuzzer_data/ntlm_client_fuzzer/a4b1b73c2178e1b968a328f3b7f77863a077390e
new file mode 100644
index 0000000..4fc28b23
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/a4b1b73c2178e1b968a328f3b7f77863a077390e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/a4e57b5160e9f5241118cc8440d13a14b6d106ed b/net/data/fuzzer_data/ntlm_client_fuzzer/a4e57b5160e9f5241118cc8440d13a14b6d106ed
new file mode 100644
index 0000000..b07070c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/a4e57b5160e9f5241118cc8440d13a14b6d106ed
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/a59a8ac04d226f1af27481f2efd9be650681bfd8 b/net/data/fuzzer_data/ntlm_client_fuzzer/a59a8ac04d226f1af27481f2efd9be650681bfd8
new file mode 100644
index 0000000..0317e05
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/a59a8ac04d226f1af27481f2efd9be650681bfd8
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/a6e593f110cffa2fd45ace837255c02fbabbcd31 b/net/data/fuzzer_data/ntlm_client_fuzzer/a6e593f110cffa2fd45ace837255c02fbabbcd31
new file mode 100644
index 0000000..422b291
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/a6e593f110cffa2fd45ace837255c02fbabbcd31
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/a747da62e7703c13302a1bd8b4af8bc42f05fd02 b/net/data/fuzzer_data/ntlm_client_fuzzer/a747da62e7703c13302a1bd8b4af8bc42f05fd02
new file mode 100644
index 0000000..6aa9ac6
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/a747da62e7703c13302a1bd8b4af8bc42f05fd02
@@ -0,0 +1 @@
+f(fffffffff
\ No newline at end of file
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/a7b4d2be7969b3611ce9bc8cc374d265f355b173 b/net/data/fuzzer_data/ntlm_client_fuzzer/a7b4d2be7969b3611ce9bc8cc374d265f355b173
new file mode 100644
index 0000000..d9d42fda
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/a7b4d2be7969b3611ce9bc8cc374d265f355b173
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/a9fb3d1ec2ecb82dd8d238def92f26ceb1108385 b/net/data/fuzzer_data/ntlm_client_fuzzer/a9fb3d1ec2ecb82dd8d238def92f26ceb1108385
new file mode 100644
index 0000000..a8c545a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/a9fb3d1ec2ecb82dd8d238def92f26ceb1108385
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/aa1979cafa26e8d136971c738a6b570eef6c4bf8 b/net/data/fuzzer_data/ntlm_client_fuzzer/aa1979cafa26e8d136971c738a6b570eef6c4bf8
new file mode 100644
index 0000000..c3e9fb2
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/aa1979cafa26e8d136971c738a6b570eef6c4bf8
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/aadd604f9bf2224f85c0254a93f73794a4076022 b/net/data/fuzzer_data/ntlm_client_fuzzer/aadd604f9bf2224f85c0254a93f73794a4076022
new file mode 100644
index 0000000..2c193e24
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/aadd604f9bf2224f85c0254a93f73794a4076022
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/ab18c9b1281c7766245907a7e9084b2dcfe4bed2 b/net/data/fuzzer_data/ntlm_client_fuzzer/ab18c9b1281c7766245907a7e9084b2dcfe4bed2
new file mode 100644
index 0000000..e77a588f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/ab18c9b1281c7766245907a7e9084b2dcfe4bed2
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/ab3cf1a3e792c7ced2de84b404aa82ff80a5eecd b/net/data/fuzzer_data/ntlm_client_fuzzer/ab3cf1a3e792c7ced2de84b404aa82ff80a5eecd
new file mode 100644
index 0000000..60543240
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/ab3cf1a3e792c7ced2de84b404aa82ff80a5eecd
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/ab9dff75a2610bd0a523f236d91cbdaae8b4b2f7 b/net/data/fuzzer_data/ntlm_client_fuzzer/ab9dff75a2610bd0a523f236d91cbdaae8b4b2f7
new file mode 100644
index 0000000..1ffaea9
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/ab9dff75a2610bd0a523f236d91cbdaae8b4b2f7
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/abf3550262b2af04dabc9dd9ca5a2d299120401e b/net/data/fuzzer_data/ntlm_client_fuzzer/abf3550262b2af04dabc9dd9ca5a2d299120401e
new file mode 100644
index 0000000..b1265ba
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/abf3550262b2af04dabc9dd9ca5a2d299120401e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/ac6855fcd9e9e45b03ee511829c88bf54b098408 b/net/data/fuzzer_data/ntlm_client_fuzzer/ac6855fcd9e9e45b03ee511829c88bf54b098408
new file mode 100644
index 0000000..32224ea5
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/ac6855fcd9e9e45b03ee511829c88bf54b098408
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/acbb57a6898a570884573cb65afc4db642166b6a b/net/data/fuzzer_data/ntlm_client_fuzzer/acbb57a6898a570884573cb65afc4db642166b6a
new file mode 100644
index 0000000..8f9c8a0f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/acbb57a6898a570884573cb65afc4db642166b6a
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/acbffd71aacfbf27f234ac3d0be2a6abafd4cf0a b/net/data/fuzzer_data/ntlm_client_fuzzer/acbffd71aacfbf27f234ac3d0be2a6abafd4cf0a
new file mode 100644
index 0000000..4e73f9d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/acbffd71aacfbf27f234ac3d0be2a6abafd4cf0a
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/acd8e8eef53d57626024da0f91393055553c59d0 b/net/data/fuzzer_data/ntlm_client_fuzzer/acd8e8eef53d57626024da0f91393055553c59d0
new file mode 100644
index 0000000..ab22e530
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/acd8e8eef53d57626024da0f91393055553c59d0
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/ade585ac38bdc13f1935f3916c904540e9d69d77 b/net/data/fuzzer_data/ntlm_client_fuzzer/ade585ac38bdc13f1935f3916c904540e9d69d77
new file mode 100644
index 0000000..88b6260b
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/ade585ac38bdc13f1935f3916c904540e9d69d77
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/aed874be11567df57b8f08d547843691ae275570 b/net/data/fuzzer_data/ntlm_client_fuzzer/aed874be11567df57b8f08d547843691ae275570
new file mode 100644
index 0000000..48b88d4
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/aed874be11567df57b8f08d547843691ae275570
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/afa33585391f280ba77076e2e945dc56fc14d4de b/net/data/fuzzer_data/ntlm_client_fuzzer/afa33585391f280ba77076e2e945dc56fc14d4de
new file mode 100644
index 0000000..f0f6664
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/afa33585391f280ba77076e2e945dc56fc14d4de
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b0be1d3b6a9ab20dba18a6e44c15912f93b1d4cf b/net/data/fuzzer_data/ntlm_client_fuzzer/b0be1d3b6a9ab20dba18a6e44c15912f93b1d4cf
new file mode 100644
index 0000000..d2e1968a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b0be1d3b6a9ab20dba18a6e44c15912f93b1d4cf
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b0e52b2214479d4b83a834a960b7ec31a91ecb58 b/net/data/fuzzer_data/ntlm_client_fuzzer/b0e52b2214479d4b83a834a960b7ec31a91ecb58
new file mode 100644
index 0000000..f89888b
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b0e52b2214479d4b83a834a960b7ec31a91ecb58
@@ -0,0 +1 @@
+˜\\ç\ff\f˜˜f
\ No newline at end of file
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b1b40b064226950bf410d9949e3cc242c70f4264 b/net/data/fuzzer_data/ntlm_client_fuzzer/b1b40b064226950bf410d9949e3cc242c70f4264
new file mode 100644
index 0000000..5854d6a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b1b40b064226950bf410d9949e3cc242c70f4264
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b1bc9c263b558b2c5b902a6d4f3f2c9c42584b9c b/net/data/fuzzer_data/ntlm_client_fuzzer/b1bc9c263b558b2c5b902a6d4f3f2c9c42584b9c
new file mode 100644
index 0000000..042af8a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b1bc9c263b558b2c5b902a6d4f3f2c9c42584b9c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b218060e4d84092ab7c1ee291896fe2b590a49db b/net/data/fuzzer_data/ntlm_client_fuzzer/b218060e4d84092ab7c1ee291896fe2b590a49db
new file mode 100644
index 0000000..2fc80ad1
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b218060e4d84092ab7c1ee291896fe2b590a49db
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b32a8e4bafd551f99d971390ffbbd12701ea5b03 b/net/data/fuzzer_data/ntlm_client_fuzzer/b32a8e4bafd551f99d971390ffbbd12701ea5b03
new file mode 100644
index 0000000..c3512b2
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b32a8e4bafd551f99d971390ffbbd12701ea5b03
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b3af3bcae52f68e7b34e3c63cdd0a4a67f5d70e0 b/net/data/fuzzer_data/ntlm_client_fuzzer/b3af3bcae52f68e7b34e3c63cdd0a4a67f5d70e0
new file mode 100644
index 0000000..3ab3b4f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b3af3bcae52f68e7b34e3c63cdd0a4a67f5d70e0
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b3e847d2d6d10231c51e12ac9d248a864b109aef b/net/data/fuzzer_data/ntlm_client_fuzzer/b3e847d2d6d10231c51e12ac9d248a864b109aef
new file mode 100644
index 0000000..551518bb
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b3e847d2d6d10231c51e12ac9d248a864b109aef
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b479a36b363e194125b03c686ea960a6fea20ddc b/net/data/fuzzer_data/ntlm_client_fuzzer/b479a36b363e194125b03c686ea960a6fea20ddc
new file mode 100644
index 0000000..adb483b
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b479a36b363e194125b03c686ea960a6fea20ddc
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b48648afc4f88caa8dd06218b7ea54b02d2da127 b/net/data/fuzzer_data/ntlm_client_fuzzer/b48648afc4f88caa8dd06218b7ea54b02d2da127
new file mode 100644
index 0000000..bab8f61f5
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b48648afc4f88caa8dd06218b7ea54b02d2da127
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b4968b6aa332397a0a91b0ce4d389a5cbfa6cf77 b/net/data/fuzzer_data/ntlm_client_fuzzer/b4968b6aa332397a0a91b0ce4d389a5cbfa6cf77
new file mode 100644
index 0000000..f9d0e6e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b4968b6aa332397a0a91b0ce4d389a5cbfa6cf77
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b4cbaee19f7755d2717f0e02f81463cba29ba632 b/net/data/fuzzer_data/ntlm_client_fuzzer/b4cbaee19f7755d2717f0e02f81463cba29ba632
new file mode 100644
index 0000000..7b105007
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b4cbaee19f7755d2717f0e02f81463cba29ba632
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b4fca94155d2f73e97b1f9ade1b9c4af4ccdb6d7 b/net/data/fuzzer_data/ntlm_client_fuzzer/b4fca94155d2f73e97b1f9ade1b9c4af4ccdb6d7
new file mode 100644
index 0000000..fb13a9e0
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b4fca94155d2f73e97b1f9ade1b9c4af4ccdb6d7
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b52b755d13af7d94679a90bfd4c89653c39e8195 b/net/data/fuzzer_data/ntlm_client_fuzzer/b52b755d13af7d94679a90bfd4c89653c39e8195
new file mode 100644
index 0000000..1a6ef3d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b52b755d13af7d94679a90bfd4c89653c39e8195
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b579be7460185c9b397b9817571f5df54fb558be b/net/data/fuzzer_data/ntlm_client_fuzzer/b579be7460185c9b397b9817571f5df54fb558be
new file mode 100644
index 0000000..51a1204
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b579be7460185c9b397b9817571f5df54fb558be
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b5884e0e9e5a64932588b6ae67c643ec2034f94b b/net/data/fuzzer_data/ntlm_client_fuzzer/b5884e0e9e5a64932588b6ae67c643ec2034f94b
new file mode 100644
index 0000000..59fccd12
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b5884e0e9e5a64932588b6ae67c643ec2034f94b
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b58c1a21b5f3f7c6b267fc83bb2daca61e3edf87 b/net/data/fuzzer_data/ntlm_client_fuzzer/b58c1a21b5f3f7c6b267fc83bb2daca61e3edf87
new file mode 100644
index 0000000..59c1ca6
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b58c1a21b5f3f7c6b267fc83bb2daca61e3edf87
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b6052492e5e67a4488fe54195c6b766eb14b1353 b/net/data/fuzzer_data/ntlm_client_fuzzer/b6052492e5e67a4488fe54195c6b766eb14b1353
new file mode 100644
index 0000000..36f838cb
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b6052492e5e67a4488fe54195c6b766eb14b1353
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b636d0d9264653d4f205db33ea6e41b683c50252 b/net/data/fuzzer_data/ntlm_client_fuzzer/b636d0d9264653d4f205db33ea6e41b683c50252
new file mode 100644
index 0000000..846f3ae8
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b636d0d9264653d4f205db33ea6e41b683c50252
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b69c31f10a80f7798271fd38b53553b134558ff5 b/net/data/fuzzer_data/ntlm_client_fuzzer/b69c31f10a80f7798271fd38b53553b134558ff5
new file mode 100644
index 0000000..a10eae94
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b69c31f10a80f7798271fd38b53553b134558ff5
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b6e88793b6947777ac1f02c6f50953c690daa331 b/net/data/fuzzer_data/ntlm_client_fuzzer/b6e88793b6947777ac1f02c6f50953c690daa331
new file mode 100644
index 0000000..c15370f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b6e88793b6947777ac1f02c6f50953c690daa331
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b7944cd822b8c633b867c1f0119a53dd5460c97b b/net/data/fuzzer_data/ntlm_client_fuzzer/b7944cd822b8c633b867c1f0119a53dd5460c97b
new file mode 100644
index 0000000..9ba867c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b7944cd822b8c633b867c1f0119a53dd5460c97b
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b8272b34b538c4f420a41c2946d63748301eb9c1 b/net/data/fuzzer_data/ntlm_client_fuzzer/b8272b34b538c4f420a41c2946d63748301eb9c1
new file mode 100644
index 0000000..882e5cb9
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b8272b34b538c4f420a41c2946d63748301eb9c1
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b87e1493ed64fd43271e2cb10a797951f8f3f4f2 b/net/data/fuzzer_data/ntlm_client_fuzzer/b87e1493ed64fd43271e2cb10a797951f8f3f4f2
new file mode 100644
index 0000000..1afdb09
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b87e1493ed64fd43271e2cb10a797951f8f3f4f2
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b8e5576942a850e8fca7ec55f377eaf38c4e26ad b/net/data/fuzzer_data/ntlm_client_fuzzer/b8e5576942a850e8fca7ec55f377eaf38c4e26ad
new file mode 100644
index 0000000..c4831839
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b8e5576942a850e8fca7ec55f377eaf38c4e26ad
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b958eb7c812fbec6430bf5b002aa30cea3f9f5f9 b/net/data/fuzzer_data/ntlm_client_fuzzer/b958eb7c812fbec6430bf5b002aa30cea3f9f5f9
new file mode 100644
index 0000000..fd89765
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b958eb7c812fbec6430bf5b002aa30cea3f9f5f9
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b9608578928f851c44144779792fb78aac76ce2c b/net/data/fuzzer_data/ntlm_client_fuzzer/b9608578928f851c44144779792fb78aac76ce2c
new file mode 100644
index 0000000..a06942b6
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b9608578928f851c44144779792fb78aac76ce2c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b9794ffb1b484631287ad98cd85795a56c6a8f17 b/net/data/fuzzer_data/ntlm_client_fuzzer/b9794ffb1b484631287ad98cd85795a56c6a8f17
new file mode 100644
index 0000000..c2e81cb
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b9794ffb1b484631287ad98cd85795a56c6a8f17
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b996072eb9638ef9be224068aae0204d84534748 b/net/data/fuzzer_data/ntlm_client_fuzzer/b996072eb9638ef9be224068aae0204d84534748
new file mode 100644
index 0000000..ad5b51e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b996072eb9638ef9be224068aae0204d84534748
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/b9d88ae50e0f60534e9188b8289c69599128c31f b/net/data/fuzzer_data/ntlm_client_fuzzer/b9d88ae50e0f60534e9188b8289c69599128c31f
new file mode 100644
index 0000000..3c4bc7a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/b9d88ae50e0f60534e9188b8289c69599128c31f
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/ba866c8c3973eb8ce6bfa602a4a24de229111514 b/net/data/fuzzer_data/ntlm_client_fuzzer/ba866c8c3973eb8ce6bfa602a4a24de229111514
new file mode 100644
index 0000000..d01b440
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/ba866c8c3973eb8ce6bfa602a4a24de229111514
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/bae5289ae9edad63804c49a2dbb185e9e444e42a b/net/data/fuzzer_data/ntlm_client_fuzzer/bae5289ae9edad63804c49a2dbb185e9e444e42a
new file mode 100644
index 0000000..313bfc9
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/bae5289ae9edad63804c49a2dbb185e9e444e42a
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/baeed8ea4e9ea09014da462a0320fcb0e6ad1f32 b/net/data/fuzzer_data/ntlm_client_fuzzer/baeed8ea4e9ea09014da462a0320fcb0e6ad1f32
new file mode 100644
index 0000000..7623e1e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/baeed8ea4e9ea09014da462a0320fcb0e6ad1f32
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/bc1038698713c6d9afcf073937d0919cc725fcc3 b/net/data/fuzzer_data/ntlm_client_fuzzer/bc1038698713c6d9afcf073937d0919cc725fcc3
new file mode 100644
index 0000000..47c697c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/bc1038698713c6d9afcf073937d0919cc725fcc3
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/bc433dada1820a81ce16363421b7d7f0ab2ff1fa b/net/data/fuzzer_data/ntlm_client_fuzzer/bc433dada1820a81ce16363421b7d7f0ab2ff1fa
new file mode 100644
index 0000000..27072c3d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/bc433dada1820a81ce16363421b7d7f0ab2ff1fa
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/bc47335fb3c4eafd8c947e4101eec7aeb05190a5 b/net/data/fuzzer_data/ntlm_client_fuzzer/bc47335fb3c4eafd8c947e4101eec7aeb05190a5
new file mode 100644
index 0000000..6064ca7
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/bc47335fb3c4eafd8c947e4101eec7aeb05190a5
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/bd0c539b72a8a486cf4d1991f869234f7dccbbb7 b/net/data/fuzzer_data/ntlm_client_fuzzer/bd0c539b72a8a486cf4d1991f869234f7dccbbb7
new file mode 100644
index 0000000..0da9505
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/bd0c539b72a8a486cf4d1991f869234f7dccbbb7
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/bd46eb3383873ada7d289565d61e4a130fba1665 b/net/data/fuzzer_data/ntlm_client_fuzzer/bd46eb3383873ada7d289565d61e4a130fba1665
new file mode 100644
index 0000000..c52ffef
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/bd46eb3383873ada7d289565d61e4a130fba1665
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/bdfba67907ecd634da28bc0fa79ea57359cee9be b/net/data/fuzzer_data/ntlm_client_fuzzer/bdfba67907ecd634da28bc0fa79ea57359cee9be
new file mode 100644
index 0000000..c7d8c7f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/bdfba67907ecd634da28bc0fa79ea57359cee9be
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/bf598b814c5322f434e7a6a9c1d8cceec519858c b/net/data/fuzzer_data/ntlm_client_fuzzer/bf598b814c5322f434e7a6a9c1d8cceec519858c
new file mode 100644
index 0000000..5c9d640a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/bf598b814c5322f434e7a6a9c1d8cceec519858c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/bf7ef08e28a17de8187a3fb4c672f031dab2e620 b/net/data/fuzzer_data/ntlm_client_fuzzer/bf7ef08e28a17de8187a3fb4c672f031dab2e620
new file mode 100644
index 0000000..089fcdef
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/bf7ef08e28a17de8187a3fb4c672f031dab2e620
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/bf8d8aeed634a689be4d5c5da7ea2b436a1421ac b/net/data/fuzzer_data/ntlm_client_fuzzer/bf8d8aeed634a689be4d5c5da7ea2b436a1421ac
new file mode 100644
index 0000000..4ea0ea4
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/bf8d8aeed634a689be4d5c5da7ea2b436a1421ac
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/bfc81c7f3f9dcdcbfed0afd578f68509ad63726c b/net/data/fuzzer_data/ntlm_client_fuzzer/bfc81c7f3f9dcdcbfed0afd578f68509ad63726c
new file mode 100644
index 0000000..ec62b14
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/bfc81c7f3f9dcdcbfed0afd578f68509ad63726c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c06d439d6a7d12f36f0d6588e2d23a6b9df4b0f2 b/net/data/fuzzer_data/ntlm_client_fuzzer/c06d439d6a7d12f36f0d6588e2d23a6b9df4b0f2
new file mode 100644
index 0000000..d3113bf
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c06d439d6a7d12f36f0d6588e2d23a6b9df4b0f2
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c0a8a01f314d56e0895afd9e1aa23f7e4210888c b/net/data/fuzzer_data/ntlm_client_fuzzer/c0a8a01f314d56e0895afd9e1aa23f7e4210888c
new file mode 100644
index 0000000..c015e6b
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c0a8a01f314d56e0895afd9e1aa23f7e4210888c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c0c4a70a12d7bfa6c42a6b4ea44b8d831a5c81a6 b/net/data/fuzzer_data/ntlm_client_fuzzer/c0c4a70a12d7bfa6c42a6b4ea44b8d831a5c81a6
new file mode 100644
index 0000000..06bc108
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c0c4a70a12d7bfa6c42a6b4ea44b8d831a5c81a6
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c0c6721dfeef7cc9277519a5bbdae00fae419a7a b/net/data/fuzzer_data/ntlm_client_fuzzer/c0c6721dfeef7cc9277519a5bbdae00fae419a7a
new file mode 100644
index 0000000..c8d0125
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c0c6721dfeef7cc9277519a5bbdae00fae419a7a
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c144a03de904daab17d62ad186799df1f99e49c1 b/net/data/fuzzer_data/ntlm_client_fuzzer/c144a03de904daab17d62ad186799df1f99e49c1
new file mode 100644
index 0000000..f9add9a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c144a03de904daab17d62ad186799df1f99e49c1
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c18163ede8affbae299762282990714d3302eda4 b/net/data/fuzzer_data/ntlm_client_fuzzer/c18163ede8affbae299762282990714d3302eda4
new file mode 100644
index 0000000..d85223f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c18163ede8affbae299762282990714d3302eda4
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c228a6813f37f514abf10f364b15904f284cd9e6 b/net/data/fuzzer_data/ntlm_client_fuzzer/c228a6813f37f514abf10f364b15904f284cd9e6
new file mode 100644
index 0000000..05011ee
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c228a6813f37f514abf10f364b15904f284cd9e6
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c30141b2147d59b3bd3055e7a8e39794537c36c3 b/net/data/fuzzer_data/ntlm_client_fuzzer/c30141b2147d59b3bd3055e7a8e39794537c36c3
new file mode 100644
index 0000000..b16f9562
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c30141b2147d59b3bd3055e7a8e39794537c36c3
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c3230eb00843e1ddf44af1e9ed9df3d9b98643c0 b/net/data/fuzzer_data/ntlm_client_fuzzer/c3230eb00843e1ddf44af1e9ed9df3d9b98643c0
new file mode 100644
index 0000000..dc85562
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c3230eb00843e1ddf44af1e9ed9df3d9b98643c0
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c3312bb04a0e5ce9e3ca06f93a3386c30ec90bf6 b/net/data/fuzzer_data/ntlm_client_fuzzer/c3312bb04a0e5ce9e3ca06f93a3386c30ec90bf6
new file mode 100644
index 0000000..00d9eb2
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c3312bb04a0e5ce9e3ca06f93a3386c30ec90bf6
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c362a11a9a647f33e138ef6b5b572e087c55e068 b/net/data/fuzzer_data/ntlm_client_fuzzer/c362a11a9a647f33e138ef6b5b572e087c55e068
new file mode 100644
index 0000000..3138730
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c362a11a9a647f33e138ef6b5b572e087c55e068
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c36ce41b1f9b3d70be72beaae7fde774193d9a98 b/net/data/fuzzer_data/ntlm_client_fuzzer/c36ce41b1f9b3d70be72beaae7fde774193d9a98
new file mode 100644
index 0000000..0fea5b9
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c36ce41b1f9b3d70be72beaae7fde774193d9a98
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c3a44c0dcb1c84c35193c760e1b7f27328ebb614 b/net/data/fuzzer_data/ntlm_client_fuzzer/c3a44c0dcb1c84c35193c760e1b7f27328ebb614
new file mode 100644
index 0000000..ff082f7
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c3a44c0dcb1c84c35193c760e1b7f27328ebb614
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c3cd3ad0f034a90b1089724505e3ab27902579f1 b/net/data/fuzzer_data/ntlm_client_fuzzer/c3cd3ad0f034a90b1089724505e3ab27902579f1
new file mode 100644
index 0000000..4267390
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c3cd3ad0f034a90b1089724505e3ab27902579f1
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c429ce244f208bb7c7c48040bcaa01cb1a8c6fd5 b/net/data/fuzzer_data/ntlm_client_fuzzer/c429ce244f208bb7c7c48040bcaa01cb1a8c6fd5
new file mode 100644
index 0000000..489554a8
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c429ce244f208bb7c7c48040bcaa01cb1a8c6fd5
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c478eb8b465a1bc2a59e56b0f964057d5baa670a b/net/data/fuzzer_data/ntlm_client_fuzzer/c478eb8b465a1bc2a59e56b0f964057d5baa670a
new file mode 100644
index 0000000..f6ed3083
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c478eb8b465a1bc2a59e56b0f964057d5baa670a
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c4a72fc42f4643ccd3abed56d40d5f9241736d22 b/net/data/fuzzer_data/ntlm_client_fuzzer/c4a72fc42f4643ccd3abed56d40d5f9241736d22
new file mode 100644
index 0000000..f637bc1e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c4a72fc42f4643ccd3abed56d40d5f9241736d22
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c4bc0fcc39649e4261bd88da3c8788f33c821532 b/net/data/fuzzer_data/ntlm_client_fuzzer/c4bc0fcc39649e4261bd88da3c8788f33c821532
new file mode 100644
index 0000000..3c88b0b
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c4bc0fcc39649e4261bd88da3c8788f33c821532
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c580b15158fa7e52e0e51590b7f6badb30ec778d b/net/data/fuzzer_data/ntlm_client_fuzzer/c580b15158fa7e52e0e51590b7f6badb30ec778d
new file mode 100644
index 0000000..8b52735
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c580b15158fa7e52e0e51590b7f6badb30ec778d
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c5c6aae397e944d36991fb5a94b174ee6ff10638 b/net/data/fuzzer_data/ntlm_client_fuzzer/c5c6aae397e944d36991fb5a94b174ee6ff10638
new file mode 100644
index 0000000..e8c8de2
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c5c6aae397e944d36991fb5a94b174ee6ff10638
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c62e728c83da61f731986d847de61b5c01d772d5 b/net/data/fuzzer_data/ntlm_client_fuzzer/c62e728c83da61f731986d847de61b5c01d772d5
new file mode 100644
index 0000000..4b4365d9
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c62e728c83da61f731986d847de61b5c01d772d5
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c6869b7d35bb3445fd8c75596fb0627586c2e3b2 b/net/data/fuzzer_data/ntlm_client_fuzzer/c6869b7d35bb3445fd8c75596fb0627586c2e3b2
new file mode 100644
index 0000000..546e086
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c6869b7d35bb3445fd8c75596fb0627586c2e3b2
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c7255dc48b42d44f6c0676d6009051b7e1aa885b b/net/data/fuzzer_data/ntlm_client_fuzzer/c7255dc48b42d44f6c0676d6009051b7e1aa885b
new file mode 100644
index 0000000..c30d058
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c7255dc48b42d44f6c0676d6009051b7e1aa885b
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c74b94db831af9f9f4ca62d282d90bdf63f5b722 b/net/data/fuzzer_data/ntlm_client_fuzzer/c74b94db831af9f9f4ca62d282d90bdf63f5b722
new file mode 100644
index 0000000..8fd61f4
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c74b94db831af9f9f4ca62d282d90bdf63f5b722
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c77ad37ffcd949aa2f04389a4f4330de5da9675b b/net/data/fuzzer_data/ntlm_client_fuzzer/c77ad37ffcd949aa2f04389a4f4330de5da9675b
new file mode 100644
index 0000000..a6c530c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c77ad37ffcd949aa2f04389a4f4330de5da9675b
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c79a4c2f5473894019e208662ead71aba1f1947c b/net/data/fuzzer_data/ntlm_client_fuzzer/c79a4c2f5473894019e208662ead71aba1f1947c
new file mode 100644
index 0000000..05e7a87
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c79a4c2f5473894019e208662ead71aba1f1947c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c8d3cc6de17682363e8b28e539851660f0299373 b/net/data/fuzzer_data/ntlm_client_fuzzer/c8d3cc6de17682363e8b28e539851660f0299373
new file mode 100644
index 0000000..894e6a02
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c8d3cc6de17682363e8b28e539851660f0299373
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c8d56e86c7bae8f098abb82a3b768d55f78def10 b/net/data/fuzzer_data/ntlm_client_fuzzer/c8d56e86c7bae8f098abb82a3b768d55f78def10
new file mode 100644
index 0000000..9d3b012
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c8d56e86c7bae8f098abb82a3b768d55f78def10
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c9813620cf70c448ac366f4829eb627c18d2ded1 b/net/data/fuzzer_data/ntlm_client_fuzzer/c9813620cf70c448ac366f4829eb627c18d2ded1
new file mode 100644
index 0000000..68d04be1
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c9813620cf70c448ac366f4829eb627c18d2ded1
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/c9aa36c9ec6ad0b14bd931a826833ea8c71065f6 b/net/data/fuzzer_data/ntlm_client_fuzzer/c9aa36c9ec6ad0b14bd931a826833ea8c71065f6
new file mode 100644
index 0000000..4776f19
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/c9aa36c9ec6ad0b14bd931a826833ea8c71065f6
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/ca1361700d6d92b47b53eb5b18b6e770714853a4 b/net/data/fuzzer_data/ntlm_client_fuzzer/ca1361700d6d92b47b53eb5b18b6e770714853a4
new file mode 100644
index 0000000..da306a0
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/ca1361700d6d92b47b53eb5b18b6e770714853a4
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/cc01028b6eaf4122034b07d75c7ec07b88f13d75 b/net/data/fuzzer_data/ntlm_client_fuzzer/cc01028b6eaf4122034b07d75c7ec07b88f13d75
new file mode 100644
index 0000000..a98d0fe0
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/cc01028b6eaf4122034b07d75c7ec07b88f13d75
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/ccdce11fdc8887cb54bb9c2eb05dc6b510e1033e b/net/data/fuzzer_data/ntlm_client_fuzzer/ccdce11fdc8887cb54bb9c2eb05dc6b510e1033e
new file mode 100644
index 0000000..7e06b4d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/ccdce11fdc8887cb54bb9c2eb05dc6b510e1033e
@@ -0,0 +1 @@
+\\\\\\\\\\\\\\
\ No newline at end of file
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/cd1671557c6aefc571cfab7070592964e171b421 b/net/data/fuzzer_data/ntlm_client_fuzzer/cd1671557c6aefc571cfab7070592964e171b421
new file mode 100644
index 0000000..e106b19
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/cd1671557c6aefc571cfab7070592964e171b421
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/cd3c634d56405fea2de86cdb418cfda47a5af3bb b/net/data/fuzzer_data/ntlm_client_fuzzer/cd3c634d56405fea2de86cdb418cfda47a5af3bb
new file mode 100644
index 0000000..989c322
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/cd3c634d56405fea2de86cdb418cfda47a5af3bb
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/ce0bfec5f2763189af06eff15d831776999b5acd b/net/data/fuzzer_data/ntlm_client_fuzzer/ce0bfec5f2763189af06eff15d831776999b5acd
new file mode 100644
index 0000000..2d842d4
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/ce0bfec5f2763189af06eff15d831776999b5acd
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/ce48f1a8bb6d029bcc2d3e92f6c825ecdc656e65 b/net/data/fuzzer_data/ntlm_client_fuzzer/ce48f1a8bb6d029bcc2d3e92f6c825ecdc656e65
new file mode 100644
index 0000000..0045c37
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/ce48f1a8bb6d029bcc2d3e92f6c825ecdc656e65
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/cecb484b6da69981df77511da19b10902be77d94 b/net/data/fuzzer_data/ntlm_client_fuzzer/cecb484b6da69981df77511da19b10902be77d94
new file mode 100644
index 0000000..be04782f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/cecb484b6da69981df77511da19b10902be77d94
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/ced1e15446c6dcae431cd920a1d010deddce27be b/net/data/fuzzer_data/ntlm_client_fuzzer/ced1e15446c6dcae431cd920a1d010deddce27be
new file mode 100644
index 0000000..4fbf6ac
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/ced1e15446c6dcae431cd920a1d010deddce27be
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/cf2043e18520f6fb82b8a33132f799b3c235c8b0 b/net/data/fuzzer_data/ntlm_client_fuzzer/cf2043e18520f6fb82b8a33132f799b3c235c8b0
new file mode 100644
index 0000000..c898db0
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/cf2043e18520f6fb82b8a33132f799b3c235c8b0
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/cf2fa6a612eeab5013f3c95dad01f845bb3f169c b/net/data/fuzzer_data/ntlm_client_fuzzer/cf2fa6a612eeab5013f3c95dad01f845bb3f169c
new file mode 100644
index 0000000..c59bcf36
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/cf2fa6a612eeab5013f3c95dad01f845bb3f169c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/challenge_spec_4_2_2_3.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/challenge_spec_4_2_2_3.bin
deleted file mode 100644
index e698a39..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/challenge_spec_4_2_2_3.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/d00471bccf37bb960516205906191aa7df89fd76 b/net/data/fuzzer_data/ntlm_client_fuzzer/d00471bccf37bb960516205906191aa7df89fd76
new file mode 100644
index 0000000..2ddfef09
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/d00471bccf37bb960516205906191aa7df89fd76
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/d030276ab97f9e9f1ab89d983f5470c6281c77fe b/net/data/fuzzer_data/ntlm_client_fuzzer/d030276ab97f9e9f1ab89d983f5470c6281c77fe
new file mode 100644
index 0000000..c450d18
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/d030276ab97f9e9f1ab89d983f5470c6281c77fe
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/d0731f0136dbbee6db7c1b8d77b4220cec5aeb5d b/net/data/fuzzer_data/ntlm_client_fuzzer/d0731f0136dbbee6db7c1b8d77b4220cec5aeb5d
new file mode 100644
index 0000000..b72c98a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/d0731f0136dbbee6db7c1b8d77b4220cec5aeb5d
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/d0fea544723bc3c1db9c28a17c9f34f793ac1bc8 b/net/data/fuzzer_data/ntlm_client_fuzzer/d0fea544723bc3c1db9c28a17c9f34f793ac1bc8
new file mode 100644
index 0000000..f9188b5
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/d0fea544723bc3c1db9c28a17c9f34f793ac1bc8
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/d1b9790b8fee0270e51037e950c12ff282e0a07a b/net/data/fuzzer_data/ntlm_client_fuzzer/d1b9790b8fee0270e51037e950c12ff282e0a07a
new file mode 100644
index 0000000..20ccccd
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/d1b9790b8fee0270e51037e950c12ff282e0a07a
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/d253d241c6de4eadc1600ee6b60f24789f64fc6a b/net/data/fuzzer_data/ntlm_client_fuzzer/d253d241c6de4eadc1600ee6b60f24789f64fc6a
new file mode 100644
index 0000000..b5b5f78e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/d253d241c6de4eadc1600ee6b60f24789f64fc6a
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/d32c77d065acfb3822a32ee521f54990e9c1fcc7 b/net/data/fuzzer_data/ntlm_client_fuzzer/d32c77d065acfb3822a32ee521f54990e9c1fcc7
new file mode 100644
index 0000000..d108e20
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/d32c77d065acfb3822a32ee521f54990e9c1fcc7
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/d33fef58bedd39dc1c2d38f16305b10010e9058e b/net/data/fuzzer_data/ntlm_client_fuzzer/d33fef58bedd39dc1c2d38f16305b10010e9058e
new file mode 100644
index 0000000..9720664
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/d33fef58bedd39dc1c2d38f16305b10010e9058e
@@ -0,0 +1 @@
+ffff
\ No newline at end of file
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/d505f3f667f992dda34a2a25bc06b97f5c6e0f84 b/net/data/fuzzer_data/ntlm_client_fuzzer/d505f3f667f992dda34a2a25bc06b97f5c6e0f84
new file mode 100644
index 0000000..ca1cbf53
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/d505f3f667f992dda34a2a25bc06b97f5c6e0f84
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/d53aaaa1c234b5482e1ce79135a7a2eb4e2f1e38 b/net/data/fuzzer_data/ntlm_client_fuzzer/d53aaaa1c234b5482e1ce79135a7a2eb4e2f1e38
new file mode 100644
index 0000000..70ed12b6
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/d53aaaa1c234b5482e1ce79135a7a2eb4e2f1e38
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/d6139157ab7c8e38e2b628ac7d4de5325695ccef b/net/data/fuzzer_data/ntlm_client_fuzzer/d6139157ab7c8e38e2b628ac7d4de5325695ccef
new file mode 100644
index 0000000..be9538dd
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/d6139157ab7c8e38e2b628ac7d4de5325695ccef
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/d68279bd73b4e31748b2cebccf8231932953dac7 b/net/data/fuzzer_data/ntlm_client_fuzzer/d68279bd73b4e31748b2cebccf8231932953dac7
new file mode 100644
index 0000000..5cfc5a0
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/d68279bd73b4e31748b2cebccf8231932953dac7
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/d80e9907486b1e7de982ebbb485905329310360a b/net/data/fuzzer_data/ntlm_client_fuzzer/d80e9907486b1e7de982ebbb485905329310360a
new file mode 100644
index 0000000..e5f84cab
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/d80e9907486b1e7de982ebbb485905329310360a
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0260.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/d810295805347b8f9d0773fa0743cc09a171373e
similarity index 100%
rename from net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0260.bin
rename to net/data/fuzzer_data/ntlm_client_fuzzer/d810295805347b8f9d0773fa0743cc09a171373e
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/d84d1ac5d3969f39b2f3ad1a63f181d4d99442ce b/net/data/fuzzer_data/ntlm_client_fuzzer/d84d1ac5d3969f39b2f3ad1a63f181d4d99442ce
new file mode 100644
index 0000000..0eddbf3
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/d84d1ac5d3969f39b2f3ad1a63f181d4d99442ce
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/d8dccd94951179c9bdad73e5f7ae1f614240d540 b/net/data/fuzzer_data/ntlm_client_fuzzer/d8dccd94951179c9bdad73e5f7ae1f614240d540
new file mode 100644
index 0000000..3cb757a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/d8dccd94951179c9bdad73e5f7ae1f614240d540
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/da59f4b7b4c665cd6750feb35acd0159f41e112b b/net/data/fuzzer_data/ntlm_client_fuzzer/da59f4b7b4c665cd6750feb35acd0159f41e112b
new file mode 100644
index 0000000..0fe88f15
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/da59f4b7b4c665cd6750feb35acd0159f41e112b
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/da6ba36dc06c94a1261c0787e5293ff856776d40 b/net/data/fuzzer_data/ntlm_client_fuzzer/da6ba36dc06c94a1261c0787e5293ff856776d40
new file mode 100644
index 0000000..95ee75c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/da6ba36dc06c94a1261c0787e5293ff856776d40
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/db28df81c00e4b20b750e3928fd4f3a6cbd33cc7 b/net/data/fuzzer_data/ntlm_client_fuzzer/db28df81c00e4b20b750e3928fd4f3a6cbd33cc7
new file mode 100644
index 0000000..deab5a8
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/db28df81c00e4b20b750e3928fd4f3a6cbd33cc7
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/dbf9f26fa35a5fbab2cbd2eea406479179619fee b/net/data/fuzzer_data/ntlm_client_fuzzer/dbf9f26fa35a5fbab2cbd2eea406479179619fee
new file mode 100644
index 0000000..ed9977ac7
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/dbf9f26fa35a5fbab2cbd2eea406479179619fee
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/dc476fe3c493ebc469c314fc673293ae8c8ccbb3 b/net/data/fuzzer_data/ntlm_client_fuzzer/dc476fe3c493ebc469c314fc673293ae8c8ccbb3
new file mode 100644
index 0000000..da36796
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/dc476fe3c493ebc469c314fc673293ae8c8ccbb3
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/dcb34b38987afeb612c8d4a93cfbc92f9948bd6c b/net/data/fuzzer_data/ntlm_client_fuzzer/dcb34b38987afeb612c8d4a93cfbc92f9948bd6c
new file mode 100644
index 0000000..e812ed6
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/dcb34b38987afeb612c8d4a93cfbc92f9948bd6c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/dd1ebfdc7f651f60c42a53967a1892880d63f1e1 b/net/data/fuzzer_data/ntlm_client_fuzzer/dd1ebfdc7f651f60c42a53967a1892880d63f1e1
new file mode 100644
index 0000000..54e062f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/dd1ebfdc7f651f60c42a53967a1892880d63f1e1
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/de1bff4c76f9e168869a5c48d7f3c9d221531da9 b/net/data/fuzzer_data/ntlm_client_fuzzer/de1bff4c76f9e168869a5c48d7f3c9d221531da9
new file mode 100644
index 0000000..8b1c383
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/de1bff4c76f9e168869a5c48d7f3c9d221531da9
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/de30dbb1db7c95555d50c87ba81ce8f584b5ab6e b/net/data/fuzzer_data/ntlm_client_fuzzer/de30dbb1db7c95555d50c87ba81ce8f584b5ab6e
new file mode 100644
index 0000000..d9200ae3
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/de30dbb1db7c95555d50c87ba81ce8f584b5ab6e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/de3e0e359bac865db3f56163b12e718f8b5dd944 b/net/data/fuzzer_data/ntlm_client_fuzzer/de3e0e359bac865db3f56163b12e718f8b5dd944
new file mode 100644
index 0000000..91057ce
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/de3e0e359bac865db3f56163b12e718f8b5dd944
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/dee4bfb3fc063f37b9b3affe4ef838624c6f7796 b/net/data/fuzzer_data/ntlm_client_fuzzer/dee4bfb3fc063f37b9b3affe4ef838624c6f7796
new file mode 100644
index 0000000..7477d57b
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/dee4bfb3fc063f37b9b3affe4ef838624c6f7796
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/e00141e223b534cc67027ce4a0ceb20a496aa77c b/net/data/fuzzer_data/ntlm_client_fuzzer/e00141e223b534cc67027ce4a0ceb20a496aa77c
new file mode 100644
index 0000000..6d89b4c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/e00141e223b534cc67027ce4a0ceb20a496aa77c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/e01b79bdc4ade1bb9eeed769c05d5643bca698d8 b/net/data/fuzzer_data/ntlm_client_fuzzer/e01b79bdc4ade1bb9eeed769c05d5643bca698d8
new file mode 100644
index 0000000..9182b73
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/e01b79bdc4ade1bb9eeed769c05d5643bca698d8
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/e07c3373f281fb2ebb131a4dd19f3751f4a05d9a b/net/data/fuzzer_data/ntlm_client_fuzzer/e07c3373f281fb2ebb131a4dd19f3751f4a05d9a
new file mode 100644
index 0000000..d2bcd4d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/e07c3373f281fb2ebb131a4dd19f3751f4a05d9a
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/e0ce653a76388bfdf36d073eaf47cb86f2027fb0 b/net/data/fuzzer_data/ntlm_client_fuzzer/e0ce653a76388bfdf36d073eaf47cb86f2027fb0
new file mode 100644
index 0000000..ad30285
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/e0ce653a76388bfdf36d073eaf47cb86f2027fb0
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/e160d7c2b10edef5b884b85b726aef09a430c226 b/net/data/fuzzer_data/ntlm_client_fuzzer/e160d7c2b10edef5b884b85b726aef09a430c226
new file mode 100644
index 0000000..9777fbe
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/e160d7c2b10edef5b884b85b726aef09a430c226
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/e1ae3f64e6b93823694059b8d5051d3ad1c05d35 b/net/data/fuzzer_data/ntlm_client_fuzzer/e1ae3f64e6b93823694059b8d5051d3ad1c05d35
new file mode 100644
index 0000000..58350fb
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/e1ae3f64e6b93823694059b8d5051d3ad1c05d35
@@ -0,0 +1 @@
+fffffffffffff
\ No newline at end of file
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/e1dfedec1bd1a833b2fcd38f82ab91ee563e9295 b/net/data/fuzzer_data/ntlm_client_fuzzer/e1dfedec1bd1a833b2fcd38f82ab91ee563e9295
new file mode 100644
index 0000000..30705f3
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/e1dfedec1bd1a833b2fcd38f82ab91ee563e9295
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/e2115b0977793afa807d02de64532f1cbc5831cd b/net/data/fuzzer_data/ntlm_client_fuzzer/e2115b0977793afa807d02de64532f1cbc5831cd
new file mode 100644
index 0000000..d1353048
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/e2115b0977793afa807d02de64532f1cbc5831cd
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/e23415059327344b4c6bf80237ea1d6ec6cbfa1c b/net/data/fuzzer_data/ntlm_client_fuzzer/e23415059327344b4c6bf80237ea1d6ec6cbfa1c
new file mode 100644
index 0000000..9c76b7cd
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/e23415059327344b4c6bf80237ea1d6ec6cbfa1c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/e2dbeb179a003f3d025ca25ce2b0f3c7933ad50b b/net/data/fuzzer_data/ntlm_client_fuzzer/e2dbeb179a003f3d025ca25ce2b0f3c7933ad50b
new file mode 100644
index 0000000..122415b5
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/e2dbeb179a003f3d025ca25ce2b0f3c7933ad50b
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/e2fc6cda8b100d30b9fb0669d7271d1b063bfc7c b/net/data/fuzzer_data/ntlm_client_fuzzer/e2fc6cda8b100d30b9fb0669d7271d1b063bfc7c
new file mode 100644
index 0000000..58630c4d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/e2fc6cda8b100d30b9fb0669d7271d1b063bfc7c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/e45e6be25996a470348adb10999037162c82238b b/net/data/fuzzer_data/ntlm_client_fuzzer/e45e6be25996a470348adb10999037162c82238b
new file mode 100644
index 0000000..f516e4b1
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/e45e6be25996a470348adb10999037162c82238b
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/e507ac2ee689674641e13a1042434e86c57668de b/net/data/fuzzer_data/ntlm_client_fuzzer/e507ac2ee689674641e13a1042434e86c57668de
new file mode 100644
index 0000000..36651cbc
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/e507ac2ee689674641e13a1042434e86c57668de
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/e50ecaa6233f3674c730affcc1e63c3fd04f09ad b/net/data/fuzzer_data/ntlm_client_fuzzer/e50ecaa6233f3674c730affcc1e63c3fd04f09ad
new file mode 100644
index 0000000..d4f5594
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/e50ecaa6233f3674c730affcc1e63c3fd04f09ad
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/e5754ca4fd8739c9c690a2e9a7dc255f3a7f3f2d b/net/data/fuzzer_data/ntlm_client_fuzzer/e5754ca4fd8739c9c690a2e9a7dc255f3a7f3f2d
new file mode 100644
index 0000000..efacb19
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/e5754ca4fd8739c9c690a2e9a7dc255f3a7f3f2d
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/e78797f2e893eea7f0341ad15881f8fa7eb8cda3 b/net/data/fuzzer_data/ntlm_client_fuzzer/e78797f2e893eea7f0341ad15881f8fa7eb8cda3
new file mode 100644
index 0000000..192e6b90
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/e78797f2e893eea7f0341ad15881f8fa7eb8cda3
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/e87c3477a494b7e3e91e45cac57896ac4fea7f41 b/net/data/fuzzer_data/ntlm_client_fuzzer/e87c3477a494b7e3e91e45cac57896ac4fea7f41
new file mode 100644
index 0000000..b6d5907
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/e87c3477a494b7e3e91e45cac57896ac4fea7f41
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/ea671f71a82891197a7d5a3a559337e5fd331e2a b/net/data/fuzzer_data/ntlm_client_fuzzer/ea671f71a82891197a7d5a3a559337e5fd331e2a
new file mode 100644
index 0000000..b9676a0
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/ea671f71a82891197a7d5a3a559337e5fd331e2a
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/eb91fbc1e24fc9af9b39cc08b3048ffbff9c3797 b/net/data/fuzzer_data/ntlm_client_fuzzer/eb91fbc1e24fc9af9b39cc08b3048ffbff9c3797
new file mode 100644
index 0000000..8cf0bdf
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/eb91fbc1e24fc9af9b39cc08b3048ffbff9c3797
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/eba921f1ef502f64b718dff4908a0e6b67710b47 b/net/data/fuzzer_data/ntlm_client_fuzzer/eba921f1ef502f64b718dff4908a0e6b67710b47
new file mode 100644
index 0000000..02ff93a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/eba921f1ef502f64b718dff4908a0e6b67710b47
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/ec41f90bb3ceae0885ad377a88ca5802e24168cb b/net/data/fuzzer_data/ntlm_client_fuzzer/ec41f90bb3ceae0885ad377a88ca5802e24168cb
new file mode 100644
index 0000000..396fc7d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/ec41f90bb3ceae0885ad377a88ca5802e24168cb
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/ec426aeebb745cbf37b47c65e637cc38bd669ef0 b/net/data/fuzzer_data/ntlm_client_fuzzer/ec426aeebb745cbf37b47c65e637cc38bd669ef0
new file mode 100644
index 0000000..cc0a537
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/ec426aeebb745cbf37b47c65e637cc38bd669ef0
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/ec9cd3f298f4538bca2649332c50646c77a812e7 b/net/data/fuzzer_data/ntlm_client_fuzzer/ec9cd3f298f4538bca2649332c50646c77a812e7
new file mode 100644
index 0000000..0bb045d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/ec9cd3f298f4538bca2649332c50646c77a812e7
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/ece53afe40cee178a98d5b103c63d7b1c33ac428 b/net/data/fuzzer_data/ntlm_client_fuzzer/ece53afe40cee178a98d5b103c63d7b1c33ac428
new file mode 100644
index 0000000..ec021e0
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/ece53afe40cee178a98d5b103c63d7b1c33ac428
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/ee8e61eeb7b38bcc9b232493dbbd1cc2b5a288ec b/net/data/fuzzer_data/ntlm_client_fuzzer/ee8e61eeb7b38bcc9b232493dbbd1cc2b5a288ec
new file mode 100644
index 0000000..3a6678c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/ee8e61eeb7b38bcc9b232493dbbd1cc2b5a288ec
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/ee8e8ab365a46fe69407ff76e2a0012017ee8cf7 b/net/data/fuzzer_data/ntlm_client_fuzzer/ee8e8ab365a46fe69407ff76e2a0012017ee8cf7
new file mode 100644
index 0000000..335f194
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/ee8e8ab365a46fe69407ff76e2a0012017ee8cf7
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/efe8bd14126d4dd4880d8c769919f3abce42fb62 b/net/data/fuzzer_data/ntlm_client_fuzzer/efe8bd14126d4dd4880d8c769919f3abce42fb62
new file mode 100644
index 0000000..1a4ecd3
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/efe8bd14126d4dd4880d8c769919f3abce42fb62
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f0363b4c5978a009ade5083ee03e71c7baeabf6c b/net/data/fuzzer_data/ntlm_client_fuzzer/f0363b4c5978a009ade5083ee03e71c7baeabf6c
new file mode 100644
index 0000000..711ebb8
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f0363b4c5978a009ade5083ee03e71c7baeabf6c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f03cdc8d4bab7812d6362f6cf2c9fef9ea44e5ea b/net/data/fuzzer_data/ntlm_client_fuzzer/f03cdc8d4bab7812d6362f6cf2c9fef9ea44e5ea
new file mode 100644
index 0000000..5f46223
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f03cdc8d4bab7812d6362f6cf2c9fef9ea44e5ea
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f0d36c54a9b55719aae3819f05b8957a8c50ebd7 b/net/data/fuzzer_data/ntlm_client_fuzzer/f0d36c54a9b55719aae3819f05b8957a8c50ebd7
new file mode 100644
index 0000000..5c59366
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f0d36c54a9b55719aae3819f05b8957a8c50ebd7
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f1361e4f6aa5c2d789781edf07d679eba0872929 b/net/data/fuzzer_data/ntlm_client_fuzzer/f1361e4f6aa5c2d789781edf07d679eba0872929
new file mode 100644
index 0000000..c3fd589
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f1361e4f6aa5c2d789781edf07d679eba0872929
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f14d5e05e9a83c29b19b689713147dbd74b62640 b/net/data/fuzzer_data/ntlm_client_fuzzer/f14d5e05e9a83c29b19b689713147dbd74b62640
new file mode 100644
index 0000000..290557e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f14d5e05e9a83c29b19b689713147dbd74b62640
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f24c2a843490284c906a89d14819dda818f53693 b/net/data/fuzzer_data/ntlm_client_fuzzer/f24c2a843490284c906a89d14819dda818f53693
new file mode 100644
index 0000000..11de7fc
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f24c2a843490284c906a89d14819dda818f53693
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f26a4bd8d1781ec968d1801da82e7b52df6f68d5 b/net/data/fuzzer_data/ntlm_client_fuzzer/f26a4bd8d1781ec968d1801da82e7b52df6f68d5
new file mode 100644
index 0000000..27c9066
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f26a4bd8d1781ec968d1801da82e7b52df6f68d5
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f2eff3b020be8e594729f9901e4360a253c6cec3 b/net/data/fuzzer_data/ntlm_client_fuzzer/f2eff3b020be8e594729f9901e4360a253c6cec3
new file mode 100644
index 0000000..f8292ee
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f2eff3b020be8e594729f9901e4360a253c6cec3
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f2f0ea78c4b745968719efd41992944c4d8ebab7 b/net/data/fuzzer_data/ntlm_client_fuzzer/f2f0ea78c4b745968719efd41992944c4d8ebab7
new file mode 100644
index 0000000..f33c43a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f2f0ea78c4b745968719efd41992944c4d8ebab7
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f30b042b2c51718ba33c7af725b8767a01e44c54 b/net/data/fuzzer_data/ntlm_client_fuzzer/f30b042b2c51718ba33c7af725b8767a01e44c54
new file mode 100644
index 0000000..ddda337
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f30b042b2c51718ba33c7af725b8767a01e44c54
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f35418c9ff8cd0958bf8426c3d8d8b4887af4e3e b/net/data/fuzzer_data/ntlm_client_fuzzer/f35418c9ff8cd0958bf8426c3d8d8b4887af4e3e
new file mode 100644
index 0000000..465c9c8
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f35418c9ff8cd0958bf8426c3d8d8b4887af4e3e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f3b39374ce0a47e4f6f1e45ad84592d028aa7c5a b/net/data/fuzzer_data/ntlm_client_fuzzer/f3b39374ce0a47e4f6f1e45ad84592d028aa7c5a
new file mode 100644
index 0000000..4a4de6a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f3b39374ce0a47e4f6f1e45ad84592d028aa7c5a
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f3bb99ffed1c643b421b896000803fd1dae270df b/net/data/fuzzer_data/ntlm_client_fuzzer/f3bb99ffed1c643b421b896000803fd1dae270df
new file mode 100644
index 0000000..547b418
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f3bb99ffed1c643b421b896000803fd1dae270df
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f3e0c2fb19014fa7c8fb27a6c89e0beed0a92621 b/net/data/fuzzer_data/ntlm_client_fuzzer/f3e0c2fb19014fa7c8fb27a6c89e0beed0a92621
new file mode 100644
index 0000000..7fdeec62
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f3e0c2fb19014fa7c8fb27a6c89e0beed0a92621
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f3e5023e892b21a098011e426cd77c30bc22610f b/net/data/fuzzer_data/ntlm_client_fuzzer/f3e5023e892b21a098011e426cd77c30bc22610f
new file mode 100644
index 0000000..96fbb25e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f3e5023e892b21a098011e426cd77c30bc22610f
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f446ca295cc66646e0ec31e6eaae3f54c84ce975 b/net/data/fuzzer_data/ntlm_client_fuzzer/f446ca295cc66646e0ec31e6eaae3f54c84ce975
new file mode 100644
index 0000000..5c840ec
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f446ca295cc66646e0ec31e6eaae3f54c84ce975
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f4dfae495b3895dfc7ed9dd0e6d30688da7d9afe b/net/data/fuzzer_data/ntlm_client_fuzzer/f4dfae495b3895dfc7ed9dd0e6d30688da7d9afe
new file mode 100644
index 0000000..18b0b6c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f4dfae495b3895dfc7ed9dd0e6d30688da7d9afe
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f504532dea4a4fdc3184100858e606e9b4d4c026 b/net/data/fuzzer_data/ntlm_client_fuzzer/f504532dea4a4fdc3184100858e606e9b4d4c026
new file mode 100644
index 0000000..817fbe7
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f504532dea4a4fdc3184100858e606e9b4d4c026
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f51ea2e3eeb1b73f13ef6c6f7bfa77cac015cc80 b/net/data/fuzzer_data/ntlm_client_fuzzer/f51ea2e3eeb1b73f13ef6c6f7bfa77cac015cc80
new file mode 100644
index 0000000..e65597d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f51ea2e3eeb1b73f13ef6c6f7bfa77cac015cc80
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f546e40a900d3107e67c80c4370ac64ce1bd554b b/net/data/fuzzer_data/ntlm_client_fuzzer/f546e40a900d3107e67c80c4370ac64ce1bd554b
new file mode 100644
index 0000000..4dd646c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f546e40a900d3107e67c80c4370ac64ce1bd554b
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f54fae32a3caf8fb9b3135108c2b70bb1e1d1509 b/net/data/fuzzer_data/ntlm_client_fuzzer/f54fae32a3caf8fb9b3135108c2b70bb1e1d1509
new file mode 100644
index 0000000..ff51591
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f54fae32a3caf8fb9b3135108c2b70bb1e1d1509
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f691112114a05ad9be413fe0d50b7fce3a193400 b/net/data/fuzzer_data/ntlm_client_fuzzer/f691112114a05ad9be413fe0d50b7fce3a193400
new file mode 100644
index 0000000..785ac4c9e1
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f691112114a05ad9be413fe0d50b7fce3a193400
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f7c1e977264dd6ae60e08c43f0c7acb539568388 b/net/data/fuzzer_data/ntlm_client_fuzzer/f7c1e977264dd6ae60e08c43f0c7acb539568388
new file mode 100644
index 0000000..07083df4
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f7c1e977264dd6ae60e08c43f0c7acb539568388
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f7ce46bdceae13fb49310932fce8b2d93a0680cb b/net/data/fuzzer_data/ntlm_client_fuzzer/f7ce46bdceae13fb49310932fce8b2d93a0680cb
new file mode 100644
index 0000000..52be12c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f7ce46bdceae13fb49310932fce8b2d93a0680cb
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f830487d459836db06b908475f4f72a09eadce70 b/net/data/fuzzer_data/ntlm_client_fuzzer/f830487d459836db06b908475f4f72a09eadce70
new file mode 100644
index 0000000..bc104b1
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f830487d459836db06b908475f4f72a09eadce70
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/f9d25420e3851f0db8e1d99986513eec1516d536 b/net/data/fuzzer_data/ntlm_client_fuzzer/f9d25420e3851f0db8e1d99986513eec1516d536
new file mode 100644
index 0000000..39d5c3d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/f9d25420e3851f0db8e1d99986513eec1516d536
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/fa35b5ac1fb5608d211b143e893db79ece124e5e b/net/data/fuzzer_data/ntlm_client_fuzzer/fa35b5ac1fb5608d211b143e893db79ece124e5e
new file mode 100644
index 0000000..825fa2b
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/fa35b5ac1fb5608d211b143e893db79ece124e5e
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/faae8197b295466e67c86eec64ef82bdf9b1c44c b/net/data/fuzzer_data/ntlm_client_fuzzer/faae8197b295466e67c86eec64ef82bdf9b1c44c
new file mode 100644
index 0000000..40b8e0e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/faae8197b295466e67c86eec64ef82bdf9b1c44c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/fcf98b4482bb5b968a483943681d120861b2262f b/net/data/fuzzer_data/ntlm_client_fuzzer/fcf98b4482bb5b968a483943681d120861b2262f
new file mode 100644
index 0000000..7c93ccd
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/fcf98b4482bb5b968a483943681d120861b2262f
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/fd0e2a4cb935307adfb2f397dff3e3396d30381a b/net/data/fuzzer_data/ntlm_client_fuzzer/fd0e2a4cb935307adfb2f397dff3e3396d30381a
new file mode 100644
index 0000000..8c1fef31
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/fd0e2a4cb935307adfb2f397dff3e3396d30381a
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/fd7d5b922907bf9135618de77295f73d0a06484c b/net/data/fuzzer_data/ntlm_client_fuzzer/fd7d5b922907bf9135618de77295f73d0a06484c
new file mode 100644
index 0000000..457b2acf
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/fd7d5b922907bf9135618de77295f73d0a06484c
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/fdc4211c72bbeef34eb6a68c519f0acbf0621d4b b/net/data/fuzzer_data/ntlm_client_fuzzer/fdc4211c72bbeef34eb6a68c519f0acbf0621d4b
new file mode 100644
index 0000000..08c0815b
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/fdc4211c72bbeef34eb6a68c519f0acbf0621d4b
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_zero_target_name_offset.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/fef223ff6a12f0b7cd03cf55f5075b4843627392
similarity index 100%
rename from net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_zero_target_name_offset.bin
rename to net/data/fuzzer_data/ntlm_client_fuzzer/fef223ff6a12f0b7cd03cf55f5075b4843627392
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/ffb53809271105f9989a5c66cba9d225377975ba b/net/data/fuzzer_data/ntlm_client_fuzzer/ffb53809271105f9989a5c66cba9d225377975ba
new file mode 100644
index 0000000..6ab285ff
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/ffb53809271105f9989a5c66cba9d225377975ba
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0001.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0001.bin
deleted file mode 100644
index 5fbd821..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0001.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0004.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0004.bin
deleted file mode 100644
index 47536b9..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0004.bin
+++ /dev/null
@@ -1 +0,0 @@
-NTLMTLM
\ No newline at end of file
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0005.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0005.bin
deleted file mode 100644
index 7473331..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0005.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0006.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0006.bin
deleted file mode 100644
index 59b8622..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0006.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0007.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0007.bin
deleted file mode 100644
index 41f9091..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0007.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0008.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0008.bin
deleted file mode 100644
index b606083..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0008.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0009.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0009.bin
deleted file mode 100644
index 0b611b6..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0009.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0010.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0010.bin
deleted file mode 100644
index 81328cc..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0010.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0011.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0011.bin
deleted file mode 100644
index c1e5459..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0011.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0012.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0012.bin
deleted file mode 100644
index 10b29fc2..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0012.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0013.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0013.bin
deleted file mode 100644
index 9d8690a8..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0013.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0014.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0014.bin
deleted file mode 100644
index 4973fb20..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0014.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0015.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0015.bin
deleted file mode 100644
index e8a58405a..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0015.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0016.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0016.bin
deleted file mode 100644
index 621e80e..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0016.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0017.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0017.bin
deleted file mode 100644
index c462bd9..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0017.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0018.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0018.bin
deleted file mode 100644
index b67afe0..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0018.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0019.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0019.bin
deleted file mode 100644
index bab5e6e..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0019.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0020.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0020.bin
deleted file mode 100644
index a30cc54..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0020.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0021.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0021.bin
deleted file mode 100644
index d1c8e05..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0021.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0022.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0022.bin
deleted file mode 100644
index f28fc3d..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0022.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0023.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0023.bin
deleted file mode 100644
index f1f4bb4..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0023.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0024.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0024.bin
deleted file mode 100644
index a0672f4..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0024.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0025.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0025.bin
deleted file mode 100644
index fe0425e..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0025.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0026.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0026.bin
deleted file mode 100644
index f8a9023..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0026.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0027.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0027.bin
deleted file mode 100644
index 3b00f011..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0027.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0028.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0028.bin
deleted file mode 100644
index 614ce50..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0028.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0029.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0029.bin
deleted file mode 100644
index 377e0f6..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0029.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0030.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0030.bin
deleted file mode 100644
index 2104a07..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0030.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0031.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0031.bin
deleted file mode 100644
index 7060f5a..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0031.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0032.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0032.bin
deleted file mode 100644
index 34f14d9..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0032.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0033.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0033.bin
deleted file mode 100644
index 7020361a..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0033.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0034.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0034.bin
deleted file mode 100644
index d9c78d1..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0034.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0035.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0035.bin
deleted file mode 100644
index 0d390d83..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0035.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0036.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0036.bin
deleted file mode 100644
index 8a45436..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0036.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0037.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0037.bin
deleted file mode 100644
index 69b0a13..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0037.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0038.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0038.bin
deleted file mode 100644
index af76586..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0038.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0039.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0039.bin
deleted file mode 100644
index 8e9671c..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0039.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0040.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0040.bin
deleted file mode 100644
index b273002..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0040.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0041.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0041.bin
deleted file mode 100644
index 51dfba6..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0041.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0042.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0042.bin
deleted file mode 100644
index 6e6e09e..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0042.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0043.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0043.bin
deleted file mode 100644
index 530b0ce2..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0043.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0044.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0044.bin
deleted file mode 100644
index 5cd8c83..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0044.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0045.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0045.bin
deleted file mode 100644
index 03af3a5a9..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0045.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0046.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0046.bin
deleted file mode 100644
index 8410149..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0046.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0047.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0047.bin
deleted file mode 100644
index 926d80a..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0047.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0048.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0048.bin
deleted file mode 100644
index 13577d2..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0048.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0049.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0049.bin
deleted file mode 100644
index 4771d6c..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0049.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0050.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0050.bin
deleted file mode 100644
index fb65c29c..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0050.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0051.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0051.bin
deleted file mode 100644
index 8217b184..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0051.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0052.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0052.bin
deleted file mode 100644
index ece8b30..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0052.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0053.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0053.bin
deleted file mode 100644
index 699dd92..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0053.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0054.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0054.bin
deleted file mode 100644
index 38e4308..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0054.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0055.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0055.bin
deleted file mode 100644
index cbc53af..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0055.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0056.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0056.bin
deleted file mode 100644
index f221f8f..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0056.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0057.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0057.bin
deleted file mode 100644
index 512f14e38..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0057.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0058.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0058.bin
deleted file mode 100644
index 9e1d0a0..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0058.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0059.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0059.bin
deleted file mode 100644
index caece732..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0059.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0060.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0060.bin
deleted file mode 100644
index 9debe5f..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0060.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0061.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0061.bin
deleted file mode 100644
index 280e506..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0061.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0062.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0062.bin
deleted file mode 100644
index 845c743c..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0062.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0063.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0063.bin
deleted file mode 100644
index 725e684..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0063.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0064.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0064.bin
deleted file mode 100644
index ba17f74..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0064.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0065.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0065.bin
deleted file mode 100644
index 3456bc1..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0065.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0066.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0066.bin
deleted file mode 100644
index cc59ed3..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0066.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0067.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0067.bin
deleted file mode 100644
index bf33a20..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0067.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0068.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0068.bin
deleted file mode 100644
index 6c4f277..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0068.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0069.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0069.bin
deleted file mode 100644
index ee77d1b..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0069.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0070.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0070.bin
deleted file mode 100644
index 46ca637..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0070.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0071.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0071.bin
deleted file mode 100644
index c2d975c..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0071.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0072.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0072.bin
deleted file mode 100644
index e4dde45..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0072.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0073.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0073.bin
deleted file mode 100644
index 91f3030..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0073.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0074.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0074.bin
deleted file mode 100644
index 7c5957a..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0074.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0075.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0075.bin
deleted file mode 100644
index 88dd3bf..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0075.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0076.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0076.bin
deleted file mode 100644
index 86a30c0..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0076.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0077.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0077.bin
deleted file mode 100644
index 9efe98e..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0077.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0078.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0078.bin
deleted file mode 100644
index 750b9aa..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0078.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0079.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0079.bin
deleted file mode 100644
index ab9857d..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0079.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0080.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0080.bin
deleted file mode 100644
index 924ee6b..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0080.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0081.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0081.bin
deleted file mode 100644
index 0ff800ef..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0081.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0082.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0082.bin
deleted file mode 100644
index 00bd3be..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0082.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0083.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0083.bin
deleted file mode 100644
index c425134..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0083.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0084.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0084.bin
deleted file mode 100644
index 0e67c2c..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0084.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0085.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0085.bin
deleted file mode 100644
index 3706e12..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0085.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0086.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0086.bin
deleted file mode 100644
index adf3728..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0086.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0087.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0087.bin
deleted file mode 100644
index 0d68d69..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0087.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0088.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0088.bin
deleted file mode 100644
index 26c582d..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0088.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0089.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0089.bin
deleted file mode 100644
index 7f9ab4e..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0089.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0090.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0090.bin
deleted file mode 100644
index f79a15d..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0090.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0091.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0091.bin
deleted file mode 100644
index 28c50a5..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0091.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0092.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0092.bin
deleted file mode 100644
index f3cae66..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0092.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0093.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0093.bin
deleted file mode 100644
index 8242183..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0093.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0094.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0094.bin
deleted file mode 100644
index deabfc2..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0094.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0095.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0095.bin
deleted file mode 100644
index fd15789..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0095.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0096.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0096.bin
deleted file mode 100644
index fa7bbeb..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0096.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0097.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0097.bin
deleted file mode 100644
index 2cf1abb..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0097.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0098.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0098.bin
deleted file mode 100644
index 00ac7a3..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0098.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0099.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0099.bin
deleted file mode 100644
index 330d7cf..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0099.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0100.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0100.bin
deleted file mode 100644
index bca0c582..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0100.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0101.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0101.bin
deleted file mode 100644
index 6b44f59..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0101.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0102.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0102.bin
deleted file mode 100644
index 5b628fe1..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0102.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0103.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0103.bin
deleted file mode 100644
index 7999eb7..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0103.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0104.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0104.bin
deleted file mode 100644
index 66f711e..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0104.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0105.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0105.bin
deleted file mode 100644
index 6e164b5..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0105.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0106.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0106.bin
deleted file mode 100644
index 83d22c21..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0106.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0107.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0107.bin
deleted file mode 100644
index d7a1bd9..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0107.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0108.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0108.bin
deleted file mode 100644
index 7381ba6..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0108.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0109.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0109.bin
deleted file mode 100644
index a69095c..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0109.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0110.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0110.bin
deleted file mode 100644
index 88f9980..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0110.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0111.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0111.bin
deleted file mode 100644
index 1003e284..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0111.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0112.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0112.bin
deleted file mode 100644
index 0e62a66..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0112.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0113.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0113.bin
deleted file mode 100644
index 38ae0fb..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0113.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0114.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0114.bin
deleted file mode 100644
index a506e02..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0114.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0115.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0115.bin
deleted file mode 100644
index 91a4aa8..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0115.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0116.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0116.bin
deleted file mode 100644
index 09efefa..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0116.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0117.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0117.bin
deleted file mode 100644
index af1652c3..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0117.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0118.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0118.bin
deleted file mode 100644
index a0874e3..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0118.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0119.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0119.bin
deleted file mode 100644
index 4a018dd8..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0119.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0120.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0120.bin
deleted file mode 100644
index b6be5c2..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0120.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0121.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0121.bin
deleted file mode 100644
index 8bb62ee..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0121.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0122.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0122.bin
deleted file mode 100644
index 272dc16..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0122.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0123.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0123.bin
deleted file mode 100644
index 04508d64..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0123.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0124.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0124.bin
deleted file mode 100644
index 4530dd4..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0124.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0125.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0125.bin
deleted file mode 100644
index 3c8dbb50..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0125.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0126.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0126.bin
deleted file mode 100644
index 98754153..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0126.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0127.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0127.bin
deleted file mode 100644
index c1496ce..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0127.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0128.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0128.bin
deleted file mode 100644
index fcd602de..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0128.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0129.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0129.bin
deleted file mode 100644
index 6a93485..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0129.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0130.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0130.bin
deleted file mode 100644
index 11e4731..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0130.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0131.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0131.bin
deleted file mode 100644
index 59b9e48..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0131.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0132.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0132.bin
deleted file mode 100644
index 77eef11..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0132.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0133.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0133.bin
deleted file mode 100644
index 3a18b53..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0133.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0134.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0134.bin
deleted file mode 100644
index 4de9ffa..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0134.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0135.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0135.bin
deleted file mode 100644
index 345ee99..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0135.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0136.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0136.bin
deleted file mode 100644
index 0673656..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0136.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0137.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0137.bin
deleted file mode 100644
index ee10d17..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0137.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0138.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0138.bin
deleted file mode 100644
index 0582d75..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0138.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0139.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0139.bin
deleted file mode 100644
index a97ba95..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0139.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0140.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0140.bin
deleted file mode 100644
index e665e49..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0140.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0141.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0141.bin
deleted file mode 100644
index cc12b12..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0141.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0142.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0142.bin
deleted file mode 100644
index e302b08..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0142.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0143.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0143.bin
deleted file mode 100644
index d80571b..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0143.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0144.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0144.bin
deleted file mode 100644
index 4421a7a..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0144.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0145.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0145.bin
deleted file mode 100644
index c1ee371d..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0145.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0146.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0146.bin
deleted file mode 100644
index 13b34ec5..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0146.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0147.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0147.bin
deleted file mode 100644
index ab07749..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0147.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0148.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0148.bin
deleted file mode 100644
index 8c66a052..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0148.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0149.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0149.bin
deleted file mode 100644
index 5c5302f..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0149.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0150.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0150.bin
deleted file mode 100644
index 6ba161ab..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0150.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0151.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0151.bin
deleted file mode 100644
index 3818c137..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0151.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0152.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0152.bin
deleted file mode 100644
index 39fd63d..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0152.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0153.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0153.bin
deleted file mode 100644
index 2d27dde4..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0153.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0154.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0154.bin
deleted file mode 100644
index 7454103..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0154.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0155.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0155.bin
deleted file mode 100644
index c0add9e..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0155.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0156.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0156.bin
deleted file mode 100644
index 6b85869..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0156.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0157.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0157.bin
deleted file mode 100644
index c777eef8..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0157.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0159.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0159.bin
deleted file mode 100644
index 8e0b967..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0159.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0160.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0160.bin
deleted file mode 100644
index 5faf34c6..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0160.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0161.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0161.bin
deleted file mode 100644
index 931ca76..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0161.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0162.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0162.bin
deleted file mode 100644
index 43d8d4e..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0162.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0163.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0163.bin
deleted file mode 100644
index 9fc7abe0..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0163.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0164.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0164.bin
deleted file mode 100644
index 3ed4d46..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0164.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0165.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0165.bin
deleted file mode 100644
index aa1b137..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0165.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0166.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0166.bin
deleted file mode 100644
index e9e2746..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0166.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0167.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0167.bin
deleted file mode 100644
index bc57d7fa..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0167.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0168.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0168.bin
deleted file mode 100644
index db6143d..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0168.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0169.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0169.bin
deleted file mode 100644
index f7e2f37..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0169.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0170.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0170.bin
deleted file mode 100644
index afa5fcb..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0170.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0171.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0171.bin
deleted file mode 100644
index 1bc1469..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0171.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0172.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0172.bin
deleted file mode 100644
index 77589fd..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0172.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0173.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0173.bin
deleted file mode 100644
index 341e1294..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0173.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0174.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0174.bin
deleted file mode 100644
index f600051..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0174.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0175.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0175.bin
deleted file mode 100644
index cb85e40..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0175.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0176.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0176.bin
deleted file mode 100644
index 4757964..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0176.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0177.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0177.bin
deleted file mode 100644
index c61395e7..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0177.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0178.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0178.bin
deleted file mode 100644
index 244324df..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0178.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0179.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0179.bin
deleted file mode 100644
index 76fafad..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0179.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0180.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0180.bin
deleted file mode 100644
index f607889..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0180.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0181.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0181.bin
deleted file mode 100644
index 97eeb3d..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0181.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0182.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0182.bin
deleted file mode 100644
index 420ecf17..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0182.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0183.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0183.bin
deleted file mode 100644
index 3d64a16..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0183.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0184.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0184.bin
deleted file mode 100644
index 6c6e27e..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0184.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0185.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0185.bin
deleted file mode 100644
index 18aff61dc..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0185.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0186.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0186.bin
deleted file mode 100644
index 5565fae..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0186.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0187.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0187.bin
deleted file mode 100644
index 8b4d50f..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0187.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0188.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0188.bin
deleted file mode 100644
index 1116e15..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0188.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0189.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0189.bin
deleted file mode 100644
index c8e21bd..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0189.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0190.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0190.bin
deleted file mode 100644
index cb8ba0ec..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0190.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0191.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0191.bin
deleted file mode 100644
index f28fcca..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0191.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0192.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0192.bin
deleted file mode 100644
index ff9b900..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0192.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0193.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0193.bin
deleted file mode 100644
index 71b3783..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0193.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0194.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0194.bin
deleted file mode 100644
index 8d9d867e..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0194.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0195.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0195.bin
deleted file mode 100644
index 2a35617..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0195.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0196.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0196.bin
deleted file mode 100644
index a021ead..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0196.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0197.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0197.bin
deleted file mode 100644
index bfdc2c3..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0197.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0198.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0198.bin
deleted file mode 100644
index 4538d31..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0198.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0199.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0199.bin
deleted file mode 100644
index 2b32f8a..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0199.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0200.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0200.bin
deleted file mode 100644
index eb21f6bf..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0200.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0201.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0201.bin
deleted file mode 100644
index 3ee1496..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0201.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0202.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0202.bin
deleted file mode 100644
index 359c465..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0202.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0203.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0203.bin
deleted file mode 100644
index 8ed1725..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0203.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0204.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0204.bin
deleted file mode 100644
index f8b0ec2..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0204.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0205.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0205.bin
deleted file mode 100644
index dce527ae..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0205.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0206.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0206.bin
deleted file mode 100644
index a048fff..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0206.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0207.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0207.bin
deleted file mode 100644
index 9be79a5..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0207.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0208.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0208.bin
deleted file mode 100644
index d887e8f1..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0208.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0209.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0209.bin
deleted file mode 100644
index cc4e2f1..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0209.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0210.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0210.bin
deleted file mode 100644
index 054d8cb..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0210.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0211.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0211.bin
deleted file mode 100644
index 099130d..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0211.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0212.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0212.bin
deleted file mode 100644
index aaf4a62..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0212.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0213.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0213.bin
deleted file mode 100644
index 96252735..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0213.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0214.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0214.bin
deleted file mode 100644
index 57a2115..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0214.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0215.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0215.bin
deleted file mode 100644
index 0699fa3d..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0215.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0216.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0216.bin
deleted file mode 100644
index 62fca99..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0216.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0217.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0217.bin
deleted file mode 100644
index 0149eae1..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0217.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0218.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0218.bin
deleted file mode 100644
index 2a3a155..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0218.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0219.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0219.bin
deleted file mode 100644
index 0fe6457..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0219.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0220.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0220.bin
deleted file mode 100644
index 010f53b5..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0220.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0221.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0221.bin
deleted file mode 100644
index aead929..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0221.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0222.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0222.bin
deleted file mode 100644
index 7090ef3..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0222.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0223.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0223.bin
deleted file mode 100644
index c06942a9..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0223.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0224.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0224.bin
deleted file mode 100644
index d2f52926..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0224.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0225.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0225.bin
deleted file mode 100644
index 11084fa..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0225.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0226.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0226.bin
deleted file mode 100644
index 67d166ae..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0226.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0227.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0227.bin
deleted file mode 100644
index b19336f5..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0227.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0228.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0228.bin
deleted file mode 100644
index cf6d673..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0228.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0229.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0229.bin
deleted file mode 100644
index 10a4faf..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0229.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0230.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0230.bin
deleted file mode 100644
index 3d10e15..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0230.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0231.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0231.bin
deleted file mode 100644
index 0ac57fb4..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0231.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0232.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0232.bin
deleted file mode 100644
index dbd466440..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0232.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0233.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0233.bin
deleted file mode 100644
index 32ba27d..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0233.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0234.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0234.bin
deleted file mode 100644
index 6e3bb081..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0234.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0235.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0235.bin
deleted file mode 100644
index 70b881d5..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0235.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0236.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0236.bin
deleted file mode 100644
index 0f3333f..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0236.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0237.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0237.bin
deleted file mode 100644
index 2b4ae31c..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0237.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0238.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0238.bin
deleted file mode 100644
index 23060649..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0238.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0239.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0239.bin
deleted file mode 100644
index 18f4ac7d..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0239.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0240.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0240.bin
deleted file mode 100644
index 4f8e3ae..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0240.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0241.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0241.bin
deleted file mode 100644
index 7e68a9d..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0241.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0242.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0242.bin
deleted file mode 100644
index f12dd875..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0242.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0243.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0243.bin
deleted file mode 100644
index ca613df..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0243.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0244.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0244.bin
deleted file mode 100644
index 4dfa10d0..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0244.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0245.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0245.bin
deleted file mode 100644
index 28f7803..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0245.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0246.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0246.bin
deleted file mode 100644
index ed9c8ec..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0246.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0247.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0247.bin
deleted file mode 100644
index a6e37a05..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0247.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0248.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0248.bin
deleted file mode 100644
index 084d44d..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0248.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0249.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0249.bin
deleted file mode 100644
index 5c6d187c..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0249.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0250.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0250.bin
deleted file mode 100644
index 558758d..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0250.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0251.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0251.bin
deleted file mode 100644
index 8ace642..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0251.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0252.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0252.bin
deleted file mode 100644
index 9976ddd..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0252.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0253.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0253.bin
deleted file mode 100644
index 1c8b94f..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0253.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0254.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0254.bin
deleted file mode 100644
index 11e7b415f..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0254.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0255.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0255.bin
deleted file mode 100644
index b19711d..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0255.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0256.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0256.bin
deleted file mode 100644
index e2835ff..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0256.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0257.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0257.bin
deleted file mode 100644
index 4a8b194c..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0257.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0258.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0258.bin
deleted file mode 100644
index 373e3104..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0258.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0259.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0259.bin
deleted file mode 100644
index 508a701..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0259.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0261.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0261.bin
deleted file mode 100644
index 188eb32..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0261.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0262.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0262.bin
deleted file mode 100644
index aa8587d0..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0262.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0263.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0263.bin
deleted file mode 100644
index 46418dc..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0263.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0264.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0264.bin
deleted file mode 100644
index 50a9ba2c..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0264.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0265.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0265.bin
deleted file mode 100644
index 8a2dbbd4..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0265.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0266.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0266.bin
deleted file mode 100644
index e0c66139..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0266.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0267.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0267.bin
deleted file mode 100644
index e62d1d5..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0267.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0268.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0268.bin
deleted file mode 100644
index b9c13fcd7..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0268.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0269.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0269.bin
deleted file mode 100644
index 8fc96c1c..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0269.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0270.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0270.bin
deleted file mode 100644
index 2777fb3..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0270.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0271.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0271.bin
deleted file mode 100644
index 508f0344..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0271.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0272.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0272.bin
deleted file mode 100644
index ba3d348..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0272.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0273.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0273.bin
deleted file mode 100644
index f3b6d04..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0273.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0274.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0274.bin
deleted file mode 100644
index 03ebbda7..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0274.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0275.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0275.bin
deleted file mode 100644
index f9518471..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0275.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0276.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0276.bin
deleted file mode 100644
index e8d6d96cd..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0276.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0277.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0277.bin
deleted file mode 100644
index a20d91d..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0277.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0278.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0278.bin
deleted file mode 100644
index fe5a9732..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0278.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0279.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0279.bin
deleted file mode 100644
index acbac321..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0279.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0280.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0280.bin
deleted file mode 100644
index c5ec44a..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0280.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0281.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0281.bin
deleted file mode 100644
index 76d5cb773..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0281.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0282.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0282.bin
deleted file mode 100644
index 06228e9..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0282.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0283.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0283.bin
deleted file mode 100644
index 71e55dd..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0283.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0284.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0284.bin
deleted file mode 100644
index 495629f..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0284.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0285.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0285.bin
deleted file mode 100644
index 3caf33c..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0285.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0286.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0286.bin
deleted file mode 100644
index d251b2a..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0286.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0287.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0287.bin
deleted file mode 100644
index 6f6a5f1f..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0287.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0288.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0288.bin
deleted file mode 100644
index 07bed6b4..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0288.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0289.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0289.bin
deleted file mode 100644
index b6ccccf..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0289.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0290.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0290.bin
deleted file mode 100644
index 487c5e4..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0290.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0291.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0291.bin
deleted file mode 100644
index 2e0cb65..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0291.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0292.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0292.bin
deleted file mode 100644
index 687ae92..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0292.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0293.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0293.bin
deleted file mode 100644
index b3433a7..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0293.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0294.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0294.bin
deleted file mode 100644
index b70f5b9..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0294.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0295.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0295.bin
deleted file mode 100644
index bad3311..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0295.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0296.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0296.bin
deleted file mode 100644
index cacebbe..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0296.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0297.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0297.bin
deleted file mode 100644
index ca7c259..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0297.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0298.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0298.bin
deleted file mode 100644
index 68decb3..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0298.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0299.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0299.bin
deleted file mode 100644
index 5668a23ab..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0299.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0300.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0300.bin
deleted file mode 100644
index 4227ca4..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0300.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0301.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0301.bin
deleted file mode 100644
index 8c05a65..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0301.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0302.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0302.bin
deleted file mode 100644
index b3719eb3..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0302.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0303.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0303.bin
deleted file mode 100644
index 5746787..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0303.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0304.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0304.bin
deleted file mode 100644
index 28c4a85..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0304.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0305.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0305.bin
deleted file mode 100644
index f9cd719..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0305.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge.bin
deleted file mode 100644
index bbe0118f..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_no_ss.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_no_ss.bin
deleted file mode 100644
index e3cb357..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_no_ss.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_target_name_len_overflow.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_target_name_len_overflow.bin
deleted file mode 100644
index 568c63c..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_target_name_len_overflow.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_target_name_len_overflow2.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_target_name_len_overflow2.bin
deleted file mode 100644
index ad4fea0..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_target_name_len_overflow2.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_target_name_offset_overflow.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_target_name_offset_overflow.bin
deleted file mode 100644
index 338099c..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_target_name_offset_overflow.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_with_target_name.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_with_target_name.bin
deleted file mode 100644
index 24b02fc..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_with_target_name.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_wrong_message_type.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_wrong_message_type.bin
deleted file mode 100644
index 2ec29f6..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_wrong_message_type.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_wrong_signature.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_wrong_signature.bin
deleted file mode 100644
index 67ad5ee7..0000000
--- a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_wrong_signature.bin
+++ /dev/null
Binary files differ
diff --git a/net/data/fuzzer_dictionaries/net_ntlm_ntlm_client_fuzzer.dict b/net/data/fuzzer_dictionaries/net_ntlm_ntlm_client_fuzzer.dict
index 93b46b43..418d256 100644
--- a/net/data/fuzzer_dictionaries/net_ntlm_ntlm_client_fuzzer.dict
+++ b/net/data/fuzzer_dictionaries/net_ntlm_ntlm_client_fuzzer.dict
@@ -33,4 +33,44 @@
 
 # Target Names
 "Server"
-"S\x00e\x00r\x00v\x00e\x00r\x00"
\ No newline at end of file
+"S\x00e\x00r\x00v\x00e\x00r\x00"
+
+# Channel bindings prefix
+"tls-server-endpoint:"
+
+# Channel bindings with correct length
+"tls-server-endpoint:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+
+# Empty LM Response
+"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+
+# Target Info Field Headers
+"\x06\x00\x04\x00"
+"\x0a\x00\x10\x00"
+"\x02\x00\x0c\x00"
+"\x01\x00\x0c\x00"
+"\x09\x00\x16\x00"
+
+# Target Info Payload - Server
+"\x02\x00\x0c\x00S\x00e\x00r\x00v\x00e\x00r\x00"
+"S\x00e\x00r\x00v\x00e\x00r\x00"
+
+# Target Info Payload - Domain
+"\x02\x00\x0c\x00D\x00o\x00m\x00a\x00i\x00n\x00"
+"D\x00o\x00m\x00a\x00i\x00n\x00"
+
+# Target Info Payload - SPN
+"\x09\x00\x16\x00H\x00T\x00T\x00P\x00/\x00S\x00e\x00r\x00v\x00e\x00r\x00"
+"H\x00T\x00T\x00P\x00/\x00S\x00e\x00r\x00v\x00e\x00r\x00"
+
+# Target Info Payload - Channel bindings
+"\x0a\x00\x10\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+
+# Target Info Payload - Flags
+"\x06\x00\x04\x00\x02\x00\x00\x00"
+
+# Full V1 Challenge
+"\x4e\x54\x4c\x4d\x53\x53\x50\x00\x02\x00\x00\x00\x0c\x00\x0c\x00\x38\x00\x00\x00\x33\x82\x0a\x82\x01\x23\x45\x67\x89\xab\xcd\xef\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x70\x17\x00\x00\x00\x0f\x53\x00\x65\x00\x72\x00\x76\x00\x65\x00\x72\x00"
+
+# Full V2 Challenge
+"\x4e\x54\x4c\x4d\x53\x53\x50\x00\x02\x00\x00\x00\x0c\x00\x0c\x00\x38\x00\x00\x00\x33\x82\x8a\xe2\x01\x23\x45\x67\x89\xab\xcd\xef\x00\x00\x00\x00\x00\x00\x00\x00\x24\x00\x24\x00\x44\x00\x00\x00\x06\x00\x70\x17\x00\x00\x00\x0f\x53\x00\x65\x00\x72\x00\x76\x00\x65\x00\x72\x00\x02\x00\x0c\x00\x44\x00\x6f\x00\x6d\x00\x61\x00\x69\x00\x6e\x00\x01\x00\x0c\x00\x53\x00\x65\x00\x72\x00\x76\x00\x65\x00\x72\x00\x00\x00\x00\x00"
diff --git a/net/disk_cache/backend_unittest.cc b/net/disk_cache/backend_unittest.cc
index 635b43b..53c5e34 100644
--- a/net/disk_cache/backend_unittest.cc
+++ b/net/disk_cache/backend_unittest.cc
@@ -3846,7 +3846,7 @@
   ASSERT_THAT(OpenEntry(key, &entry), IsError(net::ERR_FAILED));
 
   // Confirm the rest of the files are gone.
-  for (int i = 1; i < disk_cache::kSimpleEntryFileCount; ++i) {
+  for (int i = 1; i < disk_cache::kSimpleEntryNormalFileCount; ++i) {
     base::FilePath should_be_gone_file(cache_path_.AppendASCII(
         disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(key, i)));
     EXPECT_FALSE(base::PathExists(should_be_gone_file));
diff --git a/net/disk_cache/disk_cache_perftest.cc b/net/disk_cache/disk_cache_perftest.cc
index c8df0df..52667df 100644
--- a/net/disk_cache/disk_cache_perftest.cc
+++ b/net/disk_cache/disk_cache_perftest.cc
@@ -5,6 +5,7 @@
 #include <limits>
 #include <string>
 
+#include "base/barrier_closure.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/files/file_enumerator.h"
@@ -13,6 +14,7 @@
 #include "base/process/process_metrics.h"
 #include "base/rand_util.h"
 #include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/test/perf_time_logger.h"
 #include "base/test/scoped_task_environment.h"
@@ -302,6 +304,89 @@
   base::RunLoop().RunUntilIdle();
 }
 
+void VerifyRvAndCallClosure(base::Closure* c, int expect_rv, int rv) {
+  EXPECT_EQ(expect_rv, rv);
+  c->Run();
+}
+
+TEST_F(DiskCachePerfTest, SimpleCacheInitialReadPortion) {
+  // A benchmark that aims to measure how much time we take in I/O thread
+  // for initial bookkeeping before returning to the caller, and how much
+  // after (batched up some). The later portion includes some event loop
+  // overhead.
+  const int kBatchSize = 100;
+
+  SetSimpleCacheMode();
+
+  InitCache();
+  // Write out the entries, and keep their objects around.
+  scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kHeadersSize));
+  scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kBodySize));
+
+  CacheTestFillBuffer(buffer1->data(), kHeadersSize, false);
+  CacheTestFillBuffer(buffer2->data(), kBodySize, false);
+
+  disk_cache::Entry* cache_entry[kBatchSize];
+  for (int i = 0; i < kBatchSize; ++i) {
+    net::TestCompletionCallback cb;
+    int rv = cache_->CreateEntry(base::IntToString(i), &cache_entry[i],
+                                 cb.callback());
+    ASSERT_EQ(net::OK, cb.GetResult(rv));
+
+    rv = cache_entry[i]->WriteData(0, 0, buffer1.get(), kHeadersSize,
+                                   cb.callback(), false);
+    ASSERT_EQ(kHeadersSize, cb.GetResult(rv));
+    rv = cache_entry[i]->WriteData(1, 0, buffer2.get(), kBodySize,
+                                   cb.callback(), false);
+    ASSERT_EQ(kBodySize, cb.GetResult(rv));
+  }
+
+  // Now repeatedly read these, batching up the waiting to try to
+  // account for the two portions separately. Note that we need separate entries
+  // since we are trying to keep interesting work from being on the delayed-done
+  // portion.
+  const int kIterations = 50000;
+
+  double elapsed_early = 0.0;
+  double elapsed_late = 0.0;
+
+  for (int i = 0; i < kIterations; ++i) {
+    base::RunLoop event_loop;
+    base::Closure barrier =
+        base::BarrierClosure(kBatchSize, event_loop.QuitWhenIdleClosure());
+    net::CompletionCallback cb_batch(base::Bind(
+        VerifyRvAndCallClosure, base::Unretained(&barrier), kHeadersSize));
+
+    base::ElapsedTimer timer_early;
+    for (int e = 0; e < kBatchSize; ++e) {
+      int rv =
+          cache_entry[e]->ReadData(0, 0, buffer1.get(), kHeadersSize, cb_batch);
+      if (rv != net::ERR_IO_PENDING) {
+        barrier.Run();
+        ASSERT_EQ(kHeadersSize, rv);
+      }
+    }
+    elapsed_early += timer_early.Elapsed().InMillisecondsF();
+
+    base::ElapsedTimer timer_late;
+    event_loop.Run();
+    elapsed_late += timer_late.Elapsed().InMillisecondsF();
+  }
+
+  // Cleanup
+  for (int i = 0; i < kBatchSize; ++i)
+    cache_entry[i]->Close();
+
+  disk_cache::SimpleBackendImpl::FlushWorkerPoolForTesting();
+  base::RunLoop().RunUntilIdle();
+  LOG(ERROR) << "Early portion:" << elapsed_early << " ms";
+  LOG(ERROR) << "\tPer entry:"
+             << 1000 * (elapsed_early / (kIterations * kBatchSize)) << " us";
+  LOG(ERROR) << "Event loop portion: " << elapsed_late << " ms";
+  LOG(ERROR) << "\tPer entry:"
+             << 1000 * (elapsed_late / (kIterations * kBatchSize)) << " us";
+}
+
 // Measures how quickly SimpleIndex can compute which entries to evict.
 TEST(SimpleIndexPerfTest, EvictionPerformance) {
   const int kEntries = 10000;
diff --git a/net/disk_cache/entry_unittest.cc b/net/disk_cache/entry_unittest.cc
index f81c6e5..23140c3e 100644
--- a/net/disk_cache/entry_unittest.cc
+++ b/net/disk_cache/entry_unittest.cc
@@ -571,13 +571,13 @@
   if (net::ERR_IO_PENDING == ret)
     expected++;
 
-  EXPECT_EQ(0,
-            entry->ReadData(
-                1,
-                35000,
-                buffer2.get(),
-                kSize2,
-                base::Bind(&CallbackTest::Run, base::Unretained(&callback7))));
+  ret = entry->ReadData(
+      1, 35000, buffer2.get(), kSize2,
+      base::Bind(&CallbackTest::Run, base::Unretained(&callback7)));
+  EXPECT_TRUE(0 == ret || net::ERR_IO_PENDING == ret);
+  if (net::ERR_IO_PENDING == ret)
+    expected++;
+
   ret = entry->ReadData(
       1,
       0,
@@ -3228,7 +3228,7 @@
   // operation and destroy the entry object.
   base::RunLoop().RunUntilIdle();
 
-  for (int i = 0; i < disk_cache::kSimpleEntryFileCount; ++i) {
+  for (int i = 0; i < disk_cache::kSimpleEntryNormalFileCount; ++i) {
     base::FilePath entry_file_path = cache_path_.AppendASCII(
         disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(key, i));
     base::File::Info info;
@@ -4602,3 +4602,22 @@
   histogram_tester.ExpectUniqueSample("SimpleCache.Http.SyncCheckEOFResult",
                                       disk_cache::CHECK_EOF_RESULT_SUCCESS, 2);
 }
+
+TEST_F(DiskCacheSimplePrefetchTest, PrefetchReadsSync) {
+  // Make sure we can read things synchronously after prefetch.
+  SetupPrefetch(32768);  // way bigger than kEntrySize
+  const char kKey[] = "a key";
+  InitCacheAndCreateEntry(kKey);
+
+  disk_cache::Entry* entry = NULL;
+  ASSERT_THAT(OpenEntry(kKey, &entry), IsOk());
+  scoped_refptr<net::IOBuffer> read_buf(new net::IOBuffer(kEntrySize));
+
+  // That this is entry->ReadData(...) rather than ReadData(entry, ...) is
+  // meaningful here, as the latter is a helper in the test fixture that blocks
+  // if needed.
+  EXPECT_EQ(kEntrySize, entry->ReadData(1, 0, read_buf.get(), kEntrySize,
+                                        net::CompletionCallback()));
+  EXPECT_EQ(0, memcmp(read_buf->data(), payload_->data(), kEntrySize));
+  entry->Close();
+}
diff --git a/net/disk_cache/simple/simple_entry_format.h b/net/disk_cache/simple/simple_entry_format.h
index f5a68b30..9b2e75e 100644
--- a/net/disk_cache/simple/simple_entry_format.h
+++ b/net/disk_cache/simple/simple_entry_format.h
@@ -36,9 +36,15 @@
 //   - the key.
 //   - the data.
 //   - at the end, a SimpleFileEOF record.
-static const int kSimpleEntryFileCount = 2;
+
+// This is the number of files we can use for representing normal/dense streams.
+static const int kSimpleEntryNormalFileCount = 2;
 static const int kSimpleEntryStreamCount = 3;
 
+// Total # of files name we can potentially use; this includes both normal
+// API and sparse streams.
+static const int kSimpleEntryTotalFileCount = kSimpleEntryNormalFileCount + 1;
+
 // Note that stream 0/stream 1 files rely on the footer to verify the entry,
 // so if the format changes, it's insufficient to change the version here;
 // likely the EOF magic should be updated as well.
diff --git a/net/disk_cache/simple/simple_entry_impl.cc b/net/disk_cache/simple/simple_entry_impl.cc
index d0a4289..29c0725 100644
--- a/net/disk_cache/simple/simple_entry_impl.cc
+++ b/net/disk_cache/simple/simple_entry_impl.cc
@@ -133,6 +133,20 @@
   completion_callback.Run(result);
 }
 
+// If |sync_possible| is false, and callback is available, posts rv to it and
+// return net::ERR_IO_PENDING; otherwise just passes through rv.
+int PostToCallbackIfNeeded(bool sync_possible,
+                           const net::CompletionCallback& callback,
+                           int rv) {
+  if (!sync_possible && !callback.is_null()) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                  base::Bind(callback, rv));
+    return net::ERR_IO_PENDING;
+  } else {
+    return rv;
+  }
+}
+
 }  // namespace
 
 using base::Closure;
@@ -370,23 +384,17 @@
     RecordReadResult(cache_type_, READ_RESULT_INVALID_ARGUMENT);
     return net::ERR_INVALID_ARGUMENT;
   }
-  if (pending_operations_.empty() && (offset >= GetDataSize(stream_index) ||
-                                      offset < 0 || !buf_len)) {
-    if (net_log_.IsCapturing()) {
-      net_log_.AddEvent(net::NetLogEventType::SIMPLE_CACHE_ENTRY_READ_END,
-                        CreateNetLogReadWriteCompleteCallback(0));
-    }
-
-    RecordReadResult(cache_type_, READ_RESULT_NONBLOCK_EMPTY_RETURN);
-    return 0;
-  }
-
-  // TODO(clamy): return immediatly when reading from stream 0.
 
   // TODO(felipeg): Optimization: Add support for truly parallel read
   // operations.
   bool alone_in_queue =
       pending_operations_.size() == 0 && state_ == STATE_READY;
+
+  if (alone_in_queue) {
+    return ReadDataInternal(/*sync_possible = */ true, stream_index, offset,
+                            buf, buf_len, callback);
+  }
+
   pending_operations_.push(SimpleEntryOperation::ReadOperation(
       this, stream_index, offset, buf_len, buf, callback, alone_in_queue));
   RunNextOperationIfNeeded();
@@ -634,11 +642,9 @@
         break;
       case SimpleEntryOperation::TYPE_READ:
         RecordReadIsParallelizable(*operation);
-        ReadDataInternal(operation->index(),
-                         operation->offset(),
-                         operation->buf(),
-                         operation->length(),
-                         operation->callback());
+        ReadDataInternal(/* sync_possible= */ false, operation->index(),
+                         operation->offset(), operation->buf(),
+                         operation->length(), operation->callback());
         break;
       case SimpleEntryOperation::TYPE_WRITE:
         RecordWriteDependencyType(*operation);
@@ -809,11 +815,12 @@
   }
 }
 
-void SimpleEntryImpl::ReadDataInternal(int stream_index,
-                                       int offset,
-                                       net::IOBuffer* buf,
-                                       int buf_len,
-                                       const CompletionCallback& callback) {
+int SimpleEntryImpl::ReadDataInternal(bool sync_possible,
+                                      int stream_index,
+                                      int offset,
+                                      net::IOBuffer* buf,
+                                      int buf_len,
+                                      const CompletionCallback& callback) {
   DCHECK(io_thread_checker_.CalledOnValidThread());
   ScopedOperationRunner operation_runner(this);
 
@@ -824,38 +831,33 @@
   }
 
   if (state_ == STATE_FAILURE || state_ == STATE_UNINITIALIZED) {
-    if (!callback.is_null()) {
-      RecordReadResult(cache_type_, READ_RESULT_BAD_STATE);
-      // Note that the API states that client-provided callbacks for entry-level
-      // (i.e. non-backend) operations (e.g. read, write) are invoked even if
-      // the backend was already destroyed.
-      base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE, base::Bind(callback, net::ERR_FAILED));
-    }
+    RecordReadResult(cache_type_, READ_RESULT_BAD_STATE);
     if (net_log_.IsCapturing()) {
       net_log_.AddEvent(net::NetLogEventType::SIMPLE_CACHE_ENTRY_READ_END,
                         CreateNetLogReadWriteCompleteCallback(net::ERR_FAILED));
     }
-    return;
+    // Note that the API states that client-provided callbacks for entry-level
+    // (i.e. non-backend) operations (e.g. read, write) are invoked even if
+    // the backend was already destroyed.
+    return PostToCallbackIfNeeded(sync_possible, callback, net::ERR_FAILED);
   }
   DCHECK_EQ(STATE_READY, state_);
   if (offset >= GetDataSize(stream_index) || offset < 0 || !buf_len) {
-    RecordReadResult(cache_type_, READ_RESULT_FAST_EMPTY_RETURN);
+    RecordReadResult(cache_type_, sync_possible
+                                      ? READ_RESULT_NONBLOCK_EMPTY_RETURN
+                                      : READ_RESULT_FAST_EMPTY_RETURN);
     // If there is nothing to read, we bail out before setting state_ to
-    // STATE_IO_PENDING.
-    if (!callback.is_null())
-      base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
-                                                    base::Bind(callback, 0));
-    return;
+    // STATE_IO_PENDING (so ScopedOperationRunner might start us on next op
+    // here).
+    return PostToCallbackIfNeeded(sync_possible, callback, 0);
   }
 
   buf_len = std::min(buf_len, GetDataSize(stream_index) - offset);
 
   // Since stream 0 data is kept in memory, it is read immediately.
   if (stream_index == 0) {
-    ReadFromBufferAndPostReply(stream_0_data_.get(), offset, buf_len, buf,
-                               callback);
-    return;
+    int rv = ReadFromBuffer(stream_0_data_.get(), offset, buf_len, buf);
+    return PostToCallbackIfNeeded(sync_possible, callback, rv);
   }
 
   // Sometimes we can read in-ram prefetched stream 1 data immediately, too.
@@ -867,9 +869,9 @@
     is_initial_stream1_read_ = false;
 
     if (stream_1_prefetch_data_) {
-      ReadFromBufferAndPostReply(stream_1_prefetch_data_.get(), offset, buf_len,
-                                 buf, callback);
-      return;
+      int rv =
+          ReadFromBuffer(stream_1_prefetch_data_.get(), offset, buf_len, buf);
+      return PostToCallbackIfNeeded(sync_possible, callback, rv);
     }
   }
 
@@ -905,6 +907,7 @@
                  offset, callback, base::Passed(&crc_request),
                  base::Passed(&entry_stat), base::Passed(&result));
   worker_pool_->PostTaskAndReply(FROM_HERE, task, reply);
+  return net::ERR_IO_PENDING;
 }
 
 void SimpleEntryImpl::WriteDataInternal(int stream_index,
@@ -1515,27 +1518,17 @@
                    type, WRITE_DEPENDENCY_TYPE_MAX);
 }
 
-void SimpleEntryImpl::ReadFromBufferAndPostReply(
-    net::GrowableIOBuffer* in_buf,
-    int offset,
-    int buf_len,
-    net::IOBuffer* out_buf,
-    const CompletionCallback& callback) {
-  int rv;
-  if (buf_len < 0) {
-    RecordReadResult(cache_type_, READ_RESULT_SYNC_READ_FAILURE);
-    rv = 0;
-  } else {
-    memcpy(out_buf->data(), in_buf->data() + offset, buf_len);
-    UpdateDataFromEntryStat(SimpleEntryStat(base::Time::Now(), last_modified_,
-                                            data_size_, sparse_data_size_));
-    RecordReadResult(cache_type_, READ_RESULT_SUCCESS);
-    rv = buf_len;
-  }
-  if (!callback.is_null()) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
-                                                  base::Bind(callback, rv));
-  }
+int SimpleEntryImpl::ReadFromBuffer(net::GrowableIOBuffer* in_buf,
+                                    int offset,
+                                    int buf_len,
+                                    net::IOBuffer* out_buf) {
+  DCHECK_GE(buf_len, 0);
+
+  memcpy(out_buf->data(), in_buf->data() + offset, buf_len);
+  UpdateDataFromEntryStat(SimpleEntryStat(base::Time::Now(), last_modified_,
+                                          data_size_, sparse_data_size_));
+  RecordReadResult(cache_type_, READ_RESULT_SUCCESS);
+  return buf_len;
 }
 
 int SimpleEntryImpl::SetStream0Data(net::IOBuffer* buf,
diff --git a/net/disk_cache/simple/simple_entry_impl.h b/net/disk_cache/simple/simple_entry_impl.h
index e3ebe51a..d79bc1e 100644
--- a/net/disk_cache/simple/simple_entry_impl.h
+++ b/net/disk_cache/simple/simple_entry_impl.h
@@ -195,11 +195,12 @@
 
   void CloseInternal();
 
-  void ReadDataInternal(int index,
-                        int offset,
-                        net::IOBuffer* buf,
-                        int buf_len,
-                        const CompletionCallback& callback);
+  int ReadDataInternal(bool sync_possible,
+                       int index,
+                       int offset,
+                       net::IOBuffer* buf,
+                       int buf_len,
+                       const CompletionCallback& callback);
 
   void WriteDataInternal(int index,
                          int offset,
@@ -305,13 +306,13 @@
   void RecordWriteDependencyType(const SimpleEntryOperation& operation) const;
 
   // Completes a read from the stream data kept in memory, logging metrics
-  // and updating metadata. If |callback| is non-null, it will be posted to the
-  // current task runner with the return code.
-  void ReadFromBufferAndPostReply(net::GrowableIOBuffer* in_buf,
-                                  int offset,
-                                  int buf_len,
-                                  net::IOBuffer* out_buf,
-                                  const CompletionCallback& callback);
+  // and updating metadata. Returns the # of bytes read successfully.
+  // This asumes the caller has already range-checked offset and buf_len
+  // appropriately.
+  int ReadFromBuffer(net::GrowableIOBuffer* in_buf,
+                     int offset,
+                     int buf_len,
+                     net::IOBuffer* out_buf);
 
   // Copies data from |buf| to the internal in-memory buffer for stream 0. If
   // |truncate| is set to true, the target buffer will be truncated at |offset|
diff --git a/net/disk_cache/simple/simple_synchronous_entry.cc b/net/disk_cache/simple/simple_synchronous_entry.cc
index 953c20a..b713c47 100644
--- a/net/disk_cache/simple/simple_synchronous_entry.cc
+++ b/net/disk_cache/simple/simple_synchronous_entry.cc
@@ -84,7 +84,7 @@
 
 bool CanOmitEmptyFile(int file_index) {
   DCHECK_GE(file_index, 0);
-  DCHECK_LT(file_index, kSimpleEntryFileCount);
+  DCHECK_LT(file_index, kSimpleEntryNormalFileCount);
   return file_index == simple_util::GetFileIndexFromStreamIndex(2);
 }
 
@@ -789,7 +789,7 @@
       break;
     }
   }
-  for (int i = 0; i < kSimpleEntryFileCount; ++i) {
+  for (int i = 0; i < kSimpleEntryNormalFileCount; ++i) {
     if (empty_file_omitted_[i])
       continue;
 
@@ -835,7 +835,7 @@
       key_(key),
       have_open_files_(false),
       initialized_(false) {
-  for (int i = 0; i < kSimpleEntryFileCount; ++i)
+  for (int i = 0; i < kSimpleEntryNormalFileCount; ++i)
     empty_file_omitted_[i] = false;
 }
 
@@ -899,7 +899,7 @@
 }
 
 bool SimpleSynchronousEntry::OpenFiles(SimpleEntryStat* out_entry_stat) {
-  for (int i = 0; i < kSimpleEntryFileCount; ++i) {
+  for (int i = 0; i < kSimpleEntryNormalFileCount; ++i) {
     File::Error error;
     if (!MaybeOpenFile(i, &error)) {
       // TODO(juliatuttle,gavinp): Remove one each of these triplets of
@@ -929,7 +929,7 @@
   have_open_files_ = true;
 
   base::TimeDelta entry_age = base::Time::Now() - base::Time::UnixEpoch();
-  for (int i = 0; i < kSimpleEntryFileCount; ++i) {
+  for (int i = 0; i < kSimpleEntryNormalFileCount; ++i) {
     if (empty_file_omitted_[i]) {
       out_entry_stat->set_data_size(i + 1, 0);
       continue;
@@ -980,7 +980,7 @@
 }
 
 bool SimpleSynchronousEntry::CreateFiles(SimpleEntryStat* out_entry_stat) {
-  for (int i = 0; i < kSimpleEntryFileCount; ++i) {
+  for (int i = 0; i < kSimpleEntryNormalFileCount; ++i) {
     File::Error error;
     if (!MaybeCreateFile(i, FILE_NOT_REQUIRED, &error)) {
       // TODO(juliatuttle,gavinp): Remove one each of these triplets of
@@ -1011,8 +1011,8 @@
   base::Time creation_time = Time::Now();
   out_entry_stat->set_last_modified(creation_time);
   out_entry_stat->set_last_used(creation_time);
-  for (int i = 0; i < kSimpleEntryStreamCount; ++i)
-      out_entry_stat->set_data_size(i, 0);
+  for (int i = 0; i < kSimpleEntryNormalFileCount; ++i)
+    out_entry_stat->set_data_size(i, 0);
 
   files_created_ = true;
 
@@ -1032,7 +1032,7 @@
 }
 
 void SimpleSynchronousEntry::CloseFiles() {
-  for (int i = 0; i < kSimpleEntryFileCount; ++i)
+  for (int i = 0; i < kSimpleEntryNormalFileCount; ++i)
     CloseFile(i);
 }
 
@@ -1112,7 +1112,7 @@
     DLOG(WARNING) << "Could not open platform files for entry.";
     return net::ERR_FAILED;
   }
-  for (int i = 0; i < kSimpleEntryFileCount; ++i) {
+  for (int i = 0; i < kSimpleEntryNormalFileCount; ++i) {
     if (empty_file_omitted_[i])
       continue;
 
@@ -1211,7 +1211,7 @@
     DLOG(WARNING) << "Could not create platform files.";
     return net::ERR_FILE_EXISTS;
   }
-  for (int i = 0; i < kSimpleEntryFileCount; ++i) {
+  for (int i = 0; i < kSimpleEntryNormalFileCount; ++i) {
     if (empty_file_omitted_[i])
       continue;
 
@@ -1402,7 +1402,7 @@
     const FilePath& path,
     const uint64_t entry_hash) {
   bool result = true;
-  for (int i = 0; i < kSimpleEntryFileCount; ++i) {
+  for (int i = 0; i < kSimpleEntryNormalFileCount; ++i) {
     if (!DeleteFileForEntryHash(path, entry_hash, i) && !CanOmitEmptyFile(i))
       result = false;
   }
@@ -1417,7 +1417,7 @@
     const FilePath& path,
     const uint64_t entry_hash) {
   bool result = true;
-  for (int i = 0; i < kSimpleEntryFileCount; ++i) {
+  for (int i = 0; i < kSimpleEntryNormalFileCount; ++i) {
     FilePath filename_to_truncate =
         path.AppendASCII(GetFilenameFromEntryHashAndFileIndex(entry_hash, i));
     if (!TruncatePath(filename_to_truncate))
diff --git a/net/disk_cache/simple/simple_synchronous_entry.h b/net/disk_cache/simple/simple_synchronous_entry.h
index 14b5b0d0..1ddda90 100644
--- a/net/disk_cache/simple/simple_synchronous_entry.h
+++ b/net/disk_cache/simple/simple_synchronous_entry.h
@@ -414,15 +414,15 @@
   // Normally false. This is set to true when an entry is opened without
   // checking the file headers. Any subsequent read will perform the check
   // before completing.
-  bool header_and_key_check_needed_[kSimpleEntryFileCount] = {
+  bool header_and_key_check_needed_[kSimpleEntryNormalFileCount] = {
       false,
   };
 
-  base::File files_[kSimpleEntryFileCount];
+  base::File files_[kSimpleEntryNormalFileCount];
 
   // True if the corresponding stream is empty and therefore no on-disk file
   // was created to store it.
-  bool empty_file_omitted_[kSimpleEntryFileCount];
+  bool empty_file_omitted_[kSimpleEntryNormalFileCount];
 
   typedef std::map<int64_t, SparseRange> SparseRangeOffsetMap;
   typedef SparseRangeOffsetMap::iterator SparseRangeIterator;
diff --git a/net/dns/dns_config_service_posix.cc b/net/dns/dns_config_service_posix.cc
index 92b68a4..b1e2bb5 100644
--- a/net/dns/dns_config_service_posix.cc
+++ b/net/dns/dns_config_service_posix.cc
@@ -317,7 +317,6 @@
     }
     UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ConfigParsePosix",
                               result, CONFIG_PARSE_POSIX_MAX);
-    UMA_HISTOGRAM_BOOLEAN("AsyncDNS.ConfigParseResult", success_);
     UMA_HISTOGRAM_TIMES("AsyncDNS.ConfigParseDuration",
                         base::TimeTicks::Now() - start_time);
   }
diff --git a/net/dns/dns_config_service_win.cc b/net/dns/dns_config_service_win.cc
index b9705a6..9d96d84 100644
--- a/net/dns/dns_config_service_win.cc
+++ b/net/dns/dns_config_service_win.cc
@@ -656,7 +656,6 @@
                 result == CONFIG_PARSE_WIN_UNHANDLED_OPTIONS);
     UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ConfigParseWin",
                               result, CONFIG_PARSE_WIN_MAX);
-    UMA_HISTOGRAM_BOOLEAN("AsyncDNS.ConfigParseResult", success_);
     UMA_HISTOGRAM_TIMES("AsyncDNS.ConfigParseDuration",
                         base::TimeTicks::Now() - start_time);
   }
diff --git a/net/dns/dns_session.cc b/net/dns/dns_session.cc
index 8303b31..d2e74765 100644
--- a/net/dns/dns_session.cc
+++ b/net/dns/dns_session.cc
@@ -167,9 +167,6 @@
   base::Time oldest_server_failure(base::Time::Now());
   unsigned oldest_server_failure_index = 0;
 
-  UMA_HISTOGRAM_BOOLEAN("AsyncDNS.ServerIsGood",
-                        server_stats_[server_index]->last_failure.is_null());
-
   do {
     base::Time cur_server_failure = server_stats_[index]->last_failure;
     // If number of failures on this server doesn't exceed number of allowed
diff --git a/net/dns/host_resolver_impl.cc b/net/dns/host_resolver_impl.cc
index 070f031..c27ef9b 100644
--- a/net/dns/host_resolver_impl.cc
+++ b/net/dns/host_resolver_impl.cc
@@ -236,42 +236,43 @@
   do {                                                             \
     switch (priority) {                                            \
       case HIGHEST:                                                \
-        UMA_HISTOGRAM_LONG_TIMES_100(basename "_HIGHEST", time);   \
+        UMA_HISTOGRAM_LONG_TIMES_100(basename ".HIGHEST", time);   \
         break;                                                     \
       case MEDIUM:                                                 \
-        UMA_HISTOGRAM_LONG_TIMES_100(basename "_MEDIUM", time);    \
+        UMA_HISTOGRAM_LONG_TIMES_100(basename ".MEDIUM", time);    \
         break;                                                     \
       case LOW:                                                    \
-        UMA_HISTOGRAM_LONG_TIMES_100(basename "_LOW", time);       \
+        UMA_HISTOGRAM_LONG_TIMES_100(basename ".LOW", time);       \
         break;                                                     \
       case LOWEST:                                                 \
-        UMA_HISTOGRAM_LONG_TIMES_100(basename "_LOWEST", time);    \
+        UMA_HISTOGRAM_LONG_TIMES_100(basename ".LOWEST", time);    \
         break;                                                     \
       case IDLE:                                                   \
-        UMA_HISTOGRAM_LONG_TIMES_100(basename "_IDLE", time);      \
+        UMA_HISTOGRAM_LONG_TIMES_100(basename ".IDLE", time);      \
         break;                                                     \
       case THROTTLED:                                              \
-        UMA_HISTOGRAM_LONG_TIMES_100(basename "_THROTTLED", time); \
+        UMA_HISTOGRAM_LONG_TIMES_100(basename ".THROTTLED", time); \
         break;                                                     \
     }                                                              \
     UMA_HISTOGRAM_LONG_TIMES_100(basename, time);                  \
   } while (0)
 
 // Record time from Request creation until a valid DNS response.
-void RecordTotalTime(bool had_dns_config,
-                     bool speculative,
+void RecordTotalTime(bool speculative,
+                     bool from_cache,
                      base::TimeDelta duration) {
-  if (had_dns_config) {
-    if (speculative) {
-      UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.TotalTime_speculative", duration);
-    } else {
-      UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.TotalTime", duration);
-    }
+  if (speculative) {
+    UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.TotalTime.Speculative", duration);
   } else {
+    UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.TotalTime", duration);
+  }
+
+  if (!from_cache) {
     if (speculative) {
-      UMA_HISTOGRAM_LONG_TIMES_100("DNS.TotalTime_speculative", duration);
+      UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.TotalTimeNotCached.Speculative",
+                                   duration);
     } else {
-      UMA_HISTOGRAM_LONG_TIMES_100("DNS.TotalTime", duration);
+      UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.TotalTimeNotCached", duration);
     }
   }
 }
@@ -692,7 +693,6 @@
         attempt_number_(0),
         completed_attempt_number_(0),
         completed_attempt_error_(ERR_UNEXPECTED),
-        had_non_speculative_request_(false),
         net_log_(job_net_log) {
     if (!params_.resolver_proc.get())
       params_.resolver_proc = HostResolverProc::GetDefault();
@@ -720,11 +720,6 @@
     net_log_.EndEvent(NetLogEventType::HOST_RESOLVER_IMPL_PROC_TASK);
   }
 
-  void set_had_non_speculative_request() {
-    DCHECK(network_task_runner_->BelongsToCurrentThread());
-    had_non_speculative_request_ = true;
-  }
-
   bool was_canceled() const {
     DCHECK(network_task_runner_->BelongsToCurrentThread());
     return callback_.is_null();
@@ -804,7 +799,6 @@
     DCHECK(network_task_runner_->BelongsToCurrentThread());
     // If results are empty, we should return an error.
     bool empty_list_on_ok = (error == OK && results.empty());
-    UMA_HISTOGRAM_BOOLEAN("DNS.EmptyAddressListAndNoError", empty_list_on_ok);
     if (empty_list_on_ok)
       error = ERR_NAME_NOT_RESOLVED;
 
@@ -816,11 +810,6 @@
     if (error != OK && NetworkChangeNotifier::IsOffline())
       error = ERR_INTERNET_DISCONNECTED;
 
-    // If this is the first attempt that is finishing later, then record data
-    // for the first attempt. Won't contaminate with retry attempt's data.
-    if (!was_retry_attempt)
-      RecordPerformanceHistograms(start_time, error, os_error);
-
     RecordAttemptHistograms(start_time, attempt_number, error, os_error);
 
     if (was_canceled())
@@ -841,6 +830,8 @@
     if (was_completed())
       return;
 
+    RecordTaskHistograms(start_time, error, os_error);
+
     // Copy the results from the first worker thread that resolves the host.
     results_ = results;
     completed_attempt_number_ = attempt_number;
@@ -864,75 +855,19 @@
     callback_.Run(error, results_);
   }
 
-  void RecordPerformanceHistograms(const base::TimeTicks& start_time,
-                                   const int error,
-                                   const int os_error) const {
+  void RecordTaskHistograms(const base::TimeTicks& start_time,
+                            const int error,
+                            const int os_error) const {
     DCHECK(network_task_runner_->BelongsToCurrentThread());
-    enum Category {  // Used in UMA_HISTOGRAM_ENUMERATION.
-      RESOLVE_SUCCESS,
-      RESOLVE_FAIL,
-      RESOLVE_SPECULATIVE_SUCCESS,
-      RESOLVE_SPECULATIVE_FAIL,
-      RESOLVE_MAX,  // Bounding value.
-    };
-    Category category = RESOLVE_MAX;  // Illegal value for later DCHECK only.
-
     base::TimeDelta duration = base::TimeTicks::Now() - start_time;
-    if (error == OK) {
-      if (had_non_speculative_request_) {
-        category = RESOLVE_SUCCESS;
-        UMA_HISTOGRAM_LONG_TIMES_100("DNS.ResolveSuccess", duration);
-      } else {
-        category = RESOLVE_SPECULATIVE_SUCCESS;
-        UMA_HISTOGRAM_LONG_TIMES_100("DNS.ResolveSpeculativeSuccess", duration);
-      }
+    if (error == OK)
+      UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ProcTask.SuccessTime", duration);
+    else
+      UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ProcTask.FailureTime", duration);
 
-      // Log DNS lookups based on |address_family|. This will help us determine
-      // if IPv4 or IPv4/6 lookups are faster or slower.
-      switch (key_.address_family) {
-        case ADDRESS_FAMILY_IPV4:
-          UMA_HISTOGRAM_LONG_TIMES_100("DNS.ResolveSuccess_FAMILY_IPV4",
-                                       duration);
-          break;
-        case ADDRESS_FAMILY_IPV6:
-          UMA_HISTOGRAM_LONG_TIMES_100("DNS.ResolveSuccess_FAMILY_IPV6",
-                                       duration);
-          break;
-        case ADDRESS_FAMILY_UNSPECIFIED:
-          UMA_HISTOGRAM_LONG_TIMES_100("DNS.ResolveSuccess_FAMILY_UNSPEC",
-                                       duration);
-          break;
-      }
-    } else {
-      if (had_non_speculative_request_) {
-        category = RESOLVE_FAIL;
-        UMA_HISTOGRAM_LONG_TIMES_100("DNS.ResolveFail", duration);
-      } else {
-        category = RESOLVE_SPECULATIVE_FAIL;
-        UMA_HISTOGRAM_LONG_TIMES_100("DNS.ResolveSpeculativeFail", duration);
-      }
-      // Log DNS lookups based on |address_family|. This will help us determine
-      // if IPv4 or IPv4/6 lookups are faster or slower.
-      switch (key_.address_family) {
-        case ADDRESS_FAMILY_IPV4:
-          UMA_HISTOGRAM_LONG_TIMES_100("DNS.ResolveFail_FAMILY_IPV4", duration);
-          break;
-        case ADDRESS_FAMILY_IPV6:
-          UMA_HISTOGRAM_LONG_TIMES_100("DNS.ResolveFail_FAMILY_IPV6", duration);
-          break;
-        case ADDRESS_FAMILY_UNSPECIFIED:
-          UMA_HISTOGRAM_LONG_TIMES_100("DNS.ResolveFail_FAMILY_UNSPEC",
-                                       duration);
-          break;
-      }
-      UMA_HISTOGRAM_CUSTOM_ENUMERATION(kOSErrorsForGetAddrinfoHistogramName,
-                                       std::abs(os_error),
-                                       GetAllGetAddrinfoOSErrors());
-    }
-    DCHECK_LT(static_cast<int>(category),
-              static_cast<int>(RESOLVE_MAX));  // Be sure it was set.
-
-    UMA_HISTOGRAM_ENUMERATION("DNS.ResolveCategory", category, RESOLVE_MAX);
+    UMA_HISTOGRAM_CUSTOM_ENUMERATION(kOSErrorsForGetAddrinfoHistogramName,
+                                     std::abs(os_error),
+                                     GetAllGetAddrinfoOSErrors());
   }
 
   void RecordAttemptHistograms(const base::TimeTicks& start_time,
@@ -1017,12 +952,6 @@
   // The time when retry attempt was finished.
   base::TimeTicks retry_attempt_finished_time_;
 
-  // True if a non-speculative request was ever attached to this job
-  // (regardless of whether or not it was later canceled.
-  // This boolean is used for histogramming the duration of jobs used to
-  // service non-speculative requests.
-  bool had_non_speculative_request_;
-
   AddressList results_;
 
   NetLogWithSource net_log_;
@@ -1351,12 +1280,8 @@
         base::Bind(&NetLogJobAttachCallback, request->source_net_log().source(),
                    priority()));
 
-    // TODO(szym): Check if this is still needed.
-    if (!request->info().is_speculative()) {
+    if (!request->info().is_speculative())
       had_non_speculative_request_ = true;
-      if (proc_task_.get())
-        proc_task_->set_had_non_speculative_request();
-    }
 
     requests_.push_back(request);
 
@@ -1533,20 +1458,14 @@
 
     had_dns_config_ = resolver_->HaveDnsConfig();
 
-    base::TimeTicks now = base::TimeTicks::Now();
-    base::TimeDelta queue_time = now - creation_time_;
-    base::TimeDelta queue_time_after_change = now - priority_change_time_;
+    start_time_ = base::TimeTicks::Now();
+    base::TimeDelta queue_time = start_time_ - creation_time_;
+    base::TimeDelta queue_time_after_change =
+        start_time_ - priority_change_time_;
 
-    if (had_dns_config_) {
-      DNS_HISTOGRAM_BY_PRIORITY("AsyncDNS.JobQueueTime", priority(),
-                                queue_time);
-      DNS_HISTOGRAM_BY_PRIORITY("AsyncDNS.JobQueueTimeAfterChange", priority(),
-                                queue_time_after_change);
-    } else {
-      DNS_HISTOGRAM_BY_PRIORITY("DNS.JobQueueTime", priority(), queue_time);
-      DNS_HISTOGRAM_BY_PRIORITY("DNS.JobQueueTimeAfterChange", priority(),
-                                queue_time_after_change);
-    }
+    DNS_HISTOGRAM_BY_PRIORITY("Net.DNS.JobQueueTime", priority(), queue_time);
+    DNS_HISTOGRAM_BY_PRIORITY("Net.DNS.JobQueueTimeAfterChange", priority(),
+                              queue_time_after_change);
 
     bool system_only =
         (key_.host_resolver_flags & HOST_RESOLVER_SYSTEM_ONLY) != 0;
@@ -1572,8 +1491,6 @@
                                 base::Unretained(this), base::TimeTicks::Now()),
                      net_log_);
 
-    if (had_non_speculative_request_)
-      proc_task_->set_had_non_speculative_request();
     // Start() could be called from within Resolve(), hence it must NOT directly
     // call OnProcTaskComplete, for example, on synchronous failure.
     proc_task_->Start();
@@ -1595,7 +1512,7 @@
         } else {
           UmaAsyncDnsResolveStatus(RESOLVE_STATUS_PROC_SUCCESS);
         }
-        UMA_HISTOGRAM_SPARSE_SLOWLY("AsyncDNS.ResolveError",
+        UMA_HISTOGRAM_SPARSE_SLOWLY("Net.DNS.DnsTask.Errors",
                                     std::abs(dns_task_error_));
         resolver_->OnDnsTaskResolve(dns_task_error_);
       } else {
@@ -1638,7 +1555,7 @@
   void OnDnsTaskFailure(const base::WeakPtr<DnsTask>& dns_task,
                         base::TimeDelta duration,
                         int net_error) {
-    UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.ResolveFail", duration);
+    UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.DnsTask.FailureTime", duration);
 
     if (!dns_task)
       return;
@@ -1673,22 +1590,8 @@
       OnDnsTaskFailure(dns_task_->AsWeakPtr(), duration, net_error);
       return;
     }
-    UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.ResolveSuccess", duration);
-    // Log DNS lookups based on |address_family|.
-    switch (key_.address_family) {
-      case ADDRESS_FAMILY_IPV4:
-        UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.ResolveSuccess_FAMILY_IPV4",
-                                     duration);
-        break;
-      case ADDRESS_FAMILY_IPV6:
-        UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.ResolveSuccess_FAMILY_IPV6",
-                                     duration);
-        break;
-      case ADDRESS_FAMILY_UNSPECIFIED:
-        UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.ResolveSuccess_FAMILY_UNSPEC",
-                                     duration);
-        break;
-    }
+
+    UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.DnsTask.SuccessTime", duration);
 
     UmaAsyncDnsResolveStatus(RESOLVE_STATUS_DNS_SUCCESS);
     RecordTTL(ttl);
@@ -1719,6 +1622,69 @@
       dns_task_->StartSecondTransaction();
   }
 
+  void RecordJobHistograms(int error) {
+    enum Category {  // Used in UMA_HISTOGRAM_ENUMERATION.
+      RESOLVE_SUCCESS,
+      RESOLVE_FAIL,
+      RESOLVE_SPECULATIVE_SUCCESS,
+      RESOLVE_SPECULATIVE_FAIL,
+      RESOLVE_MAX,  // Bounding value.
+    };
+    Category category = RESOLVE_MAX;  // Illegal value for later DCHECK only.
+
+    base::TimeDelta duration = base::TimeTicks::Now() - start_time_;
+    if (error == OK) {
+      if (had_non_speculative_request_) {
+        category = RESOLVE_SUCCESS;
+        UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime", duration);
+        switch (key_.address_family) {
+          case ADDRESS_FAMILY_IPV4:
+            UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime.IPV4",
+                                         duration);
+            break;
+          case ADDRESS_FAMILY_IPV6:
+            UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime.IPV6",
+                                         duration);
+            break;
+          case ADDRESS_FAMILY_UNSPECIFIED:
+            UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime.UNSPEC",
+                                         duration);
+            break;
+        }
+      } else {
+        category = RESOLVE_SPECULATIVE_SUCCESS;
+        UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime.Speculative",
+                                     duration);
+      }
+    } else {
+      if (had_non_speculative_request_) {
+        category = RESOLVE_FAIL;
+        UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveFailureTime", duration);
+        switch (key_.address_family) {
+          case ADDRESS_FAMILY_IPV4:
+            UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime.IPV4",
+                                         duration);
+            break;
+          case ADDRESS_FAMILY_IPV6:
+            UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime.IPV6",
+                                         duration);
+            break;
+          case ADDRESS_FAMILY_UNSPECIFIED:
+            UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime.UNSPEC",
+                                         duration);
+            break;
+        }
+      } else {
+        category = RESOLVE_SPECULATIVE_FAIL;
+        UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveFailureTime.Speculative",
+                                     duration);
+      }
+    }
+    DCHECK_LT(static_cast<int>(category),
+              static_cast<int>(RESOLVE_MAX));  // Be sure it was set.
+    UMA_HISTOGRAM_ENUMERATION("Net.DNS.ResolveCategory", category, RESOLVE_MAX);
+  }
+
   // Performs Job's last rites. Completes all Requests. Deletes this.
   void CompleteRequests(const HostCache::Entry& entry,
                         base::TimeDelta ttl) {
@@ -1770,8 +1736,10 @@
 
     bool did_complete = (entry.error() != ERR_NETWORK_CHANGED) &&
                         (entry.error() != ERR_HOST_RESOLVER_QUEUE_TOO_LARGE);
-    if (did_complete)
+    if (did_complete) {
       resolver_->CacheResult(key_, entry, ttl);
+      RecordJobHistograms(entry.error());
+    }
 
     // Complete all of the requests that were attached to the job and
     // detach them.
@@ -1783,7 +1751,7 @@
       LogFinishRequest(req->source_net_log(), req->info(), entry.error());
       if (did_complete) {
         // Record effective total time from creation to completion.
-        RecordTotalTime(had_dns_config_, req->info().is_speculative(),
+        RecordTotalTime(req->info().is_speculative(), false,
                         base::TimeTicks::Now() - req->request_time());
       }
       req->OnJobCompleted(this, entry.error(), entry.addresses());
@@ -1834,6 +1802,7 @@
 
   const base::TimeTicks creation_time_;
   base::TimeTicks priority_change_time_;
+  base::TimeTicks start_time_;
 
   NetLogWithSource net_log_;
 
@@ -1907,7 +1876,7 @@
   int rv = ResolveHelper(info, false, nullptr, source_net_log, addresses, &key);
   if (rv != ERR_DNS_CACHE_MISS) {
     LogFinishRequest(source_net_log, info, rv);
-    RecordTotalTime(HaveDnsConfig(), info.is_speculative(), base::TimeDelta());
+    RecordTotalTime(info.is_speculative(), true, base::TimeDelta());
     return rv;
   }
 
diff --git a/net/http/http_auth_controller.h b/net/http/http_auth_controller.h
index 4c0ba17..64e40cc 100644
--- a/net/http/http_auth_controller.h
+++ b/net/http/http_auth_controller.h
@@ -28,11 +28,21 @@
 struct HttpRequestInfo;
 class SSLInfo;
 
+// HttpAuthController is interface between other classes and HttpAuthHandlers.
+// It handles all challenges when attempting to make a single request to a
+// server, both in the case of trying multiple sets of credentials (Possibly on
+// different sockets), and when going through multiple rounds of auth with
+// connection-based auth, creating new HttpAuthHandlers as necessary.
+//
+// It is unaware of when a round of auth uses a new socket, which can lead to
+// problems for connection-based auth.
 class NET_EXPORT_PRIVATE HttpAuthController
     : public base::RefCounted<HttpAuthController> {
  public:
   // The arguments are self explanatory except possibly for |auth_url|, which
   // should be both the auth target and auth path in a single url argument.
+  // |target| indicates whether this is for authenticating with a proxy or
+  // destination server.
   HttpAuthController(HttpAuth::Target target,
                      const GURL& auth_url,
                      HttpAuthCache* http_auth_cache,
diff --git a/net/http/http_auth_handler.h b/net/http/http_auth_handler.h
index 8d521b4..b0ab3400 100644
--- a/net/http/http_auth_handler.h
+++ b/net/http/http_auth_handler.h
@@ -21,6 +21,14 @@
 // HttpAuthHandler is the interface for the authentication schemes
 // (basic, digest, NTLM, Negotiate).
 // HttpAuthHandler objects are typically created by an HttpAuthHandlerFactory.
+//
+// HttpAuthHandlers and generally created and managed by an HttpAuthController,
+// which is the interaction point between the rest of net and the HTTP auth
+// code.
+//
+// For connection-based authentication, an HttpAuthHandler handles all rounds
+// related to using a single identity. If the identity is rejected, a new
+// HttpAuthHandler must be created.
 class NET_EXPORT_PRIVATE HttpAuthHandler {
  public:
   HttpAuthHandler();
@@ -122,8 +130,16 @@
     return (properties_ & IS_CONNECTION_BASED) != 0;
   }
 
-  // Returns true if the response to the current authentication challenge
-  // requires an identity.
+  // If NeedsIdentity() returns true, then a subsequent call to
+  // GenerateAuthToken() must indicate which identity to use. This can be done
+  // either by passing in a non-empty set of credentials, or an empty set to
+  // force the handler to use the default credentials. The latter is only an
+  // option if AllowsDefaultCredentials() returns true.
+  //
+  // If NeedsIdentity() returns false, then the handler is already bound to an
+  // identity and GenerateAuthToken() will ignore any credentials that are
+  // passed in.
+  //
   // TODO(wtc): Find a better way to handle a multi-round challenge-response
   // sequence used by a connection-based authentication scheme.
   virtual bool NeedsIdentity();
diff --git a/net/http/http_auth_handler_factory.cc b/net/http/http_auth_handler_factory.cc
index cf3c32f3..97f3f2f7 100644
--- a/net/http/http_auth_handler_factory.cc
+++ b/net/http/http_auth_handler_factory.cc
@@ -7,6 +7,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
+#include "build/build_config.h"
 #include "net/base/net_errors.h"
 #include "net/http/http_auth_challenge_tokenizer.h"
 #include "net/http/http_auth_filter.h"
@@ -87,10 +88,12 @@
         new HttpAuthHandlerNegotiate::Factory();
 #if defined(OS_WIN)
     negotiate_factory->set_library(std::make_unique<SSPILibraryDefault>());
-#elif defined(OS_POSIX) && !defined(OS_ANDROID)
+#elif defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
     negotiate_factory->set_library(
         std::make_unique<GSSAPISharedLibrary>(prefs.GssapiLibraryName()));
-#endif  // defined(OS_POSIX) && !defined(OS_ANDROID)
+#elif defined(OS_CHROMEOS)
+    negotiate_factory->set_library(std::make_unique<GSSAPISharedLibrary>(""));
+#endif
     negotiate_factory->set_host_resolver(host_resolver);
     registry_factory->RegisterSchemeFactory(kNegotiateAuthScheme,
                                             negotiate_factory);
@@ -142,7 +145,7 @@
   std::vector<std::string> auth_types(std::begin(kDefaultAuthSchemes),
                                       std::end(kDefaultAuthSchemes));
   HttpAuthPreferences prefs(auth_types
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
                             ,
                             std::string()
 #endif
diff --git a/net/http/http_auth_handler_ntlm.h b/net/http/http_auth_handler_ntlm.h
index fe12132..0ab8d95 100644
--- a/net/http/http_auth_handler_ntlm.h
+++ b/net/http/http_auth_handler_ntlm.h
@@ -72,6 +72,10 @@
   };
 
 #if defined(NTLM_PORTABLE)
+  // A function that returns the time as the number of 100 nanosecond ticks
+  // since Jan 1, 1601 (UTC).
+  typedef uint64_t (*GetMSTimeProc)();
+
   // A function that generates n random bytes in the output buffer.
   typedef void (*GenerateRandomProc)(uint8_t* output, size_t n);
 
@@ -83,18 +87,22 @@
   // GetHostName functions.
   class ScopedProcSetter {
    public:
-    ScopedProcSetter(GenerateRandomProc random_proc,
+    ScopedProcSetter(GetMSTimeProc ms_time_proc,
+                     GenerateRandomProc random_proc,
                      HostNameProc host_name_proc) {
+      old_ms_time_proc_ = SetGetMSTimeProc(ms_time_proc);
       old_random_proc_ = SetGenerateRandomProc(random_proc);
       old_host_name_proc_ = SetHostNameProc(host_name_proc);
     }
 
     ~ScopedProcSetter() {
+      SetGetMSTimeProc(old_ms_time_proc_);
       SetGenerateRandomProc(old_random_proc_);
       SetHostNameProc(old_host_name_proc_);
     }
 
    private:
+    GetMSTimeProc old_ms_time_proc_;
     GenerateRandomProc old_random_proc_;
     HostNameProc old_host_name_proc_;
   };
@@ -132,8 +140,9 @@
   ~HttpAuthHandlerNTLM() override;
 
 #if defined(NTLM_PORTABLE)
-  // For unit tests to override the GenerateRandom and GetHostName functions.
-  // Returns the old function.
+  // For unit tests to override the GetMSTime, GenerateRandom and GetHostName
+  // functions. Returns the old function.
+  static GetMSTimeProc SetGetMSTimeProc(GetMSTimeProc proc);
   static GenerateRandomProc SetGenerateRandomProc(GenerateRandomProc proc);
   static HostNameProc SetHostNameProc(HostNameProc proc);
 
@@ -156,6 +165,7 @@
 #endif
 
 #if defined(NTLM_PORTABLE)
+  static GetMSTimeProc get_ms_time_proc_;
   static GenerateRandomProc generate_random_proc_;
   static HostNameProc get_host_name_proc_;
 #endif
diff --git a/net/http/http_auth_handler_ntlm_portable.cc b/net/http/http_auth_handler_ntlm_portable.cc
index 97627f63..fe94357 100644
--- a/net/http/http_auth_handler_ntlm_portable.cc
+++ b/net/http/http_auth_handler_ntlm_portable.cc
@@ -5,6 +5,7 @@
 #include "net/http/http_auth_handler_ntlm.h"
 
 #include "base/rand_util.h"
+#include "base/time/time.h"
 #include "net/base/net_errors.h"
 #include "net/base/network_interfaces.h"
 
@@ -12,6 +13,10 @@
 
 namespace {
 
+uint64_t GetMSTime() {
+  return base::Time::Now().since_origin().InMicroseconds() * 10;
+}
+
 void GenerateRandom(uint8_t* output, size_t n) {
   base::RandBytes(output, n);
 }
@@ -19,6 +24,10 @@
 }  // namespace
 
 // static
+HttpAuthHandlerNTLM::GetMSTimeProc HttpAuthHandlerNTLM::get_ms_time_proc_ =
+    GetMSTime;
+
+// static
 HttpAuthHandlerNTLM::GenerateRandomProc
     HttpAuthHandlerNTLM::generate_random_proc_ = GenerateRandom;
 
@@ -26,7 +35,8 @@
 HttpAuthHandlerNTLM::HostNameProc HttpAuthHandlerNTLM::get_host_name_proc_ =
     GetHostName;
 
-HttpAuthHandlerNTLM::HttpAuthHandlerNTLM() : ntlm_client_() {}
+HttpAuthHandlerNTLM::HttpAuthHandlerNTLM()
+    : ntlm_client_(ntlm::NtlmFeatures(false)) {}
 
 bool HttpAuthHandlerNTLM::NeedsIdentity() {
   // This gets called for each round-trip.  Only require identity on
@@ -48,6 +58,14 @@
 HttpAuthHandlerNTLM::~HttpAuthHandlerNTLM() {}
 
 // static
+HttpAuthHandlerNTLM::GetMSTimeProc HttpAuthHandlerNTLM::SetGetMSTimeProc(
+    GetMSTimeProc proc) {
+  GetMSTimeProc old_proc = get_ms_time_proc_;
+  get_ms_time_proc_ = proc;
+  return old_proc;
+}
+
+// static
 HttpAuthHandlerNTLM::GenerateRandomProc
 HttpAuthHandlerNTLM::SetGenerateRandomProc(GenerateRandomProc proc) {
   GenerateRandomProc old_proc = generate_random_proc_;
@@ -80,10 +98,12 @@
     return ntlm::Buffer();
   uint8_t client_challenge[8];
   generate_random_proc_(client_challenge, 8);
+  uint64_t client_time = get_ms_time_proc_();
 
   return ntlm_client_.GenerateAuthenticateMessage(
       domain_, credentials_.username(), credentials_.password(), hostname,
-      client_challenge, in_token);
+      channel_bindings_, CreateSPN(origin_), client_time, client_challenge,
+      in_token);
 }
 
 int HttpAuthHandlerNTLM::Factory::CreateAuthHandler(
diff --git a/net/http/http_auth_handler_ntlm_portable_unittest.cc b/net/http/http_auth_handler_ntlm_portable_unittest.cc
index 2f3ffcb..66fbbf7 100644
--- a/net/http/http_auth_handler_ntlm_portable_unittest.cc
+++ b/net/http/http_auth_handler_ntlm_portable_unittest.cc
@@ -142,6 +142,11 @@
     memset(output, 0xaa, n);
   }
 
+  static uint64_t MockGetMSTime() {
+    // Tue, 23 May 2017 20:13:07 +0000
+    return 131400439870000000;
+  }
+
   static std::string MockGetHostName() { return ntlm::test::kHostnameAscii; }
 
  private:
@@ -205,373 +210,27 @@
             HandleAnotherChallenge("Negotiate SSdtIG5vdCBhIHJlYWwgdG9rZW4h"));
 }
 
-TEST_F(HttpAuthHandlerNtlmPortableTest, MinimalStructurallyValidType2) {
-  ASSERT_EQ(OK, CreateHandler());
-  ASSERT_EQ(OK, GetGenerateAuthTokenResult());
-  ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
-            HandleAnotherChallenge(CreateNtlmAuthHeader(
-                ntlm::test::kMinChallengeMessage, ntlm::kChallengeHeaderLen)));
-  ASSERT_EQ(OK, GetGenerateAuthTokenResult());
-}
-
-TEST_F(HttpAuthHandlerNtlmPortableTest, Type2MessageTooShort) {
-  ASSERT_EQ(OK, CreateHandler());
-  ASSERT_EQ(OK, GetGenerateAuthTokenResult());
-
-  uint8_t raw[31];
-  memcpy(raw, ntlm::test::kMinChallengeMessage, 31);
-
-  // Fail because the minimum size valid message is 32 bytes.
-  ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
-            HandleAnotherChallenge(CreateNtlmAuthHeader(raw, arraysize(raw))));
-  ASSERT_EQ(ERR_UNEXPECTED, GetGenerateAuthTokenResult());
-}
-
-TEST_F(HttpAuthHandlerNtlmPortableTest, Type2MessageWrongSignature) {
-  ASSERT_EQ(OK, CreateHandler());
-  ASSERT_EQ(OK, GetGenerateAuthTokenResult());
-
-  uint8_t raw[32];
-  memcpy(raw, ntlm::test::kMinChallengeMessage, 32);
-  // Modify the default valid message to overwrite the last byte of the
-  // signature.
-  raw[7] = 0xff;
-
-  // Fail because the first 8 bytes don't match "NTLMSSP\0"
-  ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
-            HandleAnotherChallenge(CreateNtlmAuthHeader(raw, arraysize(raw))));
-  ASSERT_EQ(ERR_UNEXPECTED, GetGenerateAuthTokenResult());
-}
-
-TEST_F(HttpAuthHandlerNtlmPortableTest, Type2WrongMessageType) {
-  ASSERT_EQ(OK, CreateHandler());
-  ASSERT_EQ(OK, GetGenerateAuthTokenResult());
-
-  uint8_t raw[32];
-  memcpy(raw, ntlm::test::kMinChallengeMessage, 32);
-  // Modify the message type so it is not 0x00000002
-  raw[8] = 0x03;
-
-  // Fail because the message type should be MessageType::kChallenge
-  // (0x00000002)
-  ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
-            HandleAnotherChallenge(CreateNtlmAuthHeader(raw, arraysize(raw))));
-  ASSERT_EQ(ERR_UNEXPECTED, GetGenerateAuthTokenResult());
-}
-
-TEST_F(HttpAuthHandlerNtlmPortableTest, Type2MessageWithNoTargetName) {
-  ASSERT_EQ(OK, CreateHandler());
-  ASSERT_EQ(OK, GetGenerateAuthTokenResult());
-
-  // The spec (2.2.1.2) states that the length SHOULD be 0 and the offset
-  // SHOULD be where the payload would be if it was present. This is the
-  // expected response from a compliant server when no target name is sent.
-  // In reality the offset should always be ignored if the length is zero.
-  // Also implementations often just write zeros.
-  uint8_t raw[32];
-  memcpy(raw, ntlm::test::kMinChallengeMessage, 32);
-  // Modify the default valid message to overwrite the offset to zero.
-  raw[16] = 0x00;
-
-  ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
-            HandleAnotherChallenge(CreateNtlmAuthHeader(raw, arraysize(raw))));
-  ASSERT_EQ(OK, GetGenerateAuthTokenResult());
-}
-
-TEST_F(HttpAuthHandlerNtlmPortableTest, Type2MessageWithTargetName) {
-  ASSERT_EQ(OK, CreateHandler());
-  ASSERT_EQ(OK, GetGenerateAuthTokenResult());
-
-  // One extra byte is provided for target name.
-  uint8_t raw[33];
-  memcpy(raw, ntlm::test::kMinChallengeMessage, 32);
-  // Modify the default valid message to indicate 1 byte is present in the
-  // target name payload.
-  raw[12] = 0x01;
-  raw[14] = 0x01;
-  // Put something in the target name.
-  raw[32] = 'Z';
-
-  ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
-            HandleAnotherChallenge(CreateNtlmAuthHeader(raw, arraysize(raw))));
-  ASSERT_EQ(OK, GetGenerateAuthTokenResult());
-}
-
-TEST_F(HttpAuthHandlerNtlmPortableTest, NoTargetNameOverflowFromOffset) {
-  ASSERT_EQ(OK, CreateHandler());
-  ASSERT_EQ(OK, GetGenerateAuthTokenResult());
-
-  uint8_t raw[32];
-  memcpy(raw, ntlm::test::kMinChallengeMessage, 32);
-  // Modify the default valid message to claim that the target name field is 1
-  // byte long overrunning the end of the message message.
-  raw[12] = 0x01;
-  raw[14] = 0x01;
-
-  // The above malformed message could cause an implementation to read outside
-  // the message buffer because the offset is past the end of the message.
-  // Verify it gets rejected.
-  ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
-            HandleAnotherChallenge(CreateNtlmAuthHeader(raw, arraysize(raw))));
-  ASSERT_EQ(ERR_UNEXPECTED, GetGenerateAuthTokenResult());
-}
-
-TEST_F(HttpAuthHandlerNtlmPortableTest, NoTargetNameOverflowFromLength) {
-  ASSERT_EQ(OK, CreateHandler());
-  ASSERT_EQ(OK, GetGenerateAuthTokenResult());
-
-  // Message has 1 extra byte of space after the header for the target name.
-  // One extra byte is provided for target name.
-  uint8_t raw[33];
-  memcpy(raw, ntlm::test::kMinChallengeMessage, 32);
-  // Modify the default valid message to indicate 2 bytes are present in the
-  // target name payload (however there is only space for 1).
-  raw[12] = 0x02;
-  raw[14] = 0x02;
-  // Put something in the target name.
-  raw[32] = 'Z';
-
-  // The above malformed message could cause an implementation to read outside
-  // the message buffer because the length is longer than available space.
-  // Verify it gets rejected.
-  ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
-            HandleAnotherChallenge(CreateNtlmAuthHeader(raw, arraysize(raw))));
-  ASSERT_EQ(ERR_UNEXPECTED, GetGenerateAuthTokenResult());
-}
-
-TEST_F(HttpAuthHandlerNtlmPortableTest, Type3RespectsUnicode) {
-  HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockRandom,
+TEST_F(HttpAuthHandlerNtlmPortableTest, NtlmV1AuthenticationSuccess) {
+  HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGetMSTime, MockRandom,
                                                     MockGetHostName);
   ASSERT_EQ(OK, CreateHandler());
   ASSERT_EQ(OK, GetGenerateAuthTokenResult());
 
-  // Generate the type 2 message from the server.
-  ntlm::NtlmBufferWriter writer(ntlm::kChallengeHeaderLen);
-  ASSERT_TRUE(writer.WriteMessageHeader(ntlm::MessageType::kChallenge));
-  // No target name. It is never used.
-  ASSERT_TRUE(writer.WriteSecurityBuffer(
-      ntlm::SecurityBuffer(ntlm::kChallengeHeaderLen, 0)));
-  // Set the unicode flag.
-  ASSERT_TRUE(writer.WriteFlags(ntlm::NegotiateFlags::kUnicode));
-
   std::string token;
   ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
-            HandleAnotherChallenge(CreateNtlmAuthHeader(writer.GetBuffer())));
+            HandleAnotherChallenge(
+                CreateNtlmAuthHeader(ntlm::test::kChallengeMsgV1,
+                                     arraysize(ntlm::test::kChallengeMsgV1))));
   ASSERT_EQ(OK, GenerateAuthToken(&token));
 
-  // Validate the type 3 message
+  // Validate the authenticate message
   std::string decoded;
   ASSERT_TRUE(DecodeChallenge(token, &decoded));
-  ntlm::NtlmBufferReader reader(decoded);
-  ASSERT_TRUE(reader.MatchMessageHeader(ntlm::MessageType::kAuthenticate));
-
-  // Skip the LM and NTLM Hash fields. This test isn't testing that.
-  ASSERT_TRUE(reader.SkipSecurityBufferWithValidation());
-  ASSERT_TRUE(reader.SkipSecurityBufferWithValidation());
-  base::string16 domain;
-  base::string16 username;
-  base::string16 hostname;
-  ReadString16Payload(&reader, &domain);
-  ASSERT_EQ(ntlm::test::kNtlmDomain, domain);
-  ReadString16Payload(&reader, &username);
-  ASSERT_EQ(ntlm::test::kUser, username);
-  ReadString16Payload(&reader, &hostname);
-  ASSERT_EQ(ntlm::test::kHostname, hostname);
-
-  // The session key is not used for the NTLM scheme in HTTP. Since
-  // NTLMSSP_NEGOTIATE_KEY_EXCH was not sent this is empty.
-  ASSERT_TRUE(reader.SkipSecurityBufferWithValidation());
-
-  // Verify the unicode flag is set.
-  ntlm::NegotiateFlags flags;
-  ASSERT_TRUE(reader.ReadFlags(&flags));
-  ASSERT_EQ(ntlm::NegotiateFlags::kUnicode,
-            flags & ntlm::NegotiateFlags::kUnicode);
-}
-
-TEST_F(HttpAuthHandlerNtlmPortableTest, Type3WithoutUnicode) {
-  HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockRandom,
-                                                    MockGetHostName);
-  ASSERT_EQ(OK, CreateHandler());
-  ASSERT_EQ(OK, GetGenerateAuthTokenResult());
-
-  // Generate the type 2 message from the server.
-  ntlm::NtlmBufferWriter writer(ntlm::kChallengeHeaderLen);
-  ASSERT_TRUE(writer.WriteMessageHeader(ntlm::MessageType::kChallenge));
-  // No target name. It is never used.
-  ASSERT_TRUE(writer.WriteSecurityBuffer(
-      ntlm::SecurityBuffer(ntlm::kChallengeHeaderLen, 0)));
-  // Set the OEM flag.
-  ASSERT_TRUE(writer.WriteFlags(ntlm::NegotiateFlags::kOem));
-
-  std::string token;
-  ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
-            HandleAnotherChallenge(CreateNtlmAuthHeader(writer.GetBuffer())));
-  ASSERT_EQ(OK, GenerateAuthToken(&token));
-
-  // Validate the type 3 message
-  std::string decoded;
-  ASSERT_TRUE(DecodeChallenge(token, &decoded));
-  ntlm::NtlmBufferReader reader(decoded);
-  ASSERT_TRUE(reader.MatchMessageHeader(ntlm::MessageType::kAuthenticate));
-
-  // Skip the 2 hash fields. This test isn't testing that.
-  ASSERT_TRUE(reader.SkipSecurityBufferWithValidation());
-  ASSERT_TRUE(reader.SkipSecurityBufferWithValidation());
-  std::string domain;
-  std::string username;
-  std::string hostname;
-  ASSERT_TRUE(ReadStringPayload(&reader, &domain));
-  ASSERT_EQ(ntlm::test::kNtlmDomainAscii, domain);
-  ASSERT_TRUE(ReadStringPayload(&reader, &username));
-  ASSERT_EQ(ntlm::test::kUserAscii, username);
-  ASSERT_TRUE(ReadStringPayload(&reader, &hostname));
-  ASSERT_EQ(ntlm::test::kHostnameAscii, hostname);
-
-  // The session key is not used for the NTLM scheme in HTTP. Since
-  // NTLMSSP_NEGOTIATE_KEY_EXCH was not sent this is empty.
-  ASSERT_TRUE(reader.SkipSecurityBufferWithValidation());
-
-  // Verify the unicode flag is not set and OEM flag is.
-  ntlm::NegotiateFlags flags;
-  ASSERT_TRUE(reader.ReadFlags(&flags));
-  ASSERT_EQ(ntlm::NegotiateFlags::kNone,
-            flags & ntlm::NegotiateFlags::kUnicode);
-  ASSERT_EQ(ntlm::NegotiateFlags::kOem, flags & ntlm::NegotiateFlags::kOem);
-}
-
-TEST_F(HttpAuthHandlerNtlmPortableTest, Type3UnicodeNoSessionSecurity) {
-  // Verify that the client won't be downgraded if the server clears
-  // the session security flag.
-  HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockRandom,
-                                                    MockGetHostName);
-  ASSERT_EQ(OK, CreateHandler());
-  ASSERT_EQ(OK, GetGenerateAuthTokenResult());
-
-  // Generate the type 2 message from the server.
-  ntlm::NtlmBufferWriter writer(ntlm::kChallengeHeaderLen);
-  ASSERT_TRUE(writer.WriteMessageHeader(ntlm::MessageType::kChallenge));
-  // No target name. It is never used.
-  ASSERT_TRUE(writer.WriteSecurityBuffer(
-      ntlm::SecurityBuffer(ntlm::kChallengeHeaderLen, 0)));
-  // Set the unicode but not the session security flag.
-  ASSERT_TRUE(writer.WriteFlags(ntlm::NegotiateFlags::kUnicode));
-
-  ASSERT_TRUE(
-      writer.WriteBytes(ntlm::test::kServerChallenge, ntlm::kChallengeLen));
-  ASSERT_TRUE(writer.IsEndOfBuffer());
-
-  std::string token;
-  ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
-            HandleAnotherChallenge(CreateNtlmAuthHeader(writer.GetBuffer())));
-  ASSERT_EQ(OK, GenerateAuthToken(&token));
-
-  // Validate the type 3 message
-  std::string decoded;
-  ASSERT_TRUE(DecodeChallenge(token, &decoded));
-  ntlm::NtlmBufferReader reader(decoded);
-  ASSERT_TRUE(reader.MatchMessageHeader(ntlm::MessageType::kAuthenticate));
-
-  // Read the LM and NTLM Response Payloads.
-  uint8_t actual_lm_response[ntlm::kResponseLenV1];
-  uint8_t actual_ntlm_response[ntlm::kResponseLenV1];
-  ASSERT_TRUE(
-      ReadBytesPayload(&reader, actual_lm_response, ntlm::kResponseLenV1));
-  ASSERT_TRUE(
-      ReadBytesPayload(&reader, actual_ntlm_response, ntlm::kResponseLenV1));
-
-  // Verify that the client still generated a response that uses
-  // session security.
-  ASSERT_EQ(0, memcmp(ntlm::test::kExpectedLmResponseWithV1SS,
-                      actual_lm_response, ntlm::kResponseLenV1));
-  ASSERT_EQ(0, memcmp(ntlm::test::kExpectedNtlmResponseWithV1SS,
-                      actual_ntlm_response, ntlm::kResponseLenV1));
-
-  base::string16 domain;
-  base::string16 username;
-  base::string16 hostname;
-  ReadString16Payload(&reader, &domain);
-  ASSERT_EQ(ntlm::test::kNtlmDomain, domain);
-  ReadString16Payload(&reader, &username);
-  ASSERT_EQ(ntlm::test::kUser, username);
-  ReadString16Payload(&reader, &hostname);
-  ASSERT_EQ(ntlm::test::kHostname, hostname);
-
-  // The session key is not used for the NTLM scheme in HTTP. Since
-  // NTLMSSP_NEGOTIATE_KEY_EXCH was not sent this is empty.
-  ASSERT_TRUE(reader.SkipSecurityBufferWithValidation());
-
-  // Verify the unicode flag is set.
-  ntlm::NegotiateFlags flags;
-  ASSERT_TRUE(reader.ReadFlags(&flags));
-  ASSERT_EQ(ntlm::NegotiateFlags::kUnicode,
-            flags & ntlm::NegotiateFlags::kUnicode);
-}
-
-TEST_F(HttpAuthHandlerNtlmPortableTest, Type3UnicodeWithSessionSecurity) {
-  HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockRandom,
-                                                    MockGetHostName);
-  ASSERT_EQ(OK, CreateHandler());
-  ASSERT_EQ(OK, GetGenerateAuthTokenResult());
-
-  // Generate the type 2 message from the server.
-  ntlm::NtlmBufferWriter writer(ntlm::kChallengeHeaderLen);
-  ASSERT_TRUE(writer.WriteMessageHeader(ntlm::MessageType::kChallenge));
-  // No target name. It is never used.
-  ASSERT_TRUE(writer.WriteSecurityBuffer(
-      ntlm::SecurityBuffer(ntlm::kChallengeHeaderLen, 0)));
-  // Set the unicode and session security flag.
-  ASSERT_TRUE(
-      writer.WriteFlags((ntlm::NegotiateFlags::kUnicode |
-                         ntlm::NegotiateFlags::kExtendedSessionSecurity)));
-
-  ASSERT_TRUE(
-      writer.WriteBytes(ntlm::test::kServerChallenge, ntlm::kChallengeLen));
-  ASSERT_TRUE(writer.IsEndOfBuffer());
-
-  std::string token;
-  ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
-            HandleAnotherChallenge(CreateNtlmAuthHeader(writer.GetBuffer())));
-  ASSERT_EQ(OK, GenerateAuthToken(&token));
-
-  // Validate the type 3 message
-  std::string decoded;
-  ASSERT_TRUE(DecodeChallenge(token, &decoded));
-  ntlm::NtlmBufferReader reader(decoded);
-  ASSERT_TRUE(reader.MatchMessageHeader(ntlm::MessageType::kAuthenticate));
-
-  // Read the LM and NTLM Response Payloads.
-  uint8_t actual_lm_response[ntlm::kResponseLenV1];
-  uint8_t actual_ntlm_response[ntlm::kResponseLenV1];
-  ASSERT_TRUE(
-      ReadBytesPayload(&reader, actual_lm_response, ntlm::kResponseLenV1));
-  ASSERT_TRUE(
-      ReadBytesPayload(&reader, actual_ntlm_response, ntlm::kResponseLenV1));
-
-  ASSERT_EQ(0, memcmp(ntlm::test::kExpectedLmResponseWithV1SS,
-                      actual_lm_response, ntlm::kResponseLenV1));
-  ASSERT_EQ(0, memcmp(ntlm::test::kExpectedNtlmResponseWithV1SS,
-                      actual_ntlm_response, ntlm::kResponseLenV1));
-
-  base::string16 domain;
-  base::string16 username;
-  base::string16 hostname;
-  ReadString16Payload(&reader, &domain);
-  ASSERT_EQ(ntlm::test::kNtlmDomain, domain);
-  ReadString16Payload(&reader, &username);
-  ASSERT_EQ(ntlm::test::kUser, username);
-  ReadString16Payload(&reader, &hostname);
-  ASSERT_EQ(ntlm::test::kHostname, hostname);
-
-  // The session key is not used for the NTLM scheme in HTTP. Since
-  // NTLMSSP_NEGOTIATE_KEY_EXCH was not sent this is empty.
-  ASSERT_TRUE(reader.SkipSecurityBufferWithValidation());
-
-  // Verify the unicode flag is set.
-  ntlm::NegotiateFlags flags;
-  ASSERT_TRUE(reader.ReadFlags(&flags));
-  ASSERT_EQ(ntlm::NegotiateFlags::kUnicode,
-            flags & ntlm::NegotiateFlags::kUnicode);
+  ASSERT_EQ(arraysize(ntlm::test::kExpectedAuthenticateMsgSpecResponseV1),
+            decoded.size());
+  ASSERT_EQ(0, memcmp(decoded.data(),
+                      ntlm::test::kExpectedAuthenticateMsgSpecResponseV1,
+                      decoded.size()));
 }
 
 }  // namespace net
diff --git a/net/http/http_auth_preferences.cc b/net/http/http_auth_preferences.cc
index c9b2d32..ba9198b 100644
--- a/net/http/http_auth_preferences.cc
+++ b/net/http/http_auth_preferences.cc
@@ -2,16 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/strings/string_split.h"
-#include "net/http/http_auth_filter.h"
 #include "net/http/http_auth_preferences.h"
+
+#include "base/strings/string_split.h"
+#include "build/build_config.h"
+#include "net/http/http_auth_filter.h"
 #include "net/http/url_security_manager.h"
 
 namespace net {
 
 HttpAuthPreferences::HttpAuthPreferences(
     const std::vector<std::string>& auth_schemes
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
     ,
     const std::string& gssapi_library_name
 #endif
@@ -23,7 +25,7 @@
     : auth_schemes_(auth_schemes.begin(), auth_schemes.end()),
       negotiate_disable_cname_lookup_(false),
       negotiate_enable_port_(false),
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
       gssapi_library_name_(gssapi_library_name),
 #endif
 #if defined(OS_CHROMEOS)
@@ -51,7 +53,7 @@
   return auth_android_negotiate_account_type_;
 }
 #endif
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
 std::string HttpAuthPreferences::GssapiLibraryName() const {
   return gssapi_library_name_;
 }
diff --git a/net/http/http_auth_preferences.h b/net/http/http_auth_preferences.h
index a77b193..b0deb56 100644
--- a/net/http/http_auth_preferences.h
+++ b/net/http/http_auth_preferences.h
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "base/macros.h"
+#include "build/build_config.h"
 #include "net/base/net_export.h"
 #include "url/gurl.h"
 
@@ -23,7 +24,7 @@
 class NET_EXPORT HttpAuthPreferences {
  public:
   HttpAuthPreferences(const std::vector<std::string>& auth_schemes
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
                       ,
                       const std::string& gssapi_library_name
 #endif
@@ -40,7 +41,7 @@
 #if defined(OS_ANDROID)
   virtual std::string AuthAndroidNegotiateAccountType() const;
 #endif
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
   virtual std::string GssapiLibraryName() const;
 #endif
 #if defined(OS_CHROMEOS)
@@ -78,7 +79,7 @@
 #if defined(OS_ANDROID)
   std::string auth_android_negotiate_account_type_;
 #endif
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
   // GSSAPI library name cannot change after startup, since changing it
   // requires unloading the existing GSSAPI library, which could cause all
   // sorts of problems for, for example, active Negotiate transactions.
diff --git a/net/http/http_auth_preferences_unittest.cc b/net/http/http_auth_preferences_unittest.cc
index f59f00f..174089c 100644
--- a/net/http/http_auth_preferences_unittest.cc
+++ b/net/http/http_auth_preferences_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
+#include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace net {
@@ -20,7 +21,7 @@
   std::vector<std::string> expected_schemes_vector(
       expected_schemes, expected_schemes + arraysize(expected_schemes));
   HttpAuthPreferences http_auth_preferences(expected_schemes_vector
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
                                             ,
                                             ""
 #endif
@@ -37,7 +38,7 @@
 TEST(HttpAuthPreferencesTest, DisableCnameLookup) {
   std::vector<std::string> auth_schemes;
   HttpAuthPreferences http_auth_preferences(auth_schemes
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
                                             ,
                                             ""
 #endif
@@ -54,7 +55,7 @@
 TEST(HttpAuthPreferencesTest, NegotiateEnablePort) {
   std::vector<std::string> auth_schemes;
   HttpAuthPreferences http_auth_preferences(auth_schemes
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
                                             ,
                                             ""
 #endif
@@ -72,7 +73,7 @@
 TEST(HttpAuthPreferencesTest, AuthAndroidhNegotiateAccountType) {
   std::vector<std::string> auth_schemes;
   HttpAuthPreferences http_auth_preferences(auth_schemes
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
                                             ,
                                             ""
 #endif
@@ -89,15 +90,10 @@
 }
 #endif
 
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
 TEST(HttpAuthPreferencesTest, GssApiLibraryName) {
   std::vector<std::string> AuthSchemes;
-  HttpAuthPreferences http_auth_preferences(AuthSchemes, "bar"
-#if defined(OS_CHROMEOS)
-                                            ,
-                                            true
-#endif
-                                            );
+  HttpAuthPreferences http_auth_preferences(AuthSchemes, "bar");
   EXPECT_EQ(std::string("bar"), http_auth_preferences.GssapiLibraryName());
 }
 #endif
@@ -105,7 +101,7 @@
 #if defined(OS_CHROMEOS)
 TEST(HttpAuthPreferencesTest, AllowGssapiLibraryLoadTrue) {
   std::vector<std::string> AuthSchemes;
-  HttpAuthPreferences http_auth_preferences(AuthSchemes, "foo", true);
+  HttpAuthPreferences http_auth_preferences(AuthSchemes, true);
   EXPECT_TRUE(http_auth_preferences.AllowGssapiLibraryLoad());
 }
 #endif
@@ -113,7 +109,7 @@
 #if defined(OS_CHROMEOS)
 TEST(HttpAuthPreferencesTest, AllowGssapiLibraryLoadFalse) {
   std::vector<std::string> AuthSchemes;
-  HttpAuthPreferences http_auth_preferences(AuthSchemes, "foo", false);
+  HttpAuthPreferences http_auth_preferences(AuthSchemes, false);
   EXPECT_FALSE(http_auth_preferences.AllowGssapiLibraryLoad());
 }
 #endif
@@ -121,7 +117,7 @@
 TEST(HttpAuthPreferencesTest, AuthServerWhitelist) {
   std::vector<std::string> auth_schemes;
   HttpAuthPreferences http_auth_preferences(auth_schemes
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
                                             ,
                                             ""
 #endif
@@ -139,7 +135,7 @@
 TEST(HttpAuthPreferencesTest, AuthDelegateWhitelist) {
   std::vector<std::string> auth_schemes;
   HttpAuthPreferences http_auth_preferences(auth_schemes
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
                                             ,
                                             ""
 #endif
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index 934ba683..ee26dc1a8 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -115,6 +115,7 @@
       retry_without_alt_svc_on_quic_errors(false),
       quic_idle_connection_timeout_seconds(kIdleConnectionTimeoutSeconds),
       quic_reduced_ping_timeout_seconds(kPingTimeoutSecs),
+      quic_connect_using_default_network(false),
       quic_migrate_sessions_on_network_change(false),
       quic_migrate_sessions_early(false),
       quic_allow_server_migration(false),
@@ -189,6 +190,7 @@
           params.mark_quic_broken_when_network_blackholes,
           params.quic_idle_connection_timeout_seconds,
           params.quic_reduced_ping_timeout_seconds,
+          params.quic_connect_using_default_network,
           params.quic_migrate_sessions_on_network_change,
           params.quic_migrate_sessions_early,
           params.quic_allow_server_migration,
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index 2d9e5cd..c6501bb7 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -149,6 +149,8 @@
     // Specifies the reduced ping timeout subsequent connections should use when
     // a connection was timed out with open streams.
     int quic_reduced_ping_timeout_seconds;
+    // If true, QUIC will attempt to explicitly use default network for sockets.
+    bool quic_connect_using_default_network;
     // If true, active QUIC sessions may be migrated onto a new network when
     // the platform indicates that the default network is changing.
     bool quic_migrate_sessions_on_network_change;
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index e5d7fcd..15f0830 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -648,6 +648,11 @@
 }
 
 #if defined(NTLM_PORTABLE)
+uint64_t MockGetMSTime() {
+  // Tue, 23 May 2017 20:13:07 +0000
+  return 131400439870000000;
+}
+
 // Alternative functions that eliminate randomness and dependency on the local
 // host name so that the generated NTLM messages are reproducible.
 void MockGenerateRandom(uint8_t* output, size_t n) {
@@ -5948,8 +5953,8 @@
   // to other auth schemes.
   request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
 
-  HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom,
-                                                    MockGetHostName);
+  HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
+      MockGetMSTime, MockGenerateRandom, MockGetHostName);
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
 
   // Generate the NTLM messages based on known test data.
@@ -5967,8 +5972,9 @@
                      &challenge_msg);
   base::Base64Encode(
       base::StringPiece(
-          reinterpret_cast<const char*>(ntlm::test::kExpectedAuthenticateMsgV1),
-          arraysize(ntlm::test::kExpectedAuthenticateMsgV1)),
+          reinterpret_cast<const char*>(
+              ntlm::test::kExpectedAuthenticateMsgSpecResponseV1),
+          arraysize(ntlm::test::kExpectedAuthenticateMsgSpecResponseV1)),
       &authenticate_msg);
 
   MockWrite data_writes1[] = {
@@ -6097,8 +6103,8 @@
   request.method = "GET";
   request.url = GURL("https://172.22.68.17/kids/login.aspx");
 
-  HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom,
-                                                    MockGetHostName);
+  HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
+      MockGetMSTime, MockGenerateRandom, MockGetHostName);
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
 
   // Generate the NTLM messages based on known test data.
@@ -6116,8 +6122,9 @@
                      &challenge_msg);
   base::Base64Encode(
       base::StringPiece(
-          reinterpret_cast<const char*>(ntlm::test::kExpectedAuthenticateMsgV1),
-          arraysize(ntlm::test::kExpectedAuthenticateMsgV1)),
+          reinterpret_cast<const char*>(
+              ntlm::test::kExpectedAuthenticateMsgSpecResponseV1),
+          arraysize(ntlm::test::kExpectedAuthenticateMsgSpecResponseV1)),
       &authenticate_msg);
 
   // The authenticate message when |kWrongPassword| is sent.
@@ -6130,6 +6137,7 @@
   // 24 bytes (32 encoded chars) of the NTLM Response.
   ASSERT_EQ(authenticate_msg.length(),
             wrong_password_authenticate_msg.length());
+  ASSERT_EQ(authenticate_msg.length(), 200u);
   ASSERT_EQ(base::StringPiece(authenticate_msg.data(), 117),
             base::StringPiece(wrong_password_authenticate_msg.data(), 117));
   ASSERT_EQ(
@@ -6322,8 +6330,8 @@
 // Server requests NTLM authentication, which is not supported over HTTP/2.
 // Subsequent request with authorization header should be sent over HTTP/1.1.
 TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2) {
-  HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom,
-                                                    MockGetHostName);
+  HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
+      MockGetMSTime, MockGenerateRandom, MockGetHostName);
 
   const char* kUrl = "https://172.22.68.17/kids/login.aspx";
 
@@ -6360,8 +6368,9 @@
                      &challenge_msg);
   base::Base64Encode(
       base::StringPiece(
-          reinterpret_cast<const char*>(ntlm::test::kExpectedAuthenticateMsgV1),
-          arraysize(ntlm::test::kExpectedAuthenticateMsgV1)),
+          reinterpret_cast<const char*>(
+              ntlm::test::kExpectedAuthenticateMsgSpecResponseV1),
+          arraysize(ntlm::test::kExpectedAuthenticateMsgSpecResponseV1)),
       &authenticate_msg);
 
   // Retry with authorization header.
diff --git a/net/http/mock_allow_http_auth_preferences.cc b/net/http/mock_allow_http_auth_preferences.cc
index 37539e5..afa600d 100644
--- a/net/http/mock_allow_http_auth_preferences.cc
+++ b/net/http/mock_allow_http_auth_preferences.cc
@@ -3,12 +3,13 @@
 // found in the LICENSE file.
 
 #include "net/http/mock_allow_http_auth_preferences.h"
+#include "build/build_config.h"
 
 namespace net {
 
 MockAllowHttpAuthPreferences::MockAllowHttpAuthPreferences()
     : HttpAuthPreferences(std::vector<std::string>()
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
                               ,
                           std::string()
 #endif
diff --git a/net/ntlm/des.cc b/net/ntlm/des.cc
deleted file mode 100644
index 1967f66..0000000
--- a/net/ntlm/des.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (c) 2011 The Chromium 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/ntlm/des.h"
-
-#include "base/logging.h"
-#include "crypto/openssl_util.h"
-#include "third_party/boringssl/src/include/openssl/des.h"
-
-// The iOS version of DESEncrypt is our own code.
-// DESSetKeyParity and DESMakeKey are based on
-// mozilla/security/manager/ssl/src/nsNTLMAuthModule.cpp, CVS rev. 1.14.
-/* clang-format off */
-
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla.
- *
- * The Initial Developer of the Original Code is IBM Corporation.
- * Portions created by IBM Corporation are Copyright (C) 2003
- * IBM Corporation. All Rights Reserved.
- *
- * Contributor(s):
- *   Darin Fisher <darin@meer.net>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-// Set odd parity bit (in least significant bit position).
-static uint8_t DESSetKeyParity(uint8_t x) {
-  if ((((x >> 7) ^ (x >> 6) ^ (x >> 5) ^
-        (x >> 4) ^ (x >> 3) ^ (x >> 2) ^
-        (x >> 1)) & 0x01) == 0) {
-    x |= 0x01;
-  } else {
-    x &= 0xfe;
-  }
-  return x;
-}
-
-namespace net {
-
-void DESMakeKey(const uint8_t* raw, uint8_t* key) {
-  key[0] = DESSetKeyParity(raw[0]);
-  key[1] = DESSetKeyParity((raw[0] << 7) | (raw[1] >> 1));
-  key[2] = DESSetKeyParity((raw[1] << 6) | (raw[2] >> 2));
-  key[3] = DESSetKeyParity((raw[2] << 5) | (raw[3] >> 3));
-  key[4] = DESSetKeyParity((raw[3] << 4) | (raw[4] >> 4));
-  key[5] = DESSetKeyParity((raw[4] << 3) | (raw[5] >> 5));
-  key[6] = DESSetKeyParity((raw[5] << 2) | (raw[6] >> 6));
-  key[7] = DESSetKeyParity((raw[6] << 1));
-}
-
-void DESEncrypt(const uint8_t* key, const uint8_t* src, uint8_t* hash) {
-  crypto::EnsureOpenSSLInit();
-
-  DES_key_schedule ks;
-  DES_set_key(
-      reinterpret_cast<const DES_cblock*>(key), &ks);
-
-  DES_ecb_encrypt(reinterpret_cast<const DES_cblock*>(src),
-                  reinterpret_cast<DES_cblock*>(hash), &ks, DES_ENCRYPT);
-}
-
-}  // namespace net
diff --git a/net/ntlm/des.h b/net/ntlm/des.h
deleted file mode 100644
index 8540d62..0000000
--- a/net/ntlm/des.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_HTTP_DES_H_
-#define NET_HTTP_DES_H_
-
-#include <stdint.h>
-
-#include "net/base/net_export.h"
-
-namespace net {
-
-//-----------------------------------------------------------------------------
-// DES support code for NTLM authentication.
-//
-// TODO(wtc): Turn this into a C++ API and move it to the base module.
-
-// Build a 64-bit DES key from a 56-bit raw key.
-NET_EXPORT_PRIVATE void DESMakeKey(const uint8_t* raw, uint8_t* key);
-
-// Run the DES encryption algorithm in ECB mode on one block (8 bytes) of
-// data.  |key| is a DES key (8 bytes), |src| is the input plaintext (8
-// bytes), and |hash| is an 8-byte buffer receiving the output ciphertext.
-NET_EXPORT_PRIVATE void DESEncrypt(const uint8_t* key,
-                                   const uint8_t* src,
-                                   uint8_t* hash);
-
-}  // namespace net
-
-#endif  // NET_HTTP_DES_H_
diff --git a/net/ntlm/des_unittest.cc b/net/ntlm/des_unittest.cc
deleted file mode 100644
index d1f9ae5..0000000
--- a/net/ntlm/des_unittest.cc
+++ /dev/null
@@ -1,46 +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.
-
-#include <string.h>
-
-#include "net/ntlm/des.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace net {
-
-// This test vector comes from the NSS FIPS power-up self-test.
-TEST(DESTest, KnownAnswerTest1) {
-  // DES known key (56-bits).
-  static const uint8_t des_known_key[] = "ANSI DES";
-
-  // DES known plaintext (64-bits).
-  static const uint8_t des_ecb_known_plaintext[] = "Netscape";
-
-  // DES known ciphertext (64-bits).
-  static const uint8_t des_ecb_known_ciphertext[] = {0x26, 0x14, 0xe9, 0xc3,
-                                                     0x28, 0x80, 0x50, 0xb0};
-
-  uint8_t ciphertext[8];
-  memset(ciphertext, 0xaf, sizeof(ciphertext));
-
-  DESEncrypt(des_known_key, des_ecb_known_plaintext, ciphertext);
-  EXPECT_EQ(0, memcmp(ciphertext, des_ecb_known_ciphertext, 8));
-}
-
-// This test vector comes from NIST Special Publication 800-17, Modes of
-// Operation Validation System (MOVS): Requirements and Procedures, Appendix
-// A, page 124.
-TEST(DESTest, KnownAnswerTest2) {
-  static const uint8_t key[] = {0x10, 0x31, 0x6e, 0x02, 0x8c, 0x8f, 0x3b, 0x4a};
-  static const uint8_t plaintext[] = {0, 0, 0, 0, 0, 0, 0, 0};
-  static const uint8_t known_ciphertext[] = {0x82, 0xdc, 0xba, 0xfb,
-                                             0xde, 0xab, 0x66, 0x02};
-  uint8_t ciphertext[8];
-  memset(ciphertext, 0xaf, sizeof(ciphertext));
-
-  DESEncrypt(key, plaintext, ciphertext);
-  EXPECT_EQ(0, memcmp(ciphertext, known_ciphertext, 8));
-}
-
-}  // namespace net
diff --git a/net/ntlm/md4.cc b/net/ntlm/md4.cc
deleted file mode 100644
index 1ea35d1..0000000
--- a/net/ntlm/md4.cc
+++ /dev/null
@@ -1,193 +0,0 @@
-// This is mozilla/security/manager/ssl/src/md4.c, CVS rev. 1.1, with trivial
-// changes to port it to our source tree.
-//
-// WARNING: MD4 is cryptographically weak.  Do not use MD4 except in NTLM
-// authentication.
-
-/* clang-format off */
-/* vim:set ts=2 sw=2 et cindent: */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla.
- *
- * The Initial Developer of the Original Code is IBM Corporation.
- * Portions created by IBM Corporation are Copyright (C) 2003
- * IBM Corporation. All Rights Reserved.
- *
- * Contributor(s):
- *   Darin Fisher <darin@meer.net>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/*
- * "clean room" MD4 implementation (see RFC 1320)
- */
-
-#include "net/ntlm/md4.h"
-
-#include <string.h>
-
-typedef uint32_t Uint32;
-typedef uint8_t Uint8;
-
-/* the "conditional" function */
-#define F(x,y,z) (((x) & (y)) | (~(x) & (z)))
-
-/* the "majority" function */
-#define G(x,y,z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
-
-/* the "parity" function */
-#define H(x,y,z) ((x) ^ (y) ^ (z))
-
-/* rotate n-bits to the left */
-#define ROTL(x,n) (((x) << (n)) | ((x) >> (0x20 - n)))
-
-/* round 1: [abcd k s]: a = (a + F(b,c,d) + X[k]) <<< s */
-#define RD1(a,b,c,d,k,s) a += F(b,c,d) + X[k]; a = ROTL(a,s)
-
-/* round 2: [abcd k s]: a = (a + G(b,c,d) + X[k] + MAGIC) <<< s */
-#define RD2(a,b,c,d,k,s) a += G(b,c,d) + X[k] + 0x5A827999; a = ROTL(a,s)
-
-/* round 3: [abcd k s]: a = (a + H(b,c,d) + X[k] + MAGIC) <<< s */
-#define RD3(a,b,c,d,k,s) a += H(b,c,d) + X[k] + 0x6ED9EBA1; a = ROTL(a,s)
-
-/* converts from word array to byte array, len is number of bytes */
-static void w2b(Uint8 *out, const Uint32 *in, Uint32 len)
-{
-  Uint8 *bp; const Uint32 *wp, *wpend;
-
-  bp = out;
-  wp = in;
-  wpend = wp + (len >> 2);
-
-  for (; wp != wpend; ++wp, bp += 4)
-  {
-    bp[0] = (Uint8) ((*wp      ) & 0xFF);
-    bp[1] = (Uint8) ((*wp >>  8) & 0xFF);
-    bp[2] = (Uint8) ((*wp >> 16) & 0xFF);
-    bp[3] = (Uint8) ((*wp >> 24) & 0xFF);
-  }
-}
-
-/* converts from byte array to word array, len is number of bytes */
-static void b2w(Uint32 *out, const Uint8 *in, Uint32 len)
-{
-  Uint32 *wp; const Uint8 *bp, *bpend;
-
-  wp = out;
-  bp = in;
-  bpend = in + len;
-
-  for (; bp != bpend; bp += 4, ++wp)
-  {
-    *wp = (Uint32) (bp[0]      ) |
-          (Uint32) (bp[1] <<  8) |
-          (Uint32) (bp[2] << 16) |
-          (Uint32) (bp[3] << 24);
-  }
-}
-
-/* update state: data is 64 bytes in length */
-static void md4step(Uint32 state[4], const Uint8 *data)
-{
-  Uint32 A, B, C, D, X[16];
-
-  b2w(X, data, 64);
-
-  A = state[0];
-  B = state[1];
-  C = state[2];
-  D = state[3];
-
-  RD1(A,B,C,D, 0,3); RD1(D,A,B,C, 1,7); RD1(C,D,A,B, 2,11); RD1(B,C,D,A, 3,19);
-  RD1(A,B,C,D, 4,3); RD1(D,A,B,C, 5,7); RD1(C,D,A,B, 6,11); RD1(B,C,D,A, 7,19);
-  RD1(A,B,C,D, 8,3); RD1(D,A,B,C, 9,7); RD1(C,D,A,B,10,11); RD1(B,C,D,A,11,19);
-  RD1(A,B,C,D,12,3); RD1(D,A,B,C,13,7); RD1(C,D,A,B,14,11); RD1(B,C,D,A,15,19);
-
-  RD2(A,B,C,D, 0,3); RD2(D,A,B,C, 4,5); RD2(C,D,A,B, 8, 9); RD2(B,C,D,A,12,13);
-  RD2(A,B,C,D, 1,3); RD2(D,A,B,C, 5,5); RD2(C,D,A,B, 9, 9); RD2(B,C,D,A,13,13);
-  RD2(A,B,C,D, 2,3); RD2(D,A,B,C, 6,5); RD2(C,D,A,B,10, 9); RD2(B,C,D,A,14,13);
-  RD2(A,B,C,D, 3,3); RD2(D,A,B,C, 7,5); RD2(C,D,A,B,11, 9); RD2(B,C,D,A,15,13);
-
-  RD3(A,B,C,D, 0,3); RD3(D,A,B,C, 8,9); RD3(C,D,A,B, 4,11); RD3(B,C,D,A,12,15);
-  RD3(A,B,C,D, 2,3); RD3(D,A,B,C,10,9); RD3(C,D,A,B, 6,11); RD3(B,C,D,A,14,15);
-  RD3(A,B,C,D, 1,3); RD3(D,A,B,C, 9,9); RD3(C,D,A,B, 5,11); RD3(B,C,D,A,13,15);
-  RD3(A,B,C,D, 3,3); RD3(D,A,B,C,11,9); RD3(C,D,A,B, 7,11); RD3(B,C,D,A,15,15);
-
-  state[0] += A;
-  state[1] += B;
-  state[2] += C;
-  state[3] += D;
-}
-
-namespace net {
-namespace weak_crypto {
-
-void MD4Sum(const Uint8 *input, Uint32 inputLen, Uint8 *result)
-{
-  Uint8 final[128];
-  Uint32 i, n, m, state[4];
-  Uint32 inputLenArr[2];
-
-  /* magic initial states */
-  state[0] = 0x67452301;
-  state[1] = 0xEFCDAB89;
-  state[2] = 0x98BADCFE;
-  state[3] = 0x10325476;
-
-  /* compute number of complete 64-byte segments contained in input */
-  m = inputLen >> 6;
-
-  /* digest first m segments */
-  for (i=0; i<m; ++i)
-    md4step(state, (input + (i << 6)));
-
-  /* build final buffer */
-  n = inputLen % 64;
-  memcpy(final, input + (m << 6), n);
-  final[n] = 0x80;
-  memset(final + n + 1, 0, 120 - (n + 1));
-
-  // Store the length of the input in bits in two 32 bit values with the
-  // least significant word first in inputLenArr. w2b will then convert the
-  // 2x 32 bit values each to 4x bytes in little endian order. This results
-  // in writing 64 bits in little endian order.
-  //
-  // See the MD4Update function in RFC1320 Section A.1 (page 10).
-  inputLenArr[0] = static_cast<Uint32>(inputLen << 3);
-  inputLenArr[1] = static_cast<Uint32>(inputLen >> 29);
-  w2b(final + (n >= 56 ? 120 : 56), inputLenArr, 8);
-
-  md4step(state, final);
-  if (n >= 56)
-    md4step(state, final + 64);
-
-  /* copy state to result */
-  w2b(result, state, 16);
-}
-
-}  // namespace weak_crypto
-}  // namespace net
diff --git a/net/ntlm/md4.h b/net/ntlm/md4.h
deleted file mode 100644
index ee020ac..0000000
--- a/net/ntlm/md4.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// This is mozilla/security/manager/ssl/src/md4.h, CVS rev. 1.1, with trivial
-// changes to port it to our source tree.
-//
-// WARNING: MD4 is cryptographically weak.  Do not use MD4 except in NTLM
-// authentication.
-
-/* vim:set ts=2 sw=2 et cindent: */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla.
- *
- * The Initial Developer of the Original Code is IBM Corporation.
- * Portions created by IBM Corporation are Copyright (C) 2003
- * IBM Corporation. All Rights Reserved.
- *
- * Contributor(s):
- *   Darin Fisher <darin@meer.net>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef NET_HTTP_MD4_H_
-#define NET_HTTP_MD4_H_
-
-#include <stdint.h>
-
-#include "net/base/net_export.h"
-
-namespace net {
-namespace weak_crypto {
-
-/**
- * MD4Sum - computes the MD4 sum over the input buffer per RFC 1320
- *
- * @param input
- *        buffer containing input data
- * @param inputLen
- *        length of input buffer (number of bytes)
- * @param result
- *        16-byte buffer that will contain the MD4 sum upon return
- *
- * NOTE: MD4 is superceded by MD5.  do not use MD4 unless required by the
- * protocol you are implementing (e.g., NTLM requires MD4).
- *
- * NOTE: this interface is designed for relatively small buffers.  A streaming
- * interface would make more sense if that were a requirement.  Currently, this
- * is good enough for the applications we care about.
- */
-NET_EXPORT_PRIVATE void MD4Sum(const uint8_t* input,
-                               uint32_t inputLen,
-                               uint8_t* result);
-
-}  // namespace weak_crypto
-}  // namespace net
-
-#endif  // NET_HTTP_MD4_H_
diff --git a/net/ntlm/md4_unittest.cc b/net/ntlm/md4_unittest.cc
deleted file mode 100644
index b823b63..0000000
--- a/net/ntlm/md4_unittest.cc
+++ /dev/null
@@ -1,93 +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.
-
-// Test cases are from RFC 1320. https://tools.ietf.org/html/rfc1320
-
-#include "net/ntlm/md4.h"
-
-#include <string>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace net {
-namespace {
-
-void Md4String(const std::string& input, uint8_t* hash) {
-  weak_crypto::MD4Sum(reinterpret_cast<const uint8_t*>(input.data()),
-                      input.length(), hash);
-}
-
-}  // namespace
-
-TEST(Md4Test, RfcTest1_EmptyString) {
-  uint8_t actual_hash[16];
-  const uint8_t expected_hash[16] = {0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a,
-                                     0xe9, 0x31, 0xb7, 0x3c, 0x59, 0xd7,
-                                     0xe0, 0xc0, 0x89, 0xc0};
-  Md4String("", actual_hash);
-  ASSERT_EQ(0, memcmp(expected_hash, actual_hash, 16));
-}
-
-TEST(Md4Test, RfcTest2_OneChar) {
-  uint8_t actual_hash[16];
-  const uint8_t expected_hash[16] = {0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3,
-                                     0x3e, 0x46, 0x24, 0x5e, 0x05, 0xfb,
-                                     0xdb, 0xd6, 0xfb, 0x24};
-  Md4String("a", actual_hash);
-  ASSERT_EQ(0, memcmp(expected_hash, actual_hash, 16));
-}
-
-TEST(Md4Test, RfcTest3_Abc) {
-  uint8_t actual_hash[16];
-  const uint8_t expected_hash[16] = {0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21,
-                                     0xd8, 0x52, 0x5f, 0xc1, 0x0a, 0xe8,
-                                     0x7a, 0xa6, 0x72, 0x9d};
-  Md4String("abc", actual_hash);
-  ASSERT_EQ(0, memcmp(expected_hash, actual_hash, 16));
-}
-
-TEST(Md4Test, RfcTest4_MessageDigest) {
-  uint8_t actual_hash[16];
-  const uint8_t expected_hash[16] = {0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54,
-                                     0x9f, 0xe8, 0x18, 0x87, 0x48, 0x06,
-                                     0xe1, 0xc7, 0x01, 0x4b};
-  Md4String("message digest", actual_hash);
-  ASSERT_EQ(0, memcmp(expected_hash, actual_hash, 16));
-}
-
-TEST(Md4Test, RfcTest5_Alphabet) {
-  uint8_t actual_hash[16];
-  const uint8_t expected_hash[16] = {0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5,
-                                     0xbb, 0xcd, 0xee, 0xa8, 0xed, 0x63,
-                                     0xdf, 0x41, 0x2d, 0xa9};
-  Md4String("abcdefghijklmnopqrstuvwxyz", actual_hash);
-  ASSERT_EQ(0, memcmp(expected_hash, actual_hash, 16));
-}
-
-TEST(Md4Test, RfcTest6_Mod56CornerCase) {
-  uint8_t actual_hash[16];
-  const uint8_t expected_hash[16] = {0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41,
-                                     0xdb, 0x35, 0x1c, 0xe6, 0x27, 0xe1,
-                                     0x53, 0xe7, 0xf0, 0xe4};
-  // The string is 62 bytes long. Inputs where (len % 64 >= 56) == true
-  // hit a special case in the implementation.
-  Md4String("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
-            actual_hash);
-  ASSERT_EQ(0, memcmp(expected_hash, actual_hash, 16));
-}
-
-TEST(Md4Test, RfcTest7_LongerThanOneBlock) {
-  uint8_t actual_hash[16];
-  const uint8_t expected_hash[16] = {0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38,
-                                     0xf2, 0x19, 0x9c, 0x3e, 0x7b, 0x16,
-                                     0x4f, 0xcc, 0x05, 0x36};
-  // The string is 70 bytes long. MD4 processes data in 64 byte chunks.
-  Md4String(
-      "123456789012345678901234567890123456789012345678901234567890123456789012"
-      "34567890",
-      actual_hash);
-  ASSERT_EQ(0, memcmp(expected_hash, actual_hash, 16));
-}
-
-}  // namespace net
\ No newline at end of file
diff --git a/net/ntlm/ntlm.cc b/net/ntlm/ntlm.cc
index 14cc4bcd..4c1cab6 100644
--- a/net/ntlm/ntlm.cc
+++ b/net/ntlm/ntlm.cc
@@ -8,48 +8,203 @@
 
 #include "base/logging.h"
 #include "base/md5.h"
-#include "net/ntlm/des.h"
-#include "net/ntlm/md4.h"
+#include "base/strings/utf_string_conversions.h"
+#include "net/base/net_string_util.h"
 #include "net/ntlm/ntlm_buffer_writer.h"
+#include "third_party/boringssl/src/include/openssl/des.h"
+#include "third_party/boringssl/src/include/openssl/hmac.h"
+#include "third_party/boringssl/src/include/openssl/md4.h"
+#include "third_party/boringssl/src/include/openssl/md5.h"
 
 namespace net {
 namespace ntlm {
 
+namespace {
+
+// Takes the parsed target info in |av_pairs| and performs the following
+// actions.
+//
+// 1) If a |TargetInfoAvId::kTimestamp| AvPair exists, |server_timestamp|
+//    is set to the payload.
+// 2) If |is_mic_enabled| is true, the existing |TargetInfoAvId::kFlags| AvPair
+//    will have the |TargetInfoAvFlags::kMicPresent| bit set. If an existing
+//    flags AvPair does not already exist, a new one is added with the value of
+//    |TargetInfoAvFlags::kMicPresent|.
+// 3) If |is_epa_enabled| is true, two new AvPair entries will be added to
+//    |av_pairs|. The first will be of type |TargetInfoAvId::kChannelBindings|
+//    and contains MD5(|channel_bindings|) as the payload. The second will be
+//    of type |TargetInfoAvId::kTargetName| and contains |spn| as a little
+//    endian UTF16 string.
+// 4) Sets |target_info_len| to the size of |av_pairs| when serialized into
+//    a payload.
+void UpdateTargetInfoAvPairs(bool is_mic_enabled,
+                             bool is_epa_enabled,
+                             const std::string& channel_bindings,
+                             const std::string& spn,
+                             std::vector<AvPair>* av_pairs,
+                             uint64_t* server_timestamp,
+                             size_t* target_info_len) {
+  // Do a pass to update flags and calculate current length and
+  // pull out the server timestamp if it is there.
+  *server_timestamp = UINT64_MAX;
+  *target_info_len = 0;
+
+  bool need_flags_added = is_mic_enabled;
+  for (AvPair& pair : *av_pairs) {
+    *target_info_len += pair.avlen + kAvPairHeaderLen;
+    switch (pair.avid) {
+      case TargetInfoAvId::kFlags:
+        // The parsing phase already set the payload to the |flags| field.
+        if (is_mic_enabled) {
+          pair.flags = pair.flags | TargetInfoAvFlags::kMicPresent;
+        }
+
+        need_flags_added = false;
+        break;
+      case TargetInfoAvId::kTimestamp:
+        // The parsing phase already set the payload to the |timestamp| field.
+        *server_timestamp = pair.timestamp;
+        break;
+      case TargetInfoAvId::kEol:
+      case TargetInfoAvId::kChannelBindings:
+      case TargetInfoAvId::kTargetName:
+        // The terminator, |kEol|, should already have been removed from the
+        // end of the list and would have been rejected if it has been inside
+        // the list. Additionally |kChannelBindings| and |kTargetName| pairs
+        // would have been rejected during the initial parsing. See
+        // |NtlmBufferReader::ReadTargetInfo|.
+        NOTREACHED();
+        break;
+      default:
+        // Ignore entries we don't care about.
+        break;
+    }
+  }
+
+  if (need_flags_added) {
+    DCHECK(is_mic_enabled);
+    AvPair flags_pair(TargetInfoAvId::kFlags, sizeof(uint32_t));
+    flags_pair.flags = TargetInfoAvFlags::kMicPresent;
+
+    av_pairs->push_back(flags_pair);
+    *target_info_len += kAvPairHeaderLen + flags_pair.avlen;
+  }
+
+  if (is_epa_enabled) {
+    Buffer channel_bindings_hash(kChannelBindingsHashLen, 0);
+
+    // Hash the channel bindings if they exist otherwise they remain zeros.
+    if (!channel_bindings.empty()) {
+      GenerateChannelBindingHashV2(channel_bindings, &channel_bindings_hash[0]);
+    }
+
+    av_pairs->emplace_back(TargetInfoAvId::kChannelBindings,
+                           std::move(channel_bindings_hash));
+
+    // Convert the SPN to little endian unicode.
+    base::string16 spn16 = base::UTF8ToUTF16(spn);
+    NtlmBufferWriter spn_writer(spn16.length() * 2);
+    bool spn_writer_result =
+        spn_writer.WriteUtf16String(spn16) && spn_writer.IsEndOfBuffer();
+    DCHECK(spn_writer_result);
+
+    av_pairs->emplace_back(TargetInfoAvId::kTargetName, spn_writer.Pass());
+
+    // Add the length of the two new AV Pairs to the total length.
+    *target_info_len +=
+        (2 * kAvPairHeaderLen) + kChannelBindingsHashLen + (spn16.length() * 2);
+  }
+
+  // Add extra space for the terminator at the end.
+  *target_info_len += kAvPairHeaderLen;
+}
+
+Buffer WriteUpdatedTargetInfo(const std::vector<AvPair>& av_pairs,
+                              size_t updated_target_info_len) {
+  bool result = true;
+  NtlmBufferWriter writer(updated_target_info_len);
+  for (const AvPair& pair : av_pairs) {
+    result = writer.WriteAvPair(pair);
+    DCHECK(result);
+  }
+
+  result = writer.WriteAvPairTerminator() && writer.IsEndOfBuffer();
+  DCHECK(result);
+  return writer.Pass();
+}
+
+// Reads 7 bytes (56 bits) from |key_56| and writes them into 8 bytes of
+// |key_64| with 7 bits in every byte. The least significant bits are
+// undefined and a subsequent operation will set those bits with a parity bit.
+// |key_56| must contain 7 bytes.
+// |key_64| must contain 8 bytes.
+void Splay56To64(const uint8_t* key_56, uint8_t* key_64) {
+  key_64[0] = key_56[0];
+  key_64[1] = key_56[0] << 7 | key_56[1] >> 1;
+  key_64[2] = key_56[1] << 6 | key_56[2] >> 2;
+  key_64[3] = key_56[2] << 5 | key_56[3] >> 3;
+  key_64[4] = key_56[3] << 4 | key_56[4] >> 4;
+  key_64[5] = key_56[4] << 3 | key_56[5] >> 5;
+  key_64[6] = key_56[5] << 2 | key_56[6] >> 6;
+  key_64[7] = key_56[6] << 1;
+}
+
+}  // namespace
+
+void Create3DesKeysFromNtlmHash(const uint8_t* ntlm_hash, uint8_t* keys) {
+  // Put the first 112 bits from |ntlm_hash| into the first 16 bytes of
+  // |keys|.
+  Splay56To64(ntlm_hash, keys);
+  Splay56To64(ntlm_hash + 7, keys + 8);
+
+  // Put the next 2x 7 bits in bytes 16 and 17 of |keys|, then
+  // the last 2 bits in byte 18, then zero pad the rest of the final key.
+  keys[16] = ntlm_hash[14];
+  keys[17] = ntlm_hash[14] << 7 | ntlm_hash[15] >> 1;
+  keys[18] = ntlm_hash[15] << 6;
+  memset(keys + 19, 0, 5);
+}
+
 void GenerateNtlmHashV1(const base::string16& password, uint8_t* hash) {
   size_t length = password.length() * 2;
   NtlmBufferWriter writer(length);
 
   // The writer will handle the big endian case if necessary.
-  bool result = writer.WriteUtf16String(password);
+  bool result = writer.WriteUtf16String(password) && writer.IsEndOfBuffer();
   DCHECK(result);
 
-  weak_crypto::MD4Sum(
-      reinterpret_cast<const uint8_t*>(writer.GetBuffer().data()), length,
-      hash);
+  MD4(writer.GetBuffer().data(), writer.GetLength(), hash);
 }
 
 void GenerateResponseDesl(const uint8_t* hash,
                           const uint8_t* challenge,
                           uint8_t* response) {
-  // See DESL(K, D) function in [MS-NLMP] Section 6
-  uint8_t key1[8];
-  uint8_t key2[8];
-  uint8_t key3[8];
+  constexpr size_t block_count = 3;
+  constexpr size_t block_size = sizeof(DES_cblock);
+  static_assert(kChallengeLen == block_size,
+                "kChallengeLen must equal block_size");
+  static_assert(kResponseLenV1 == block_count * block_size,
+                "kResponseLenV1 must equal block_count * block_size");
 
-  // The last 2 bytes of the hash are zero padded (5 zeros) as the
-  // input to generate key3.
-  uint8_t padded_hash[7];
-  padded_hash[0] = hash[14];
-  padded_hash[1] = hash[15];
-  memset(padded_hash + 2, 0, 5);
+  const DES_cblock* challenge_block =
+      reinterpret_cast<const DES_cblock*>(challenge);
+  uint8_t keys[block_count * block_size];
 
-  DESMakeKey(hash, key1);
-  DESMakeKey(hash + 7, key2);
-  DESMakeKey(padded_hash, key3);
+  // Map the NTLM hash to three 8 byte DES keys, with 7 bits of the key in each
+  // byte and the least significant bit set with odd parity. Then encrypt the
+  // 8 byte challenge with each of the three keys. This produces three 8 byte
+  // encrypted blocks into |response|.
+  Create3DesKeysFromNtlmHash(hash, keys);
+  for (size_t ix = 0; ix < block_count * block_size; ix += block_size) {
+    DES_cblock* key_block = reinterpret_cast<DES_cblock*>(keys + ix);
+    DES_cblock* response_block = reinterpret_cast<DES_cblock*>(response + ix);
 
-  DESEncrypt(key1, challenge, response);
-  DESEncrypt(key2, challenge, response + 8);
-  DESEncrypt(key3, challenge, response + 16);
+    DES_key_schedule key_schedule;
+    DES_set_odd_parity(key_block);
+    DES_set_key(key_block, &key_schedule);
+    DES_ecb_encrypt(challenge_block, response_block, &key_schedule,
+                    DES_ENCRYPT);
+  }
 }
 
 void GenerateNtlmResponseV1(const base::string16& password,
@@ -81,17 +236,12 @@
 
 void GenerateSessionHashV1WithSessionSecurity(const uint8_t* server_challenge,
                                               const uint8_t* client_challenge,
-                                              base::MD5Digest* session_hash) {
-  base::MD5Context ctx;
-  base::MD5Init(&ctx);
-  base::MD5Update(
-      &ctx, base::StringPiece(reinterpret_cast<const char*>(server_challenge),
-                              kChallengeLen));
-  base::MD5Update(
-      &ctx, base::StringPiece(reinterpret_cast<const char*>(client_challenge),
-                              kChallengeLen));
-
-  base::MD5Final(session_hash, &ctx);
+                                              uint8_t* session_hash) {
+  MD5_CTX ctx;
+  MD5_Init(&ctx);
+  MD5_Update(&ctx, server_challenge, kChallengeLen);
+  MD5_Update(&ctx, client_challenge, kChallengeLen);
+  MD5_Final(session_hash, &ctx);
 }
 
 void GenerateNtlmResponseV1WithSessionSecurity(const base::string16& password,
@@ -103,12 +253,12 @@
   GenerateNtlmHashV1(password, ntlm_hash);
 
   // Generate the NTLMv1 Session Hash.
-  base::MD5Digest session_hash;
+  uint8_t session_hash[kNtlmHashLen];
   GenerateSessionHashV1WithSessionSecurity(server_challenge, client_challenge,
-                                           &session_hash);
+                                           session_hash);
 
-  // Only the first 8 bytes of |session_hash.a| are actually used.
-  GenerateResponseDesl(ntlm_hash, session_hash.a, ntlm_response);
+  // Only the first 8 bytes of |session_hash| are actually used.
+  GenerateResponseDesl(ntlm_hash, session_hash, ntlm_response);
 }
 
 void GenerateResponsesV1WithSessionSecurity(const base::string16& password,
@@ -121,5 +271,120 @@
                                             client_challenge, ntlm_response);
 }
 
+void GenerateNtlmHashV2(const base::string16& domain,
+                        const base::string16& username,
+                        const base::string16& password,
+                        uint8_t* v2_hash) {
+  // NOTE: According to [MS-NLMP] Section 3.3.2 only the username and not the
+  // domain is uppercased.
+  base::string16 upper_username;
+  bool result = ToUpper(username, &upper_username);
+  DCHECK(result);
+
+  uint8_t v1_hash[kNtlmHashLen];
+  GenerateNtlmHashV1(password, v1_hash);
+  NtlmBufferWriter input_writer((upper_username.length() + domain.length()) *
+                                2);
+  bool writer_result = input_writer.WriteUtf16String(upper_username) &&
+                       input_writer.WriteUtf16String(domain) &&
+                       input_writer.IsEndOfBuffer();
+  DCHECK(writer_result);
+
+  unsigned int outlen = kNtlmHashLen;
+  v2_hash =
+      HMAC(EVP_md5(), v1_hash, sizeof(v1_hash), input_writer.GetBuffer().data(),
+           input_writer.GetLength(), v2_hash, &outlen);
+  DCHECK_NE(nullptr, v2_hash);
+  DCHECK_EQ(sizeof(v1_hash), outlen);
+}
+
+Buffer GenerateProofInputV2(uint64_t timestamp,
+                            const uint8_t* client_challenge) {
+  NtlmBufferWriter writer(kProofInputLenV2);
+  bool result = writer.WriteUInt16(kProofInputVersionV2) &&
+                writer.WriteZeros(6) && writer.WriteUInt64(timestamp) &&
+                writer.WriteBytes(client_challenge, kChallengeLen) &&
+                writer.WriteZeros(4) && writer.IsEndOfBuffer();
+
+  DCHECK(result);
+  return writer.Pass();
+}
+
+void GenerateNtlmProofV2(const uint8_t* v2_hash,
+                         const uint8_t* server_challenge,
+                         const Buffer& v2_input,
+                         const Buffer& target_info,
+                         uint8_t* v2_proof) {
+  DCHECK_EQ(kProofInputLenV2, v2_input.size());
+
+  bssl::ScopedHMAC_CTX ctx;
+  HMAC_Init_ex(ctx.get(), v2_hash, kNtlmHashLen, EVP_md5(), NULL);
+  DCHECK_EQ(kNtlmProofLenV2, HMAC_size(ctx.get()));
+  HMAC_Update(ctx.get(), server_challenge, kChallengeLen);
+  HMAC_Update(ctx.get(), v2_input.data(), v2_input.size());
+  HMAC_Update(ctx.get(), target_info.data(), target_info.size());
+  const uint32_t zero = 0;
+  HMAC_Update(ctx.get(), reinterpret_cast<const uint8_t*>(&zero),
+              sizeof(uint32_t));
+  HMAC_Final(ctx.get(), v2_proof, nullptr);
+}
+
+void GenerateSessionBaseKeyV2(const uint8_t* v2_hash,
+                              const uint8_t* v2_proof,
+                              uint8_t* session_key) {
+  unsigned int outlen = kSessionKeyLenV2;
+  session_key = HMAC(EVP_md5(), v2_hash, kNtlmHashLen, v2_proof,
+                     kNtlmProofLenV2, session_key, &outlen);
+  DCHECK_NE(nullptr, session_key);
+  DCHECK_EQ(kSessionKeyLenV2, outlen);
+}
+
+void GenerateChannelBindingHashV2(const std::string& channel_bindings,
+                                  uint8_t* channel_bindings_hash) {
+  NtlmBufferWriter writer(kEpaUnhashedStructHeaderLen);
+  bool result = writer.WriteZeros(16) &&
+                writer.WriteUInt32(channel_bindings.length()) &&
+                writer.IsEndOfBuffer();
+  DCHECK(result);
+
+  MD5_CTX ctx;
+  MD5_Init(&ctx);
+  MD5_Update(&ctx, writer.GetBuffer().data(), writer.GetBuffer().size());
+  MD5_Update(&ctx, channel_bindings.data(), channel_bindings.size());
+  MD5_Final(channel_bindings_hash, &ctx);
+}
+
+void GenerateMicV2(const uint8_t* session_key,
+                   const Buffer& negotiate_msg,
+                   const Buffer& challenge_msg,
+                   const Buffer& authenticate_msg,
+                   uint8_t* mic) {
+  bssl::ScopedHMAC_CTX ctx;
+  HMAC_Init_ex(ctx.get(), session_key, kNtlmHashLen, EVP_md5(), NULL);
+  DCHECK_EQ(kMicLenV2, HMAC_size(ctx.get()));
+  HMAC_Update(ctx.get(), negotiate_msg.data(), negotiate_msg.size());
+  HMAC_Update(ctx.get(), challenge_msg.data(), challenge_msg.size());
+  HMAC_Update(ctx.get(), authenticate_msg.data(), authenticate_msg.size());
+  HMAC_Final(ctx.get(), mic, nullptr);
+}
+
+#if defined(__clang__)
+[[clang::optnone]]  // TODO(crbug.com/769759) Clang crashes on this function.
+#endif
+    NET_EXPORT_PRIVATE Buffer
+    GenerateUpdatedTargetInfo(bool is_mic_enabled,
+                              bool is_epa_enabled,
+                              const std::string& channel_bindings,
+                              const std::string& spn,
+                              const std::vector<AvPair>& av_pairs,
+                              uint64_t* server_timestamp) {
+  size_t updated_target_info_len = 0;
+  std::vector<AvPair> updated_av_pairs(av_pairs);
+  UpdateTargetInfoAvPairs(is_mic_enabled, is_epa_enabled, channel_bindings, spn,
+                          &updated_av_pairs, server_timestamp,
+                          &updated_target_info_len);
+  return WriteUpdatedTargetInfo(updated_av_pairs, updated_target_info_len);
+}
+
 }  // namespace ntlm
 }  // namespace net
diff --git a/net/ntlm/ntlm.h b/net/ntlm/ntlm.h
index 1d98611..31a570b 100644
--- a/net/ntlm/ntlm.h
+++ b/net/ntlm/ntlm.h
@@ -15,19 +15,25 @@
 #include <stdint.h>
 
 #include <memory>
+#include <vector>
 
 #include "base/strings/string16.h"
 #include "base/strings/string_piece.h"
 #include "net/base/net_export.h"
 #include "net/ntlm/ntlm_constants.h"
 
-namespace base {
-struct MD5Digest;
-}
-
 namespace net {
 namespace ntlm {
 
+// Maps the bits in the NTLM Hash into 3 DES keys. The DES keys each have 56
+// bits stored in the 7 most significant bits of 8 bytes. The least
+// significant bit is undefined and will subsequently be set with odd parity
+// prior to use.
+// |ntlm_hash| must contain 16 bytes.
+// |keys| must contain 24 bytes.
+NET_EXPORT_PRIVATE void Create3DesKeysFromNtlmHash(const uint8_t* ntlm_hash,
+                                                   uint8_t* keys);
+
 // Generates the NTLMv1 Hash and writes the |kNtlmHashLen| byte result to
 // |hash|. Defined by NTOWFv1() in [MS-NLMP] Section 3.3.1.
 NET_EXPORT_PRIVATE void GenerateNtlmHashV1(const base::string16& password,
@@ -91,10 +97,11 @@
 //
 // |server_challenge| must contain |kChallengeLen| bytes.
 // |client_challenge| must contain |kChallengeLen| bytes.
+// |session_hash| must contain |kNtlmHashLen|.
 NET_EXPORT_PRIVATE void GenerateSessionHashV1WithSessionSecurity(
     const uint8_t* server_challenge,
     const uint8_t* client_challenge,
-    base::MD5Digest* session_hash);
+    uint8_t* session_hash);
 
 // Generates the NTLM Response for NTLMv1 with session security.
 // Defined by ComputeResponse() in [MS-NLMP] Section 3.3.1 for the
@@ -125,6 +132,130 @@
     uint8_t* lm_response,
     uint8_t* ntlm_response);
 
+// Generates the NTLMv2 Hash and writes the |kNtlmHashLen| byte result to
+// |v2_hash|.
+// |v2_hash| must contain |kNtlmHashLen| bytes.
+NET_EXPORT_PRIVATE void GenerateNtlmHashV2(const base::string16& domain,
+                                           const base::string16& username,
+                                           const base::string16& password,
+                                           uint8_t* v2_hash);
+
+// In this implementation the Proof Input is the first 28 bytes of what
+// [MS-NLMP] section 3.3.2 calls "temp". "temp" is part of the input to
+// generate the NTLMv2 proof. "temp" is composed of a fixed 28 byte prefix
+// (the Proof Input), then the variable length updated target info that is
+// sent in the authenticate message, then followed by 4 zero bytes. See
+// [MS-NLMP] Section 2.2.2.7.
+//
+// |timestamp| contains a 64 bit Windows timestamp defined as the number of
+// 100 nanosecond ticks since midnight Jan 01, 1601 (UTC).
+//
+// The format of the returned |proof_input| is;
+//
+// [0-1]    - 0x0101                              (Version)
+// [2-7]    - 0x000000000000                      (Reserved - all zero)
+// [8-15]   - |timestamp|                         (Timestamp)
+// [16-23]  - |client_challenge|                  (Client challenge)
+// [24-27]  - 0x00000000                          (Reserved - all zero)
+//
+// |client_challenge| must contain |kChallengeLen| bytes.
+NET_EXPORT_PRIVATE Buffer GenerateProofInputV2(uint64_t timestamp,
+                                               const uint8_t* client_challenge);
+
+// The NTLMv2 Proof is part of the NTLMv2 Response. See NTProofStr in [MS-NLMP]
+// Section 3.3.2.
+//
+// The NTLMv2 Proof is defined as;
+//     v2_proof = HMAC_MD5(
+//         v2_hash,
+//         CONCAT(server_challenge, v2_input, target_info, 0x00000000))
+//
+// |v2_hash| must contain |kNtlmHashLen| bytes.
+// |server_challenge| must contain |kChallengeLen| bytes.
+// |v2_input| must contain |kProofInputLenV2| bytes.
+// |target_info| contains the target info field that will be sent in the
+// authenticate message.
+// |v2_proof| must contain |kNtlmProofLenV2| bytes.
+NET_EXPORT_PRIVATE void GenerateNtlmProofV2(const uint8_t* v2_hash,
+                                            const uint8_t* server_challenge,
+                                            const Buffer& v2_input,
+                                            const Buffer& target_info,
+                                            uint8_t* v2_proof);
+
+// The session base key is used to generate the Message Integrity Check (MIC).
+// See [MS-NLMP] Section 3.3.2.
+//
+// It is defined as;
+//     session_key = HMAC_MD5(v2_hash, v2_proof)
+//
+// |v2_hash| must contain |kNtlmHashLen| bytes.
+// |v2_proof| must contain |kNtlmProofLenV2| bytes.
+// |session_key| must contain |kSessionKeyLenV2| bytes.
+NET_EXPORT_PRIVATE void GenerateSessionBaseKeyV2(const uint8_t* v2_hash,
+                                                 const uint8_t* v2_proof,
+                                                 uint8_t* session_key);
+
+// The channel bindings hash is an MD5 hash of a data structure containing
+// a hash of the server's certificate.
+//
+// The |channel_bindings| string is supplied out of band (usually from a web
+// browser) and is a (21+sizeof(hash)) byte ASCII string, where 'hash' is
+// usually a SHA-256 of the servers certificate, but may be another hash
+// algorithm. The format as defined by RFC 5929 Section 4 is shown below;
+//
+// [0-20]                 - "tls-server-end-point:"   (Literal string)
+// [21-(20+sizeof(hash)]  - HASH(server_certificate)  (Certificate hash)
+//
+// The |channel_bindings| string is then combined into a data structure called
+// gss_channel_bindings_struct (on Windows SEC_CHANNEL_BINDINGS) and MD5 hashed
+// according to the rules in RFC 4121 Section 4.1.1.2. When simplified this
+// results in the input to the hash (aka "ClientChannelBindingsUnhashed")
+// being defined as follows;
+//
+// [0-15]   - 16 zero bytes                        (Collapsed fields)
+// [16-19]  - |strlen(channel_bindings)|           (Length=0x00000035)
+// [20-72]  - |channel_bindings|                   (Channel bindings)
+//
+// See also RFC 5056 and [MS-NLMP] Section 3.1.5.1.2.
+//
+// The channel bindings hash is then defined as;
+//     channel_bindings_hash = MD5(ClientChannelBindingsUnhashed)
+NET_EXPORT_PRIVATE void GenerateChannelBindingHashV2(
+    const std::string& channel_bindings,
+    uint8_t* channel_bindings_hash);
+
+// The Message Integrity Check (MIC) is a hash calculated over all three
+// messages in the NTLM protocol. The MIC field in the authenticate message
+// is set to all zeros when calculating the hash. See [MS-NLMP] Section
+// 3.1.5.1.2.
+//
+// In this implementation NTLMSSP_NEGOTIATE_KEY_EXCH never negotiated and
+// the MIC for this case is defined as below. If NTLMSSP_NEGOTIATE_KEY_EXCH
+// was negotiated, an alternate key is used. See [MS-NLMP] SEction 3.1.5.1.2
+// for additional details.
+//
+//     mic = HMAC_MD5(
+//         session_base_key,
+//         CONCAT(negotiate_msg, challenge_msg, authenticate_msg))
+//
+// |session_key| must contain |kSessionKeyLenV2| bytes.
+// |mic| must contain |kMicLenV2| bytes.
+NET_EXPORT_PRIVATE void GenerateMicV2(const uint8_t* session_key,
+                                      const Buffer& negotiate_msg,
+                                      const Buffer& challenge_msg,
+                                      const Buffer& authenticate_msg,
+                                      uint8_t* mic);
+
+// Updates the target info sent by the server, and generates the clients
+// response target info.
+NET_EXPORT_PRIVATE Buffer
+GenerateUpdatedTargetInfo(bool is_mic_enabled,
+                          bool is_epa_enabled,
+                          const std::string& channel_bindings,
+                          const std::string& spn,
+                          const std::vector<AvPair>& av_pairs,
+                          uint64_t* server_timestamp);
+
 }  // namespace ntlm
 }  // namespace net
 
diff --git a/net/ntlm/ntlm_buffer_reader.cc b/net/ntlm/ntlm_buffer_reader.cc
index ebebc50..01e59ca 100644
--- a/net/ntlm/ntlm_buffer_reader.cc
+++ b/net/ntlm/ntlm_buffer_reader.cc
@@ -11,17 +11,19 @@
 namespace net {
 namespace ntlm {
 
+NtlmBufferReader::NtlmBufferReader() : NtlmBufferReader(nullptr, 0) {}
+
 NtlmBufferReader::NtlmBufferReader(const Buffer& buffer)
-    : buffer_(buffer), cursor_(0) {
-  DCHECK(buffer.data());
-}
+    : NtlmBufferReader(
+          base::StringPiece(reinterpret_cast<const char*>(buffer.data()),
+                            buffer.length())) {}
 
 NtlmBufferReader::NtlmBufferReader(base::StringPiece str)
-    : NtlmBufferReader(reinterpret_cast<const uint8_t*>(str.data()),
-                       str.size()) {}
+    : buffer_(str), cursor_(0) {}
 
 NtlmBufferReader::NtlmBufferReader(const uint8_t* ptr, size_t len)
-    : NtlmBufferReader(Buffer(ptr, len)) {}
+    : NtlmBufferReader(
+          base::StringPiece(reinterpret_cast<const char*>(ptr), len)) {}
 
 NtlmBufferReader::~NtlmBufferReader() {}
 
@@ -80,11 +82,136 @@
   return true;
 }
 
+bool NtlmBufferReader::ReadPayloadAsBufferReader(const SecurityBuffer& sec_buf,
+                                                 NtlmBufferReader* reader) {
+  if (!CanReadFrom(sec_buf))
+    return false;
+
+  *reader = NtlmBufferReader(GetBufferPtr() + sec_buf.offset, sec_buf.length);
+  return true;
+}
+
 bool NtlmBufferReader::ReadSecurityBuffer(SecurityBuffer* sec_buf) {
   return ReadUInt16(&sec_buf->length) && SkipBytes(sizeof(uint16_t)) &&
          ReadUInt32(&sec_buf->offset);
 }
 
+bool NtlmBufferReader::ReadAvPairHeader(ntlm::TargetInfoAvId* avid,
+                                        uint16_t* avlen) {
+  if (!CanRead(ntlm::kAvPairHeaderLen))
+    return false;
+
+  uint16_t raw_avid;
+  bool result = ReadUInt16(&raw_avid) && ReadUInt16(avlen);
+  DCHECK(result);
+
+  // Don't try and validate the avid because the code only cares about a few
+  // specific ones and it is likely a future version might extend this field.
+  // The implementation can ignore and skip over AV Pairs it doesn't
+  // understand.
+  *avid = static_cast<ntlm::TargetInfoAvId>(raw_avid);
+
+  return true;
+}
+
+bool NtlmBufferReader::ReadTargetInfo(size_t target_info_len,
+                                      std::vector<ntlm::AvPair>* av_pairs) {
+  DCHECK(av_pairs->empty());
+
+  // A completely empty target info is allowed.
+  if (target_info_len == 0)
+    return true;
+
+  // If there is any content there has to be at least one terminating header.
+  if (!CanRead(target_info_len) || target_info_len < ntlm::kAvPairHeaderLen) {
+    return false;
+  }
+
+  size_t target_info_end = GetCursor() + target_info_len;
+  bool saw_eol = false;
+
+  while ((GetCursor() < target_info_end)) {
+    ntlm::AvPair pair;
+    if (!ReadAvPairHeader(&pair.avid, &pair.avlen))
+      break;
+
+    // Make sure the length wouldn't read outside the buffer.
+    if (!CanRead(pair.avlen))
+      return false;
+
+    // Take a copy of the payload in the AVPair.
+    pair.buffer.assign(GetBufferAtCursor(), pair.avlen);
+    if (pair.avid == ntlm::TargetInfoAvId::kEol) {
+      // Terminator must have zero length.
+      if (pair.avlen != 0)
+        return false;
+
+      // Break out of the loop once a valid terminator is found. After the
+      // loop it will be validated that the whole target info was consumed.
+      saw_eol = true;
+      break;
+    }
+
+    switch (pair.avid) {
+      case ntlm::TargetInfoAvId::kFlags:
+        // For flags also populate the flags field so it doesn't
+        // have to be modified through the raw buffer later.
+        if (pair.avlen != sizeof(uint32_t) ||
+            !ReadUInt32(reinterpret_cast<uint32_t*>(&pair.flags)))
+          return false;
+        break;
+      case ntlm::TargetInfoAvId::kTimestamp:
+        // Populate timestamp so it doesn't need to be read through the
+        // raw buffer later.
+        if (pair.avlen != sizeof(uint64_t) || !ReadUInt64(&pair.timestamp))
+          return false;
+        break;
+      case ntlm::TargetInfoAvId::kChannelBindings:
+      case ntlm::TargetInfoAvId::kTargetName:
+        // The server should never send these, and with EPA enabled the client
+        // will add these to the authenticate message. To avoid issues with
+        // duplicates or only one being read, just don't allow them.
+        return false;
+      default:
+        // For all other types, just jump over the payload to the next pair.
+        // If there aren't enough bytes left, then fail.
+        if (!SkipBytes(pair.avlen))
+          return false;
+        break;
+    }
+
+    av_pairs->push_back(std::move(pair));
+  }
+
+  // Fail if the buffer wasn't properly formed. The entire payload should have
+  // been consumed and a terminator found.
+  if ((GetCursor() != target_info_end) || !saw_eol)
+    return false;
+
+  return true;
+}
+
+bool NtlmBufferReader::ReadTargetInfoPayload(
+    std::vector<ntlm::AvPair>* av_pairs) {
+  DCHECK(av_pairs->empty());
+
+  ntlm::SecurityBuffer sec_buf;
+
+  // First read the security buffer.
+  if (!ReadSecurityBuffer(&sec_buf))
+    return false;
+
+  NtlmBufferReader payload_reader;
+  if (!ReadPayloadAsBufferReader(sec_buf, &payload_reader))
+    return false;
+
+  if (!payload_reader.ReadTargetInfo(sec_buf.length, av_pairs))
+    return false;
+
+  // |ReadTargetInfo| should have consumed the entire contents.
+  return payload_reader.IsEndOfBuffer();
+}
+
 bool NtlmBufferReader::ReadMessageType(MessageType* message_type) {
   uint32_t raw_message_type;
   if (!ReadUInt32(&raw_message_type))
diff --git a/net/ntlm/ntlm_buffer_reader.h b/net/ntlm/ntlm_buffer_reader.h
index dd72b9b..1723ca52 100644
--- a/net/ntlm/ntlm_buffer_reader.h
+++ b/net/ntlm/ntlm_buffer_reader.h
@@ -9,6 +9,7 @@
 #include <stdint.h>
 
 #include <string>
+#include <vector>
 
 #include "base/strings/string_piece.h"
 #include "net/base/net_export.h"
@@ -46,6 +47,8 @@
 // [2] http://davenport.sourceforge.net/ntlm.html
 class NET_EXPORT_PRIVATE NtlmBufferReader {
  public:
+  NtlmBufferReader();
+  // |buffer| is not copied and must outlive the |NtlmBufferReader|.
   explicit NtlmBufferReader(const Buffer& buffer);
   explicit NtlmBufferReader(base::StringPiece buffer);
 
@@ -98,6 +101,14 @@
   bool ReadBytesFrom(const SecurityBuffer& sec_buf,
                      uint8_t* buffer) WARN_UNUSED_RESULT;
 
+  // Reads |sec_buf.length| bytes from offset |sec_buf.offset| and assigns
+  // |reader| an |NtlmBufferReader| representing the payload. If the security
+  //  buffer specifies a payload outside the buffer, then the call fails, and
+  // the state of |reader| is undefined. Unlike the other Read* methods, this
+  // does not move the cursor.
+  bool ReadPayloadAsBufferReader(const SecurityBuffer& sec_buf,
+                                 NtlmBufferReader* reader) WARN_UNUSED_RESULT;
+
   // A security buffer is an 8 byte structure that defines the offset and
   // length of a payload (string, struct or byte array) that appears after the
   // fixed part of the message.
@@ -108,6 +119,19 @@
   //     uint32 - |offset| Offset from start of message
   bool ReadSecurityBuffer(SecurityBuffer* sec_buf) WARN_UNUSED_RESULT;
 
+  // Reads an AvPair header. AvPairs appear sequentially, terminated by a
+  // special EOL AvPair, in the target info payload of the Challenge message.
+  // See [MS-NLMP] Section 2.2.2.1.
+  //
+  // An AvPair contains an inline payload, and has the structure below (
+  // little endian fields):
+  //    uint16      - AvID: Identifies the type of the payload.
+  //    uint16      - AvLen: The length of the following payload.
+  //    (variable)  - Payload: Variable length payload. The content and
+  //                  format are determined by the AvId.
+  bool ReadAvPairHeader(ntlm::TargetInfoAvId* avid,
+                        uint16_t* avlen) WARN_UNUSED_RESULT;
+
   // There are 3 message types Negotiate (sent by client), Challenge (sent by
   // server), and Authenticate (sent by client).
   //
@@ -115,6 +139,24 @@
   // value is invalid.
   bool ReadMessageType(MessageType* message_type) WARN_UNUSED_RESULT;
 
+  // Reads |target_info_len| bytes and parses them as a sequence of Av Pairs.
+  // |av_pairs| should be empty on entry to this function. If |ReadTargetInfo|
+  // returns false, the content of |av_pairs| is in an undefined state and
+  // should be discarded.
+  bool ReadTargetInfo(size_t target_info_len,
+                      std::vector<ntlm::AvPair>* av_pairs) WARN_UNUSED_RESULT;
+
+  // Reads a security buffer, then parses the security buffer payload as a
+  // target info. The target info is returned as a sequence of AvPairs, with
+  // the terminating AvPair omitted. A zero length payload is valid and will
+  // result in an empty list in |av_pairs|. Any non-zero length payload must
+  // have a terminating AvPair.
+  // |av_pairs| should be empty on entry to this function. If |ReadTargetInfo|
+  // returns false, the content of |av_pairs| is in an undefined state and
+  // should be discarded.
+  bool ReadTargetInfoPayload(std::vector<ntlm::AvPair>* av_pairs)
+      WARN_UNUSED_RESULT;
+
   // Skips over a security buffer field without reading the fields. This is
   // the equivalent of advancing the cursor 8 bytes. Returns false if there
   // are less than 8 bytes left in the buffer.
@@ -166,7 +208,9 @@
   void AdvanceCursor(size_t count) { SetCursor(GetCursor() + count); }
 
   // Returns a constant pointer to the start of the buffer.
-  const uint8_t* GetBufferPtr() const { return buffer_.data(); }
+  const uint8_t* GetBufferPtr() const {
+    return reinterpret_cast<const uint8_t*>(buffer_.data());
+  }
 
   // Returns a pointer to the underlying buffer at the current cursor
   // position.
@@ -178,10 +222,8 @@
     return *(GetBufferAtCursor());
   }
 
-  const Buffer buffer_;
+  base::StringPiece buffer_;
   size_t cursor_;
-
-  DISALLOW_COPY_AND_ASSIGN(NtlmBufferReader);
 };
 
 }  // namespace ntlm
diff --git a/net/ntlm/ntlm_buffer_reader_unittest.cc b/net/ntlm/ntlm_buffer_reader_unittest.cc
index 592c5d3..4ecfbed 100644
--- a/net/ntlm/ntlm_buffer_reader_unittest.cc
+++ b/net/ntlm/ntlm_buffer_reader_unittest.cc
@@ -32,6 +32,27 @@
   ASSERT_TRUE(reader.CanReadFrom(SecurityBuffer(99, 0)));
 }
 
+TEST(NtlmBufferReaderTest, EmptyBuffer) {
+  Buffer b;
+  NtlmBufferReader reader(b);
+
+  ASSERT_EQ(0u, reader.GetCursor());
+  ASSERT_EQ(0u, reader.GetLength());
+  ASSERT_TRUE(reader.CanRead(0));
+  ASSERT_FALSE(reader.CanRead(1));
+  ASSERT_TRUE(reader.IsEndOfBuffer());
+}
+
+TEST(NtlmBufferReaderTest, NullBuffer) {
+  NtlmBufferReader reader(nullptr, 0);
+
+  ASSERT_EQ(0u, reader.GetCursor());
+  ASSERT_EQ(0u, reader.GetLength());
+  ASSERT_TRUE(reader.CanRead(0));
+  ASSERT_FALSE(reader.CanRead(1));
+  ASSERT_TRUE(reader.IsEndOfBuffer());
+}
+
 TEST(NtlmBufferReaderTest, Read16) {
   const uint8_t buf[2] = {0x22, 0x11};
   const uint16_t expected = 0x1122;
@@ -106,6 +127,51 @@
   ASSERT_FALSE(reader.ReadSecurityBuffer(&sec_buf));
 }
 
+TEST(NtlmBufferReaderTest, ReadPayloadAsBufferReader) {
+  const uint8_t buf[8] = {0xff, 0xff, 0x11, 0x22, 0x33, 0x44, 0xff, 0xff};
+  const uint32_t expected = 0x44332211;
+  NtlmBufferReader reader(buf, arraysize(buf));
+  ASSERT_EQ(0u, reader.GetCursor());
+
+  // Create a security buffer with offset 2 and length 4.
+  SecurityBuffer sec_buf(2, 4);
+  NtlmBufferReader sub_reader;
+  ASSERT_EQ(0u, sub_reader.GetLength());
+  ASSERT_EQ(0u, sub_reader.GetCursor());
+
+  // Read the 4 non-0xff bytes from the middle of |buf|.
+  ASSERT_TRUE(reader.ReadPayloadAsBufferReader(sec_buf, &sub_reader));
+
+  // |reader| cursor should not move.
+  ASSERT_EQ(0u, reader.GetCursor());
+  ASSERT_EQ(sec_buf.length, sub_reader.GetLength());
+  ASSERT_EQ(0u, sub_reader.GetCursor());
+
+  // Read from the payload in |sub_reader|.
+  uint32_t actual;
+  ASSERT_TRUE(sub_reader.ReadUInt32(&actual));
+  ASSERT_EQ(expected, actual);
+  ASSERT_TRUE(sub_reader.IsEndOfBuffer());
+}
+
+TEST(NtlmBufferReaderTest, ReadPayloadBadOffset) {
+  const uint8_t buf[4] = {0};
+  NtlmBufferReader reader(buf, arraysize(buf));
+
+  NtlmBufferReader sub_reader;
+  ASSERT_FALSE(
+      reader.ReadPayloadAsBufferReader(SecurityBuffer(4, 1), &sub_reader));
+}
+
+TEST(NtlmBufferReaderTest, ReadPayloadBadLength) {
+  const uint8_t buf[4] = {0};
+  NtlmBufferReader reader(buf, arraysize(buf));
+
+  NtlmBufferReader sub_reader;
+  ASSERT_FALSE(
+      reader.ReadPayloadAsBufferReader(SecurityBuffer(3, 2), &sub_reader));
+}
+
 TEST(NtlmBufferReaderTest, SkipSecurityBuffer) {
   const uint8_t buf[kSecurityBufferLen] = {0};
 
@@ -250,6 +316,245 @@
   ASSERT_TRUE(reader.IsEndOfBuffer());
 }
 
+TEST(NtlmBufferReaderTest, ReadTargetInfoEolOnly) {
+  // Buffer contains only an EOL terminator.
+  const uint8_t buf[4] = {0, 0, 0, 0};
+
+  NtlmBufferReader reader(buf, arraysize(buf));
+
+  std::vector<ntlm::AvPair> av_pairs;
+  ASSERT_TRUE(reader.ReadTargetInfo(arraysize(buf), &av_pairs));
+  ASSERT_TRUE(reader.IsEndOfBuffer());
+  ASSERT_TRUE(av_pairs.empty());
+}
+
+TEST(NtlmBufferReaderTest, ReadTargetInfoEmpty) {
+  NtlmBufferReader reader;
+
+  std::vector<ntlm::AvPair> av_pairs;
+  ASSERT_TRUE(reader.ReadTargetInfo(0, &av_pairs));
+  ASSERT_TRUE(reader.IsEndOfBuffer());
+  ASSERT_TRUE(av_pairs.empty());
+}
+
+TEST(NtlmBufferReaderTest, ReadTargetInfoTimestampAndEolOnly) {
+  // Buffer contains a timestamp av pair and an EOL terminator.
+  const uint8_t buf[16] = {0x07, 0,    0x08, 0,    0x11, 0x22, 0x33, 0x44,
+                           0x55, 0x66, 0x77, 0x88, 0,    0,    0,    0};
+  const uint64_t expected_timestamp = 0x8877665544332211;
+
+  NtlmBufferReader reader(buf, arraysize(buf));
+
+  std::vector<ntlm::AvPair> av_pairs;
+  ASSERT_TRUE(reader.ReadTargetInfo(arraysize(buf), &av_pairs));
+  ASSERT_TRUE(reader.IsEndOfBuffer());
+  ASSERT_EQ(1u, av_pairs.size());
+
+  // Verify the timestamp av pair.
+  ASSERT_EQ(ntlm::TargetInfoAvId::kTimestamp, av_pairs[0].avid);
+  ASSERT_EQ(sizeof(uint64_t), av_pairs[0].avlen);
+  ASSERT_EQ(sizeof(uint64_t), av_pairs[0].buffer.size());
+  ASSERT_EQ(expected_timestamp, av_pairs[0].timestamp);
+}
+
+TEST(NtlmBufferReaderTest, ReadTargetInfoFlagsAndEolOnly) {
+  // Buffer contains a flags av pair with the MIC bit and an EOL terminator.
+  const uint8_t buf[12] = {0x06, 0, 0x04, 0, 0x02, 0, 0, 0, 0, 0, 0, 0};
+
+  NtlmBufferReader reader(buf, arraysize(buf));
+
+  std::vector<ntlm::AvPair> av_pairs;
+  ASSERT_TRUE(reader.ReadTargetInfo(arraysize(buf), &av_pairs));
+  ASSERT_TRUE(reader.IsEndOfBuffer());
+  ASSERT_EQ(1u, av_pairs.size());
+
+  // Verify the flags av pair.
+  ASSERT_EQ(ntlm::TargetInfoAvId::kFlags, av_pairs[0].avid);
+  ASSERT_EQ(sizeof(ntlm::TargetInfoAvFlags), av_pairs[0].avlen);
+  ASSERT_EQ(ntlm::TargetInfoAvFlags::kMicPresent, av_pairs[0].flags);
+}
+
+TEST(NtlmBufferReaderTest, ReadTargetInfoTooSmall) {
+  // Target info must least contain enough space for a terminator pair.
+  const uint8_t buf[3] = {0};
+
+  NtlmBufferReader reader(buf, arraysize(buf));
+
+  std::vector<ntlm::AvPair> av_pairs;
+  ASSERT_FALSE(reader.ReadTargetInfo(arraysize(buf), &av_pairs));
+}
+
+TEST(NtlmBufferReaderTest, ReadTargetInfoInvalidTimestampSize) {
+  // Timestamps must be 64 bits/8 bytes. A timestamp av pair with a
+  // different length is invalid.
+  const uint8_t buf[15] = {0x07, 0,    0x07, 0, 0x11, 0x22, 0x33, 0x44,
+                           0x55, 0x66, 0x77, 0, 0,    0,    0};
+
+  NtlmBufferReader reader(buf, arraysize(buf));
+
+  std::vector<ntlm::AvPair> av_pairs;
+  ASSERT_FALSE(reader.ReadTargetInfo(arraysize(buf), &av_pairs));
+}
+
+TEST(NtlmBufferReaderTest, ReadTargetInfoInvalidTimestampPastEob) {
+  // The timestamp avlen is correct but would read past the end of the buffer.
+  const uint8_t buf[11] = {0x07, 0,    0x08, 0,    0x11, 0x22,
+                           0x33, 0x44, 0x55, 0x66, 0x77};
+
+  NtlmBufferReader reader(buf, arraysize(buf));
+
+  std::vector<ntlm::AvPair> av_pairs;
+  ASSERT_FALSE(reader.ReadTargetInfo(arraysize(buf), &av_pairs));
+}
+
+TEST(NtlmBufferReaderTest, ReadTargetInfoOtherField) {
+  // A domain name AvPair containing the string L'ABCD' followed by
+  // a terminating AvPair.
+  const uint8_t buf[16] = {0x02, 0, 0x08, 0, 'A', 0, 'B', 0,
+                           'C',  0, 'D',  0, 0,   0, 0,   0};
+
+  NtlmBufferReader reader(buf, arraysize(buf));
+
+  std::vector<ntlm::AvPair> av_pairs;
+  ASSERT_TRUE(reader.ReadTargetInfo(arraysize(buf), &av_pairs));
+  ASSERT_TRUE(reader.IsEndOfBuffer());
+  ASSERT_EQ(1u, av_pairs.size());
+
+  // Verify the domain name AvPair.
+  ASSERT_EQ(ntlm::TargetInfoAvId::kDomainName, av_pairs[0].avid);
+  ASSERT_EQ(8, av_pairs[0].avlen);
+  ASSERT_EQ(0, memcmp(buf + 4, av_pairs[0].buffer.data(), 8));
+}
+
+TEST(NtlmBufferReaderTest, ReadTargetInfoNoTerminator) {
+  // A domain name AvPair containing the string L'ABCD' but there is no
+  // terminating AvPair.
+  const uint8_t buf[12] = {0x02, 0, 0x08, 0, 'A', 0, 'B', 0, 'C', 0, 'D', 0};
+
+  NtlmBufferReader reader(buf, arraysize(buf));
+
+  std::vector<ntlm::AvPair> av_pairs;
+  ASSERT_FALSE(reader.ReadTargetInfo(arraysize(buf), &av_pairs));
+}
+
+TEST(NtlmBufferReaderTest, ReadTargetInfoTerminatorAtLocationOtherThanEnd) {
+  // Target info contains [flags, terminator, domain, terminator]. This
+  // should fail because the terminator should only appear at the end.
+  const uint8_t buf[] = {0x06, 0, 0x04, 0, 0x02, 0, 0,   0, 0,   0,
+                         0,    0, 0x02, 0, 0x08, 0, 'A', 0, 'B', 0,
+                         'C',  0, 'D',  0, 0,    0, 0,   0};
+
+  NtlmBufferReader reader(buf, arraysize(buf));
+
+  std::vector<ntlm::AvPair> av_pairs;
+  ASSERT_FALSE(reader.ReadTargetInfo(arraysize(buf), &av_pairs));
+}
+
+TEST(NtlmBufferReaderTest, ReadTargetInfoTerminatorNonZeroLength) {
+  // A flags Av Pair followed by a terminator pair with a non-zero length.
+  const uint8_t buf[] = {0x06, 0, 0x04, 0, 0x02, 0, 0, 0, 0, 0, 0x01, 0};
+
+  NtlmBufferReader reader(buf, arraysize(buf));
+
+  std::vector<ntlm::AvPair> av_pairs;
+  ASSERT_FALSE(reader.ReadTargetInfo(arraysize(buf), &av_pairs));
+}
+
+TEST(NtlmBufferReaderTest, ReadTargetInfoTerminatorNonZeroLength2) {
+  // A flags Av Pair followed by a terminator pair with a non-zero length,
+  // but otherwise in bounds payload. Terminator pairs must have zero
+  // length, so this is not valid.
+  const uint8_t buf[] = {0x06, 0,    0x04, 0,    0x02, 0, 0, 0, 0,
+                         0,    0x01, 0,    0xff, 0,    0, 0, 0};
+
+  NtlmBufferReader reader(buf, arraysize(buf));
+
+  std::vector<ntlm::AvPair> av_pairs;
+  ASSERT_FALSE(reader.ReadTargetInfo(arraysize(buf), &av_pairs));
+}
+
+TEST(NtlmBufferReaderTest, ReadTargetInfoEmptyPayload) {
+  // Security buffer with no payload.
+  const uint8_t buf[] = {0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00};
+
+  NtlmBufferReader reader(buf, arraysize(buf));
+
+  std::vector<ntlm::AvPair> av_pairs;
+  ASSERT_TRUE(reader.ReadTargetInfoPayload(&av_pairs));
+  ASSERT_TRUE(reader.IsEndOfBuffer());
+  ASSERT_TRUE(av_pairs.empty());
+}
+
+TEST(NtlmBufferReaderTest, ReadTargetInfoEolOnlyPayload) {
+  // Security buffer with an EOL payload
+  const uint8_t buf[] = {0x04, 0x00, 0x04, 0x00, 0x08, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+  NtlmBufferReader reader(buf, arraysize(buf));
+
+  std::vector<ntlm::AvPair> av_pairs;
+  ASSERT_TRUE(reader.ReadTargetInfoPayload(&av_pairs));
+  ASSERT_FALSE(reader.IsEndOfBuffer());
+
+  // Should only have advanced over the security buffer.
+  ASSERT_EQ(kSecurityBufferLen, reader.GetCursor());
+  ASSERT_TRUE(av_pairs.empty());
+}
+
+TEST(NtlmBufferReaderTest, ReadTargetInfoTooShortPayload) {
+  // Security buffer with a payload too small to contain any pairs.
+  const uint8_t buf[] = {0x03, 0x00, 0x03, 0x00, 0x08, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00};
+
+  NtlmBufferReader reader(buf, arraysize(buf));
+
+  std::vector<ntlm::AvPair> av_pairs;
+  ASSERT_FALSE(reader.ReadTargetInfoPayload(&av_pairs));
+}
+
+TEST(NtlmBufferReaderTest, ReadTargetInfoFlagsPayload) {
+  // Security buffer followed by a 12 byte payload containing a flags AvPair
+  // with the MIC bit, followed by a terminator pair.
+  const uint8_t buf[] = {0x0c, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x00,
+                         0x00, 0x06, 0,    0x04, 0,    0x02, 0,
+                         0,    0,    0,    0,    0,    0};
+
+  NtlmBufferReader reader(buf, arraysize(buf));
+
+  std::vector<ntlm::AvPair> av_pairs;
+  ASSERT_TRUE(reader.ReadTargetInfoPayload(&av_pairs));
+  ASSERT_FALSE(reader.IsEndOfBuffer());
+
+  // Should only have advanced over the security buffer.
+  ASSERT_EQ(kSecurityBufferLen, reader.GetCursor());
+
+  // Contains a single flags AVPair containing the MIC bit.
+  ASSERT_EQ(1u, av_pairs.size());
+  ASSERT_EQ(TargetInfoAvFlags::kMicPresent, av_pairs[0].flags);
+}
+
+TEST(NtlmBufferReaderTest, ReadTargetInfoFlagsPayloadWithPaddingBetween) {
+  // Security buffer followed by a 12 byte payload containing a flags AvPair
+  // with the MIC bit, followed by a terminator pair. 5 bytes of 0xff padding
+  // are between the SecurityBuffer and the payload to test when the payload
+  // is not contiguous.
+  const uint8_t buf[] = {0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x00, 0x00,
+                         0xff, 0xff, 0xff, 0xff, 0x06, 0,    0x04, 0,
+                         0x02, 0,    0,    0,    0,    0,    0,    0};
+  NtlmBufferReader reader(buf, arraysize(buf));
+
+  std::vector<ntlm::AvPair> av_pairs;
+  ASSERT_TRUE(reader.ReadTargetInfoPayload(&av_pairs));
+  ASSERT_FALSE(reader.IsEndOfBuffer());
+
+  // Should only have advanced over the security buffer.
+  ASSERT_EQ(kSecurityBufferLen, reader.GetCursor());
+
+  // Contains a single flags AVPair containing the MIC bit.
+  ASSERT_EQ(1u, av_pairs.size());
+  ASSERT_EQ(TargetInfoAvFlags::kMicPresent, av_pairs[0].flags);
+}
+
 TEST(NtlmBufferReaderTest, ReadMessageTypeAuthenticate) {
   const uint8_t buf[4] = {static_cast<uint8_t>(MessageType::kAuthenticate), 0,
                           0, 0};
@@ -363,5 +668,29 @@
   ASSERT_FALSE(reader.MatchEmptySecurityBuffer());
 }
 
+TEST(NtlmBufferReaderTest, ReadAvPairHeader) {
+  const uint8_t buf[4] = {0x06, 0x00, 0x11, 0x22};
+
+  NtlmBufferReader reader(buf, arraysize(buf));
+
+  ntlm::TargetInfoAvId actual_avid;
+  uint16_t actual_avlen;
+  ASSERT_TRUE(reader.ReadAvPairHeader(&actual_avid, &actual_avlen));
+  ASSERT_EQ(ntlm::TargetInfoAvId::kFlags, actual_avid);
+  ASSERT_EQ(0x2211, actual_avlen);
+  ASSERT_TRUE(reader.IsEndOfBuffer());
+  ASSERT_FALSE(reader.ReadAvPairHeader(&actual_avid, &actual_avlen));
+}
+
+TEST(NtlmBufferReaderTest, ReadAvPairHeaderPastEob) {
+  const uint8_t buf[3] = {0x06, 0x00, 0x11};
+
+  NtlmBufferReader reader(buf, arraysize(buf));
+
+  ntlm::TargetInfoAvId avid;
+  uint16_t avlen;
+  ASSERT_FALSE(reader.ReadAvPairHeader(&avid, &avlen));
+}
+
 }  // namespace ntlm
 }  // namespace net
diff --git a/net/ntlm/ntlm_buffer_writer.cc b/net/ntlm/ntlm_buffer_writer.cc
index 746b453..a10be0f 100644
--- a/net/ntlm/ntlm_buffer_writer.cc
+++ b/net/ntlm/ntlm_buffer_writer.cc
@@ -59,9 +59,8 @@
   return true;
 }
 
-bool NtlmBufferWriter::WriteBytes(base::StringPiece bytes) {
-  return WriteBytes(reinterpret_cast<const uint8_t*>(bytes.data()),
-                    bytes.length());
+bool NtlmBufferWriter::WriteBytes(const Buffer& bytes) {
+  return WriteBytes(bytes.data(), bytes.length());
 }
 
 bool NtlmBufferWriter::WriteZeros(size_t count) {
@@ -78,6 +77,34 @@
          WriteUInt32(sec_buf.offset);
 }
 
+bool NtlmBufferWriter::WriteAvPairHeader(ntlm::TargetInfoAvId avid,
+                                         uint16_t avlen) {
+  if (!CanWrite(ntlm::kAvPairHeaderLen))
+    return false;
+
+  bool result = WriteUInt16(static_cast<uint16_t>(avid)) && WriteUInt16(avlen);
+
+  DCHECK(result);
+  return result;
+}
+
+bool NtlmBufferWriter::WriteAvPairTerminator() {
+  return WriteAvPairHeader(ntlm::TargetInfoAvId::kEol, 0);
+}
+
+bool NtlmBufferWriter::WriteAvPair(const AvPair& pair) {
+  if (!WriteAvPairHeader(pair))
+    return false;
+
+  if (pair.avid == TargetInfoAvId::kFlags) {
+    if (pair.avlen != sizeof(uint32_t))
+      return false;
+    return WriteUInt32(static_cast<uint32_t>(pair.flags));
+  } else {
+    return WriteBytes(pair.buffer);
+  }
+}
+
 bool NtlmBufferWriter::WriteUtf8String(const std::string& str) {
   return WriteBytes(reinterpret_cast<const uint8_t*>(str.c_str()),
                     str.length());
diff --git a/net/ntlm/ntlm_buffer_writer.h b/net/ntlm/ntlm_buffer_writer.h
index ecda8cd8..eb8b748 100644
--- a/net/ntlm/ntlm_buffer_writer.h
+++ b/net/ntlm/ntlm_buffer_writer.h
@@ -75,9 +75,9 @@
   // the buffer, it returns false.
   bool WriteBytes(const uint8_t* buffer, size_t len) WARN_UNUSED_RESULT;
 
-  // Writes the bytes from the |base::StringPiece|. If there are not enough
+  // Writes the bytes from the |Buffer|. If there are not enough
   // bytes in the buffer, it returns false.
-  bool WriteBytes(base::StringPiece bytes) WARN_UNUSED_RESULT;
+  bool WriteBytes(const Buffer& buffer) WARN_UNUSED_RESULT;
 
   // Writes |count| bytes of zeros to the buffer. If there are not |count|
   // more bytes in available in the buffer, it returns false.
@@ -93,6 +93,30 @@
   //     uint32 - |offset| Offset from start of message
   bool WriteSecurityBuffer(SecurityBuffer sec_buf) WARN_UNUSED_RESULT;
 
+  // Writes an AvPair header. See [MS-NLMP] Section 2.2.2.1.
+  //
+  // The header has the following structure:
+  //    uint16 - |avid| The identifier of the following payload.
+  //    uint16 - |avlen| The length of the following payload.
+  bool WriteAvPairHeader(ntlm::TargetInfoAvId avid,
+                         uint16_t avlen) WARN_UNUSED_RESULT;
+
+  // Writes an AvPair header for an |AvPair|. See [MS-NLMP] Section 2.2.2.1.
+  bool WriteAvPairHeader(const AvPair& pair) WARN_UNUSED_RESULT {
+    return WriteAvPairHeader(pair.avid, pair.avlen);
+  }
+
+  // Writes a special AvPair header with both fields equal to 0. This zero
+  // length AvPair signals the end of the AvPair list.
+  bool WriteAvPairTerminator() WARN_UNUSED_RESULT;
+
+  // Writes an |AvPair| header and its payload to the buffer. If the |avid|
+  // is of type |TargetInfoAvId::kFlags| the |flags| field of |pair| will be
+  // used as the payload and the |buffer| field is ignored. In all other cases
+  // |buffer| is used as the payload. See also
+  // |NtlmBufferReader::ReadTargetInfo|.
+  bool WriteAvPair(const AvPair& pair) WARN_UNUSED_RESULT;
+
   // Writes a string of 8 bit characters to the buffer.
   //
   // When Unicode was not negotiated only the hostname string will go through
diff --git a/net/ntlm/ntlm_buffer_writer_unittest.cc b/net/ntlm/ntlm_buffer_writer_unittest.cc
index c05a1728..ab451cd 100644
--- a/net/ntlm/ntlm_buffer_writer_unittest.cc
+++ b/net/ntlm/ntlm_buffer_writer_unittest.cc
@@ -230,5 +230,22 @@
   ASSERT_FALSE(writer.WriteMessageType(MessageType::kNegotiate));
 }
 
+TEST(NtlmBufferWriterTest, WriteAvPairHeader) {
+  const uint8_t expected[4] = {0x06, 0x00, 0x11, 0x22};
+  NtlmBufferWriter writer(4);
+
+  ASSERT_TRUE(writer.WriteAvPairHeader(ntlm::TargetInfoAvId::kFlags, 0x2211));
+  ASSERT_TRUE(writer.IsEndOfBuffer());
+
+  ASSERT_EQ(0, memcmp(expected, GetBufferPtr(writer), arraysize(expected)));
+}
+
+TEST(NtlmBufferWriterTest, WriteAvPairHeaderPastEob) {
+  NtlmBufferWriter writer(ntlm::kAvPairHeaderLen - 1);
+
+  ASSERT_FALSE(writer.WriteAvPairHeader(ntlm::TargetInfoAvId::kFlags, 0x2211));
+  ASSERT_EQ(0u, writer.GetCursor());
+}
+
 }  // namespace ntlm
 }  // namespace net
diff --git a/net/ntlm/ntlm_client.cc b/net/ntlm/ntlm_client.cc
index a2b8f54..a034fd37 100644
--- a/net/ntlm/ntlm_client.cc
+++ b/net/ntlm/ntlm_client.cc
@@ -7,6 +7,7 @@
 #include <string.h>
 
 #include "base/logging.h"
+#include "base/md5.h"
 #include "base/strings/utf_string_conversions.h"
 #include "net/ntlm/ntlm.h"
 #include "net/ntlm/ntlm_buffer_reader.h"
@@ -30,12 +31,34 @@
          challenge_reader.ReadBytes(server_challenge, kChallengeLen);
 }
 
+// Parses the challenge message and extracts the information necessary to
+// make an NTLMv2 response.
+// |server_challenge| must contain at least 8 bytes.
+bool ParseChallengeMessageV2(const Buffer& challenge_message,
+                             NegotiateFlags* challenge_flags,
+                             uint8_t* server_challenge,
+                             std::vector<AvPair>* av_pairs) {
+  NtlmBufferReader challenge_reader(challenge_message);
+
+  return challenge_reader.MatchMessageHeader(MessageType::kChallenge) &&
+         challenge_reader.SkipSecurityBufferWithValidation() &&
+         challenge_reader.ReadFlags(challenge_flags) &&
+         challenge_reader.ReadBytes(server_challenge, kChallengeLen) &&
+         challenge_reader.SkipBytes(8) &&
+         // challenge_reader.ReadTargetInfoPayload(av_pairs);
+         (((*challenge_flags & NegotiateFlags::kTargetInfo) ==
+           NegotiateFlags::kTargetInfo)
+              ? challenge_reader.ReadTargetInfoPayload(av_pairs)
+              : true);
+}
+
 bool WriteAuthenticateMessage(NtlmBufferWriter* authenticate_writer,
                               SecurityBuffer lm_payload,
                               SecurityBuffer ntlm_payload,
                               SecurityBuffer domain_payload,
                               SecurityBuffer username_payload,
                               SecurityBuffer hostname_payload,
+                              SecurityBuffer session_key_payload,
                               NegotiateFlags authenticate_flags) {
   return authenticate_writer->WriteMessageHeader(MessageType::kAuthenticate) &&
          authenticate_writer->WriteSecurityBuffer(lm_payload) &&
@@ -43,18 +66,35 @@
          authenticate_writer->WriteSecurityBuffer(domain_payload) &&
          authenticate_writer->WriteSecurityBuffer(username_payload) &&
          authenticate_writer->WriteSecurityBuffer(hostname_payload) &&
-         authenticate_writer->WriteSecurityBuffer(
-             SecurityBuffer(kAuthenticateHeaderLenV1, 0)) &&
+         authenticate_writer->WriteSecurityBuffer(session_key_payload) &&
          authenticate_writer->WriteFlags(authenticate_flags);
 }
 
+// Writes the NTLMv1 LM Response and NTLM Response.
+// |lm_response| must contain |kResponseLenV1| bytes.
+// |ntlm_response| must contain |kResponseLenV1| bytes.
 bool WriteResponsePayloads(NtlmBufferWriter* authenticate_writer,
                            const uint8_t* lm_response,
-                           size_t lm_response_len,
-                           const uint8_t* ntlm_response,
-                           size_t ntlm_response_len) {
-  return authenticate_writer->WriteBytes(lm_response, lm_response_len) &&
-         authenticate_writer->WriteBytes(ntlm_response, ntlm_response_len);
+                           const uint8_t* ntlm_response) {
+  return authenticate_writer->WriteBytes(lm_response, kResponseLenV1) &&
+         authenticate_writer->WriteBytes(ntlm_response, kResponseLenV1);
+}
+
+// Writes the |lm_response| and writes the NTLMv2 response by concatenating
+// |v2_proof|, |v2_proof_input|, |updated_target_info| and 4 zero bytes.
+//
+// |lm_response| must contain |kResponseLenV1| bytes.
+// |v2_proof| must contain |kNtlmProofLenV2| bytes.
+bool WriteResponsePayloadsV2(NtlmBufferWriter* authenticate_writer,
+                             const uint8_t* lm_response,
+                             const uint8_t* v2_proof,
+                             const Buffer& v2_proof_input,
+                             const Buffer& updated_target_info) {
+  return authenticate_writer->WriteBytes(lm_response, kResponseLenV1) &&
+         authenticate_writer->WriteBytes(v2_proof, kNtlmProofLenV2) &&
+         authenticate_writer->WriteBytes(v2_proof_input) &&
+         authenticate_writer->WriteBytes(updated_target_info) &&
+         authenticate_writer->WriteUInt32(0);
 }
 
 bool WriteStringPayloads(NtlmBufferWriter* authenticate_writer,
@@ -96,10 +136,11 @@
 
 }  // namespace
 
-NtlmClient::NtlmClient() : negotiate_flags_(kNegotiateMessageFlags) {
+NtlmClient::NtlmClient(NtlmFeatures features)
+    : features_(features), negotiate_flags_(kNegotiateMessageFlags) {
   // Just generate the negotiate message once and hold on to it. It never
-  // changes and in a NTLMv2 it's used as an input
-  // to the Message Integrity Check in the Authenticate message.
+  // changes and in NTLMv2 it's used as an input to the Message Integrity
+  // Check (MIC) in the Authenticate message.
   GenerateNegotiateMessage();
 }
 
@@ -128,6 +169,9 @@
     const base::string16& username,
     const base::string16& password,
     const std::string& hostname,
+    const std::string& channel_bindings,
+    const std::string& spn,
+    uint64_t client_time,
     const uint8_t* client_challenge,
     const Buffer& server_challenge_message) const {
   // Limit the size of strings that are accepted. As an absolute limit any
@@ -149,26 +193,55 @@
 
   NegotiateFlags challenge_flags;
   uint8_t server_challenge[kChallengeLen];
-
-  // Read the flags and the server's random challenge from the challenge
-  // message.
-  if (!ParseChallengeMessage(server_challenge_message, &challenge_flags,
-                             server_challenge)) {
-    return Buffer();
-  }
-
-  // Calculate the responses for the authenticate message.
   uint8_t lm_response[kResponseLenV1];
   uint8_t ntlm_response[kResponseLenV1];
 
+  // Response fields only for NTLMv2
+  Buffer updated_target_info;
+  Buffer v2_proof_input;
+  uint8_t v2_proof[kNtlmProofLenV2];
+  uint8_t v2_session_key[kSessionKeyLenV2];
+
+  if (IsNtlmV2()) {
+    std::vector<AvPair> av_pairs;
+    if (!ParseChallengeMessageV2(server_challenge_message, &challenge_flags,
+                                 server_challenge, &av_pairs)) {
+      return Buffer();
+    }
+
+    uint64_t timestamp;
+    updated_target_info =
+        GenerateUpdatedTargetInfo(IsMicEnabled(), IsEpaEnabled(),
+                                  channel_bindings, spn, av_pairs, &timestamp);
+
+    memset(lm_response, 0, kResponseLenV1);
+    if (timestamp == UINT64_MAX) {
+      // If the server didn't send a time, then use the clients time.
+      timestamp = client_time;
+    }
+
+    uint8_t v2_hash[kNtlmHashLen];
+    GenerateNtlmHashV2(domain, username, password, v2_hash);
+    v2_proof_input = GenerateProofInputV2(timestamp, client_challenge);
+    GenerateNtlmProofV2(v2_hash, server_challenge, v2_proof_input,
+                        updated_target_info, v2_proof);
+    GenerateSessionBaseKeyV2(v2_hash, v2_proof, v2_session_key);
+  } else {
+    if (!ParseChallengeMessage(server_challenge_message, &challenge_flags,
+                               server_challenge)) {
+      return Buffer();
+    }
+
+    // Calculate the responses for the authenticate message.
+    GenerateResponsesV1WithSessionSecurity(password, server_challenge,
+                                           client_challenge, lm_response,
+                                           ntlm_response);
+  }
+
   // Always use extended session security even if the server tries to downgrade.
   NegotiateFlags authenticate_flags = (challenge_flags & negotiate_flags_) |
                                       NegotiateFlags::kExtendedSessionSecurity;
 
-  // Generate the LM and NTLM responses.
-  GenerateResponsesV1WithSessionSecurity(
-      password, server_challenge, client_challenge, lm_response, ntlm_response);
-
   // Calculate all the payload lengths and offsets.
   bool is_unicode = (authenticate_flags & NegotiateFlags::kUnicode) ==
                     NegotiateFlags::kUnicode;
@@ -178,21 +251,52 @@
   SecurityBuffer domain_info;
   SecurityBuffer username_info;
   SecurityBuffer hostname_info;
+  SecurityBuffer session_key_info;
   size_t authenticate_message_len;
-  CalculatePayloadLayout(is_unicode, domain, username, hostname, &lm_info,
-                         &ntlm_info, &domain_info, &username_info,
-                         &hostname_info, &authenticate_message_len);
+
+  CalculatePayloadLayout(is_unicode, domain, username, hostname,
+                         updated_target_info.size(), &lm_info, &ntlm_info,
+                         &domain_info, &username_info, &hostname_info,
+                         &session_key_info, &authenticate_message_len);
 
   NtlmBufferWriter authenticate_writer(authenticate_message_len);
   bool writer_result = WriteAuthenticateMessage(
       &authenticate_writer, lm_info, ntlm_info, domain_info, username_info,
-      hostname_info, authenticate_flags);
+      hostname_info, session_key_info, authenticate_flags);
   DCHECK(writer_result);
-  DCHECK_EQ(authenticate_writer.GetCursor(), GetAuthenticateHeaderLength());
 
-  writer_result =
-      WriteResponsePayloads(&authenticate_writer, lm_response, lm_info.length,
-                            ntlm_response, ntlm_info.length);
+  if (IsNtlmV2()) {
+    // Write the optional (for V1) Version and MIC fields. Note that they
+    // could also safely be sent in V1. However, the server should never try to
+    // read them, because neither the version negotiate flag nor the
+    // |TargetInfoAvFlags::kMicPresent| in the target info are set.
+    //
+    // Version is never supported so it is filled with zeros. MIC is a hash
+    // calculated over all 3 messages while the MIC is set to zeros then
+    // backfilled at the end if the MIC feature is enabled.
+    writer_result = authenticate_writer.WriteZeros(kVersionFieldLen) &&
+                    authenticate_writer.WriteZeros(kMicLenV2);
+
+    DCHECK(writer_result);
+  }
+
+  // Verify the location in the payload buffer.
+  DCHECK(authenticate_writer.GetCursor() == GetAuthenticateHeaderLength());
+  DCHECK(GetAuthenticateHeaderLength() == lm_info.offset);
+
+  if (IsNtlmV2()) {
+    // Write the response payloads for V2.
+    writer_result =
+        WriteResponsePayloadsV2(&authenticate_writer, lm_response, v2_proof,
+                                v2_proof_input, updated_target_info);
+  } else {
+    // Write the response payloads.
+    DCHECK_EQ(kResponseLenV1, lm_info.length);
+    DCHECK_EQ(kResponseLenV1, ntlm_info.length);
+    writer_result =
+        WriteResponsePayloads(&authenticate_writer, lm_response, ntlm_response);
+  }
+
   DCHECK(writer_result);
   DCHECK_EQ(authenticate_writer.GetCursor(), domain_info.offset);
 
@@ -202,7 +306,20 @@
   DCHECK(authenticate_writer.IsEndOfBuffer());
   DCHECK_EQ(authenticate_message_len, authenticate_writer.GetLength());
 
-  return authenticate_writer.Pass();
+  Buffer auth_msg = authenticate_writer.Pass();
+
+  // Backfill the MIC if enabled.
+  if (IsMicEnabled()) {
+    // The MIC has to be generated over all 3 completed messages with the MIC
+    // set to zeros.
+    DCHECK_LT(kMicOffsetV2 + kMicLenV2, authenticate_message_len);
+
+    uint8_t* mic_ptr = reinterpret_cast<uint8_t*>(&auth_msg[kMicOffsetV2]);
+    GenerateMicV2(v2_session_key, negotiate_message_, server_challenge_message,
+                  auth_msg, mic_ptr);
+  }
+
+  return auth_msg;
 }
 
 void NtlmClient::CalculatePayloadLayout(
@@ -210,20 +327,26 @@
     const base::string16& domain,
     const base::string16& username,
     const std::string& hostname,
+    size_t updated_target_info_len,
     SecurityBuffer* lm_info,
     SecurityBuffer* ntlm_info,
     SecurityBuffer* domain_info,
     SecurityBuffer* username_info,
     SecurityBuffer* hostname_info,
+    SecurityBuffer* session_key_info,
     size_t* authenticate_message_len) const {
   size_t upto = GetAuthenticateHeaderLength();
 
+  session_key_info->offset = upto;
+  session_key_info->length = 0;
+  upto += session_key_info->length;
+
   lm_info->offset = upto;
   lm_info->length = kResponseLenV1;
   upto += lm_info->length;
 
   ntlm_info->offset = upto;
-  ntlm_info->length = GetNtlmResponseLength();
+  ntlm_info->length = GetNtlmResponseLength(updated_target_info_len);
   upto += ntlm_info->length;
 
   domain_info->offset = upto;
@@ -242,10 +365,18 @@
 }
 
 size_t NtlmClient::GetAuthenticateHeaderLength() const {
+  if (IsNtlmV2()) {
+    return kAuthenticateHeaderLenV2;
+  }
+
   return kAuthenticateHeaderLenV1;
 }
 
-size_t NtlmClient::GetNtlmResponseLength() const {
+size_t NtlmClient::GetNtlmResponseLength(size_t updated_target_info_len) const {
+  if (IsNtlmV2()) {
+    return kNtlmResponseHeaderLenV2 + updated_target_info_len + 4;
+  }
+
   return kResponseLenV1;
 }
 
diff --git a/net/ntlm/ntlm_client.h b/net/ntlm/ntlm_client.h
index 94dd8c9..5ef1bd4 100644
--- a/net/ntlm/ntlm_client.h
+++ b/net/ntlm/ntlm_client.h
@@ -3,10 +3,13 @@
 // found in the LICENSE file.
 
 // Based on [MS-NLMP]: NT LAN Manager (NTLM) Authentication Protocol
-// Specification version 28.0 [1]. Additional NTLM reference [2].
+// Specification version 28.0 [1], an unofficial NTLM reference [2], and a
+// blog post describing Extended Protection for Authentication [3].
 //
 // [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
 // [2] http://davenport.sourceforge.net/ntlm.html
+// [3]
+// https://blogs.msdn.microsoft.com/openspecification/2013/03/26/ntlm-and-channel-binding-hash-aka-extended-protection-for-authentication/
 
 #ifndef NET_BASE_NTLM_CLIENT_H_
 #define NET_BASE_NTLM_CLIENT_H_
@@ -25,24 +28,59 @@
 namespace net {
 namespace ntlm {
 
-// Provides an implementation of an NTLMv1 Client.
+// Provides an implementation of an NTLMv1 or NTLMv2 Client with support
+// for MIC and EPA [1]. This implementation does not support the key exchange,
+// signing or sealing feature as the NTLMSSP_NEGOTIATE_KEY_EXCH flag is never
+// negotiated.
 //
-// The implementation supports NTLMv1 with extended session security (NTLM2).
+// [1] -
+// https://support.microsoft.com/en-us/help/968389/extended-protection-for-authentication
 class NET_EXPORT_PRIVATE NtlmClient {
  public:
-  NtlmClient();
+  // Pass feature flags to enable/disable NTLMv2 and additional NTLMv2
+  // features such as Extended Protection for Authentication (EPA) and Message
+  // Integrity Check (MIC).
+  explicit NtlmClient(NtlmFeatures features);
+
   ~NtlmClient();
 
+  bool IsNtlmV2() const { return features_.enable_NTLMv2; }
+
+  bool IsMicEnabled() const { return IsNtlmV2() && features_.enable_MIC; }
+
+  bool IsEpaEnabled() const { return IsNtlmV2() && features_.enable_EPA; }
+
   // Returns a |Buffer| containing the Negotiate message.
   Buffer GetNegotiateMessage() const;
 
   // Returns a |Buffer| containing the Authenticate message. If the method
   // fails an empty |Buffer| is returned.
   //
+  // |username| is treated case insensitively by NTLM however the mechanism
+  // to uppercase is not clearly defined. In this implementation the default
+  // locale is used. Additionally for names longer than 20 characters, the
+  // fully qualified name in the new '@' format must be used.
+  // eg. very_long_name@domain.com. Names shorter than 20 characters can
+  // optionally omit the '@domain.com' part.
   // |hostname| can be a short NetBIOS name or an FQDN, however the server will
   // only inspect this field if the default domain policy is to restrict NTLM.
   // In this case the hostname will be compared to a whitelist stored in this
   // group policy [1].
+  // |channel_bindings| is a string supplied out of band (usually from a web
+  // browser) and is a (21+sizeof(hash)) byte ASCII string, where 'hash' is
+  // usually a SHA-256 of the servers certificate, but may be another hash
+  // algorithm. The format as defined by RFC 5929 Section 4 is shown below;
+  //
+  // [0-20]                 - "tls-server-end-point:"   (Literal string)
+  // [21-(20+sizeof(hash)]  - HASH(server_certificate)  (Certificate hash)
+  //
+  // |spn| is a string supplied out of band (usually from a web browser) and
+  // is a Service  Principal Name [2]. For NTLM over HTTP the value of this
+  // string will usually be "HTTP/<hostname>".
+  // |client_time| 64 bit Windows timestamp defined as the number of
+  // 100 nanosecond ticks since midnight Jan 01, 1601 (UTC). If the server does
+  // not send a timestamp, the client timestamp is used in the Proof Input
+  // instead.
   // |client_challenge| must contain 8 bytes of random data.
   // |server_challenge_message| is the full content of the challenge message
   // sent by the server.
@@ -53,34 +91,64 @@
       const base::string16& username,
       const base::string16& password,
       const std::string& hostname,
+      const std::string& channel_bindings,
+      const std::string& spn,
+      uint64_t client_time,
       const uint8_t* client_challenge,
       const Buffer& server_challenge_message) const;
 
+  // Simplified method for NTLMv1 which does not require |channel_bindings|,
+  // |spn|, or |client_time|. See |GenerateAuthenticateMessage| for more
+  // details.
+  Buffer GenerateAuthenticateMessageV1(
+      const base::string16& domain,
+      const base::string16& username,
+      const base::string16& password,
+      const std::string& hostname,
+      const uint8_t* client_challenge,
+      const Buffer& server_challenge_message) const {
+    DCHECK(!IsNtlmV2());
+
+    return GenerateAuthenticateMessage(
+        domain, username, password, hostname, std::string(), std::string(), 0,
+        client_challenge, server_challenge_message);
+  }
+
  private:
-  // Calculates the lengths and offset for all the payloads in the message.
+  // Returns the length of the Authenticate message based on the length of the
+  // variable length parts of the message and whether Unicode support was
+  // negotiated.
+  size_t CalculateAuthenticateMessageLength(
+      bool is_unicode,
+      const base::string16& domain,
+      const base::string16& username,
+      const std::string& hostname,
+      size_t updated_target_info_len) const;
+
   void CalculatePayloadLayout(bool is_unicode,
                               const base::string16& domain,
                               const base::string16& username,
                               const std::string& hostname,
+                              size_t updated_target_info_len,
                               SecurityBuffer* lm_info,
                               SecurityBuffer* ntlm_info,
                               SecurityBuffer* domain_info,
                               SecurityBuffer* username_info,
                               SecurityBuffer* hostname_info,
+                              SecurityBuffer* session_key_info,
                               size_t* authenticate_message_len) const;
 
   // Returns the length of the header part of the Authenticate message.
-  // NOTE: When NTLMv2 support is added this is no longer a fixed value.
   size_t GetAuthenticateHeaderLength() const;
 
   // Returns the length of the NTLM response.
-  // NOTE: When NTLMv2 support is added this is no longer a fixed value.
-  size_t GetNtlmResponseLength() const;
+  size_t GetNtlmResponseLength(size_t updated_target_info_len) const;
 
   // Generates the negotiate message (which is always the same) into
   // |negotiate_message_|.
   void GenerateNegotiateMessage();
 
+  NtlmFeatures features_;
   NegotiateFlags negotiate_flags_;
   Buffer negotiate_message_;
 
diff --git a/net/ntlm/ntlm_client_fuzzer.cc b/net/ntlm/ntlm_client_fuzzer.cc
index e937f69..4f914bc 100644
--- a/net/ntlm/ntlm_client_fuzzer.cc
+++ b/net/ntlm/ntlm_client_fuzzer.cc
@@ -18,12 +18,16 @@
 }
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  net::ntlm::NtlmClient client;
+  base::FuzzedDataProvider fdp(data, size);
+  bool is_v2 = fdp.ConsumeBool();
+  uint64_t client_time =
+      ((uint64_t)fdp.ConsumeUint32InRange(0, 0xffffffffu) << 32) |
+      (uint64_t)fdp.ConsumeUint32InRange(0, 0xffffffffu);
+  net::ntlm::NtlmClient client((net::ntlm::NtlmFeatures(is_v2)));
 
   // Generate the input strings and challenge message. The strings will have a
   // maximum length 1 character longer than the maximum that |NtlmClient| will
   // accept to allow exploring the error cases.
-  base::FuzzedDataProvider fdp(data, size);
   base::string16 domain =
       ConsumeRandomLengthString16(fdp, net::ntlm::kMaxFqdnLen + 1);
   base::string16 username =
@@ -32,10 +36,14 @@
       ConsumeRandomLengthString16(fdp, net::ntlm::kMaxPasswordLen + 1);
   std::string hostname =
       fdp.ConsumeRandomLengthString(net::ntlm::kMaxFqdnLen + 1);
+  std::string channel_bindings = fdp.ConsumeRandomLengthString(150);
+  std::string spn =
+      fdp.ConsumeRandomLengthString(net::ntlm::kMaxFqdnLen + 5 + 1);
   std::string challenge_msg_bytes = fdp.ConsumeRemainingBytes();
 
   client.GenerateAuthenticateMessage(
-      domain, username, password, hostname, net::ntlm::test::kClientChallenge,
+      domain, username, password, hostname, channel_bindings, spn, client_time,
+      net::ntlm::test::kClientChallenge,
       net::ntlm::Buffer(
           reinterpret_cast<const uint8_t*>(challenge_msg_bytes.data()),
           challenge_msg_bytes.size()));
diff --git a/net/ntlm/ntlm_client_unittest.cc b/net/ntlm/ntlm_client_unittest.cc
index 7d785d4..07ddfa7 100644
--- a/net/ntlm/ntlm_client_unittest.cc
+++ b/net/ntlm/ntlm_client_unittest.cc
@@ -21,6 +21,7 @@
 Buffer GenerateAuthMsg(const NtlmClient& client, const Buffer& challenge_msg) {
   return client.GenerateAuthenticateMessage(
       test::kNtlmDomain, test::kUser, test::kPassword, test::kHostnameAscii,
+      test::kChannelBindings, test::kNtlmSpn, test::kClientTimestamp,
       test::kClientChallenge, challenge_msg);
 }
 
@@ -86,8 +87,16 @@
 
 }  // namespace
 
+TEST(NtlmClientTest, SimpleConstructionV1) {
+  NtlmClient client(NtlmFeatures(false));
+
+  ASSERT_FALSE(client.IsNtlmV2());
+  ASSERT_FALSE(client.IsEpaEnabled());
+  ASSERT_FALSE(client.IsMicEnabled());
+}
+
 TEST(NtlmClientTest, VerifyNegotiateMessageV1) {
-  NtlmClient client;
+  NtlmClient client(NtlmFeatures(false));
 
   Buffer result = client.GetNegotiateMessage();
 
@@ -97,7 +106,7 @@
 }
 
 TEST(NtlmClientTest, MinimalStructurallyValidChallenge) {
-  NtlmClient client;
+  NtlmClient client(NtlmFeatures(false));
 
   NtlmBufferWriter writer(kMinChallengeHeaderLen);
   ASSERT_TRUE(
@@ -107,7 +116,7 @@
 }
 
 TEST(NtlmClientTest, MinimalStructurallyValidChallengeZeroOffset) {
-  NtlmClient client;
+  NtlmClient client(NtlmFeatures(false));
 
   // The spec (2.2.1.2) states that the length SHOULD be 0 and the offset
   // SHOULD be where the payload would be if it was present. This is the
@@ -127,7 +136,7 @@
 }
 
 TEST(NtlmClientTest, ChallengeMsgTooShort) {
-  NtlmClient client;
+  NtlmClient client(NtlmFeatures(false));
 
   // Fail because the minimum size valid message is 32 bytes.
   NtlmBufferWriter writer(kMinChallengeHeaderLen - 1);
@@ -137,7 +146,7 @@
 }
 
 TEST(NtlmClientTest, ChallengeMsgNoSig) {
-  NtlmClient client;
+  NtlmClient client(NtlmFeatures(false));
 
   // Fail because the first 8 bytes don't match "NTLMSSP\0"
   uint8_t raw[kMinChallengeHeaderLen];
@@ -152,7 +161,7 @@
 }
 
 TEST(NtlmClientTest, ChallengeMsgWrongMessageType) {
-  NtlmClient client;
+  NtlmClient client(NtlmFeatures(false));
 
   // Fail because the message type should be MessageType::kChallenge
   // (0x00000002)
@@ -169,7 +178,7 @@
 }
 
 TEST(NtlmClientTest, ChallengeWithNoTargetName) {
-  NtlmClient client;
+  NtlmClient client(NtlmFeatures(false));
 
   // The spec (2.2.1.2) states that the length SHOULD be 0 and the offset
   // SHOULD be where the payload would be if it was present. This is the
@@ -189,7 +198,7 @@
 }
 
 TEST(NtlmClientTest, Type2MessageWithTargetName) {
-  NtlmClient client;
+  NtlmClient client(NtlmFeatures(false));
 
   // One extra byte is provided for target name.
   uint8_t raw[kMinChallengeHeaderLen + 1];
@@ -208,12 +217,11 @@
 
   NtlmBufferWriter writer(kChallengeHeaderLen + 1);
   ASSERT_TRUE(writer.WriteBytes(raw, arraysize(raw)));
-
   ASSERT_TRUE(GetAuthMsgResult(client, writer));
 }
 
 TEST(NtlmClientTest, NoTargetNameOverflowFromOffset) {
-  NtlmClient client;
+  NtlmClient client(NtlmFeatures(false));
 
   uint8_t raw[kMinChallengeHeaderLen];
   memcpy(raw, test::kMinChallengeMessage, kMinChallengeHeaderLen);
@@ -236,7 +244,7 @@
 }
 
 TEST(NtlmClientTest, NoTargetNameOverflowFromLength) {
-  NtlmClient client;
+  NtlmClient client(NtlmFeatures(false));
 
   // Message has 1 extra byte of space after the header for the target name.
   // One extra byte is provided for target name.
@@ -264,19 +272,20 @@
 }
 
 TEST(NtlmClientTest, Type3UnicodeWithSessionSecuritySpecTest) {
-  NtlmClient client;
+  NtlmClient client(NtlmFeatures(false));
 
   Buffer result = GenerateAuthMsg(client, test::kChallengeMsgV1,
                                   arraysize(test::kChallengeMsgV1));
 
   ASSERT_FALSE(result.empty());
-  ASSERT_EQ(arraysize(test::kExpectedAuthenticateMsgV1), result.size());
-  ASSERT_EQ(0, memcmp(test::kExpectedAuthenticateMsgV1, result.data(),
-                      result.size()));
+  ASSERT_EQ(arraysize(test::kExpectedAuthenticateMsgSpecResponseV1),
+            result.size());
+  ASSERT_EQ(0, memcmp(test::kExpectedAuthenticateMsgSpecResponseV1,
+                      result.data(), result.size()));
 }
 
 TEST(NtlmClientTest, Type3WithoutUnicode) {
-  NtlmClient client;
+  NtlmClient client(NtlmFeatures(false));
 
   Buffer result = GenerateAuthMsg(client, test::kMinChallengeMessageNoUnicode,
                                   kMinChallengeHeaderLen);
@@ -319,7 +328,7 @@
 }
 
 TEST(NtlmClientTest, ClientDoesNotDowngradeSessionSecurity) {
-  NtlmClient client;
+  NtlmClient client(NtlmFeatures(false));
 
   Buffer result = GenerateAuthMsg(client, test::kMinChallengeMessageNoSS,
                                   kMinChallengeHeaderLen);
@@ -365,5 +374,58 @@
             flags & NegotiateFlags::kExtendedSessionSecurity);
 }
 
+// ------------------------------------------------
+// NTLM V2 specific tests.
+// ------------------------------------------------
+
+TEST(NtlmClientTest, SimpleConstructionV2) {
+  NtlmClient client(NtlmFeatures(true));
+
+  ASSERT_TRUE(client.IsNtlmV2());
+  ASSERT_TRUE(client.IsEpaEnabled());
+  ASSERT_TRUE(client.IsMicEnabled());
+}
+
+TEST(NtlmClientTest, VerifyNegotiateMessageV2) {
+  NtlmClient client(NtlmFeatures(true));
+
+  Buffer result = client.GetNegotiateMessage();
+  ASSERT_FALSE(result.empty());
+  ASSERT_EQ(arraysize(test::kExpectedNegotiateMsg), result.size());
+  ASSERT_EQ(0,
+            memcmp(test::kExpectedNegotiateMsg, result.data(), result.size()));
+}
+
+TEST(NtlmClientTest, VerifyAuthenticateMessageV2) {
+  // Generate the auth message from the client based on the test challenge
+  // message.
+  NtlmClient client(NtlmFeatures(true));
+  Buffer result = GenerateAuthMsg(client, test::kChallengeMsgFromSpecV2,
+                                  arraysize(test::kChallengeMsgFromSpecV2));
+  ASSERT_FALSE(result.empty());
+  ASSERT_EQ(arraysize(test::kExpectedAuthenticateMsgSpecResponseV2),
+            result.size());
+  ASSERT_EQ(0, memcmp(test::kExpectedAuthenticateMsgSpecResponseV2,
+                      result.data(), result.size()));
+}
+
+TEST(NtlmClientTest,
+     VerifyAuthenticateMessageInResponseToChallengeWithoutTargetInfoV2) {
+  // Test how the V2 client responds when the server sends a challenge that
+  // does not contain target info. eg. Windows 2003 and earlier do not send
+  // this. See [MS-NLMP] Appendix B Item 8. These older Windows servers
+  // support NTLMv2 but don't send target info. Other implementations may
+  // also be affected.
+  NtlmClient client(NtlmFeatures(true));
+  Buffer result = GenerateAuthMsg(client, test::kChallengeMsgV1,
+                                  arraysize(test::kChallengeMsgV1));
+  ASSERT_FALSE(result.empty());
+
+  ASSERT_EQ(arraysize(test::kExpectedAuthenticateMsgToOldV1ChallegeV2),
+            result.size());
+  ASSERT_EQ(0, memcmp(test::kExpectedAuthenticateMsgToOldV1ChallegeV2,
+                      result.data(), result.size()));
+}
+
 }  // namespace ntlm
 }  // namespace net
diff --git a/net/ntlm/ntlm_constants.h b/net/ntlm/ntlm_constants.h
index cebba53..d74e38b 100644
--- a/net/ntlm/ntlm_constants.h
+++ b/net/ntlm/ntlm_constants.h
@@ -32,9 +32,19 @@
   uint16_t length;
 };
 
-enum class NtlmVersion {
-  kNtlmV1 = 0x01,
-  kNtlmV2 = 0x02,
+struct NtlmFeatures {
+  explicit NtlmFeatures(bool enable_NTLMv2) : enable_NTLMv2(enable_NTLMv2) {}
+
+  // Whether the use NTLMv2.
+  bool enable_NTLMv2 = true;
+
+  // Enables Message Integrity Check (MIC). This flag is ignored if
+  // enable_NTLMv2 is false.
+  bool enable_MIC = true;
+
+  // Enables Extended Protection for Authentication (EPA). This flag is
+  // ignored if enable_NTLMv2 is false.
+  bool enable_EPA = true;
 };
 
 // There are 3 types of messages in NTLM. The message type is a field in
@@ -55,6 +65,7 @@
   kNtlm = 0x200,
   kAlwaysSign = 0x8000,
   kExtendedSessionSecurity = 0x80000,
+  kTargetInfo = 0x800000,
 };
 
 constexpr inline NegotiateFlags operator|(NegotiateFlags lhs,
@@ -73,17 +84,96 @@
                                      static_cast<TFlagsInt>(rhs));
 }
 
+// Identifies the payload type in an AV Pair. See [MS-NLMP] 2.2.2.1
+enum class TargetInfoAvId : uint16_t {
+  kEol = 0x0000,
+  kServerName = 0x00001,
+  kDomainName = 0x00002,
+  kFlags = 0x0006,
+  kTimestamp = 0x0007,
+  kTargetName = 0x0009,
+  kChannelBindings = 0x000A,
+};
+
+// Flags used in an TargetInfoAvId::kFlags AV Pair. See [MS-NLMP] 2.2.2.1
+enum class TargetInfoAvFlags : uint32_t {
+  kNone = 0,
+  kMicPresent = 0x00000002,
+};
+
+using TAvFlagsInt = std::underlying_type<TargetInfoAvFlags>::type;
+
+constexpr inline TargetInfoAvFlags operator|(TargetInfoAvFlags lhs,
+                                             TargetInfoAvFlags rhs) {
+  return static_cast<TargetInfoAvFlags>(static_cast<TAvFlagsInt>(lhs) |
+                                        static_cast<TAvFlagsInt>(rhs));
+}
+
+constexpr inline TargetInfoAvFlags operator&(TargetInfoAvFlags lhs,
+                                             TargetInfoAvFlags rhs) {
+  return static_cast<TargetInfoAvFlags>(static_cast<TAvFlagsInt>(lhs) &
+                                        static_cast<TAvFlagsInt>(rhs));
+}
+
+// An AV Pair is a structure that appears inside the target info field. It
+// consists of an |avid| to identify the data type and an |avlen| specifying
+// the size of the payload. Following that is |avlen| bytes of inline payload.
+// AV Pairs are concatenated together and a special terminator with |avid|
+// equal to |kEol| and |avlen| equal to zero signals that no further pairs
+// follow. See [MS-NLMP] 2.2.2.1
+//
+// AV Pairs from the Challenge message are read from the challenge message
+// and a potentially modified version is written into the authenticate
+// message. In some cases the existing AV Pair is modified, eg. flags. In
+// some cases new AV Pairs are add, eg. channel bindings and spn.
+//
+// For simplicity of processing two special fields |flags|, and |timestamp|
+// are populated during the initial parsing phase for AVIDs |kFlags| and
+// |kTimestamp| respectively. This avoids subsequent code having to
+// manipulate the payload value through the buffer directly. For all
+// other AvPairs the value of these 2 fields is undefined and the payload
+// is in the |buffer| field. For these fields the payload is copied verbatim
+// and it's content is not read or validated in any way.
+struct AvPair {
+  AvPair() {}
+  AvPair(TargetInfoAvId avid, uint16_t avlen) : avid(avid), avlen(avlen) {}
+  AvPair(TargetInfoAvId avid, Buffer buffer)
+      : buffer(std::move(buffer)), avid(avid) {
+    avlen = this->buffer.size();
+  }
+
+  Buffer buffer;
+  uint64_t timestamp;
+  TargetInfoAvFlags flags;
+  TargetInfoAvId avid;
+  uint16_t avlen;
+};
+
 static constexpr uint8_t kSignature[] = "NTLMSSP";
 static constexpr size_t kSignatureLen = arraysize(kSignature);
+static constexpr uint16_t kProofInputVersionV2 = 0x0101;
 static constexpr size_t kSecurityBufferLen =
     (2 * sizeof(uint16_t)) + sizeof(uint32_t);
 static constexpr size_t kNegotiateMessageLen = 32;
 static constexpr size_t kMinChallengeHeaderLen = 32;
-static constexpr size_t kChallengeHeaderLen = 32;
+static constexpr size_t kChallengeHeaderLen = 48;
 static constexpr size_t kResponseLenV1 = 24;
 static constexpr size_t kChallengeLen = 8;
+static constexpr size_t kVersionFieldLen = 8;
 static constexpr size_t kNtlmHashLen = 16;
+static constexpr size_t kNtlmProofLenV2 = kNtlmHashLen;
+static constexpr size_t kSessionKeyLenV2 = kNtlmHashLen;
+static constexpr size_t kMicLenV2 = kNtlmHashLen;
+static constexpr size_t kChannelBindingsHashLen = kNtlmHashLen;
+static constexpr size_t kEpaUnhashedStructHeaderLen = 20;
+static constexpr size_t kProofInputLenV2 = 28;
+static constexpr size_t kAvPairHeaderLen = 2 * sizeof(uint16_t);
+static constexpr size_t kNtlmResponseHeaderLenV2 =
+    kNtlmProofLenV2 + kProofInputLenV2;
 static constexpr size_t kAuthenticateHeaderLenV1 = 64;
+static constexpr size_t kMicOffsetV2 = 72;
+static constexpr size_t kAuthenticateHeaderLenV2 = 88;
+
 static constexpr size_t kMaxFqdnLen = 255;
 static constexpr size_t kMaxUsernameLen = 104;
 static constexpr size_t kMaxPasswordLen = 256;
diff --git a/net/ntlm/ntlm_test_data.h b/net/ntlm/ntlm_test_data.h
index 5f14749..eed3b0d 100644
--- a/net/ntlm/ntlm_test_data.h
+++ b/net/ntlm/ntlm_test_data.h
@@ -5,7 +5,13 @@
 // This file contains common input and result values use to verify the NTLM
 // implementation. They are defined in [MS-NLMP] Section 4.2 [1].
 //
+// [MS-NLMP] has no test data for Extended Protection for Authentication (EPA).
+// Test vectors related to EPA (aka Channel Binding) have been taken from
+// a Microsoft blog post [2].
+//
 // [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
+// [2] https://blogs.msdn.microsoft.com/openspecification/2013/03/26/ntlm-and-
+//         channel-binding-hash-aka-extended-protection-for-authentication/
 
 #ifndef NET_BASE_NTLM_TEST_DATA_H_
 #define NET_BASE_NTLM_TEST_DATA_H_
@@ -20,17 +26,46 @@
 constexpr base::char16 kPassword[] = {'P', 'a', 's', 's', 'w',
                                       'o', 'r', 'd', '\0'};
 constexpr base::char16 kNtlmDomain[] = {'D', 'o', 'm', 'a', 'i', 'n', '\0'};
+constexpr uint8_t kNtlmDomainRaw[] = {'D', 0x00, 'o', 0x00, 'm', 0x00,
+                                      'a', 0x00, 'i', 0x00, 'n', 0x00};
 constexpr base::char16 kUser[] = {'U', 's', 'e', 'r', '\0'};
 constexpr base::char16 kDomainUserCombined[] = {'D',  'o', 'm', 'a', 'i', 'n',
                                                 '\\', 'U', 's', 'e', 'r', '\0'};
 constexpr base::char16 kHostname[] = {'C', 'O', 'M', 'P', 'U',
                                       'T', 'E', 'R', '\0'};
+constexpr base::char16 kServer[] = {'S', 'e', 'r', 'v', 'e', 'r', '\0'};
+constexpr uint8_t kServerRaw[] = {'S', 0x00, 'e', 0x00, 'r', 0x00,
+                                  'v', 0x00, 'e', 0x00, 'r', 0x00};
 
 // ASCII Versions of the above strings.
 constexpr char kNtlmDomainAscii[] = "Domain";
 constexpr char kUserAscii[] = "User";
 constexpr char kHostnameAscii[] = "COMPUTER";
 
+// Test data obtained from [2].
+constexpr char kChannelBindings[] = {
+    't',  'l',  's',  '-',  's',  'e',  'r',  'v',  'e',  'r',  '-',
+    'e',  'n',  'd',  '-',  'p',  'o',  'i',  'n',  't',  ':',  0xea,
+    0x05, 0xfe, 0xfe, 0xcc, 0x6b, 0x0b, 0xd5, 0x71, 0xdb, 0xbc, 0x5b,
+    0xaa, 0x3e, 0xd4, 0x53, 0x86, 0xd0, 0x44, 0x68, 0x35, 0xf7, 0xb7,
+    0x4c, 0x85, 0x62, 0x1b, 0x99, 0x83, 0x47, 0x5f, 0x95, '\0'};
+
+constexpr char kNtlmSpn[] = {'H', 'T', 'T', 'P', '/', 'S',
+                             'e', 'r', 'v', 'e', 'r', '\0'};
+constexpr uint8_t kNtlmSpnRaw[] = {'H', 0x00, 'T', 0x00, 'T', 0x00, 'P', 0x00,
+                                   '/', 0x00, 'S', 0x00, 'e', 0x00, 'r', 0x00,
+                                   'v', 0x00, 'e', 0x00, 'r', 0x00};
+
+// Input value defined in [MS-NLMP] Section 4.2.1.
+constexpr uint64_t kServerTimestamp = 0;
+
+// Arbitrary value for client timestamp. The spec does not provide test data
+// or scenarios involving the client timestamp. The relevant thing is that it
+// is not equal to |kServerTimestamp| so it can be determined which timestamp
+// is within the message.
+// Tue, 23 May 2017 20:13:07 +0000
+constexpr uint64_t kClientTimestamp = 131400439870000000;
+
 // Challenge vectors defined in [MS-NLMP] Section 4.2.1.
 constexpr uint8_t kServerChallenge[kChallengeLen] = {0x01, 0x23, 0x45, 0x67,
                                                      0x89, 0xab, 0xcd, 0xef};
@@ -46,17 +81,30 @@
     0x06, 0x00, 0x70, 0x17, 0x00, 0x00, 0x00, 0x0f, 0x53, 0x00, 0x65, 0x00,
     0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00};
 
+// Test input defined in [MS-NLMP] Section 4.2.4.3.
+constexpr uint8_t kChallengeMsgFromSpecV2[] = {
+    0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00,
+    0x0c, 0x00, 0x0c, 0x00, 0x38, 0x00, 0x00, 0x00, 0x33, 0x82, 0x8a, 0xe2,
+    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x24, 0x00, 0x44, 0x00, 0x00, 0x00,
+    0x06, 0x00, 0x70, 0x17, 0x00, 0x00, 0x00, 0x0f, 0x53, 0x00, 0x65, 0x00,
+    0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x02, 0x00, 0x0c, 0x00,
+    0x44, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00,
+    0x01, 0x00, 0x0c, 0x00, 0x53, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00,
+    0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
 // A minimal challenge message for tests. For NTLMv1 this implementation only
 // reads the smallest required version of the message (32 bytes). Some
 // servers may still send messages this small. The only relevant flags
 // that affect behavior are that both NTLMSSP_NEGOTIATE_UNICODE and
 // NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY are set.
 //
-// [0-7]    - "NTLMSSP\0"                       (Signature)
+// [0-7]    - "NTLMSSP\0"                        (Signature)
 // [9-11]   - |MessageType::kChallenge|          (Message Type = 0x00000002)
-// [12-19]  - |SecBuf(kNegotiateMessageLen, 0)|(Target Name - Not Used)
-// [20-23]  - |NEGOTIATE_MESSAGE_FLAGS|         (Flags = 0x00088207)
-// [24-31]  - |SERVER_CHALLENGE|                (Server Challenge)
+// [12-19]  - |SecBuf(kNegotiateMessageLen, 0)|  (Target Name - Not Used)
+// [20-23]  - |kNegotiateMessageFlags|           (Flags = 0x00088207)
+// [24-31]  - |kServerChallenge|                 (Server Challenge)
 //
 // See [MS-NLMP] Section 2.2.2.2 for more information about the Challenge
 // message.
@@ -84,6 +132,11 @@
     0xa4, 0xf4, 0x9c, 0x40, 0x65, 0x10, 0xbd, 0xca,
     0xb6, 0x82, 0x4e, 0xe7, 0xc3, 0x0f, 0xd8, 0x52};
 
+// Test result value for NTOWFv2() defined in [MS-NLMP] Section 4.2.4.1.1.
+constexpr uint8_t kExpectedNtlmHashV2[kNtlmHashLen] = {
+    0x0c, 0x86, 0x8a, 0x40, 0x3b, 0xfd, 0x7a, 0x93,
+    0xa3, 0x00, 0x1e, 0xf2, 0x2e, 0xf0, 0x2e, 0x3f};
+
 // Test result value defined in [MS-NLMP] Section 4.2.2.1.
 constexpr uint8_t kExpectedNtlmResponseV1[kResponseLenV1] = {
     0x67, 0xc4, 0x30, 0x11, 0xf3, 0x02, 0x98, 0xa2, 0xad, 0x35, 0xec, 0xe6,
@@ -99,12 +152,170 @@
     0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
+// Test result value defined in [MS-NLMP] Section 4.2.4.1.3.
+//
+// "temp" is defined in Section 3.3.2 and is part of the data to be hashed
+// to generate the NTLMv2 Proof. It is composed of 3 parts;
+//
+// 1) [0-27] A fixed length part in the first 28 (|kProofInputLenV2|) bytes
+// which in this implementation is generated by |GenerateProofInputV2|.
+//
+// 2) [28-63] A variable length part which the spec calls "ServerName" but
+// defines as the AV Pairs (aka Target Information) from the Authenticate
+// message. See |kExpectedTargetInfoFromSpecV2| for more information.
+//
+// 3) [64-68] 4 zero bytes.
+//
+// NOTE: The timestamp (bytes [8-15]) should not actually be 0 here. In order
+// to use the test data from the spec some lower level tests do generate this
+// value. The target info sent by the server does not contain a timestamp
+// AvPair, and section 3.1.5.1.2 states that the client should populate the
+// timestamp with the servers timestamp if it exists, otherwise with the
+// client's local time. For end to end tests the alternate value
+// |kExpectedTempWithClientTimestampV2| below is used for end to end tests.
+// Having different test data for the server and client time allows testing
+// the logic more correctly.
+constexpr uint8_t kExpectedTempFromSpecV2[] = {
+    0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+    0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x44, 0x00, 0x6f, 0x00,
+    0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x01, 0x00, 0x0c, 0x00,
+    0x53, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+// This value is the same as |kExpectedTempFromSpecV2| but with the timestamp
+// field at bytes [8-15] populated with |kClientTimestamp|.
+constexpr uint8_t kExpectedTempWithClientTimestampV2[] = {
+    0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0b, 0xc8, 0xfd,
+    0x00, 0xd4, 0xd2, 0x01, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+    0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x44, 0x00, 0x6f, 0x00,
+    0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x01, 0x00, 0x0c, 0x00,
+    0x53, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+// Test result value defined (indirectly) in [MS-NLMP] Section 4.2.4.
+//
+// This is part 2 (bytes [28-63]) of |kExpectedTempFromSpecV2|. Additional
+// notes;
+//
+// a) The spec defines the AV Pairs to be in the opposite order to which they
+//    actually appear in the output in Section 4.2.4.1.3.
+//
+// b) The implicit presence of a terminating AV Pair is not mentioned.
+//
+// c) Section 4.2.4 does not show the byte sequences of the AV Pair Headers.
+//
+// NOTE: The real implementation in default settings would not have such a
+// simple set of AV Pairs since a flags field to indicate the presence of a
+// MIC, and a channel bindings field would also have been added.
+constexpr uint8_t kExpectedTargetInfoFromSpecV2[] = {
+    0x02, 0x00, 0x0c, 0x00, 0x44, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00,
+    0x69, 0x00, 0x6e, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x53, 0x00, 0x65, 0x00,
+    0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+// This target info is to test the behavior when a server timestamp is
+// present. It is the same as |kExpectedTargetInfoFromSpecV2| but with
+// an additional timestamp AvPair.
+constexpr uint8_t kExpectedTargetInfoFromSpecPlusServerTimestampV2[] = {
+    0x02, 0x00, 0x0c, 0x00, 0x44, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00,
+    0x69, 0x00, 0x6e, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x53, 0x00, 0x65, 0x00,
+    0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x07, 0x00, 0x08, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+// The target info after being updated by the client when the server sends
+// |kExpectedTargetInfoFromSpecV2| in the challenge message with both EPA and
+// MIC enabled.
+//
+// When MIC and EPA are enabled, 3 additional AvPairs are added.
+// 1) A flags AVPair with the MIC_PRESENT bit set.
+// 2) A channel bindings AVPair containing the channel bindings hash.
+// 3) A target name AVPair containing the SPN of the server.
+//
+// AvPair 1 [0-1]    |TargetInfoAvId::kDomainName|      Av ID = 0x0002
+// AvPair 1 [2-3]    |len(kNtlmDomainRaw)|              Av Length = 0x000c
+// AvPair 1 [4-15]   |kNtlmDomainRaw|                   Av Payload = L"Domain"
+//
+// AvPair 2 [16-17]  |TargetInfoAvId::kServerName|      Av ID = 0x0001
+// AvPair 2 [18-19]  |len(kServerRaw)|                  Av Length = 0x000c
+// AvPair 2 [20-31]  |kServerRaw|                       Av Payload = L"Server"
+//
+// AvPair 3 [32-33]  |TargetInfoAvId::kFlags|           Av ID = 0x0006
+// AvPair 3 [34-35]  |sizeof(uint32_t)|                 Av Length = 0x0004
+// AvPair 3 [36-39]  |TargetInfoAvFlags::kMicPresent|   Av Payload = 0x00000002
+//
+// AvPair 4 [40-41]  |TargetInfoAvId::kChannelBindings| Av ID = 0x000a
+// AvPair 4 [42-43]  |kChannelBindingsHashLen|          Av Length = 0x0010
+// AvPair 4 [44-59]  |kExpectedChannelBindingHashV2|    Av Payload
+//
+// AvPair 5 [60-61]  |TargetInfoAvId::kTargetName|      Av ID = 0x0009
+// AvPair 5 [62-63]  |len(kNtlmSpnRaw)|                 Av Length = 0x0016
+// AvPair 5 [64-85]  |kNtlmSpnRaw|                      Av Payload =
+//                                                          L"HTTP/Server"
+//
+// AvPair 6 [86-87]  |TargetInfoAvId::kEol|             Av ID = 0x0000
+// AvPair 6 [88-89]                                     Av Length = 0x0000
+constexpr uint8_t kExpectedTargetInfoSpecResponseV2[] = {
+    0x02, 0x00, 0x0c, 0x00, 'D',  0x00, 'o',  0x00, 'm',  0x00, 'a',  0x00,
+    'i',  0x00, 'n',  0x00, 0x01, 0x00, 0x0c, 0x00, 'S',  0x00, 'e',  0x00,
+    'r',  0x00, 'v',  0x00, 'e',  0x00, 'r',  0x00, 0x06, 0x00, 0x04, 0x00,
+    0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x65, 0x86, 0xE9, 0x9D,
+    0x81, 0xC2, 0xFC, 0x98, 0x4E, 0x47, 0x17, 0x2F, 0xD4, 0xDD, 0x03, 0x10,
+    0x09, 0x00, 0x16, 0x00, 'H',  0x00, 'T',  0x00, 'T',  0x00, 'P',  0x00,
+    '/',  0x00, 'S',  0x00, 'e',  0x00, 'r',  0x00, 'v',  0x00, 'e',  0x00,
+    'r',  0x00, 0x00, 0x00, 0x00, 0x00};
+
+// Test result value defined in [MS-NLMP] Section 4.2.4.2.2.
+constexpr uint8_t kExpectedProofFromSpecV2[kNtlmProofLenV2] = {
+    0x68, 0xcd, 0x0a, 0xb8, 0x51, 0xe5, 0x1c, 0x96,
+    0xaa, 0xbc, 0x92, 0x7b, 0xeb, 0xef, 0x6a, 0x1c};
+
+// The value of the NTLMv2 proof when |kExpectedTargetInfoSpecResponseV2| is
+// the updated target info in the Authenticate message.
+constexpr uint8_t kExpectedProofSpecResponseV2[kNtlmProofLenV2] = {
+    0x01, 0x0c, 0x0b, 0xd1, 0x4e, 0xf7, 0xa2, 0x96,
+    0x89, 0xc0, 0xc1, 0x9c, 0xea, 0xe8, 0xb7, 0xdf};
+
+// The value of the NTLMv2 proof when |kExpectedTargetInfoSpecResponseV2| is
+// the updated target info, and |kClientTimestamp| is correctly set in the
+// Authenticate message.
+constexpr uint8_t
+    kExpectedProofSpecResponseWithClientTimestampV2[kNtlmProofLenV2] = {
+        0x8c, 0x02, 0x60, 0xdb, 0xef, 0x69, 0x06, 0x62,
+        0xaf, 0x9c, 0x42, 0xd5, 0x07, 0x82, 0xd2, 0xed};
+
+// Test result data obtained from [2].
+constexpr uint8_t kExpectedChannelBindingHashV2[kChannelBindingsHashLen] = {
+    0x65, 0x86, 0xE9, 0x9D, 0x81, 0xC2, 0xFC, 0x98,
+    0x4E, 0x47, 0x17, 0x2F, 0xD4, 0xDD, 0x03, 0x10};
+
+// Test result value defined in [MS-NLMP] Section 4.2.4.1.2.
+constexpr uint8_t kExpectedSessionBaseKeyFromSpecV2[kSessionKeyLenV2] = {
+    0x8d, 0xe4, 0x0c, 0xca, 0xdb, 0xc1, 0x4a, 0x82,
+    0xf1, 0x5c, 0xb0, 0xad, 0x0d, 0xe9, 0x5c, 0xa3};
+
+// The session base key when the proof is
+// |kExpectedProofSpecResponseWithClientTimestampV2|.
+constexpr uint8_t
+    kExpectedSessionBaseKeyWithClientTimestampV2[kSessionKeyLenV2] = {
+        0x62, 0x3d, 0xbd, 0x07, 0x1b, 0xe7, 0xa5, 0x30,
+        0xb6, 0xa9, 0x5c, 0x2e, 0xb4, 0x98, 0x24, 0x70};
+
+// The Message Integrity Check (MIC) using
+// |kExpectedSessionBaseKeyWithClientTimestampV2| over the following 3
+// messages; |kExpectedNegotiateMsg|, |kChallengeMsgFromSpecV2|, and
+// |kExpectedAuthenticateMsgSpecResponseV2|.
+// The MIC field in |kExpectedAuthenticateMsgSpecResponseV2| is set to all
+// zeros while calculating the hash.
+constexpr uint8_t kExpectedMicV2[kMicLenV2] = {
+    0xf7, 0x36, 0x16, 0x33, 0xf0, 0xad, 0x9b, 0xdf,
+    0x4a, 0x7c, 0x42, 0x1b, 0xc6, 0xb8, 0x24, 0xa3};
+
 // Expected negotiate message from this implementation.
 // [0-7]    - "NTLMSSP\0"                       (Signature)
-// [9-11]   - |MessageType::NEGOTIATE|          (Message Type = 0x00000001)
-// [12-15]  - |NEGOTIATE_MESSAGE_FLAGS|         (Flags = 0x00088207)
-// [16-23]  - |SecBuf(kNegotiateMessageLen, 0)|(Domain)
-// [24-32]  - |SecBuf(kNegotiateMessageLen, 0)|(Workstation)
+// [9-11]   - |MessageType::kNegotiate|         (Message Type = 0x00000001)
+// [12-15]  - |kNegotiateMessageFlags|          (Flags = 0x00088207)
+// [16-23]  - |SecBuf(kNegotiateMessageLen, 0)| (Domain)
+// [24-32]  - |SecBuf(kNegotiateMessageLen, 0)| (Workstation)
 //
 // NOTE: Message does not include Version field. Since
 // NTLMSSP_NEGOTIATE_VERSION is never sent, it is not required, and the server
@@ -132,8 +343,8 @@
 //
 // [0-7]    - "NTLMSSP\0"                         (Signature)
 // [9-11]   - |MessageType::kAuthenticate|        (Message Type = 0x00000003)
-// [12-19]  - |SecBuf(64, RESPONSE_V1_LEN)|       (LM Response)
-// [20-27]  - |SecBuf(88, RESPONSE_V1_LEN)|       (NTLM Response)
+// [12-19]  - |SecBuf(64, kResponseLenV1)|        (LM Response)
+// [20-27]  - |SecBuf(88, kResponseLenV1)|       (NTLM Response)
 // [28-35]  - |SecBuf(112, 12)|                   (Target Name = L"Domain")
 // [36-43]  - |SecBuf(124, 8)|                    (User = L"User")
 // [44-51]  - |SecBuf(132, 16)|                   (Workstation = L"COMPUTER")
@@ -157,7 +368,7 @@
 // prior) implementation uses a different payload order than the example.
 // 4) The version field is Windows specific and there is no provision for
 // non-Windows OS information. This message does not include a version field.
-constexpr uint8_t kExpectedAuthenticateMsgV1[] = {
+constexpr uint8_t kExpectedAuthenticateMsgSpecResponseV1[] = {
     'N',  'T',  'L',  'M',  'S',  'S',  'P',  '\0', 0x03, 0x00, 0x00, 0x00,
     0x18, 0x00, 0x18, 0x00, 0x40, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00,
     0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x70, 0x00, 0x00, 0x00,
@@ -173,6 +384,146 @@
     'E',  0x00, 'R',  0x00,
 };
 
+// Expected V2 Authenticate message from this implementation when sent
+// |kChallengeMsgFromSpecV2| as the challenge using default features.
+//
+// [0-7]    - "NTLMSSP\0"                          (Signature)
+// [9-11]   - |MessageType::kAuthenticate|         (Message Type = 0x00000003)
+// [12-19]  - |SecBuf(88, kResponseLenV1)|         (LM Response)
+// [20-27]  - |SecBuf(112, 138)|                   (NTLM Response)
+// [28-35]  - |SecBuf(250, 12)|                    (Target Name = L"Domain")
+// [36-43]  - |SecBuf(262, 8)|                     (User = L"User")
+// [44-51]  - |SecBuf(270, 16)|                    (Workstation = L"COMPUTER")
+// [52-59]  - |SecBuf(88, 0)|                      (Session Key (empty))
+// [60-63]  - 0x00088203                           (Flags)
+// [64-71]  - All zero                             (Version)
+// [72-87]  - |kExpectedMicV2|                     (MIC)
+// [88-111] - All zero                             (LM Response Payload)
+// [112-249]-------------------------------------- (NTLM Response Payload)
+//   [112-127]-|kExpectedProofSpecResponseWithClientTimestampV2|
+//                                                 (NTLMv2 Proof)
+//   [128-155]-|kExpectedTempWithClientTimestampV2[0-27]|
+//                                                 (Proof Input)
+//   [156-245]-|kExpectedTargetInfoSpecResponseV2| (Updated target info)
+//   [246-249]-0x00000000                          (Reserved - zeros)
+// -----------------------------------------------------------------------
+// [250-261]- L"Domain"                            (Target Name Payload)
+// [262-269]- L"User"                              (User Payload)
+// [270-285]- L"COMPUTER"                          (Workstation Payload)
+//
+// NOTE: This is not identical to the message in [MS-NLMP] Section TODO(X) for
+// several reasons.
+//
+// 1) The flags are different because this implementation does not support
+// the flags related to version, key exchange, signing and sealing. These
+// flags are not relevant to implementing the NTLM scheme in HTTP.
+// 2) Since key exchange is not required nor supported, the session base key
+// payload is not required nor present.
+// 3) The specification allows payloads to be in any order. This (and the
+// prior) implementation uses a different payload order than the example.
+// 4) The version field is Windows specific and there is no provision for a
+// non-Windows OS information. This message does not include a version field.
+// 5) The example in the spec does not use Extended Protection for
+// Authentication (EPA). This message includes an extra AV Pair containing
+// the hashed channel bindings.
+// 6) The example in the spec does not use Message Integrity Check (MIC).
+// The optional field is not present, nor is the flags AV Pair that indicates
+// it's presence.
+// 7) Since the server does not provide a timestamp, the client should
+// provide one.
+constexpr uint8_t kExpectedAuthenticateMsgSpecResponseV2[] = {
+    'N',  'T',  'L',  'M',  'S',  'S',  'P',  '\0', 0x03, 0x00, 0x00, 0x00,
+    0x18, 0x00, 0x18, 0x00, 0x58, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x8a, 0x00,
+    0x70, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0xfa, 0x00, 0x00, 0x00,
+    0x08, 0x00, 0x08, 0x00, 0x06, 0x01, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00,
+    0x0e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+    0x03, 0x82, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0xf7, 0x36, 0x16, 0x33, 0xf0, 0xad, 0x9b, 0xdf, 0x4a, 0x7c, 0x42, 0x1b,
+    0xc6, 0xb8, 0x24, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x8c, 0x02, 0x60, 0xdb, 0xef, 0x69, 0x06, 0x62,
+    0xaf, 0x9c, 0x42, 0xd5, 0x07, 0x82, 0xd2, 0xed, 0x01, 0x01, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x80, 0x0b, 0xc8, 0xfd, 0x00, 0xd4, 0xd2, 0x01,
+    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
+    0x02, 0x00, 0x0c, 0x00, 'D',  0x00, 'o',  0x00, 'm',  0x00, 'a',  0x00,
+    'i',  0x00, 'n',  0x00, 0x01, 0x00, 0x0c, 0x00, 'S',  0x00, 'e',  0x00,
+    'r',  0x00, 'v',  0x00, 'e',  0x00, 'r',  0x00, 0x06, 0x00, 0x04, 0x00,
+    0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x65, 0x86, 0xE9, 0x9D,
+    0x81, 0xC2, 0xFC, 0x98, 0x4E, 0x47, 0x17, 0x2F, 0xD4, 0xDD, 0x03, 0x10,
+    0x09, 0x00, 0x16, 0x00, 'H',  0x00, 'T',  0x00, 'T',  0x00, 'P',  0x00,
+    '/',  0x00, 'S',  0x00, 'e',  0x00, 'r',  0x00, 'v',  0x00, 'e',  0x00,
+    'r',  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 'D',  0x00,
+    'o',  0x00, 'm',  0x00, 'a',  0x00, 'i',  0x00, 'n',  0x00, 'U',  0x00,
+    's',  0x00, 'e',  0x00, 'r',  0x00, 'C',  0x00, 'O',  0x00, 'M',  0x00,
+    'P',  0x00, 'U',  0x00, 'T',  0x00, 'E',  0x00, 'R',  0x00,
+};
+
+// Expected V2 Authenticate message from this implementation when sent
+// |kChallengeMsgV1| as the challenge using default features. This scenario
+// can occur because some older implementations (Windows 2003 and earlier),
+// do not send NTLMSSP_NEGOTIATE_TARGET_INFO, nor a Target Info payload in
+// the challenge message.
+//
+// [0-7]    - "NTLMSSP\0"                          (Signature)
+// [9-11]   - |MessageType::kAuthenticate|         (Message Type = 0x00000003)
+// [12-19]  - |SecBuf(88, kResponseLenV1)|         (LM Response)
+// [20-27]  - |SecBuf(112, 106)|                   (NTLM Response)
+// [28-35]  - |SecBuf(218, 12)|                    (Target Name = L"Domain")
+// [36-43]  - |SecBuf(230, 8)|                     (User = L"User")
+// [44-51]  - |SecBuf(238, 16)|                    (Workstation = L"COMPUTER")
+// [52-59]  - |SecBuf(88, 0)|                      (Session Key (empty))
+// [60-63]  - 0x00088203                           (Flags)
+// [64-71]  - All zero                             (Version)
+// [72-87]  -                                      (MIC)
+// [88-111] - All zero                             (LM Response Payload)
+// [112-217]-------------------------------------- (NTLM Response Payload)
+//   [112-127]-                                    (NTLMv2 Proof)
+//   [128-155]-|kExpectedTempWithClientTimestampV2[0-27]|
+//                                                 (Proof Input)
+//   [156-213]-|kExpectedTargetInfoSpecResponseV2[32-89]|
+//                                                 (Updated target info)
+//   [214-217]-0x00000000                          (Reserved - zeros)
+// -----------------------------------------------------------------------
+// [218-229]- L"Domain"                            (Target Name Payload)
+// [230-237]- L"User"                              (User Payload)
+// [238-253]- L"COMPUTER"                          (Workstation Payload)
+//
+// NOTE: This is message is almost the same as
+// |kExpectedAuthenticateMsgSpecResponseV2| with the following changes.
+// 1) The target info within the NTLM response is missing the first 32
+// bytes, which represent the 2 AvPairs that the server does not send in
+// this case.
+// 2) The NTLM Response security buffer length is reduced by 32 and therefore
+// all subsequent security buffer offsets are reduced by 32.
+// 3) The NTLMv2 Proof is different since the different target info changes
+// the hash.
+// 4) As with the NTLMv2 Proof, the MIC is different because the message is
+// different.
+constexpr uint8_t kExpectedAuthenticateMsgToOldV1ChallegeV2[] = {
+    'N',  'T',  'L',  'M',  'S',  'S',  'P',  '\0', 0x03, 0x00, 0x00, 0x00,
+    0x18, 0x00, 0x18, 0x00, 0x58, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x6a, 0x00,
+    0x70, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0xda, 0x00, 0x00, 0x00,
+    0x08, 0x00, 0x08, 0x00, 0xe6, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00,
+    0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+    0x03, 0x82, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x31, 0x37, 0xd6, 0x9e, 0x5c, 0xc8, 0x7d, 0x7a, 0x9f, 0x7c, 0xf4, 0x1a,
+    0x5a, 0x19, 0xdc, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0xbe, 0xd9, 0xa9, 0x42, 0x20, 0xc2, 0x25, 0x2b,
+    0x91, 0x6e, 0x9c, 0xe3, 0x9d, 0x97, 0x3a, 0x2d, 0x01, 0x01, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x80, 0x0b, 0xc8, 0xfd, 0x00, 0xd4, 0xd2, 0x01,
+    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
+    0x06, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00,
+    0x65, 0x86, 0xE9, 0x9D, 0x81, 0xC2, 0xFC, 0x98, 0x4E, 0x47, 0x17, 0x2F,
+    0xD4, 0xDD, 0x03, 0x10, 0x09, 0x00, 0x16, 0x00, 'H',  0x00, 'T',  0x00,
+    'T',  0x00, 'P',  0x00, '/',  0x00, 'S',  0x00, 'e',  0x00, 'r',  0x00,
+    'v',  0x00, 'e',  0x00, 'r',  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 'D',  0x00, 'o',  0x00, 'm',  0x00, 'a',  0x00, 'i',  0x00,
+    'n',  0x00, 'U',  0x00, 's',  0x00, 'e',  0x00, 'r',  0x00, 'C',  0x00,
+    'O',  0x00, 'M',  0x00, 'P',  0x00, 'U',  0x00, 'T',  0x00, 'E',  0x00,
+    'R',  0x00,
+};
+
 }  // namespace test
 }  // namespace ntlm
 }  // namespace net
diff --git a/net/ntlm/ntlm_unittest.cc b/net/ntlm/ntlm_unittest.cc
index 6a2ce032..a708012 100644
--- a/net/ntlm/ntlm_unittest.cc
+++ b/net/ntlm/ntlm_unittest.cc
@@ -15,6 +15,7 @@
 
 #include <string>
 
+#include "base/md5.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "net/ntlm/ntlm_test_data.h"
@@ -23,6 +24,75 @@
 namespace net {
 namespace ntlm {
 
+namespace {
+
+AvPair MakeDomainAvPair() {
+  return AvPair(TargetInfoAvId::kDomainName,
+                Buffer(test::kNtlmDomainRaw, arraysize(test::kNtlmDomainRaw)));
+}
+
+AvPair MakeServerAvPair() {
+  return AvPair(TargetInfoAvId::kServerName,
+                Buffer(test::kServerRaw, arraysize(test::kServerRaw)));
+}
+
+// Clear the least significant bit in each byte.
+void ClearLsb(uint8_t* data, size_t len) {
+  for (size_t i = 0; i < len; i++) {
+    data[i] &= ~1;
+  }
+}
+
+}  // namespace
+
+TEST(NtlmTest, MapHashToDesKeysAllOnes) {
+  // Test mapping an NTLM hash with all 1 bits.
+  const uint8_t hash[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+  const uint8_t expected[24] = {0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+                                0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+                                0xfe, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+  uint8_t result[24];
+  Create3DesKeysFromNtlmHash(hash, result);
+  // The least significant bit in result from |Create3DesKeysFromNtlmHash|
+  // is undefined, so clear it to do memcmp.
+  ClearLsb(result, arraysize(result));
+
+  ASSERT_EQ(0, memcmp(expected, result, arraysize(expected)));
+}
+
+TEST(NtlmTest, MapHashToDesKeysAllZeros) {
+  // Test mapping an NTLM hash with all 0 bits.
+  const uint8_t hash[16] = {0x00};
+  const uint8_t expected[24] = {0x00};
+
+  uint8_t result[24];
+  Create3DesKeysFromNtlmHash(hash, result);
+  // The least significant bit in result from |Create3DesKeysFromNtlmHash|
+  // is undefined, so clear it to do memcmp.
+  ClearLsb(result, arraysize(result));
+
+  ASSERT_EQ(0, memcmp(expected, result, arraysize(expected)));
+}
+
+TEST(NtlmTest, MapHashToDesKeysAlternatingBits) {
+  // Test mapping an NTLM hash with alternating 0 and 1 bits.
+  const uint8_t hash[16] = {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+                            0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
+  const uint8_t expected[24] = {0xaa, 0x54, 0xaa, 0x54, 0xaa, 0x54, 0xaa, 0x54,
+                                0xaa, 0x54, 0xaa, 0x54, 0xaa, 0x54, 0xaa, 0x54,
+                                0xaa, 0x54, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+  uint8_t result[24];
+  Create3DesKeysFromNtlmHash(hash, result);
+  // The least significant bit in result from |Create3DesKeysFromNtlmHash|
+  // is undefined, so clear it to do memcmp.
+  ClearLsb(result, arraysize(result));
+
+  ASSERT_EQ(0, memcmp(expected, result, arraysize(expected)));
+}
+
 TEST(NtlmTest, GenerateNtlmHashV1PasswordSpecTests) {
   uint8_t hash[kNtlmHashLen];
   GenerateNtlmHashV1(test::kPassword, hash);
@@ -119,5 +189,241 @@
   ASSERT_NE(0, memcmp(ntlm_response1, ntlm_response2, kResponseLenV1));
 }
 
+// ------------------------------------------------
+// NTLM V2 specific tests.
+// ------------------------------------------------
+
+TEST(NtlmTest, GenerateNtlmHashV2SpecTests) {
+  uint8_t hash[kNtlmHashLen];
+  GenerateNtlmHashV2(test::kNtlmDomain, test::kUser, test::kPassword, hash);
+  ASSERT_EQ(0, memcmp(hash, test::kExpectedNtlmHashV2, kNtlmHashLen));
+}
+
+TEST(NtlmTest, GenerateProofInputV2SpecTests) {
+  Buffer proof_input;
+  proof_input =
+      GenerateProofInputV2(test::kServerTimestamp, test::kClientChallenge);
+  ASSERT_EQ(kProofInputLenV2, proof_input.size());
+
+  // |GenerateProofInputV2| generates the first |kProofInputLenV2| bytes of
+  // what [MS-NLMP] calls "temp".
+  ASSERT_EQ(0, memcmp(test::kExpectedTempFromSpecV2, proof_input.data(),
+                      proof_input.size()));
+}
+
+TEST(NtlmTest, GenerateNtlmProofV2SpecTests) {
+  // Only the first |kProofInputLenV2| bytes of |test::kExpectedTempFromSpecV2|
+  // are read and this is equivalent to the output of |GenerateProofInputV2|.
+  // See |GenerateProofInputV2SpecTests| for validation.
+  uint8_t v2_proof[kNtlmProofLenV2];
+  GenerateNtlmProofV2(test::kExpectedNtlmHashV2, test::kServerChallenge,
+                      Buffer(test::kExpectedTempFromSpecV2, kProofInputLenV2),
+                      Buffer(test::kExpectedTargetInfoFromSpecV2,
+                             arraysize(test::kExpectedTargetInfoFromSpecV2)),
+                      v2_proof);
+
+  ASSERT_EQ(0,
+            memcmp(test::kExpectedProofFromSpecV2, v2_proof, kNtlmProofLenV2));
+}
+
+TEST(NtlmTest, GenerateSessionBaseKeyV2SpecTests) {
+  // Generate the session base key.
+  uint8_t session_base_key[kSessionKeyLenV2];
+  GenerateSessionBaseKeyV2(test::kExpectedNtlmHashV2,
+                           test::kExpectedProofFromSpecV2, session_base_key);
+
+  // Verify the session base key.
+  ASSERT_EQ(0, memcmp(test::kExpectedSessionBaseKeyFromSpecV2, session_base_key,
+                      kSessionKeyLenV2));
+}
+
+TEST(NtlmTest, GenerateSessionBaseKeyWithClientTimestampV2SpecTests) {
+  // Generate the session base key.
+  uint8_t session_base_key[kSessionKeyLenV2];
+  GenerateSessionBaseKeyV2(
+      test::kExpectedNtlmHashV2,
+      test::kExpectedProofSpecResponseWithClientTimestampV2, session_base_key);
+
+  // Verify the session base key.
+  ASSERT_EQ(0, memcmp(test::kExpectedSessionBaseKeyWithClientTimestampV2,
+                      session_base_key, kSessionKeyLenV2));
+}
+
+TEST(NtlmTest, GenerateChannelBindingHashV2SpecTests) {
+  uint8_t v2_channel_binding_hash[kChannelBindingsHashLen];
+  GenerateChannelBindingHashV2(test::kChannelBindings, v2_channel_binding_hash);
+
+  ASSERT_EQ(0, memcmp(test::kExpectedChannelBindingHashV2,
+                      v2_channel_binding_hash, kChannelBindingsHashLen));
+}
+
+TEST(NtlmTest, GenerateMicV2Simple) {
+  // The MIC is defined as HMAC_MD5(session_base_key, CONCAT(a, b, c)) where
+  // a, b, c are the negotiate, challenge and authenticate messages
+  // respectively.
+  //
+  // This compares a simple set of inputs to a precalculated result.
+  const Buffer a{0x44, 0x44, 0x44, 0x44};
+  const Buffer b{0x66, 0x66, 0x66, 0x66, 0x66, 0x66};
+  const Buffer c{0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88};
+
+  // expected_mic = HMAC_MD5(
+  //          key=8de40ccadbc14a82f15cb0ad0de95ca3,
+  //          input=444444446666666666668888888888888888)
+  uint8_t expected_mic[kMicLenV2] = {0x71, 0xfe, 0xef, 0xd7, 0x76, 0xd4,
+                                     0x42, 0xa8, 0x5f, 0x6e, 0x18, 0x0a,
+                                     0x6b, 0x02, 0x47, 0x20};
+
+  uint8_t mic[kMicLenV2];
+  GenerateMicV2(test::kExpectedSessionBaseKeyFromSpecV2, a, b, c, mic);
+  ASSERT_EQ(0, memcmp(expected_mic, mic, kMicLenV2));
+}
+
+TEST(NtlmTest, GenerateMicSpecResponseV2) {
+  Buffer negotiate_msg(test::kExpectedNegotiateMsg,
+                       arraysize(test::kExpectedNegotiateMsg));
+  Buffer challenge_msg(test::kChallengeMsgFromSpecV2,
+                       arraysize(test::kChallengeMsgFromSpecV2));
+  size_t authenticate_msg_len =
+      arraysize(test::kExpectedAuthenticateMsgSpecResponseV2);
+  Buffer authenticate_msg(authenticate_msg_len, '\0');
+  memcpy(&authenticate_msg[0], test::kExpectedAuthenticateMsgSpecResponseV2,
+         authenticate_msg_len);
+  memset(&authenticate_msg[kMicOffsetV2], 0x00, kMicLenV2);
+
+  uint8_t mic[kMicLenV2];
+  GenerateMicV2(test::kExpectedSessionBaseKeyWithClientTimestampV2,
+                negotiate_msg, challenge_msg, authenticate_msg, mic);
+  ASSERT_EQ(0, memcmp(test::kExpectedMicV2, mic, kMicLenV2));
+}
+
+TEST(NtlmTest, GenerateUpdatedTargetInfo) {
+  // This constructs a std::vector<AvPair> that corresponds to the test input
+  // values in [MS-NLMP] Section 4.2.4.
+  std::vector<AvPair> server_av_pairs;
+  server_av_pairs.push_back(MakeDomainAvPair());
+  server_av_pairs.push_back(MakeServerAvPair());
+
+  uint64_t server_timestamp = UINT64_MAX;
+  Buffer updated_target_info = GenerateUpdatedTargetInfo(
+      true, true, test::kChannelBindings, test::kNtlmSpn, server_av_pairs,
+      &server_timestamp);
+
+  // With MIC and EPA enabled 3 additional AvPairs will be added.
+  // 1) A flags AVPair with the MIC_PRESENT bit set.
+  // 2) A channel bindings AVPair containing the channel bindings hash.
+  // 3) A target name AVPair containing the SPN of the server.
+  ASSERT_EQ(arraysize(test::kExpectedTargetInfoSpecResponseV2),
+            updated_target_info.size());
+  ASSERT_EQ(0, memcmp(test::kExpectedTargetInfoSpecResponseV2,
+                      updated_target_info.data(), updated_target_info.size()));
+}
+
+TEST(NtlmTest, GenerateUpdatedTargetInfoNoEpaOrMic) {
+  // This constructs a std::vector<AvPair> that corresponds to the test input
+  // values in [MS-NLMP] Section 4.2.4.
+  std::vector<AvPair> server_av_pairs;
+  server_av_pairs.push_back(MakeDomainAvPair());
+  server_av_pairs.push_back(MakeServerAvPair());
+
+  uint64_t server_timestamp = UINT64_MAX;
+
+  // When both EPA and MIC are false the target info does not get modified by
+  // the client.
+  Buffer updated_target_info = GenerateUpdatedTargetInfo(
+      false, false, test::kChannelBindings, test::kNtlmSpn, server_av_pairs,
+      &server_timestamp);
+  ASSERT_EQ(arraysize(test::kExpectedTargetInfoFromSpecV2),
+            updated_target_info.size());
+  ASSERT_EQ(0, memcmp(test::kExpectedTargetInfoFromSpecV2,
+                      updated_target_info.data(), updated_target_info.size()));
+}
+
+TEST(NtlmTest, GenerateUpdatedTargetInfoWithServerTimestamp) {
+  // This constructs a std::vector<AvPair> that corresponds to the test input
+  // values in [MS-NLMP] Section 4.2.4 with an additional server timestamp.
+  std::vector<AvPair> server_av_pairs;
+  server_av_pairs.push_back(MakeDomainAvPair());
+  server_av_pairs.push_back(MakeServerAvPair());
+
+  // Set the timestamp to |test::kServerTimestamp| and the buffer to all zeros.
+  AvPair pair(TargetInfoAvId::kTimestamp, Buffer(sizeof(uint64_t), 0));
+  pair.timestamp = test::kServerTimestamp;
+  server_av_pairs.push_back(std::move(pair));
+
+  uint64_t server_timestamp = UINT64_MAX;
+  // When both EPA and MIC are false the target info does not get modified by
+  // the client.
+  Buffer updated_target_info = GenerateUpdatedTargetInfo(
+      false, false, test::kChannelBindings, test::kNtlmSpn, server_av_pairs,
+      &server_timestamp);
+  // Verify that the server timestamp was read from the target info.
+  ASSERT_EQ(test::kServerTimestamp, server_timestamp);
+  ASSERT_EQ(arraysize(test::kExpectedTargetInfoFromSpecPlusServerTimestampV2),
+            updated_target_info.size());
+  ASSERT_EQ(0, memcmp(test::kExpectedTargetInfoFromSpecPlusServerTimestampV2,
+                      updated_target_info.data(), updated_target_info.size()));
+}
+
+TEST(NtlmTest, GenerateUpdatedTargetInfoWhenServerSendsNoTargetInfo) {
+  // In some older implementations the server supports NTLMv2 but does not
+  // send target info. This manifests as an empty list of AvPairs.
+  std::vector<AvPair> server_av_pairs;
+
+  uint64_t server_timestamp = UINT64_MAX;
+  Buffer updated_target_info = GenerateUpdatedTargetInfo(
+      true, true, test::kChannelBindings, test::kNtlmSpn, server_av_pairs,
+      &server_timestamp);
+
+  // With MIC and EPA enabled 3 additional AvPairs will be added.
+  // 1) A flags AVPair with the MIC_PRESENT bit set.
+  // 2) A channel bindings AVPair containing the channel bindings hash.
+  // 3) A target name AVPair containing the SPN of the server.
+  //
+  // Compared to the spec example in |GenerateUpdatedTargetInfo| the result
+  // is the same but with the first 32 bytes (which were the Domain and
+  // Server pairs) not present.
+  const size_t kMissingServerPairsLength = 32;
+
+  ASSERT_EQ(arraysize(test::kExpectedTargetInfoSpecResponseV2) -
+                kMissingServerPairsLength,
+            updated_target_info.size());
+  ASSERT_EQ(0, memcmp(test::kExpectedTargetInfoSpecResponseV2 +
+                          kMissingServerPairsLength,
+                      updated_target_info.data(), updated_target_info.size()));
+}
+
+TEST(NtlmTest, GenerateNtlmProofV2) {
+  uint8_t proof[kNtlmProofLenV2];
+
+  // NOTE: Only the first |kProofInputLenV2| bytes of |kExpectedTempFromSpecV2|
+  // are read.
+  GenerateNtlmProofV2(
+      test::kExpectedNtlmHashV2, test::kServerChallenge,
+      Buffer(test::kExpectedTempFromSpecV2, kProofInputLenV2),
+      Buffer(test::kExpectedTargetInfoSpecResponseV2,
+             arraysize(test::kExpectedTargetInfoSpecResponseV2)),
+      proof);
+  ASSERT_EQ(0,
+            memcmp(test::kExpectedProofSpecResponseV2, proof, kNtlmProofLenV2));
+}
+
+TEST(NtlmTest, GenerateNtlmProofWithClientTimestampV2) {
+  uint8_t proof[kNtlmProofLenV2];
+
+  // NOTE: Only the first |kProofInputLenV2| bytes of
+  // |kExpectedTempWithClientTimestampV2| are read. Since the test data for
+  // "temp" in the spec does not include the client timestamp, a separate
+  // proof test value must be validated for use in full message validation.
+  GenerateNtlmProofV2(
+      test::kExpectedNtlmHashV2, test::kServerChallenge,
+      Buffer(test::kExpectedTempWithClientTimestampV2, kProofInputLenV2),
+      Buffer(test::kExpectedTargetInfoSpecResponseV2,
+             arraysize(test::kExpectedTargetInfoSpecResponseV2)),
+      proof);
+  ASSERT_EQ(0, memcmp(test::kExpectedProofSpecResponseWithClientTimestampV2,
+                      proof, kNtlmProofLenV2));
+}
+
 }  // namespace ntlm
 }  // namespace net
diff --git a/net/quic/chromium/quic_stream_factory.cc b/net/quic/chromium/quic_stream_factory.cc
index 05872e7d..4627cf8 100644
--- a/net/quic/chromium/quic_stream_factory.cc
+++ b/net/quic/chromium/quic_stream_factory.cc
@@ -702,6 +702,7 @@
     bool mark_quic_broken_when_network_blackholes,
     int idle_connection_timeout_seconds,
     int reduced_ping_timeout_seconds,
+    bool connect_using_default_network,
     bool migrate_sessions_on_network_change,
     bool migrate_sessions_early,
     bool allow_server_migration,
@@ -743,6 +744,9 @@
       yield_after_packets_(kQuicYieldAfterPacketsRead),
       yield_after_duration_(QuicTime::Delta::FromMilliseconds(
           kQuicYieldAfterDurationMilliseconds)),
+      connect_using_default_network_(
+          connect_using_default_network &&
+          NetworkChangeNotifier::AreNetworkHandlesSupported()),
       migrate_sessions_on_network_change_(migrate_sessions_on_network_change),
       migrate_sessions_early_(migrate_sessions_early &&
                               migrate_sessions_on_network_change_),
@@ -1496,6 +1500,8 @@
     } else {
       rv = socket->ConnectUsingNetwork(network, addr);
     }
+  } else if (connect_using_default_network_) {
+    rv = socket->ConnectUsingDefaultNetwork(addr);
   } else {
     rv = socket->Connect(addr);
   }
diff --git a/net/quic/chromium/quic_stream_factory.h b/net/quic/chromium/quic_stream_factory.h
index 77b30f8..f96ba54 100644
--- a/net/quic/chromium/quic_stream_factory.h
+++ b/net/quic/chromium/quic_stream_factory.h
@@ -219,6 +219,7 @@
       bool mark_quic_broken_when_network_blackholes,
       int idle_connection_timeout_seconds,
       int reduced_ping_timeout_seconds,
+      bool connect_using_default_network,
       bool migrate_sessions_on_network_change,
       bool migrate_sessions_early,
       bool allow_server_migration,
@@ -542,6 +543,10 @@
   int yield_after_packets_;
   QuicTime::Delta yield_after_duration_;
 
+  // Set if sockets should explicitly use default network to connect and
+  // NetworkHandle is supported.
+  const bool connect_using_default_network_;
+
   // Set if migration should be attempted on active sessions when primary
   // interface changes.
   const bool migrate_sessions_on_network_change_;
diff --git a/net/quic/chromium/quic_stream_factory_test.cc b/net/quic/chromium/quic_stream_factory_test.cc
index 965aedb2..fc0d5a8 100644
--- a/net/quic/chromium/quic_stream_factory_test.cc
+++ b/net/quic/chromium/quic_stream_factory_test.cc
@@ -216,6 +216,7 @@
         kDefaultMaxPacketSize, string(), store_server_configs_in_properties_,
         /*mark_quic_broken_when_network_blackholes*/ false,
         idle_connection_timeout_seconds_, reduced_ping_timeout_seconds_,
+        /*connect_using_default_network*/ true,
         migrate_sessions_on_network_change_, migrate_sessions_early_,
         allow_server_migration_, race_cert_verification_, estimate_initial_rtt_,
         connection_options_, client_connection_options_,
diff --git a/net/quic/core/congestion_control/bbr_sender.cc b/net/quic/core/congestion_control/bbr_sender.cc
index e27c7bb..d27e438 100644
--- a/net/quic/core/congestion_control/bbr_sender.cc
+++ b/net/quic/core/congestion_control/bbr_sender.cc
@@ -203,16 +203,10 @@
       config.HasClientRequestedIndependentOption(kBBRR, perspective)) {
     rate_based_recovery_ = true;
   }
-  if (FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes4 &&
-      config.HasClientRequestedIndependentOption(kBBR1, perspective)) {
-    QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_aggregation_bytes4, 1,
-                      2);
+  if (config.HasClientRequestedIndependentOption(kBBR1, perspective)) {
     max_aggregation_bytes_multiplier_ = 1.5;
   }
-  if (FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes4 &&
-      config.HasClientRequestedIndependentOption(kBBR2, perspective)) {
-    QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_aggregation_bytes4, 2,
-                      2);
+  if (config.HasClientRequestedIndependentOption(kBBR2, perspective)) {
     max_aggregation_bytes_multiplier_ = 2;
   }
 }
diff --git a/net/quic/core/congestion_control/bbr_sender_test.cc b/net/quic/core/congestion_control/bbr_sender_test.cc
index 69e151b..fd103674 100644
--- a/net/quic/core/congestion_control/bbr_sender_test.cc
+++ b/net/quic/core/congestion_control/bbr_sender_test.cc
@@ -92,7 +92,6 @@
                               {&receiver_, &competing_receiver_}) {
     // These will be changed by the appropriate tests as necessary.
     FLAGS_quic_reloadable_flag_quic_bbr_add_tso_cwnd = false;
-    FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes4 = true;
 
     rtt_stats_ = bbr_sender_.connection()->sent_packet_manager().GetRttStats();
     sender_ = SetupBbrSender(&bbr_sender_);
diff --git a/net/quic/core/crypto/aes_128_gcm_12_decrypter.cc b/net/quic/core/crypto/aes_128_gcm_12_decrypter.cc
index a5a5a4ae..c57be8b 100644
--- a/net/quic/core/crypto/aes_128_gcm_12_decrypter.cc
+++ b/net/quic/core/crypto/aes_128_gcm_12_decrypter.cc
@@ -4,7 +4,9 @@
 
 #include "net/quic/core/crypto/aes_128_gcm_12_decrypter.h"
 
-#include "third_party/boringssl/src/include/openssl/evp.h"
+#include "net/quic/platform/api/quic_flag_utils.h"
+#include "net/quic/platform/api/quic_flags.h"
+#include "third_party/boringssl/src/include/openssl/aead.h"
 #include "third_party/boringssl/src/include/openssl/tls1.h"
 
 namespace net {
@@ -29,9 +31,10 @@
 Aes128Gcm12Decrypter::~Aes128Gcm12Decrypter() {}
 
 uint32_t Aes128Gcm12Decrypter::cipher_id() const {
-  // This OpenSSL macro has the value 0x0300C02F. The two most significant bytes
-  // 0x0300 are OpenSSL specific and are NOT part of the TLS CipherSuite value
-  // for TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256.
+  if (FLAGS_quic_reloadable_flag_quic_use_tls13_cipher_suites) {
+    QUIC_FLAG_COUNT(quic_reloadable_flag_quic_use_tls13_cipher_suites);
+    return TLS1_CK_AES_128_GCM_SHA256;
+  }
   return TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
 }
 
diff --git a/net/quic/core/crypto/chacha20_poly1305_decrypter.cc b/net/quic/core/crypto/chacha20_poly1305_decrypter.cc
index 010b7b7..c734cb4c 100644
--- a/net/quic/core/crypto/chacha20_poly1305_decrypter.cc
+++ b/net/quic/core/crypto/chacha20_poly1305_decrypter.cc
@@ -4,7 +4,9 @@
 
 #include "net/quic/core/crypto/chacha20_poly1305_decrypter.h"
 
-#include "third_party/boringssl/src/include/openssl/evp.h"
+#include "net/quic/platform/api/quic_flag_utils.h"
+#include "net/quic/platform/api/quic_flags.h"
+#include "third_party/boringssl/src/include/openssl/aead.h"
 #include "third_party/boringssl/src/include/openssl/tls1.h"
 
 namespace net {
@@ -29,6 +31,10 @@
 ChaCha20Poly1305Decrypter::~ChaCha20Poly1305Decrypter() {}
 
 uint32_t ChaCha20Poly1305Decrypter::cipher_id() const {
+  if (FLAGS_quic_reloadable_flag_quic_use_tls13_cipher_suites) {
+    QUIC_FLAG_COUNT(quic_reloadable_flag_quic_use_tls13_cipher_suites);
+    return TLS1_CK_CHACHA20_POLY1305_SHA256;
+  }
   return TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
 }
 
diff --git a/net/quic/core/crypto/crypto_handshake_message.cc b/net/quic/core/crypto/crypto_handshake_message.cc
index 502743ba..3499a553 100644
--- a/net/quic/core/crypto/crypto_handshake_message.cc
+++ b/net/quic/core/crypto/crypto_handshake_message.cc
@@ -12,6 +12,7 @@
 #include "net/quic/core/quic_socket_address_coder.h"
 #include "net/quic/core/quic_utils.h"
 #include "net/quic/platform/api/quic_endian.h"
+#include "net/quic/platform/api/quic_flag_utils.h"
 #include "net/quic/platform/api/quic_map_util.h"
 #include "net/quic/platform/api/quic_str_cat.h"
 #include "net/quic/platform/api/quic_text_utils.h"
@@ -72,15 +73,29 @@
 
 void CryptoHandshakeMessage::SetVersionVector(QuicTag tag,
                                               QuicVersionVector versions) {
-  QuicTagVector version_tags;
+  QuicVersionLabelVector version_labels;
   for (QuicVersion version : versions) {
-    version_tags.push_back(QuicVersionToQuicTag(version));
+    if (!FLAGS_quic_reloadable_flag_quic_use_net_byte_order_version_label) {
+      version_labels.push_back(QuicVersionToQuicVersionLabel(version));
+    } else {
+      QUIC_FLAG_COUNT_N(
+          quic_reloadable_flag_quic_use_net_byte_order_version_label, 7, 10);
+      version_labels.push_back(
+          QuicEndian::HostToNet32(QuicVersionToQuicVersionLabel(version)));
+    }
   }
-  SetVector(tag, version_tags);
+  SetVector(tag, version_labels);
 }
 
 void CryptoHandshakeMessage::SetVersion(QuicTag tag, QuicVersion version) {
-  SetValue(tag, QuicVersionToQuicTag(version));
+  if (!FLAGS_quic_reloadable_flag_quic_use_net_byte_order_version_label) {
+    SetValue(tag, QuicVersionToQuicVersionLabel(version));
+  } else {
+    QUIC_FLAG_COUNT_N(
+        quic_reloadable_flag_quic_use_net_byte_order_version_label, 8, 10);
+    SetValue(tag,
+             QuicEndian::HostToNet32(QuicVersionToQuicVersionLabel(version)));
+  }
 }
 
 void CryptoHandshakeMessage::SetStringPiece(QuicTag tag,
@@ -119,6 +134,45 @@
   return ret;
 }
 
+QuicErrorCode CryptoHandshakeMessage::GetVersionLabelList(
+    QuicTag tag,
+    QuicVersionLabelVector* out) const {
+  if (!FLAGS_quic_reloadable_flag_quic_use_net_byte_order_version_label) {
+    return GetTaglist(tag, out);
+  }
+
+  QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_use_net_byte_order_version_label,
+                    9, 10);
+  QuicErrorCode error = GetTaglist(tag, out);
+  if (error != QUIC_NO_ERROR) {
+    return error;
+  }
+
+  for (size_t i = 0; i < out->size(); ++i) {
+    (*out)[i] = QuicEndian::HostToNet32((*out)[i]);
+  }
+
+  return QUIC_NO_ERROR;
+}
+
+QuicErrorCode CryptoHandshakeMessage::GetVersionLabel(
+    QuicTag tag,
+    QuicVersionLabel* out) const {
+  if (!FLAGS_quic_reloadable_flag_quic_use_net_byte_order_version_label) {
+    return GetUint32(tag, out);
+  }
+
+  QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_use_net_byte_order_version_label,
+                    10, 10);
+  QuicErrorCode error = GetUint32(tag, out);
+  if (error != QUIC_NO_ERROR) {
+    return error;
+  }
+
+  *out = QuicEndian::HostToNet32(*out);
+  return QUIC_NO_ERROR;
+}
+
 bool CryptoHandshakeMessage::GetStringPiece(QuicTag tag,
                                             QuicStringPiece* out) const {
   QuicTagValueMap::const_iterator it = tag_value_map_.find(tag);
diff --git a/net/quic/core/crypto/crypto_handshake_message.h b/net/quic/core/crypto/crypto_handshake_message.h
index bbd8079..7e93bcb9 100644
--- a/net/quic/core/crypto/crypto_handshake_message.h
+++ b/net/quic/core/crypto/crypto_handshake_message.h
@@ -84,6 +84,17 @@
   // populates |out_tags| with the tags and returns QUIC_NO_ERROR.
   QuicErrorCode GetTaglist(QuicTag tag, QuicTagVector* out_tags) const;
 
+  // GetVersionLabelList finds an element with the given tag containing zero or
+  // more version labels. If such a tag doesn't exist, it returns an error code.
+  // Otherwise it populates |out| with the labels and returns QUIC_NO_ERROR.
+  QuicErrorCode GetVersionLabelList(QuicTag tag,
+                                    QuicVersionLabelVector* out) const;
+
+  // GetVersionLabel finds an element with the given tag containing a single
+  // version label. If such a tag doesn't exist, it returns an error code.
+  // Otherwise it populates |out| with the label and returns QUIC_NO_ERROR.
+  QuicErrorCode GetVersionLabel(QuicTag tag, QuicVersionLabel* out) const;
+
   bool GetStringPiece(QuicTag tag, QuicStringPiece* out) const;
   bool HasStringPiece(QuicTag tag) const;
 
diff --git a/net/quic/core/crypto/crypto_server_test.cc b/net/quic/core/crypto/crypto_server_test.cc
index 1da1384dc..2dd719c 100644
--- a/net/quic/core/crypto/crypto_server_test.cc
+++ b/net/quic/core/crypto/crypto_server_test.cc
@@ -118,8 +118,8 @@
     config_.set_enable_serving_sct(true);
 
     client_version_ = supported_versions_.front();
-    client_version_string_ =
-        QuicTagToString(QuicVersionToQuicTag(client_version_));
+    client_version_string_ = QuicVersionLabelToString(
+        QuicVersionToQuicVersionLabel(client_version_));
 
     FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support =
         GetParam().enable_stateless_rejects;
@@ -215,11 +215,12 @@
   };
 
   void CheckServerHello(const CryptoHandshakeMessage& server_hello) {
-    QuicTagVector versions;
-    server_hello.GetTaglist(kVER, &versions);
+    QuicVersionLabelVector versions;
+    server_hello.GetVersionLabelList(kVER, &versions);
     ASSERT_EQ(supported_versions_.size(), versions.size());
     for (size_t i = 0; i < versions.size(); ++i) {
-      EXPECT_EQ(QuicVersionToQuicTag(supported_versions_[i]), versions[i]);
+      EXPECT_EQ(QuicVersionToQuicVersionLabel(supported_versions_[i]),
+                versions[i]);
     }
 
     QuicStringPiece address;
@@ -667,8 +668,8 @@
   }
   // Set the client's preferred version to a supported version that
   // is not the "current" version (supported_versions_.front()).
-  string bad_version =
-      QuicTagToString(QuicVersionToQuicTag(supported_versions_.back()));
+  string bad_version = QuicVersionLabelToString(
+      QuicVersionToQuicVersionLabel(supported_versions_.back()));
 
   CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
       {{"PDMD", "X509"}, {"VER\0", bad_version}}, kClientHelloMinimumSize);
@@ -1039,8 +1040,8 @@
  public:
   void SetUp() override {
     client_version_ = supported_versions_.back();
-    client_version_string_ =
-        QuicTagToString(QuicVersionToQuicTag(client_version_));
+    client_version_string_ = QuicVersionLabelToString(
+        QuicVersionToQuicVersionLabel(client_version_));
     CryptoServerTest::SetUp();
   }
 };
diff --git a/net/quic/core/crypto/crypto_utils.cc b/net/quic/core/crypto/crypto_utils.cc
index 382acc7..e348ce7 100644
--- a/net/quic/core/crypto/crypto_utils.cc
+++ b/net/quic/core/crypto/crypto_utils.cc
@@ -188,15 +188,17 @@
     return QUIC_INVALID_CRYPTO_MESSAGE_TYPE;
   }
 
-  QuicTagVector supported_version_tags;
-  if (server_hello.GetTaglist(kVER, &supported_version_tags) != QUIC_NO_ERROR) {
+  QuicVersionLabelVector supported_version_labels;
+  if (server_hello.GetVersionLabelList(kVER, &supported_version_labels) !=
+      QUIC_NO_ERROR) {
     *error_details = "server hello missing version list";
     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
   }
   if (!negotiated_versions.empty()) {
-    bool mismatch = supported_version_tags.size() != negotiated_versions.size();
-    for (size_t i = 0; i < supported_version_tags.size() && !mismatch; ++i) {
-      mismatch = QuicTagToQuicVersion(supported_version_tags[i]) !=
+    bool mismatch =
+        supported_version_labels.size() != negotiated_versions.size();
+    for (size_t i = 0; i < supported_version_labels.size() && !mismatch; ++i) {
+      mismatch = QuicVersionLabelToQuicVersion(supported_version_labels[i]) !=
                  negotiated_versions[i];
     }
     // The server sent a list of supported versions, and the connection
@@ -224,12 +226,14 @@
   // speaking, then the client went through a version negotiation.  In this
   // case, we need to make sure that we actually do not support this version
   // and that it wasn't a downgrade attack.
-  QuicTag client_version_tag;
-  if (client_hello.GetUint32(kVER, &client_version_tag) != QUIC_NO_ERROR) {
+  QuicVersionLabel client_version_label;
+  if (client_hello.GetVersionLabel(kVER, &client_version_label) !=
+      QUIC_NO_ERROR) {
     *error_details = "client hello missing version list";
     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
   }
-  QuicVersion client_version = QuicTagToQuicVersion(client_version_tag);
+  QuicVersion client_version =
+      QuicVersionLabelToQuicVersion(client_version_label);
   if (client_version != version) {
     // Just because client_version is a valid version enum doesn't mean that
     // this server actually supports that version, so we check to see if
diff --git a/net/quic/core/crypto/quic_crypto_client_config_test.cc b/net/quic/core/crypto/quic_crypto_client_config_test.cc
index a9490e13..78db122d 100644
--- a/net/quic/core/crypto/quic_crypto_client_config_test.cc
+++ b/net/quic/core/crypto/quic_crypto_client_config_test.cc
@@ -184,9 +184,9 @@
   config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &rand,
                                  /* demand_x509_proof= */ true, params, &msg);
 
-  QuicTag cver;
-  EXPECT_EQ(QUIC_NO_ERROR, msg.GetUint32(kVER, &cver));
-  EXPECT_EQ(QuicVersionToQuicTag(QuicVersionMax()), cver);
+  QuicVersionLabel cver;
+  EXPECT_EQ(QUIC_NO_ERROR, msg.GetVersionLabel(kVER, &cver));
+  EXPECT_EQ(QuicVersionToQuicVersionLabel(QuicVersionMax()), cver);
   QuicStringPiece proof_nonce;
   EXPECT_TRUE(msg.GetStringPiece(kNONP, &proof_nonce));
   EXPECT_EQ(string(32, 'r'), proof_nonce);
@@ -294,10 +294,10 @@
                          nullptr,  // channel_id_key
                          params, &chlo, &error_details);
 
-  // Verify that certain QuicTags have been set correctly in the CHLO.
-  QuicTag cver;
-  EXPECT_EQ(QUIC_NO_ERROR, chlo.GetUint32(kVER, &cver));
-  EXPECT_EQ(QuicVersionToQuicTag(QuicVersionMax()), cver);
+  // Verify that the version label has been set correctly in the CHLO.
+  QuicVersionLabel cver;
+  EXPECT_EQ(QUIC_NO_ERROR, chlo.GetVersionLabel(kVER, &cver));
+  EXPECT_EQ(QuicVersionToQuicVersionLabel(QuicVersionMax()), cver);
 }
 
 TEST_F(QuicCryptoClientConfigTest, ProcessServerDowngradeAttack) {
@@ -306,14 +306,15 @@
     // No downgrade attack is possible if the client only supports one version.
     return;
   }
-  QuicTagVector supported_version_tags;
+
+  QuicVersionVector supported_version_vector;
   for (size_t i = supported_versions.size(); i > 0; --i) {
-    supported_version_tags.push_back(
-        QuicVersionToQuicTag(supported_versions[i - 1]));
+    supported_version_vector.push_back(supported_versions[i - 1]);
   }
+
   CryptoHandshakeMessage msg;
   msg.set_tag(kSHLO);
-  msg.SetVector(kVER, supported_version_tags);
+  msg.SetVersionVector(kVER, supported_version_vector);
 
   QuicCryptoClientConfig::CachedState cached;
   QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params(
@@ -571,9 +572,7 @@
   QuicVersionVector supported_versions;
   QuicVersion version = AllSupportedVersions().front();
   supported_versions.push_back(version);
-  QuicTagVector versions;
-  versions.push_back(QuicVersionToQuicTag(version));
-  msg.SetVector(kVER, versions);
+  msg.SetVersionVector(kVER, supported_versions);
 
   QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
   QuicCryptoClientConfig::CachedState cached;
diff --git a/net/quic/core/quic_connection.cc b/net/quic/core/quic_connection.cc
index ef42140..70e0f07 100644
--- a/net/quic/core/quic_connection.cc
+++ b/net/quic/core/quic_connection.cc
@@ -1332,12 +1332,53 @@
     self_address_ = last_packet_destination_address_;
   }
 
-  if (!Near(header.packet_number, last_header_.packet_number)) {
-    QUIC_DLOG(INFO) << ENDPOINT << "Packet " << header.packet_number
-                    << " out of bounds.  Discarding";
-    CloseConnection(QUIC_INVALID_PACKET_HEADER, "Packet number out of bounds.",
-                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
-    return false;
+  if (FLAGS_quic_restart_flag_quic_enable_accept_random_ipn) {
+    QUIC_FLAG_COUNT_N(quic_restart_flag_quic_enable_accept_random_ipn, 2, 2);
+    // Configured to accept any packet number in range 1...0x7fffffff
+    // as initial packet number.
+    if (last_header_.packet_number != 0) {
+      // The last packet's number is not 0. Ensure that this packet
+      // is reasonably close to where it should be.
+      if (!Near(header.packet_number, last_header_.packet_number)) {
+        QUIC_DLOG(INFO) << ENDPOINT << "Packet " << header.packet_number
+                        << " out of bounds.  Discarding";
+        CloseConnection(QUIC_INVALID_PACKET_HEADER,
+                        "Packet number out of bounds.",
+                        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+        return false;
+      }
+    } else {
+      // The "last packet's number" is 0, meaning that this packet is the first
+      // one received. Ensure it is in range 1..kMaxRandomInitialPacketNumber,
+      // inclusive.
+      if ((header.packet_number == 0) ||
+          (header.packet_number > kMaxRandomInitialPacketNumber)) {
+        // packet number is bad.
+        QUIC_DLOG(INFO) << ENDPOINT << "Initial packet " << header.packet_number
+                        << " out of bounds.  Discarding";
+        CloseConnection(QUIC_INVALID_PACKET_HEADER,
+                        "Initial packet number out of bounds.",
+                        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+        return false;
+      }
+    }
+  } else {  //  if (FLAGS_quic_reloadable_flag_quic_accept_random_ipn) {
+    // Count those that would have been accepted if FLAGS..random_ipn
+    // were true -- to detect/diagnose potential issues prior to
+    // enabling the flag.
+    if ((header.packet_number > 1) &&
+        (header.packet_number <= kMaxRandomInitialPacketNumber)) {
+      QUIC_CODE_COUNT_N(had_possibly_random_ipn, 2, 2);
+    }
+
+    if (!Near(header.packet_number, last_header_.packet_number)) {
+      QUIC_DLOG(INFO) << ENDPOINT << "Packet " << header.packet_number
+                      << " out of bounds.  Discarding";
+      CloseConnection(QUIC_INVALID_PACKET_HEADER,
+                      "Packet number out of bounds.",
+                      ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+      return false;
+    }
   }
 
   if (version_negotiation_state_ != NEGOTIATED_VERSION) {
diff --git a/net/quic/core/quic_connection_test.cc b/net/quic/core/quic_connection_test.cc
index 0520710..77232f3 100644
--- a/net/quic/core/quic_connection_test.cc
+++ b/net/quic/core/quic_connection_test.cc
@@ -1036,7 +1036,12 @@
                                              ConnectionCloseSource::FROM_SELF));
     // Call ProcessDataPacket rather than ProcessPacket, as we should not get a
     // packet call to the visitor.
-    ProcessDataPacket(6000);
+    if (FLAGS_quic_restart_flag_quic_enable_accept_random_ipn) {
+      ProcessDataPacket(kMaxRandomInitialPacketNumber + 6000);
+    } else {
+      ProcessDataPacket(6000);
+    }
+
     EXPECT_FALSE(QuicConnectionPeer::GetConnectionClosePacket(&connection_) ==
                  nullptr);
   }
@@ -1438,9 +1443,14 @@
 TEST_P(QuicConnectionTest, RejectPacketTooFarOut) {
   EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_PACKET_HEADER, _,
                                            ConnectionCloseSource::FROM_SELF));
+
   // Call ProcessDataPacket rather than ProcessPacket, as we should not get a
   // packet call to the visitor.
-  ProcessDataPacket(6000);
+  if (FLAGS_quic_restart_flag_quic_enable_accept_random_ipn) {
+    ProcessDataPacket(kMaxRandomInitialPacketNumber + 6000);
+  } else {
+    ProcessDataPacket(6000);
+  }
   EXPECT_FALSE(QuicConnectionPeer::GetConnectionClosePacket(&connection_) ==
                nullptr);
 }
diff --git a/net/quic/core/quic_constants.h b/net/quic/core/quic_constants.h
index 9dd96c78..1ae1fc4 100644
--- a/net/quic/core/quic_constants.h
+++ b/net/quic/core/quic_constants.h
@@ -188,6 +188,10 @@
 // contain data from multiple data slices.
 const QuicByteCount kQuicStreamSendBufferSliceSize = 4 * 1024;
 
+// For When using Random Initial Packet Numbers, they can start
+// anyplace in the range 1...((2^31)-1) or 0x7fffffff
+const QuicPacketNumber kMaxRandomInitialPacketNumber = 0x7fffffff;
+
 }  // namespace net
 
 #endif  // NET_QUIC_CORE_QUIC_CONSTANTS_H_
diff --git a/net/quic/core/quic_data_reader.cc b/net/quic/core/quic_data_reader.cc
index 8b80eab..bb3953a 100644
--- a/net/quic/core/quic_data_reader.cc
+++ b/net/quic/core/quic_data_reader.cc
@@ -56,6 +56,7 @@
 }
 
 bool QuicDataReader::ReadBytesToUInt64(size_t num_bytes, uint64_t* result) {
+  *result = 0u;
   if (num_bytes > sizeof(*result)) {
     return false;
   }
diff --git a/net/quic/core/quic_data_reader.h b/net/quic/core/quic_data_reader.h
index 6c60d191..b96c7b9 100644
--- a/net/quic/core/quic_data_reader.h
+++ b/net/quic/core/quic_data_reader.h
@@ -49,8 +49,8 @@
   bool ReadUInt32(uint32_t* result);
   bool ReadUInt64(uint64_t* result);
 
-  // Reads |num_bytes| bytes in the correct byte order into least significant
-  // bytes of |result|.
+  // Set |result| to 0, then read |num_bytes| bytes in the correct byte order
+  // into least significant bytes of |result|.
   bool ReadBytesToUInt64(size_t num_bytes, uint64_t* result);
 
   // Reads a 16-bit unsigned float into the given output parameter.
diff --git a/net/quic/core/quic_data_writer_test.cc b/net/quic/core/quic_data_writer_test.cc
index 832d390..2217ed1c 100644
--- a/net/quic/core/quic_data_writer_test.cc
+++ b/net/quic/core/quic_data_writer_test.cc
@@ -310,7 +310,7 @@
                                                     : little_endian16,
         2);
 
-    uint64_t read_number16 = 0u;
+    uint64_t read_number16;
     QuicDataReader reader(buffer16, 2, GetParam().endianness);
     reader.ReadBytesToUInt64(2, &read_number16);
     EXPECT_EQ(in_memory16, read_number16);
@@ -330,7 +330,7 @@
                                                   : little_endian24,
       3);
 
-  uint64_t read_number24 = 0u;
+  uint64_t read_number24;
   QuicDataReader reader(buffer24, 3, GetParam().endianness);
   reader.ReadBytesToUInt64(3, &read_number24);
   EXPECT_EQ(in_memory24, read_number24);
@@ -366,7 +366,7 @@
                                                     : little_endian32,
         4);
 
-    uint64_t read_number32 = 0u;
+    uint64_t read_number32;
     QuicDataReader reader(buffer32, 4, GetParam().endianness);
     reader.ReadBytesToUInt64(4, &read_number32);
     EXPECT_EQ(in_memory32, read_number32);
@@ -386,7 +386,7 @@
                                                   : little_endian40,
       5);
 
-  uint64_t read_number40 = 0u;
+  uint64_t read_number40;
   QuicDataReader reader(buffer40, 5, GetParam().endianness);
   reader.ReadBytesToUInt64(5, &read_number40);
   EXPECT_EQ(in_memory40, read_number40);
@@ -405,7 +405,7 @@
                                                   : little_endian48,
       6);
 
-  uint64_t read_number48 = 0u;
+  uint64_t read_number48;
   QuicDataReader reader(buffer48, 6, GetParam().endianness);
   reader.ReadBytesToUInt64(6., &read_number48);
   EXPECT_EQ(in_memory48, read_number48);
@@ -424,7 +424,7 @@
                                                   : little_endian56,
       7);
 
-  uint64_t read_number56 = 0u;
+  uint64_t read_number56;
   QuicDataReader reader(buffer56, 7, GetParam().endianness);
   reader.ReadBytesToUInt64(7, &read_number56);
   EXPECT_EQ(in_memory56, read_number56);
@@ -445,7 +445,7 @@
                                                   : AsChars(little_endian64),
       8);
 
-  uint64_t read_number64 = 0u;
+  uint64_t read_number64;
   QuicDataReader reader(buffer64, 8, GetParam().endianness);
   reader.ReadBytesToUInt64(8, &read_number64);
   EXPECT_EQ(in_memory64, read_number64);
@@ -506,7 +506,7 @@
     uint8_t read8;
     uint16_t read16;
     uint32_t read32;
-    uint64_t read64 = 0u;
+    uint64_t read64;
     switch (i) {
       case 0u:
         EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
diff --git a/net/quic/core/quic_flags_list.h b/net/quic/core/quic_flags_list.h
index f6d39e8..a109aaa 100644
--- a/net/quic/core/quic_flags_list.h
+++ b/net/quic/core/quic_flags_list.h
@@ -124,9 +124,6 @@
 // If true, enable QUIC v42.
 QUIC_FLAG(bool, FLAGS_quic_enable_version_42, false)
 
-// Small optimization for QuicSentPacketManager::HandleAckForSentPackets.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_handle_acks, true)
-
 // When true, respect configured limits on header list size.
 QUIC_FLAG(bool, FLAGS_quic_restart_flag_quic_header_list_size, true)
 
@@ -146,12 +143,6 @@
 // Max size of data slice in bytes for QUIC stream send buffer.
 QUIC_FLAG(uint32_t, FLAGS_quic_send_buffer_max_data_slice_size, 4096u)
 
-// Enables the BBR1 and BBR2 QUIC connection options, which enable two forms of
-// ack aggregation that prevent persistent standing queues.
-QUIC_FLAG(bool,
-          FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes4,
-          true)
-
 // Add 4 new ack decimation modes to QUIC that are entirely time based at 1/4
 // or 1/8 RTT.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_ack_decimation, false)
@@ -178,3 +169,15 @@
 // If true, QUIC can take ownership of data provided in a reference counted
 // memory to avoid data copy.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_use_mem_slices, false)
+
+// Allow QUIC to accept initial packet numbers that are random, not 1.
+QUIC_FLAG(bool, FLAGS_quic_restart_flag_quic_enable_accept_random_ipn, false)
+
+// Report the more analogous TLS 1.3 cipher suites rather than TLS 1.2 ECDHE_RSA
+// ciphers in QuicDecrypters.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_use_tls13_cipher_suites, false)
+
+// If true, read and write QUIC version labels in network byte order.
+QUIC_FLAG(bool,
+          FLAGS_quic_reloadable_flag_quic_use_net_byte_order_version_label,
+          false)
diff --git a/net/quic/core/quic_framer.cc b/net/quic/core/quic_framer.cc
index a89b817..e8be85c 100644
--- a/net/quic/core/quic_framer.cc
+++ b/net/quic/core/quic_framer.cc
@@ -162,7 +162,7 @@
       last_packet_number_(0),
       largest_packet_number_(0),
       last_serialized_connection_id_(0),
-      last_version_tag_(0),
+      last_version_label_(0),
       supported_versions_(supported_versions),
       decrypter_level_(ENCRYPTION_NONE),
       alternative_decrypter_level_(ENCRYPTION_NONE),
@@ -519,8 +519,19 @@
   }
 
   for (QuicVersion version : versions) {
-    if (!writer.WriteTag(QuicVersionToQuicTag(version))) {
-      return nullptr;
+    if (FLAGS_quic_reloadable_flag_quic_use_net_byte_order_version_label) {
+      QUIC_FLAG_COUNT_N(
+          quic_reloadable_flag_quic_use_net_byte_order_version_label, 3, 10);
+      // TODO(rch): Use WriteUInt32() once QUIC_VERSION_38 and earlier
+      // are removed.
+      if (!writer.WriteTag(QuicEndian::HostToNet32(
+              QuicVersionToQuicVersionLabel(version)))) {
+        return nullptr;
+      }
+    } else {
+      if (!writer.WriteTag(QuicVersionToQuicVersionLabel(version))) {
+        return nullptr;
+      }
     }
   }
 
@@ -585,12 +596,20 @@
   DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
   // Try reading at least once to raise error if the packet is invalid.
   do {
-    QuicTag version;
-    if (!reader->ReadTag(&version)) {
+    QuicVersionLabel version_label;
+    if (!reader->ReadTag(&version_label)) {
       set_detailed_error("Unable to read supported version in negotiation.");
       return RaiseError(QUIC_INVALID_VERSION_NEGOTIATION_PACKET);
     }
-    public_header->versions.push_back(QuicTagToQuicVersion(version));
+    if (FLAGS_quic_reloadable_flag_quic_use_net_byte_order_version_label) {
+      QUIC_FLAG_COUNT_N(
+          quic_reloadable_flag_quic_use_net_byte_order_version_label, 4, 10);
+      // TODO(rch): Use ReadUInt32() once QUIC_VERSION_38 and earlier
+      // are removed.
+      version_label = QuicEndian::NetToHost32(version_label);
+    }
+    public_header->versions.push_back(
+        QuicVersionLabelToQuicVersion(version_label));
   } while (!reader->IsDoneReading());
 
   visitor_->OnVersionNegotiationPacket(*public_header);
@@ -726,12 +745,24 @@
 
   if (header.public_header.version_flag) {
     DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
-    QuicTag tag = QuicVersionToQuicTag(quic_version_);
-    if (!writer->WriteTag(tag)) {
-      return false;
+    QuicVersionLabel version_label =
+        QuicVersionToQuicVersionLabel(quic_version_);
+    if (FLAGS_quic_reloadable_flag_quic_use_net_byte_order_version_label) {
+      QUIC_FLAG_COUNT_N(
+          quic_reloadable_flag_quic_use_net_byte_order_version_label, 5, 10);
+      // TODO(rch): Use WriteUInt32() once QUIC_VERSION_38 and earlier
+      // are removed.
+      if (!writer->WriteTag(QuicEndian::NetToHost32(version_label))) {
+        return false;
+      }
+    } else {
+      if (!writer->WriteTag(version_label)) {
+        return false;
+      }
     }
-    QUIC_DVLOG(1) << ENDPOINT << "version = " << quic_version_ << ", tag = '"
-                  << QuicTagToString(tag) << "'";
+
+    QUIC_DVLOG(1) << ENDPOINT << "version = " << quic_version_ << ", label = '"
+                  << QuicVersionLabelToString(version_label) << "'";
   }
 
   if (header.public_header.nonce != nullptr &&
@@ -844,17 +875,24 @@
   // Read the version only if the packet is from the client.
   // version flag from the server means version negotiation packet.
   if (public_header->version_flag && perspective_ == Perspective::IS_SERVER) {
-    QuicTag version_tag;
-    if (!reader->ReadTag(&version_tag)) {
+    QuicVersionLabel version_label;
+    if (!reader->ReadTag(&version_label)) {
       set_detailed_error("Unable to read protocol version.");
       return false;
     }
+    if (FLAGS_quic_reloadable_flag_quic_use_net_byte_order_version_label) {
+      QUIC_FLAG_COUNT_N(
+          quic_reloadable_flag_quic_use_net_byte_order_version_label, 6, 10);
+      // TODO(rch): Use ReadUInt32() once QUIC_VERSION_38 and earlier
+      // are removed.
+      version_label = QuicEndian::NetToHost32(version_label);
+    }
 
     // If the version from the new packet is the same as the version of this
     // framer, then the public flags should be set to something we understand.
     // If not, this raises an error.
-    last_version_tag_ = version_tag;
-    QuicVersion version = QuicTagToQuicVersion(version_tag);
+    last_version_label_ = version_label;
+    QuicVersion version = QuicVersionLabelToQuicVersion(version_label);
     if (version == quic_version_ && public_flags > PACKET_PUBLIC_FLAGS_MAX) {
       set_detailed_error("Illegal public flags value.");
       return false;
@@ -978,7 +1016,7 @@
     QuicPacketNumberLength packet_number_length,
     QuicPacketNumber base_packet_number,
     QuicPacketNumber* packet_number) {
-  QuicPacketNumber wire_packet_number = 0u;
+  QuicPacketNumber wire_packet_number;
   if (!reader->ReadBytesToUInt64(packet_number_length, &wire_packet_number)) {
     return false;
   }
@@ -1243,14 +1281,13 @@
     frame->fin = ExtractBit(stream_flags, kQuicStreamFinShift);
   }
 
-  uint64_t stream_id = 0;
+  uint64_t stream_id;
   if (!reader->ReadBytesToUInt64(stream_id_length, &stream_id)) {
     set_detailed_error("Unable to read stream_id.");
     return false;
   }
   frame->stream_id = static_cast<QuicStreamId>(stream_id);
 
-  frame->offset = 0;
   if (!reader->ReadBytesToUInt64(offset_length, &frame->offset)) {
     set_detailed_error("Unable to read offset.");
     return false;
@@ -1331,7 +1368,7 @@
     }
   }
 
-  uint64_t first_block_length = 0;
+  uint64_t first_block_length;
   if (!reader->ReadBytesToUInt64(ack_block_length, &first_block_length)) {
     set_detailed_error("Unable to read first ack block length.");
     return false;
@@ -1358,7 +1395,7 @@
         set_detailed_error("Unable to read gap to next ack block.");
         return false;
       }
-      uint64_t current_block_length = 0;
+      uint64_t current_block_length;
       if (!reader->ReadBytesToUInt64(ack_block_length, &current_block_length)) {
         set_detailed_error("Unable to ack block length.");
         return false;
@@ -1448,7 +1485,7 @@
 bool QuicFramer::ProcessStopWaitingFrame(QuicDataReader* reader,
                                          const QuicPacketHeader& header,
                                          QuicStopWaitingFrame* stop_waiting) {
-  QuicPacketNumber least_unacked_delta = 0;
+  QuicPacketNumber least_unacked_delta;
   if (!reader->ReadBytesToUInt64(header.public_header.packet_number_length,
                                  &least_unacked_delta)) {
     set_detailed_error("Unable to read least unacked delta.");
diff --git a/net/quic/core/quic_framer.h b/net/quic/core/quic_framer.h
index 513505e..a814622 100644
--- a/net/quic/core/quic_framer.h
+++ b/net/quic/core/quic_framer.h
@@ -347,7 +347,7 @@
 
   Perspective perspective() const { return perspective_; }
 
-  QuicTag last_version_tag() { return last_version_tag_; }
+  QuicVersionLabel last_version_label() { return last_version_label_; }
 
   void set_data_producer(QuicStreamFrameDataProducer* data_producer) {
     data_producer_ = data_producer;
@@ -518,8 +518,8 @@
   QuicPacketNumber largest_packet_number_;
   // Updated by WritePacketHeader.
   QuicConnectionId last_serialized_connection_id_;
-  // The last QUIC version tag received.
-  QuicTag last_version_tag_;
+  // The last QUIC version label received.
+  QuicVersionLabel last_version_label_;
   // Version of the protocol being used.
   QuicVersion quic_version_;
   // This vector contains QUIC versions which we currently support.
diff --git a/net/quic/core/quic_sent_packet_manager.cc b/net/quic/core/quic_sent_packet_manager.cc
index 5b181e3..8477aa21 100644
--- a/net/quic/core/quic_sent_packet_manager.cc
+++ b/net/quic/core/quic_sent_packet_manager.cc
@@ -281,8 +281,6 @@
 
 void QuicSentPacketManager::HandleAckForSentPackets(
     const QuicAckFrame& ack_frame) {
-  const bool skip_unackable_packets_early =
-      FLAGS_quic_reloadable_flag_quic_handle_acks;
   // Go through the packets we have not received an ack for and see if this
   // incoming_ack shows they've been seen by the peer.
   QuicTime::Delta ack_delay_time = ack_frame.ack_delay_time;
@@ -293,8 +291,7 @@
       // These packets are still in flight.
       break;
     }
-    if (skip_unackable_packets_early && it->is_unackable) {
-      QUIC_FLAG_COUNT(quic_reloadable_flag_quic_handle_acks);
+    if (it->is_unackable) {
       continue;
     }
     if (!ack_frame.packets.Contains(packet_number)) {
@@ -312,8 +309,8 @@
     if (it->in_flight) {
       packets_acked_.push_back(SendAlgorithmInterface::AckedPacket(
           packet_number, it->bytes_sent, QuicTime::Zero()));
-    } else if (skip_unackable_packets_early || !it->is_unackable) {
-      // Packets are marked unackable after they've been acked once.
+    } else {
+      // Unackable packets are skipped earlier.
       largest_newly_acked_ = packet_number;
     }
     MarkPacketHandled(packet_number, &(*it), ack_delay_time);
diff --git a/net/quic/core/quic_session.cc b/net/quic/core/quic_session.cc
index a32f3464..6fdab1b 100644
--- a/net/quic/core/quic_session.cc
+++ b/net/quic/core/quic_session.cc
@@ -39,7 +39,7 @@
       num_locally_closed_incoming_streams_highest_offset_(0),
       error_(QUIC_NO_ERROR),
       flow_controller_(connection_,
-                       0,
+                       kConnectionLevelId,
                        perspective(),
                        kMinimumFlowControlSendWindow,
                        config_.GetInitialSessionFlowControlWindowToSend(),
diff --git a/net/quic/core/quic_versions.cc b/net/quic/core/quic_versions.cc
index 1faf560..a1988c6 100644
--- a/net/quic/core/quic_versions.cc
+++ b/net/quic/core/quic_versions.cc
@@ -7,12 +7,28 @@
 #include "net/quic/core/quic_error_codes.h"
 #include "net/quic/core/quic_tag.h"
 #include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_endian.h"
+#include "net/quic/platform/api/quic_flag_utils.h"
 #include "net/quic/platform/api/quic_flags.h"
 #include "net/quic/platform/api/quic_logging.h"
 
 using std::string;
 
 namespace net {
+namespace {
+
+// Constructs a version label from the 4 bytes such that the on-the-wire
+// order will be: d, c, b, a.
+QuicVersionLabel MakeVersionLabel(char a, char b, char c, char d) {
+  if (!FLAGS_quic_reloadable_flag_quic_use_net_byte_order_version_label) {
+    return MakeQuicTag(a, b, c, d);
+  }
+  QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_use_net_byte_order_version_label,
+                    1, 10);
+  return MakeQuicTag(d, c, b, a);
+}
+
+}  // namespace
 
 QuicVersionVector AllSupportedVersions() {
   QuicVersionVector supported_versions;
@@ -70,20 +86,20 @@
   return version;
 }
 
-QuicTag QuicVersionToQuicTag(const QuicVersion version) {
+QuicVersionLabel QuicVersionToQuicVersionLabel(const QuicVersion version) {
   switch (version) {
     case QUIC_VERSION_35:
-      return MakeQuicTag('Q', '0', '3', '5');
+      return MakeVersionLabel('Q', '0', '3', '5');
     case QUIC_VERSION_37:
-      return MakeQuicTag('Q', '0', '3', '7');
+      return MakeVersionLabel('Q', '0', '3', '7');
     case QUIC_VERSION_38:
-      return MakeQuicTag('Q', '0', '3', '8');
+      return MakeVersionLabel('Q', '0', '3', '8');
     case QUIC_VERSION_39:
-      return MakeQuicTag('Q', '0', '3', '9');
+      return MakeVersionLabel('Q', '0', '3', '9');
     case QUIC_VERSION_41:
-      return MakeQuicTag('Q', '0', '4', '1');
+      return MakeVersionLabel('Q', '0', '4', '1');
     case QUIC_VERSION_42:
-      return MakeQuicTag('Q', '0', '4', '2');
+      return MakeVersionLabel('Q', '0', '4', '2');
     default:
       // This shold be an ERROR because we should never attempt to convert an
       // invalid QuicVersion to be written to the wire.
@@ -92,15 +108,25 @@
   }
 }
 
-QuicVersion QuicTagToQuicVersion(const QuicTag version_tag) {
+string QuicVersionLabelToString(QuicVersionLabel version_label) {
+  if (!FLAGS_quic_reloadable_flag_quic_use_net_byte_order_version_label) {
+    return QuicTagToString(version_label);
+  }
+  QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_use_net_byte_order_version_label,
+                    2, 10);
+  return QuicTagToString(QuicEndian::HostToNet32(version_label));
+}
+
+QuicVersion QuicVersionLabelToQuicVersion(QuicVersionLabel version_label) {
   for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
-    if (version_tag == QuicVersionToQuicTag(kSupportedQuicVersions[i])) {
+    if (version_label ==
+        QuicVersionToQuicVersionLabel(kSupportedQuicVersions[i])) {
       return kSupportedQuicVersions[i];
     }
   }
   // Reading from the client so this should not be considered an ERROR.
-  QUIC_DLOG(INFO) << "Unsupported QuicTag version: "
-                  << QuicTagToString(version_tag);
+  QUIC_DLOG(INFO) << "Unsupported QuicVersionLabel version: "
+                  << QuicVersionLabelToString(version_label);
   return QUIC_VERSION_UNSUPPORTED;
 }
 
diff --git a/net/quic/core/quic_versions.h b/net/quic/core/quic_versions.h
index 87eb486e..0c35eef 100644
--- a/net/quic/core/quic_versions.h
+++ b/net/quic/core/quic_versions.h
@@ -39,6 +39,11 @@
   // http://sites/quic/adding-and-removing-versions
 };
 
+// Representation of the on-the-wire QUIC version number. Will be written/read
+// to the wire in network-byte-order.
+using QuicVersionLabel = uint32_t;
+using QuicVersionLabelVector = std::vector<QuicVersionLabel>;
+
 // This vector contains QUIC versions which we currently support.
 // This should be ordered such that the highest supported version is the first
 // element, with subsequent elements in descending order (versions can be
@@ -69,15 +74,21 @@
 QUIC_EXPORT_PRIVATE QuicVersionVector
 VersionOfIndex(const QuicVersionVector& versions, int index);
 
-// QuicTag is written to and read from the wire, but we prefer to use
+// QuicVersionLabel is written to and read from the wire, but we prefer to use
 // the more readable QuicVersion at other levels.
-// Helper function which translates from a QuicVersion to a QuicTag. Returns 0
-// if QuicVersion is unsupported.
-QUIC_EXPORT_PRIVATE QuicTag QuicVersionToQuicTag(const QuicVersion version);
+// Helper function which translates from a QuicVersion to a QuicVersionLabel.
+// Returns 0 if |version| is unsupported.
+QUIC_EXPORT_PRIVATE QuicVersionLabel
+QuicVersionToQuicVersionLabel(const QuicVersion version);
 
-// Returns appropriate QuicVersion from a QuicTag.
+// Helper function which translates from a QuicVersionLabel to a std::string.
+QUIC_EXPORT_PRIVATE std::string QuicVersionLabelToString(
+    QuicVersionLabel version_label);
+
+// Returns appropriate QuicVersion from a QuicVersionLabel.
 // Returns QUIC_VERSION_UNSUPPORTED if version_tag cannot be understood.
-QUIC_EXPORT_PRIVATE QuicVersion QuicTagToQuicVersion(const QuicTag version_tag);
+QUIC_EXPORT_PRIVATE QuicVersion
+QuicVersionLabelToQuicVersion(QuicVersionLabel version_label);
 
 // Helper function which translates from a QuicVersion to a string.
 // Returns strings corresponding to enum names (e.g. QUIC_VERSION_6).
diff --git a/net/quic/core/quic_versions_test.cc b/net/quic/core/quic_versions_test.cc
index 6585eb2..9b985806 100644
--- a/net/quic/core/quic_versions_test.cc
+++ b/net/quic/core/quic_versions_test.cc
@@ -14,9 +14,9 @@
 
 class QuicVersionsTest : public QuicTest {};
 
-TEST_F(QuicVersionsTest, QuicVersionToQuicTag) {
+TEST_F(QuicVersionsTest, QuicVersionToQuicVersionLabel) {
 // If you add a new version to the QuicVersion enum you will need to add a new
-// case to QuicVersionToQuicTag, otherwise this test will fail.
+// case to QuicVersionToQuicVersionLabel, otherwise this test will fail.
 
 // TODO(rtenneti): Enable checking of Log(ERROR) messages.
 #if 0
@@ -27,19 +27,24 @@
 #endif
 
   // Explicitly test a specific version.
-  EXPECT_EQ(MakeQuicTag('Q', '0', '3', '5'),
-            QuicVersionToQuicTag(QUIC_VERSION_35));
+  if (!FLAGS_quic_reloadable_flag_quic_use_net_byte_order_version_label) {
+    EXPECT_EQ(MakeQuicTag('Q', '0', '3', '5'),
+              QuicVersionToQuicVersionLabel(QUIC_VERSION_35));
+  } else {
+    EXPECT_EQ(MakeQuicTag('5', '3', '0', 'Q'),
+              QuicVersionToQuicVersionLabel(QUIC_VERSION_35));
+  }
 
   // Loop over all supported versions and make sure that we never hit the
   // default case (i.e. all supported versions should be successfully converted
-  // to valid QuicTags).
+  // to valid QuicVersionLabels).
   for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
     QuicVersion version = kSupportedQuicVersions[i];
-    EXPECT_LT(0u, QuicVersionToQuicTag(version));
+    EXPECT_LT(0u, QuicVersionToQuicVersionLabel(version));
   }
 }
 
-TEST_F(QuicVersionsTest, QuicVersionToQuicTagUnsupported) {
+TEST_F(QuicVersionsTest, QuicVersionToQuicVersionLabelUnsupported) {
 // TODO(rtenneti): Enable checking of Log(ERROR) messages.
 #if 0
   // TODO(rjshade): Change to DFATAL once we actually support multiple versions,
@@ -51,12 +56,12 @@
   log.StartCapturingLogs();
 #endif
 
-  EXPECT_EQ(0u, QuicVersionToQuicTag(QUIC_VERSION_UNSUPPORTED));
+  EXPECT_EQ(0u, QuicVersionToQuicVersionLabel(QUIC_VERSION_UNSUPPORTED));
 }
 
-TEST_F(QuicVersionsTest, QuicTagToQuicVersion) {
+TEST_F(QuicVersionsTest, QuicVersionLabelToQuicVersion) {
 // If you add a new version to the QuicVersion enum you will need to add a new
-// case to QuicTagToQuicVersion, otherwise this test will fail.
+// case to QuicVersionLabelToQuicVersion, otherwise this test will fail.
 
 // TODO(rtenneti): Enable checking of Log(ERROR) messages.
 #if 0
@@ -67,37 +72,49 @@
 #endif
 
   // Explicitly test specific versions.
-  EXPECT_EQ(QUIC_VERSION_35,
-            QuicTagToQuicVersion(MakeQuicTag('Q', '0', '3', '5')));
+  if (!FLAGS_quic_reloadable_flag_quic_use_net_byte_order_version_label) {
+    EXPECT_EQ(QUIC_VERSION_35,
+              QuicVersionLabelToQuicVersion(MakeQuicTag('Q', '0', '3', '5')));
+  } else {
+    EXPECT_EQ(QUIC_VERSION_35,
+              QuicVersionLabelToQuicVersion(MakeQuicTag('5', '3', '0', 'Q')));
+  }
 
   for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
     QuicVersion version = kSupportedQuicVersions[i];
 
-    // Get the tag from the version (we can loop over QuicVersions easily).
-    QuicTag tag = QuicVersionToQuicTag(version);
-    EXPECT_LT(0u, tag);
+    // Get the label from the version (we can loop over QuicVersions easily).
+    QuicVersionLabel version_label = QuicVersionToQuicVersionLabel(version);
+    EXPECT_LT(0u, version_label);
 
     // Now try converting back.
-    QuicVersion tag_to_quic_version = QuicTagToQuicVersion(tag);
-    EXPECT_EQ(version, tag_to_quic_version);
-    EXPECT_NE(QUIC_VERSION_UNSUPPORTED, tag_to_quic_version);
+    QuicVersion label_to_quic_version =
+        QuicVersionLabelToQuicVersion(version_label);
+    EXPECT_EQ(version, label_to_quic_version);
+    EXPECT_NE(QUIC_VERSION_UNSUPPORTED, label_to_quic_version);
   }
 }
 
-TEST_F(QuicVersionsTest, QuicTagToQuicVersionUnsupported) {
+TEST_F(QuicVersionsTest, QuicVersionLabelToQuicVersionUnsupported) {
 // TODO(rtenneti): Enable checking of Log(ERROR) messages.
 #if 0
   ScopedMockLog log(kDoNotCaptureLogsYet);
 #ifndef NDEBUG
-  EXPECT_CALL(log,
-              Log(base_logging::INFO, _, "Unsupported QuicTag version: FAKE"))
-      .Times(1);
+  if (!FLAGS_quic_reloadable_flag_quic_use_net_byte_order_version_label) {
+    EXPECT_CALL(log, Log(base_logging::INFO, _,
+                         "Unsupported QuicVersionLabel version: FAKE"))
+        .Times(1);
+  } else {
+    EXPECT_CALL(log, Log(base_logging::INFO, _,
+                         "Unsupported QuicVersionLabel version: EKAF"))
+        .Times(1);
+  }
 #endif
   log.StartCapturingLogs();
 #endif
 
   EXPECT_EQ(QUIC_VERSION_UNSUPPORTED,
-            QuicTagToQuicVersion(MakeQuicTag('F', 'A', 'K', 'E')));
+            QuicVersionLabelToQuicVersion(MakeQuicTag('F', 'A', 'K', 'E')));
 }
 
 TEST_F(QuicVersionsTest, QuicVersionToString) {
diff --git a/net/quic/quartc/quartc_factory.cc b/net/quic/quartc/quartc_factory.cc
index 87a867a..c81cc4a 100644
--- a/net/quic/quartc/quartc_factory.cc
+++ b/net/quic/quartc/quartc_factory.cc
@@ -151,6 +151,10 @@
 QuicArenaScopedPtr<QuicAlarm> QuartcFactory::CreateAlarm(
     QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
     QuicConnectionArena* arena) {
+  if (arena != nullptr) {
+    return arena->New<QuartcAlarm>(GetClock(), task_runner_,
+                                   std::move(delegate));
+  }
   return QuicArenaScopedPtr<QuicAlarm>(
       new QuartcAlarm(GetClock(), task_runner_, std::move(delegate)));
 }
diff --git a/net/quic/test_tools/crypto_test_utils.cc b/net/quic/test_tools/crypto_test_utils.cc
index 70206f2..5162087 100644
--- a/net/quic/test_tools/crypto_test_utils.cc
+++ b/net/quic/test_tools/crypto_test_utils.cc
@@ -956,7 +956,8 @@
        {"KEXS", "C255"},
        {"PUBS", GenerateClientPublicValuesHex().c_str()},
        {"NONC", GenerateClientNonceHex(clock, crypto_config).c_str()},
-       {"VER\0", QuicTagToString(QuicVersionToQuicTag(version)).c_str()}},
+       {"VER\0", QuicVersionLabelToString(
+           QuicVersionToQuicVersionLabel(version)).c_str()}},
       kClientHelloMinimumSize);
   // clang-format on
 }
diff --git a/net/quic/test_tools/crypto_test_utils_test.cc b/net/quic/test_tools/crypto_test_utils_test.cc
index cd27d08..86968096 100644
--- a/net/quic/test_tools/crypto_test_utils_test.cc
+++ b/net/quic/test_tools/crypto_test_utils_test.cc
@@ -157,7 +157,8 @@
        {"COPT", "SREJ"},
        {"PUBS", pub_hex},
        {"NONC", nonce_hex},
-       {"VER\0", QuicTagToString(QuicVersionToQuicTag(version))}},
+       {"VER\0",
+        QuicVersionLabelToString(QuicVersionToQuicVersionLabel(version))}},
       kClientHelloMinimumSize);
 
   crypto_test_utils::GenerateFullCHLO(
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc
index 7d69a275..b27e0231 100644
--- a/net/socket/ssl_client_socket_impl.cc
+++ b/net/socket/ssl_client_socket_impl.cc
@@ -1209,9 +1209,9 @@
   server_cert_ = x509_util::CreateX509CertificateFromBuffers(
       SSL_get0_peer_certificates(ssl_.get()));
 
-  // OpenSSL decoded the certificate, but the platform certificate
-  // implementation could not. This is treated as a fatal SSL-level protocol
-  // error rather than a certificate error. See https://crbug.com/91341.
+  // OpenSSL decoded the certificate, but the X509Certificate implementation
+  // could not. This is treated as a fatal SSL-level protocol error rather than
+  // a certificate error. See https://crbug.com/91341.
   if (!server_cert_)
     return ERR_SSL_SERVER_CERT_BAD_FORMAT;
 
diff --git a/net/socket/ssl_client_socket_pool.cc b/net/socket/ssl_client_socket_pool.cc
index 1d62a94..8be83e5 100644
--- a/net/socket/ssl_client_socket_pool.cc
+++ b/net/socket/ssl_client_socket_pool.cc
@@ -128,9 +128,11 @@
                context.transport_security_state,
                context.cert_transparency_verifier,
                context.ct_policy_enforcer,
-               (params->privacy_mode() == PRIVACY_MODE_ENABLED
-                    ? "pm/" + context.ssl_session_cache_shard
-                    : context.ssl_session_cache_shard)),
+               (context.ssl_session_cache_shard.empty()
+                    ? context.ssl_session_cache_shard
+                    : (params->privacy_mode() == PRIVACY_MODE_ENABLED
+                           ? "pm/" + context.ssl_session_cache_shard
+                           : context.ssl_session_cache_shard))),
       callback_(
           base::Bind(&SSLConnectJob::OnIOComplete, base::Unretained(this))),
       version_interference_probe_(false),
diff --git a/net/socket/ssl_server_socket_unittest.cc b/net/socket/ssl_server_socket_unittest.cc
index d493079..e6e6bbc 100644
--- a/net/socket/ssl_server_socket_unittest.cc
+++ b/net/socket/ssl_server_socket_unittest.cc
@@ -71,7 +71,6 @@
 #include "testing/platform_test.h"
 #include "third_party/boringssl/src/include/openssl/evp.h"
 #include "third_party/boringssl/src/include/openssl/ssl.h"
-#include "third_party/boringssl/src/include/openssl/x509.h"
 
 using net::test::IsError;
 using net::test::IsOk;
@@ -84,7 +83,6 @@
 const char kClientPrivateKeyFileName[] = "client_1.pk8";
 const char kWrongClientCertFileName[] = "client_2.pem";
 const char kWrongClientPrivateKeyFileName[] = "client_2.pk8";
-const char kClientCertCAFileName[] = "client_1_ca.pem";
 
 class MockCTPolicyEnforcer : public CTPolicyEnforcer {
  public:
@@ -435,22 +433,12 @@
     server_ssl_config_.client_cert_type =
         SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT;
 
-    bssl::UniquePtr<STACK_OF(X509_NAME)> cert_names(
-        SSL_load_client_CA_file(GetTestCertsDirectory()
-                                    .AppendASCII(kClientCertCAFileName)
-                                    .MaybeAsASCII()
-                                    .c_str()));
-    ASSERT_TRUE(cert_names);
-
-    for (size_t i = 0; i < sk_X509_NAME_num(cert_names.get()); ++i) {
-      uint8_t* str = nullptr;
-      int length = i2d_X509_NAME(sk_X509_NAME_value(cert_names.get(), i), &str);
-      ASSERT_LT(0, length);
-
-      server_ssl_config_.cert_authorities_.push_back(std::string(
-          reinterpret_cast<const char*>(str), static_cast<size_t>(length)));
-      OPENSSL_free(str);
-    }
+    // "CN=B CA" - DER encoded DN of the issuer of client_1.pem
+    static const uint8_t kClientCertCAName[] = {
+        0x30, 0x0f, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55,
+        0x04, 0x03, 0x0c, 0x04, 0x42, 0x20, 0x43, 0x41};
+    server_ssl_config_.cert_authorities_.push_back(std::string(
+        std::begin(kClientCertCAName), std::end(kClientCertCAName)));
 
     scoped_refptr<X509Certificate> expected_client_cert(
         ImportCertFromFile(GetTestCertsDirectory(), kClientCertFileName));
diff --git a/net/tools/cert_verify_tool/cert_verify_tool.cc b/net/tools/cert_verify_tool/cert_verify_tool.cc
index 92806e5..f4f8514e0e 100644
--- a/net/tools/cert_verify_tool/cert_verify_tool.cc
+++ b/net/tools/cert_verify_tool/cert_verify_tool.cc
@@ -10,12 +10,95 @@
 #include "base/logging.h"
 #include "base/task_scheduler/task_scheduler.h"
 #include "base/time/time.h"
+#include "net/cert/cert_verify_proc.h"
+#include "net/cert/cert_verify_proc_builtin.h"
 #include "net/tools/cert_verify_tool/cert_verify_tool_util.h"
 #include "net/tools/cert_verify_tool/verify_using_cert_verify_proc.h"
 #include "net/tools/cert_verify_tool/verify_using_path_builder.h"
 
 namespace {
 
+// Base class to abstract running a particular implementation of certificate
+// verification.
+class CertVerifyImpl {
+ public:
+  virtual ~CertVerifyImpl() = default;
+
+  virtual std::string GetName() const = 0;
+
+  // Does certificate verification.
+  //
+  // Note that |hostname| may be empty to indicate that no name validation is
+  // requested, and a null value of |verify_time| means to use the current time.
+  virtual bool VerifyCert(const CertInput& target_der_cert,
+                          const std::string& hostname,
+                          const std::vector<CertInput>& intermediate_der_certs,
+                          const std::vector<CertInput>& root_der_certs,
+                          base::Time verify_time,
+                          const base::FilePath& dump_prefix_path) = 0;
+};
+
+// Runs certificate verification using a particular CertVerifyProc.
+class CertVerifyImplUsingProc : public CertVerifyImpl {
+ public:
+  CertVerifyImplUsingProc(const std::string& name,
+                          scoped_refptr<net::CertVerifyProc> proc)
+      : name_(name), proc_(std::move(proc)) {}
+
+  std::string GetName() const override { return name_; }
+
+  bool VerifyCert(const CertInput& target_der_cert,
+                  const std::string& hostname,
+                  const std::vector<CertInput>& intermediate_der_certs,
+                  const std::vector<CertInput>& root_der_certs,
+                  base::Time verify_time,
+                  const base::FilePath& dump_prefix_path) override {
+    if (!verify_time.is_null()) {
+      std::cerr << "WARNING: --time is not supported by " << GetName()
+                << ", will use current time.\n";
+    }
+
+    if (hostname.empty()) {
+      std::cerr << "ERROR: --hostname is required for " << GetName()
+                << ", skipping\n";
+      return true;  // "skipping" is considered a successful return.
+    }
+
+    return VerifyUsingCertVerifyProc(proc_.get(), target_der_cert, hostname,
+                                     intermediate_der_certs, root_der_certs,
+                                     dump_prefix_path);
+  }
+
+ private:
+  const std::string name_;
+  scoped_refptr<net::CertVerifyProc> proc_;
+};
+
+// Runs certificate verification using CertPathBuilder.
+class CertVerifyImplUsingPathBuilder : public CertVerifyImpl {
+ public:
+  std::string GetName() const override { return "CertPathBuilder"; }
+
+  bool VerifyCert(const CertInput& target_der_cert,
+                  const std::string& hostname,
+                  const std::vector<CertInput>& intermediate_der_certs,
+                  const std::vector<CertInput>& root_der_certs,
+                  base::Time verify_time,
+                  const base::FilePath& dump_prefix_path) override {
+    if (!hostname.empty()) {
+      std::cerr << "WARNING: --hostname is not verified with CertPathBuilder\n";
+    }
+
+    if (verify_time.is_null()) {
+      verify_time = base::Time::Now();
+    }
+
+    return VerifyUsingPathBuilder(target_der_cert, intermediate_der_certs,
+                                  root_der_certs, verify_time,
+                                  dump_prefix_path);
+  }
+};
+
 const char kUsage[] =
     " [flags] <target/chain>\n"
     "\n"
@@ -62,7 +145,7 @@
 
   // TODO(mattm): allow <certs path> to be a directory containing DER/PEM files?
   // TODO(mattm): allow target to specify an HTTPS URL to check the cert of?
-  // TODO(mattm): allow target to be a verify_certificate_chain_unittest PEM
+  // TODO(mattm): allow target to be a verify_certificate_chain_unittest .test
   // file?
 }
 
@@ -97,8 +180,6 @@
       std::cerr << "Error parsing --time flag\n";
       return 1;
     }
-  } else {
-    verify_time = base::Time::Now();
   }
 
   base::FilePath roots_path = command_line.GetSwitchValuePath("roots");
@@ -128,31 +209,28 @@
     return 1;
   }
 
-  // TODO(eroman): Also use CertVerifyProcBuiltin.
+  // Sequentially run each of the certificate verifier implementations.
+  std::vector<std::unique_ptr<CertVerifyImpl>> impls;
 
-  std::cout << "CertVerifyProc:\n";
-  bool cert_verify_proc_ok = true;
-  if (!time_flag.empty()) {
-    std::cerr << "ERROR: --time is not supported with CertVerifyProc, "
-                 "skipping.\n";
-  } else if (hostname.empty()) {
-    std::cerr << "ERROR: --hostname is required for CertVerifyProc, skipping\n";
-  } else {
-    cert_verify_proc_ok = VerifyUsingCertVerifyProc(
-        target_der_cert, hostname, intermediate_der_certs, root_der_certs,
-        dump_prefix_path);
+  impls.push_back(
+      std::unique_ptr<CertVerifyImplUsingProc>(new CertVerifyImplUsingProc(
+          "CertVerifyProc (default)", net::CertVerifyProc::CreateDefault())));
+  impls.push_back(base::MakeUnique<CertVerifyImplUsingProc>(
+      "CertVerifyProcBuiltin", net::CreateCertVerifyProcBuiltin()));
+  impls.push_back(base::MakeUnique<CertVerifyImplUsingPathBuilder>());
+
+  bool all_impls_success = true;
+
+  for (size_t i = 0; i < impls.size(); ++i) {
+    if (i != 0)
+      std::cout << "\n";
+
+    std::cout << impls[i]->GetName() << ":\n";
+    if (!impls[i]->VerifyCert(target_der_cert, hostname, intermediate_der_certs,
+                              root_der_certs, verify_time, dump_prefix_path)) {
+      all_impls_success = false;
+    }
   }
 
-  std::cout << "\nCertPathBuilder:\n";
-
-  if (!hostname.empty()) {
-    std::cerr
-        << "WARNING: --hostname is not yet verified with CertPathBuilder\n";
-  }
-
-  bool path_builder_ok =
-      VerifyUsingPathBuilder(target_der_cert, intermediate_der_certs,
-                             root_der_certs, verify_time, dump_prefix_path);
-
-  return (cert_verify_proc_ok && path_builder_ok) ? 0 : 1;
+  return all_impls_success ? 0 : 1;
 }
diff --git a/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc b/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc
index ba449fd..24e9231 100644
--- a/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc
+++ b/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc
@@ -110,6 +110,7 @@
 }  // namespace
 
 bool VerifyUsingCertVerifyProc(
+    net::CertVerifyProc* cert_verify_proc,
     const CertInput& target_der_cert,
     const std::string& hostname,
     const std::vector<CertInput>& intermediate_der_certs,
@@ -152,8 +153,6 @@
   int flags = net::CertVerifier::VERIFY_EV_CERT |
               net::CertVerifier::VERIFY_CERT_IO_ENABLED;
 
-  scoped_refptr<net::CertVerifyProc> cert_verify_proc =
-      net::CertVerifyProc::CreateDefault();
   if (!x509_additional_trust_anchors.empty() &&
       !cert_verify_proc->SupportsAdditionalTrustAnchors()) {
     std::cerr << "WARNING: Additional trust anchors not supported on this "
diff --git a/net/tools/cert_verify_tool/verify_using_cert_verify_proc.h b/net/tools/cert_verify_tool/verify_using_cert_verify_proc.h
index b31d0e1..2485d08 100644
--- a/net/tools/cert_verify_tool/verify_using_cert_verify_proc.h
+++ b/net/tools/cert_verify_tool/verify_using_cert_verify_proc.h
@@ -12,13 +12,18 @@
 class FilePath;
 }
 
+namespace net {
+class CertVerifyProc;
+}
+
 struct CertInput;
 
-// Verifies |target_der_cert| using CertVerifyProc. Returns true if the
+// Verifies |target_der_cert| using |cert_verify_proc|. Returns true if the
 // certificate verified successfully, false if it failed to verify or there was
 // some other error.
 // Informational messages will be printed to stdout/stderr as appropriate.
 bool VerifyUsingCertVerifyProc(
+    net::CertVerifyProc* cert_verify_proc,
     const CertInput& target_der_cert,
     const std::string& hostname,
     const std::vector<CertInput>& intermediate_der_certs,
diff --git a/net/tools/quic/quic_client_epoll_network_helper.cc b/net/tools/quic/quic_client_epoll_network_helper.cc
index 57b064b..fd8d0c7 100644
--- a/net/tools/quic/quic_client_epoll_network_helper.cc
+++ b/net/tools/quic/quic_client_epoll_network_helper.cc
@@ -46,7 +46,8 @@
       packets_dropped_(0),
       overflow_supported_(false),
       packet_reader_(new QuicPacketReader()),
-      client_(client) {}
+      client_(client),
+      max_reads_per_epoll_loop_(std::numeric_limits<int>::max()) {}
 
 QuicClientEpollNetworkHelper::~QuicClientEpollNetworkHelper() {
   if (client_->connected()) {
@@ -133,12 +134,18 @@
   DCHECK_EQ(fd, GetLatestFD());
 
   if (event->in_events & EPOLLIN) {
+    DVLOG(1) << "Read packets on EPOLLIN";
+    int times_to_read = max_reads_per_epoll_loop_;
     bool more_to_read = true;
-    while (client_->connected() && more_to_read) {
+    while (client_->connected() && more_to_read && times_to_read > 0) {
       more_to_read = packet_reader_->ReadAndDispatchPackets(
           GetLatestFD(), GetLatestClientAddress().port(),
           *client_->helper()->GetClock(), this,
           overflow_supported_ ? &packets_dropped_ : nullptr);
+      --times_to_read;
+    }
+    if (client_->connected() && more_to_read) {
+      event->out_ready_mask |= EPOLLIN;
     }
   }
   if (client_->connected() && (event->in_events & EPOLLOUT)) {
diff --git a/net/tools/quic/quic_client_epoll_network_helper.h b/net/tools/quic/quic_client_epoll_network_helper.h
index bc2fa1ba..4e83100 100644
--- a/net/tools/quic/quic_client_epoll_network_helper.h
+++ b/net/tools/quic/quic_client_epoll_network_helper.h
@@ -83,6 +83,10 @@
 
   QuicClientBase* client() { return client_; }
 
+  void set_max_reads_per_epoll_loop(int num_reads) {
+    max_reads_per_epoll_loop_ = num_reads;
+  }
+
  private:
   friend class test::QuicClientPeer;
 
@@ -117,6 +121,8 @@
 
   QuicClientBase* client_;
 
+  int max_reads_per_epoll_loop_;
+
   DISALLOW_COPY_AND_ASSIGN(QuicClientEpollNetworkHelper);
 };
 
diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc
index 7c3435e4..a52ba6f 100644
--- a/net/tools/quic/quic_dispatcher.cc
+++ b/net/tools/quic/quic_dispatcher.cc
@@ -373,7 +373,7 @@
       framer_.SetSupportedVersions(GetSupportedVersions());
     }
     if (!framer_.IsSupportedVersion(packet_version)) {
-      if (ShouldCreateSessionForUnknownVersion(framer_.last_version_tag())) {
+      if (ShouldCreateSessionForUnknownVersion(framer_.last_version_label())) {
         return true;
       }
       // Since the version is not supported, send a version negotiation
@@ -483,14 +483,32 @@
     return kFateTimeWait;
   }
 
-  // Check that the sequence number is within the range that the client is
-  // expected to send before receiving a response from the server.
+  // initial packet number of 0 is always invalid.
   const int kInvalidPacketNumber = 0;
-  if (header.packet_number == kInvalidPacketNumber ||
-      header.packet_number > kMaxReasonableInitialPacketNumber) {
+  if (header.packet_number == kInvalidPacketNumber) {
     return kFateTimeWait;
   }
-
+  if (FLAGS_quic_restart_flag_quic_enable_accept_random_ipn) {
+    QUIC_FLAG_COUNT_N(quic_restart_flag_quic_enable_accept_random_ipn, 1, 2);
+    // Accepting Initial Packet Numbers in 1...((2^31)-1) range... check
+    // maximum accordingly.
+    if (header.packet_number > kMaxRandomInitialPacketNumber) {
+      return kFateTimeWait;
+    }
+  } else {
+    // Count those that would have been accepted if FLAGS..random_ipn
+    // were true -- to detect/diagnose potential issues prior to
+    // enabling the flag.
+    if ((header.packet_number > kMaxReasonableInitialPacketNumber) &&
+        (header.packet_number <= kMaxRandomInitialPacketNumber)) {
+      QUIC_CODE_COUNT_N(had_possibly_random_ipn, 1, 2);
+    }
+    // Check that the sequence number is within the range that the client is
+    // expected to send before receiving a response from the server.
+    if (header.packet_number > kMaxReasonableInitialPacketNumber) {
+      return kFateTimeWait;
+    }
+  }
   return kFateProcess;
 }
 
@@ -607,17 +625,19 @@
   QUIC_DLOG(INFO) << QuicErrorCodeToString(error);
 }
 
-bool QuicDispatcher::ShouldCreateSessionForUnknownVersion(QuicTag version_tag) {
+bool QuicDispatcher::ShouldCreateSessionForUnknownVersion(
+    QuicVersionLabel /*version_label*/) {
   return false;
 }
 
 bool QuicDispatcher::OnProtocolVersionMismatch(
     QuicVersion /*received_version*/) {
-  QUIC_BUG_IF(!time_wait_list_manager_->IsConnectionIdInTimeWait(
-                  current_connection_id_) &&
-              !ShouldCreateSessionForUnknownVersion(framer_.last_version_tag()))
+  QUIC_BUG_IF(
+      !time_wait_list_manager_->IsConnectionIdInTimeWait(
+          current_connection_id_) &&
+      !ShouldCreateSessionForUnknownVersion(framer_.last_version_label()))
       << "Unexpected version mismatch: "
-      << QuicTagToString(framer_.last_version_tag());
+      << QuicVersionLabelToString(framer_.last_version_label());
 
   // Keep processing after protocol mismatch - this will be dealt with by the
   // time wait list or connection that we will create.
diff --git a/net/tools/quic/quic_dispatcher.h b/net/tools/quic/quic_dispatcher.h
index 52905bc..27204ab 100644
--- a/net/tools/quic/quic_dispatcher.h
+++ b/net/tools/quic/quic_dispatcher.h
@@ -252,8 +252,9 @@
   virtual QuicPacketWriter* CreatePerConnectionWriter();
 
   // Returns true if a session should be created for a connection with an
-  // unknown version identified by |version_tag|.
-  virtual bool ShouldCreateSessionForUnknownVersion(QuicTag version_tag);
+  // unknown version identified by |version_label|.
+  virtual bool ShouldCreateSessionForUnknownVersion(
+      QuicVersionLabel version_label);
 
   void SetLastError(QuicErrorCode error);
 
diff --git a/net/tools/quic/quic_dispatcher_test.cc b/net/tools/quic/quic_dispatcher_test.cc
index b2faeab9..b1543217 100644
--- a/net/tools/quic/quic_dispatcher_test.cc
+++ b/net/tools/quic/quic_dispatcher_test.cc
@@ -527,22 +527,29 @@
 
 TEST_F(QuicDispatcherTest, TooBigSeqNoPacketToTimeWaitListManager) {
   CreateTimeWaitListManager();
-
+  FLAGS_quic_restart_flag_quic_enable_accept_random_ipn = false;
   QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
   QuicConnectionId connection_id = 1;
+
   // Dispatcher forwards this packet for this connection_id to the time wait
   // list manager.
   EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, QuicStringPiece("hq")))
       .Times(0);
-  EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, connection_id))
-      .Times(1);
+  EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, 1)).Times(1);
+  EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, 2)).Times(1);
   EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _, _))
-      .Times(1);
+      .Times(2);
   // A packet whose packet number is one to large to be allowed to start a
   // connection.
   ProcessPacket(client_address, connection_id, true, SerializeCHLO(),
                 PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER,
                 QuicDispatcher::kMaxReasonableInitialPacketNumber + 1);
+  connection_id = 2;
+  FLAGS_quic_restart_flag_quic_enable_accept_random_ipn = true;
+  ProcessPacket(client_address, connection_id, true, SerializeCHLO(),
+                PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER,
+                kMaxRandomInitialPacketNumber +
+                    QuicDispatcher::kMaxReasonableInitialPacketNumber + 1);
 }
 
 TEST_F(QuicDispatcherTest, SupportedVersionsChangeInFlight) {
diff --git a/net/tools/quic/stateless_rejector_test.cc b/net/tools/quic/stateless_rejector_test.cc
index 20fe8bc..4e6074b4 100644
--- a/net/tools/quic/stateless_rejector_test.cc
+++ b/net/tools/quic/stateless_rejector_test.cc
@@ -108,7 +108,8 @@
         "#" + QuicTextUtils::HexEncode(config_peer_.GetPrimaryConfig()->id);
 
     // Encode the QUIC version.
-    ver_hex_ = QuicTagToString(QuicVersionToQuicTag(GetParam().version));
+    ver_hex_ = QuicVersionLabelToString(
+        QuicVersionToQuicVersionLabel(GetParam().version));
 
     // Generate a public value.
     char public_value[32];
diff --git a/net/url_request/redirect_info.cc b/net/url_request/redirect_info.cc
index 5b10f70..a65ec36 100644
--- a/net/url_request/redirect_info.cc
+++ b/net/url_request/redirect_info.cc
@@ -4,8 +4,107 @@
 
 #include "net/url_request/redirect_info.h"
 
+#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "net/url_request/url_request_job.h"
+
 namespace net {
 
+namespace {
+
+std::string ComputeMethodForRedirect(const std::string& method,
+                                     int http_status_code) {
+  // For 303 redirects, all request methods except HEAD are converted to GET,
+  // as per the latest httpbis draft.  The draft also allows POST requests to
+  // be converted to GETs when following 301/302 redirects, for historical
+  // reasons. Most major browsers do this and so shall we.  Both RFC 2616 and
+  // the httpbis draft say to prompt the user to confirm the generation of new
+  // requests, other than GET and HEAD requests, but IE omits these prompts and
+  // so shall we.
+  // See:
+  // https://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-17#section-7.3
+  if ((http_status_code == 303 && method != "HEAD") ||
+      ((http_status_code == 301 || http_status_code == 302) &&
+       method == "POST")) {
+    return "GET";
+  }
+  return method;
+}
+
+// A redirect response can contain a Referrer-Policy header
+// (https://w3c.github.io/webappsec-referrer-policy/). This function checks for
+// a Referrer-Policy header, and parses it if present. Returns the referrer
+// policy that should be used for the request.
+URLRequest::ReferrerPolicy ProcessReferrerPolicyHeaderOnRedirect(
+    URLRequest::ReferrerPolicy original_referrer_policy,
+    const HttpResponseHeaders* headers) {
+  URLRequest::ReferrerPolicy new_policy = original_referrer_policy;
+  std::string referrer_policy_header;
+  if (headers)
+    headers->GetNormalizedHeader("Referrer-Policy", &referrer_policy_header);
+  std::vector<std::string> policy_tokens =
+      base::SplitString(referrer_policy_header, ",", base::TRIM_WHITESPACE,
+                        base::SPLIT_WANT_NONEMPTY);
+
+  UMA_HISTOGRAM_BOOLEAN("Net.URLRequest.ReferrerPolicyHeaderPresentOnRedirect",
+                        !policy_tokens.empty());
+
+  // Per https://w3c.github.io/webappsec-referrer-policy/#unknown-policy-values,
+  // use the last recognized policy value, and ignore unknown policies.
+  for (const auto& token : policy_tokens) {
+    if (base::CompareCaseInsensitiveASCII(token, "no-referrer") == 0) {
+      new_policy = URLRequest::NO_REFERRER;
+      continue;
+    }
+
+    if (base::CompareCaseInsensitiveASCII(token,
+                                          "no-referrer-when-downgrade") == 0) {
+      new_policy =
+          URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
+      continue;
+    }
+
+    if (base::CompareCaseInsensitiveASCII(token, "origin") == 0) {
+      new_policy = URLRequest::ORIGIN;
+      continue;
+    }
+
+    if (base::CompareCaseInsensitiveASCII(token, "origin-when-cross-origin") ==
+        0) {
+      new_policy = URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN;
+      continue;
+    }
+
+    if (base::CompareCaseInsensitiveASCII(token, "unsafe-url") == 0) {
+      new_policy = URLRequest::NEVER_CLEAR_REFERRER;
+      continue;
+    }
+
+    if (base::CompareCaseInsensitiveASCII(token, "same-origin") == 0) {
+      new_policy = URLRequest::CLEAR_REFERRER_ON_TRANSITION_CROSS_ORIGIN;
+      continue;
+    }
+
+    if (base::CompareCaseInsensitiveASCII(token, "strict-origin") == 0) {
+      new_policy =
+          URLRequest::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
+      continue;
+    }
+
+    if (base::CompareCaseInsensitiveASCII(
+            token, "strict-origin-when-cross-origin") == 0) {
+      new_policy =
+          URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN;
+      continue;
+    }
+  }
+  return new_policy;
+}
+
+}  // namespace
+
 RedirectInfo::RedirectInfo()
     : status_code(-1),
       new_referrer_policy(
@@ -15,4 +114,71 @@
 
 RedirectInfo::~RedirectInfo() {}
 
+RedirectInfo RedirectInfo::ComputeRedirectInfo(
+    const std::string& original_method,
+    const GURL& original_url,
+    const GURL& original_site_for_cookies,
+    URLRequest::FirstPartyURLPolicy original_first_party_url_policy,
+    URLRequest::ReferrerPolicy original_referrer_policy,
+    const std::string& original_referrer,
+    const HttpResponseHeaders* response_headers,
+    int http_status_code,
+    const GURL& new_location,
+    bool token_binding_negotiated,
+    bool copy_fragment) {
+  DCHECK(!response_headers ||
+         response_headers->response_code() == http_status_code);
+
+  RedirectInfo redirect_info;
+
+  redirect_info.status_code = http_status_code;
+
+  // The request method may change, depending on the status code.
+  redirect_info.new_method =
+      ComputeMethodForRedirect(original_method, http_status_code);
+
+  // Move the reference fragment of the old location to the new one if the
+  // new one has none. This duplicates mozilla's behavior.
+  if (original_url.is_valid() && original_url.has_ref() &&
+      !new_location.has_ref() && copy_fragment) {
+    GURL::Replacements replacements;
+    // Reference the |ref| directly out of the original URL to avoid a
+    // malloc.
+    replacements.SetRef(original_url.spec().data(),
+                        original_url.parsed_for_possibly_invalid_spec().ref);
+    redirect_info.new_url = new_location.ReplaceComponents(replacements);
+  } else {
+    redirect_info.new_url = new_location;
+  }
+
+  // Update the first-party URL if appropriate.
+  if (original_first_party_url_policy ==
+      URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT) {
+    redirect_info.new_site_for_cookies = redirect_info.new_url;
+  } else {
+    redirect_info.new_site_for_cookies = original_site_for_cookies;
+  }
+
+  redirect_info.new_referrer_policy = ProcessReferrerPolicyHeaderOnRedirect(
+      original_referrer_policy, response_headers);
+
+  // Alter the referrer if redirecting cross-origin (especially HTTP->HTTPS).
+  redirect_info.new_referrer =
+      URLRequestJob::ComputeReferrerForPolicy(redirect_info.new_referrer_policy,
+                                              GURL(original_referrer),
+                                              redirect_info.new_url)
+          .spec();
+
+  if (response_headers) {
+    std::string include_referer;
+    response_headers->GetNormalizedHeader("include-referred-token-binding-id",
+                                          &include_referer);
+    include_referer = base::ToLowerASCII(include_referer);
+    if (include_referer == "true" && token_binding_negotiated)
+      redirect_info.referred_token_binding_host = original_url.host();
+  }
+
+  return redirect_info;
+}
+
 }  // namespace net
diff --git a/net/url_request/redirect_info.h b/net/url_request/redirect_info.h
index 5342220..34a6e30 100644
--- a/net/url_request/redirect_info.h
+++ b/net/url_request/redirect_info.h
@@ -21,6 +21,33 @@
   RedirectInfo(const RedirectInfo& other);
   ~RedirectInfo();
 
+  // Computes a new RedirectInfo.
+  static RedirectInfo ComputeRedirectInfo(
+      // The following arguments |original_*| are the properties of the original
+      // request.
+      const std::string& original_method,
+      const GURL& original_url,
+      const GURL& original_site_for_cookies,
+      URLRequest::FirstPartyURLPolicy original_first_party_url_policy,
+      URLRequest::ReferrerPolicy original_referrer_policy,
+      const std::string& original_referrer,
+      // |response_headers| can be null. This is for non-HTTP URLRequestJobs
+      // which implement IsRedirectResponse() without having HttpResponseHeaders
+      // (ex: URLRequestFileJob). |http_status_code| and |new_location|
+      // arguments are for such case.
+      const HttpResponseHeaders* response_headers,
+      // The HTTP status code of the redirect response.
+      int http_status_code,
+      // The new location URL of the redirect response.
+      const GURL& new_location,
+      // Whether Token Binding of TLS was negotiated.
+      bool token_binding_negotiated,
+      // This method copies the URL fragment of the original URL to the new URL
+      // by default. Set false only when the network delegate has set the
+      // desired redirect URL (with or without fragment), so it must not be
+      // changed any more.
+      bool copy_fragment = true);
+
   // The status code for the redirect response. This is almost redundant with
   // the response headers, but some URLRequestJobs emit redirects without
   // headers.
diff --git a/net/url_request/redirect_info_unittest.cc b/net/url_request/redirect_info_unittest.cc
new file mode 100644
index 0000000..c7b6a3f
--- /dev/null
+++ b/net/url_request/redirect_info_unittest.cc
@@ -0,0 +1,516 @@
+// 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 "net/url_request/redirect_info.h"
+
+#include "base/strings/string_number_conversions.h"
+#include "net/http/http_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace net {
+namespace {
+
+TEST(RedirectInfoTest, MethodForRedirect) {
+  struct TestCase {
+    const char* original_method;
+    int http_status_code;
+    const char* expected_new_method;
+  };
+  const TestCase kTests[] = {
+      {"GET", 301, "GET"},   {"GET", 302, "GET"},   {"GET", 303, "GET"},
+      {"GET", 307, "GET"},   {"GET", 308, "GET"},   {"HEAD", 301, "HEAD"},
+      {"HEAD", 302, "HEAD"}, {"HEAD", 303, "HEAD"}, {"HEAD", 307, "HEAD"},
+      {"HEAD", 308, "HEAD"}, {"POST", 301, "GET"},  {"POST", 302, "GET"},
+      {"POST", 303, "GET"},  {"POST", 307, "POST"}, {"POST", 308, "POST"},
+      {"PUT", 301, "PUT"},   {"PUT", 302, "PUT"},   {"PUT", 303, "GET"},
+      {"PUT", 307, "PUT"},   {"PUT", 308, "PUT"},
+  };
+
+  const GURL kOriginalUrl = GURL("https://foo.test/original");
+  const GURL kOriginalSiteForCookies = GURL("https://foo.test/");
+  const URLRequest::FirstPartyURLPolicy kOriginalFirstPartyUrlPolicy =
+      net::URLRequest::NEVER_CHANGE_FIRST_PARTY_URL;
+  const URLRequest::ReferrerPolicy kOriginalReferrerPolicy =
+      net::URLRequest::NEVER_CLEAR_REFERRER;
+  const std::string kOriginalReferrer = "";
+  const GURL kNewLocation = GURL("https://foo.test/redirected");
+  const bool kTokenBindingNegotiated = false;
+  const bool kCopyFragment = true;
+
+  for (const auto& test : kTests) {
+    SCOPED_TRACE(::testing::Message()
+                 << "original_method: " << test.original_method
+                 << " http_status_code: " << test.http_status_code);
+
+    RedirectInfo redirect_info = RedirectInfo::ComputeRedirectInfo(
+        test.original_method, kOriginalUrl, kOriginalSiteForCookies,
+        kOriginalFirstPartyUrlPolicy, kOriginalReferrerPolicy,
+        kOriginalReferrer, nullptr /* response_headers */,
+        test.http_status_code, kNewLocation, kTokenBindingNegotiated,
+        kCopyFragment);
+
+    EXPECT_EQ(test.expected_new_method, redirect_info.new_method);
+    EXPECT_EQ(test.http_status_code, redirect_info.status_code);
+    EXPECT_EQ(kNewLocation, redirect_info.new_url);
+  }
+}
+
+TEST(RedirectInfoTest, CopyFragment) {
+  struct TestCase {
+    bool copy_fragment;
+    const char* original_url;
+    const char* new_location;
+    const char* expected_new_url;
+  };
+  const TestCase kTests[] = {
+      {true, "http://foo.test/original", "http://foo.test/redirected",
+       "http://foo.test/redirected"},
+      {true, "http://foo.test/original#1", "http://foo.test/redirected",
+       "http://foo.test/redirected#1"},
+      {true, "http://foo.test/original#1", "http://foo.test/redirected#2",
+       "http://foo.test/redirected#2"},
+      {false, "http://foo.test/original", "http://foo.test/redirected",
+       "http://foo.test/redirected"},
+      {false, "http://foo.test/original#1", "http://foo.test/redirected",
+       "http://foo.test/redirected"},
+      {false, "http://foo.test/original#1", "http://foo.test/redirected#2",
+       "http://foo.test/redirected#2"},
+  };
+
+  const std::string KOriginalMethod = "GET";
+  const GURL kOriginalSiteForCookies = GURL("https://foo.test/");
+  const URLRequest::FirstPartyURLPolicy kOriginalFirstPartyUrlPolicy =
+      net::URLRequest::NEVER_CHANGE_FIRST_PARTY_URL;
+  const URLRequest::ReferrerPolicy kOriginalReferrerPolicy =
+      net::URLRequest::NEVER_CLEAR_REFERRER;
+  const std::string kOriginalReferrer = "";
+  const int kHttpStatusCode = 301;
+  const bool kTokenBindingNegotiated = false;
+
+  for (const auto& test : kTests) {
+    SCOPED_TRACE(::testing::Message()
+                 << "copy_fragment: " << test.copy_fragment
+                 << " original_url: " << test.original_url
+                 << " new_location: " << test.new_location);
+
+    RedirectInfo redirect_info = RedirectInfo::ComputeRedirectInfo(
+        KOriginalMethod, GURL(test.original_url), kOriginalSiteForCookies,
+        kOriginalFirstPartyUrlPolicy, kOriginalReferrerPolicy,
+        kOriginalReferrer, nullptr /* response_headers */, kHttpStatusCode,
+        GURL(test.new_location), kTokenBindingNegotiated, test.copy_fragment);
+
+    EXPECT_EQ(GURL(test.expected_new_url), redirect_info.new_url);
+  }
+}
+
+TEST(RedirectInfoTest, FirstPartyURLPolicy) {
+  struct TestCase {
+    URLRequest::FirstPartyURLPolicy original_first_party_url_policy;
+    const char* expected_new_site_for_cookies;
+  };
+  const TestCase kTests[] = {
+      {URLRequest::NEVER_CHANGE_FIRST_PARTY_URL, "https://foo.test/"},
+      {URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT,
+       "https://foo.test/redirected"},
+  };
+
+  const std::string KOriginalMethod = "GET";
+  const GURL kOriginalUrl = GURL("https://foo.test/");
+  const GURL kOriginalSiteForCookies = GURL("https://foo.test/");
+  const URLRequest::ReferrerPolicy kOriginalReferrerPolicy =
+      net::URLRequest::NEVER_CLEAR_REFERRER;
+  const std::string kOriginalReferrer = "";
+  const GURL kNewLocation = GURL("https://foo.test/redirected");
+  const int kHttpStatusCode = 301;
+  const bool kTokenBindingNegotiated = false;
+  const bool kCopyFragment = true;
+
+  for (const auto& test : kTests) {
+    SCOPED_TRACE(::testing::Message()
+                 << "original_first_party_url_policy: "
+                 << static_cast<int>(test.original_first_party_url_policy));
+
+    RedirectInfo redirect_info = RedirectInfo::ComputeRedirectInfo(
+        KOriginalMethod, kOriginalUrl, kOriginalSiteForCookies,
+        test.original_first_party_url_policy, kOriginalReferrerPolicy,
+        kOriginalReferrer, nullptr /* response_headers */, kHttpStatusCode,
+        kNewLocation, kTokenBindingNegotiated, kCopyFragment);
+
+    EXPECT_EQ(GURL(test.expected_new_site_for_cookies),
+              redirect_info.new_site_for_cookies);
+  }
+}
+
+TEST(RedirectInfoTest, ReferrerPolicy) {
+  struct TestCase {
+    const char* original_url;
+    const char* original_referrer;
+    const char* response_headers;
+    URLRequest::ReferrerPolicy original_referrer_policy;
+    URLRequest::ReferrerPolicy expected_new_referrer_policy;
+    const char* expected_referrer;
+  };
+
+  const TestCase kTests[] = {
+      // If a redirect serves 'Referrer-Policy: no-referrer', then the referrer
+      // should be cleared.
+      {"http://foo.test/one" /* original url */,
+       "http://foo.test/one" /* original referrer */,
+       "Location: http://foo.test/test\n"
+       "Referrer-Policy: no-referrer\n",
+       // original policy
+       URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+       URLRequest::NO_REFERRER /* expected new policy */,
+       "" /* expected new referrer */},
+
+      // Same as above but for the legacy keyword 'never', which should not be
+      // supported.
+      {"http://foo.test/one" /* original url */,
+       "http://foo.test/one" /* original referrer */,
+       "Location: http://foo.test/test\nReferrer-Policy: never\n",
+       // original policy
+       URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+       // expected new policy
+       URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+       "http://foo.test/one" /* expected new referrer */},
+
+      // If a redirect serves 'Referrer-Policy: no-referrer-when-downgrade',
+      // then the referrer should be cleared on downgrade, even if the original
+      // request's policy specified that the referrer should never be cleared.
+      {"https://foo.test/one" /* original url */,
+       "https://foo.test/one" /* original referrer */,
+       "Location: http://foo.test\n"
+       "Referrer-Policy: no-referrer-when-downgrade\n",
+       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
+       // expected new policy
+       URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+       "" /* expected new referrer */},
+
+      // Same as above but for the legacy keyword 'default', which should not be
+      // supported.
+      {"https://foo.test/one" /* original url */,
+       "https://foo.test/one" /* original referrer */,
+       "Location: http://foo.test\n"
+       "Referrer-Policy: default\n",
+       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
+       // expected new policy
+       URLRequest::NEVER_CLEAR_REFERRER,
+       "https://foo.test/one" /* expected new referrer */},
+
+      // If a redirect serves 'Referrer-Policy: no-referrer-when-downgrade',
+      // the referrer should not be cleared for a non-downgrading redirect. But
+      // the policy should be updated.
+      {"https://foo.test/one" /* original url */,
+       "https://foo.test/one" /* original referrer */,
+       "Location: https://foo.test\n"
+       "Referrer-Policy: no-referrer-when-downgrade\n",
+       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
+       // expected new policy
+       URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+       "https://foo.test/one" /* expected new referrer */},
+
+      // If a redirect serves 'Referrer-Policy: origin', then the referrer
+      // should be stripped to its origin, even if the original request's policy
+      // specified that the referrer should never be cleared.
+      {"https://foo.test/one" /* original url */,
+       "https://foo.test/one" /* original referrer */,
+       "Location: https://foo.test/two\n"
+       "Referrer-Policy: origin\n",
+       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
+       URLRequest::ORIGIN /* expected new policy */,
+       "https://foo.test/" /* expected new referrer */},
+
+      // If a redirect serves 'Referrer-Policy: origin-when-cross-origin', then
+      // the referrer should be untouched for a same-origin redirect...
+      {"https://foo.test/one" /* original url */,
+       "https://foo.test/referrer" /* original referrer */,
+       "Location: https://foo.test/two\n"
+       "Referrer-Policy: origin-when-cross-origin\n",
+       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
+       URLRequest::
+           ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* expected new policy */,
+       "https://foo.test/referrer" /* expected new referrer */},
+
+      // ... but should be stripped to the origin for a cross-origin redirect.
+      {"https://foo.test/one" /* original url */,
+       "https://foo.test/one" /* original referrer */,
+       "Location: https://bar.test/two\n"
+       "Referrer-Policy: origin-when-cross-origin\n",
+       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
+       URLRequest::
+           ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* expected new policy */,
+       "https://foo.test/" /* expected new referrer */},
+
+      // If a redirect serves 'Referrer-Policy: same-origin', then the referrer
+      // should be untouched for a same-origin redirect,
+      {"https://foo.test/one" /* original url */,
+       "https://foo.test/referrer" /* original referrer */,
+       "Location: https://foo.test/two\n"
+       "Referrer-Policy: same-origin\n",
+       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
+       URLRequest::CLEAR_REFERRER_ON_TRANSITION_CROSS_ORIGIN /* new policy */
+       ,
+       "https://foo.test/referrer" /* expected new referrer */},
+
+      // ... but should be cleared for a cross-origin redirect.
+      {"https://foo.test/one" /* original url */,
+       "https://foo.test/referrer" /* original referrer */,
+       "Location: https://bar.test/two\n"
+       "Referrer-Policy: same-origin\n",
+       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
+       URLRequest::CLEAR_REFERRER_ON_TRANSITION_CROSS_ORIGIN,
+       "" /* expected new referrer */},
+
+      // If a redirect serves 'Referrer-Policy: strict-origin', then the
+      // referrer should be the origin only for a cross-origin non-downgrading
+      // redirect,
+      {"https://foo.test/one" /* original url */,
+       "https://foo.test/referrer" /* original referrer */,
+       "Location: https://bar.test/two\n"
+       "Referrer-Policy: strict-origin\n",
+       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
+       URLRequest::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+       "https://foo.test/" /* expected new referrer */},
+      {"http://foo.test/one" /* original url */,
+       "http://foo.test/referrer" /* original referrer */,
+       "Location: http://bar.test/two\n"
+       "Referrer-Policy: strict-origin\n",
+       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
+       URLRequest::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+       "http://foo.test/" /* expected new referrer */},
+
+      // ... but should be cleared for a downgrading redirect.
+      {"https://foo.test/one" /* original url */,
+       "https://foo.test/referrer" /* original referrer */,
+       "Location: http://foo.test/two\n"
+       "Referrer-Policy: strict-origin\n",
+       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
+       URLRequest::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+       "" /* expected new referrer */},
+
+      // If a redirect serves 'Referrer-Policy:
+      // strict-origin-when-cross-origin', then the referrer should be preserved
+      // for a same-origin redirect,
+      {"https://foo.test/one" /* original url */,
+       "https://foo.test/referrer" /* original referrer */,
+       "Location: https://foo.test/two\n"
+       "Referrer-Policy: strict-origin-when-cross-origin\n",
+       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
+       URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
+       "https://foo.test/referrer" /* expected new referrer */},
+      {"http://foo.test/one" /* original url */,
+       "http://foo.test/referrer" /* original referrer */,
+       "Location: http://foo.test/two\n"
+       "Referrer-Policy: strict-origin-when-cross-origin\n",
+       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
+       URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
+       "http://foo.test/referrer" /* expected new referrer */},
+
+      // ... but should be stripped to the origin for a cross-origin
+      // non-downgrading redirect,
+      {"https://foo.test/one" /* original url */,
+       "https://foo.test/referrer" /* original referrer */,
+       "Location: https://bar.test/two\n"
+       "Referrer-Policy: strict-origin-when-cross-origin\n",
+       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
+       URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
+       "https://foo.test/" /* expected new referrer */},
+      {"http://foo.test/one" /* original url */,
+       "http://foo.test/referrer" /* original referrer */,
+       "Location: http://bar.test/two\n"
+       "Referrer-Policy: strict-origin-when-cross-origin\n",
+       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
+       URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
+       "http://foo.test/" /* expected new referrer */},
+
+      // ... and should be cleared for a downgrading redirect.
+      {"https://foo.test/one" /* original url */,
+       "https://foo.test/referrer" /* original referrer */,
+       "Location: http://foo.test/two\n"
+       "Referrer-Policy: strict-origin-when-cross-origin\n",
+       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
+       URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
+       "" /* expected new referrer */},
+
+      // If a redirect serves 'Referrer-Policy: unsafe-url', then the referrer
+      // should remain, even if originally set to clear on downgrade.
+      {"https://foo.test/one" /* original url */,
+       "https://foo.test/one" /* original referrer */,
+       "Location: http://bar.test/two\n"
+       "Referrer-Policy: unsafe-url\n",
+       URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */,
+       URLRequest::NEVER_CLEAR_REFERRER /* expected new policy */,
+       "https://foo.test/one" /* expected new referrer */},
+
+      // Same as above but for the legacy keyword 'always', which should not be
+      // supported.
+      {"https://foo.test/one" /* original url */,
+       "https://foo.test/one" /* original referrer */,
+       "Location: http://bar.test/two\n"
+       "Referrer-Policy: always\n",
+       URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */,
+       URLRequest::
+           ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* expected new policy */,
+       "https://foo.test/" /* expected new referrer */},
+
+      // An invalid keyword should leave the policy untouched.
+      {"https://foo.test/one" /* original url */,
+       "https://foo.test/one" /* original referrer */,
+       "Location: https://bar.test/two\n"
+       "Referrer-Policy: not-a-valid-policy\n",
+       URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */,
+       URLRequest::
+           ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* expected new policy */,
+       "https://foo.test/" /* expected new referrer */},
+
+      {"https://foo.test/one" /* original url */,
+       "https://foo.test/one" /* original referrer */,
+       "Location: http://bar.test/two\n"
+       "Referrer-Policy: not-a-valid-policy\n",
+       // original policy
+       URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+       // expected new policy
+       URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+       "" /* expected new referrer */},
+
+      // The last valid keyword should take precedence.
+      {"https://foo.test/one" /* original url */,
+       "https://foo.test/one" /* original referrer */,
+       "Location: https://bar.test/two\n"
+       "Referrer-Policy: unsafe-url\n"
+       "Referrer-Policy: not-a-valid-policy\n",
+       URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */,
+       URLRequest::NEVER_CLEAR_REFERRER /* expected new policy */,
+       "https://foo.test/one" /* expected new referrer */},
+
+      {"https://foo.test/one" /* original url */,
+       "https://foo.test/one" /* original referrer */,
+       "Location: https://bar.test/two\n"
+       "Referrer-Policy: unsafe-url\n"
+       "Referrer-Policy: origin\n",
+       URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */,
+       URLRequest::ORIGIN /* expected new policy */,
+       "https://foo.test/" /* expected new referrer */},
+
+      // An empty header should not affect the request.
+      {"https://foo.test/one" /* original url */,
+       "https://foo.test/one" /* original referrer */,
+       "Location: https://bar.test/two\n"
+       "Referrer-Policy: \n",
+       URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */,
+       URLRequest::
+           ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* expected new policy */,
+       "https://foo.test/" /* expected new referrer */},
+
+      // A redirect response without Referrer-Policy header should not affect
+      // the policy and the referrer.
+      {"http://foo.test/one" /* original url */,
+       "http://foo.test/one" /* original referrer */,
+       "Location: http://foo.test/test\n",
+       // original policy
+       URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+       // expected new policy
+       URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+       "http://foo.test/one" /* expected new referrer */},
+  };
+
+  const std::string KOriginalMethod = "GET";
+  const GURL kOriginalSiteForCookies = GURL("https://foo.test/");
+  const URLRequest::FirstPartyURLPolicy kOriginalFirstPartyUrlPolicy =
+      net::URLRequest::NEVER_CHANGE_FIRST_PARTY_URL;
+  const bool kTokenBindingNegotiated = false;
+  const bool kCopyFragment = true;
+
+  for (const auto& test : kTests) {
+    SCOPED_TRACE(::testing::Message()
+                 << "original_url: " << test.original_url
+                 << " original_referrer: " << test.original_referrer
+                 << " response_headers: " << test.response_headers
+                 << " original_referrer_policy: "
+                 << static_cast<int>(test.original_referrer_policy));
+
+    std::string response_header_text =
+        "HTTP/1.1 302 Redirect\n" + std::string(test.response_headers);
+    std::string raw_headers = HttpUtil::AssembleRawHeaders(
+        response_header_text.c_str(),
+        static_cast<int>(response_header_text.length()));
+    auto response_headers =
+        base::MakeRefCounted<HttpResponseHeaders>(raw_headers);
+    EXPECT_EQ(302, response_headers->response_code());
+
+    std::string location_string;
+    EXPECT_TRUE(response_headers->IsRedirect(&location_string));
+    const GURL original_url = GURL(test.original_url);
+    const GURL new_location = original_url.Resolve(location_string);
+
+    RedirectInfo redirect_info = RedirectInfo::ComputeRedirectInfo(
+        KOriginalMethod, original_url, kOriginalSiteForCookies,
+        kOriginalFirstPartyUrlPolicy, test.original_referrer_policy,
+        test.original_referrer, response_headers.get(),
+        response_headers->response_code(), new_location,
+        kTokenBindingNegotiated, kCopyFragment);
+
+    EXPECT_EQ(test.expected_new_referrer_policy,
+              redirect_info.new_referrer_policy);
+    EXPECT_EQ(test.expected_referrer, redirect_info.new_referrer);
+  }
+}
+
+TEST(RedirectInfoTest, ReferredTokenBinding) {
+  struct TestCase {
+    bool token_binding_negotiated;
+    const char* response_headers;
+    const char* expected_referred_token_binding_host;
+  };
+  const TestCase kTests[] = {
+      {true, "", ""},
+      {true, "Include-Referred-Token-Binding-ID: true", "foo.test"},
+      {true, "Include-Referred-Token-Binding-ID: bar", ""},
+      {false, "", ""},
+      {false, "Include-Referred-Token-Binding-ID: true", ""},
+      {false, "Include-Referred-Token-Binding-ID: bar", ""},
+  };
+
+  const std::string KOriginalMethod = "GET";
+  const GURL kriginalUrl = GURL("https://foo.test/");
+  const GURL kOriginalSiteForCookies = GURL("https://foo.test/");
+  const URLRequest::FirstPartyURLPolicy kOriginalFirstPartyUrlPolicy =
+      net::URLRequest::NEVER_CHANGE_FIRST_PARTY_URL;
+  const URLRequest::ReferrerPolicy kOriginalReferrerPolicy =
+      net::URLRequest::NEVER_CLEAR_REFERRER;
+  const std::string kOriginalReferrer = "";
+  const GURL kNewLocation = GURL("https://bar.test/redirected");
+  const bool kCopyFragment = true;
+
+  for (const auto& test : kTests) {
+    SCOPED_TRACE(::testing::Message()
+                 << "token_binding_negotiated: "
+                 << test.token_binding_negotiated
+                 << " response_headers:" << test.response_headers);
+
+    std::string response_header_text =
+        "HTTP/1.1 302 Redirect\nLocation: " + kNewLocation.spec() + "\n" +
+        std::string(test.response_headers);
+    std::string raw_headers = HttpUtil::AssembleRawHeaders(
+        response_header_text.c_str(),
+        static_cast<int>(response_header_text.length()));
+    auto response_headers =
+        base::MakeRefCounted<HttpResponseHeaders>(raw_headers);
+    EXPECT_EQ(302, response_headers->response_code());
+
+    RedirectInfo redirect_info = RedirectInfo::ComputeRedirectInfo(
+        KOriginalMethod, kriginalUrl, kOriginalSiteForCookies,
+        kOriginalFirstPartyUrlPolicy, kOriginalReferrerPolicy,
+        kOriginalReferrer, response_headers.get(),
+        response_headers->response_code(), kNewLocation,
+        test.token_binding_negotiated, kCopyFragment);
+
+    EXPECT_EQ(test.expected_referred_token_binding_host,
+              redirect_info.referred_token_binding_host);
+  }
+}
+
+}  // namespace
+}  // namespace net
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc
index 224f48b..ea17dcf 100644
--- a/net/url_request/url_request_job.cc
+++ b/net/url_request/url_request_job.cc
@@ -15,8 +15,6 @@
 #include "base/power_monitor/power_monitor.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "net/base/auth.h"
@@ -48,95 +46,6 @@
   return std::move(event_params);
 }
 
-std::string ComputeMethodForRedirect(const std::string& method,
-                                     int http_status_code) {
-  // For 303 redirects, all request methods except HEAD are converted to GET,
-  // as per the latest httpbis draft.  The draft also allows POST requests to
-  // be converted to GETs when following 301/302 redirects, for historical
-  // reasons. Most major browsers do this and so shall we.  Both RFC 2616 and
-  // the httpbis draft say to prompt the user to confirm the generation of new
-  // requests, other than GET and HEAD requests, but IE omits these prompts and
-  // so shall we.
-  // See:
-  // https://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-17#section-7.3
-  if ((http_status_code == 303 && method != "HEAD") ||
-      ((http_status_code == 301 || http_status_code == 302) &&
-       method == "POST")) {
-    return "GET";
-  }
-  return method;
-}
-
-// A redirect response can contain a Referrer-Policy header
-// (https://w3c.github.io/webappsec-referrer-policy/). This function
-// checks for a Referrer-Policy header, and parses it if
-// present. Returns the referrer policy that should be used for the
-// request.
-URLRequest::ReferrerPolicy ProcessReferrerPolicyHeaderOnRedirect(
-    URLRequest* request) {
-  URLRequest::ReferrerPolicy new_policy = request->referrer_policy();
-
-  std::string referrer_policy_header;
-  request->GetResponseHeaderByName("Referrer-Policy", &referrer_policy_header);
-  std::vector<std::string> policy_tokens =
-      base::SplitString(referrer_policy_header, ",", base::TRIM_WHITESPACE,
-                        base::SPLIT_WANT_NONEMPTY);
-
-  UMA_HISTOGRAM_BOOLEAN("Net.URLRequest.ReferrerPolicyHeaderPresentOnRedirect",
-                        !policy_tokens.empty());
-
-  // Per https://w3c.github.io/webappsec-referrer-policy/#unknown-policy-values,
-  // use the last recognized policy value, and ignore unknown policies.
-  for (const auto& token : policy_tokens) {
-    if (base::CompareCaseInsensitiveASCII(token, "no-referrer") == 0) {
-      new_policy = URLRequest::NO_REFERRER;
-      continue;
-    }
-
-    if (base::CompareCaseInsensitiveASCII(token,
-                                          "no-referrer-when-downgrade") == 0) {
-      new_policy =
-          URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
-      continue;
-    }
-
-    if (base::CompareCaseInsensitiveASCII(token, "origin") == 0) {
-      new_policy = URLRequest::ORIGIN;
-      continue;
-    }
-
-    if (base::CompareCaseInsensitiveASCII(token, "origin-when-cross-origin") ==
-        0) {
-      new_policy = URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN;
-      continue;
-    }
-
-    if (base::CompareCaseInsensitiveASCII(token, "unsafe-url") == 0) {
-      new_policy = URLRequest::NEVER_CLEAR_REFERRER;
-      continue;
-    }
-
-    if (base::CompareCaseInsensitiveASCII(token, "same-origin") == 0) {
-      new_policy = URLRequest::CLEAR_REFERRER_ON_TRANSITION_CROSS_ORIGIN;
-      continue;
-    }
-
-    if (base::CompareCaseInsensitiveASCII(token, "strict-origin") == 0) {
-      new_policy =
-          URLRequest::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
-      continue;
-    }
-
-    if (base::CompareCaseInsensitiveASCII(
-            token, "strict-origin-when-cross-origin") == 0) {
-      new_policy =
-          URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN;
-      continue;
-    }
-  }
-  return new_policy;
-}
-
 }  // namespace
 
 // Each SourceStreams own the previous SourceStream in the chain, but the
@@ -334,13 +243,13 @@
 
 void URLRequestJob::FollowDeferredRedirect() {
   // OnReceivedRedirect must have been called.
-  DCHECK_NE(-1, deferred_redirect_info_.status_code);
+  DCHECK(deferred_redirect_info_);
 
   // It is possible that FollowRedirect will delete |this|, so it is not safe to
   // pass along a reference to |deferred_redirect_info_|.
-  RedirectInfo redirect_info = deferred_redirect_info_;
-  deferred_redirect_info_ = RedirectInfo();
-  FollowRedirect(redirect_info);
+  base::Optional<RedirectInfo> redirect_info =
+      std::move(deferred_redirect_info_);
+  FollowRedirect(*redirect_info);
 }
 
 bool URLRequestJob::GetMimeType(std::string* mime_type) const {
@@ -494,8 +403,12 @@
     // code must return immediately.
     base::WeakPtr<URLRequestJob> weak_this(weak_factory_.GetWeakPtr());
 
-    RedirectInfo redirect_info =
-        ComputeRedirectInfo(new_location, http_status_code);
+    RedirectInfo redirect_info = RedirectInfo::ComputeRedirectInfo(
+        request_->method(), request_->url(), request_->site_for_cookies(),
+        request_->first_party_url_policy(), request_->referrer_policy(),
+        request_->referrer(), request_->response_headers(), http_status_code,
+        new_location, request_->ssl_info().token_binding_negotiated,
+        CopyFragmentOnRedirect(new_location));
     bool defer_redirect = false;
     request_->NotifyReceivedRedirect(redirect_info, &defer_redirect);
 
@@ -505,7 +418,7 @@
       return;
 
     if (defer_redirect) {
-      deferred_redirect_info_ = redirect_info;
+      deferred_redirect_info_ = std::move(redirect_info);
     } else {
       FollowRedirect(redirect_info);
     }
@@ -815,62 +728,6 @@
 void URLRequestJob::UpdatePacketReadTimes() {
 }
 
-RedirectInfo URLRequestJob::ComputeRedirectInfo(const GURL& location,
-                                                int http_status_code) {
-  const GURL& url = request_->url();
-
-  RedirectInfo redirect_info;
-
-  redirect_info.status_code = http_status_code;
-
-  // The request method may change, depending on the status code.
-  redirect_info.new_method =
-      ComputeMethodForRedirect(request_->method(), http_status_code);
-
-  // Move the reference fragment of the old location to the new one if the
-  // new one has none. This duplicates mozilla's behavior.
-  if (url.is_valid() && url.has_ref() && !location.has_ref() &&
-      CopyFragmentOnRedirect(location)) {
-    GURL::Replacements replacements;
-    // Reference the |ref| directly out of the original URL to avoid a
-    // malloc.
-    replacements.SetRef(url.spec().data(),
-                        url.parsed_for_possibly_invalid_spec().ref);
-    redirect_info.new_url = location.ReplaceComponents(replacements);
-  } else {
-    redirect_info.new_url = location;
-  }
-
-  // Update the first-party URL if appropriate.
-  if (request_->first_party_url_policy() ==
-          URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT) {
-    redirect_info.new_site_for_cookies = redirect_info.new_url;
-  } else {
-    redirect_info.new_site_for_cookies = request_->site_for_cookies();
-  }
-
-  redirect_info.new_referrer_policy =
-      ProcessReferrerPolicyHeaderOnRedirect(request_);
-
-  // Alter the referrer if redirecting cross-origin (especially HTTP->HTTPS).
-  redirect_info.new_referrer =
-      ComputeReferrerForPolicy(redirect_info.new_referrer_policy,
-                               GURL(request_->referrer()),
-                               redirect_info.new_url)
-          .spec();
-
-  std::string include_referer;
-  request_->GetResponseHeaderByName("include-referred-token-binding-id",
-                                    &include_referer);
-  include_referer = base::ToLowerASCII(include_referer);
-  if (include_referer == "true" &&
-      request_->ssl_info().token_binding_negotiated) {
-    redirect_info.referred_token_binding_host = url.host();
-  }
-
-  return redirect_info;
-}
-
 void URLRequestJob::MaybeNotifyNetworkBytes() {
   if (!network_delegate_)
     return;
diff --git a/net/url_request/url_request_job.h b/net/url_request/url_request_job.h
index 51c03ad..37f4aee2 100644
--- a/net/url_request/url_request_job.h
+++ b/net/url_request/url_request_job.h
@@ -13,6 +13,7 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/optional.h"
 #include "base/power_monitor/power_observer.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/load_states.h"
@@ -390,9 +391,6 @@
   // read since the last invocation.
   virtual void UpdatePacketReadTimes();
 
-  // Computes a new RedirectInfo based on receiving a redirect response of
-  // |location| and |http_status_code|.
-  RedirectInfo ComputeRedirectInfo(const GURL& location, int http_status_code);
 
   // Notify the network delegate that more bytes have been received or sent over
   // the network, if bytes have been received or sent since the previous
@@ -430,7 +428,7 @@
 
   // Set when a redirect is deferred. Redirects are deferred after validity
   // checks are performed, so this field must not be modified.
-  RedirectInfo deferred_redirect_info_;
+  base::Optional<RedirectInfo> deferred_redirect_info_;
 
   // The network delegate to use with this request, if any.
   NetworkDelegate* network_delegate_;
diff --git a/net/url_request/url_request_job_unittest.cc b/net/url_request/url_request_job_unittest.cc
index 6057b49..29d98fec 100644
--- a/net/url_request/url_request_job_unittest.cc
+++ b/net/url_request/url_request_job_unittest.cc
@@ -381,6 +381,7 @@
     const char* expected_final_referrer;
   };
 
+  // Note: There are more thorough test cases in RedirectInfoTest.
   const TestCase kTests[] = {
       // If a redirect serves 'Referrer-Policy: no-referrer', then the referrer
       // should be cleared.
@@ -393,234 +394,16 @@
        URLRequest::NO_REFERRER /* expected final policy */,
        "" /* expected final referrer */},
 
-      // Same as above but for the legacy keyword 'never', which should
-      // not be supported.
+      // A redirect response without Referrer-Policy header should not affect
+      // the policy and the referrer.
       {"http://foo.test/one" /* original url */,
        "http://foo.test/one" /* original referrer */,
-       "Location: http://foo.test/test\nReferrer-Policy: never\n",
+       "Location: http://foo.test/test\n",
        // original policy
        URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
        // expected final policy
        URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
        "http://foo.test/one" /* expected final referrer */},
-
-      // If a redirect serves 'Referrer-Policy:
-      // no-referrer-when-downgrade', then the referrer should be cleared
-      // on downgrade, even if the original request's policy specified
-      // that the referrer should never be cleared.
-      {"https://foo.test/one" /* original url */,
-       "https://foo.test/one" /* original referrer */,
-       "Location: http://foo.test\n"
-       "Referrer-Policy: no-referrer-when-downgrade\n",
-       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
-       // expected final policy
-       URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
-       "" /* expected final referrer */},
-
-      // Same as above but for the legacy keyword 'default', which
-      // should not be supported.
-      {"https://foo.test/one" /* original url */,
-       "https://foo.test/one" /* original referrer */,
-       "Location: http://foo.test\n"
-       "Referrer-Policy: default\n",
-       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
-       // expected final policy
-       URLRequest::NEVER_CLEAR_REFERRER,
-       "https://foo.test/one" /* expected final referrer */},
-
-      // If a redirect serves 'Referrer-Policy: origin', then the referrer
-      // should be stripped to its origin, even if the original request's
-      // policy specified that the referrer should never be cleared.
-      {"https://foo.test/one" /* original url */,
-       "https://foo.test/one" /* original referrer */,
-       "Location: https://foo.test/two\n"
-       "Referrer-Policy: origin\n",
-       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
-       URLRequest::ORIGIN /* expected final policy */,
-       "https://foo.test/" /* expected final referrer */},
-
-      // If a redirect serves 'Referrer-Policy: origin-when-cross-origin',
-      // then the referrer should be untouched for a same-origin redirect...
-      {"https://foo.test/one" /* original url */,
-       "https://foo.test/referrer" /* original referrer */,
-       "Location: https://foo.test/two\n"
-       "Referrer-Policy: origin-when-cross-origin\n",
-       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
-       URLRequest::
-           ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* expected final policy */,
-       "https://foo.test/referrer" /* expected final referrer */},
-
-      // ... but should be stripped to the origin for a cross-origin redirect.
-      {"https://foo.test/one" /* original url */,
-       "https://foo.test/one" /* original referrer */,
-       "Location: https://bar.test/two\n"
-       "Referrer-Policy: origin-when-cross-origin\n",
-       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
-       URLRequest::
-           ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* expected final policy */,
-       "https://foo.test/" /* expected final referrer */},
-
-      // If a redirect serves 'Referrer-Policy: same-origin', then the referrer
-      // should be untouched for a same-origin redirect,
-      {"https://foo.test/one" /* original url */,
-       "https://foo.test/referrer" /* original referrer */,
-       "Location: https://foo.test/two\n"
-       "Referrer-Policy: same-origin\n",
-       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
-       URLRequest::CLEAR_REFERRER_ON_TRANSITION_CROSS_ORIGIN /* final policy */
-       ,
-       "https://foo.test/referrer" /* expected final referrer */},
-
-      // ... but should be cleared for a cross-origin redirect.
-      {"https://foo.test/one" /* original url */,
-       "https://foo.test/referrer" /* original referrer */,
-       "Location: https://bar.test/two\n"
-       "Referrer-Policy: same-origin\n",
-       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
-       URLRequest::CLEAR_REFERRER_ON_TRANSITION_CROSS_ORIGIN,
-       "" /* expected final referrer */},
-
-      // If a redirect serves 'Referrer-Policy: strict-origin', then the
-      // referrer should be the origin only for a cross-origin non-downgrading
-      // redirect,
-      {"https://foo.test/one" /* original url */,
-       "https://foo.test/referrer" /* original referrer */,
-       "Location: https://bar.test/two\n"
-       "Referrer-Policy: strict-origin\n",
-       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
-       URLRequest::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
-       "https://foo.test/" /* expected final referrer */},
-      {"http://foo.test/one" /* original url */,
-       "http://foo.test/referrer" /* original referrer */,
-       "Location: http://bar.test/two\n"
-       "Referrer-Policy: strict-origin\n",
-       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
-       URLRequest::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
-       "http://foo.test/" /* expected final referrer */},
-
-      // ... but should be cleared for a downgrading redirect.
-      {"https://foo.test/one" /* original url */,
-       "https://foo.test/referrer" /* original referrer */,
-       "Location: http://foo.test/two\n"
-       "Referrer-Policy: strict-origin\n",
-       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
-       URLRequest::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
-       "" /* expected final referrer */},
-
-      // If a redirect serves 'Referrer-Policy:
-      // strict-origin-when-cross-origin', then the referrer should be preserved
-      // for a same-origin redirect,
-      {"https://foo.test/one" /* original url */,
-       "https://foo.test/referrer" /* original referrer */,
-       "Location: https://foo.test/two\n"
-       "Referrer-Policy: strict-origin-when-cross-origin\n",
-       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
-       URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
-       "https://foo.test/referrer" /* expected final referrer */},
-      {"http://foo.test/one" /* original url */,
-       "http://foo.test/referrer" /* original referrer */,
-       "Location: http://foo.test/two\n"
-       "Referrer-Policy: strict-origin-when-cross-origin\n",
-       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
-       URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
-       "http://foo.test/referrer" /* expected final referrer */},
-
-      // ... but should be stripped to the origin for a cross-origin
-      // non-downgrading redirect,
-      {"https://foo.test/one" /* original url */,
-       "https://foo.test/referrer" /* original referrer */,
-       "Location: https://bar.test/two\n"
-       "Referrer-Policy: strict-origin-when-cross-origin\n",
-       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
-       URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
-       "https://foo.test/" /* expected final referrer */},
-      {"http://foo.test/one" /* original url */,
-       "http://foo.test/referrer" /* original referrer */,
-       "Location: http://bar.test/two\n"
-       "Referrer-Policy: strict-origin-when-cross-origin\n",
-       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
-       URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
-       "http://foo.test/" /* expected final referrer */},
-
-      // ... and should be cleared for a downgrading redirect.
-      {"https://foo.test/one" /* original url */,
-       "https://foo.test/referrer" /* original referrer */,
-       "Location: http://foo.test/two\n"
-       "Referrer-Policy: strict-origin-when-cross-origin\n",
-       URLRequest::NEVER_CLEAR_REFERRER /* original policy */,
-       URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
-       "" /* expected final referrer */},
-
-      // If a redirect serves 'Referrer-Policy: unsafe-url', then the
-      // referrer should remain, even if originally set to clear on
-      // downgrade.
-      {"https://foo.test/one" /* original url */,
-       "https://foo.test/one" /* original referrer */,
-       "Location: https://bar.test/two\n"
-       "Referrer-Policy: unsafe-url\n",
-       URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */,
-       URLRequest::NEVER_CLEAR_REFERRER /* expected final policy */,
-       "https://foo.test/one" /* expected final referrer */},
-
-      // Same as above but for the legacy keyword 'always', which should
-      // not be supported.
-      {"https://foo.test/one" /* original url */,
-       "https://foo.test/one" /* original referrer */,
-       "Location: https://bar.test/two\n"
-       "Referrer-Policy: always\n",
-       URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */,
-       URLRequest::
-           ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* expected final policy */,
-       "https://foo.test/" /* expected final referrer */},
-
-      // An invalid keyword should leave the policy untouched.
-      {"https://foo.test/one" /* original url */,
-       "https://foo.test/one" /* original referrer */,
-       "Location: https://bar.test/two\n"
-       "Referrer-Policy: not-a-valid-policy\n",
-       URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */,
-       URLRequest::
-           ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* expected final policy */,
-       "https://foo.test/" /* expected final referrer */},
-
-      {"https://foo.test/one" /* original url */,
-       "https://foo.test/one" /* original referrer */,
-       "Location: http://bar.test/two\n"
-       "Referrer-Policy: not-a-valid-policy\n",
-       // original policy
-       URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
-       // expected final policy
-       URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
-       "" /* expected final referrer */},
-
-      // The last valid keyword should take precedence.
-      {"https://foo.test/one" /* original url */,
-       "https://foo.test/one" /* original referrer */,
-       "Location: https://bar.test/two\n"
-       "Referrer-Policy: unsafe-url\n"
-       "Referrer-Policy: not-a-valid-policy\n",
-       URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */,
-       URLRequest::NEVER_CLEAR_REFERRER /* expected final policy */,
-       "https://foo.test/one" /* expected final referrer */},
-
-      {"https://foo.test/one" /* original url */,
-       "https://foo.test/one" /* original referrer */,
-       "Location: https://bar.test/two\n"
-       "Referrer-Policy: unsafe-url\n"
-       "Referrer-Policy: origin\n",
-       URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */,
-       URLRequest::ORIGIN /* expected final policy */,
-       "https://foo.test/" /* expected final referrer */},
-
-      // An empty header should not affect the request.
-      {"https://foo.test/one" /* original url */,
-       "https://foo.test/one" /* original referrer */,
-       "Location: https://bar.test/two\n"
-       "Referrer-Policy: \n",
-       URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */,
-       URLRequest::
-           ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* expected final policy */,
-       "https://foo.test/" /* expected final referrer */},
   };
 
   for (const auto& test : kTests) {
diff --git a/ppapi/BUILD.gn b/ppapi/BUILD.gn
index 0f11d0a..cf28f25 100644
--- a/ppapi/BUILD.gn
+++ b/ppapi/BUILD.gn
@@ -5,6 +5,7 @@
 import("//build/config/features.gni")
 import("//build/config/nacl/config.gni")
 import("//build/config/nacl/rules.gni")
+import("//components/nacl/features.gni")
 import("//ppapi/features/features.gni")
 import("//testing/test.gni")
 if (is_mac) {
diff --git a/ppapi/native_client/nacl_test_data.gni b/ppapi/native_client/nacl_test_data.gni
index 823b732..4bf1b90b 100644
--- a/ppapi/native_client/nacl_test_data.gni
+++ b/ppapi/native_client/nacl_test_data.gni
@@ -2,7 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/nacl/config.gni")
 import("//build/config/nacl/rules.gni")
+import("//components/nacl/features.gni")
 
 assert(enable_nacl)
 
diff --git a/ppapi/native_client/src/untrusted/pnacl_support_extension/BUILD.gn b/ppapi/native_client/src/untrusted/pnacl_support_extension/BUILD.gn
index f81896e..a4ee207 100644
--- a/ppapi/native_client/src/untrusted/pnacl_support_extension/BUILD.gn
+++ b/ppapi/native_client/src/untrusted/pnacl_support_extension/BUILD.gn
@@ -2,141 +2,141 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/features.gni")
+import("//components/nacl/features.gni")
 
-if (enable_nacl) {
-  # This target copies files from the prebuilt/DEPS'ed in pnacl_translator
-  # toolchain and copies the latest PNaCl IRT shim library.
-  # We could use 'copies', but we want to rename the files in a white-listed
-  # way first.  Thus use an action.
-  action("pnacl_support_extension") {
-    script = "pnacl_component_crx_gen.py"
-    inputs = [
-      "//native_client/build/package_version/package_version.py",
-      "//native_client/pnacl/driver/pnacl_info_template.json",
-      "//native_client/toolchain_revisions/pnacl_translator.json",
-    ]
-    shim_target_label =
-        "//ppapi/native_client/src/untrusted/pnacl_irt_shim:browser"
-    src_shim_name = "libpnacl_irt_shim_browser.a"
-    desired_shim_name = "libpnacl_irt_shim.a"
+assert(enable_nacl)
 
-    # Use the IRT toolchain to build the shim. We want similar properties
-    # (x86-64 sandbox base address hiding). One thing we don't want is the
-    # IRT's secondary TLS, but that is handled by tls_edit and not compiler
-    # flags (so IRT compiler flags should be fine).
-    shim_toolchain_base = "//build/toolchain/nacl:irt_"
+# This target copies files from the prebuilt/DEPS'ed in pnacl_translator
+# toolchain and copies the latest PNaCl IRT shim library.
+# We could use 'copies', but we want to rename the files in a white-listed
+# way first.  Thus use an action.
+action("pnacl_support_extension") {
+  script = "pnacl_component_crx_gen.py"
+  inputs = [
+    "//native_client/build/package_version/package_version.py",
+    "//native_client/pnacl/driver/pnacl_info_template.json",
+    "//native_client/toolchain_revisions/pnacl_translator.json",
+  ]
+  shim_target_label =
+      "//ppapi/native_client/src/untrusted/pnacl_irt_shim:browser"
+  src_shim_name = "libpnacl_irt_shim_browser.a"
+  desired_shim_name = "libpnacl_irt_shim.a"
 
-    shim_target_tc_label = "$shim_target_label($shim_toolchain_base$target_cpu)"
-    deps = [
-      shim_target_tc_label,
-    ]
-    shim_cpu = target_cpu
+  # Use the IRT toolchain to build the shim. We want similar properties
+  # (x86-64 sandbox base address hiding). One thing we don't want is the
+  # IRT's secondary TLS, but that is handled by tls_edit and not compiler
+  # flags (so IRT compiler flags should be fine).
+  shim_toolchain_base = "//build/toolchain/nacl:irt_"
 
-    output_prefix = "$root_out_dir/pnacl/pnacl_public_"
-    outputs = [
-      "${output_prefix}pnacl_json",
-    ]
+  shim_target_tc_label = "$shim_target_label($shim_toolchain_base$target_cpu)"
+  deps = [
+    shim_target_tc_label,
+  ]
+  shim_cpu = target_cpu
 
-    # Files that will be copied from the toolchain to output.
-    outputs_from_toolchain = [
-      "crtbegin_o",
-      "crtend_o",
-      "ld_nexe",
-      "libcrt_platform_a",
-      "libgcc_a",
-      "libpnacl_irt_shim_a",
-      "pnacl_llc_nexe",
-      "pnacl_sz_nexe",
-    ]
+  output_prefix = "$root_out_dir/pnacl/pnacl_public_"
+  outputs = [
+    "${output_prefix}pnacl_json",
+  ]
 
-    if (target_cpu == "arm") {
-      output_cpu = "arm"
-    } else if (target_cpu == "mipsel") {
-      output_cpu = "mips32"
-    } else if (target_cpu == "x64") {
-      output_cpu = "x86_64"
-    } else if (target_cpu == "x86") {
-      output_cpu = "x86_32"
-    } else {
-      assert(false, "unhandled target_cpu")
-    }
+  # Files that will be copied from the toolchain to output.
+  outputs_from_toolchain = [
+    "crtbegin_o",
+    "crtend_o",
+    "ld_nexe",
+    "libcrt_platform_a",
+    "libgcc_a",
+    "libpnacl_irt_shim_a",
+    "pnacl_llc_nexe",
+    "pnacl_sz_nexe",
+  ]
 
-    foreach(output_elem, outputs_from_toolchain) {
-      outputs += [ output_prefix + output_cpu + "_" + output_elem ]
-    }
+  if (target_cpu == "arm") {
+    output_cpu = "arm"
+  } else if (target_cpu == "mipsel") {
+    output_cpu = "mips32"
+  } else if (target_cpu == "x64") {
+    output_cpu = "x86_64"
+  } else if (target_cpu == "x86") {
+    output_cpu = "x86_32"
+  } else {
+    assert(false, "unhandled target_cpu")
+  }
+
+  foreach(output_elem, outputs_from_toolchain) {
+    outputs += [ output_prefix + output_cpu + "_" + output_elem ]
+  }
+
+  shim_lib_path =
+      rebase_path(get_label_info(shim_target_tc_label, "target_out_dir") +
+                      "/$src_shim_name",
+                  root_build_dir)
+
+  # This describes the irt shim library for the main architecture.
+  # On Windows x86, another switch will be added to this below.
+  lib_overrides = [
+    "--lib_override",
+    "$shim_cpu,$shim_lib_path,$desired_shim_name",
+  ]
+
+  if (is_win && target_cpu == "x86") {
+    # On Windows, for offline testing (i.e., without component updater
+    # selecting the platform-specific files with multi-CRXes), we need
+    # to stage both x86-32 and x86-64 (because 32-bit chrome on 64-bit
+    # windows will need 64-bit nexes).
+
+    shim_target_tc_label = "$shim_target_label(${shim_toolchain_base}x64)"
+    shim_cpu = "x64"
 
     shim_lib_path =
         rebase_path(get_label_info(shim_target_tc_label, "target_out_dir") +
                         "/$src_shim_name",
                     root_build_dir)
 
-    # This describes the irt shim library for the main architecture.
-    # On Windows x86, another switch will be added to this below.
-    lib_overrides = [
+    # Pass a second --lib_override for the second architecture.
+    lib_overrides += [
       "--lib_override",
       "$shim_cpu,$shim_lib_path,$desired_shim_name",
     ]
 
-    if (is_win && target_cpu == "x86") {
-      # On Windows, for offline testing (i.e., without component updater
-      # selecting the platform-specific files with multi-CRXes), we need
-      # to stage both x86-32 and x86-64 (because 32-bit chrome on 64-bit
-      # windows will need 64-bit nexes).
+    deps += [ shim_target_tc_label ]
 
-      shim_target_tc_label = "$shim_target_label(${shim_toolchain_base}x64)"
-      shim_cpu = "x64"
-
-      shim_lib_path =
-          rebase_path(get_label_info(shim_target_tc_label, "target_out_dir") +
-                          "/$src_shim_name",
-                      root_build_dir)
-
-      # Pass a second --lib_override for the second architecture.
-      lib_overrides += [
-        "--lib_override",
-        "$shim_cpu,$shim_lib_path,$desired_shim_name",
-      ]
-
-      deps += [ shim_target_tc_label ]
-
-      foreach(output_elem, outputs_from_toolchain) {
-        outputs += [ output_prefix + "x86_64_" + output_elem ]
-      }
+    foreach(output_elem, outputs_from_toolchain) {
+      outputs += [ output_prefix + "x86_64_" + output_elem ]
     }
-
-    if (current_os == "chromeos") {
-      toolchain_os = "linux"
-    } else {
-      toolchain_os = current_os
-    }
-
-    args = lib_overrides
-    args += [
-      "--dest",
-      rebase_path("$root_out_dir/pnacl", root_build_dir),
-
-      "--target_arch",
-      target_cpu,
-
-      "--info_template_path",
-      rebase_path("//native_client/pnacl/driver/pnacl_info_template.json",
-                  root_build_dir),
-
-      "--pnacl_translator_path",
-      rebase_path(
-          "//native_client/toolchain/${toolchain_os}_x86/pnacl_translator",
-          root_build_dir),
-
-      "--package_version_path",
-      rebase_path("//native_client/build/package_version/package_version.py",
-                  root_build_dir),
-
-      "--pnacl_package_name",
-      "pnacl_translator",
-
-      # ABI Version Number
-      "1",
-    ]
   }
+
+  if (current_os == "chromeos") {
+    toolchain_os = "linux"
+  } else {
+    toolchain_os = current_os
+  }
+
+  args = lib_overrides
+  args += [
+    "--dest",
+    rebase_path("$root_out_dir/pnacl", root_build_dir),
+
+    "--target_arch",
+    target_cpu,
+
+    "--info_template_path",
+    rebase_path("//native_client/pnacl/driver/pnacl_info_template.json",
+                root_build_dir),
+
+    "--pnacl_translator_path",
+    rebase_path(
+        "//native_client/toolchain/${toolchain_os}_x86/pnacl_translator",
+        root_build_dir),
+
+    "--package_version_path",
+    rebase_path("//native_client/build/package_version/package_version.py",
+                root_build_dir),
+
+    "--pnacl_package_name",
+    "pnacl_translator",
+
+    # ABI Version Number
+    "1",
+  ]
 }
diff --git a/ppapi/tests/extensions/BUILD.gn b/ppapi/tests/extensions/BUILD.gn
index b8363ab..83017579 100644
--- a/ppapi/tests/extensions/BUILD.gn
+++ b/ppapi/tests/extensions/BUILD.gn
@@ -2,8 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/features.gni")
-import("//build/config/nacl/config.gni")
+import("//components/nacl/features.gni")
 import("//ppapi/native_client/nacl_test_data.gni")
 
 group("extensions") {
diff --git a/printing/printing_context_win.cc b/printing/printing_context_win.cc
index cc48c78..e625c6a6 100644
--- a/printing/printing_context_win.cc
+++ b/printing/printing_context_win.cc
@@ -204,7 +204,9 @@
     int width = requested_media.size_microns.width() / kFromUm;
     int height = requested_media.size_microns.height() / kFromUm;
     unsigned id = 0;
-    if (base::StringToUint(requested_media.vendor_id, &id) && id) {
+    // If the paper size is a custom user size, setting by ID may not work.
+    if (base::StringToUint(requested_media.vendor_id, &id) && id &&
+        id < DMPAPER_USER) {
       dev_mode->dmFields |= DM_PAPERSIZE;
       dev_mode->dmPaperSize = static_cast<short>(id);
     } else if (width > 0 && height > 0) {
diff --git a/remoting/BUILD.gn b/remoting/BUILD.gn
index 8c90858..a0bd295 100644
--- a/remoting/BUILD.gn
+++ b/remoting/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//components/nacl/features.gni")
 import("//media/media_options.gni")
 import("//remoting/build/config/remoting_build.gni")
 
diff --git a/remoting/client/gesture_interpreter.cc b/remoting/client/gesture_interpreter.cc
index 1dcec9f..f4b6d75 100644
--- a/remoting/client/gesture_interpreter.cc
+++ b/remoting/client/gesture_interpreter.cc
@@ -65,7 +65,9 @@
                               GestureState state) {
   AbortAnimations();
   SetGestureInProgress(TouchInputStrategy::ZOOM, state != GESTURE_ENDED);
-  input_strategy_->HandleZoom({pivot_x, pivot_y}, scale, &viewport_);
+  if (viewport_.IsViewportReady()) {
+    input_strategy_->HandleZoom({pivot_x, pivot_y}, scale, &viewport_);
+  }
 }
 
 void GestureInterpreter::Pan(float translation_x, float translation_y) {
@@ -97,7 +99,8 @@
   bool is_dragging_mode = state != GESTURE_ENDED;
   SetGestureInProgress(TouchInputStrategy::DRAG, is_dragging_mode);
 
-  if (!input_strategy_->TrackTouchInput({x, y}, viewport_)) {
+  if (!viewport_.IsViewportReady() ||
+      !input_strategy_->TrackTouchInput({x, y}, viewport_)) {
     return;
   }
   ViewMatrix::Point cursor_position = input_strategy_->GetCursorPosition();
@@ -121,7 +124,8 @@
 void GestureInterpreter::Scroll(float x, float y, float dx, float dy) {
   AbortAnimations();
 
-  if (!input_strategy_->TrackTouchInput({x, y}, viewport_)) {
+  if (!viewport_.IsViewportReady() ||
+      !input_strategy_->TrackTouchInput({x, y}, viewport_)) {
     return;
   }
   ViewMatrix::Point cursor_position = input_strategy_->GetCursorPosition();
@@ -151,7 +155,9 @@
 
 void GestureInterpreter::OnSurfaceSizeChanged(int width, int height) {
   viewport_.SetSurfaceSize(width, height);
-  input_strategy_->FocusViewportOnCursor(&viewport_);
+  if (viewport_.IsViewportReady()) {
+    input_strategy_->FocusViewportOnCursor(&viewport_);
+  }
 }
 
 void GestureInterpreter::OnDesktopSizeChanged(int width, int height) {
@@ -160,7 +166,8 @@
 
 void GestureInterpreter::PanWithoutAbortAnimations(float translation_x,
                                                    float translation_y) {
-  if (input_strategy_->HandlePan({translation_x, translation_y},
+  if (viewport_.IsViewportReady() &&
+      input_strategy_->HandlePan({translation_x, translation_y},
                                  gesture_in_progress_, &viewport_)) {
     // Cursor position changed.
     ViewMatrix::Point cursor_position = input_strategy_->GetCursorPosition();
@@ -178,6 +185,9 @@
 }
 
 void GestureInterpreter::ScrollWithoutAbortAnimations(float dx, float dy) {
+  if (!viewport_.IsViewportReady()) {
+    return;
+  }
   ViewMatrix::Point desktopDelta =
       input_strategy_->MapScreenVectorToDesktop({dx, dy}, viewport_);
   input_stub_->SendMouseWheelEvent(desktopDelta.x, desktopDelta.y);
@@ -192,7 +202,8 @@
     float touch_x,
     float touch_y,
     protocol::MouseEvent_MouseButton button) {
-  if (!input_strategy_->TrackTouchInput({touch_x, touch_y}, viewport_)) {
+  if (!viewport_.IsViewportReady() ||
+      !input_strategy_->TrackTouchInput({touch_x, touch_y}, viewport_)) {
     return;
   }
   ViewMatrix::Point cursor_position = input_strategy_->GetCursorPosition();
diff --git a/remoting/client/plugin/BUILD.gn b/remoting/client/plugin/BUILD.gn
index 763a7450..a2aa05c6 100644
--- a/remoting/client/plugin/BUILD.gn
+++ b/remoting/client/plugin/BUILD.gn
@@ -2,6 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//components/nacl/features.gni")
+assert(enable_nacl)
+
 assert(is_nacl,
        "These targets must only be built using the untrusted NaCl toolchains.")
 
diff --git a/remoting/client/ui/desktop_viewport.cc b/remoting/client/ui/desktop_viewport.cc
index 0b243af..6547a4c 100644
--- a/remoting/client/ui/desktop_viewport.cc
+++ b/remoting/client/ui/desktop_viewport.cc
@@ -97,6 +97,11 @@
          point.y < desktop_size_.y;
 }
 
+bool DesktopViewport::IsViewportReady() const {
+  return desktop_size_.x != 0 && desktop_size_.y != 0 && surface_size_.x != 0 &&
+         surface_size_.y != 0;
+}
+
 ViewMatrix::Point DesktopViewport::ConstrainPointToDesktop(
     const ViewMatrix::Point& point) const {
   if (!IsViewportReady()) {
@@ -151,11 +156,6 @@
   UpdateViewport();
 }
 
-bool DesktopViewport::IsViewportReady() const {
-  return desktop_size_.x != 0 && desktop_size_.y != 0 && surface_size_.x != 0 &&
-         surface_size_.y != 0;
-}
-
 void DesktopViewport::UpdateViewport() {
   if (!IsViewportReady()) {
     // User may attempt to zoom and pan before the desktop image is received.
@@ -223,6 +223,12 @@
   MoveViewportWithoutUpdate(new_center.x - old_center.x,
                             new_center.y - old_center.y);
 
+  DCHECK(desktop_to_surface_transform_.GetScale() >= 0)
+      << "Desktop scale should never be negative.";
+  DCHECK(std::isfinite(desktop_to_surface_transform_.GetOffset().x) &&
+         std::isfinite(desktop_to_surface_transform_.GetOffset().y))
+      << "Desktop offset should be finite number vector.";
+
   if (on_transformation_changed_) {
     on_transformation_changed_.Run(desktop_to_surface_transform_);
   }
diff --git a/remoting/client/ui/desktop_viewport.h b/remoting/client/ui/desktop_viewport.h
index f22451e..983c8d9 100644
--- a/remoting/client/ui/desktop_viewport.h
+++ b/remoting/client/ui/desktop_viewport.h
@@ -61,6 +61,9 @@
   // Returns true if |point| is within the bounds of the desktop.
   bool IsPointWithinDesktopBounds(const ViewMatrix::Point& point) const;
 
+  // True if desktop size and surface size are set.
+  bool IsViewportReady() const;
+
   // Constrains |point| within the bounds of the desktop. Do nothing if the
   // desktop size is not set.
   ViewMatrix::Point ConstrainPointToDesktop(
@@ -89,9 +92,6 @@
   // and the surface size are set.
   void ResizeToFit();
 
-  // True if desktop size and surface size are set.
-  bool IsViewportReady() const;
-
   // Adjusts the size and position of the viewport so that the constrains always
   // hold, then feed the matrix to |on_transformation_changed_|.
   void UpdateViewport();
diff --git a/remoting/client/ui/view_matrix.cc b/remoting/client/ui/view_matrix.cc
index 7ab6a45c..912f0f4 100644
--- a/remoting/client/ui/view_matrix.cc
+++ b/remoting/client/ui/view_matrix.cc
@@ -37,6 +37,10 @@
   offset_ = offset;
 }
 
+const ViewMatrix::Vector2D& ViewMatrix::GetOffset() const {
+  return offset_;
+}
+
 void ViewMatrix::PostScale(const Point& pivot, float scale) {
   scale_ *= scale;
   offset_.x *= scale;
diff --git a/remoting/client/ui/view_matrix.h b/remoting/client/ui/view_matrix.h
index 75ede051..a04b29b 100644
--- a/remoting/client/ui/view_matrix.h
+++ b/remoting/client/ui/view_matrix.h
@@ -47,6 +47,8 @@
   // Sets the offset.
   void SetOffset(const Point& offset);
 
+  const Vector2D& GetOffset() const;
+
   // Adjust the matrix M to M' such that:
   // M * p_a = p_b => M' * p_a = scale * (p_b - pivot) + pivot
   void PostScale(const Point& pivot, float scale);
diff --git a/remoting/ios/app/client_connection_view_controller.mm b/remoting/ios/app/client_connection_view_controller.mm
index 54e9f19..245fb2c 100644
--- a/remoting/ios/app/client_connection_view_controller.mm
+++ b/remoting/ios/app/client_connection_view_controller.mm
@@ -129,14 +129,15 @@
   _activityIndicator.radius = kActivityIndicatorRadius;
   _activityIndicator.trackEnabled = YES;
   _activityIndicator.strokeWidth = kActivityIndicatorStrokeWidth;
-  _activityIndicator.cycleColors = @[ UIColor.whiteColor ];
+  _activityIndicator.cycleColors =
+      @[ RemotingTheme.connectionViewForegroundColor ];
   _activityIndicator.translatesAutoresizingMaskIntoConstraints = NO;
   [self.view addSubview:_activityIndicator];
 
   _statusLabel = [[UILabel alloc] initWithFrame:CGRectZero];
   _statusLabel.numberOfLines = 1;
   _statusLabel.lineBreakMode = NSLineBreakByTruncatingTail;
-  _statusLabel.textColor = [UIColor whiteColor];
+  _statusLabel.textColor = RemotingTheme.connectionViewForegroundColor;
   _statusLabel.textAlignment = NSTextAlignmentCenter;
   _statusLabel.translatesAutoresizingMaskIntoConstraints = NO;
   [self.view addSubview:_statusLabel];
@@ -418,7 +419,8 @@
   _iconView.backgroundColor = RemotingTheme.hostOnlineColor;
 
   [_activityIndicator stopAnimating];
-  _activityIndicator.cycleColors = @[ [UIColor whiteColor] ];
+  _activityIndicator.cycleColors =
+      @[ RemotingTheme.connectionViewForegroundColor ];
   _activityIndicator.indicatorMode = MDCActivityIndicatorModeIndeterminate;
   _activityIndicator.hidden = NO;
   [_activityIndicator startAnimating];
@@ -456,7 +458,7 @@
   _activityIndicator.progress = 0.0;
   _activityIndicator.hidden = NO;
   _activityIndicator.indicatorMode = MDCActivityIndicatorModeDeterminate;
-  _activityIndicator.cycleColors = @[ [UIColor greenColor] ];
+  _activityIndicator.cycleColors = @[ RemotingTheme.hostOnlineColor ];
   [_activityIndicator startAnimating];
   _activityIndicator.progress = 1.0;
 
diff --git a/remoting/ios/app/host_collection_header_view.mm b/remoting/ios/app/host_collection_header_view.mm
index 2aace22..176999b 100644
--- a/remoting/ios/app/host_collection_header_view.mm
+++ b/remoting/ios/app/host_collection_header_view.mm
@@ -11,6 +11,7 @@
 #import <UIKit/UIKit.h>
 
 #import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h"
+#import "remoting/ios/app/remoting_theme.h"
 #import "remoting/ios/app/view_utils.h"
 
 // Applied on the left and right of the label.
@@ -29,7 +30,7 @@
   if (self) {
     _titleLabel = [[UILabel alloc] init];
     _titleLabel.font = [MDCTypography body2Font];
-    _titleLabel.textColor = [UIColor whiteColor];
+    _titleLabel.textColor = RemotingTheme.hostListHeaderTitleColor;
     _titleLabel.backgroundColor = [UIColor clearColor];
     _titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
     [self addSubview:_titleLabel];
diff --git a/remoting/ios/app/host_collection_view_cell.mm b/remoting/ios/app/host_collection_view_cell.mm
index b35898fc..8aadaac 100644
--- a/remoting/ios/app/host_collection_view_cell.mm
+++ b/remoting/ios/app/host_collection_view_cell.mm
@@ -68,14 +68,14 @@
   _titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
   _titleLabel.font = [MDCTypography boldFontFromFont:MDCTypography.subheadFont];
   _titleLabel.alpha = MDCTypography.subheadFontOpacity;
-  _titleLabel.textColor = [UIColor colorWithWhite:0 alpha:0.87f];
+  _titleLabel.textColor = RemotingTheme.hostCellTitleColor;
   [_labelView addSubview:_titleLabel];
 
   _statusLabel = [[UILabel alloc] init];
   _statusLabel.translatesAutoresizingMaskIntoConstraints = NO;
   _statusLabel.font = MDCTypography.captionFont;
   _statusLabel.alpha = MDCTypography.captionFontOpacity;
-  _statusLabel.textColor = [UIColor colorWithWhite:0 alpha:0.60f];
+  _statusLabel.textColor = RemotingTheme.hostCellStatusTextColor;
   [_labelView addSubview:_statusLabel];
 
   UILayoutGuide* safeAreaLayoutGuide =
diff --git a/remoting/ios/app/host_view_controller.mm b/remoting/ios/app/host_view_controller.mm
index f6b3ad6..1baf7d4 100644
--- a/remoting/ios/app/host_view_controller.mm
+++ b/remoting/ios/app/host_view_controller.mm
@@ -46,6 +46,8 @@
   CGSize _keyboardSize;
   BOOL _surfaceCreated;
   HostSettings* _settings;
+
+  // Only change this by calling setFabIsRight:.
   BOOL _fabIsRight;
   NSArray<NSLayoutConstraint*>* _fabLeftConstraints;
   NSArray<NSLayoutConstraint*>* _fabRightConstraints;
@@ -86,13 +88,11 @@
     [_surfaceSizeAnimationLink addToRunLoop:NSRunLoop.currentRunLoop
                                     forMode:NSDefaultRunLoopMode];
 
-    if ([UIView userInterfaceLayoutDirectionForSemanticContentAttribute:
+    BOOL fabIsRight =
+        [UIView userInterfaceLayoutDirectionForSemanticContentAttribute:
                     self.view.semanticContentAttribute] ==
-        UIUserInterfaceLayoutDirectionRightToLeft) {
-      _fabIsRight = NO;
-    } else {
-      _fabIsRight = YES;
-    }
+        UIUserInterfaceLayoutDirectionLeftToRight;
+    [self setFabIsRight:fabIsRight shouldLayout:NO];
   }
   return self;
 }
@@ -152,6 +152,10 @@
                                    primaryImage:RemotingTheme.menuIcon
                                     activeImage:RemotingTheme.closeIcon];
   [_floatingButton addSubview:_actionImageView];
+  // TODO(yuweih): The accessibility label should be changed to "Close" when
+  // the FAB is open.
+  _floatingButton.accessibilityLabel =
+      l10n_util::GetNSString(IDS_ACTIONBAR_MENU);
   [self.view addSubview:_floatingButton];
 
   [self applyInputMode];
@@ -241,8 +245,6 @@
   _surfaceSizeAnimationLink.paused = NO;
 
   [self resizeHostToFitIfNeeded];
-
-  [self updateFABConstraintsAnimated:NO];
 }
 
 #pragma mark - Keyboard Notifications
@@ -332,13 +334,14 @@
 }
 
 - (void)moveFAB {
-  _fabIsRight = !_fabIsRight;
-  [self updateFABConstraintsAnimated:YES];
+  [self setFabIsRight:!_fabIsRight shouldLayout:YES];
 }
 
 #pragma mark - Private
 
-- (void)updateFABConstraintsAnimated:(BOOL)animated {
+- (void)setFabIsRight:(BOOL)fabIsRight shouldLayout:(BOOL)shouldLayout {
+  _fabIsRight = fabIsRight;
+
   [NSLayoutConstraint deactivateConstraints:_fabRightConstraints];
   [NSLayoutConstraint deactivateConstraints:_fabLeftConstraints];
   if (_fabIsRight) {
@@ -347,13 +350,11 @@
     [NSLayoutConstraint activateConstraints:_fabLeftConstraints];
   }
 
-  if (animated) {
+  if (shouldLayout) {
     [UIView animateWithDuration:kMoveFABAnimationTime
                      animations:^{
                        [self.view layoutIfNeeded];
                      }];
-  } else {
-    [self.view layoutIfNeeded];
   }
 }
 
diff --git a/remoting/ios/app/pin_entry_view.mm b/remoting/ios/app/pin_entry_view.mm
index b5dde42..29e1167 100644
--- a/remoting/ios/app/pin_entry_view.mm
+++ b/remoting/ios/app/pin_entry_view.mm
@@ -39,15 +39,13 @@
     self.backgroundColor = [UIColor clearColor];
 
     _pairingSwitch = [[UISwitch alloc] init];
-    _pairingSwitch.tintColor =
-        [UIColor colorWithRed:1.f green:1.f blue:1.f alpha:0.5];
+    _pairingSwitch.tintColor = RemotingTheme.pinEntryPairingColor;
     _pairingSwitch.transform = CGAffineTransformMakeScale(0.5, 0.5);
     _pairingSwitch.translatesAutoresizingMaskIntoConstraints = NO;
     [self addSubview:_pairingSwitch];
 
     _pairingLabel = [[UILabel alloc] init];
-    _pairingLabel.textColor =
-        [UIColor colorWithRed:1.f green:1.f blue:1.f alpha:0.5];
+    _pairingLabel.textColor = RemotingTheme.pinEntryPairingColor;
     _pairingLabel.font = [UIFont systemFontOfSize:12.f];
     _pairingLabel.text =
         l10n_util::GetNSString(IDS_REMEMBER_PIN_ON_THIS_DEVICE);
@@ -69,6 +67,7 @@
         setImage:[RemotingTheme
                          .arrowIcon imageFlippedForRightToLeftLayoutDirection]
         forState:UIControlStateNormal];
+    _pinButton.accessibilityLabel = l10n_util::GetNSString(IDS_CONTINUE_BUTTON);
     [_pinButton setBackgroundColor:RemotingTheme.buttonBackgroundColor
                           forState:UIControlStateNormal];
     [_pinButton setDisabledAlpha:0.7];
@@ -81,14 +80,14 @@
     [self addSubview:_pinButton];
 
     _pinEntry = [[UITextField alloc] init];
-    _pinEntry.textColor = [UIColor whiteColor];
+    _pinEntry.textColor = RemotingTheme.pinEntryTextColor;
     _pinEntry.secureTextEntry = YES;
     _pinEntry.keyboardType = UIKeyboardTypeNumberPad;
     _pinEntry.attributedPlaceholder = [[NSAttributedString alloc]
         initWithString:l10n_util::GetNSString(IDS_ENTER_PIN)
             attributes:@{
               NSForegroundColorAttributeName :
-                  [UIColor colorWithWhite:1.f alpha:0.26f]
+                  RemotingTheme.pinEntryPlaceholderColor
             }];
     _pinEntry.translatesAutoresizingMaskIntoConstraints = NO;
     _pinEntry.delegate = self;
diff --git a/remoting/ios/app/remoting_theme.h b/remoting/ios/app/remoting_theme.h
index f3a2e911..ee3eaae27 100644
--- a/remoting/ios/app/remoting_theme.h
+++ b/remoting/ios/app/remoting_theme.h
@@ -15,14 +15,22 @@
 @property(class, nonatomic, readonly) UIColor* buttonBackgroundColor;
 @property(class, nonatomic, readonly) UIColor* buttonTextColor;
 @property(class, nonatomic, readonly) UIColor* connectionViewBackgroundColor;
+@property(class, nonatomic, readonly) UIColor* connectionViewForegroundColor;
 @property(class, nonatomic, readonly) UIColor* firstLaunchViewBackgroundColor;
 @property(class, nonatomic, readonly) UIColor* flatButtonTextColor;
+@property(class, nonatomic, readonly) UIColor* hostCellTitleColor;
+@property(class, nonatomic, readonly) UIColor* hostCellStatusTextColor;
 @property(class, nonatomic, readonly) UIColor* hostErrorColor;
 @property(class, nonatomic, readonly) UIColor* hostListBackgroundColor;
+@property(class, nonatomic, readonly) UIColor* hostListHeaderTitleColor;
 @property(class, nonatomic, readonly) UIColor* hostOfflineColor;
 @property(class, nonatomic, readonly) UIColor* hostOnlineColor;
 @property(class, nonatomic, readonly) UIColor* menuBlueColor;
+@property(class, nonatomic, readonly) UIColor* menuTextColor;
 @property(class, nonatomic, readonly) UIColor* refreshIndicatorColor;
+@property(class, nonatomic, readonly) UIColor* pinEntryPairingColor;
+@property(class, nonatomic, readonly) UIColor* pinEntryPlaceholderColor;
+@property(class, nonatomic, readonly) UIColor* pinEntryTextColor;
 @property(class, nonatomic, readonly) UIColor* setupListBackgroundColor;
 @property(class, nonatomic, readonly) UIColor* setupListNumberColor;
 @property(class, nonatomic, readonly) UIColor* setupListTextColor;
@@ -34,11 +42,11 @@
 @property(class, nonatomic, readonly) UIImage* backIcon;
 @property(class, nonatomic, readonly) UIImage* checkboxCheckedIcon;
 @property(class, nonatomic, readonly) UIImage* checkboxOutlineIcon;
-@property(class, nonatomic, readonly) UIImage* closeIcon;
+@property(class, nonatomic, readonly) UIImage* closeIcon;  // ally: "Close"
 @property(class, nonatomic, readonly) UIImage* desktopIcon;
 @property(class, nonatomic, readonly) UIImage* feedbackIcon;
 @property(class, nonatomic, readonly) UIImage* helpIcon;
-@property(class, nonatomic, readonly) UIImage* menuIcon;
+@property(class, nonatomic, readonly) UIImage* menuIcon;  // ally: "Menu"
 @property(class, nonatomic, readonly) UIImage* radioCheckedIcon;
 @property(class, nonatomic, readonly) UIImage* radioOutlineIcon;
 @property(class, nonatomic, readonly) UIImage* refreshIcon;
diff --git a/remoting/ios/app/remoting_theme.mm b/remoting/ios/app/remoting_theme.mm
index c330b82..8b566a6a 100644
--- a/remoting/ios/app/remoting_theme.mm
+++ b/remoting/ios/app/remoting_theme.mm
@@ -8,6 +8,9 @@
 
 #import "remoting/ios/app/remoting_theme.h"
 
+#include "remoting/base/string_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
 @implementation RemotingTheme
 
 #pragma mark - Colors
@@ -25,6 +28,10 @@
   return color;
 }
 
++ (UIColor*)connectionViewForegroundColor {
+  return UIColor.whiteColor;
+}
+
 + (UIColor*)hostListBackgroundColor {
   static UIColor* color;
   static dispatch_once_t onceToken;
@@ -34,6 +41,14 @@
   return color;
 }
 
++ (UIColor*)hostListForegroundColor {
+  return UIColor.whiteColor;
+}
+
++ (UIColor*)hostListHeaderTitleColor {
+  return UIColor.whiteColor;
+}
+
 + (UIColor*)menuBlueColor {
   static UIColor* color;
   static dispatch_once_t onceToken;
@@ -46,6 +61,32 @@
   return color;
 }
 
++ (UIColor*)menuTextColor {
+  return UIColor.whiteColor;
+}
+
++ (UIColor*)pinEntryPairingColor {
+  static UIColor* color;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    color = [UIColor colorWithWhite:1.f alpha:0.5f];
+  });
+  return color;
+}
+
++ (UIColor*)pinEntryPlaceholderColor {
+  static UIColor* color;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    color = [UIColor colorWithWhite:1.f alpha:0.26f];
+  });
+  return color;
+}
+
++ (UIColor*)pinEntryTextColor {
+  return UIColor.whiteColor;
+}
+
 + (UIColor*)hostOfflineColor {
   static UIColor* color;
   static dispatch_once_t onceToken;
@@ -107,6 +148,24 @@
   return color;
 }
 
++ (UIColor*)hostCellTitleColor {
+  static UIColor* color;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    color = [UIColor colorWithWhite:0 alpha:0.87f];
+  });
+  return color;
+}
+
++ (UIColor*)hostCellStatusTextColor {
+  static UIColor* color;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    color = [UIColor colorWithWhite:0 alpha:0.60f];
+  });
+  return color;
+}
+
 + (UIColor*)setupListBackgroundColor {
   static UIColor* color;
   static dispatch_once_t onceToken;
@@ -176,6 +235,7 @@
   static dispatch_once_t onceToken;
   dispatch_once(&onceToken, ^{
     icon = [UIImage imageNamed:@"ic_close_white"];
+    icon.accessibilityLabel = l10n_util::GetNSString(IDS_CLOSE);
   });
   return icon;
 }
@@ -194,6 +254,7 @@
   static dispatch_once_t onceToken;
   dispatch_once(&onceToken, ^{
     icon = [UIImage imageNamed:@"ic_menu_white"];
+    icon.accessibilityLabel = l10n_util::GetNSString(IDS_ACTIONBAR_MENU);
   });
   return icon;
 }
diff --git a/remoting/ios/app/remoting_view_controller.mm b/remoting/ios/app/remoting_view_controller.mm
index 7ac6a869..bdc513c 100644
--- a/remoting/ios/app/remoting_view_controller.mm
+++ b/remoting/ios/app/remoting_view_controller.mm
@@ -27,6 +27,7 @@
 #import "remoting/ios/app/refresh_control_provider.h"
 #import "remoting/ios/app/remoting_menu_view_controller.h"
 #import "remoting/ios/app/remoting_theme.h"
+#import "remoting/ios/app/view_utils.h"
 #import "remoting/ios/domain/client_session_details.h"
 #import "remoting/ios/facade/remoting_service.h"
 
@@ -128,6 +129,7 @@
                                          style:UIBarButtonItemStyleDone
                                         target:self
                                         action:@selector(didSelectMenu)];
+    remoting::SetAccessibilityInfoFromImage(menuButton);
     self.navigationItem.leftBarButtonItem = menuButton;
 
     _appBar.headerViewController.headerView.backgroundColor =
diff --git a/remoting/ios/app/settings/remoting_settings_view_controller.mm b/remoting/ios/app/settings/remoting_settings_view_controller.mm
index d62aec4..f235746 100644
--- a/remoting/ios/app/settings/remoting_settings_view_controller.mm
+++ b/remoting/ios/app/settings/remoting_settings_view_controller.mm
@@ -13,6 +13,7 @@
 #import "remoting/ios/app/app_delegate.h"
 #import "remoting/ios/app/remoting_theme.h"
 #import "remoting/ios/app/settings/setting_option.h"
+#import "remoting/ios/app/view_utils.h"
 
 #include "base/logging.h"
 #include "remoting/base/string_resources.h"
@@ -43,9 +44,9 @@
     self.view.backgroundColor = RemotingTheme.menuBlueColor;
     _appBar.headerViewController.headerView.backgroundColor =
         RemotingTheme.menuBlueColor;
-    _appBar.navigationBar.tintColor = [UIColor whiteColor];
-    _appBar.navigationBar.titleTextAttributes =
-        @{NSForegroundColorAttributeName : [UIColor whiteColor]};
+    MDCNavigationBarTextColorAccessibilityMutator* mutator =
+        [[MDCNavigationBarTextColorAccessibilityMutator alloc] init];
+    [mutator mutate:_appBar.navigationBar];
   }
   return self;
 }
@@ -61,12 +62,12 @@
 
   self.collectionView.backgroundColor = RemotingTheme.menuBlueColor;
 
-  // TODO(nicholss): X should be an image.
   UIBarButtonItem* closeButton =
       [[UIBarButtonItem alloc] initWithImage:RemotingTheme.closeIcon
                                        style:UIBarButtonItemStyleDone
                                       target:self
                                       action:@selector(didTapClose:)];
+  remoting::SetAccessibilityInfoFromImage(closeButton);
   self.navigationItem.leftBarButtonItem = nil;
   self.navigationItem.rightBarButtonItem = closeButton;
 
@@ -120,10 +121,10 @@
                                 forIndexPath:indexPath];
   cell.contentView.backgroundColor = RemotingTheme.menuBlueColor;
   cell.textLabel.text = setting.title;
-  cell.textLabel.textColor = [UIColor whiteColor];
+  cell.textLabel.textColor = RemotingTheme.menuTextColor;
   cell.textLabel.numberOfLines = 1;
   cell.detailTextLabel.text = setting.subtext;
-  cell.detailTextLabel.textColor = [UIColor whiteColor];
+  cell.detailTextLabel.textColor = RemotingTheme.menuTextColor;
   cell.detailTextLabel.numberOfLines = 1;
   cell.tintColor = RemotingTheme.menuBlueColor;
 
@@ -208,7 +209,7 @@
   if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
     supplementaryView.contentView.backgroundColor = RemotingTheme.menuBlueColor;
     supplementaryView.textLabel.text = _sections[(NSUInteger)indexPath.section];
-    supplementaryView.textLabel.textColor = [UIColor whiteColor];
+    supplementaryView.textLabel.textColor = RemotingTheme.menuTextColor;
   }
   return supplementaryView;
 }
diff --git a/remoting/ios/app/view_utils.h b/remoting/ios/app/view_utils.h
index f719947..73acc1d 100644
--- a/remoting/ios/app/view_utils.h
+++ b/remoting/ios/app/view_utils.h
@@ -16,6 +16,12 @@
 // guide for older OS versions that exactly matches the anchors of the view.
 UILayoutGuide* SafeAreaLayoutGuideForView(UIView* view);
 
+// Sets the a11y label of the UIBarButtonItem according to the image it holds.
+void SetAccessibilityInfoFromImage(UIBarButtonItem* button);
+
+// Sets the a11y label of the UIButton according to the image it holds.
+void SetAccessibilityInfoFromImage(UIButton* button);
+
 }  // namespace remoting
 
 #endif  // REMOTING_IOS_APP_VIEW_UTILS_H_
diff --git a/remoting/ios/app/view_utils.mm b/remoting/ios/app/view_utils.mm
index 4a47bb7..1a485e0f9 100644
--- a/remoting/ios/app/view_utils.mm
+++ b/remoting/ios/app/view_utils.mm
@@ -46,4 +46,13 @@
   }
 }
 
+void SetAccessibilityInfoFromImage(UIBarButtonItem* button) {
+  button.accessibilityLabel = button.image.accessibilityLabel;
+}
+
+void SetAccessibilityInfoFromImage(UIButton* button) {
+  button.accessibilityLabel =
+      [button imageForState:UIControlStateNormal].accessibilityLabel;
+}
+
 }  // namespace remoting
diff --git a/remoting/ios/app/web_view_controller.mm b/remoting/ios/app/web_view_controller.mm
index 3e625922..c2799234 100644
--- a/remoting/ios/app/web_view_controller.mm
+++ b/remoting/ios/app/web_view_controller.mm
@@ -11,6 +11,7 @@
 #import <WebKit/WebKit.h>
 
 #import "remoting/ios/app/remoting_theme.h"
+#import "remoting/ios/app/view_utils.h"
 
 @interface WebViewController () {
   NSString* _urlString;
@@ -54,6 +55,8 @@
                                          style:UIBarButtonItemStylePlain
                                         target:self
                                         action:@selector(didTapClose:)];
+    remoting::SetAccessibilityInfoFromImage(
+        self.navigationItem.leftBarButtonItem);
   }
 }
 
diff --git a/remoting/tools/BUILD.gn b/remoting/tools/BUILD.gn
index 67f76533..14c3ff4 100644
--- a/remoting/tools/BUILD.gn
+++ b/remoting/tools/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//components/nacl/features.gni")
 import("//remoting/build/config/remoting_build.gni")
 
 group("all_tests") {
diff --git a/remoting/tools/javascript_key_tester/BUILD.gn b/remoting/tools/javascript_key_tester/BUILD.gn
index 3fea768..02bd63d 100644
--- a/remoting/tools/javascript_key_tester/BUILD.gn
+++ b/remoting/tools/javascript_key_tester/BUILD.gn
@@ -2,47 +2,47 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/features.gni")
+import("//components/nacl/features.gni")
 
-if (enable_nacl) {
-  group("javascript_key_tester") {
-    deps = [
-      ":javascript_key_tester_copies",
-    ]
-  }
+assert(enable_nacl)
 
-  copy("javascript_key_tester_copies") {
-    pexe_dir = get_label_info(
-            "pnacl:remoting_key_tester_newlib(//build/toolchain/nacl:newlib_pnacl)",
-            "root_out_dir")
+group("javascript_key_tester") {
+  deps = [
+    ":javascript_key_tester_copies",
+  ]
+}
 
-    sources = [
-      "$pexe_dir/remoting_key_tester_newlib.pexe",
-      "background.js",
-      "chord_tracker.js",
-      "event_listeners.js",
-      "icon_128.png",
-      "main.css",
-      "main.html",
-      "main.js",
-      "manifest.json",
-      "pnacl/remoting_key_tester.nmf",
-    ]
+copy("javascript_key_tester_copies") {
+  pexe_dir = get_label_info(
+          "pnacl:remoting_key_tester_newlib(//build/toolchain/nacl:newlib_pnacl)",
+          "root_out_dir")
 
-    outputs = [
-      "$target_out_dir/remoting/key_tester/{{source_file_part}}",
-    ]
+  sources = [
+    "$pexe_dir/remoting_key_tester_newlib.pexe",
+    "background.js",
+    "chord_tracker.js",
+    "event_listeners.js",
+    "icon_128.png",
+    "main.css",
+    "main.html",
+    "main.js",
+    "manifest.json",
+    "pnacl/remoting_key_tester.nmf",
+  ]
 
-    deps = [
-      ":javascript_key_tester_jscompile",
-      "pnacl:remoting_key_tester_newlib(//build/toolchain/nacl:newlib_pnacl)",
-    ]
-  }
+  outputs = [
+    "$target_out_dir/remoting/key_tester/{{source_file_part}}",
+  ]
 
-  group("javascript_key_tester_jscompile") {
-    # TODO(GYP): crbug.com/471926 add support for run_jscompile=true.
-    run_jscompile = false
-    if (run_jscompile) {
-    }
+  deps = [
+    ":javascript_key_tester_jscompile",
+    "pnacl:remoting_key_tester_newlib(//build/toolchain/nacl:newlib_pnacl)",
+  ]
+}
+
+group("javascript_key_tester_jscompile") {
+  # TODO(GYP): crbug.com/471926 add support for run_jscompile=true.
+  run_jscompile = false
+  if (run_jscompile) {
   }
 }
diff --git a/remoting/webapp/build_template.gni b/remoting/webapp/build_template.gni
index 28b4c91..3e430b0 100644
--- a/remoting/webapp/build_template.gni
+++ b/remoting/webapp/build_template.gni
@@ -7,6 +7,7 @@
 import("//build/config/chrome_build.gni")
 import("//build/config/features.gni")
 import("//build/util/version.gni")
+import("//components/nacl/features.gni")
 import("//remoting/remoting_enable.gni")
 import("//remoting/remoting_locales.gni")
 import("//remoting/remoting_options.gni")
diff --git a/sandbox/win/src/acl.cc b/sandbox/win/src/acl.cc
index f2f5ac4..be1079f8 100644
--- a/sandbox/win/src/acl.cc
+++ b/sandbox/win/src/acl.cc
@@ -48,8 +48,7 @@
   new_access.Trustee.pMultipleTrustee = NULL;
   new_access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
   new_access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
-  new_access.Trustee.ptstrName = reinterpret_cast<LPWSTR>(
-                                    const_cast<SID*>(sid.GetPSID()));
+  new_access.Trustee.ptstrName = reinterpret_cast<LPWSTR>(sid.GetPSID());
 
   if (ERROR_SUCCESS != ::SetEntriesInAcl(1, &new_access, old_dacl, new_dacl))
     return false;
diff --git a/sandbox/win/src/internal_types.h b/sandbox/win/src/internal_types.h
index 7ea4b7d..472ab9d1d 100644
--- a/sandbox/win/src/internal_types.h
+++ b/sandbox/win/src/internal_types.h
@@ -51,12 +51,12 @@
     buffer_.vp = buffer;
   }
 
-  explicit IPCInt(unsigned __int32 i32) {
+  explicit IPCInt(uint32_t i32) {
     buffer_.vp = NULL;
     buffer_.i32 = i32;
   }
 
-  unsigned __int32 As32Bit() const {
+  uint32_t As32Bit() const {
     return buffer_.i32;
   }
 
@@ -67,7 +67,7 @@
  private:
   union U {
     void* vp;
-    unsigned __int32 i32;
+    uint32_t i32;
   } buffer_;
 };
 
diff --git a/sandbox/win/src/policy_engine_opcodes.h b/sandbox/win/src/policy_engine_opcodes.h
index 11a9c813..6300699a 100644
--- a/sandbox/win/src/policy_engine_opcodes.h
+++ b/sandbox/win/src/policy_engine_opcodes.h
@@ -8,6 +8,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include "base/logging.h"
 #include "base/macros.h"
 #include "base/numerics/safe_conversions.h"
 #include "sandbox/win/src/policy_engine_params.h"
@@ -185,7 +186,7 @@
   // evaluating it. Used to do a quick scan forward to the next opcode group.
   bool IsAction() const {
     return (OP_ACTION == opcode_id_);
-  };
+  }
 
   // Returns the opcode type.
   OpcodeID GetID() const {
@@ -294,6 +295,7 @@
 
   // Returns the available memory to make opcodes.
   size_t memory_size() const {
+    DCHECK_GE(memory_bottom_, memory_top_);
     return memory_bottom_ - memory_top_;
   }
 
diff --git a/sandbox/win/src/policy_engine_params.h b/sandbox/win/src/policy_engine_params.h
index fb4c00e3..918d6306 100644
--- a/sandbox/win/src/policy_engine_params.h
+++ b/sandbox/win/src/policy_engine_params.h
@@ -173,7 +173,7 @@
 };
 
 struct CountedParameterSetBase {
-  int count;
+  size_t count;
   ParameterSet parameters[1];
 };
 
@@ -193,7 +193,7 @@
     return reinterpret_cast<CountedParameterSetBase*>(this);
   }
 
-  int count;
+  size_t count;
   ParameterSet parameters[T::PolParamLast];
 };
 
diff --git a/sandbox/win/src/policy_target.cc b/sandbox/win/src/policy_target.cc
index 568fe2f..9e5ae167 100644
--- a/sandbox/win/src/policy_target.cc
+++ b/sandbox/win/src/policy_target.cc
@@ -53,7 +53,7 @@
     return false;
   }
 
-  for (int i = 0; i < params->count; i++) {
+  for (size_t i = 0; i < params->count; i++) {
     if (!params->parameters[i].IsValid()) {
       NOTREACHED_NT();
       return false;
diff --git a/sandbox/win/src/restricted_token.cc b/sandbox/win/src/restricted_token.cc
index b696a24b..63bc38c 100644
--- a/sandbox/win/src/restricted_token.cc
+++ b/sandbox/win/src/restricted_token.cc
@@ -92,8 +92,7 @@
 
     for (unsigned int i = 0; i < sids_for_deny_only_.size() ; ++i) {
       deny_only_array[i].Attributes = SE_GROUP_USE_FOR_DENY_ONLY;
-      deny_only_array[i].Sid =
-          const_cast<SID*>(sids_for_deny_only_[i].GetPSID());
+      deny_only_array[i].Sid = sids_for_deny_only_[i].GetPSID();
     }
   }
 
@@ -103,8 +102,7 @@
 
     for (unsigned int i = 0; i < restrict_size; ++i) {
       sids_to_restrict_array[i].Attributes = 0;
-      sids_to_restrict_array[i].Sid =
-          const_cast<SID*>(sids_to_restrict_[i].GetPSID());
+      sids_to_restrict_array[i].Sid = sids_to_restrict_[i].GetPSID();
     }
   }
 
@@ -242,8 +240,8 @@
       bool should_ignore = false;
       if (exceptions) {
         for (unsigned int j = 0; j < exceptions->size(); ++j) {
-          if (::EqualSid(const_cast<SID*>((*exceptions)[j].GetPSID()),
-                          token_groups->Groups[i].Sid)) {
+          if (::EqualSid((*exceptions)[j].GetPSID(),
+                         token_groups->Groups[i].Sid)) {
             should_ignore = true;
             break;
           }
diff --git a/sandbox/win/src/sandbox.h b/sandbox/win/src/sandbox.h
index 0f613f7d..dc1bcc9 100644
--- a/sandbox/win/src/sandbox.h
+++ b/sandbox/win/src/sandbox.h
@@ -91,6 +91,9 @@
   //   If the return is ERROR_GENERIC, you can call ::GetLastError() to get
   //   more information.
   virtual ResultCode WaitForAllTargets() = 0;
+
+ protected:
+  ~BrokerServices() {}
 };
 
 // TargetServices models the current process from the perspective
@@ -133,6 +136,9 @@
   // information about the current state of the process, such as whether
   // LowerToken has been called or not.
   virtual ProcessState* GetState() = 0;
+
+ protected:
+  ~TargetServices() {}
 };
 
 }  // namespace sandbox
diff --git a/sandbox/win/src/sandbox_nt_util.h b/sandbox/win/src/sandbox_nt_util.h
index 3e02382..c227ede 100644
--- a/sandbox/win/src/sandbox_nt_util.h
+++ b/sandbox/win/src/sandbox_nt_util.h
@@ -67,7 +67,7 @@
 // the one provided by kernel32.
 __forceinline void* _InterlockedCompareExchangePointer(
     void* volatile* destination, void* exchange, void* comperand) {
-  size_t ret = _InterlockedCompareExchange(
+  long ret = _InterlockedCompareExchange(
       reinterpret_cast<long volatile*>(destination),
       static_cast<long>(reinterpret_cast<size_t>(exchange)),
       static_cast<long>(reinterpret_cast<size_t>(comperand)));
diff --git a/sandbox/win/src/sandbox_policy.h b/sandbox/win/src/sandbox_policy.h
index b8a6459..779ca374 100644
--- a/sandbox/win/src/sandbox_policy.h
+++ b/sandbox/win/src/sandbox_policy.h
@@ -252,6 +252,9 @@
   virtual void SetEnableOPMRedirection() = 0;
   // Enable OPM API emulation when in Win32k lockdown.
   virtual bool GetEnableOPMRedirection() = 0;
+
+ protected:
+  ~TargetPolicy() {}
 };
 
 }  // namespace sandbox
diff --git a/sandbox/win/src/sandbox_policy_base.cc b/sandbox/win/src/sandbox_policy_base.cc
index 5c75c84..d3b23a91 100644
--- a/sandbox/win/src/sandbox_policy_base.cc
+++ b/sandbox/win/src/sandbox_policy_base.cc
@@ -611,7 +611,7 @@
       // deal.
       return DENY_ACCESS;
     }
-    for (int i = 0; i < params->count; i++) {
+    for (size_t i = 0; i < params->count; i++) {
       if (!params->parameters[i].IsValid()) {
         NOTREACHED();
         return SIGNAL_ALARM;
diff --git a/sandbox/win/src/sid.cc b/sandbox/win/src/sid.cc
index 19c645b..5df1acf 100644
--- a/sandbox/win/src/sid.cc
+++ b/sandbox/win/src/sid.cc
@@ -4,23 +4,123 @@
 
 #include "sandbox/win/src/sid.h"
 
+#include <sddl.h>
+
 #include "base/logging.h"
+#include "base/win/windows_version.h"
 
 namespace sandbox {
 
-Sid::Sid(const SID *sid) {
-  ::CopySid(SECURITY_MAX_SID_SIZE, sid_, const_cast<SID*>(sid));
+namespace {
+
+typedef decltype(
+    ::DeriveCapabilitySidsFromName) DeriveCapabilitySidsFromNameFunc;
+
+class SidArray {
+ public:
+  SidArray() : count_(0), sids_(nullptr) {}
+
+  ~SidArray() {
+    if (sids_) {
+      for (size_t index = 0; index < count_; ++index) {
+        ::LocalFree(sids_[index]);
+      }
+      ::LocalFree(sids_);
+    }
+  }
+
+  DWORD count() { return count_; }
+  PSID* sids() { return sids_; }
+  PDWORD count_ptr() { return &count_; }
+  PSID** sids_ptr() { return &sids_; }
+
+ private:
+  DWORD count_;
+  PSID* sids_;
 };
 
+const wchar_t* WellKnownCapabilityToName(WellKnownCapabilities capability) {
+  switch (capability) {
+    case kInternetClient:
+      return L"internetClient";
+    case kInternetClientServer:
+      return L"internetClientServer";
+    case kRegistryRead:
+      return L"registryRead";
+    case kLpacCryptoServices:
+      return L"lpacCryptoServices";
+    case kEnterpriseAuthentication:
+      return L"enterpriseAuthentication";
+    case kPrivateNetworkClientServer:
+      return L"privateNetworkClientServer";
+    default:
+      return nullptr;
+  }
+}
+
+}  // namespace
+
+Sid::Sid() : sid_() {}
+
+Sid::Sid(PSID sid) : sid_() {
+  ::CopySid(SECURITY_MAX_SID_SIZE, sid_, sid);
+}
+
+Sid::Sid(const SID* sid) : sid_() {
+  ::CopySid(SECURITY_MAX_SID_SIZE, sid_, const_cast<SID*>(sid));
+}
+
 Sid::Sid(WELL_KNOWN_SID_TYPE type) {
   DWORD size_sid = SECURITY_MAX_SID_SIZE;
-  BOOL result = ::CreateWellKnownSid(type, NULL, sid_, &size_sid);
+  BOOL result = ::CreateWellKnownSid(type, nullptr, sid_, &size_sid);
   DCHECK(result);
   (void)result;
 }
 
-const SID *Sid::GetPSID() const {
-  return reinterpret_cast<SID*>(const_cast<BYTE*>(sid_));
+Sid Sid::FromKnownCapability(WellKnownCapabilities capability) {
+  return Sid::FromNamedCapability(WellKnownCapabilityToName(capability));
+}
+
+Sid Sid::FromNamedCapability(const wchar_t* capability_name) {
+  DeriveCapabilitySidsFromNameFunc* derive_capablity_sids =
+      (DeriveCapabilitySidsFromNameFunc*)GetProcAddress(
+          GetModuleHandle(L"kernelbase"), "DeriveCapabilitySidsFromName");
+  if (!derive_capablity_sids)
+    return Sid();
+
+  if (capability_name == nullptr || ::wcslen(capability_name) == 0)
+    return Sid();
+
+  SidArray capability_group_sids;
+  SidArray capability_sids;
+
+  if (!derive_capablity_sids(capability_name, capability_group_sids.sids_ptr(),
+                             capability_group_sids.count_ptr(),
+                             capability_sids.sids_ptr(),
+                             capability_sids.count_ptr())) {
+    return Sid();
+  }
+
+  if (capability_sids.count() < 1)
+    return Sid();
+
+  return Sid(capability_sids.sids()[0]);
+}
+
+Sid Sid::FromSddlString(const wchar_t* sddl_sid) {
+  PSID converted_sid;
+  if (!::ConvertStringSidToSid(sddl_sid, &converted_sid))
+    return Sid();
+
+  return Sid(converted_sid);
+}
+
+PSID Sid::GetPSID() const {
+  return const_cast<BYTE*>(sid_);
+}
+
+bool Sid::IsValid() const {
+  return !!::IsValidSid(GetPSID());
 }
 
 }  // namespace sandbox
diff --git a/sandbox/win/src/sid.h b/sandbox/win/src/sid.h
index 4656859..c415545 100644
--- a/sandbox/win/src/sid.h
+++ b/sandbox/win/src/sid.h
@@ -9,18 +9,41 @@
 
 namespace sandbox {
 
+enum WellKnownCapabilities {
+  kInternetClient,
+  kInternetClientServer,
+  kRegistryRead,
+  kLpacCryptoServices,
+  kEnterpriseAuthentication,
+  kPrivateNetworkClientServer,
+  kMaxWellKnownCapability
+};
+
 // This class is used to hold and generate SIDS.
 class Sid {
  public:
   // Constructors initializing the object with the SID passed.
   // This is a converting constructor. It is not explicit.
-  Sid(const SID *sid);
+  Sid(PSID sid);
+  Sid(const SID* sid);
   Sid(WELL_KNOWN_SID_TYPE type);
 
+  // Create a Sid from an AppContainer capability name. The name can be
+  // completely arbitrary.
+  static Sid FromNamedCapability(const wchar_t* capability_name);
+  // Create a Sid from a known capability enumeration value.
+  static Sid FromKnownCapability(WellKnownCapabilities capability);
+  // Create a Sid from a SDDL format string, such as S-1-1-0.
+  static Sid FromSddlString(const wchar_t* sddl_sid);
+
   // Returns sid_.
-  const SID *GetPSID() const;
+  PSID GetPSID() const;
+
+  // Gets whether the sid is valid.
+  bool IsValid() const;
 
  private:
+  Sid();
   BYTE sid_[SECURITY_MAX_SID_SIZE];
 };
 
diff --git a/sandbox/win/src/sid_unittest.cc b/sandbox/win/src/sid_unittest.cc
index 76d61e82..b6c2f50 100644
--- a/sandbox/win/src/sid_unittest.cc
+++ b/sandbox/win/src/sid_unittest.cc
@@ -7,65 +7,129 @@
 #define _ATL_NO_EXCEPTIONS
 #include <atlbase.h>
 #include <atlsecurity.h>
+#include <sddl.h>
 
+#include "base/win/windows_version.h"
 #include "sandbox/win/src/sid.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace sandbox {
 
-// Calls ::EqualSid. This function exists only to simplify the calls to
-// ::EqualSid by removing the need to cast the input params.
-BOOL EqualSid(const SID *sid1, const SID *sid2) {
-  return ::EqualSid(const_cast<SID*>(sid1), const_cast<SID*>(sid2));
+namespace {
+
+bool EqualSid(const Sid& sid, const ATL::CSid& compare_sid) {
+  if (!sid.IsValid())
+    return false;
+  return !!::EqualSid(sid.GetPSID(), const_cast<SID*>(compare_sid.GetPSID()));
 }
 
-// Tests the creation if a Sid
+bool EqualSid(const Sid& sid, const wchar_t* sddl_sid) {
+  PSID compare_sid;
+  if (!sid.IsValid())
+    return false;
+  if (!::ConvertStringSidToSid(sddl_sid, &compare_sid))
+    return false;
+  bool equal = !!::EqualSid(sid.GetPSID(), compare_sid);
+  ::LocalFree(compare_sid);
+  return equal;
+}
+
+struct CapabilityTestEntry {
+  WellKnownCapabilities capability_;
+  const wchar_t* capability_name_;
+  const wchar_t* sddl_sid_;
+};
+}
+
+// Tests the creation of a Sid.
 TEST(SidTest, Constructors) {
   ATL::CSid sid_world = ATL::Sids::World();
-  SID *sid_world_pointer = const_cast<SID*>(sid_world.GetPSID());
+  PSID sid_world_pointer = const_cast<SID*>(sid_world.GetPSID());
 
-  // Check the SID* constructor
+  // Check the SID* constructor.
   Sid sid_sid_star(sid_world_pointer);
-  ASSERT_TRUE(EqualSid(sid_world_pointer, sid_sid_star.GetPSID()));
+  ASSERT_TRUE(EqualSid(sid_sid_star, sid_world));
 
-  // Check the copy constructor
+  // Check the copy constructor.
   Sid sid_copy(sid_sid_star);
-  ASSERT_TRUE(EqualSid(sid_world_pointer, sid_copy.GetPSID()));
+  ASSERT_TRUE(EqualSid(sid_copy, sid_world));
+
+  Sid sid_sddl = Sid::FromSddlString(L"S-1-1-0");
+  ASSERT_TRUE(sid_sddl.IsValid());
+  ASSERT_TRUE(EqualSid(sid_sddl, sid_world));
+
+  Sid sid_sddl_invalid = Sid::FromSddlString(L"X-1-1-0");
+  ASSERT_FALSE(sid_sddl_invalid.IsValid());
+
+  Sid sid_sddl_empty = Sid::FromSddlString(L"");
+  ASSERT_FALSE(sid_sddl_empty.IsValid());
 
   // Note that the WELL_KNOWN_SID_TYPE constructor is tested in the GetPSID
-  // test.
+  // test. AppContainer related constructors are tested in AppContainer.
 }
 
 // Tests the method GetPSID
 TEST(SidTest, GetPSID) {
   // Check for non-null result;
-  ASSERT_NE(static_cast<SID*>(NULL), Sid(::WinLocalSid).GetPSID());
-  ASSERT_NE(static_cast<SID*>(NULL), Sid(::WinCreatorOwnerSid).GetPSID());
-  ASSERT_NE(static_cast<SID*>(NULL), Sid(::WinBatchSid).GetPSID());
+  ASSERT_NE(nullptr, Sid(::WinLocalSid).GetPSID());
+  ASSERT_NE(nullptr, Sid(::WinCreatorOwnerSid).GetPSID());
+  ASSERT_NE(nullptr, Sid(::WinBatchSid).GetPSID());
 
-  ASSERT_TRUE(EqualSid(Sid(::WinNullSid).GetPSID(),
-                       ATL::Sids::Null().GetPSID()));
+  ASSERT_TRUE(EqualSid(Sid(::WinNullSid), ATL::Sids::Null()));
 
-  ASSERT_TRUE(EqualSid(Sid(::WinWorldSid).GetPSID(),
-                       ATL::Sids::World().GetPSID()));
+  ASSERT_TRUE(EqualSid(Sid(::WinWorldSid), ATL::Sids::World()));
 
-  ASSERT_TRUE(EqualSid(Sid(::WinDialupSid).GetPSID(),
-                       ATL::Sids::Dialup().GetPSID()));
+  ASSERT_TRUE(EqualSid(Sid(::WinDialupSid), ATL::Sids::Dialup()));
 
-  ASSERT_TRUE(EqualSid(Sid(::WinNetworkSid).GetPSID(),
-                       ATL::Sids::Network().GetPSID()));
+  ASSERT_TRUE(EqualSid(Sid(::WinNetworkSid), ATL::Sids::Network()));
 
-  ASSERT_TRUE(EqualSid(Sid(::WinBuiltinAdministratorsSid).GetPSID(),
-                       ATL::Sids::Admins().GetPSID()));
+  ASSERT_TRUE(
+      EqualSid(Sid(::WinBuiltinAdministratorsSid), ATL::Sids::Admins()));
 
-  ASSERT_TRUE(EqualSid(Sid(::WinBuiltinUsersSid).GetPSID(),
-                       ATL::Sids::Users().GetPSID()));
+  ASSERT_TRUE(EqualSid(Sid(::WinBuiltinUsersSid), ATL::Sids::Users()));
 
-  ASSERT_TRUE(EqualSid(Sid(::WinBuiltinGuestsSid).GetPSID(),
-                       ATL::Sids::Guests().GetPSID()));
+  ASSERT_TRUE(EqualSid(Sid(::WinBuiltinGuestsSid), ATL::Sids::Guests()));
 
-  ASSERT_TRUE(EqualSid(Sid(::WinProxySid).GetPSID(),
-                       ATL::Sids::Proxy().GetPSID()));
+  ASSERT_TRUE(EqualSid(Sid(::WinProxySid), ATL::Sids::Proxy()));
+}
+
+TEST(SidTest, AppContainer) {
+  const CapabilityTestEntry capabilities[] = {
+      {kInternetClient, L"internetClient", L"S-1-15-3-1"},
+      {kInternetClientServer, L"internetClientServer", L"S-1-15-3-2"},
+      {kRegistryRead, L"registryRead",
+       L"S-1-15-3-1024-1065365936-1281604716-3511738428-"
+       "1654721687-432734479-3232135806-4053264122-3456934681"},
+      {kLpacCryptoServices, L"lpacCryptoServices",
+       L"S-1-15-3-1024-3203351429-2120443784-2872670797-"
+       "1918958302-2829055647-4275794519-765664414-2751773334"},
+      {kEnterpriseAuthentication, L"enterpriseAuthentication", L"S-1-15-3-8"},
+      {kPrivateNetworkClientServer, L"privateNetworkClientServer",
+       L"S-1-15-3-3"}};
+
+  // No support for AppContainer less than Win10 RS2.
+  if (base::win::GetVersion() < base::win::VERSION_WIN10_RS2)
+    return;
+
+  Sid sid_nullptr = Sid::FromNamedCapability(nullptr);
+  EXPECT_FALSE(sid_nullptr.IsValid());
+
+  Sid sid_empty = Sid::FromNamedCapability(L"");
+  EXPECT_FALSE(sid_empty.IsValid());
+
+  WellKnownCapabilities invalid_well_known =
+      static_cast<WellKnownCapabilities>(kMaxWellKnownCapability + 1);
+  Sid sid_invalid_well_known = Sid::FromKnownCapability(invalid_well_known);
+  EXPECT_FALSE(sid_invalid_well_known.IsValid());
+
+  for (auto capability : capabilities) {
+    EXPECT_TRUE(EqualSid(Sid::FromNamedCapability(capability.capability_name_),
+                         capability.sddl_sid_))
+        << "Named Capability: " << capability.sddl_sid_;
+    EXPECT_TRUE(EqualSid(Sid::FromKnownCapability(capability.capability_),
+                         capability.sddl_sid_))
+        << "Known Capability: " << capability.sddl_sid_;
+  }
 }
 
 }  // namespace sandbox
diff --git a/sandbox/win/src/target_services.h b/sandbox/win/src/target_services.h
index 45e0d8e..a33c9201 100644
--- a/sandbox/win/src/target_services.h
+++ b/sandbox/win/src/target_services.h
@@ -57,6 +57,7 @@
   bool TestIPCPing(int version);
 
  private:
+  ~TargetServicesBase() {}
   ProcessState process_state_;
   DISALLOW_COPY_AND_ASSIGN(TargetServicesBase);
 };
diff --git a/sandbox/win/src/win_utils.h b/sandbox/win/src/win_utils.h
index a123a13e..7751dee 100644
--- a/sandbox/win/src/win_utils.h
+++ b/sandbox/win/src/win_utils.h
@@ -29,12 +29,12 @@
   // Acquires the lock.
   explicit AutoLock(CRITICAL_SECTION *lock) : lock_(lock) {
     ::EnterCriticalSection(lock);
-  };
+  }
 
   // Releases the lock;
   ~AutoLock() {
     ::LeaveCriticalSection(lock_);
-  };
+  }
 
  private:
   CRITICAL_SECTION *lock_;
diff --git a/services/ui/manifest.json b/services/ui/manifest.json
index 6ec86855..9eb29d0a 100644
--- a/services/ui/manifest.json
+++ b/services/ui/manifest.json
@@ -1,5 +1,6 @@
 {
   "name": "ui",
+  "sandbox_type": "none",
   "display_name": "UI Service",
   "interface_provider_specs": {
     "service_manager:connector": {
diff --git a/services/viz/public/cpp/compositing/OWNERS b/services/viz/public/cpp/compositing/OWNERS
index 4df0c71..45218e5a 100644
--- a/services/viz/public/cpp/compositing/OWNERS
+++ b/services/viz/public/cpp/compositing/OWNERS
@@ -1,4 +1,4 @@
-per-file *_struct_traits*.*=set noparent
-per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *struct_traits*.*=set noparent
+per-file *struct_traits*.*=file://ipc/SECURITY_OWNERS
 per-file *.typemap=set noparent
 per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/services/viz/public/cpp/compositing/copy_output_request_struct_traits.cc b/services/viz/public/cpp/compositing/copy_output_request_struct_traits.cc
index 28f6ef9a..e896345 100644
--- a/services/viz/public/cpp/compositing/copy_output_request_struct_traits.cc
+++ b/services/viz/public/cpp/compositing/copy_output_request_struct_traits.cc
@@ -80,6 +80,17 @@
   auto request = std::make_unique<viz::CopyOutputRequest>(
       result_format, base::BindOnce(SendResult, base::Passed(&result_sender)));
 
+  gfx::Vector2d scale_from;
+  if (!data.ReadScaleFrom(&scale_from) || scale_from.x() <= 0 ||
+      scale_from.y() <= 0) {
+    return false;
+  }
+  gfx::Vector2d scale_to;
+  if (!data.ReadScaleTo(&scale_to) || scale_to.x() <= 0 || scale_to.y() <= 0) {
+    return false;
+  }
+  request->SetScaleRatio(scale_from, scale_to);
+
   if (!data.ReadSource(&request->source_))
     return false;
 
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 3cf32a60..058fbe8 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
@@ -21,6 +21,16 @@
     return request->result_format();
   }
 
+  static const gfx::Vector2d& scale_from(
+      const std::unique_ptr<viz::CopyOutputRequest>& request) {
+    return request->scale_from();
+  }
+
+  static const gfx::Vector2d& scale_to(
+      const std::unique_ptr<viz::CopyOutputRequest>& request) {
+    return request->scale_to();
+  }
+
   static const base::Optional<base::UnguessableToken>& source(
       const std::unique_ptr<viz::CopyOutputRequest>& request) {
     return request->source_;
diff --git a/services/viz/public/cpp/compositing/struct_traits_unittest.cc b/services/viz/public/cpp/compositing/struct_traits_unittest.cc
index 5f6ceb6..12c1964 100644
--- a/services/viz/public/cpp/compositing/struct_traits_unittest.cc
+++ b/services/viz/public/cpp/compositing/struct_traits_unittest.cc
@@ -246,6 +246,10 @@
   const gfx::Rect area(5, 7, 44, 55);
   const auto source =
       base::UnguessableToken::Deserialize(0xdeadbeef, 0xdeadf00d);
+  // Requesting 2:3 scale in X dimension, 5:4 in Y dimension.
+  const gfx::Vector2d scale_from(2, 5);
+  const gfx::Vector2d scale_to(3, 4);
+  const gfx::Rect result_rect(7, 8, 132, 44);
 
   base::RunLoop run_loop;
   std::unique_ptr<CopyOutputRequest> input(new CopyOutputRequest(
@@ -256,21 +260,29 @@
             EXPECT_EQ(expected_rect, result->rect());
             quit_closure.Run();
           },
-          run_loop.QuitClosure(), area)));
+          run_loop.QuitClosure(), result_rect)));
+  input->SetScaleRatio(scale_from, scale_to);
+  EXPECT_EQ(scale_from, input->scale_from());
+  EXPECT_EQ(scale_to, input->scale_to());
   input->set_area(area);
   input->set_source(source);
+  EXPECT_TRUE(input->is_scaled());
   std::unique_ptr<CopyOutputRequest> output;
   SerializeAndDeserialize<mojom::CopyOutputRequest>(input, &output);
 
-  EXPECT_EQ(output->result_format(), result_format);
+  EXPECT_EQ(result_format, output->result_format());
+  EXPECT_TRUE(output->is_scaled());
+  EXPECT_EQ(scale_from, output->scale_from());
+  EXPECT_EQ(scale_to, output->scale_to());
   EXPECT_TRUE(output->has_source());
   EXPECT_EQ(source, output->source());
   EXPECT_TRUE(output->has_area());
   EXPECT_EQ(area, output->area());
 
   SkBitmap bitmap;
-  bitmap.allocN32Pixels(area.width(), area.height());
-  output->SendResult(std::make_unique<CopyOutputSkBitmapResult>(area, bitmap));
+  bitmap.allocN32Pixels(result_rect.width(), result_rect.height());
+  output->SendResult(
+      std::make_unique<CopyOutputSkBitmapResult>(result_rect, bitmap));
   // If the CopyOutputRequest callback is called, this ends. Otherwise, the test
   // will time out and fail.
   run_loop.Run();
@@ -321,10 +333,12 @@
           },
           run_loop_for_result.QuitClosure(), result_rect)));
   input->SetTextureMailbox(texture_mailbox);
+  EXPECT_FALSE(input->is_scaled());
   std::unique_ptr<CopyOutputRequest> output;
   SerializeAndDeserialize<mojom::CopyOutputRequest>(input, &output);
 
   EXPECT_EQ(output->result_format(), result_format);
+  EXPECT_FALSE(output->is_scaled());
   EXPECT_FALSE(output->has_source());
   EXPECT_FALSE(output->has_area());
   EXPECT_TRUE(output->has_texture_mailbox());
diff --git a/services/viz/public/interfaces/compositing/copy_output_request.mojom b/services/viz/public/interfaces/compositing/copy_output_request.mojom
index e8f67d2..f6c1443 100644
--- a/services/viz/public/interfaces/compositing/copy_output_request.mojom
+++ b/services/viz/public/interfaces/compositing/copy_output_request.mojom
@@ -13,6 +13,10 @@
 struct CopyOutputRequest {
   CopyOutputResultFormat result_format;
 
+  // Set both to (1,1) for no scaling. Both must have positive X and Y values.
+  gfx.mojom.Vector2d scale_from;
+  gfx.mojom.Vector2d scale_to;
+
   mojo.common.mojom.UnguessableToken? source;
   gfx.mojom.Rect? area;
 
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 1e81bdd..951e106 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -92,6 +92,34 @@
         "test": "browser_tests"
       },
       {
+        "args": [
+          "--mash",
+          "--override-use-software-gl-for-tests",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/single.mash.browser_tests.filter"
+        ],
+        "name": "single-mash_browser_test",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "hard_timeout": 1800
+        },
+        "test": "browser_tests"
+      },
+      {
+        "args": [
+          "--mus",
+          "--ozone-platform=headless",
+          "--override-use-software-gl-for-tests",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/mus.browser_tests.filter"
+        ],
+        "name": "mus_browser_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "hard_timeout": 1500,
+          "shards": 5
+        },
+        "test": "browser_tests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -262,18 +290,6 @@
         "test": "latency_unittests"
       },
       {
-        "args": [
-          "--override-use-software-gl-for-tests",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/single.mash.browser_tests.filter"
-        ],
-        "name": "single-mash_browser_test",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "hard_timeout": 1800
-        },
-        "test": "mash_browser_tests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -310,19 +326,6 @@
         "test": "midi_unittests"
       },
       {
-        "args": [
-          "--ozone-platform=headless",
-          "--override-use-software-gl-for-tests",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/mus.browser_tests.filter"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "hard_timeout": 1500,
-          "shards": 5
-        },
-        "test": "mus_browser_tests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index bb37a58d..6116aaf 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -3491,6 +3491,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "libfuzzer_tests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_blink_unittests"
       },
       {
@@ -3820,6 +3826,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "libfuzzer_tests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_blink_unittests"
       },
       {
@@ -12695,26 +12707,22 @@
         "test": "ash_unittests"
       },
       {
-        "name": "keyboard_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "keyboard_unittests"
-      },
-      {
         "args": [
+          "--mash",
           "--override-use-software-gl-for-tests",
           "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.browser_tests.filter"
         ],
+        "name": "mash_browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "hard_timeout": 1800,
           "shards": 5
         },
-        "test": "mash_browser_tests"
+        "test": "browser_tests"
       },
       {
         "args": [
+          "--mash",
           "--override-use-software-gl-for-tests",
           "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.single.mash.browser_tests.filter"
         ],
@@ -12723,19 +12731,28 @@
           "can_use_on_swarming_builders": true,
           "hard_timeout": 1800
         },
-        "test": "mash_browser_tests"
+        "test": "browser_tests"
       },
       {
         "args": [
+          "--mus",
           "--override-use-software-gl-for-tests",
           "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.mus.browser_tests.filter"
         ],
+        "name": "mus_browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "hard_timeout": 1500,
           "shards": 5
         },
-        "test": "mus_browser_tests"
+        "test": "browser_tests"
+      },
+      {
+        "name": "keyboard_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "keyboard_unittests"
       },
       {
         "swarming": {
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json
index 1af4ebd..be82ffb 100644
--- a/testing/buildbot/chromium.perf.fyi.json
+++ b/testing/buildbot/chromium.perf.fyi.json
@@ -71,10 +71,16 @@
         "isolate_name": "telemetry_perf_tests_new",
         "name": "benchmarks for bot 1",
         "override_compile_targets": [
-          "telemetry_perf_tests"
+          "telemetry_perf_tests_new"
         ],
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "id": "swarm823-c4",
+              "pool": "Chrome-perf-fyi"
+            }
+          ],
           "expiration": 36000,
           "hard_timeout": 10800,
           "ignore_task_failure": false,
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index 99d8495b..35ccc1d 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -29834,6 +29834,11 @@
       "microdump_stackwalk"
     ]
   },
+  "Linux Builder": {
+    "additional_compile_targets": [
+      "telemetry_perf_tests_new"
+    ]
+  },
   "Linux Perf": {
     "isolated_scripts": [
       {
diff --git a/testing/buildbot/filters/ash_unittests_mash.filter b/testing/buildbot/filters/ash_unittests_mash.filter
index 2f599ed7..98ac5d9 100644
--- a/testing/buildbot/filters/ash_unittests_mash.filter
+++ b/testing/buildbot/filters/ash_unittests_mash.filter
@@ -283,6 +283,9 @@
 -SystemGestureEventFilterTest.WindowsWithMaxSizeDontSnap
 -ToastManagerTest.NullMessageHasNoDismissButton
 -ToplevelWindowEventHandlerTest.GestureDragCaptureLoss
+-TouchCalibratorControllerTest.CustomCalibration
+-TouchCalibratorControllerTest.CustomCalibrationInvalidTouchId
+-TouchCalibratorControllerTest.TouchDeviceIdIsSet
 -TouchHudDebugTest.DualDisplays
 -TouchHudDebugTest.Headless
 -TouchHudDebugTest.MirrorDisplays
@@ -331,10 +334,6 @@
 -WindowTreeHostManagerTest.UpdateMouseLocationAfterDisplayChange_PrimaryDisconnected
 -WindowTreeHostManagerTest.UpdateMouseLocationAfterDisplayChange_SwapPrimary
 -WindowTreeHostManagerTest.UpdateMouseocationfterisplayChange
-# TODO: fix this. It fails because a container used in the test has more
-# children in mash.
-# http://crbug.com/764577.
--WorkspaceLayoutManagerBackdropTest.BackdropForSplitScreenTest
 -WorkspaceLayoutManagerKeyboardTest2.ChangeWorkAreaInNonStickyMode
 -WorkspaceLayoutManagerKeyboardTest2.IgnoreWorkAreaChangeinNonStickyMode
 # TODO: fix these. They fail because DeviceDataManager isn't created.
diff --git a/testing/buildbot/filters/ash_unittests_mus.filter b/testing/buildbot/filters/ash_unittests_mus.filter
index 957afcd..97fcb0b 100644
--- a/testing/buildbot/filters/ash_unittests_mus.filter
+++ b/testing/buildbot/filters/ash_unittests_mus.filter
@@ -1,5 +1,8 @@
 # TODO: fix these. They fail because DeviceDataManager isn't created.
 # http://crbug.com/734812.
+-TouchCalibratorControllerTest.CustomCalibration
+-TouchCalibratorControllerTest.CustomCalibrationInvalidTouchId
+-TouchCalibratorControllerTest.TouchDeviceIdIsSet
 -TrayIMETest.HidesOnA11yEnabled
 -TrayIMETest.PerformActionOnDetailedView
 -VirtualKeyboardControllerAlwaysEnabledTest.DoesNotSuppressKeyboard
diff --git a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
index 794ee03..34233e6 100644
--- a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
+++ b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
@@ -65,6 +65,9 @@
 -DownloadContentTest.StrongValidators
 -DragDownloadFileTest.DragDownloadFileTest_Complete
 
+# http://crbug.com/769993
+-DownloadContentTest.FetchErrorResponseBodyResumption
+
 # http://crbug.com/721398
 -ClearSiteDataThrottleBrowserTest.CookiesIntegrationTest
 -ClearSiteDataThrottleBrowserTest.Credentials
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index 6eb57510..5d6e218b 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -666,6 +666,10 @@
     "label": "//components/leveldb:leveldb_service_unittests",
     "type": "console_test_launcher",
   },
+  "libfuzzer_tests": {
+    "label": "//testing/libfuzzer/tests:libfuzzer_tests",
+    "type": "console_test_launcher",
+  },
   "libjingle_xmpp_unittests": {
     "label": "//third_party/libjingle_xmpp:libjingle_xmpp_unittests",
     "type": "console_test_launcher",
@@ -678,15 +682,6 @@
     "label": "//mash:all",
     "type": "additional_compile_target",
   },
-  "mash_browser_tests": {
-    "label": "//chrome/test:mash_browser_tests",
-    "label_type": "group",
-    "type": "windowed_test_launcher",
-    "executable": "browser_tests",
-    "args": [
-      "--run-in-mash",
-    ],
-  },
   "media_unittests": {
     "label": "//media:media_unittests",
     "type": "windowed_test_launcher",
@@ -763,16 +758,6 @@
     "label": "//chrome/android:monochrome_static_initializers",
     "type": "additional_compile_target",
   },
-  "mus_browser_tests": {
-    "label": "//chrome/test:mus_browser_tests",
-    "label_type": "group",
-    "type": "windowed_test_launcher",
-    "executable": "browser_tests",
-    "args": [
-      "--mus",
-      "--service-overrides=../../chrome/app/mash/mash_service_overrides.json",
-    ],
-  },
   "message_center_unittests": {
     "label": "//ui/message_center:message_center_unittests",
     "type": "windowed_test_launcher",
@@ -903,6 +888,10 @@
     "label": "//chrome/test:sync_integration_tests",
     "type": "windowed_test_launcher",
   },
+  "system_webview_apk": {
+    "label": "//android_webview:system_webview_apk",
+    "type": "additional_compile_target",
+  },
   "system_webview_shell_layout_test_apk": {
     "label": "//android_webview/tools/system_webview_shell:system_webview_shell_layout_test_apk",
     "type": "console_test_launcher",
diff --git a/testing/buildbot/manage.py b/testing/buildbot/manage.py
index 7ad2647..e14fcad 100755
--- a/testing/buildbot/manage.py
+++ b/testing/buildbot/manage.py
@@ -130,6 +130,7 @@
   'net_junit_tests',
   'net_junit_tests',
   'service_junit_tests',
+  'system_webview_apk',
   'ui_junit_tests',
   'vrcore_fps_test',
   'vr_perf_tests',
diff --git a/testing/scripts/run_multiple_telemetry_benchmarks_as_googletest.py b/testing/scripts/run_multiple_telemetry_benchmarks_as_googletest.py
index 151f85d..8a6b562 100755
--- a/testing/scripts/run_multiple_telemetry_benchmarks_as_googletest.py
+++ b/testing/scripts/run_multiple_telemetry_benchmarks_as_googletest.py
@@ -100,9 +100,7 @@
 # This is not really a "script test" so does not need to manually add
 # any additional compile targets.
 def main_compile_targets(args):
-  # Force compilation of the new isolate. Will change to telemetry_perf_tests
-  # once we switch the main isolate over to running this file.
-  json.dump(['telemetry_perf_tests_new'], args.output)
+  json.dump([], args.output)
 
 
 if __name__ == '__main__':
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 1f58705..d4ad026 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -231,18 +231,6 @@
             ]
         }
     ],
-    "AsyncDNS": [
-        {
-            "platforms": [
-                "linux"
-            ],
-            "experiments": [
-                {
-                    "name": "AsyncDNSA"
-                }
-            ]
-        }
-    ],
     "AsyncDns": [
         {
             "platforms": [
@@ -250,13 +238,10 @@
             ],
             "experiments": [
                 {
-                    "name": "AsyncDnsA"
-                },
-                {
-                    "name": "SystemDnsA"
-                },
-                {
-                    "name": "AsyncDnsNoFallbackA"
+                    "name": "Enabled",
+                    "enable_features": [
+                        "AsyncDns"
+                    ]
                 }
             ]
         }
@@ -1768,7 +1753,6 @@
                         "NTPCondensedTileLayout"
                     ],
                     "disable_features": [
-                        "ContentSuggestionsShowSummary",
                         "NTPShowGoogleGInOmnibox"
                     ]
                 }
@@ -1854,22 +1838,6 @@
             ]
         }
     ],
-    "NTPUseDdljsonApi": [
-        {
-            "platforms": [
-                "android",
-                "ios"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "UseDdljsonApi"
-                    ]
-                }
-            ]
-        }
-    ],
     "NetAdaptiveProxyConnectionTimeout": [
         {
             "platforms": [
@@ -2798,6 +2766,41 @@
             ]
         }
     ],
+    "SafeBrowsingAdSamplerPerformance": [
+        {
+            "platforms": [
+                "android",
+                "linux",
+                "mac",
+                "win"
+            ],
+            "experiments": [
+                {
+                    "name": "AllAdSamples_NoReportsSent",
+                    "params": {
+                        "safe_browsing_ad_sampler_frequency_denominator": "1",
+                        "trigger_type_and_quota_csv": "2,10000"
+                    },
+                    "enable_features": [
+                        "SafeBrowsingAdSamplerCollectButDontSend",
+                        "SafeBrowsingAdSamplerTrigger",
+                        "SafeBrowsingTriggerThrottlerDailyQuota"
+                    ]
+                },
+                {
+                    "name": "Control",
+                    "disable_features": [
+                        "SafeBrowsingAdSamplerCollectButDontSend",
+                        "SafeBrowsingAdSamplerTrigger",
+                        "SafeBrowsingTriggerThrottlerDailyQuota"
+                    ]
+                },
+                {
+                    "name": "Default"
+                }
+            ]
+        }
+    ],
     "SafeBrowsingAndroid": [
         {
             "platforms": [
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index 145cef34..2d9b95e3 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -32,7 +32,6 @@
 crbug.com/591099 fast/text/word-space.html [ Failure ]
 
 # Glyph overflow.
-crbug.com/591099 fast/text/letter-spacing-negative-opacity.html [ Failure Pass ]
 crbug.com/591099 fast/text/shadow-no-blur.html [ Failure ]
 
 # Improved shaping we can rebase once we switch.
@@ -71,10 +70,14 @@
 crbug.com/724697 overflow/overflow-basic-002.html [ Pass ]
 
 # New failures are appended below by the script.
+crbug.com/591099 accessibility/aom-relation-list-properties.html [ Failure Pass ]
 crbug.com/591099 accessibility/aria-activedescendant.html [ Crash Failure ]
 crbug.com/591099 accessibility/aria-describedby-on-input.html [ Crash Failure ]
 crbug.com/591099 accessibility/aria-disabled.html [ Failure ]
 crbug.com/591099 accessibility/aria-labelledby-on-input.html [ Crash Failure ]
+crbug.com/591099 accessibility/aria-labelledby-stay-within.html [ Failure Pass ]
+crbug.com/591099 accessibility/aria-owns.html [ Failure Pass ]
+crbug.com/591099 accessibility/aria-tab-roles.html [ Failure Pass ]
 crbug.com/591099 accessibility/canvas-accessibilitynodeobject.html [ Failure ]
 crbug.com/591099 accessibility/canvas-fallback-content-2.html [ Crash Timeout ]
 crbug.com/591099 accessibility/canvas-fallback-content.html [ Failure ]
@@ -88,6 +91,7 @@
 crbug.com/591099 accessibility/element-role-mapping-focusable.html [ Crash Failure ]
 crbug.com/591099 accessibility/element-role-mapping-normal.html [ Crash Failure Timeout ]
 crbug.com/591099 accessibility/ellipsis-text.html [ Failure ]
+crbug.com/591099 accessibility/focusable-div.html [ Failure Pass ]
 crbug.com/591099 accessibility/image-link-inline-cont.html [ Failure ]
 crbug.com/591099 accessibility/image-map1.html [ Failure ]
 crbug.com/591099 accessibility/img-fallsback-to-title.html [ Crash Failure ]
@@ -100,12 +104,15 @@
 crbug.com/591099 accessibility/inline-text-word-boundaries.html [ Failure ]
 crbug.com/591099 accessibility/input-type-password-value-and-selection.html [ Crash Failure Pass Timeout ]
 crbug.com/591099 accessibility/input-type-range-aria-value.html [ Failure ]
+crbug.com/591099 accessibility/listitem-presentation-inherited.html [ Failure Pass ]
 crbug.com/591099 accessibility/misspellings.html [ Timeout ]
+crbug.com/591099 accessibility/name-calc-aria-owns.html [ Failure Pass ]
 crbug.com/591099 accessibility/name-calc-img.html [ Crash Failure ]
 crbug.com/591099 accessibility/presentation-owned-elements.html [ Crash Failure ]
 crbug.com/591099 accessibility/radio-button-title-label.html [ Failure ]
 crbug.com/591099 accessibility/readonly.html [ Crash Failure ]
 crbug.com/591099 accessibility/removed-continuation-element-causes-crash.html [ Crash Failure ]
+crbug.com/591099 accessibility/role-attribute.html [ Failure Pass ]
 crbug.com/591099 accessibility/scroll-div-horiz-sends-notification.html [ Failure Timeout ]
 crbug.com/591099 accessibility/set-selection-whitespace.html [ Failure ]
 crbug.com/591099 accessibility/slider-thumb-bounds.html [ Failure ]
@@ -117,6 +124,7 @@
 crbug.com/591099 animations/3d/change-transform-in-end-event.html [ Failure Pass ]
 crbug.com/591099 animations/3d/state-at-end-event-transform.html [ Failure Pass ]
 crbug.com/591099 animations/animations-parsing.html [ Timeout ]
+crbug.com/591099 animations/cross-fade-list-style-image.html [ Failure Pass ]
 crbug.com/591099 animations/display-inline-style-adjust.html [ Failure ]
 crbug.com/591099 animations/interpolation/backdrop-filter-interpolation.html [ Crash Timeout ]
 crbug.com/591099 animations/interpolation/background-image-interpolation.html [ Crash Pass Timeout ]
@@ -620,8 +628,9 @@
 crbug.com/591099 css2.1/20110323/margin-applies-to-015.htm [ Failure Pass ]
 crbug.com/591099 css2.1/20110323/margin-collapse-012.htm [ Failure ]
 crbug.com/591099 css2.1/20110323/outline-color-applies-to-008.htm [ Failure ]
-crbug.com/591099 css2.1/20110323/outline-color-applies-to-010.htm [ Failure ]
+crbug.com/591099 css2.1/20110323/outline-color-applies-to-010.htm [ Failure Pass ]
 crbug.com/591099 css2.1/20110323/outline-color-applies-to-014.htm [ Failure Pass ]
+crbug.com/591099 css2.1/20110323/overflow-applies-to-010.htm [ Failure Pass ]
 crbug.com/591099 css2.1/20110323/table-caption-001.htm [ Failure Pass ]
 crbug.com/591099 css2.1/20110323/table-caption-002.htm [ Crash Failure Pass ]
 crbug.com/591099 css2.1/20110323/table-caption-horizontal-alignment-001.htm [ Failure Pass ]
@@ -1192,7 +1201,7 @@
 crbug.com/591099 css3/filters/regions-expanding.html [ Crash Failure ]
 crbug.com/591099 css3/filters/remove-filter-rendering.html [ Failure ]
 crbug.com/591099 css3/filters/simple-filter-rendering.html [ Failure ]
-crbug.com/591099 css3/flexbox/bug527039.html [ Failure ]
+crbug.com/591099 css3/flexbox/bug527039.html [ Failure Pass ]
 crbug.com/591099 css3/flexbox/button.html [ Failure ]
 crbug.com/591099 css3/flexbox/child-overflow.html [ Failure Pass ]
 crbug.com/591099 css3/flexbox/flex-align-vertical-writing-mode.html [ Failure Pass ]
@@ -2016,6 +2025,7 @@
 crbug.com/591099 editing/deleting/5369009.html [ Failure ]
 crbug.com/591099 editing/deleting/5433862-2.html [ Failure ]
 crbug.com/591099 editing/deleting/5483370.html [ Failure ]
+crbug.com/591099 editing/deleting/backspace-merge-into-list-item.html [ Failure Pass ]
 crbug.com/591099 editing/deleting/delete-3608430-fix.html [ Crash Failure ]
 crbug.com/591099 editing/deleting/delete-3865854-fix.html [ Failure ]
 crbug.com/591099 editing/deleting/delete-at-paragraph-boundaries-011.html [ Failure ]
@@ -2023,6 +2033,7 @@
 crbug.com/591099 editing/deleting/delete-br-013.html [ Failure ]
 crbug.com/591099 editing/deleting/delete-contiguous-ws-001.html [ Crash Failure ]
 crbug.com/591099 editing/deleting/delete-empty-table.html [ Failure ]
+crbug.com/591099 editing/deleting/delete-first-list-item.html [ Failure Pass ]
 crbug.com/591099 editing/deleting/delete-leading-ws-001.html [ Failure ]
 crbug.com/591099 editing/deleting/delete-line-001.html [ Failure ]
 crbug.com/591099 editing/deleting/delete-line-002.html [ Failure ]
@@ -2048,6 +2059,7 @@
 crbug.com/591099 editing/deleting/delete_ws_fixup.html [ Crash Failure ]
 crbug.com/591099 editing/deleting/merge-different-styles.html [ Failure ]
 crbug.com/591099 editing/deleting/merge-endOfParagraph.html [ Failure ]
+crbug.com/591099 editing/deleting/merge-lists.html [ Failure Pass ]
 crbug.com/591099 editing/deleting/merge-no-br.html [ Failure ]
 crbug.com/591099 editing/deleting/merge-paragraph-from-address.html [ Failure ]
 crbug.com/591099 editing/deleting/merge-paragraph-from-listing.html [ Failure ]
@@ -2076,6 +2088,8 @@
 crbug.com/591099 editing/execCommand/align-in-span.html [ Failure ]
 crbug.com/591099 editing/execCommand/arguments-combinations.html [ Failure ]
 crbug.com/591099 editing/execCommand/backcolor-crash.html [ Crash Failure ]
+crbug.com/591099 editing/execCommand/break-out-of-empty-list-item.html [ Failure Pass ]
+crbug.com/591099 editing/execCommand/crash-line-break-after-outdent.html [ Failure Pass ]
 crbug.com/591099 editing/execCommand/default-paragraph-separator.html [ Failure ]
 crbug.com/591099 editing/execCommand/delete-selection-has-style.html [ Failure ]
 crbug.com/591099 editing/execCommand/enabling-and-selection-2.html [ Failure Pass Timeout ]
@@ -2090,6 +2104,7 @@
 crbug.com/591099 editing/execCommand/forward-delete-no-scroll.html [ Failure ]
 crbug.com/591099 editing/execCommand/indent-empty-root.html [ Failure ]
 crbug.com/591099 editing/execCommand/insert-image-on-top-of-directional-text.html [ Failure ]
+crbug.com/591099 editing/execCommand/insert-list-and-strikethrough.html [ Failure Pass ]
 crbug.com/591099 editing/execCommand/insertHTML.html [ Failure ]
 crbug.com/591099 editing/execCommand/insertImage-src.html [ Failure ]
 crbug.com/591099 editing/execCommand/insertImage.html [ Failure ]
@@ -2109,7 +2124,9 @@
 crbug.com/591099 editing/execCommand/remove-format-background-color.html [ Failure ]
 crbug.com/591099 editing/execCommand/remove-list-from-range-selection.html [ Crash Failure ]
 crbug.com/591099 editing/execCommand/remove_format_and_extract_contents.html [ Failure ]
+crbug.com/591099 editing/execCommand/replaceSelectorCommand-crash.html [ Failure Pass ]
 crbug.com/591099 editing/execCommand/selection-after-insert-list.html [ Crash Failure ]
+crbug.com/591099 editing/execCommand/switch-multiple-list-items-crash.html [ Failure Pass ]
 crbug.com/591099 editing/execCommand/toggle-compound-styles.html [ Crash Timeout ]
 crbug.com/591099 editing/input/caret-at-the-edge-of-contenteditable.html [ Failure ]
 crbug.com/591099 editing/input/caret-at-the-edge-of-input.html [ Crash Failure ]
@@ -2136,6 +2153,7 @@
 crbug.com/591099 editing/inserting/5685601-3.html [ Failure ]
 crbug.com/591099 editing/inserting/6703873.html [ Failure ]
 crbug.com/591099 editing/inserting/break-blockquote-after-delete.html [ Failure ]
+crbug.com/591099 editing/inserting/break-out-of-nested-lists.html [ Failure Pass ]
 crbug.com/591099 editing/inserting/caret-position.html [ Crash Failure ]
 crbug.com/591099 editing/inserting/editable-inline-element.html [ Failure ]
 crbug.com/591099 editing/inserting/edited-whitespace-1.html [ Failure ]
@@ -2190,9 +2208,11 @@
 crbug.com/591099 editing/pasteboard/5780697-2.html [ Failure ]
 crbug.com/591099 editing/pasteboard/6018653.html [ Failure ]
 crbug.com/591099 editing/pasteboard/7955.html [ Failure ]
+crbug.com/591099 editing/pasteboard/avoid-copying-body-with-background.html [ Failure Pass ]
 crbug.com/591099 editing/pasteboard/bad-placeholder.html [ Failure ]
 crbug.com/591099 editing/pasteboard/block-wrappers-necessary.html [ Failure ]
 crbug.com/591099 editing/pasteboard/copy-backslash-with-euc.html [ Crash Failure ]
+crbug.com/591099 editing/pasteboard/copy-crash.html [ Failure Pass ]
 crbug.com/591099 editing/pasteboard/copy-element-with-conflicting-background-color-from-rule.html [ Failure ]
 crbug.com/591099 editing/pasteboard/copy-image-with-alt-text.html [ Crash Failure ]
 crbug.com/591099 editing/pasteboard/copy-in-password-field.html [ Crash Failure ]
@@ -2207,7 +2227,7 @@
 crbug.com/591099 editing/pasteboard/drag-and-drop-inputimage-contenteditable.html [ Timeout ]
 crbug.com/591099 editing/pasteboard/drag-and-drop-objectimage-contenteditable.html [ Timeout ]
 crbug.com/591099 editing/pasteboard/drag-drop-dead-frame.html [ Timeout ]
-crbug.com/591099 editing/pasteboard/drag-drop-list.html [ Failure ]
+crbug.com/591099 editing/pasteboard/drag-drop-list.html [ Failure Pass ]
 crbug.com/591099 editing/pasteboard/drag-drop-modifies-page.html [ Failure ]
 crbug.com/591099 editing/pasteboard/drag-drop-url-text.html [ Crash Failure ]
 crbug.com/591099 editing/pasteboard/drag-drop-url-with-style.html [ Failure ]
@@ -2227,6 +2247,7 @@
 crbug.com/591099 editing/pasteboard/merge-start-list.html [ Failure ]
 crbug.com/591099 editing/pasteboard/mixed_editability.html [ Crash Failure ]
 crbug.com/591099 editing/pasteboard/onpaste-text-html.html [ Failure ]
+crbug.com/591099 editing/pasteboard/paste-4039777-fix.html [ Failure Pass ]
 crbug.com/591099 editing/pasteboard/paste-after-inline-style-element.html [ Failure ]
 crbug.com/591099 editing/pasteboard/paste-and-sanitize.html [ Failure ]
 crbug.com/591099 editing/pasteboard/paste-blockquote-1.html [ Failure ]
@@ -2242,6 +2263,9 @@
 crbug.com/591099 editing/pasteboard/paste-line-endings-003.html [ Failure ]
 crbug.com/591099 editing/pasteboard/paste-line-endings-004.html [ Failure ]
 crbug.com/591099 editing/pasteboard/paste-line-endings-005.html [ Failure ]
+crbug.com/591099 editing/pasteboard/paste-list-001.html [ Failure Pass ]
+crbug.com/591099 editing/pasteboard/paste-list-002.html [ Failure Pass ]
+crbug.com/591099 editing/pasteboard/paste-list-004.html [ Failure Pass ]
 crbug.com/591099 editing/pasteboard/paste-noplugin.html [ Failure ]
 crbug.com/591099 editing/pasteboard/paste-noscript-svg.html [ Crash Failure ]
 crbug.com/591099 editing/pasteboard/paste-noscript.html [ Crash Failure ]
@@ -2942,9 +2966,9 @@
 crbug.com/591099 external/wpt/css/css-writing-modes-3/abs-pos-non-replaced-vrl-222.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes-3/abs-pos-non-replaced-vrl-226.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes-3/abs-pos-non-replaced-vrl-228.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-writing-modes-3/block-flow-direction-vlr-022.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes-3/block-flow-direction-vlr-022.xht [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes-3/block-flow-direction-vrl-012.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-writing-modes-3/block-flow-direction-vrl-021.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes-3/block-flow-direction-vrl-021.xht [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes-3/block-flow-direction-vrl-024.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes-3/block-flow-direction-vrl-026.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes-3/central-baseline-alignment-002.xht [ Failure ]
@@ -2973,7 +2997,7 @@
 crbug.com/591099 external/wpt/css/css-writing-modes-3/inline-replaced-vrl-004.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes-3/inline-table-alignment-002.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes-3/inline-table-alignment-004.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-writing-modes-3/line-box-direction-vlr-020.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes-3/line-box-direction-vlr-020.xht [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes-3/line-box-direction-vrl-002.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes-3/line-box-direction-vrl-005.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes-3/line-box-direction-vrl-006.xht [ Failure ]
@@ -3211,6 +3235,7 @@
 crbug.com/591099 external/wpt/html-media-capture/capture_video_cancel-manual.html [ Crash Failure ]
 crbug.com/591099 external/wpt/html/browsers/windows/noreferrer-window-name.html [ Crash Timeout ]
 crbug.com/591099 external/wpt/html/dom/documents/dom-tree-accessors/Document.currentScript.html [ Pass ]
+crbug.com/591099 external/wpt/html/dom/interfaces.html [ Pass Timeout ]
 crbug.com/591099 external/wpt/html/infrastructure/urls/resolving-urls/query-encoding/utf-16be.html [ Crash Timeout ]
 crbug.com/591099 external/wpt/html/infrastructure/urls/resolving-urls/query-encoding/utf-16le.html [ Crash Timeout ]
 crbug.com/591099 external/wpt/html/infrastructure/urls/resolving-urls/query-encoding/utf-8.html [ Crash Timeout ]
@@ -3229,8 +3254,19 @@
 crbug.com/591099 external/wpt/html/semantics/embedded-content/the-img-element/usemap-casing.html [ Failure ]
 crbug.com/591099 external/wpt/html/semantics/embedded-content/the-object-element/usemap-casing.html [ Failure ]
 crbug.com/591099 external/wpt/html/semantics/forms/the-input-element/type-change-state.html [ Pass Timeout ]
+crbug.com/591099 external/wpt/html/semantics/grouping-content/the-li-element/grouping-li-reftest-002.html [ Failure Pass ]
 crbug.com/591099 external/wpt/html/semantics/grouping-content/the-li-element/grouping-li-reftest-list-owner-menu.html [ Crash Failure ]
 crbug.com/591099 external/wpt/html/semantics/grouping-content/the-li-element/grouping-li-reftest-list-owner-skip-no-boxes.html [ Crash Failure ]
+crbug.com/591099 external/wpt/html/semantics/grouping-content/the-ol-element/grouping-ol-rev-reftest-001.html [ Failure Pass ]
+crbug.com/591099 external/wpt/html/semantics/grouping-content/the-ol-element/grouping-ol-start-reftest-001.html [ Failure Pass ]
+crbug.com/591099 external/wpt/html/semantics/grouping-content/the-ol-element/grouping-ol-start-reftest-002.html [ Failure Pass ]
+crbug.com/591099 external/wpt/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-001.html [ Failure Pass ]
+crbug.com/591099 external/wpt/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-002.html [ Failure Pass ]
+crbug.com/591099 external/wpt/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-003.html [ Failure Pass ]
+crbug.com/591099 external/wpt/html/semantics/grouping-content/the-ol-element/reversed-1a.html [ Failure Pass ]
+crbug.com/591099 external/wpt/html/semantics/grouping-content/the-ol-element/reversed-1c.html [ Failure Pass ]
+crbug.com/591099 external/wpt/html/semantics/grouping-content/the-ol-element/reversed-1d.html [ Failure Pass ]
+crbug.com/591099 external/wpt/html/semantics/grouping-content/the-ol-element/reversed-1e.html [ Failure Pass ]
 crbug.com/591099 external/wpt/html/semantics/interactive-elements/the-dialog-element/centering.html [ Failure ]
 crbug.com/591099 external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-showModal.html [ Failure ]
 crbug.com/591099 external/wpt/html/semantics/text-level-semantics/the-br-element/br-bidi-in-inline-ancestors.html [ Failure ]
@@ -3260,7 +3296,7 @@
 crbug.com/591099 external/wpt/payment-request/payment-disabled-by-feature-policy.https.sub.html [ Pass ]
 crbug.com/591099 external/wpt/performance-timeline/po-callback-mutate.any.html [ Pass ]
 crbug.com/591099 external/wpt/performance-timeline/po-callback-mutate.any.worker.html [ Pass ]
-crbug.com/591099 external/wpt/pointerevents/compat/pointerevent_touch-action_two-finger_interaction-manual.html [ Timeout ]
+crbug.com/591099 external/wpt/pointerevents/compat/pointerevent_touch-action_two-finger_interaction-manual.html [ Pass Timeout ]
 crbug.com/591099 external/wpt/pointerevents/pointerevent_attributes_hoverable_pointers-manual.html [ Crash Pass Timeout ]
 crbug.com/591099 external/wpt/pointerevents/pointerevent_attributes_nohover_pointers-manual.html [ Crash Pass Timeout ]
 crbug.com/591099 external/wpt/pointerevents/pointerevent_click_during_capture-manual.html [ Crash Timeout ]
@@ -3405,6 +3441,7 @@
 crbug.com/591099 fast/block/basic/020.html [ Failure ]
 crbug.com/591099 fast/block/basic/quirk-height.html [ Failure ]
 crbug.com/591099 fast/block/basic/quirk-percent-height-grandchild.html [ Failure ]
+crbug.com/591099 fast/block/block-add-child-crash.html [ Failure Pass ]
 crbug.com/591099 fast/block/block-width-recalc-with-relative-height.html [ Crash Failure ]
 crbug.com/591099 fast/block/float-avoids-padding-inline-ancestors.html [ Failure ]
 crbug.com/591099 fast/block/float/002.html [ Crash Failure ]
@@ -3436,7 +3473,7 @@
 crbug.com/591099 fast/block/float/float-in-float-hit-testing.html [ Failure ]
 crbug.com/591099 fast/block/float/float-in-float-painting.html [ Failure ]
 crbug.com/591099 fast/block/float/float-inserted-into-clean-line.html [ Failure ]
-crbug.com/635619 fast/block/float/float-not-removed-from-first-letter.html [ Crash Failure ]
+crbug.com/635619 fast/block/float/float-not-removed-from-first-letter.html [ Crash Failure Pass ]
 crbug.com/591099 fast/block/float/float-overflow-hidden-containing-block-width.html [ Failure ]
 crbug.com/591099 fast/block/float/floats-and-text-indent-rl.html [ Failure ]
 crbug.com/591099 fast/block/float/floats-and-text-indent.html [ Failure ]
@@ -3521,6 +3558,7 @@
 crbug.com/591099 fast/block/positioning/auto/vertical-rl/006.html [ Failure ]
 crbug.com/591099 fast/block/positioning/auto/vertical-rl/007.html [ Failure ]
 crbug.com/591099 fast/block/positioning/child-of-absolute-with-auto-height.html [ Failure ]
+crbug.com/591099 fast/block/positioning/complex-percentage-height.html [ Failure Pass ]
 crbug.com/591099 fast/block/positioning/fixed-positioning-scrollbar-bug.html [ Failure ]
 crbug.com/591099 fast/block/positioning/hiding-inside-relpositioned-inline.html [ Failure ]
 crbug.com/591099 fast/block/positioning/hittest-on-relative-positioned-children.html [ Failure ]
@@ -3613,6 +3651,7 @@
 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-color-visited.html [ Failure Pass ]
 crbug.com/591099 fast/borders/border-image-border-radius.html [ Failure Pass ]
 crbug.com/591099 fast/borders/border-radius-mask-canvas-all.html [ Crash Failure ]
 crbug.com/591099 fast/borders/border-radius-mask-canvas-border.html [ Failure ]
@@ -4046,7 +4085,6 @@
 crbug.com/591099 fast/css/outline-auto-empty-rects.html [ Failure ]
 crbug.com/591099 fast/css/outline-auto-location.html [ Failure ]
 crbug.com/591099 fast/css/outline-narrowLine.html [ Failure ]
-crbug.com/591099 fast/css/outline-small-visual-overflow.html [ Failure Pass ]
 crbug.com/591099 fast/css/overflow-rtl-border-after.html [ Failure ]
 crbug.com/591099 fast/css/pending-stylesheet-repaint.html [ Failure ]
 crbug.com/591099 fast/css/pendingStylesheetFontSize.html [ Failure ]
@@ -4240,6 +4278,7 @@
 crbug.com/591099 fast/dom/insertedIntoDocument-child.html [ Crash Failure ]
 crbug.com/591099 fast/dom/insertedIntoDocument-no-crash.html [ Failure ]
 crbug.com/591099 fast/dom/insertedIntoDocument-sibling.html [ Crash Failure ]
+crbug.com/591099 fast/dom/left-overflow-in-ltr.html [ Failure Pass ]
 crbug.com/591099 fast/dom/nodesFromRect/nodesFromRect-basic.html [ Failure ]
 crbug.com/591099 fast/dom/nodesFromRect/nodesFromRect-child-frame-scrolled-content.html [ Failure ]
 crbug.com/591099 fast/dom/nodesFromRect/nodesFromRect-culled-inlines-between-silblings.html [ Failure ]
@@ -4250,11 +4289,15 @@
 crbug.com/591099 fast/dom/open-and-close-by-DOM.html [ Failure ]
 crbug.com/591099 fast/dom/outerText.html [ Failure ]
 crbug.com/591099 fast/dom/replaced-image-map.html [ Failure ]
+crbug.com/591099 fast/dom/right-overflow-in-rtl.html [ Failure Pass ]
 crbug.com/591099 fast/dom/row-inner-text.html [ Failure ]
 crbug.com/591099 fast/dom/rtl-scroll-to-leftmost-and-resize.html [ Failure ]
 crbug.com/591099 fast/dom/scroll-reveal-left-overflow.html [ Failure ]
 crbug.com/591099 fast/dom/scroll-reveal-top-overflow.html [ Failure ]
+crbug.com/591099 fast/dom/set-outer-html.html [ Failure Pass ]
+crbug.com/591099 fast/dom/set-outer-text.html [ Failure Pass ]
 crbug.com/591099 fast/dom/shadow/content-child-whitespace-between-span.html [ Failure ]
+crbug.com/591099 fast/dom/shadow/ol-with-distribution-recalc-crash.html [ Failure Pass ]
 crbug.com/591099 fast/dom/shadow/querySelector-for-useragent-shadowroot.html [ Crash Failure ]
 crbug.com/591099 fast/dom/shadow/selection-in-nested-shadow.html [ Crash Failure ]
 crbug.com/591099 fast/dom/shadow/selections-in-shadow.html [ Timeout ]
@@ -4324,6 +4367,7 @@
 crbug.com/591099 fast/encoding/invalid-UTF-8.html [ Failure ]
 crbug.com/591099 fast/encoding/latin1-unencodables.html [ Crash Failure ]
 crbug.com/591099 fast/encoding/namespace-tolerance.html [ Failure Pass ]
+crbug.com/591099 fast/encoding/preload-encoding.html [ Failure Pass ]
 crbug.com/591099 fast/encoding/utf-16-big-endian.html [ Crash Failure ]
 crbug.com/591099 fast/encoding/utf-16-little-endian.html [ Crash Failure ]
 crbug.com/591099 fast/encoding/x-user-defined-unencodables.html [ Crash Failure ]
@@ -4362,7 +4406,7 @@
 crbug.com/591099 fast/events/frame-detached-in-mousedown.html [ Timeout ]
 crbug.com/591099 fast/events/frame-programmatic-focus.html [ Failure ]
 crbug.com/591099 fast/events/frame-scroll-fake-mouse-move.html [ Failure ]
-crbug.com/591099 fast/events/frame-tab-focus.html [ Failure Timeout ]
+crbug.com/591099 fast/events/frame-tab-focus.html [ Crash Failure Timeout ]
 crbug.com/591099 fast/events/hit-test-counts.html [ Failure ]
 crbug.com/591099 fast/events/iframe-mousewheel.html [ Failure ]
 crbug.com/591099 fast/events/iframe-onmousemove.html [ Timeout ]
@@ -4394,6 +4438,7 @@
 crbug.com/591099 fast/events/no-blur-on-enter-button.html [ Failure ]
 crbug.com/591099 fast/events/onblur-remove.html [ Crash Failure ]
 crbug.com/591099 fast/events/onchange-range-slider.html [ Failure ]
+crbug.com/591099 fast/events/onclick-list-marker.html [ Failure Pass ]
 crbug.com/591099 fast/events/onload-re-entry.html [ Failure ]
 crbug.com/591099 fast/events/onload-webkit-before-webcore.html [ Failure ]
 crbug.com/591099 fast/events/page-scaled-mouse-click-iframe.html [ Failure ]
@@ -4533,6 +4578,7 @@
 crbug.com/591099 fast/forms/input-align.html [ Crash Failure ]
 crbug.com/591099 fast/forms/input-appearance-height.html [ Crash Failure ]
 crbug.com/591099 fast/forms/input-button-sizes.html [ Failure ]
+crbug.com/591099 fast/forms/input-common/duplicate-names.html [ Failure Pass ]
 crbug.com/591099 fast/forms/input-common/reset-checked.html [ Failure ]
 crbug.com/591099 fast/forms/input-first-letter.html [ Failure ]
 crbug.com/591099 fast/forms/input-multiple.html [ Crash Failure ]
@@ -4701,35 +4747,35 @@
 crbug.com/591099 fast/forms/submit-add-remove-element.html [ Crash Failure ]
 crbug.com/591099 fast/forms/submit-onFocus-invalidForm.html [ Crash Failure ]
 crbug.com/591099 fast/forms/submit/submit-appearance-basic.html [ Failure ]
-crbug.com/591099 fast/forms/suggestion-picker/date-suggestion-picker-appearance-rtl.html [ Failure ]
-crbug.com/591099 fast/forms/suggestion-picker/date-suggestion-picker-appearance-with-scroll-bar.html [ Failure ]
+crbug.com/591099 fast/forms/suggestion-picker/date-suggestion-picker-appearance-rtl.html [ Failure Pass ]
+crbug.com/591099 fast/forms/suggestion-picker/date-suggestion-picker-appearance-with-scroll-bar.html [ Failure Pass ]
 crbug.com/591099 fast/forms/suggestion-picker/date-suggestion-picker-appearance-zoom125.html [ Crash Failure Timeout ]
 crbug.com/591099 fast/forms/suggestion-picker/date-suggestion-picker-appearance-zoom200.html [ Crash Failure ]
-crbug.com/591099 fast/forms/suggestion-picker/date-suggestion-picker-appearance.html [ Failure ]
-crbug.com/591099 fast/forms/suggestion-picker/date-suggestion-picker-key-operations.html [ Crash Failure Timeout ]
-crbug.com/591099 fast/forms/suggestion-picker/date-suggestion-picker-mouse-operations.html [ Failure ]
+crbug.com/591099 fast/forms/suggestion-picker/date-suggestion-picker-appearance.html [ Failure Pass ]
+crbug.com/591099 fast/forms/suggestion-picker/date-suggestion-picker-key-operations.html [ Crash Failure Pass Timeout ]
+crbug.com/591099 fast/forms/suggestion-picker/date-suggestion-picker-mouse-operations.html [ Failure Pass ]
 crbug.com/591099 fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-locale-hebrew.html [ Crash Failure Timeout ]
-crbug.com/591099 fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-rtl.html [ Failure ]
-crbug.com/591099 fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-with-scroll-bar.html [ Failure ]
-crbug.com/591099 fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance.html [ Failure ]
-crbug.com/591099 fast/forms/suggestion-picker/datetimelocal-suggestion-picker-key-operations.html [ Failure ]
-crbug.com/591099 fast/forms/suggestion-picker/datetimelocal-suggestion-picker-mouse-operations.html [ Failure ]
-crbug.com/591099 fast/forms/suggestion-picker/month-suggestion-picker-appearance-rtl.html [ Failure ]
-crbug.com/591099 fast/forms/suggestion-picker/month-suggestion-picker-appearance-with-scroll-bar.html [ Failure ]
-crbug.com/591099 fast/forms/suggestion-picker/month-suggestion-picker-appearance.html [ Failure ]
-crbug.com/591099 fast/forms/suggestion-picker/month-suggestion-picker-key-operations.html [ Crash Failure Timeout ]
-crbug.com/591099 fast/forms/suggestion-picker/month-suggestion-picker-mouse-operations.html [ Failure Timeout ]
+crbug.com/591099 fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-rtl.html [ Failure Pass ]
+crbug.com/591099 fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-with-scroll-bar.html [ Failure Pass ]
+crbug.com/591099 fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance.html [ Failure Pass ]
+crbug.com/591099 fast/forms/suggestion-picker/datetimelocal-suggestion-picker-key-operations.html [ Failure Pass ]
+crbug.com/591099 fast/forms/suggestion-picker/datetimelocal-suggestion-picker-mouse-operations.html [ Failure Pass ]
+crbug.com/591099 fast/forms/suggestion-picker/month-suggestion-picker-appearance-rtl.html [ Failure Pass ]
+crbug.com/591099 fast/forms/suggestion-picker/month-suggestion-picker-appearance-with-scroll-bar.html [ Failure Pass ]
+crbug.com/591099 fast/forms/suggestion-picker/month-suggestion-picker-appearance.html [ Failure Pass ]
+crbug.com/591099 fast/forms/suggestion-picker/month-suggestion-picker-key-operations.html [ Crash Failure Pass Timeout ]
+crbug.com/591099 fast/forms/suggestion-picker/month-suggestion-picker-mouse-operations.html [ Failure Pass Timeout ]
 crbug.com/591099 fast/forms/suggestion-picker/time-suggestion-picker-appearance-locale-hebrew.html [ Crash Failure ]
-crbug.com/591099 fast/forms/suggestion-picker/time-suggestion-picker-appearance-rtl.html [ Crash Failure ]
-crbug.com/591099 fast/forms/suggestion-picker/time-suggestion-picker-appearance-with-scroll-bar.html [ Crash Failure ]
-crbug.com/591099 fast/forms/suggestion-picker/time-suggestion-picker-appearance.html [ Failure Timeout ]
-crbug.com/591099 fast/forms/suggestion-picker/time-suggestion-picker-key-operations.html [ Failure ]
-crbug.com/591099 fast/forms/suggestion-picker/time-suggestion-picker-mouse-operations.html [ Failure ]
-crbug.com/591099 fast/forms/suggestion-picker/week-suggestion-picker-appearance-rtl.html [ Failure ]
-crbug.com/591099 fast/forms/suggestion-picker/week-suggestion-picker-appearance-with-scroll-bar.html [ Failure ]
-crbug.com/591099 fast/forms/suggestion-picker/week-suggestion-picker-appearance.html [ Failure ]
-crbug.com/591099 fast/forms/suggestion-picker/week-suggestion-picker-key-operations.html [ Crash Failure Timeout ]
-crbug.com/591099 fast/forms/suggestion-picker/week-suggestion-picker-mouse-operations.html [ Failure ]
+crbug.com/591099 fast/forms/suggestion-picker/time-suggestion-picker-appearance-rtl.html [ Crash Failure Pass ]
+crbug.com/591099 fast/forms/suggestion-picker/time-suggestion-picker-appearance-with-scroll-bar.html [ Crash Failure Pass ]
+crbug.com/591099 fast/forms/suggestion-picker/time-suggestion-picker-appearance.html [ Failure Pass Timeout ]
+crbug.com/591099 fast/forms/suggestion-picker/time-suggestion-picker-key-operations.html [ Failure Pass ]
+crbug.com/591099 fast/forms/suggestion-picker/time-suggestion-picker-mouse-operations.html [ Failure Pass ]
+crbug.com/591099 fast/forms/suggestion-picker/week-suggestion-picker-appearance-rtl.html [ Failure Pass ]
+crbug.com/591099 fast/forms/suggestion-picker/week-suggestion-picker-appearance-with-scroll-bar.html [ Failure Pass ]
+crbug.com/591099 fast/forms/suggestion-picker/week-suggestion-picker-appearance.html [ Failure Pass ]
+crbug.com/591099 fast/forms/suggestion-picker/week-suggestion-picker-key-operations.html [ Crash Failure Pass Timeout ]
+crbug.com/591099 fast/forms/suggestion-picker/week-suggestion-picker-mouse-operations.html [ Failure Pass ]
 crbug.com/591099 fast/forms/tabbing-input-iframe.html [ Crash Failure ]
 crbug.com/591099 fast/forms/targeted-frame-submission.html [ Failure ]
 crbug.com/591099 fast/forms/text-control-intrinsic-widths.html [ Timeout ]
@@ -4795,6 +4841,7 @@
 crbug.com/591099 fast/forms/textarea/textarea-placeholder-visibility-2.html [ Crash Failure ]
 crbug.com/591099 fast/forms/textarea/textarea-resize-orthogonal-containing-block.html [ Crash Failure Timeout ]
 crbug.com/591099 fast/forms/textarea/textarea-scroll-height.html [ Crash Failure ]
+crbug.com/591099 fast/forms/textarea/textarea-scrollbar-height.html [ Failure Pass ]
 crbug.com/591099 fast/forms/textarea/textarea-scrollbar.html [ Crash Failure ]
 crbug.com/591099 fast/forms/textarea/textarea-scrolled-focus-ring.html [ Crash Failure ]
 crbug.com/591099 fast/forms/textarea/textarea-scrolled-mask.html [ Crash Failure ]
@@ -4913,6 +4960,7 @@
 crbug.com/591099 fast/inline/absolute-positioned-inline-in-centred-block.html [ Failure ]
 crbug.com/591099 fast/inline/br-client-rect.html [ Failure ]
 crbug.com/591099 fast/inline/break-between-nobr.html [ Failure ]
+crbug.com/591099 fast/inline/collapsing-text-after-list-markers.html [ Failure Pass ]
 crbug.com/591099 fast/inline/continuation-outlines-with-layers.html [ Failure ]
 crbug.com/591099 fast/inline/continuation-outlines.html [ Failure ]
 crbug.com/591099 fast/inline/drawStyledEmptyInlines.html [ Failure ]
@@ -4928,6 +4976,7 @@
 crbug.com/591099 fast/inline/inline-offsetLeft-relpos.html [ Crash Failure ]
 crbug.com/591099 fast/inline/inline-position-top-align.html [ Failure ]
 crbug.com/591099 fast/inline/inline-text-quirk-bpm.html [ Failure ]
+crbug.com/591099 fast/inline/inline-width-containing-collapsed-whitespace-and-image-in-float.html [ Failure Pass ]
 crbug.com/591099 fast/inline/inline-with-empty-inline-children.html [ Failure ]
 crbug.com/591099 fast/inline/justify-emphasis-inline-box.html [ Failure ]
 crbug.com/591099 fast/inline/left-right-center-inline-alignment-in-ltr-and-rtl-blocks.html [ Crash Failure ]
@@ -5004,6 +5053,7 @@
 crbug.com/591099 fast/lists/002.html [ Crash Failure ]
 crbug.com/591099 fast/lists/003-vertical.html [ Crash Failure ]
 crbug.com/591099 fast/lists/003.html [ Crash Failure ]
+crbug.com/591099 fast/lists/004.html [ Failure Pass ]
 crbug.com/591099 fast/lists/005-vertical.html [ Crash Failure ]
 crbug.com/591099 fast/lists/005.html [ Crash Failure ]
 crbug.com/591099 fast/lists/006-vertical.html [ Crash Failure ]
@@ -5012,37 +5062,100 @@
 crbug.com/591099 fast/lists/007.html [ Crash Failure ]
 crbug.com/591099 fast/lists/008-vertical.html [ Crash Failure ]
 crbug.com/591099 fast/lists/008.html [ Crash Failure ]
+crbug.com/591099 fast/lists/009-vertical.html [ Failure Pass ]
+crbug.com/591099 fast/lists/009.html [ Failure Pass ]
 crbug.com/591099 fast/lists/alpha-boundary-values.html [ Crash Failure ]
 crbug.com/591099 fast/lists/alpha-list-wrap.html [ Crash Failure ]
 crbug.com/591099 fast/lists/anonymous-items.html [ Crash Failure ]
 crbug.com/591099 fast/lists/big-list-marker.html [ Crash Failure ]
+crbug.com/591099 fast/lists/calc-width-with-space.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-052.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-053.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-054.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-055.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-056.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-057.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-058.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-059.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-060.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-061.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-062.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-063.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-064.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-065.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-066.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-071.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-072.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-073.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-074.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-075.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-076.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-077.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-078.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-079.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-080.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-081.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-082.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-083.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-084.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-085.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-086.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-087.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-088.html [ Failure Pass ]
+crbug.com/591099 fast/lists/css3-counter-styles-089.html [ Failure Pass ]
+crbug.com/591099 fast/lists/decimal-leading-zero.html [ Failure Pass ]
 crbug.com/591099 fast/lists/drag-into-marker.html [ Failure ]
 crbug.com/591099 fast/lists/dynamic-marker-crash.html [ Crash Failure ]
 crbug.com/591099 fast/lists/inline-before-content-after-list-marker.html [ Failure ]
 crbug.com/591099 fast/lists/inlineBoxWrapperNullCheck.html [ Crash Failure ]
+crbug.com/591099 fast/lists/item-not-in-list-line-wrapping.html [ Failure Pass ]
 crbug.com/591099 fast/lists/li-br.html [ Crash Failure ]
 crbug.com/591099 fast/lists/li-style-alpha-huge-value-crash.html [ Crash Failure ]
+crbug.com/591099 fast/lists/li-values.html [ Failure Pass ]
+crbug.com/591099 fast/lists/list-color-change-no-layout.html [ Failure Pass ]
 crbug.com/591099 fast/lists/list-item-line-height.html [ Failure ]
-crbug.com/591099 fast/lists/list-marker-avoid-float-2.html [ Failure ]
-crbug.com/591099 fast/lists/list-marker-avoid-float.html [ Crash Failure ]
+crbug.com/591099 fast/lists/list-marker-avoid-float-2.html [ Failure Pass ]
+crbug.com/591099 fast/lists/list-marker-avoid-float.html [ Crash Failure Pass ]
 crbug.com/591099 fast/lists/list-marker-before-content-table.html [ Failure ]
 crbug.com/591099 fast/lists/list-marker-before-float-nested-rtl.html [ Crash Failure ]
 crbug.com/591099 fast/lists/list-marker-before-float-nested.html [ Crash Failure ]
 crbug.com/591099 fast/lists/list-marker-before-float-rtl.html [ Crash Failure ]
 crbug.com/591099 fast/lists/list-marker-before-float.html [ Crash Failure ]
-crbug.com/591099 fast/lists/list-marker-inside-overflow-hidden.html [ Failure ]
+crbug.com/591099 fast/lists/list-marker-inside-overflow-hidden.html [ Failure Pass ]
 crbug.com/591099 fast/lists/list-marker-padding-overflow-hidden-rtl.html [ Failure ]
 crbug.com/591099 fast/lists/list-marker-padding-overflow-hidden.html [ Failure ]
 crbug.com/591099 fast/lists/list-marker-with-line-height.html [ Crash Failure ]
+crbug.com/591099 fast/lists/list-style-type-dynamic-change.html [ Failure Pass ]
 crbug.com/591099 fast/lists/marker-before-empty-inline.html [ Crash Failure ]
 crbug.com/591099 fast/lists/marker-image-error.html [ Crash Failure ]
+crbug.com/591099 fast/lists/marker-preferred-margins.html [ Failure Pass ]
 crbug.com/591099 fast/lists/markers-in-selection.html [ Crash Failure ]
 crbug.com/591099 fast/lists/numeric-markers-outside-list.html [ Failure ]
 crbug.com/591099 fast/lists/ol-display-types.html [ Crash Failure ]
+crbug.com/591099 fast/lists/ol-nested-items-dynamic-insert.html [ Failure Pass ]
+crbug.com/591099 fast/lists/ol-nested-items-dynamic-remove.html [ Failure Pass ]
+crbug.com/591099 fast/lists/ol-nested-items.html [ Failure Pass ]
+crbug.com/591099 fast/lists/ol-nested-list-dynamic-insert.html [ Failure Pass ]
+crbug.com/591099 fast/lists/ol-nested-list-dynamic-remove.html [ Failure Pass ]
+crbug.com/591099 fast/lists/ol-nested-list.html [ Failure Pass ]
+crbug.com/591099 fast/lists/ol-reversed-dynamic-simple.html [ Failure Pass ]
+crbug.com/591099 fast/lists/ol-reversed-dynamic.html [ Failure Pass ]
+crbug.com/591099 fast/lists/ol-reversed-nested-items.html [ Failure Pass ]
+crbug.com/591099 fast/lists/ol-reversed-nested-list.html [ Failure Pass ]
+crbug.com/591099 fast/lists/ol-reversed-simple-xhtml.xhtml [ Failure Pass ]
+crbug.com/591099 fast/lists/ol-reversed-simple.html [ Failure Pass ]
 crbug.com/591099 fast/lists/ol-start-dynamic.html [ Crash Failure ]
 crbug.com/591099 fast/lists/ol-start-parsing.html [ Failure ]
 crbug.com/591099 fast/lists/olstart.html [ Failure ]
 crbug.com/591099 fast/lists/ordered-list-with-no-ol-tag.html [ Crash Failure ]
+crbug.com/591099 fast/lists/positioned-count-crash.html [ Failure Pass ]
+crbug.com/591099 fast/lists/scrolled-marker-paint.html [ Failure Pass ]
+crbug.com/591099 fast/lists/w3-css3-list-styles-alphabetic.html [ Failure Pass Timeout ]
+crbug.com/591099 fast/lists/w3-css3-list-styles-fallback-style.html [ Failure Pass ]
+crbug.com/591099 fast/lists/w3-css3-list-styles-numeric.html [ Failure Pass Timeout ]
+crbug.com/591099 fast/lists/w3-css3-lower-armenian.html [ Failure Pass ]
+crbug.com/591099 fast/lists/w3-css3-upper-armenian.html [ Failure Pass ]
+crbug.com/591099 fast/lists/w3-list-styles.html [ Failure Pass ]
 crbug.com/591099 fast/loader/child-frame-add-after-back-forward.html [ Failure Timeout ]
 crbug.com/591099 fast/loader/frame-creation-removal.html [ Failure ]
 crbug.com/591099 fast/loader/local-CSS-from-local.html [ Failure Pass ]
@@ -5278,6 +5391,7 @@
 crbug.com/591099 fast/multicol/newmulticol/fixed-height-fill-balance.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 Pass ]
+crbug.com/591099 fast/multicol/newmulticol/list-item.html [ Failure Pass ]
 crbug.com/591099 fast/multicol/newmulticol/orphans-and-widows-balance.html [ Failure ]
 crbug.com/591099 fast/multicol/newmulticol/regular-block-becomes-multicol.html [ Failure ]
 crbug.com/591099 fast/multicol/newmulticol/unresolvable-percent-height-2.html [ Failure ]
@@ -5532,6 +5646,7 @@
 crbug.com/591099 fast/parser/entity-comment-in-textarea.html [ Crash Failure ]
 crbug.com/591099 fast/parser/fonts.html [ Failure ]
 crbug.com/591099 fast/parser/innerhtml-with-prefixed-elements.xhtml [ Failure Pass ]
+crbug.com/591099 fast/parser/nested-fragment-parser-crash.html [ Failure Pass ]
 crbug.com/591099 fast/parser/nofoo-tags-inside-paragraph.html [ Failure ]
 crbug.com/591099 fast/parser/noscript-with-javascript-disabled.html [ Failure ]
 crbug.com/591099 fast/parser/open-comment-in-style.html [ Failure ]
@@ -5850,6 +5965,7 @@
 crbug.com/591099 fast/table/recalc-section-first-body-crash-main.html [ Failure ]
 crbug.com/591099 fast/table/row-in-inline-block.html [ Failure ]
 crbug.com/591099 fast/table/table-display-types-vertical.html [ Failure ]
+crbug.com/591099 fast/table/table-parts-not-ortho-writing-mode-root.html [ Failure ]
 crbug.com/591099 fast/table/table-rowspan-table-height-and-row-precent-height-too-large.html [ Failure ]
 crbug.com/591099 fast/table/table-sections-border-spacing.html [ Failure ]
 crbug.com/591099 fast/table/table-toggle-paragraph-padding.html [ Failure ]
@@ -5922,7 +6038,7 @@
 crbug.com/591099 fast/text/complex-text-opacity.html [ Failure ]
 crbug.com/591099 fast/text/container-align-with-inlines.html [ Failure ]
 crbug.com/591099 fast/text/decorations-with-text-combine.html [ Failure ]
-crbug.com/591099 fast/text/descent-clip-in-scaled-page.html [ Failure ]
+crbug.com/591099 fast/text/descent-clip-in-scaled-page.html [ Failure Pass ]
 crbug.com/591099 fast/text/ellipsis-at-edge-of-ltr-text-in-rtl-flow.html [ Failure ]
 crbug.com/591099 fast/text/ellipsis-at-edge-of-rtl-text-in-ltr-flow.html [ Failure ]
 crbug.com/591099 fast/text/ellipsis-in-absolute-block.html [ Failure ]
@@ -5948,6 +6064,8 @@
 crbug.com/591099 fast/text/ellipsis-rtl-text-in-rtl-flow-underline.html [ Failure ]
 crbug.com/591099 fast/text/ellipsis-rtl-text-in-rtl-flow.html [ Failure ]
 crbug.com/591099 fast/text/ellipsis-stroked.html [ Failure ]
+crbug.com/591099 fast/text/ellipsis-with-list-marker-in-ltr-flow.html [ Failure Pass ]
+crbug.com/591099 fast/text/ellipsis-with-list-marker-in-rtl-flow.html [ Failure Pass ]
 crbug.com/591099 fast/text/emphasis-avoid-ruby.html [ Crash Failure ]
 crbug.com/591099 fast/text/emphasis-combined-text.html [ Failure ]
 crbug.com/591099 fast/text/emphasis-complex.html [ Failure ]
@@ -5955,9 +6073,8 @@
 crbug.com/591099 fast/text/emphasis-overlap.html [ Failure ]
 crbug.com/591099 fast/text/find-kana.html [ Timeout ]
 crbug.com/591099 fast/text/font-smallcaps-layout.html [ Failure ]
-crbug.com/591099 fast/text/glyph-overflow-with-word-spacing.html [ Failure Pass ]
-crbug.com/591099 fast/text/glyph-overflow.html [ Failure Pass ]
 crbug.com/591099 fast/text/hide-atomic-inlines-after-ellipsis.html [ Crash Failure ]
+crbug.com/591099 fast/text/insert-text-crash.html [ Failure Pass ]
 crbug.com/591099 fast/text/international/bidi-AN-after-empty-run.html [ Failure ]
 crbug.com/591099 fast/text/international/bidi-LDB-2-CSS.html [ Failure ]
 crbug.com/591099 fast/text/international/bidi-LDB-2-HTML.html [ Failure ]
@@ -6025,6 +6142,7 @@
 crbug.com/591099 fast/text/whitespace/select-new-line-with-line-break-normal.html [ Failure ]
 crbug.com/591099 fast/text/whitespace/tab-character-basics.html [ Failure ]
 crbug.com/636993 fast/text/whitespace/text-align-justify-and-whitespace-pre.html [ Failure Pass ]
+crbug.com/591099 fast/text/whitespace/whitespace-and-margin-wrap-after-list-marker-crash.html [ Failure Pass ]
 crbug.com/591099 fast/text/whitespace/whitespace-in-pre.html [ Failure ]
 crbug.com/591099 fast/text/wide-preformatted.html [ Failure ]
 crbug.com/591099 fast/text/word-break.html [ Failure Pass ]
@@ -6034,6 +6152,7 @@
 crbug.com/591099 fast/text/zero-width-characters.html [ Failure ]
 crbug.com/591099 fast/tokenizer/001.html [ Failure ]
 crbug.com/591099 fast/tokenizer/003.html [ Failure ]
+crbug.com/591099 fast/tokenizer/004.html [ Failure Pass ]
 crbug.com/591099 fast/tokenizer/ignore-tags-in-iframe.html [ Failure ]
 crbug.com/591099 fast/tokenizer/missing-style-end-tag-1.html [ Crash Failure ]
 crbug.com/591099 fast/tokenizer/missing-style-end-tag-2.html [ Failure ]
@@ -6205,7 +6324,7 @@
 crbug.com/591099 fullscreen/full-screen-placeholder.html [ Failure ]
 crbug.com/591099 fullscreen/full-screen-with-flex-item.html [ Crash Failure ]
 crbug.com/591099 hittesting/border-hittest-inlineFlowBox.html [ Failure ]
-crbug.com/591099 hittesting/culled-inline-crash.html [ Failure ]
+crbug.com/591099 hittesting/culled-inline-crash.html [ Failure Pass ]
 crbug.com/591099 hittesting/hittest-child-of-inlineblock.html [ Crash Failure ]
 crbug.com/591099 hittesting/image-with-border-radius.html [ Failure ]
 crbug.com/591099 hittesting/inline-with-clip-path.html [ Failure ]
@@ -6300,6 +6419,7 @@
 crbug.com/591099 html/tabular_data/table_createcaption.html [ Failure ]
 crbug.com/591099 html/tabular_data/td_colspan_rendering.html [ Failure ]
 crbug.com/591099 html/text_level_semantics/font-weight-bold-for-b-and-strong.html [ Failure ]
+crbug.com/591099 html/text_level_semantics/ol-reversed.html [ Failure Pass ]
 crbug.com/591099 http/tests/appcache/main-resource-hash.html [ Crash Failure Timeout ]
 crbug.com/591099 http/tests/appcache/offline-access.html [ Crash Failure ]
 crbug.com/591099 http/tests/cache/xhr-vary-header.html [ Crash Failure ]
@@ -6318,8 +6438,24 @@
 crbug.com/591099 http/tests/devtools/console/console-functions.html [ Failure Pass ]
 crbug.com/591099 http/tests/devtools/console/console-uncaught-promise.html [ Failure Pass ]
 crbug.com/591099 http/tests/devtools/console/console-viewport-selection.html [ Failure ]
+crbug.com/591099 http/tests/devtools/elements/breadcrumb-updates.html [ Pass Timeout ]
 crbug.com/591099 http/tests/devtools/elements/edit/edit-dom-actions-1.html [ Crash Failure Timeout ]
-crbug.com/591099 http/tests/devtools/elements/elements-css-path.html [ Crash Failure ]
+crbug.com/591099 http/tests/devtools/elements/edit/edit-dom-actions-2.html [ Pass Timeout ]
+crbug.com/591099 http/tests/devtools/elements/edit/edit-dom-actions-3.html [ Pass Timeout ]
+crbug.com/591099 http/tests/devtools/elements/edit/edit-dom-actions-4.html [ Pass Timeout ]
+crbug.com/591099 http/tests/devtools/elements/edit/edit-dom-actions-shadow-1.html [ Pass Timeout ]
+crbug.com/591099 http/tests/devtools/elements/edit/edit-dom-actions-shadow-2.html [ Pass Timeout ]
+crbug.com/591099 http/tests/devtools/elements/edit/remove-node.html [ Pass Timeout ]
+crbug.com/591099 http/tests/devtools/elements/edit/set-outer-html-2.html [ Pass Timeout ]
+crbug.com/591099 http/tests/devtools/elements/edit/set-outer-html-body.html [ Pass Timeout ]
+crbug.com/591099 http/tests/devtools/elements/edit/set-outer-html-for-xhtml.xhtml [ Pass Timeout ]
+crbug.com/591099 http/tests/devtools/elements/edit/set-outer-html.html [ Pass Timeout ]
+crbug.com/591099 http/tests/devtools/elements/edit/switch-panels-while-editing-as-html.html [ Pass Timeout ]
+crbug.com/591099 http/tests/devtools/elements/edit/undo-dom-edits-2.html [ Pass Timeout ]
+crbug.com/591099 http/tests/devtools/elements/edit/undo-dom-edits.html [ Pass Timeout ]
+crbug.com/591099 http/tests/devtools/elements/edit/undo-set-outer-html-2.html [ Pass Timeout ]
+crbug.com/591099 http/tests/devtools/elements/edit/undo-set-outer-html.html [ Pass Timeout ]
+crbug.com/591099 http/tests/devtools/elements/elements-css-path.html [ Crash Failure Timeout ]
 crbug.com/591099 http/tests/devtools/elements/elements-linkify-attributes.html [ Crash Failure Timeout ]
 crbug.com/591099 http/tests/devtools/elements/elements-panel-restore-selection-when-node-comes-later.html [ Crash Failure ]
 crbug.com/591099 http/tests/devtools/elements/elements-panel-search.html [ Crash Failure ]
@@ -6329,12 +6465,20 @@
 crbug.com/591099 http/tests/devtools/elements/event-listener-sidebar.html [ Crash Failure Pass ]
 crbug.com/591099 http/tests/devtools/elements/highlight/highlight-css-shapes-outside-scroll.html [ Crash Failure Timeout ]
 crbug.com/591099 http/tests/devtools/elements/highlight/highlight-css-shapes-outside.html [ Crash Failure ]
+crbug.com/591099 http/tests/devtools/elements/highlight/highlight-dom-updates.html [ Pass Timeout ]
 crbug.com/591099 http/tests/devtools/elements/highlight/highlight-node-scroll.html [ Crash Failure ]
 crbug.com/591099 http/tests/devtools/elements/highlight/highlight-node.html [ Crash Failure ]
+crbug.com/591099 http/tests/devtools/elements/insert-node.html [ Pass Timeout ]
 crbug.com/591099 http/tests/devtools/elements/inspect-pointer-events-none.html [ Crash Timeout ]
+crbug.com/591099 http/tests/devtools/elements/shadow/breadcrumb-shadow-roots.html [ Pass Timeout ]
+crbug.com/591099 http/tests/devtools/elements/shadow/create-shadow-root.html [ Pass Timeout ]
+crbug.com/591099 http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-3.html [ Pass Timeout ]
 crbug.com/591099 http/tests/devtools/elements/shadow/inspect-deep-shadow-element.html [ Crash Failure ]
+crbug.com/591099 http/tests/devtools/elements/shadow/shadow-distribution.html [ Pass Timeout ]
+crbug.com/591099 http/tests/devtools/elements/shadow/shadow-host-display-modes.html [ Pass Timeout ]
 crbug.com/591099 http/tests/devtools/elements/styles-1/color-aware-property-value-edit.html [ Crash Failure ]
 crbug.com/591099 http/tests/devtools/elements/styles-2/add-import-rule.html [ Failure ]
+crbug.com/591099 http/tests/devtools/elements/styles-2/pseudo-elements.html [ Pass Timeout ]
 crbug.com/591099 http/tests/devtools/elements/styles-3/style-rule-from-imported-stylesheet.html [ Crash Failure ]
 crbug.com/591099 http/tests/devtools/elements/styles-4/styles-history.html [ Crash ]
 crbug.com/591099 http/tests/devtools/elements/styles-4/svg-style.xhtml [ Crash Failure ]
@@ -6348,7 +6492,7 @@
 crbug.com/591099 http/tests/devtools/layers/layer-replay-scale.html [ Crash Failure ]
 crbug.com/591099 http/tests/devtools/layers/layer-sticky-position-constraint-get.html [ Failure ]
 crbug.com/591099 http/tests/devtools/network/network-columns-visible.html [ Crash Failure Pass Timeout ]
-crbug.com/591099 http/tests/devtools/network/network-datareceived.html [ Pass Timeout ]
+crbug.com/591099 http/tests/devtools/network/network-datareceived.html [ Failure Pass Timeout ]
 crbug.com/591099 http/tests/devtools/network/network-disable-cache-preloads.php [ Crash Failure ]
 crbug.com/591099 http/tests/devtools/network/network-filters.html [ Crash Failure Timeout ]
 crbug.com/591099 http/tests/devtools/network/network-initiator.html [ Crash Failure Timeout ]
@@ -6376,6 +6520,7 @@
 crbug.com/591099 http/tests/devtools/tracing/timeline-layout/timeline-layout-with-invalidations.html [ Crash Failure ]
 crbug.com/591099 http/tests/devtools/tracing/timeline-misc/timeline-bound-function.html [ Crash Failure ]
 crbug.com/591099 http/tests/devtools/tracing/worker-js-frames.html [ Crash Failure Pass ]
+crbug.com/591099 http/tests/dom/location-stringify.html [ Failure Pass ]
 crbug.com/591099 http/tests/feature-policy-experimental-features/vibrate-allowed-by-container-policy-relocate-and-no-reload.html [ Timeout ]
 crbug.com/591099 http/tests/feature-policy-experimental-features/vibrate-allowed-by-container-policy-relocate-and-reload.html [ Crash Timeout ]
 crbug.com/591099 http/tests/feature-policy-experimental-features/vibrate-allowed-by-container-policy.html [ Crash Timeout ]
@@ -6590,6 +6735,7 @@
 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/591099 ietestcenter/css3/multicolumn/column-width-applies-to-009.htm [ Failure ]
+crbug.com/591099 ietestcenter/css3/multicolumn/column-width-applies-to-010.htm [ Failure Pass ]
 crbug.com/591099 ietestcenter/css3/multicolumn/column-width-applies-to-012.htm [ Failure ]
 crbug.com/591099 ietestcenter/css3/multicolumn/column-width-negative-001.htm [ Failure ]
 crbug.com/591099 ietestcenter/css3/multicolumn/column-width-percentage-001.htm [ Failure ]
@@ -7080,6 +7226,7 @@
 crbug.com/591099 paint/invalidation/multicol-relpos-with-abspos.html [ Failure Pass ]
 crbug.com/591099 paint/invalidation/multicol-repaint.html [ Failure ]
 crbug.com/591099 paint/invalidation/multicol-resize-with-rule.html [ Failure ]
+crbug.com/591099 paint/invalidation/multicol-rule-actual-columns-change.html [ Crash ]
 crbug.com/591099 paint/invalidation/multicol-with-abspos-in-relpos.html [ Failure Timeout ]
 crbug.com/591099 paint/invalidation/multicol-with-abspos.html [ Failure ]
 crbug.com/591099 paint/invalidation/multicol-with-block.html [ Failure Pass ]
@@ -7369,6 +7516,7 @@
 crbug.com/591099 paint/pagination/composited-paginated-outlined-box.html [ Failure ]
 crbug.com/591099 paint/pagination/pagination-change-clip-crash.html [ Failure ]
 crbug.com/591099 paint/printing/print-box-shadow.html [ Failure ]
+crbug.com/591099 paint/printing/print-text-shadow.html [ Failure ]
 crbug.com/591099 paint/roundedrects/circle-with-shadow.html [ Failure Pass ]
 crbug.com/591099 paint/roundedrects/input-with-rounded-rect-and-shadow.html [ Failure ]
 crbug.com/591099 paint/selection/text-selection-inline-block-rtl.html [ Failure ]
@@ -7535,7 +7683,7 @@
 crbug.com/591099 svg/animations/animateTransform-translate-invalid-attributetype.html [ Timeout ]
 crbug.com/591099 svg/animations/animation-begin-change-js.html [ Timeout ]
 crbug.com/591099 svg/animations/deferred-insertion.html [ Timeout ]
-crbug.com/591099 svg/animations/multiple-animations-ending.html [ Failure Timeout ]
+crbug.com/591099 svg/animations/multiple-animations-ending.html [ Failure Pass Timeout ]
 crbug.com/591099 svg/animations/svgPreserveAspectRatio-animation-1.html [ Timeout ]
 crbug.com/591099 svg/animations/svgangle-animation-deg-to-grad.html [ Timeout ]
 crbug.com/591099 svg/animations/svgangle-animation-deg-to-rad.html [ Timeout ]
@@ -7631,7 +7779,7 @@
 crbug.com/591099 svg/as-image/svg-non-integer-scaled-image.html [ Failure ]
 crbug.com/591099 svg/as-image/svg-object-intrinsic-size.html [ Failure ]
 crbug.com/591099 svg/as-image/svgview-references-use-counters.html [ Failure ]
-crbug.com/591099 svg/as-list-image/svg-list-image-intrinsic-size-zoom.html [ Failure ]
+crbug.com/591099 svg/as-list-image/svg-list-image-intrinsic-size-zoom.html [ Failure Pass ]
 crbug.com/591099 svg/as-object/object-box-sizing-no-width-height.html [ Failure Pass ]
 crbug.com/591099 svg/as-object/svg-embedded-in-html-in-iframe.html [ Failure Pass Timeout ]
 crbug.com/591099 svg/canvas/canvas-default-object-sizing.html [ Failure Pass ]
@@ -7775,7 +7923,6 @@
 crbug.com/591099 svg/overflow/overflow-on-outermost-svg-element-in-xhtml-hidden.xhtml [ Failure ]
 crbug.com/591099 svg/overflow/overflow-on-outermost-svg-element-in-xhtml-scroll.xhtml [ Failure ]
 crbug.com/591099 svg/overflow/overflow-on-outermost-svg-element-in-xhtml-visible.xhtml [ Failure ]
-crbug.com/591099 svg/parser/whitespace-angle-1.html [ Crash Pass Timeout ]
 crbug.com/591099 svg/parser/whitespace-angle-invalid-1.html [ Crash Timeout ]
 crbug.com/591099 svg/parser/whitespace-angle-invalid-2.html [ Crash Timeout ]
 crbug.com/591099 svg/parser/whitespace-integer.html [ Crash Pass Timeout ]
@@ -8108,8 +8255,7 @@
 crbug.com/591099 virtual/gpu-rasterization/images/sprite-no-bleed.html [ Failure ]
 crbug.com/591099 virtual/gpu-rasterization/images/webp-flip.html [ Failure ]
 crbug.com/591099 virtual/gpu-rasterization/images/zoomed-img-size.html [ Crash Failure ]
-crbug.com/591099 virtual/gpu/fast/canvas/OffscreenCanvas-2d-imageSmoothing-in-worker.html [ Timeout ]
-crbug.com/591099 virtual/gpu/fast/canvas/canvas-createImageBitmap-colorClamping.html [ Pass ]
+crbug.com/591099 virtual/gpu/fast/canvas/canvas-createImageBitmap-colorClamping.html [ Failure Pass ]
 crbug.com/591099 virtual/gpu/fast/canvas/canvas-createImageBitmap-drawImage.html [ Crash Timeout ]
 crbug.com/591099 virtual/gpu/fast/canvas/canvas-drawImage-animated-images.html [ Crash Failure ]
 crbug.com/591099 virtual/gpu/fast/canvas/canvas-drawImage-video-imageSmoothingEnabled.html [ Pass ]
@@ -8135,11 +8281,11 @@
 crbug.com/591099 virtual/scalefactor150/fast/hidpi/static/drag-image.html [ Failure ]
 crbug.com/591099 virtual/scalefactor150/fast/hidpi/static/popup-menu-with-scrollbar-appearance.html [ Failure ]
 crbug.com/591099 virtual/scalefactor150/fast/hidpi/static/validation-bubble-appearance-hidpi.html [ Failure ]
-crbug.com/591099 virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance.html [ Crash Failure ]
+crbug.com/591099 virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance.html [ Crash Failure Pass ]
 crbug.com/591099 virtual/scalefactor200/fast/hidpi/static/drag-image.html [ Failure ]
 crbug.com/591099 virtual/scalefactor200/fast/hidpi/static/popup-menu-with-scrollbar-appearance.html [ Failure ]
 crbug.com/591099 virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi.html [ Failure ]
-crbug.com/591099 virtual/scalefactor200withzoom/fast/hidpi/static/data-suggestion-picker-appearance.html [ Crash Failure ]
+crbug.com/591099 virtual/scalefactor200withzoom/fast/hidpi/static/data-suggestion-picker-appearance.html [ Crash Failure Pass ]
 crbug.com/591099 virtual/scalefactor200withzoom/fast/hidpi/static/drag-image.html [ Failure ]
 crbug.com/591099 virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-with-scrollbar-appearance.html [ Failure ]
 crbug.com/591099 virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
index a25d19c..14478de 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
@@ -60,7 +60,60 @@
 Bug(none) external/wpt/preload/fetch-destination.https.html [ Crash Failure Timeout ]
 Bug(none) external/wpt/resource-timing/test_resource_timing.html [ Failure Timeout ]
 Bug(none) external/wpt/service-workers/cache-storage/serviceworker [ Crash Failure Timeout ]
-Bug(none) external/wpt/service-workers/service-worker [ Crash Failure Timeout ]
+Bug(none) external/wpt/service-workers/service-worker/ServiceWorkerGlobalScope/unregister.https.html [ Pass Failure ]
+Bug(none) external/wpt/service-workers/service-worker/claim-affect-other-registration.https.html [ Crash ]
+Bug(none) external/wpt/service-workers/service-worker/claim-shared-worker-fetch.https.html [ Failure ]
+Bug(none) external/wpt/service-workers/service-worker/claim-using-registration.https.html [ Crash ]
+Bug(none) external/wpt/service-workers/service-worker/claim-worker-fetch.https.html [ Failure ]
+Bug(none) external/wpt/service-workers/service-worker/client-navigate.https.html [ Failure ]
+Bug(none) external/wpt/service-workers/service-worker/clients-get-client-types.https.html [ Failure ]
+Bug(none) external/wpt/service-workers/service-worker/clients-get.https.html [ Failure ]
+Bug(none) external/wpt/service-workers/service-worker/fetch-canvas-tainting-cache.https.html [ Crash ]
+Bug(none) external/wpt/service-workers/service-worker/fetch-canvas-tainting.https.html [ Crash ]
+Bug(none) external/wpt/service-workers/service-worker/fetch-cors-xhr.https.html [ Crash ]
+Bug(none) external/wpt/service-workers/service-worker/fetch-header-visibility.https.html [ Crash ]
+Bug(none) external/wpt/service-workers/service-worker/fetch-event-network-error.https.html [ Crash ]
+Bug(none) external/wpt/service-workers/service-worker/fetch-event-redirect.https.html [ Failure ]
+Bug(none) external/wpt/service-workers/service-worker/fetch-event-respond-with-argument.https.html [ Failure ]
+Bug(none) external/wpt/service-workers/service-worker/fetch-event-respond-with-response-body-with-invalid-chunk.https.html [ Failure ]
+Bug(none) external/wpt/service-workers/service-worker/fetch-event-respond-with-stops-propagation.https.html [ Timeout ]
+Bug(none) external/wpt/service-workers/service-worker/fetch-event.https.html [ Timeout ]
+Bug(none) external/wpt/service-workers/service-worker/fetch-frame-resource.https.html [ Crash ]
+Bug(none) external/wpt/service-workers/service-worker/fetch-request-css-images.https.html [ Crash Pass ]
+Bug(none) external/wpt/service-workers/service-worker/fetch-request-fallback.https.html [ Failure ]
+Bug(none) external/wpt/service-workers/service-worker/fetch-request-redirect.https.html [ Crash ]
+Bug(none) external/wpt/service-workers/service-worker/fetch-request-resources.https.html [ Pass Failure Crash ]
+Bug(none) external/wpt/service-workers/service-worker/fetch-request-xhr-sync.https.html [ Timeout ]
+Bug(none) external/wpt/service-workers/service-worker/fetch-request-xhr.https.html [ Crash ]
+Bug(none) external/wpt/service-workers/service-worker/fetch-response-taint.https.html [ Failure ]
+Bug(none) external/wpt/service-workers/service-worker/fetch-response-xhr.https.html [ Crash ]
+Bug(none) external/wpt/service-workers/service-worker/foreign-fetch-workers.https.html [ Crash ]
+Bug(none) external/wpt/service-workers/service-worker/import-scripts-redirect.https.html [ Failure ]
+Bug(none) external/wpt/service-workers/service-worker/import-scripts-resource-map.https.html [ Crash ]
+Bug(none) external/wpt/service-workers/service-worker/import-scripts-updated-flag.https.html [ Crash ]
+Bug(none) external/wpt/service-workers/service-worker/invalid-blobtype.https.html [ Crash ]
+Bug(none) external/wpt/service-workers/service-worker/invalid-header.https.html [ Crash ]
+Bug(none) external/wpt/service-workers/service-worker/iso-latin1-header.https.html [ Crash ]
+Bug(none) external/wpt/service-workers/service-worker/navigation-redirect-to-http.https.html [ Failure ]
+Bug(none) external/wpt/service-workers/service-worker/navigation-redirect.https.html [ Timeout ]
+Bug(none) external/wpt/service-workers/service-worker/opaque-response-preloaded.https.html [ Failure ]
+Bug(none) external/wpt/service-workers/service-worker/redirected-response.https.html [ Failure ]
+Bug(none) external/wpt/service-workers/service-worker/register-link-header.https.html [ Timeout ]
+Bug(none) external/wpt/service-workers/service-worker/registration-security-error.https.html [ Failure ]
+Bug(none) external/wpt/service-workers/service-worker/registration-updateviacache.https.html [ Timeout ]
+Bug(none) external/wpt/service-workers/service-worker/request-body-blob.https.html [ Crash ]
+Bug(none) external/wpt/service-workers/service-worker/resource-timing.https.html [ Failure ]
+Bug(none) external/wpt/service-workers/service-worker/shared-worker-controlled.https.html [ Timeout ]
+Bug(none) external/wpt/service-workers/service-worker/update-bytecheck.https.html [ Pass Timeout Failure ]
+Bug(none) external/wpt/service-workers/service-worker/update-recovery.https.html [ Crash ]
+Bug(none) external/wpt/service-workers/service-worker/worker-interception.https.html [ Pass Crash Failure ]
+Bug(none) external/wpt/service-workers/service-worker/navigation-preload/broken-chunked-encoding.https.html [ Failure ]
+Bug(none) external/wpt/service-workers/service-worker/navigation-preload/redirect.https.html [ Crash ]
+
+# NetworkService won't support Foreign Fetch.
+Bug(wontfix) external/wpt/service-workers/service-worker/foreign-fetch-basics.https.html [ Skip ]
+Bug(wontfix) external/wpt/service-workers/service-worker/foreign-fetch-cors.https.html [ Skip ]
+
 Bug(none) external/wpt/streams/byte-length-queuing-strategy.serviceworker.https.html [ Crash Failure Timeout ]
 Bug(none) external/wpt/streams/count-queuing-strategy.serviceworker.https.html [ Crash Failure Timeout ]
 Bug(none) external/wpt/streams/piping/close-propagation-backward.serviceworker.https.html [ Crash Failure Timeout ]
@@ -461,6 +514,7 @@
 Bug(none) virtual/mojo-loading/http/tests/xmlhttprequest/methods-lower-case.html [ Failure Timeout Pass Crash ]
 Bug(none) installedapp/getinstalledrelatedapps-empty.html [ Timeout ]
 Bug(none) installedapp/getinstalledrelatedapps.html [ Timeout ]
+Bug(none) paint/invalidation/video-paint-invalidation.html [ Failure ]
 Bug(none) plugins/iframe-plugin-bgcolor.html [ Timeout ]
 
 Bug(none) virtual [ Crash Failure Timeout ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
index 17d031b..f96cdf3 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -54,7 +54,6 @@
 Bug(none) security/ [ Skip ]
 Bug(none) shadow-dom/ [ Skip ]
 Bug(none) storage/ [ Skip ]
-Bug(none) svg/clip-path/ [ Skip ]
 Bug(none) tables/ [ Skip ]
 Bug(none) third_party/ [ Skip ]
 Bug(none) touchadjustment/ [ Skip ]
@@ -84,6 +83,7 @@
 Bug(none) virtual/mojo-loading/ [ Skip ]
 Bug(none) virtual/mojo-localstorage/ [ Skip ]
 Bug(none) virtual/mse-1mb-buffers/ [ Skip ]
+Bug(none) virtual/new-remote-playback-pipeline/ [ Skip ]
 Bug(none) virtual/prefer_compositing_to_lcd_text/ [ Skip ]
 Bug(none) virtual/rootlayerscrolls/ [ Skip ]
 Bug(none) virtual/scalefactor150/ [ Skip ]
@@ -125,7 +125,6 @@
 Bug(none) compositing/contents-opaque/hidden-with-visible-text.html [ Failure ]
 Bug(none) compositing/contents-opaque/layer-opacity.html [ Failure ]
 Bug(none) compositing/contents-opaque/overflow-hidden-child-layers.html [ Failure ]
-Bug(none) compositing/culling/filter-occlusion-alpha-large.html [ Failure Crash ]
 Bug(none) compositing/culling/tile-occlusion-boundaries.html [ Failure ]
 Bug(none) compositing/direct-image-compositing.html [ Failure ]
 Bug(none) compositing/draws-content/canvas-background-layer.html [ Failure ]
@@ -149,10 +148,8 @@
 Bug(none) compositing/geometry/clip-with-shadow.html [ Failure ]
 Bug(none) compositing/geometry/clip.html [ Failure ]
 Bug(none) compositing/geometry/composited-in-columns.html [ Failure Crash ]
-Bug(none) compositing/geometry/fixed-in-composited.html [ Failure ]
 Bug(none) compositing/geometry/flipped-writing-mode.html [ Failure ]
 Bug(none) compositing/geometry/foreground-layer.html [ Failure ]
-Bug(none) compositing/geometry/horizontal-scroll-composited.html [ Failure ]
 Bug(none) compositing/geometry/layer-due-to-layer-children-deep.html [ Failure ]
 Bug(none) compositing/geometry/layer-due-to-layer-children-deep-switch.html [ Failure ]
 Bug(none) compositing/geometry/layer-due-to-layer-children-switch.html [ Failure ]
@@ -163,7 +160,6 @@
 Bug(none) compositing/geometry/limit-layer-bounds-positioned.html [ Failure ]
 Bug(none) compositing/geometry/limit-layer-bounds-transformed.html [ Failure ]
 Bug(none) compositing/geometry/preserve-3d-switching.html [ Failure ]
-Bug(none) compositing/geometry/tall-page-composited.html [ Failure ]
 Bug(none) compositing/geometry/video-fixed-scrolling.html [ Failure ]
 Bug(none) compositing/geometry/video-opacity-overlay.html [ Failure ]
 Bug(none) compositing/gestures/gesture-tapHighlight-1-iframe-composited-scrolled-late-composite.html [ Failure ]
@@ -184,6 +180,7 @@
 Bug(none) compositing/gestures/gesture-tapHighlight-2-iframe-composited-outer.html [ Failure ]
 Bug(none) compositing/gestures/gesture-tapHighlight-2-iframe-scrolled-inner-late-composite.html [ Failure ]
 Bug(none) compositing/gestures/gesture-tapHighlight-2-iframe-scrolled-inner.html [ Failure ]
+Bug(none) compositing/gestures/gesture-tapHighlight-2-iframe-scrolled-outer-late-composite.html [ Failure ]
 Bug(none) compositing/gestures/gesture-tapHighlight-2-iframe-scrolled-outer.html [ Failure ]
 Bug(none) compositing/gestures/gesture-tapHighlight-2-iframe.html [ Failure ]
 Bug(none) compositing/gestures/gesture-tapHighlight-2-overflow-div-composited-inner-scroll-inner.html [ Failure ]
@@ -244,7 +241,6 @@
 Bug(none) compositing/images/direct-image-clip-path.html [ Failure ]
 Bug(none) compositing/images/direct-image-dynamic-border-draws-content.html [ Failure ]
 Bug(none) compositing/images/direct-image-dynamic-clip-path.html [ Failure ]
-Bug(none) compositing/img-layer-grow.html [ Failure ]
 Bug(none) compositing/layer-creation/animation-overlap-with-children.html [ Failure ]
 Bug(none) compositing/layer-creation/assumed-overlap-for-inline-transform.html [ Failure ]
 Bug(none) compositing/layer-creation/fixed-position-and-transform.html [ Failure ]
@@ -258,7 +254,6 @@
 Bug(none) compositing/layer-creation/fixed-position-out-of-view-scaled.html [ Failure ]
 Bug(none) compositing/layer-creation/fixed-position-out-of-view-with-backdrop-filter.html [ Failure ]
 Bug(none) compositing/layer-creation/fixed-position-out-of-view.html [ Failure ]
-Bug(none) compositing/layer-creation/fixed-position-scroll.html [ Failure ]
 Bug(none) compositing/layer-creation/fixed-position-under-transform.html [ Failure ]
 Bug(none) compositing/layer-creation/no-compositing-for-fixed-position-under-transform.html [ Failure ]
 Bug(none) compositing/layer-creation/no-compositing-for-preserve-3d.html [ Failure ]
@@ -288,15 +283,12 @@
 Bug(none) compositing/overflow/accelerated-overflow-scroll-should-not-affect-perspective.html [ Failure ]
 Bug(none) compositing/overflow/accelerated-scrolling-with-clip-path-text.html [ Failure ]
 Bug(none) compositing/overflow/accelerated-scrolling-with-clip-path.html [ Failure ]
-Bug(none) compositing/overflow/ancestor-with-clip-path.html [ Failure ]
 Bug(none) compositing/overflow/avoid-ancestor-clip-for-scroll-children.html [ Failure ]
-Bug(none) compositing/overflow/body-switch-composited-scrolling.html [ Failure ]
 Bug(none) compositing/overflow/clear-scroll-parent.html [ Failure ]
 Bug(none) compositing/overflow/clip-descendents.html [ Failure ]
 Bug(none) compositing/overflow/composited-scrolling-paint-phases.html [ Failure ]
 Bug(none) compositing/overflow/content-loses-scrollbars.html [ Failure ]
 Bug(none) compositing/overflow/content-gains-scrollbars.html [ Failure ]
-Bug(none) compositing/overflow/descendant-with-clip-path.html [ Failure ]
 Bug(none) compositing/overflow/mask-with-filter.html [ Failure Crash ]
 Bug(none) compositing/overflow/mask-with-small-content-rect.html [ Failure ]
 Bug(none) compositing/overflow/nested-render-surfaces-with-intervening-clip.html [ Failure Crash ]
@@ -329,7 +321,6 @@
 Bug(none) compositing/overflow/textarea-scroll-touch.html [ Failure ]
 Bug(none) compositing/overflow/tiled-mask.html [ Failure ]
 Bug(none) compositing/overflow/universal-accelerated-overflow-scroll.html [ Failure ]
-Bug(none) compositing/overlap-blending/children-opacity-huge.html [ Failure ]
 Bug(none) compositing/overlap-blending/reflection-opacity-huge.html [ Failure Crash ]
 Bug(none) compositing/perpendicular-layer-sorting.html [ Failure ]
 Bug(none) compositing/plugins/webplugin-reflection.html [ Failure Crash ]
@@ -361,8 +352,6 @@
 Bug(none) compositing/rtl/rtl-iframe-fixed-overflow.html [ Failure ]
 Bug(none) compositing/rtl/rtl-iframe-fixed.html [ Failure ]
 Bug(none) compositing/rtl/rtl-iframe-relative.html [ Failure ]
-Bug(none) compositing/rtl/rtl-overflow-invalidation.html [ Failure Crash ]
-Bug(none) compositing/scrollbars/custom-composited-different-track-parts.html [ Failure ]
 Bug(none) compositing/scrollbars/nested-overlay-scrollbars.html [ Failure ]
 Bug(none) compositing/self-painting-layers.html [ Failure ]
 Bug(none) compositing/squashing/add-remove-squashed-layers.html [ Failure ]
@@ -419,29 +408,20 @@
 Bug(none) fast/backgrounds/transformed-body-html-background.html [ Failure ]
 Bug(none) fast/backgrounds/transformed-html-body-background.html [ Failure ]
 Bug(none) fast/block/basic/016.html [ Failure ]
-Bug(none) fast/block/basic/fieldset-stretch-to-legend.html [ Failure ]
 Bug(none) fast/block/float/008.html [ Failure ]
 Bug(none) fast/block/float/021.html [ Failure ]
 Bug(none) fast/block/float/025.html [ Failure ]
 Bug(none) fast/block/float/026.html [ Failure ]
 Bug(none) fast/block/float/027.html [ Failure ]
 Bug(none) fast/block/float/028.html [ Failure ]
-Bug(none) fast/block/float/032.html [ Failure ]
-Bug(none) fast/block/float/033.html [ Failure ]
-Bug(none) fast/block/float/035.html [ Failure ]
-Bug(none) fast/block/float/br-with-clear-2.html [ Failure ]
 Bug(none) fast/block/float/centered-float-avoidance-complexity.html [ Failure ]
 Bug(none) fast/block/float/float-avoidance.html [ Failure ]
-Bug(none) fast/block/float/nested-clearance.html [ Failure ]
-Bug(none) fast/block/float/relative-painted-twice.html [ Failure ]
 Bug(none) fast/block/float/shrink-to-avoid-float-complexity.html [ Failure ]
-Bug(none) fast/block/margin-collapse/103.html [ Failure ]
 Bug(none) fast/block/margin-collapse/104.html [ Failure ]
 Bug(none) fast/block/margin-collapse/empty-clear-blocks.html [ Failure ]
 Bug(none) fast/block/positioning/047.html [ Failure ]
 Bug(none) fast/block/positioning/051.html [ Failure ]
 Bug(none) fast/block/positioning/055.html [ Failure ]
-Bug(none) fast/block/positioning/auto/007.html [ Failure ]
 Bug(none) fast/block/positioning/fixed-positioning-scrollbar-bug.html [ Failure ]
 Bug(none) fast/block/positioning/offsetLeft-offsetTop-multicolumn.html [ Failure ]
 Bug(none) fast/block/positioning/relative-overflow-block.html [ Failure ]
@@ -467,7 +447,7 @@
 Bug(none) fast/box-shadow/basic-shadows.html [ Failure ]
 Bug(none) fast/box-sizing/box-sizing.html [ Failure ]
 Bug(none) fast/canvas/canvas-composite-video.html [ Failure ]
-Bug(none) fast/canvas/canvas-css-clip-path.html [ Failure ]
+Bug(none) fast/canvas/imagebitmap/transferFromImageBitmap-no-alpha.html [ Failure ]
 Bug(none) fast/canvas/OffscreenCanvas-2d-drawImage-in-worker.html [ Failure ]
 Bug(none) fast/canvas/OffscreenCanvas-2d-drawImage.html [ Failure ]
 Bug(none) fast/canvas/OffscreenCanvas-2d-gradients-in-worker.html [ Failure ]
@@ -481,9 +461,7 @@
 Bug(none) fast/canvas/OffscreenCanvas-strokeRect-in-worker.html [ Failure ]
 Bug(none) fast/canvas/OffscreenCanvas-text-rendering-in-worker.html [ Failure ]
 Bug(none) fast/canvas/OffscreenCanvas-transform-shadow-in-worker.html [ Failure ]
-Bug(none) fast/clip/nestedTransparencyClip.html [ Failure ]
 Bug(none) fast/css-generated-content/014.html [ Failure ]
-Bug(none) fast/css-generated-content/table-parts-before-and-after.html [ Failure ]
 Bug(none) fast/css/bidi-override-in-anonymous-block.html [ Failure ]
 Bug(none) fast/css/border-height.html [ Failure ]
 Bug(none) fast/css/color-correction-backgrounds-and-text.html [ Failure ]
@@ -542,7 +520,6 @@
 Bug(none) fast/events/wheel/wheelevent-in-vertical-scrollbar-in-rtl.html [ Failure ]
 Bug(none) fast/forms/button-default-title.html [ Failure ]
 Bug(none) fast/forms/fieldset/fieldset-align.html [ Failure ]
-Bug(none) fast/forms/huge-mac-input-clamped-height.html [ Failure ]
 Bug(none) fast/forms/huge-mac-input-clamped-width.html [ Failure ]
 Bug(none) fast/forms/placeholder-position.html [ Failure ]
 Bug(none) fast/forms/select/listbox-appearance-basic.html [ Failure ]
@@ -596,7 +573,6 @@
 Bug(none) fast/lists/008.html [ Failure ]
 Bug(none) fast/lists/ol-start-parsing.html [ Failure ]
 Bug(none) fast/lists/olstart.html [ Failure ]
-Bug(none) fast/masking/clip-path-inset-large-radii.html [ Failure ]
 Bug(none) fast/multicol/abspos-after-break-after.html [ Failure ]
 Bug(none) fast/multicol/abspos-in-overflow-hidden-in-2nd-column.html [ Failure ]
 Bug(none) fast/multicol/balance-breakafter-before-nested-block.html [ Failure ]
@@ -774,7 +750,6 @@
 Bug(none) fast/multicol/table-cell-content-change-with-decorations.html [ Failure ]
 Bug(none) fast/multicol/table-margin-collapse.html [ Failure ]
 Bug(none) fast/multicol/tall-float2.html [ Failure ]
-Bug(none) fast/multicol/transform-inside-opacity.html [ Failure ]
 Bug(none) fast/multicol/transform-with-fixedpos.html [ Crash ]
 Bug(none) fast/multicol/unbreakable-block-too-tall-at-column-start.html [ Failure ]
 Bug(none) fast/multicol/unbreakable-block-too-tall-to-fit.html [ Failure ]
@@ -829,8 +804,6 @@
 Bug(none) fast/reflections/transparent-reflected-sublayers.html [ Crash Failure ]
 Bug(none) fast/replaced/width100percent-textarea.html [ Failure ]
 Bug(none) fast/scroll-behavior/ [ Skip ]
-Bug(none) fast/scrolling/scrollbar-tickmarks-styled-after-onload.html [ Failure ]
-Bug(none) fast/scrolling/scrollbar-tickmarks-styled.html [ Failure ]
 Bug(none) fast/selectors/166.html [ Failure ]
 Bug(none) fast/sub-pixel/column-clipping.html [ Failure ]
 Bug(none) fast/sub-pixel/repaint-subpixel-layer-in-subpixel-composited-layer.html [ Failure ]
@@ -850,8 +823,6 @@
 Bug(none) virtual/mojo-loading/fast/table/empty-cells.html [ Failure ]
 Bug(none) fast/table/frame-and-rules.html [ Failure ]
 Bug(none) virtual/mojo-loading/fast/table/frame-and-rules.html [ Failure ]
-Bug(none) fast/table/height-percent-test.html [ Failure ]
-Bug(none) virtual/mojo-loading/fast/table/height-percent-test.html [ Failure ]
 Bug(none) fast/table/overflowHidden.html [ Failure ]
 Bug(none) virtual/mojo-loading/fast/table/overflowHidden.html [ Failure ]
 Bug(none) fast/table/prepend-in-anonymous-table.html [ Failure ]
@@ -932,7 +903,6 @@
 Bug(none) virtual/mojo-loading/fast/table/backgr_simple-table-row.html [ Failure ]
 Bug(none) fast/table/backgr_simple-table.html [ Failure ]
 Bug(none) virtual/mojo-loading/fast/table/backgr_simple-table.html [ Failure ]
-Bug(none) fast/text-autosizing/hackernews-comments.html [ Failure ]
 Bug(none) fast/text/capitalize-boundaries.html [ Failure ]
 Bug(none) fast/text/emphasis.html [ Failure ]
 Bug(none) fast/text/font-stretch-variant.html [ Failure ]
@@ -941,12 +911,11 @@
 Bug(none) fast/text/softHyphen.html [ Failure ]
 Bug(none) fast/text/stroking-decorations.html [ Failure Pass ]
 Bug(none) fast/text/text-letter-spacing.html [ Failure ]
-Bug(none) fast/text/unicode-fallback-font.html [ Failure ]
 Bug(none) fast/text/whitespace/024.html [ Failure ]
 Bug(none) fast/text/whitespace/pre-wrap-spaces-after-newline.html [ Failure ]
 Bug(none) fast/text/word-break.html [ Failure ]
 Bug(none) fast/writing-mode/fieldsets.html [ Failure ]
-Bug(none) paint/clipath/clip-path-with-background-and-box-behind.html [ Failure ]
+Bug(none) images/cross-fade-invalidation.html [ Crash Failure Pass ]
 Bug(none) paint/pagination/pagination-change-clip-crash.html [ Failure ]
 Bug(none) paint/selection/text-selection-newline-mixed-ltr-rtl.html [ Failure ]
 
@@ -967,31 +936,41 @@
 Bug(none) paint/invalidation/paint-invalidation-with-reparent-across-frame-boundaries.html [ Failure ]
 Bug(none) paint/invalidation/svg/resize-svg-invalidate-children-2.html [ Failure ]
 Bug(none) paint/invalidation/svg/resize-svg-invalidate-children.html [ Failure ]
+Bug(none) paint/invalidation/video-mute-repaint.html [ Failure ]
+Bug(none) paint/invalidation/video-unmute-repaint.html [ Failure ]
 
 # The expectation seems incorrect?
 Bug(none) paint/invalidation/paged-with-overflowing-block-rl.html [ Failure ]
 
-# Corrupted painting or rasterization. Some might be under-invalidations.
+crbug.com/769942 svg/clip-path/ [ Skip ]
+crbug.com/769942 compositing/overflow/ancestor-with-clip-path.html [ Failure ]
+crbug.com/769942 compositing/overflow/descendant-with-clip-path.html [ Failure ]
+crbug.com/769942 fast/canvas/canvas-css-clip-path.html [ Failure ]
+crbug.com/769942 fast/masking/clip-path-inset-large-radii.html [ Failure ]
+crbug.com/769942 paint/clipath/clip-path-with-background-and-box-behind.html [ Failure ]
+crbug.com/769942 paint/invalidation/clip-path-constant-repaint.html [ Failure ]
+crbug.com/769942 paint/invalidation/svg/clip-path-child-changes.svg [ Failure ]
+crbug.com/769942 paint/invalidation/svg/clip-path-href-changes.svg [ Failure ]
+crbug.com/769942 paint/invalidation/svg/clip-path-id-changes.svg [ Failure ]
+crbug.com/769942 paint/invalidation/svg/clip-path-units-changes.svg [ Failure ]
+crbug.com/769942 paint/invalidation/svg/image-with-clip-path.svg [ Failure ]
+crbug.com/769942 paint/invalidation/svg/js-late-clipPath-and-object-creation.svg [ Failure ]
+crbug.com/769942 paint/invalidation/svg/js-late-clipPath-creation.svg [ Failure ]
+crbug.com/769942 svg/custom/clip-path-referencing-use.svg [ Failure ]
+crbug.com/769942 svg/custom/clip-path-with-css-transform-1.svg [ Failure ]
+crbug.com/769942 svg/custom/clip-path-with-css-transform-2.svg [ Failure ]
+crbug.com/769942 svg/custom/clip-path-with-transform.svg [ Failure ]
+crbug.com/769942 svg/custom/use-on-clip-path-with-transformation.svg [ Failure ]
+crbug.com/769942 svg/custom/recursive-clippath.svg [ Failure ]
+crbug.com/769942 svg/custom/viewport-clippath-invalidation.html [ Failure ]
+crbug.com/769942 svg/transforms/svg-css-transforms-clip-path.xhtml [ Failure ]
+
+# Corrupted painting or rasterization.
 Bug(none) paint/invalidation/scroll-descendant-with-cached-cliprects.html [ Failure ]
-Bug(none) paint/invalidation/scroll-fixed-layer-with-no-visible-content.html [ Failure ]
-Bug(none) paint/invalidation/scroll-fixed-layer-with-reflection.html [ Failure ]
-Bug(none) paint/invalidation/scroll-fixed-reflected-layer.html [ Failure ]
-Bug(none) paint/invalidation/scroll-in-fixed-layer.html [ Failure ]
-Bug(none) paint/invalidation/svg/clip-path-child-changes.svg [ Failure ]
-Bug(none) paint/invalidation/svg/clip-path-href-changes.svg [ Failure ]
-Bug(none) paint/invalidation/svg/clip-path-id-changes.svg [ Failure ]
-Bug(none) paint/invalidation/svg/clip-path-units-changes.svg [ Failure ]
-Bug(none) paint/invalidation/svg/filter-refresh.svg [ Failure ]
-Bug(none) paint/invalidation/svg/image-animation-with-zoom.html [ Pass Failure ]
-Bug(none) paint/invalidation/svg/js-late-clipPath-and-object-creation.svg [ Failure ]
-Bug(none) paint/invalidation/svg/js-late-clipPath-creation.svg [ Failure ]
-Bug(none) paint/invalidation/svg/paintorder-filtered.svg [ Failure ]
-Bug(none) paint/invalidation/svg/relative-sized-document-scrollbars.svg [ Failure ]
 Bug(none) paint/invalidation/svg/use-clipped-hit.svg [ Failure ]
 Bug(none) paint/invalidation/svg/zoom-coords-viewattr-01-b.svg [ Failure ]
 
 # Extra raster invalidations.
-Bug(none) paint/invalidation/clip-path-constant-repaint.html [ Failure ]
 Bug(none) paint/invalidation/compositing/clipping-should-not-repaint-composited-descendants.html [ Failure ]
 Bug(none) paint/invalidation/compositing/fixed-scroll-in-empty-root-layer.html [ Failure ]
 Bug(none) paint/invalidation/compositing/resize-repaint.html [ Failure ]
@@ -1008,9 +987,11 @@
 Bug(none) paint/invalidation/iframe-scroll-repaint.html [ Failure ]
 Bug(none) paint/invalidation/invalidate-after-composited-scroll-of-window.html [ Failure ]
 Bug(none) paint/invalidation/invalidation-after-opacity-change-subtree.html [ Failure ]
+Bug(none) paint/invalidation/japanese-rl-selection-repaint.html [ Failure ]
 Bug(none) paint/invalidation/layout-state-only-positioned.html [ Failure ]
 Bug(none) paint/invalidation/opacity-change-on-overflow-float.html [ Failure ]
 Bug(none) paint/invalidation/relative-positioned-movement-repaint.html [ Failure ]
+Bug(none) paint/invalidation/repaint-across-writing-mode-boundary.html [ Failure ]
 Bug(none) paint/invalidation/scroll-absolute-layer-with-reflection.html [ Failure ]
 Bug(none) paint/invalidation/scroll-fixed-layer-with-transformed-parent-layer.html [ Failure ]
 Bug(none) paint/invalidation/scrolled-iframe-scrollbar-change.html [ Failure ]
@@ -1022,36 +1003,15 @@
 Bug(none) paint/invalidation/svg/use-detach.svg [ Failure ]
 Bug(none) paint/invalidation/window-resize-percent-html.html [ Failure ]
 
-# Missing painting of scrollbars.
-crbug.com/757938 fast/text/international/vertical-text-glyph-test.html [ Failure ]
-crbug.com/757938 paint/invalidation/background-image-paint-invalidation-large-abspos-div.html [ Failure ]
-crbug.com/757938 paint/invalidation/compositing/newly-composited-on-scroll.html [ Failure ]
-crbug.com/757938 paint/invalidation/compositing/newly-composited-repaint-rect.html [ Pass Failure ]
-crbug.com/757938 paint/invalidation/full-viewport-repaint-for-background-attachment-fixed.html [ Failure ]
-crbug.com/757938 paint/invalidation/inline-style-change-in-scrolled-view.html [ Failure ]
-crbug.com/757938 paint/invalidation/nested-fixed-iframe-scrolled.html [ Failure ]
-crbug.com/757938 paint/invalidation/overflow-scroll-body-appear.html [ Failure ]
-crbug.com/757938 paint/invalidation/repaint-during-scroll.html [ Failure ]
-crbug.com/757938 paint/invalidation/svg/repaint-in-scrolled-view.html [ Failure ]
-crbug.com/757938 paint/invalidation/svg/text-xy-updates-SVGList.xhtml [ Failure ]
-
-# Different invalidation rect for filter and reflection.
+# Different invalidation rect or corrupted rendering for filter and reflection.
 Bug(none) paint/invalidation/filter-invalidation-positioned-child.html [ Failure ]
 Bug(none) paint/invalidation/filter-repaint-accelerated-on-accelerated-filter.html [ Failure ]
-Bug(none) paint/invalidation/filters/effect-reference-repaint-composite-1.html [ Failure ]
-Bug(none) paint/invalidation/filters/effect-reference-repaint-composite-2.html [ Failure ]
-Bug(none) paint/invalidation/filters/effect-reference-repaint-composite-3.html [ Failure ]
-Bug(none) paint/invalidation/filters/effect-reference-repaint-composite-4.html [ Failure ]
-Bug(none) paint/invalidation/filters/effect-reference-repaint-composite-5.html [ Failure ]
-Bug(none) paint/invalidation/filters/effect-reference-repaint-composite-6.html [ Failure ]
-Bug(none) paint/invalidation/filters/effect-reference-repaint-gaussianblur-xonly.html [ Failure ]
-Bug(none) paint/invalidation/filters/effect-reference-repaint-gaussianblur-yonly.html [ Failure ]
-Bug(none) paint/invalidation/filters/effect-reference-repaint-gaussianblur.html [ Failure ]
-Bug(none) paint/invalidation/filters/effect-reference-repaint-lighting.html [ Failure ]
-Bug(none) paint/invalidation/filters/effect-reference-repaint-merge.html [ Failure ]
-Bug(none) paint/invalidation/filters/effect-reference-repaint-offset.html [ Failure ]
 Bug(none) paint/invalidation/reflection-invalidation-positioned-child.html [ Failure ]
 Bug(none) paint/invalidation/reflection-redraw.html [ Failure ]
+Bug(none) paint/invalidation/scroll-fixed-layer-with-reflection.html [ Failure ]
+Bug(none) paint/invalidation/scroll-fixed-reflected-layer.html [ Failure ]
+Bug(none) paint/invalidation/svg/filter-refresh.svg [ Failure ]
+Bug(none) paint/invalidation/svg/paintorder-filtered.svg [ Failure ]
 
 # Extra layer for fixed-position.
 Bug(none) paint/invalidation/absolute-position-changed.html [ Failure ]
@@ -1075,6 +1035,8 @@
 Bug(none) paint/invalidation/fixed-under-composited-fixed-scrolled.html [ Failure ]
 Bug(none) paint/invalidation/fixed-with-border-under-composited-absolute-scrolled.html [ Failure ]
 Bug(none) paint/invalidation/fixed.html [ Failure ]
+Bug(none) paint/invalidation/scroll-fixed-layer-with-no-visible-content.html [ Failure ]
+Bug(none) paint/invalidation/scroll-in-fixed-layer.html [ Failure ]
 
 # Extra layers for SVG elements. Some have extra invalidations.
 Bug(none) paint/invalidation/svg/absolute-sized-content-with-resources.xhtml [ Failure ]
@@ -1084,20 +1046,33 @@
 Bug(none) paint/invalidation/svg/js-update-bounce.svg [ Failure ]
 Bug(none) paint/invalidation/svg/mask-child-changes.svg [ Failure ]
 Bug(none) paint/invalidation/svg/mask-invalidation.svg [ Failure ]
+Bug(none) paint/invalidation/svg/repaint-in-scrolled-view.html [ Failure ]
 Bug(none) paint/invalidation/svg/text-mask-update.svg [ Failure ]
+Bug(none) paint/invalidation/svg/text-xy-updates-SVGList.xhtml [ Failure ]
 
 # Other extra layers.
+Bug(none) compositing/composite-scrollable-fixed-position-when-descendants-composite.html [ Failure ]
+Bug(none) paint/invalidation/abspos-shift-image-incorrect-repaint.html [ Failure ]
+Bug(none) paint/invalidation/animated-gif-transformed-offscreen.html [ Failure ]
+Bug(none) paint/invalidation/canvas-composite-repaint-by-all-imagesource.html [ Failure ]
 Bug(none) paint/invalidation/clipped-overflow-visible-subtree.html [ Failure ]
 Bug(none) paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll.html [ Failure ]
 Bug(none) paint/invalidation/compositing/should-not-repaint-scrolling-contents-outline-change.html [ Failure ]
 Bug(none) paint/invalidation/create-layer-repaint.html [ Failure ]
 Bug(none) paint/invalidation/filter-on-html-element-with-fixed-position-child.html [ Failure ]
+Bug(none) paint/invalidation/full-viewport-repaint-for-background-attachment-fixed.html [ Failure ]
+Bug(none) paint/invalidation/inline-style-change-in-scrolled-view.html [ Failure ]
 Bug(none) paint/invalidation/invalidate-caret-in-composited-scrolling-container.html [ Failure ]
 Bug(none) paint/invalidation/invalidate-caret-in-non-composited-scrolling-container.html [ Failure ]
 Bug(none) paint/invalidation/mix-blend-mode-separate-stacking-context.html [ Failure ]
+Bug(none) paint/invalidation/nested-fixed-iframe-scrolled.html [ Failure ]
+Bug(none) paint/invalidation/overflow-scroll-body-appear.html [ Failure ]
 Bug(none) paint/invalidation/paint-invalidation-with-opacity.html [ Failure ]
+Bug(none) paint/invalidation/repaint-overlay/layers.html [ Failure ]
 Bug(none) paint/invalidation/svg/deep-nested-embedded-svg-size-changes-no-layout-triggers-1.html [ Failure ]
 Bug(none) paint/invalidation/svg/deep-nested-embedded-svg-size-changes-no-layout-triggers-2.html [ Failure ]
+Bug(none) paint/invalidation/svg/animated-svg-as-image-transformed-offscreen.html [ Failure ]
+Bug(none) paint/invalidation/window-resize-vertical-writing-mode.html [ Failure ]
 
 # Wrong invalidation/painting/rasterization for multicol. Different layer tree.
 crbug.com/648274 fast/text/letter-spacing-leading-and-trailing.html [ Failure ]
@@ -1113,6 +1088,7 @@
 crbug.com/648274 paint/invalidation/multicol-with-text.html [ Failure ]
 
 # Different layer tree about squashing.
+crbug.com/757977 compositing/squashing/squashed-layer-loses-graphicslayer.html [ Failure ]
 crbug.com/757977 paint/invalidation/compositing/invalidate-when-leaving-squashed-layer.html [ Failure ]
 crbug.com/757977 paint/invalidation/compositing/invalidation-for-subpixel-offset-of-squashed-layer.html [ Failure ]
 crbug.com/757977 paint/invalidation/compositing/remove-squashed-layer-plus-move.html [ Failure ]
@@ -1139,31 +1115,6 @@
 Bug(none) paint/invalidation/compositing/should-not-repaint-composited-descendants.html [ Failure ]
 Bug(none) paint/invalidation/filter-repaint-accelerated-child-with-filter-child.html [ Failure ]
 
-# Negative layer position because of negative content position. Extra invalidation caused by layer position change.
-crbug.com/757090 paint/invalidation/abspos-shift-image-incorrect-repaint.html [ Failure ]
-crbug.com/757090 paint/invalidation/inline-focus.html [ Failure ]
-crbug.com/757090 paint/invalidation/justify-items-overflow-change.html [ Failure ]
-crbug.com/757090 paint/invalidation/justify-self-overflow-change.html [ Failure ]
-crbug.com/757090 paint/invalidation/offset-change-wrong-invalidation-with-float.html [ Failure ]
-crbug.com/757090 paint/invalidation/outline-add-repaint.html [ Failure ]
-crbug.com/757090 paint/invalidation/outline-change-repaint.html [ Failure ]
-crbug.com/757090 paint/invalidation/overflow-flipped-writing-mode-block.html [ Failure ]
-crbug.com/757090 paint/invalidation/overflow-flipped-writing-mode-table.html [ Failure ]
-crbug.com/757090 paint/invalidation/reflection-invalidation-after-display.html [ Failure ]
-crbug.com/757090 paint/invalidation/repaint-subrect-grid.html [ Failure ]
-crbug.com/757090 paint/invalidation/selection/invalidation-rect-includes-newline-for-rtl.html [ Failure ]
-crbug.com/757090 paint/invalidation/svg/add-outline-property-on-root.html [ Failure ]
-crbug.com/757090 paint/invalidation/svg/remove-outline-property-on-root.html [ Failure ]
-crbug.com/757090 paint/invalidation/transform-replaced-shadows.html [ Failure ]
-crbug.com/757090 paint/invalidation/transform-rotate-and-remove.html [ Failure ]
-crbug.com/757090 paint/invalidation/window-resize-vertical-writing-mode.html [ Failure ]
-
-# Need to support partial invalidation for some changes.
-crbug.com/732612 paint/invalidation/canvas-composite-repaint-by-all-imagesource.html [ Failure ]
-crbug.com/732612 paint/invalidation/canvas-putImageData.html [ Failure ]
-crbug.com/732612 paint/invalidation/japanese-rl-selection-repaint.html [ Failure ]
-crbug.com/732612 paint/invalidation/repaint-across-writing-mode-boundary.html [ Failure ]
-
 # Raster invalidation for background on scrolling contents layer.
 crbug.com/732611 paint/invalidation/overflow-scroll-local-background-text-color-change.html [ Failure ]
 
@@ -1177,7 +1128,21 @@
 crbug.com/707444 svg/custom/mask-inside-defs.svg [ Failure ]
 
 # Subpixel differences
+Bug(none) compositing/composited-scaled-child-with-border-radius-parent-clip.html [ Failure ]
+Bug(none) compositing/composited-translated-child-with-border-radius-parent-clip.html [ Failure ]
+Bug(none) compositing/overflow/border-radius-on-grandparent-composited-grandchild.html [ Failure ]
+Bug(none) compositing/overflow/border-radius-on-two-ancestors-composited-grandchild.html [ Failure ]
+Bug(none) compositing/overflow/border-radius-styles-with-composited-child.html [ Failure ]
+Bug(none) compositing/overflow/grandchild-composited-with-border-radius-ancestor.html [ Failure ]
+Bug(none) compositing/overflow/grandchild-with-border-radius-ancestor.html [ Failure ]
+Bug(none) compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped.html [ Failure ]
+Bug(none) compositing/overflow/siblings-composited-with-border-radius-ancestor.html [ Failure ]
+Bug(none) compositing/overflow/siblings-with-border-radius-ancestor.html [ Failure ]
 Bug(none) fast/backgrounds/animated-svg-as-mask.html [ Failure ]
+Bug(none) fast/canvas/canvas-composite-video-shadow.html [ Failure ]
+Bug(none) fast/scrolling/fractional-scroll-offset-fixed-position-non-composited.html [ Failure ]
+Bug(none) fast/text/international/vertical-text-glyph-test.html [ Failure ]
+Bug(none) fast/writing-mode/border-radius-clipping-vertical-lr.html [ Failure ]
 Bug(none) images/color-profile-mask-image-svg.html [ Failure ]
 Bug(none) paint/printing/print-box-shadow.html [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/masking-mask-01-b.svg [ Failure ]
@@ -1229,10 +1194,6 @@
 Bug(none) svg/carto.net/scrollbar.svg [ Failure ]
 Bug(none) svg/carto.net/textbox.svg [ Failure ]
 Bug(none) svg/custom/bug45331.svg [ Failure ]
-Bug(none) svg/custom/clip-path-referencing-use.svg [ Failure ]
-Bug(none) svg/custom/clip-path-with-css-transform-1.svg [ Failure ]
-Bug(none) svg/custom/clip-path-with-css-transform-2.svg [ Failure ]
-Bug(none) svg/custom/clip-path-with-transform.svg [ Failure ]
 Bug(none) svg/custom/container-opacity-clip-viewBox.svg [ Failure ]
 Bug(none) svg/custom/cross-referenced-resources.html [ Failure Crash ]
 Bug(none) svg/custom/embedding-external-svgs.xhtml [ Failure ]
@@ -1243,13 +1204,10 @@
 Bug(none) svg/custom/image-with-preserveAspectRatio-none.html [ Failure ]
 Bug(none) svg/custom/image-with-transform-clip-filter.svg [ Failure ]
 Bug(none) svg/custom/junk-data.svg [ Failure ]
-Bug(none) svg/custom/load-non-wellformed.svg [ Failure ]
 Bug(none) svg/custom/masking-clipping-hidpi.svg [ Failure Crash ]
 Bug(none) svg/custom/missing-xlink.svg [ Failure ]
 Bug(none) svg/custom/object-sizing-no-width-height.xhtml [ Failure ]
-Bug(none) svg/custom/path-bad-data.svg [ Failure ]
 Bug(none) svg/custom/preserve-aspect-ratio-syntax.svg [ Failure ]
-Bug(none) svg/custom/recursive-clippath.svg [ Failure ]
 Bug(none) svg/custom/svg-overflow-types.svg [ Failure ]
 Bug(none) svg/custom/text-clip.svg [ Failure ]
 Bug(none) svg/custom/transformed-outlines.svg [ Failure ]
@@ -1258,13 +1216,11 @@
 Bug(none) svg/custom/use-font-face-crash.svg [ Failure ]
 Bug(none) svg/custom/use-modify-container-in-target.svg [ Failure ]
 Bug(none) svg/custom/use-modify-target-container.svg [ Failure ]
-Bug(none) svg/custom/use-on-clip-path-with-transformation.svg [ Failure ]
 Bug(none) svg/custom/use-on-g-containing-use.svg [ Failure ]
 Bug(none) svg/custom/use-on-g.svg [ Failure ]
 Bug(none) svg/custom/use-on-use.svg [ Failure ]
 Bug(none) svg/custom/use-transform.svg [ Failure ]
 Bug(none) svg/custom/viewbox-syntax.svg [ Failure ]
-Bug(none) svg/custom/viewport-clippath-invalidation.html [ Failure ]
 Bug(none) svg/custom/visibility-override-clip.svg [ Failure ]
 Bug(none) svg/custom/visibility-override-mask.svg [ Failure Crash ]
 Bug(none) svg/custom/width-full-percentage.svg [ Failure ]
@@ -1281,7 +1237,6 @@
 Bug(none) svg/filters/svg-filter-child-box-reflect.html [ Failure Crash ]
 Bug(none) svg/filters/svg-filter-root-box-reflect.html [ Failure Crash ]
 Bug(none) svg/foreignObject/clip.html [ Failure ]
-Bug(none) svg/hixie/error/012.xml [ Failure ]
 Bug(none) svg/hixie/mixed/006.xml [ Failure ]
 Bug(none) svg/hixie/mixed/009.xml [ Failure ]
 Bug(none) svg/hixie/mixed/011.xml [ Failure ]
@@ -1295,7 +1250,6 @@
 Bug(none) svg/overflow/overflow-on-outermost-svg-element-ignore-attribute-3.svg [ Failure ]
 Bug(none) svg/overflow/overflow-on-outermost-svg-element-in-xhtml-defaults.xhtml [ Failure ]
 Bug(none) svg/text/foreignObject-text-clipping-bug.xml [ Failure ]
-Bug(none) svg/transforms/svg-css-transforms-clip-path.xhtml [ Failure ]
 Bug(none) svg/transforms/text-with-mask-with-svg-transform.svg [ Failure ]
 Bug(none) svg/transforms/text-with-pattern-inside-transformed-html.xhtml [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/coords-viewattr-01-b.svg [ Failure ]
@@ -1327,21 +1281,15 @@
 Bug(none) transforms/transformed-caret.html [ Pass Failure ]
 Bug(none) transforms/transformed-focused-text-input.html [ Failure ]
 Bug(none) compositing/geometry/transformed-abs-position-inside-composited.html [ Failure ]
+Bug(none) fast/table/border-collapsing/001-vertical.html [ Failure ]
+Bug(none) fast/table/border-collapsing/001.html [ Failure ]
 
 # crashes due to unexpected calls to GeometryMapper (inverted scroll clip)
 crbug.com/768102 compositing/overflow/reflected-overlay-scrollbars-should-appear-without-compositing.html [ Crash ]
 crbug.com/768102 compositing/overflow/reflected-overlay-scrollbars-should-respect-ancestor-clip.html [ Crash ]
 crbug.com/768102 compositing/overflow/reparented-overlay-scrollbars-should-respect-ancestor-clip.html [ Crash ]
 
-crbug.com/644358 compositing/gestures/gesture-tapHighlight-2-iframe-scrolled-outer-late-composite.html [ Failure ]
-crbug.com/644358 compositing/iframes/connect-compositing-iframe-delayed.html [ Failure ]
-crbug.com/644358 compositing/iframes/connect-compositing-iframe.html [ Failure ]
-crbug.com/644358 compositing/iframes/enter-compositing-iframe.html [ Failure ]
-crbug.com/644358 compositing/squashing/squashed-layer-loses-graphicslayer.html [ Failure ]
-crbug.com/644358 fast/canvas/canvas-composite-video-shadow.html [ Failure ]
-crbug.com/644358 fast/canvas/imagebitmap/transferFromImageBitmap-no-alpha.html [ Failure ]
 crbug.com/644358 fast/css3-text/css3-text-decoration/repaint/repaint-text-decoration-style.html [ Failure ]
-crbug.com/644358 paint/invalidation/svg/image-with-clip-path.svg [ Failure ]
 crbug.com/644358 paint/invalidation/video-paint-invalidation.html [ Crash ]
 
 Bug(none) compositing/layer-creation/main-thread-scrolling-for-non-composited-fixed-position-if-overflow-hidden.html [ Failure ]
@@ -1450,7 +1398,7 @@
 
 Bug(none) css3/blending/background-blend-mode-overlapping-accelerated-elements.html [ Failure ]
 Bug(none) css3/blending/mix-blend-mode-simple-text.html [ Failure Timeout ]
-Bug(none) css3/blending/mix-blend-mode-simple.html [ Failure ]
+Bug(none) css3/blending/mix-blend-mode-simple.html [ Failure Timeout ]
 Bug(none) css3/blending/effect-background-blend-mode-stacking.html [ Failure Crash ]
 
 Bug(none) svg/custom/marker-zero-length-linecaps.svg [ Failure ]
@@ -1474,7 +1422,7 @@
 crbug.com/589265 css3/blending/effect-background-blend-mode.html [ Failure ]
 crbug.com/589265 css3/blending/mix-blend-mode-isolated-group-1.html [ Failure Timeout ]
 crbug.com/589265 css3/blending/mix-blend-mode-isolated-group-2.html [ Failure Timeout ]
-crbug.com/589265 css3/blending/mix-blend-mode-isolated-group-3.html [ Failure ]
+crbug.com/589265 css3/blending/mix-blend-mode-isolated-group-3.html [ Failure Timeout ]
 crbug.com/589265 css3/blending/svg-blend-exclusion.html [ Failure ]
 crbug.com/589265 css3/blending/svg-blend-screen.html [ Failure ]
 crbug.com/589265 fast/backgrounds/size/contain-and-cover-zoomed.html [ Failure ]
@@ -1518,10 +1466,6 @@
 crbug.com/589265 fast/css/nested-rounded-corners.html [ Failure ]
 crbug.com/589265 paint/overflow/composited-rounded-clip-floating-element.html [ Failure ]
 
-# Failures due to frame scrollbars not painted
-crbug.com/589279 css3/blending/background-blend-mode-data-uri-svg-image.html [ Failure ]
-crbug.com/589279 fast/writing-mode/border-radius-clipping-vertical-lr.html [ Failure ]
-
 # Notes about rebaselined tests:
 #
 # Rebaselined for small pixel differences.
@@ -1759,6 +1703,7 @@
 Bug(none) fast/text-autosizing/tables/single-percent-width-cell-lots-of-text.html [ Failure ]
 Bug(none) fast/text-autosizing/tables/table-with-inline-block.html [ Failure ]
 Bug(none) paint/invalidation/svg/animated-path-inside-transformed-html.xhtml [ Failure ]
+Bug(none) paint/overflow/fixed-background-scroll-in-frame.html [ Pass Failure ]
 Bug(none) paint/overflow/fixed-background-scroll-window.html [ Failure ]
 Bug(none) svg/custom/getscreenctm-in-scrollable-div-area-nested.xhtml [ Failure ]
 Bug(none) svg/custom/getscreenctm-in-scrollable-div-area.xhtml [ Failure ]
@@ -1778,6 +1723,9 @@
 crbug.com/755274 compositing/overflow/fractional-sized-scrolling-layer.html [ Failure ]
 
 # Different layer tree about scrolling layer. Some may also have wrong invalidations.
+crbug.com/738613 compositing/iframes/connect-compositing-iframe-delayed.html [ Failure ]
+crbug.com/738613 compositing/iframes/connect-compositing-iframe.html [ Failure ]
+crbug.com/738613 compositing/iframes/enter-compositing-iframe.html [ Failure ]
 crbug.com/738613 paint/invalidation/caret-with-composited-scroll.html [ Failure ]
 crbug.com/738613 paint/invalidation/composited-overflow-with-borderbox-background.html [ Failure ]
 crbug.com/738613 paint/invalidation/composited-overflow-with-local-background.html [ Failure ]
@@ -1796,6 +1744,14 @@
 crbug.com/738613 paint/invalidation/scroll-stacking-context-backface-visiblity-leaves-traces.html [ Failure ]
 crbug.com/738613 paint/invalidation/selection/selection-within-composited-scroller.html [ Failure ]
 
+# Sticky positioned objects are not invalidated when scroll offset changes.
+crbug.com/762098 compositing/overflow/composited-nested-sticky-table.html [ Failure ]
+crbug.com/762098 compositing/overflow/mixed-composited-nested-sticky-overflow-scroller.html [ Failure ]
+crbug.com/762098 compositing/overflow/composited-nested-sticky-left.html [ Failure ]
+crbug.com/762098 compositing/overflow/composited-nested-sticky-deep.html [ Failure ]
+crbug.com/762098 compositing/overflow/composited-nested-sticky-top.html [ Failure ]
+crbug.com/762098 compositing/overflow/non-composited-sticky-element-in-main-thread-scrolled-composited-ancestor.html [ Failure ]
+
 # Subsequence under-invalidation of scroller related to ScrollHitTest.
 crbug.com/738613 compositing/overflow/overflow-scroll-with-pointer-events-toggle.html [ Failure Crash ]
 
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process b/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process
index b9a1221..bd42de5 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process
@@ -1,6 +1,13 @@
 # These tests currently fail when they run with --site-per-process.
 # See https://crbug.com/477150.
 
+# https://crbug.com/769502: PlzNavigate-related, not-yet-investigated timeout.
+crbug.com/769502 fast/loader/recursive-before-unload-crash.html [ Timeout ]
+
+# https://crbug.com/769508: PlzNavigate-related, not-yet-investigated failures.
+crbug.com/769508 fast/css/acid2.html [ Failure ]
+crbug.com/769508 fast/css/acid2-pixel.html [ Failure ]
+
 # https://crbug.com/765779: unique name trouble with PlzNavigate
 crbug.com/765779 http/tests/loading/bad-server-subframe.html [ Failure ]
 crbug.com/765779 virtual/mojo-loading/http/tests/loading/bad-server-subframe.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/MSANExpectations b/third_party/WebKit/LayoutTests/MSANExpectations
index fc684f5..d7f1b2a 100644
--- a/third_party/WebKit/LayoutTests/MSANExpectations
+++ b/third_party/WebKit/LayoutTests/MSANExpectations
@@ -53,6 +53,8 @@
 # These tests use OpenGl, which crashes on MSAN builds due to missing instrumentation
 crbug.com/555703 [ Linux ] virtual/media-gpu-accelerated [ Skip ]
 
+crbug.com/769729 [ Linux ] paint/invalidation/video-paint-invalidation.html [ Crash ]
+
 # These tests are just a tad bit too slow on MSAN bots and time out. Setting
 # them as "Slow" doesn't seem to help the problem (see discussion on bug), so
 # marking them as "Timeout" while crbug.com/729136 is worked out.
diff --git a/third_party/WebKit/LayoutTests/SlowTests b/third_party/WebKit/LayoutTests/SlowTests
index 934ace0..dd3efc8b 100644
--- a/third_party/WebKit/LayoutTests/SlowTests
+++ b/third_party/WebKit/LayoutTests/SlowTests
@@ -375,70 +375,75 @@
 crbug.com/646528 compositing/lots-of-img-layers-with-opacity.html [ Slow ]
 
 # SwiftShader slow tests
-crbug.com/726075 [ Win ] animations/svg/animated-filter-svg-element.html [ Slow ]
-crbug.com/726075 [ Win ] compositing/masks/mask-with-added-filters.html [ Slow ]
-crbug.com/726075 [ Win ] css3/filters/effect-all-on-background-hw.html [ Slow ]
-crbug.com/726075 [ Win ] css3/filters/effect-blur-hw.html [ Slow ]
-crbug.com/726075 [ Win ] css3/filters/effect-brightness-clamping-hw.html [ Slow ]
-crbug.com/726075 [ Win ] css3/filters/effect-combined-hw.html [ Slow ]
-crbug.com/726075 [ Win ] css3/filters/effect-drop-shadow-hw.html [ Slow ]
-crbug.com/726075 [ Win ] css3/filters/effect-reference-colorspace-hw.html [ Slow ]
-crbug.com/726075 [ Win ] css3/filters/effect-reference-hw.html [ Slow ]
-crbug.com/726075 [ Win ] css3/filters/effect-reference-ordering-hw.html [ Slow ]
-crbug.com/726075 [ Win ] css3/filters/effect-reference-subregion-hw.html [ Slow ]
-crbug.com/726075 [ Win ] css3/filters/effect-reference-zoom-hw.html [ Slow ]
-crbug.com/726075 [ Win ] css3/filters/filter-change-repaint.html [ Slow ]
-crbug.com/726075 [ Win ] css3/filters/filter-repaint-composited-fallback-crash.html [ Slow ]
-crbug.com/726075 [ Win ] css3/filters/filter-repaint-composited-fallback.html [ Slow ]
-crbug.com/726075 [ Win ] images/color-profile-layer-filter.html [ Slow ]
-crbug.com/726075 [ Win ] paint/invalidation/filter-repaint-accelerated-on-accelerated-filter.html [ Slow ]
-crbug.com/726075 [ Win ] virtual/exotic-color-space/images/color-profile-layer-filter.html [ Slow ]
-crbug.com/726075 [ Win ] virtual/gpu-rasterization/images/color-profile-image-filter-all.html [ Slow ]
-crbug.com/726075 [ Win ] virtual/gpu-rasterization/images/color-profile-mask-image-svg.html [ Slow ]
-crbug.com/726075 [ Win ] virtual/gpu/fast/canvas/OffscreenCanvas-filter-in-worker.html [ Slow ]
-crbug.com/726075 [ Win ] virtual/gpu/fast/canvas/OffscreenCanvas-filter.html [ Slow ]
-crbug.com/726075 [ Win ] virtual/gpu/fast/canvas/canvas-blending-color-over-pattern.html [ Slow ]
-crbug.com/726075 [ Win ] virtual/gpu/fast/canvas/canvas-blending-gradient-over-image.html [ Slow ]
-crbug.com/726075 [ Win ] virtual/gpu/fast/canvas/canvas-blending-gradient-over-pattern.html [ Slow ]
-crbug.com/726075 [ Win ] virtual/gpu/fast/canvas/canvas-blending-gradient-over-gradient.html [ Slow ]
-crbug.com/726075 [ Win ] virtual/gpu/fast/canvas/canvas-blending-pattern-over-gradient.html [ Slow ]
-crbug.com/726075 [ Win ] virtual/gpu/fast/canvas/canvas-blending-pattern-over-image.html [ Slow ]
-crbug.com/726075 [ Win ] virtual/gpu/fast/canvas/canvas-blending-pattern-over-pattern.html [ Slow ]
-crbug.com/726075 [ Win ] virtual/gpu/fast/canvas/canvas-composite-shadow.html [ Slow ]
-crbug.com/726075 [ Win ] virtual/gpu/fast/canvas/canvas-composite-video-shadow.html [ Slow ]
-crbug.com/726075 [ Win ] virtual/gpu/fast/canvas/canvas-fillPath-alpha-shadow.html [ Slow ]
-crbug.com/726075 [ Win ] virtual/gpu/fast/canvas/canvas-fillPath-gradient-shadow.html [ Slow ]
-crbug.com/726075 [ Win ] virtual/gpu/fast/canvas/canvas-fillPath-pattern-shadow.html [ Slow ]
-crbug.com/726075 [ Win ] virtual/gpu/fast/canvas/canvas-filter-origin-clean.html [ Slow ]
-crbug.com/726075 [ Win ] virtual/gpu/fast/canvas/canvas-filter-removed.html [ Slow ]
-crbug.com/726075 [ Win ] virtual/gpu/fast/canvas/canvas-scale-strokePath-shadow.html [ Slow ]
-crbug.com/726075 [ Win ] virtual/gpu/fast/canvas/canvas-shadow-source-in.html [ Slow ]
-crbug.com/726075 [ Win ] virtual/gpu/fast/canvas/canvas-strokePath-alpha-shadow.html [ Slow ]
+crbug.com/726075 [ Win Linux ] animations/svg/animated-filter-svg-element.html [ Slow ]
+crbug.com/726075 [ Win Linux ] compositing/culling/filter-occlusion-blur.html [ Slow ]
+crbug.com/726075 [ Win Linux ] compositing/masks/mask-with-added-filters.html [ Slow ]
+crbug.com/726075 [ Win Linux ] css3/blending/mix-blend-mode-with-filters.html [ Slow ]
+crbug.com/726075 [ Win Linux ] css3/filters/effect-all-on-background-hw.html [ Slow ]
+crbug.com/726075 [ Win Linux ] css3/filters/effect-blur-hw.html [ Slow ]
+crbug.com/726075 [ Win Linux ] css3/filters/effect-brightness-clamping-hw.html [ Slow ]
+crbug.com/726075 [ Win Linux ] css3/filters/effect-combined-hw.html [ Slow ]
+crbug.com/726075 [ Win Linux ] css3/filters/effect-drop-shadow-hw.html [ Slow ]
+crbug.com/726075 [ Win Linux ] css3/filters/effect-reference-colorspace-hw.html [ Slow ]
+crbug.com/726075 [ Win Linux ] css3/filters/effect-reference-hw.html [ Slow ]
+crbug.com/726075 [ Win Linux ] css3/filters/effect-reference-ordering-hw.html [ Slow ]
+crbug.com/726075 [ Win Linux ] css3/filters/effect-reference-subregion-hw.html [ Slow ]
+crbug.com/726075 [ Win Linux ] css3/filters/effect-reference-zoom-hw.html [ Slow ]
+crbug.com/726075 [ Win Linux ] css3/filters/filter-change-repaint.html [ Slow ]
+crbug.com/726075 [ Win Linux ] css3/filters/filter-repaint-composited-fallback-crash.html [ Slow ]
+crbug.com/726075 [ Win Linux ] css3/filters/filter-repaint-composited-fallback.html [ Slow ]
+crbug.com/726075 [ Win Linux ] images/color-profile-layer-filter.html [ Slow ]
+crbug.com/726075 [ Win Linux ] paint/invalidation/filter-repaint-accelerated-child-with-filter-child.html [ Slow ]
+crbug.com/726075 [ Win Linux ] paint/invalidation/filter-repaint-accelerated-on-accelerated-filter.html [ Slow ]
+crbug.com/726075 [ Win Linux ] paint/invalidation/filter-repaint-on-accelerated-layer.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/exotic-color-space/images/color-profile-layer-filter.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu-rasterization/images/color-profile-mask-image-svg.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu-rasterization/images/color-profile-image-filter-all.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/OffscreenCanvas-filter-in-worker.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/OffscreenCanvas-filter.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-blending-clipping.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-blending-color-over-color.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-blending-color-over-image.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-blending-color-over-gradient.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-blending-color-over-pattern.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-blending-fill-style.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-blending-global-alpha.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-blending-gradient-over-color.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-blending-gradient-over-image.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-blending-gradient-over-pattern.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-blending-gradient-over-gradient.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-blending-image-over-color.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-blending-image-over-gradient.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-blending-image-over-image.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-blending-image-over-pattern.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-blending-pattern-over-color.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-blending-pattern-over-gradient.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-blending-pattern-over-image.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-blending-pattern-over-pattern.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-blending-shadow.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-blending-text.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-blending-transforms.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-composite-transformclip.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-composite-shadow.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-composite-video-shadow.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-fillPath-alpha-shadow.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-fillPath-gradient-shadow.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-fillPath-pattern-shadow.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-filter-origin-clean.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-filter-modified-save-restore.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-filter-modified.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-filter-removed.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-scale-drawImage-shadow.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-scale-strokePath-shadow.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-shadow-source-in.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/gpu/fast/canvas/canvas-strokePath-alpha-shadow.html [ Slow ]
+crbug.com/726075 [ Win Linux ] virtual/threaded/animations/svg/animated-filter-svg-element.html [ Slow ]
 
-crbug.com/726075 [ Win Debug ] compositing/culling/filter-occlusion-blur.html [ Slow ]
-crbug.com/726075 [ Win Debug ] css3/blending/mix-blend-mode-with-filters.html [ Slow ]
-crbug.com/726075 [ Win Debug ] paint/invalidation/filter-repaint-accelerated-child-with-filter-child.html [ Slow ]
-crbug.com/726075 [ Win Debug ] paint/invalidation/filter-repaint-on-accelerated-layer.html [ Slow ]
-crbug.com/726075 [ Win Debug ] virtual/gpu/fast/canvas/canvas-blending-clipping.html [ Slow ]
-crbug.com/726075 [ Win Debug ] virtual/gpu/fast/canvas/canvas-blending-color-over-color.html [ Slow ]
-crbug.com/726075 [ Win Debug ] virtual/gpu/fast/canvas/canvas-blending-color-over-gradient.html [ Slow ]
-crbug.com/726075 [ Win Debug ] virtual/gpu/fast/canvas/canvas-blending-color-over-image.html [ Slow ]
-crbug.com/726075 [ Win Debug ] virtual/gpu/fast/canvas/canvas-blending-fill-style.html [ Slow ]
-crbug.com/726075 [ Win Debug ] virtual/gpu/fast/canvas/canvas-blending-global-alpha.html [ Slow ]
-crbug.com/726075 [ Win Debug ] virtual/gpu/fast/canvas/canvas-blending-gradient-over-color.html [ Slow ]
-crbug.com/726075 [ Win Debug ] virtual/gpu/fast/canvas/canvas-blending-image-over-color.html [ Slow ]
-crbug.com/726075 [ Win Debug ] virtual/gpu/fast/canvas/canvas-blending-image-over-gradient.html [ Slow ]
-crbug.com/726075 [ Win Debug ] virtual/gpu/fast/canvas/canvas-blending-image-over-image.html [ Slow ]
-crbug.com/726075 [ Win Debug ] virtual/gpu/fast/canvas/canvas-blending-image-over-pattern.html [ Slow ]
-crbug.com/726075 [ Win Debug ] virtual/gpu/fast/canvas/canvas-blending-pattern-over-color.html [ Slow ]
-crbug.com/726075 [ Win Debug ] virtual/gpu/fast/canvas/canvas-blending-shadow.html [ Slow ]
-crbug.com/726075 [ Win Debug ] virtual/gpu/fast/canvas/canvas-blending-text.html [ Slow ]
-crbug.com/726075 [ Win Debug ] virtual/gpu/fast/canvas/canvas-blending-transforms.html [ Slow ]
-crbug.com/726075 [ Win Debug ] virtual/gpu/fast/canvas/canvas-composite-transformclip.html [ Slow ]
-crbug.com/726075 [ Win Debug ] virtual/gpu/fast/canvas/canvas-filter-modified-save-restore.html [ Slow ]
-crbug.com/726075 [ Win Debug ] virtual/gpu/fast/canvas/canvas-filter-modified.html [ Slow ]
-crbug.com/726075 [ Win Debug ] virtual/gpu/fast/canvas/canvas-scale-drawImage-shadow.html [ Slow ]
-crbug.com/726075 [ Win Debug ] virtual/threaded/animations/svg/animated-filter-svg-element.html [ Slow ]
+crbug.com/726075 [ Linux ] media/color-profile-video-seek-filter.html [ Slow ]
+crbug.com/726075 [ Linux ] shapedetection/detection-HTMLVideoElement.html [ Slow ]
+crbug.com/726075 [ Linux ] virtual/gpu/fast/canvas/canvas-strokeRect-alpha-shadow.html [ Slow ]
+
+crbug.com/726075 [ Linux Debug ] virtual/gpu/fast/canvas/canvas-drawImage-live-video.html [ Slow ]
 
 # IDB Observer tests require multiple browsing contexts/workers interacting with
 # IndexedDB, which can be slow.
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 1bcc19e..4020221 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -92,13 +92,14 @@
 # The failure in the next line is due to virtual/gpu bots using osmesa
 # Under osmesa, skia's filter quality doesn't work correctly. This test is expected to pass
 # when we swith to swiftshader.
-crbug.com/549742 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-drawImage-video-imageSmoothingEnabled.html [ Failure ]
+crbug.com/549742 [ Mac ] virtual/gpu/fast/canvas/canvas-drawImage-video-imageSmoothingEnabled.html [ Failure ]
 
 # SwiftShader Failures
-crbug.com/726075 [ Win ] compositing/3d-cube.html [ Failure ]
+crbug.com/726075 [ Win Linux ] compositing/3d-cube.html [ Failure ]
 crbug.com/726075 [ Win ] virtual/gpu/fast/canvas/2d.fillText.gradient.html [ Failure ]
-crbug.com/726075 [ Win ] external/wpt/webvtt/rendering/cues-with-video/processing-model/dom_override_remove_cue_while_paused.html [ Failure ]
-crbug.com/726075 [ Win Debug ] virtual/exotic-color-space/images/color-profile-border-fade.html [ Failure ]
+crbug.com/726075 [ Win Linux ] external/wpt/webvtt/rendering/cues-with-video/processing-model/dom_override_remove_cue_while_paused.html [ Failure ]
+crbug.com/726075 [ Win Linux ] virtual/exotic-color-space/images/color-profile-border-fade.html [ Failure ]
+crbug.com/726075 [ Linux ] shapedetection/detection-HTMLVideoElement.html [ Timeout ]
 
 # Fails because the manual test hasn't been automated yet
 crbug.com/762054 external/wpt/cssom-view/scrollBoundaryBehavior-manual.html [ Skip ]
@@ -622,7 +623,7 @@
 crbug.com/521858 [ Win7 ] virtual/mojo-loading/http/tests/security/media-element-audio-source-node-same-origin.html [ Failure Pass ]
 crbug.com/521853 [ Win ] http/tests/devtools/search/sources-search-scope.html [ Failure Pass ]
 crbug.com/520170 fast/dom/timer-throttling-hidden-page.html [ Failure Pass ]
-crbug.com/652536 fast/events/mouse-cursor-change-after-image-load.html [ Failure Pass ]
+crbug.com/652536 fast/events/mouse-cursor-change-after-image-load.html [ Failure Pass Crash ]
 crbug.com/520188 [ Win ] http/tests/local/fileapi/file-last-modified-after-delete.html [ Failure Pass ]
 crbug.com/520188 [ Win ] virtual/mojo-loading/http/tests/local/fileapi/file-last-modified-after-delete.html [ Failure Pass ]
 crbug.com/520611 [ Debug ] fast/filesystem/workers/file-writer-events-shared-worker.html [ Failure Pass ]
@@ -666,7 +667,7 @@
 crbug.com/326139 crbug.com/390125 media/video-frame-accurate-seek.html [ Failure Pass ]
 crbug.com/248938 virtual/threaded/animations/stability/animation-iteration-event-destroy-renderer.html [ Pass Timeout ]
 crbug.com/248938 virtual/threaded/animations/dynamic-stylesheet-loading.html [ Pass Failure Timeout ]
-crbug.com/248938 [ Win7 Debug ] virtual/threaded/animations/display-none-terminates-animation.html [ Pass Failure ]
+crbug.com/248938 [ Linux Win7 Debug ] virtual/threaded/animations/display-none-terminates-animation.html [ Pass Failure ]
 crbug.com/421283 html/marquee/marquee-scrollamount.html [ Pass Failure ]
 
 # TODO(oshima): Mac Android are currently not supported.
@@ -1065,6 +1066,7 @@
 crbug.com/377696 printing/width-overflow.html [ Skip ]
 
 crbug.com/769323 [ Mac Debug ] media/controls/captions-menu-always-visible.html [ Failure Pass ]
+crbug.com/769323 [ Mac Debug ] virtual/new-remote-playback-pipeline/media/controls/captions-menu-always-visible.html [ Failure Pass ]
 
 crbug.com/658305 css3/filters/buffer-offset.html [ Failure Pass ]
 crbug.com/658305 css3/filters/effect-all-on-background-hw.html [ Failure Pass ]
@@ -1532,7 +1534,7 @@
 
 crbug.com/610464 [ Linux Win7 Debug ] http/tests/devtools/components/throttler.html [ Failure Pass ]
 crbug.com/667560 [ Linux Win7 Debug ] virtual/mojo-loading/http/tests/devtools/components/throttler.html [ Failure Pass ]
-crbug.com/654477 [ Linux Mac Win7 ] paint/invalidation/video-paint-invalidation.html [ Failure ]
+crbug.com/654477 paint/invalidation/video-paint-invalidation.html [ Failure Crash ]
 crbug.com/654477 [ Win ] compositing/video/video-controls-layer-creation.html [ Pass Failure ]
 crbug.com/654477 fast/hidpi/video-controls-in-hidpi.html [ Failure ]
 crbug.com/654477 fast/layers/video-layer.html [ Failure ]
@@ -3430,7 +3432,7 @@
 crbug.com/755405 [ Android ] fast/selectors/061.html [ Failure ]
 crbug.com/755405 [ Android ] images/imagemap-focus-ring-outline-color-not-inherited-from-map.html [ Failure ]
 crbug.com/755405 [ Android ] paint/invalidation/focus-layers.html [ Failure ]
-crbug.com/755405 [ Android ] paint/invalidation/selected-replaced.html [ Failure ]
+crbug.com/755405 [ Android ] paint/invalidation/selected-replaced.html [ Failure Timeout ]
 crbug.com/755405 [ Android ] paint/invalidation/shadow-multiple.html [ Failure ]
 crbug.com/755405 [ Android ] svg/as-background-image/svg-width-100p-as-background.html [ Failure ]
 crbug.com/755405 [ Android ] svg/batik/text/textAnchor3.svg [ Failure ]
@@ -3611,7 +3613,7 @@
 crbug.com/757955 [ Win7 Debug ] storage/indexeddb/objectstore-cursor.html [ Pass Timeout ]
 crbug.com/757955 [ Win7 Debug ] http/tests/devtools/tracing/timeline-paint/layer-tree.html [ Pass Failure Timeout ]
 crbug.com/760546 [ Win7 Debug ] virtual/mojo-loading/http/tests/devtools/tracing/timeline-paint/layer-tree.html [ Pass Failure Timeout ]
-crbug.com/757955 [ Win7 Debug ] virtual/threaded/transitions/transition-end-event-transform.html [ Pass Failure ]
+crbug.com/757955 [ Linux Win7 Debug ] virtual/threaded/transitions/transition-end-event-transform.html [ Pass Failure ]
 
 # Tests flakely timing out on WebKit Linux Trusty dbg builder
 crbug.com/758109 [ Linux Debug ] fast/workers/worker-multi-startup.html [ Pass Timeout ]
@@ -3648,7 +3650,10 @@
 crbug.com/760543 [ Linux Release ] http/tests/devtools/tracing/timeline-paint/timeline-paint.html [ Pass Timeout ]
 crbug.com/760543 [ Linux Release ] virtual/mojo-loading/http/tests/devtools/tracing/timeline-paint/timeline-paint.html [ Pass Timeout ]
 
-crbug.com/761891 [ Win7 Debug ] virtual/threaded/animations/transition-and-animation-3.html [ Pass Failure Timeout ]
+crbug.com/761891 [ Win7 Linux Debug ] virtual/threaded/animations/transition-and-animation-3.html [ Pass Failure Timeout ]
+crbug.com/769879 [ Linux Debug ] virtual/threaded/transitions/transition-end-event-multiple-02.html [ Pass Failure ]
+crbug.com/769879 [ Linux Debug ] virtual/threaded/transitions/transition-end-event-unprefixed-02.html [ Pass Failure ]
+crbug.com/769879 [ Linux Debug ] virtual/threaded/transitions/transition-end-event-window.html [ Pass Failure ]
 crbug.com/769347 [ Mac ] fast/dom/inert/inert-node-is-uneditable.html [ Failure ]
 
 # Paint-timing tests timeout without threaded-compositing, so skip them.
@@ -3668,14 +3673,15 @@
 crbug.com/762486 [ Win7 Debug ] virtual/mojo-loading/http/tests/security/xss-DENIED-iframe-src-alias.html [ Pass Failure ]
 
 # Sheriff failures 2017-09-08
-crbug.com/763208 [ Win Linux Mac10.12 ] virtual/mojo-loading/http/tests/devtools/sources/debugger-ui/source-frame-count.html [ Pass Failure ]
+crbug.com/763208 http/tests/devtools/sources/debugger-ui/source-frame-count.html [ Pass Failure ]
+crbug.com/763208 virtual/mojo-loading/http/tests/devtools/sources/debugger-ui/source-frame-count.html [ Pass Failure ]
 
 crbug.com/763666 external/wpt/assumptions/ahem.html [ Failure ]
 crbug.com/763667 external/wpt/upgrade-insecure-requests/iframe-redirect-upgrade.https.html [ Timeout ]
 
 # Sheriff failures 2017-09-11
 crbug.com/763809 [ Win7 Debug ] fast/multicol/nested-very-tall-inside-short-crash.html [ Pass Failure Timeout ]
-crbug.com/763810 [ Win7 Debug ] virtual/threaded/transitions/transition-end-event-nested.html [ Pass Failure ]
+crbug.com/763810 [ Linux Win7 Debug ] virtual/threaded/transitions/transition-end-event-nested.html [ Pass Failure ]
 crbug.com/763975 [ Linux Mac Debug ] webaudio/internals/cycle-connection-gc.html [ Pass Failure ]
 
 # Sheriff failures 2017-09-12
@@ -3701,8 +3707,6 @@
 crbug.com/749965 [ Win7 Debug ] media/controls/controls-video-keynav.html [ Failure ]
 
 # Sheriff failures 2017-09-20
-# Flaky on chromium.webkit/WebKit Linux Trusty Leak
-crbug.com/766952 [ Win10 Linux ] http/tests/devtools/sources/debugger-ui/source-frame-count.html [ Pass Failure ]
 # Timeouts flakily on chromium.webkit/WebKit Win7 and WebKit Win10
 crbug.com/767012 [ Win7 Win10 ] virtual/mojo-loading/http/tests/devtools/startup/console-log-before-frame-navigation.html [ Pass Timeout ]
 # Fails flakily on chromium.mac/Mac10.12 Tests and WebKit Mac10.12.
@@ -3712,7 +3716,9 @@
 
 # Sheriff failures 2017-09-21
 crbug.com/767012 [ Win10 ] http/tests/devtools/startup/console-log-before-frame-navigation.html [ Pass Timeout ]
-crbug.com/767469 [ Linux Mac ] virtual/stable/http/tests/navigation/start-load-during-provisional-loader-detach.html [ Pass Failure ]
+crbug.com/767469 http/tests/navigation/start-load-during-provisional-loader-detach.html [ Pass Failure ]
+crbug.com/767469 virtual/stable/http/tests/navigation/start-load-during-provisional-loader-detach.html [ Pass Failure ]
+crbug.com/767469 virtual/mojo-loading/http/tests/navigation/start-load-during-provisional-loader-detach.html [ Pass Failure ]
 
 # Sheriff failures 2017-09-22
 crbug.com/767892 [ Win Linux Mac ] virtual/mojo-loading/http/tests/devtools/startup/database-open.html [ Pass Timeout ]
diff --git a/third_party/WebKit/LayoutTests/VirtualTestSuites b/third_party/WebKit/LayoutTests/VirtualTestSuites
index a6b99e3a..9a223bc 100644
--- a/third_party/WebKit/LayoutTests/VirtualTestSuites
+++ b/third_party/WebKit/LayoutTests/VirtualTestSuites
@@ -295,6 +295,11 @@
     "args": ["--force-device-scale-factor=2"]
   },
   {
+    "prefix": "scalefactor200",
+    "base": "http/tests/csspaint/hidpi",
+    "args": ["--force-device-scale-factor=2"]
+  },
+  {
     "prefix": "scalefactor150",
     "base": "fast/hidpi/static",
     "args": ["--force-device-scale-factor=1.5"]
diff --git a/third_party/WebKit/LayoutTests/accessibility/heading-level-expected.txt b/third_party/WebKit/LayoutTests/accessibility/heading-level-expected.txt
index 16cebea..f1f02ce2 100644
--- a/third_party/WebKit/LayoutTests/accessibility/heading-level-expected.txt
+++ b/third_party/WebKit/LayoutTests/accessibility/heading-level-expected.txt
@@ -21,8 +21,8 @@
 PASS: level is 4.
 PASS: level is 5.
 PASS: level is 6.
-PASS: level is 1.
-PASS: level is 1.
+PASS: level is 2.
+PASS: level is 2.
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/accessibility/heading-level.html b/third_party/WebKit/LayoutTests/accessibility/heading-level.html
index 96ba59f..fffff15 100644
--- a/third_party/WebKit/LayoutTests/accessibility/heading-level.html
+++ b/third_party/WebKit/LayoutTests/accessibility/heading-level.html
@@ -39,8 +39,8 @@
 <div class="ex" role="heading" data-expected="6" aria-level="6">X</div>
 
 <!-- A level that is specified either as 0 or as a ntegative number,should be set to 1. -->
-<div class="ex" role="heading" data-expected="1" aria-level="0">X</div>
-<div class="ex" role="heading" data-expected="1" aria-level="-1">X</div>
+<div class="ex" role="heading" data-expected="2" aria-level="0">X</div>
+<div class="ex" role="heading" data-expected="2" aria-level="-1">X</div>
 
 <!-- todo: h1 elements nested in section elements should inherit nested level. -->
 
diff --git a/third_party/WebKit/LayoutTests/bluetooth/idl/idl-BluetoothDevice.html b/third_party/WebKit/LayoutTests/bluetooth/idl/idl-BluetoothDevice.html
index 0e6c795..34198a4 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/idl/idl-BluetoothDevice.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/idl/idl-BluetoothDevice.html
@@ -5,27 +5,27 @@
 <script src="../../resources/bluetooth/web-bluetooth-test.js"></script>
 <script src="../../resources/mojo-helpers.js"></script>
 <script>
+'use strict';
+const test_desc_idl = 'BluetoothDevice IDL test.';
 test(() => {
-  assert_throws(null, () => new BluetoothDevice(),
-                'the constructor should not be callable with "new"');
-  assert_throws(null, () => BluetoothDevice(),
-                'the constructor should not be callable');
-}, 'BluetoothDevice IDL test');
+  assert_throws(new TypeError(), () => new BluetoothDevice(),
+      'the constructor should not be callable with "new"');
+  assert_throws(new TypeError(), () => BluetoothDevice(),
+      'the constructor should not be callable');
+}, test_desc_idl);
 
-promise_test(() => {
-  return setUpHealthThermometerAndHeartRateDevices()
-    .then(() => requestDeviceWithKeyDown({
-      filters: [{services: ['heart_rate']}]}))
-    .then(device => {
-      assert_equals(device.constructor.name, 'BluetoothDevice');
-
-      // Attempt (and fail) to overwrite all members, verifying they are
-      // readonly.
-      var old_device_id = device.id;
-      device.id = 'overwritten';
-      device.name = 'overwritten';
-      assert_equals(device.id, old_device_id);
-      assert_equals(device.name, 'Heart Rate');
-    });
-}, 'BluetoothDevice attributes.');
+const test_desc_attr = 'BluetoothDevice attributes.';
+let device;
+promise_test(() => getHealthThermometerDevice()
+  .then(_ => ({device} = _))
+  .then(() => {
+    assert_equals(device.constructor.name, 'BluetoothDevice');
+    var old_device_id = device.id;
+    assert_throws(new TypeError(), () => device.id = 'overwritten',
+      'the device id should not be writable');
+    assert_throws(new TypeError(), () => device.name = 'overwritten',
+      'the device name should not be writable');
+    assert_equals(device.id, old_device_id);
+    assert_equals(device.name, 'Health Thermometer');
+  }),  test_desc_attr);
 </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/requestDevice/request-from-iframe.html b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/request-from-iframe.html
index c942d00..83ca1ced 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/requestDevice/request-from-iframe.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/request-from-iframe.html
@@ -4,48 +4,46 @@
 <script src="../../resources/bluetooth/bluetooth-helpers.js"></script>
 <script src="../../resources/bluetooth/web-bluetooth-test.js"></script>
 <script src="../../resources/mojo-helpers.js"></script>
-<body>
-  <script>
-  "use strict";
+<script>
+'use strict';
+const test_desc = 'Concurrent requestDevice calls in iframes work.';
+const iframes = [];
+for (let i = 0; i < 5; i++) {
+  iframes.push(document.createElement('iframe'));
+}
 
-  const numIframes = 5;
-
-  async_test(test => {
-    let readiesReceived = 0;
-    window.onmessage = messageEvent => test.step(() => {
-      if (messageEvent.data === 'Ready') {
-        readiesReceived++;
-      }
-      if (readiesReceived < numIframes) {
-        return;
+promise_test(() => setUpHealthThermometerAndHeartRateDevices()
+  // 1. Load the iframes.
+  .then(() => new Promise(resolve => {
+    let numMessages = 0;
+    window.onmessage = messageEvent => {
+      if (messageEvent.data !== 'Ready') {
+        assert_unreached('Bad message, expected "Ready": ' +
+            messageEvent.data);
       }
 
-      let iframesFinished = 0;
-      window.onmessage = messageEvent => test.step(() => {
-        if (messageEvent.data !== 'Success') {
-          console.error(messageEvent.data);
-        }
-        iframesFinished++;
-        if (iframesFinished === numIframes) {
-          test.done();
-        }
-      });
+      if (++numMessages === iframes.length) resolve();
+    }
 
-      Array.prototype.forEach.call(document.querySelectorAll('iframe'), iframe => {
-        callWithKeyDown(() => {
-          iframe.contentWindow.postMessage('Go', '*');
-        });
-      });
-    });
+    for (let iframe of iframes) {
+      iframe.src = '../../resources/bluetooth/requestDevice-in-iframe.html';
+      document.body.appendChild(iframe);
+    }
+  }))
+  // 2. Request the device from the iframes.
+  .then(() => new Promise(resolve => {
+    let numMessages = 0;
+    window.onmessage = messageEvent => {
+      if (messageEvent.data !== 'Success') {
+        assert_unreached('Bad message, expected "Success": ' +
+            messageEvent.data);
+      }
 
-    return setUpHealthThermometerAndHeartRateDevices()
-      .then(() => {
-        for (let i = 0; i < numIframes; i++) {
-          let iframe = document.createElement('iframe');
-          iframe.src = '../../resources/bluetooth/requestDevice-in-iframe.html';
-          document.body.appendChild(iframe);
-        }
-      });
-  }, 'Concurrent requestDevice calls in iframes work.');
-  </script>
-</body>
+      if (++numMessages === iframes.length) resolve();
+    }
+
+    for (let iframe of iframes) {
+      callWithKeyDown(() => iframe.contentWindow.postMessage('Go', '*'));
+    }
+  })), test_desc);
+</script>
diff --git a/third_party/WebKit/LayoutTests/compositing/culling/filter-occlusion-blur-expected.png b/third_party/WebKit/LayoutTests/compositing/culling/filter-occlusion-blur-expected.png
index 1df89a6..46428a3 100644
--- a/third_party/WebKit/LayoutTests/compositing/culling/filter-occlusion-blur-expected.png
+++ b/third_party/WebKit/LayoutTests/compositing/culling/filter-occlusion-blur-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/css3/filters/effect-blur-hw-expected.png b/third_party/WebKit/LayoutTests/css3/filters/effect-blur-hw-expected.png
index f92bdbb..c0ab7c9 100644
--- a/third_party/WebKit/LayoutTests/css3/filters/effect-blur-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/css3/filters/effect-blur-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-brightness-clamping-hw-expected.png b/third_party/WebKit/LayoutTests/css3/filters/effect-brightness-clamping-hw-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-brightness-clamping-hw-expected.png
rename to third_party/WebKit/LayoutTests/css3/filters/effect-brightness-clamping-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-combined-hw-expected.png b/third_party/WebKit/LayoutTests/css3/filters/effect-combined-hw-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-combined-hw-expected.png
rename to third_party/WebKit/LayoutTests/css3/filters/effect-combined-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-drop-shadow-hw-expected.png b/third_party/WebKit/LayoutTests/css3/filters/effect-drop-shadow-hw-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-drop-shadow-hw-expected.png
rename to third_party/WebKit/LayoutTests/css3/filters/effect-drop-shadow-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/css3/filters/filter-repaint-composited-fallback-crash-expected.png b/third_party/WebKit/LayoutTests/css3/filters/filter-repaint-composited-fallback-crash-expected.png
index 4aff4f1..85fde79 100644
--- a/third_party/WebKit/LayoutTests/css3/filters/filter-repaint-composited-fallback-crash-expected.png
+++ b/third_party/WebKit/LayoutTests/css3/filters/filter-repaint-composited-fallback-crash-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/css3/filters/filter-repaint-composited-fallback-expected.png b/third_party/WebKit/LayoutTests/css3/filters/filter-repaint-composited-fallback-expected.png
index 4aff4f1..85fde79 100644
--- a/third_party/WebKit/LayoutTests/css3/filters/filter-repaint-composited-fallback-expected.png
+++ b/third_party/WebKit/LayoutTests/css3/filters/filter-repaint-composited-fallback-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/editing/spelling/cancel_check.html b/third_party/WebKit/LayoutTests/editing/spelling/cancel_check.html
new file mode 100644
index 0000000..23c55f1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/editing/spelling/cancel_check.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../assert_selection.js"></script>
+<script src="spellcheck_test.js"></script>
+<script>
+spellcheck_test(
+    '<div contenteditable>zz.|</div>',
+    '',
+    '<div contenteditable>#zz#.</div>',
+    {
+      title: 'Setup a contenteditable div with spelling marker',
+      callback: sample => spellcheck_test(
+          sample,
+          document => {
+            document.execCommand('insertText', false, ' zz.');
+            if (window.internals) {
+              internals.runIdleTimeSpellChecker(document);
+              internals.cancelCurrentSpellCheckRequest(document);
+            }
+          },
+          '<div contenteditable>#zz#. zz.</div>',
+          'Canceled spellcheck request should not remove existing marker')
+    });
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
index 93f96d2b..58d2f3b 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -2851,6 +2851,12 @@
      {}
     ]
    ],
+   "fullscreen/api/element-request-fullscreen-dialog-manual.html": [
+    [
+     "/fullscreen/api/element-request-fullscreen-dialog-manual.html",
+     {}
+    ]
+   ],
    "fullscreen/api/element-request-fullscreen-manual.html": [
     [
      "/fullscreen/api/element-request-fullscreen-manual.html",
@@ -2863,6 +2869,12 @@
      {}
     ]
    ],
+   "fullscreen/api/element-request-fullscreen-null-ns-manual.html": [
+    [
+     "/fullscreen/api/element-request-fullscreen-null-ns-manual.html",
+     {}
+    ]
+   ],
    "fullscreen/api/element-request-fullscreen-same-manual.html": [
     [
      "/fullscreen/api/element-request-fullscreen-same-manual.html",
@@ -110679,6 +110691,11 @@
      {}
     ]
    ],
+   "html/semantics/interactive-elements/the-dialog-element/resources/common.js": [
+    [
+     {}
+    ]
+   ],
    "html/semantics/interactive-elements/the-menu-element/.gitkeep": [
     [
      {}
@@ -113759,6 +113776,11 @@
      {}
     ]
    ],
+   "mediacapture-streams/historical-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "mediasession/OWNERS": [
     [
      {}
@@ -120079,6 +120101,11 @@
      {}
     ]
    ],
+   "speech-api/historical-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "staticrange/OWNERS": [
     [
      {}
@@ -121639,11 +121666,6 @@
      {}
     ]
    ],
-   "webaudio/js/vendor-prefixes.js": [
-    [
-     {}
-    ]
-   ],
    "webaudio/refresh_idl.rb": [
     [
      {}
@@ -125184,6 +125206,46 @@
      {}
     ]
    ],
+   "worklets/OWNERS": [
+    [
+     {}
+    ]
+   ],
+   "worklets/README.md": [
+    [
+     {}
+    ]
+   ],
+   "worklets/resources/empty-worklet-script.js": [
+    [
+     {}
+    ]
+   ],
+   "worklets/resources/import-cyclic-worklet-script.js": [
+    [
+     {}
+    ]
+   ],
+   "worklets/resources/import-nested-internal-worklet-script.js": [
+    [
+     {}
+    ]
+   ],
+   "worklets/resources/import-nested-worklet-script.js": [
+    [
+     {}
+    ]
+   ],
+   "worklets/resources/import-tests.js": [
+    [
+     {}
+    ]
+   ],
+   "worklets/resources/throwing-worklet-script.js": [
+    [
+     {}
+    ]
+   ],
    "x-frame-options/OWNERS": [
     [
      {}
@@ -153344,6 +153406,18 @@
      {}
     ]
    ],
+   "html/semantics/interactive-elements/the-dialog-element/dialog-autofocus-multiple-times.html": [
+    [
+     "/html/semantics/interactive-elements/the-dialog-element/dialog-autofocus-multiple-times.html",
+     {}
+    ]
+   ],
+   "html/semantics/interactive-elements/the-dialog-element/dialog-autofocus.html": [
+    [
+     "/html/semantics/interactive-elements/the-dialog-element/dialog-autofocus.html",
+     {}
+    ]
+   ],
    "html/semantics/interactive-elements/the-dialog-element/dialog-close.html": [
     [
      "/html/semantics/interactive-elements/the-dialog-element/dialog-close.html",
@@ -154036,6 +154110,12 @@
      {}
     ]
    ],
+   "html/semantics/scripting-1/the-template-element/template-element/template-content-hierarcy.html": [
+    [
+     "/html/semantics/scripting-1/the-template-element/template-element/template-content-hierarcy.html",
+     {}
+    ]
+   ],
    "html/semantics/scripting-1/the-template-element/template-element/template-content-node-document.html": [
     [
      "/html/semantics/scripting-1/the-template-element/template-element/template-content-node-document.html",
@@ -157380,6 +157460,12 @@
      {}
     ]
    ],
+   "mediacapture-streams/historical.html": [
+    [
+     "/mediacapture-streams/historical.html",
+     {}
+    ]
+   ],
    "mediasession/idlharness.html": [
     [
      "/mediasession/idlharness.html",
@@ -179264,6 +179350,12 @@
      {}
     ]
    ],
+   "speech-api/historical.html": [
+    [
+     "/speech-api/historical.html",
+     {}
+    ]
+   ],
    "staticrange/idlharness.html": [
     [
      "/staticrange/idlharness.html",
@@ -181438,6 +181530,12 @@
      {}
     ]
    ],
+   "webaudio/historical.html": [
+    [
+     "/webaudio/historical.html",
+     {}
+    ]
+   ],
    "webaudio/the-audio-api/the-audiobuffer-interface/idl-test.html": [
     [
      "/webaudio/the-audio-api/the-audiobuffer-interface/idl-test.html",
@@ -186216,6 +186314,18 @@
      {}
     ]
    ],
+   "worklets/animation-worklet-import.html": [
+    [
+     "/worklets/animation-worklet-import.html",
+     {}
+    ]
+   ],
+   "worklets/paint-worklet-import.html": [
+    [
+     "/worklets/paint-worklet-import.html",
+     {}
+    ]
+   ],
    "x-frame-options/deny.sub.html": [
     [
      "/x-frame-options/deny.sub.html",
@@ -248960,7 +249070,7 @@
    "testharness"
   ],
   "dom/events/Event-timestamp-safe-resolution.html": [
-   "8e707dcd84b87dc3ebb8cff30e61439ce47bd58a",
+   "dd22e8532f7ae8424d0a8ec898841a1c7545d020",
    "testharness"
   ],
   "dom/events/Event-type-empty.html": [
@@ -252900,7 +253010,7 @@
    "support"
   ],
   "eventsource/resources/last-event-id.py": [
-   "ac5566baba69431f2c9f7cdb2ecdc613aa0032fd",
+   "60b7b62c4f825b69f8354729a0fb6d9c216b2d05",
    "support"
   ],
   "eventsource/resources/message.py": [
@@ -253724,7 +253834,7 @@
    "support"
   ],
   "fetch/api/request/request-headers.html": [
-   "0a645876664c428f6ac8d170e991ccf257bb307e",
+   "ca4f2d4b881202dc965ac13a06609ac6a2684ffc",
    "testharness"
   ],
   "fetch/api/request/request-idl-expected.txt": [
@@ -253912,7 +254022,7 @@
    "testharness"
   ],
   "fetch/api/response/response-init-001.html": [
-   "e1d9ffd41e8ff0871b27ca7d33f088a124c09f4b",
+   "a45bf860ad19e31ff95c3add7b6f4ad7c0573254",
    "testharness"
   ],
   "fetch/api/response/response-init-002.html": [
@@ -254244,7 +254354,7 @@
    "manual"
   ],
   "fullscreen/api/element-request-fullscreen-and-move-manual.html": [
-   "29fb0d686ac510d169fbc10ca98eaed599f292df",
+   "5a4ee7d6ebcb448b58f61c9334f0585dba49a3f0",
    "manual"
   ],
   "fullscreen/api/element-request-fullscreen-and-move-to-iframe-manual.html": [
@@ -254259,6 +254369,10 @@
    "86c1ac20aa86e860cfa8f05a9873f3a3cddbdcd9",
    "manual"
   ],
+  "fullscreen/api/element-request-fullscreen-dialog-manual.html": [
+   "46033232549f3b3333443a97d23d0229c9705b24",
+   "manual"
+  ],
   "fullscreen/api/element-request-fullscreen-manual.html": [
    "ed7683b3c4a7134b640e07a7329a21361b122402",
    "manual"
@@ -254271,12 +254385,16 @@
    "8991e8df530fa7c24a9e084f2ab17fa9c70fb120",
    "testharness"
   ],
+  "fullscreen/api/element-request-fullscreen-null-ns-manual.html": [
+   "5fe4a901e450a2f3e52866bc61324571866fb879",
+   "manual"
+  ],
   "fullscreen/api/element-request-fullscreen-same-manual.html": [
    "10b6ff2c859c50516209735dd1bdc3ea4d24f330",
    "manual"
   ],
   "fullscreen/api/element-request-fullscreen-svg-rect-manual.html": [
-   "c22355542ab46b4981dbca8c30b8e44da258998f",
+   "2efd96350b1c3de0efc1e2b3d1aa603cfe7e7738",
    "manual"
   ],
   "fullscreen/api/element-request-fullscreen-svg-svg-manual.html": [
@@ -264792,7 +264910,7 @@
    "testharness"
   ],
   "html/semantics/embedded-content/media-elements/historical.html": [
-   "b5a667eb0acb011336be671a700214af2dd10e2f",
+   "3437c85a3b5e106c61ebb0b96207108d178f0890",
    "testharness"
   ],
   "html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/addTextTrack.html": [
@@ -267947,6 +268065,14 @@
    "340924bc329569ce605ce228619d95f09f335ec5",
    "support"
   ],
+  "html/semantics/interactive-elements/the-dialog-element/dialog-autofocus-multiple-times.html": [
+   "d172f6ea35a52d72284d912d944b72a15aed18ac",
+   "testharness"
+  ],
+  "html/semantics/interactive-elements/the-dialog-element/dialog-autofocus.html": [
+   "23b7417daa9d2d9d026b97653997fb866083b65f",
+   "testharness"
+  ],
   "html/semantics/interactive-elements/the-dialog-element/dialog-close.html": [
    "94ed2b8f019e1b65c47c5f971503496bb4765048",
    "testharness"
@@ -267963,6 +268089,10 @@
    "c00ac5b6d038b45b1a7cfbef94a4527757fa74e6",
    "testharness"
   ],
+  "html/semantics/interactive-elements/the-dialog-element/resources/common.js": [
+   "15580f3e0243093710d4914224ca3963992e3f5b",
+   "support"
+  ],
   "html/semantics/interactive-elements/the-menu-element/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
@@ -269115,6 +269245,10 @@
    "661adb3f098161bf4535d9184e175612cfcab886",
    "testharness"
   ],
+  "html/semantics/scripting-1/the-template-element/template-element/template-content-hierarcy.html": [
+   "20d5847c7978323f71a46625e9e1fd2eb899063c",
+   "testharness"
+  ],
   "html/semantics/scripting-1/the-template-element/template-element/template-content-node-document.html": [
    "1943b45780474af52c24d8c734072aba2fe6a442",
    "testharness"
@@ -272720,7 +272854,7 @@
    "support"
   ],
   "mediacapture-streams/MediaStreamTrack-MediaElement-disabled-audio-is-silence.https.html": [
-   "37c655ef9b01d3e9d3d9512c966bd24adf870245",
+   "c70017e897191d1c3d77ee504f9ca2f73bb0aa48",
    "testharness"
   ],
   "mediacapture-streams/MediaStreamTrack-MediaElement-disabled-video-is-black.https-expected.txt": [
@@ -272728,7 +272862,7 @@
    "support"
   ],
   "mediacapture-streams/MediaStreamTrack-MediaElement-disabled-video-is-black.https.html": [
-   "6427b6bea51c488ca15ac02b3cbecb776c294c0c",
+   "9f8b4811f67bd0c9ed67327e9589db68432e3117",
    "testharness"
   ],
   "mediacapture-streams/MediaStreamTrack-end-manual.https.html": [
@@ -272759,6 +272893,14 @@
    "07fc6a5ece5e626316fe1d70f23fbe377b6618d3",
    "support"
   ],
+  "mediacapture-streams/historical-expected.txt": [
+   "ab1451018c4255bce7458738e604b58489ce824a",
+   "support"
+  ],
+  "mediacapture-streams/historical.html": [
+   "96a34ddfb393f19df98b2334a71e78b40e333e26",
+   "testharness"
+  ],
   "mediasession/OWNERS": [
    "27bf5ebefa8583974d0961d9a9b68ebede0dfb67",
    "support"
@@ -281316,7 +281458,7 @@
    "manual"
   ],
   "payment-request/payment-response/helpers.js": [
-   "12ab0390ad4dce730effa9543ca7e0c2e6d994cb",
+   "992e5ce9af876e7d3f76168f15691afd43b41791",
    "support"
   ],
   "payment-request/payment-response/methodName-attribute-manual.https.html": [
@@ -293119,6 +293261,14 @@
    "bc28599cea839c13daf4739168f8c1ea42526050",
    "testharness"
   ],
+  "speech-api/historical-expected.txt": [
+   "0ea0408ab857b42d5359deebec1ebf11f776046a",
+   "support"
+  ],
+  "speech-api/historical.html": [
+   "45bfdcce349e2cb28611520b006c060347fdf58d",
+   "testharness"
+  ],
   "staticrange/OWNERS": [
    "4a751ed955527472b3c130870c8fbc7b79868290",
    "support"
@@ -295204,27 +295354,27 @@
    "support"
   ],
   "vibration/api-is-present.html": [
-   "0c3c74860bfa27bcdc22a29fe97aa1459a05148f",
+   "b8f5622deb5141ec9a3b66f6e30c6054d5a42288",
    "testharness"
   ],
   "vibration/cancel-when-hidden-manual.html": [
-   "919d3a12fe1ae0b518f7a69a50bd95aaf06c4cd5",
+   "c83e444bb323268d89cca72b68de6893495ae702",
    "manual"
   ],
   "vibration/cancel-with-0-manual.html": [
-   "98eeadb226d27685907319f364ac4091a962d995",
+   "33fefd5310ead5f12747716b30f212d8a8026b81",
    "manual"
   ],
   "vibration/cancel-with-array-0-manual.html": [
-   "64a3b25d44cfe5773254ebdc6e22705177fb1eef",
+   "cd7b9d2818e06b8e305a087c00b770dcc6dddef1",
    "manual"
   ],
   "vibration/cancel-with-empty-array-manual.html": [
-   "c5cb3390f2ba8af94f4f35398caa29b8f3c7c852",
+   "063a18afa082e52900742047dff81a3c22cd574b",
    "manual"
   ],
   "vibration/cancel-with-new-manual.html": [
-   "4efea60445ee5349e58077cc06184f95d8c969af",
+   "62578765cf586c984017d38fac9e8f46cad96201",
    "manual"
   ],
   "vibration/idl.html": [
@@ -295232,19 +295382,19 @@
    "testharness"
   ],
   "vibration/invalid-values.html": [
-   "52dda7cccc18982483eaba6fd3e8d8ebcb4155fd",
+   "9c7367db5eaf70dc9a020560b43531e16d44fca4",
    "testharness"
   ],
   "vibration/pattern-array-extra-manual.html": [
-   "48f43b7ddc69b0cedb1f3077212ec554c0d5a818",
+   "35ad58df83597875739f4c532b5e72011de0f0d3",
    "manual"
   ],
   "vibration/pattern-array-manual.html": [
-   "cb86e49638093e65b0660982649733e96fa9c813",
+   "d0d8d333566ff1a2ace0ca3e36dadeb36952549e",
    "manual"
   ],
   "vibration/pattern-array-with-0-manual.html": [
-   "ce0e6f0374c75ca7f6067fb837580ed850de30af",
+   "bd5c644b5609f702dfec4985e3b2dfdf2de4c622",
    "manual"
   ],
   "vibration/silent-ignore-expected.txt": [
@@ -295252,15 +295402,15 @@
    "support"
   ],
   "vibration/silent-ignore.html": [
-   "bfa8b3fd032dcddf8b2fb6ea83d449b15c74b6fb",
+   "986e856b25f4cb4c28d0add4acd46ec3d83612f6",
    "testharness"
   ],
   "vibration/simple-array-manual.html": [
-   "ae52d64dfea4e39179595d565f86c6a3a0fae756",
+   "30734ec1632c9666069505bb19554adb03c8f9b6",
    "manual"
   ],
   "vibration/simple-scalar-manual.html": [
-   "f6ae98a534bfc2d0b57ef11f8f1ebb3d72629c3c",
+   "fcc5e59095f69e8f62120e392d84de9f4c5647a2",
    "manual"
   ],
   "viewport/OWNERS": [
@@ -296023,6 +296173,10 @@
    "230684ec60fd2e408f9b6014417f3eddfe2dc95a",
    "support"
   ],
+  "webaudio/historical.html": [
+   "93068df297042344669093ce899f0230c87ebf54",
+   "testharness"
+  ],
   "webaudio/js/buffer-loader.js": [
    "4d564eae0b3d7d1045626d1f144cd2638dba64e5",
    "support"
@@ -296035,10 +296189,6 @@
    "58c3eae918fedad54c56d488a14f99ce87943500",
    "support"
   ],
-  "webaudio/js/vendor-prefixes.js": [
-   "3b7d06164273077415b7fc99652355bcf0e10e17",
-   "support"
-  ],
   "webaudio/refresh_idl.rb": [
    "9ef52c13448d19b241b40a5c81f4a0480c05c5de",
    "support"
@@ -296060,7 +296210,7 @@
    "support"
   ],
   "webaudio/the-audio-api/the-audiobuffer-interface/idl-test.html": [
-   "11ec68dec57c960cea256c28237715866c58ac84",
+   "a799ad9a51801a67a82159e9a16b639ad0c50226",
    "testharness"
   ],
   "webaudio/the-audio-api/the-audiobuffersourcenode-interface/.gitkeep": [
@@ -296076,7 +296226,7 @@
    "support"
   ],
   "webaudio/the-audio-api/the-audiodestinationnode-interface/idl-test.html": [
-   "74770d22caf02df7fb3cd3fb1e7499436e69cbed",
+   "215cd494eca448981b5f0a4dc931d7ece9a33b80",
    "testharness"
   ],
   "webaudio/the-audio-api/the-audiolistener-interface/.gitkeep": [
@@ -296096,7 +296246,7 @@
    "support"
   ],
   "webaudio/the-audio-api/the-audioparam-interface/idl-test.html": [
-   "c1680330a6224285ad9bc9d6a6b046b75a860101",
+   "a1bba8cf32a40cefdc3cd27bb4cd33ab2ddb72db",
    "testharness"
   ],
   "webaudio/the-audio-api/the-audioparam-interface/retrospective-exponentialRampToValueAtTime.html": [
@@ -296156,7 +296306,7 @@
    "support"
   ],
   "webaudio/the-audio-api/the-delaynode-interface/idl-test.html": [
-   "55a67c98908e18856e55c2e9437b63e8dc6feb94",
+   "2721b0ff902b22214a2c1cecd0b7978d520efad2",
    "testharness"
   ],
   "webaudio/the-audio-api/the-dynamicscompressornode-interface/.gitkeep": [
@@ -296172,11 +296322,11 @@
    "support"
   ],
   "webaudio/the-audio-api/the-gainnode-interface/idl-test.html": [
-   "35c753a641939795d00ec7ce1a55bfc74324a075",
+   "7d3e3335d8b7fe23faec74788b402c8383da53b8",
    "testharness"
   ],
   "webaudio/the-audio-api/the-gainnode-interface/test-gainnode.html": [
-   "0933aa32383aa561af5956a1e21f1c2b6890942b",
+   "32f1b481b638364f2a33fbbf2b63e529f9ead61c",
    "testharness"
   ],
   "webaudio/the-audio-api/the-iirfilternode-interface/test-iirfilternode.html": [
@@ -296188,7 +296338,7 @@
    "support"
   ],
   "webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/mediaElementAudioSourceToScriptProcessorTest.html": [
-   "ad08dea6c04f20892a7bc3404b7ca0abdabdebce",
+   "a394f084e22f4b27b695b3b5b14352053b5e25e4",
    "testharness"
   ],
   "webaudio/the-audio-api/the-mediastreamaudiodestinationnode-interface/.gitkeep": [
@@ -296232,7 +296382,7 @@
    "support"
   ],
   "webaudio/the-audio-api/the-waveshapernode-interface/curve-tests.html": [
-   "cc9f8148b1e7d75a61599a094f9ed21377e97edb",
+   "f88431616d6a8084a3434c1606e3543178d019fb",
    "testharness"
   ],
   "webauthn/OWNERS": [
@@ -297252,11 +297402,11 @@
    "testharness"
   ],
   "webrtc/historical-expected.txt": [
-   "2d32407f17c287101f72ad30f8f05555ce143b13",
+   "38c9d88ee8bafe14e4dbabf9da22b6869c555835",
    "support"
   ],
   "webrtc/historical.html": [
-   "39495fabcd2e3a60b92a38e40e3f9820549b2311",
+   "918bdc69f500ff726dc98643b418f14ac5ba3c3a",
    "testharness"
   ],
   "webrtc/identity-helper.js": [
@@ -297292,7 +297442,7 @@
    "support"
   ],
   "webrtc/simplecall.html": [
-   "660ee6590039769adc1997679ba12c4995b5a3e6",
+   "6194af79f137d59334da2193cc6f24b9458344be",
    "testharness"
   ],
   "websockets/Close-1000-reason.htm": [
@@ -302595,6 +302745,46 @@
    "d1759a707897f66bf013e888ed188023145e2622",
    "testharness"
   ],
+  "worklets/OWNERS": [
+   "2c0d14a64d1111b54c353ac7d9ad0ea73caf9b7c",
+   "support"
+  ],
+  "worklets/README.md": [
+   "33a3530260a18e74dd96470d9890bbdb4ecdb08d",
+   "support"
+  ],
+  "worklets/animation-worklet-import.html": [
+   "21d213d3b71476bcfab7cd5e560450b99f53552c",
+   "testharness"
+  ],
+  "worklets/paint-worklet-import.html": [
+   "58d18185c32964d1d233f9701f3f0e6fdbddd48b",
+   "testharness"
+  ],
+  "worklets/resources/empty-worklet-script.js": [
+   "84b3339c3419e318803e51f46d7252d9e8ac183b",
+   "support"
+  ],
+  "worklets/resources/import-cyclic-worklet-script.js": [
+   "f32abb012c93bb69087688f31a0c243d9e6d1060",
+   "support"
+  ],
+  "worklets/resources/import-nested-internal-worklet-script.js": [
+   "b897cf335179eb5c0e9536e8e883da1eba509ea7",
+   "support"
+  ],
+  "worklets/resources/import-nested-worklet-script.js": [
+   "463fc9e39a1502333cfe329613516e82f66f08de",
+   "support"
+  ],
+  "worklets/resources/import-tests.js": [
+   "b54605a24cf1c82c70427f27fa586fb46b370656",
+   "support"
+  ],
+  "worklets/resources/throwing-worklet-script.js": [
+   "a7164f899afec387321c7737aa1006aa5f225669",
+   "support"
+  ],
   "x-frame-options/OWNERS": [
    "fad08f267635717c6a2930de14df27107039b3a8",
    "support"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-timestamp-safe-resolution.html b/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-timestamp-safe-resolution.html
index c19c7a0..5009c8a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-timestamp-safe-resolution.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-timestamp-safe-resolution.html
@@ -1,20 +1,49 @@
 <!DOCTYPE html>
-
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script type="text/javascript">
 'use strict';
 
+// Computes greatest common divisor of a and b using Euclid's algorithm
+function computeGCD(a, b) {
+  if (!Number.isInteger(a) || !Number.isInteger(b)) {
+    throw new Error('Parameters must be integer numbers');
+  }
+
+  var r;
+  while (b != 0) {
+    r = a % b;
+    a = b;
+    b = r;
+  }
+  return (a < 0) ? -a : a;
+}
+
+// Finds minimum resolution Δ given a set of samples which are known to be in the form of N*Δ.
+// We use GCD of all samples as a simple estimator.
+function estimateMinimumResolution(samples) {
+  var gcd;
+  for (const sample of samples) {
+    gcd = gcd ? computeGCD(gcd, sample) : sample;
+  }
+
+  return gcd;
+}
+
 test(function() {
-    let e1 = new MouseEvent('test1');
-    let e2 = new MouseEvent('test2');
+  const samples = [];
+  for (var i = 0; i < 1e3; i++) {
+    var deltaInMicroSeconds = 0;
+    const e1 = new MouseEvent('test1');
+    do {
+      const e2 = new MouseEvent('test2');
+      deltaInMicroSeconds = Math.round((e2.timeStamp - e1.timeStamp) * 1000);
+    } while (deltaInMicroSeconds == 0) // only collect non-zero samples
 
-    while (e1.timeStamp == e2.timeStamp)
-        e2 = new MouseEvent('test2');
+    samples.push(deltaInMicroSeconds);
+  }
 
-    let expectedResolutionMilliseconds = 0.005;
-    let integerMultipleOfResolution = (e2.timeStamp - e1.timeStamp) / expectedResolutionMilliseconds;
-    let shouldBeNearZeroOrOne = integerMultipleOfResolution % 1;
-    assert_true(shouldBeNearZeroOrOne < 1e-10 || Math.abs(shouldBeNearZeroOrOne - 1) < 1e-10);
+  const minResolution = estimateMinimumResolution(samples);
+  assert_greater_than_equal(minResolution, 5);
 }, 'Event timestamp should not have a resolution better that 5 microseconds');
 </script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/eventsource/resources/last-event-id.py b/third_party/WebKit/LayoutTests/external/wpt/eventsource/resources/last-event-id.py
index b14076d..09e4f29 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/eventsource/resources/last-event-id.py
+++ b/third_party/WebKit/LayoutTests/external/wpt/eventsource/resources/last-event-id.py
@@ -1,11 +1,9 @@
- # -*- coding: utf-8 -*-
-
 def main(request, response):
   response.headers.set("Content-Type", "text/event-stream")
-  last_event_id = request.headers.get('Last-Event-ID', None)
-  value = request.GET.first("idvalue", "…")
 
-  if(last_event_id):
-      return "data: " + last_event_id + "\n\n"
+  last_event_id = request.headers.get("Last-Event-ID", None)
+  if last_event_id:
+    return "data: " + last_event_id + "\n\n"
   else:
-    return "id: " + value + "\nretry: 200\ndata: hello\n\n"
+    idvalue = request.GET.first("idvalue", u"\u2026")
+    return "id: " + idvalue + "\nretry: 200\ndata: hello\n\n"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/request/request-headers.html b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/request/request-headers.html
index 1d54728..014f2fb 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/request/request-headers.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/request/request-headers.html
@@ -168,6 +168,19 @@
         });
       }, "Testing empty Request Content-Type header");
 
+      test(function() {
+        const request1 = new Request("");
+        assert_equals(request1.headers, request1.headers);
+
+        const request2 = new Request("", {"headers": {"X-Foo": "bar"}});
+        assert_equals(request2.headers, request2.headers);
+        const headers = request2.headers;
+        request2.headers.set("X-Foo", "quux");
+        assert_equals(headers, request2.headers);
+        headers.set("X-Other-Header", "baz");
+        assert_equals(headers, request2.headers);
+      }, "Test that Request.headers has the [SameObject] extended attribute");
+
     </script>
   </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/response/response-init-001.html b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/response/response-init-001.html
index 4a8a7bd..cd89448 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/response/response-init-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/response/response-init-001.html
@@ -58,6 +58,19 @@
               "Expect response.ok is " + isOkStatus(response.status));
           }
         }, "Check " + attributeName + " init values and associated getter");
+
+        test(function() {
+          const response1 = new Response("");
+          assert_equals(response1.headers, response1.headers);
+
+          const response2 = new Response("", {"headers": {"X-Foo": "bar"}});
+          assert_equals(response2.headers, response2.headers);
+          const headers = response2.headers;
+          response2.headers.set("X-Foo", "quux");
+          assert_equals(headers, response2.headers);
+          headers.set("X-Other-Header", "baz");
+          assert_equals(headers, response2.headers);
+        }, "Test that Response.headers has the [SameObject] extended attribute");
     </script>
   </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fullscreen/api/element-request-fullscreen-and-move-manual.html b/third_party/WebKit/LayoutTests/external/wpt/fullscreen/api/element-request-fullscreen-and-move-manual.html
index c09cebb..f86e75f2 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/fullscreen/api/element-request-fullscreen-and-move-manual.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/fullscreen/api/element-request-fullscreen-and-move-manual.html
@@ -15,7 +15,7 @@
     assert_equals(document.fullscreenElement, target);
     assert_equals(target.parentNode, moveTo);
   });
-  document.onfullscreenerror = t.unreached_func("fullscreenchange event");
+  document.onfullscreenerror = t.unreached_func("fullscreenerror event");
 
   trusted_click(t, () => {
     target.requestFullscreen();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fullscreen/api/element-request-fullscreen-dialog-manual.html b/third_party/WebKit/LayoutTests/external/wpt/fullscreen/api/element-request-fullscreen-dialog-manual.html
new file mode 100644
index 0000000..360ade0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/fullscreen/api/element-request-fullscreen-dialog-manual.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>Element#requestFullscreen() for dialog element</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<dialog></dialog>
+<script>
+async_test(t => {
+  var dialog = document.querySelector("dialog");
+  assert_true(dialog instanceof HTMLDialogElement);
+  trusted_request(t, dialog);
+  document.onfullscreenchange = t.unreached_func("fullscreenchange event");
+  document.onfullscreenerror = t.step_func_done();
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fullscreen/api/element-request-fullscreen-null-ns-manual.html b/third_party/WebKit/LayoutTests/external/wpt/fullscreen/api/element-request-fullscreen-null-ns-manual.html
new file mode 100644
index 0000000..443346b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/fullscreen/api/element-request-fullscreen-null-ns-manual.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>Element#requestFullscreen() for an element in null namespace</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<script>
+async_test(t => {
+  const element = document.createElementNS(null, 'a');
+  assert_equals(Object.getPrototypeOf(element), Element.prototype);
+  document.body.appendChild(element);
+  trusted_request(t, element);
+  document.onfullscreenchange = t.unreached_func("fullscreenchange event");
+  document.onfullscreenerror = t.step_func_done();
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fullscreen/api/element-request-fullscreen-svg-rect-manual.html b/third_party/WebKit/LayoutTests/external/wpt/fullscreen/api/element-request-fullscreen-svg-rect-manual.html
index 77ea2b2..56ae56ee 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/fullscreen/api/element-request-fullscreen-svg-rect-manual.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/fullscreen/api/element-request-fullscreen-svg-rect-manual.html
@@ -11,7 +11,7 @@
     var rect = document.querySelector("rect");
     assert_true(rect instanceof SVGRectElement);
     trusted_request(t, rect, document.body);
-    document.onfullscreenchange = t.unreached_func("fullscreenerror event");
+    document.onfullscreenchange = t.unreached_func("fullscreenchange event");
     document.onfullscreenerror = t.step_func_done();
 });
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/historical.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/historical.html
index 45192340..efdd90f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/historical.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/historical.html
@@ -35,6 +35,7 @@
 t('initialTime'); // added in r5310, removed in r7046.
 t('audio', 'video'); // added in r5636, replaced with muted in r5991.
 t('startDate'); // added in r7045, replaced with getStartDate() in r8113.
+t('mozSrcObject'); // never in the spec
 
 // TextTrackCue constructor: added in r5723, removed in r7742.
 test(function() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-autofocus-multiple-times.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-autofocus-multiple-times.html
new file mode 100644
index 0000000..ff9ebd7d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-autofocus-multiple-times.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="./resources/common.js"></script>
+<script>
+promise_test(() => {
+  return waitUntilLoadedAndAutofocused().then(() => {
+        assert_equals(document.activeElement, document.getElementById("outer-button"));
+
+        var focusCount = 0;
+        var dlg = document.getElementById("dlg");
+        var input1 = document.getElementById("input1");
+        var input2 = document.getElementById("input2");
+        input2.onfocus = function() { focusCount += 1 };
+
+        var expectedFocusCount = 3;
+        for (i = 0; i < expectedFocusCount; i++) {
+            dlg.show();
+            assert_equals(document.activeElement, input2);
+            input1.focus();
+            assert_equals(document.activeElement,input1);
+            dlg.close();
+        }
+
+        assert_equals(focusCount.toString(), expectedFocusCount.toString());
+  });
+}, "autofocus is run every time a dialog is opened");
+</script>
+</head>
+<body>
+<button id="outer-button" autofocus></button>
+<dialog id="dlg">
+    <!-- Unfocusable elements with [autofocus] should be ignored. -->
+    <input autofocus disabled>
+    <textarea autofocus hidden></textarea>
+    <input id="input1"></input>
+    <input id="input2" autofocus></input>
+</dialog>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-autofocus.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-autofocus.html
new file mode 100644
index 0000000..149a53e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-autofocus.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="./resources/common.js"></script>
+<script>
+promise_test(() => {
+  return waitUntilLoadedAndAutofocused().then(() => {
+        assert_equals(document.activeElement, document.getElementById("outer-button"));
+
+        var dialog = document.getElementById('dialog');
+        dialog.showModal();
+
+        autofocusButton = document.getElementById('autofocus-button');
+        assert_equals(document.activeElement, autofocusButton);
+
+        anotherButton = document.getElementById('another-button');
+        anotherButton.focus();
+        assert_equals(document.activeElement, anotherButton);
+
+        // Test that recreating layout does not give focus back to a previously autofocused element.
+        autofocusButton.style.display = 'none';
+        document.body.offsetHeight;
+        autofocusButton.style.display = 'block';
+        document.body.offsetHeight;
+        assert_equals(document.activeElement, anotherButton);
+
+        // Test that reinserting does not give focus back to a previously autofocused element.
+        var parentNode = autofocusButton.parentNode;
+        parentNode.removeChild(autofocusButton);
+        document.body.offsetHeight;
+        parentNode.appendChild(autofocusButton);
+        document.body.offsetHeight;
+        assert_equals(document.activeElement, anotherButton);
+
+        dialog.close();
+        // Test that dialog focusing steps run when a dialog is reopened.
+        dialog.showModal();
+        assert_equals(document.activeElement, autofocusButton);
+        dialog.close();
+  });
+}, "autofocus when a modal dialog is opened");
+</script>
+</head>
+<body>
+<button id="outer-button" autofocus></button>
+<dialog id="dialog">
+    <button></button>
+    <!-- Unfocusable elements with [autofocus] should be ignored. -->
+    <input autofocus disabled>
+    <textarea autofocus hidden></textarea>
+    <dialog>
+        <button autofocus></button>
+    </dialog>
+    <div>
+        <span>
+            <button id="autofocus-button" autofocus></button>
+        </span>
+    </div>
+    <button id="another-button" autofocus></button>
+</dialog>
+
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/interactive-elements/the-dialog-element/resources/common.js b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/interactive-elements/the-dialog-element/resources/common.js
new file mode 100644
index 0000000..c72ed7f1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/interactive-elements/the-dialog-element/resources/common.js
@@ -0,0 +1,18 @@
+function waitUntilLoadedAndAutofocused() {
+  return new Promise(function(resolve) {
+      var loaded = false;
+      var autofocused = false;
+      window.addEventListener('load', function() {
+          loaded = true;
+          if (autofocused)
+              resolve();
+      }, false);
+      document.addEventListener('focusin', function() {
+          if (autofocused)
+              return;
+          autofocused = true;
+          if (loaded)
+              resolve();
+      }, false);
+    });
+}
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-template-element/template-element/template-content-hierarcy.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-template-element/template-element/template-content-hierarcy.html
new file mode 100644
index 0000000..1f33b96
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-template-element/template-element/template-content-hierarcy.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title></title>
+</head>
+<meta name="author" title="Takayoshi Kochi" href="mailto:kochi@chromium.org">
+<meta name="assert" title="host-including inclusive ancestor should be checked for template content">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-tree-host-including-inclusive-ancestor">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="parent">
+  <template id="tmpl"><span>Happy Templating!</span></template>
+</div>
+</body>
+<script>
+test(() => {
+  var parent = document.getElementById('parent');
+  var tmpl = document.getElementById('tmpl');
+
+  assert_equals(tmpl.innerHTML, '<span>Happy Templating!</span>');
+  var span = tmpl.content.querySelector('span');
+
+  // Hierarchy checks at various combinations.
+  assert_throws('HierarchyRequestError', () => {
+    tmpl.content.appendChild(parent);
+  }, 'Template content should throw if any of ancestor is being appended.');
+  assert_throws('HierarchyRequestError', () => {
+    tmpl.content.appendChild(tmpl);
+  }, 'Template content should throw if its host is being appended.');
+  assert_throws('HierarchyRequestError', () => {
+    span.appendChild(parent);
+  }, 'Template content child should throw if any of ancestor is being appended.');
+  assert_throws('HierarchyRequestError', () => {
+    span.appendChild(tmpl);
+  }, 'Template content child should throw template\'s host is being appended.');
+}, "Template content should throw when its ancestor is being appended.");
+
+test(() => {
+  var parent = document.getElementById('parent');
+  var tmpl = document.getElementById('tmpl');
+
+  assert_equals(tmpl.innerHTML, '<span>Happy Templating!</span>');
+  var span = tmpl.content.querySelector('span');
+
+  var tmpl_doc = tmpl.content.ownerDocument;
+  assert_equals(tmpl.ownerDocument, document);
+  assert_not_equals(tmpl_doc, document);
+
+  var new_doc = document.implementation.createHTMLDocument();
+  assert_not_equals(new_doc, document);
+  assert_not_equals(new_doc, tmpl_doc);
+
+  // Try moving tmpl.content to new_doc and check the results.
+  var new_node = new_doc.adoptNode(tmpl.content);
+  assert_equals(new_node.ownerDocument, new_doc);
+  assert_equals(tmpl.ownerDocument, document);
+  assert_equals(tmpl.content.ownerDocument, new_doc);
+  assert_not_equals(tmpl.content.ownerDocument, tmpl_doc);
+  assert_not_equals(tmpl.content.ownerDocument, document);
+
+  // Hierarchy checks at various combinations.
+  assert_throws('HierarchyRequestError', () => {
+    tmpl.content.appendChild(parent);
+  }, 'Template content should throw if any of ancestor is being appended.');
+  assert_throws('HierarchyRequestError', () => {
+    tmpl.content.appendChild(tmpl);
+  }, 'Template content should throw if its host is being appended.');
+  assert_throws('HierarchyRequestError', () => {
+    span.appendChild(parent);
+  }, 'Template content child should throw if any of ancestor is being appended.');
+  assert_throws('HierarchyRequestError', () => {
+    span.appendChild(tmpl);
+  }, 'Template content child should throw template\'s host is being appended.');
+
+  // Sanity check: template.content before and after move.
+  var tmpl_content_reference = tmpl.content;
+  assert_equals(tmpl.content.firstChild, span,
+                '<span> should be kept until it is removed, even after ' +
+                'adopted to another document.');
+  new_doc.body.appendChild(new_node);
+  assert_equals(tmpl.content.firstChild, null,
+                '<span> should be removed from template content.');
+  assert_equals(tmpl_content_reference, tmpl.content,
+                'template.content should be identical before and after ' +
+                'moving its children.');
+}, 'Template content should throw exception when its ancestor in ' +
+   'a different document but connected via host is being append.');
+</script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-audio-is-silence.https.html b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-audio-is-silence.https.html
index 48be005..0d6123d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-audio-is-silence.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-audio-is-silence.https.html
@@ -17,7 +17,6 @@
 <div id='log'></div>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["window"], "name":"AudioContext"}]'></script>
 <script>
 var t = async_test("Tests that a disabled audio track in a MediaStream is rendered as silence", {timeout: 200000});
 var aud = document.getElementById("aud");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-video-is-black.https.html b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-video-is-black.https.html
index c4c5e33b..8aee8e2 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-video-is-black.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-video-is-black.https.html
@@ -16,7 +16,6 @@
 <div id='log'></div>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src="/common/vendor-prefix.js" data-prefixed-prototypes='[{"ancestors":["HTMLMediaElement"],"name":"srcObject"}]'></script>
 <script>
 var vid = document.getElementById("vid");
 var cv = document.createElement("canvas");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/historical-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/historical-expected.txt
new file mode 100644
index 0000000..21f1152
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/historical-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+FAIL webkitMediaStream interface should not exist assert_false: expected false got true
+FAIL navigator.webkitGetUserMedia should not exist assert_false: expected false got true
+PASS navigator.mozGetUserMedia should not exist
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/historical.html b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/historical.html
new file mode 100644
index 0000000..d9616f12
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/historical.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>Historical Media Capture and Streams features</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  assert_false("webkitMediaStream" in window);
+}, "webkitMediaStream interface should not exist");
+
+test(function() {
+  assert_false("webkitGetUserMedia" in navigator);
+}, "navigator.webkitGetUserMedia should not exist");
+
+test(function() {
+  assert_false("mozGetUserMedia" in navigator);
+}, "navigator.mozGetUserMedia should not exist");
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-response/helpers.js b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-response/helpers.js
index 312f9e40..bf938c5e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-response/helpers.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-response/helpers.js
@@ -115,11 +115,8 @@
     }
     assert_idl_attribute(response, "details");
     assert_equals(typeof response.details, "object", "Expected an object");
-    try {
-      response.toJSON();
-    } catch (err) {
-      assertion_unreached("Unexpected error calling response.toJSON()");
-    }
+    // Testing that this does not throw:
+    response.toJSON();
     if (options && options.requestShipping) {
       assert_equals(
         response.shippingOption,
diff --git a/third_party/WebKit/LayoutTests/external/wpt/speech-api/historical-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/speech-api/historical-expected.txt
new file mode 100644
index 0000000..42510d6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/speech-api/historical-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+FAIL webkitSpeechGrammar interface should not exist assert_false: expected false got true
+FAIL webkitSpeechGrammarList interface should not exist assert_false: expected false got true
+FAIL webkitSpeechRecognition interface should not exist assert_false: expected false got true
+FAIL webkitSpeechRecognitionError interface should not exist assert_false: expected false got true
+FAIL webkitSpeechRecognitionEvent interface should not exist assert_false: expected false got true
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/speech-api/historical.html b/third_party/WebKit/LayoutTests/external/wpt/speech-api/historical.html
new file mode 100644
index 0000000..4ca574b171
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/speech-api/historical.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>Historical Speech API features</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+[
+  "webkitSpeechGrammar",
+  "webkitSpeechGrammarList",
+  "webkitSpeechRecognition",
+  "webkitSpeechRecognitionError",
+  "webkitSpeechRecognitionEvent",
+].forEach(name => {
+  test(function() {
+    assert_false(name in window);
+  }, name + " interface should not exist");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/vibration/api-is-present.html b/third_party/WebKit/LayoutTests/external/wpt/vibration/api-is-present.html
index f5c976df..8f6a7e0 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/vibration/api-is-present.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/vibration/api-is-present.html
@@ -17,7 +17,6 @@
     <div id='log'></div>
     <script src='/resources/testharness.js'></script>
     <script src='/resources/testharnessreport.js'></script>
-    <script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
     <script>
       test(function () {
           assert_true(undefined !== navigator.vibrate, "navigator.vibrate exists");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/vibration/cancel-when-hidden-manual.html b/third_party/WebKit/LayoutTests/external/wpt/vibration/cancel-when-hidden-manual.html
index 5699707..0ae30b62 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/vibration/cancel-when-hidden-manual.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/vibration/cancel-when-hidden-manual.html
@@ -19,7 +19,6 @@
   the test has failed.
 </p>
 <button id='vib'>Vibrate!</button>
-<script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
 <script>
   var win;
 
@@ -35,4 +34,3 @@
     };
   }
 </script>
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/vibration/cancel-with-0-manual.html b/third_party/WebKit/LayoutTests/external/wpt/vibration/cancel-with-0-manual.html
index 6890d57..86981c11 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/vibration/cancel-with-0-manual.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/vibration/cancel-with-0-manual.html
@@ -16,7 +16,6 @@
       the test has failed.
     </p>
     <button id='vib'>Vibrate!</button>
-    <script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
     <script>
       if (undefined !== navigator.vibrate) {
           document.getElementById("vib").onclick = function () {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/vibration/cancel-with-array-0-manual.html b/third_party/WebKit/LayoutTests/external/wpt/vibration/cancel-with-array-0-manual.html
index 60689cc..9cdf282e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/vibration/cancel-with-array-0-manual.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/vibration/cancel-with-array-0-manual.html
@@ -19,7 +19,6 @@
   the test has failed.
 </p>
 <button id='vib'>Vibrate!</button>
-<script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
 <script>
   if (undefined !== navigator.vibrate) {
     document.getElementById('vib').onclick = function () {
@@ -30,4 +29,3 @@
     };
   }
 </script>
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/vibration/cancel-with-empty-array-manual.html b/third_party/WebKit/LayoutTests/external/wpt/vibration/cancel-with-empty-array-manual.html
index 9d4be2b..8e48173 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/vibration/cancel-with-empty-array-manual.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/vibration/cancel-with-empty-array-manual.html
@@ -16,7 +16,6 @@
       the test has failed.
     </p>
     <button id='vib'>Vibrate!</button>
-    <script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
     <script>
       if (undefined !== navigator.vibrate) {
           document.getElementById("vib").onclick = function () {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/vibration/cancel-with-new-manual.html b/third_party/WebKit/LayoutTests/external/wpt/vibration/cancel-with-new-manual.html
index 1cd9daf1..64e6e9b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/vibration/cancel-with-new-manual.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/vibration/cancel-with-new-manual.html
@@ -17,7 +17,6 @@
       failed.
     </p>
     <button id='vib'>Vibrate!</button>
-    <script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
     <script>
       if (undefined !== navigator.vibrate) {
           document.getElementById("vib").onclick = function () {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/vibration/invalid-values.html b/third_party/WebKit/LayoutTests/external/wpt/vibration/invalid-values.html
index a544ac23..523d2ce 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/vibration/invalid-values.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/vibration/invalid-values.html
@@ -12,7 +12,6 @@
 <div id='log'></div>
 <script src='/resources/testharness.js'></script>
 <script src='/resources/testharnessreport.js'></script>
-<script src='../support/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
 <script>
   test(function() {
     assert_throws(new TypeError(), function() {
@@ -76,4 +75,3 @@
     }
   }, 'pattern of {} resolves to [{}]');
 </script>
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/vibration/pattern-array-extra-manual.html b/third_party/WebKit/LayoutTests/external/wpt/vibration/pattern-array-extra-manual.html
index 3f5ccf3..b23323a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/vibration/pattern-array-extra-manual.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/vibration/pattern-array-extra-manual.html
@@ -15,7 +15,6 @@
       by one second intervals.
     </p>
     <button id='vib'>Vibrate!</button>
-    <script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
     <script>
       if (undefined !== navigator.vibrate) {
           document.getElementById("vib").onclick = function () {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/vibration/pattern-array-manual.html b/third_party/WebKit/LayoutTests/external/wpt/vibration/pattern-array-manual.html
index 43674bf8..0c7063f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/vibration/pattern-array-manual.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/vibration/pattern-array-manual.html
@@ -14,7 +14,6 @@
       by one second intervals.
     </p>
     <button id='vib'>Vibrate!</button>
-    <script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
     <script>
       if (undefined !== navigator.vibrate) {
           document.getElementById("vib").onclick = function () {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/vibration/pattern-array-with-0-manual.html b/third_party/WebKit/LayoutTests/external/wpt/vibration/pattern-array-with-0-manual.html
index dff2f1e..491f2b1 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/vibration/pattern-array-with-0-manual.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/vibration/pattern-array-with-0-manual.html
@@ -17,10 +17,8 @@
 </p>
 <button id='vib'>Vibrate!</button>
 <div id='log'></div>
-<script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
 <script>
   document.getElementById("vib").onclick = function () {
     navigator.vibrate([0, 0, 2000]);
   };
 </script>
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/vibration/silent-ignore.html b/third_party/WebKit/LayoutTests/external/wpt/vibration/silent-ignore.html
index c7447df..88ef5092 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/vibration/silent-ignore.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/vibration/silent-ignore.html
@@ -19,7 +19,6 @@
     <div id='log'></div>
     <script src='/resources/testharness.js'></script>
     <script src='/resources/testharnessreport.js'></script>
-    <script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
     <script>
       if (undefined !== navigator.vibrate) {
           test(function () {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/vibration/simple-array-manual.html b/third_party/WebKit/LayoutTests/external/wpt/vibration/simple-array-manual.html
index 4a85bd6..52fa997 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/vibration/simple-array-manual.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/vibration/simple-array-manual.html
@@ -13,7 +13,6 @@
     </p>
     <button id='vib'>Vibrate!</button>
     <div id='log'></div>
-    <script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
     <script>
       document.getElementById("vib").onclick = function () {
         navigator.vibrate([2000]);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/vibration/simple-scalar-manual.html b/third_party/WebKit/LayoutTests/external/wpt/vibration/simple-scalar-manual.html
index 0c7637bb..16fc2a9 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/vibration/simple-scalar-manual.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/vibration/simple-scalar-manual.html
@@ -13,7 +13,6 @@
       After hitting the button below, your device must vibrate continuously for about two seconds, once.
     </p>
     <button id='vib'>Vibrate!</button>
-    <script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
     <script>
       if (undefined !== navigator.vibrate) {
           document.getElementById("vib").onclick = function () {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/historical.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/historical.html
new file mode 100644
index 0000000..2407a87
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/historical.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>Historical Web Audio API features</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+[
+  "webkitAudioContext",
+  "webkitAudioPannerNode",
+  "webkitOfflineAudioContext",
+].forEach(name => {
+  test(function() {
+    assert_false(name in window);
+  }, name + " interface should not exist");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/js/vendor-prefixes.js b/third_party/WebKit/LayoutTests/external/wpt/webaudio/js/vendor-prefixes.js
deleted file mode 100644
index 287d692..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/webaudio/js/vendor-prefixes.js
+++ /dev/null
@@ -1,2 +0,0 @@
-window.AudioContext = window.AudioContext || window.webkitAudioContext;
-window.OfflineAudioContext = window.OfflineAudioContext || window.webkitOfflineAudioContext;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audiobuffer-interface/idl-test.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audiobuffer-interface/idl-test.html
index 41b07e9..634c0f5 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audiobuffer-interface/idl-test.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audiobuffer-interface/idl-test.html
@@ -2,7 +2,13 @@
 <html class="a">
 <head>
 <title>AudioBuffer IDL Test</title>
-<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script><script src="/resources/idlharness.js"></script><script src="/resources/WebIDLParser.js"></script><script src="/webaudio/js/lodash.js"></script><script src="/webaudio/js/vendor-prefixes.js"></script><script src="/webaudio/js/helpers.js"></script><style type="text/css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/idlharness.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/webaudio/js/lodash.js"></script>
+<script src="/webaudio/js/helpers.js"></script>
+<style type="text/css">
     #event-target-idl,
     #base-audio-context-idl
     { visibility:hidden; height: 0px;}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audiodestinationnode-interface/idl-test.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audiodestinationnode-interface/idl-test.html
index e4bd977..46ae074 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audiodestinationnode-interface/idl-test.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audiodestinationnode-interface/idl-test.html
@@ -2,7 +2,13 @@
 <html class="a">
 <head>
 <title>AudioDestinationNode IDL Test</title>
-<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script><script src="/resources/idlharness.js"></script><script src="/resources/WebIDLParser.js"></script><script src="/webaudio/js/lodash.js"></script><script src="/webaudio/js/vendor-prefixes.js"></script><script src="/webaudio/js/helpers.js"></script><style type="text/css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/idlharness.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/webaudio/js/lodash.js"></script>
+<script src="/webaudio/js/helpers.js"></script>
+<style type="text/css">
     #event-target-idl,
     #base-audio-context-idl,
     #audio-node-idl
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audioparam-interface/idl-test.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audioparam-interface/idl-test.html
index 6118748..f1f6b41 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audioparam-interface/idl-test.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audioparam-interface/idl-test.html
@@ -2,7 +2,13 @@
 <html class="a">
 <head>
 <title>AudioParam IDL Test</title>
-<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script><script src="/resources/idlharness.js"></script><script src="/resources/WebIDLParser.js"></script><script src="/webaudio/js/lodash.js"></script><script src="/webaudio/js/vendor-prefixes.js"></script><script src="/webaudio/js/helpers.js"></script><style type="text/css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/idlharness.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/webaudio/js/lodash.js"></script>
+<script src="/webaudio/js/helpers.js"></script>
+<style type="text/css">
     #audio-param-idl
     { visibility:hidden; height: 0px;}
   </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-delaynode-interface/idl-test.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-delaynode-interface/idl-test.html
index 8787414a..df65b58 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-delaynode-interface/idl-test.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-delaynode-interface/idl-test.html
@@ -2,7 +2,13 @@
 <html class="a">
 <head>
 <title>DelayNode IDL Test</title>
-<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script><script src="/resources/idlharness.js"></script><script src="/resources/WebIDLParser.js"></script><script src="/webaudio/js/lodash.js"></script><script src="/webaudio/js/vendor-prefixes.js"></script><script src="/webaudio/js/helpers.js"></script><style type="text/css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/idlharness.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/webaudio/js/lodash.js"></script>
+<script src="/webaudio/js/helpers.js"></script>
+<style type="text/css">
     #event-target-idl,
     #base-audio-context-idl,
     #audio-node-idl,
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-gainnode-interface/idl-test.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-gainnode-interface/idl-test.html
index e8500b85..098f1623 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-gainnode-interface/idl-test.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-gainnode-interface/idl-test.html
@@ -2,7 +2,13 @@
 <html class="a">
 <head>
 <title>GainNode IDL Test</title>
-<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script><script src="/resources/idlharness.js"></script><script src="/resources/WebIDLParser.js"></script><script src="/webaudio/js/lodash.js"></script><script src="/webaudio/js/vendor-prefixes.js"></script><script src="/webaudio/js/helpers.js"></script><style type="text/css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/idlharness.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/webaudio/js/lodash.js"></script>
+<script src="/webaudio/js/helpers.js"></script>
+<style type="text/css">
     #event-target-idl,
     #base-audio-context-idl,
     #audio-node-idl,
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-gainnode-interface/test-gainnode.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-gainnode-interface/test-gainnode.html
index 4f92fbb..b2b9f79b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-gainnode-interface/test-gainnode.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-gainnode-interface/test-gainnode.html
@@ -15,7 +15,6 @@
   <script src="/resources/testharness.js"></script>
   <script src="/resources/testharnessreport.js"></script>
   <script src="/webaudio/js/lodash.js"></script>
-  <script src="/webaudio/js/vendor-prefixes.js"></script>
   <script src="/webaudio/js/helpers.js"></script>
   <script src="/webaudio/js/buffer-loader.js"></script>
  </head>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/mediaElementAudioSourceToScriptProcessorTest.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/mediaElementAudioSourceToScriptProcessorTest.html
index ba6eec6..b234e64 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/mediaElementAudioSourceToScriptProcessorTest.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/mediaElementAudioSourceToScriptProcessorTest.html
@@ -17,7 +17,6 @@
   <script src="/resources/testharness.js"></script>
   <script src="/resources/testharnessreport.js"></script>
   <script src="/webaudio/js/lodash.js"></script>
-  <script src="/webaudio/js/vendor-prefixes.js"></script>
   <script src="/webaudio/js/helpers.js"></script>
   <script src="/webaudio/js/buffer-loader.js"></script>
  </head>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-waveshapernode-interface/curve-tests.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-waveshapernode-interface/curve-tests.html
index ad31366..a2e40777 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-waveshapernode-interface/curve-tests.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-waveshapernode-interface/curve-tests.html
@@ -5,7 +5,6 @@
 
 	<script type="text/javascript" src="/resources/testharness.js"></script>
 	<script type="text/javascript" src="/resources/testharnessreport.js"></script>
-	<script type="text/javascript" src="../../js/vendor-prefixes.js"></script>
 </head>
 <body>
 	<div id="log">
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/historical-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webrtc/historical-expected.txt
index a1c0a31f..0ba83d8a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/historical-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/historical-expected.txt
@@ -9,5 +9,9 @@
 FAIL RTCPeerConnection member onremovestream should not exist assert_false: expected false got true
 FAIL RTCPeerConnection member removeStream should not exist assert_false: expected false got true
 PASS RTCPeerConnection member updateIce should not exist
+PASS mozRTCIceCandidate interface should not exist
+PASS mozRTCPeerConnection interface should not exist
+PASS mozRTCSessionDescription interface should not exist
+FAIL webkitRTCPeerConnection interface should not exist assert_false: expected false got true
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/historical.html b/third_party/WebKit/LayoutTests/external/wpt/webrtc/historical.html
index 3a683e5..c57a1ca 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/historical.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/historical.html
@@ -23,4 +23,15 @@
     assert_false(name in RTCPeerConnection.prototype);
   }, "RTCPeerConnection member " + name + " should not exist");
 });
+
+[
+  "mozRTCIceCandidate",
+  "mozRTCPeerConnection",
+  "mozRTCSessionDescription",
+  "webkitRTCPeerConnection",
+].forEach(function(name) {
+  test(function() {
+    assert_false(name in window);
+  }, name + " interface should not exist");
+});
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/simplecall.html b/third_party/WebKit/LayoutTests/external/wpt/webrtc/simplecall.html
index 5eb676c..f27c7ff1 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/simplecall.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/simplecall.html
@@ -24,12 +24,6 @@
   <!-- These files are in place when executing on W3C. -->
   <script src="/resources/testharness.js"></script>
   <script src="/resources/testharnessreport.js"></script>
-  <script src="/common/vendor-prefix.js"
-          data-prefixed-objects=
-              '[{"ancestors":["navigator"], "name":"getUserMedia"}]'
-          data-prefixed-prototypes=
-               '[{"ancestors":["HTMLMediaElement"],"name":"srcObject"}]'>
-  </script>
   <script type="text/javascript">
   var test = async_test('Can set up a basic WebRTC call.', {timeout: 5000});
 
diff --git a/third_party/WebKit/LayoutTests/fast/harness/test-expectations.html b/third_party/WebKit/LayoutTests/fast/harness/test-expectations.html
index 452b07c..af0b4ad 100644
--- a/third_party/WebKit/LayoutTests/fast/harness/test-expectations.html
+++ b/third_party/WebKit/LayoutTests/fast/harness/test-expectations.html
@@ -5,6 +5,9 @@
 Displays LayoutTests results.
 -->
 <style>
+html {
+  scroll-behavior: smooth;
+}
 body {
   font-family: sans-serif;
   min-height: 200vh;
@@ -13,6 +16,10 @@
   margin-top: 4px;
 }
 
+p, h2, h3, h4 {
+  margin: 8px 0 4px 0;
+}
+
 #right-toolbar {
   position: absolute;
   top: 8px;
@@ -81,7 +88,7 @@
   line-height: 200%;
   cursor: zoom-in;
 }
-.expect:hover {
+.expect:hover, .expect:focus {
   background-color: #F4F4F4;
 }
 .expect:focus > .details {
@@ -162,22 +169,42 @@
   <div style="">go back to <a href="results.html">legacy results.html</a></div>
 </div>
 
-<div id="help" class="hidden">
+<div id="help" class="hidden hide-on-esc">
   <button style="position:fixed;right:30px;" onclick="GUI.toggleVisibility('help')">Close</button>
+  <h3>Keyboard navigation</h3>
+
+  <ul>
+  <li><b>Space</b> Show full results of the next test. This is the easiest way to navigate, just hit spacebar (and shift space to go back).
+  <li><b>Tab</b> to select the next test.
+  <li><b>Enter</b> to see test details. This will automatically close other details.
+  <li><b>C</b> to select text of the selected test.
+  <li><b>ctrl A</b> to select text of all tests for easy copying.
+  </ul>
+  <p>Modifiers:</p>
+  <ul>
+  <li><b>Shift</b> hold shift key to keep other details open.
+  <li><b>Alt|Option</b> hold alt key to open details on all results (limit: 100)
+  </ul>
   <p>This page lets you query and display test results.</p>
 
-  <h3>Results</h3>
+  <h3>Querying Results</h3>
 
-  <p>Select the results you are interested in with "Query" buttons.
+  <p>Select the results you are interested in using "Query" buttons.
   Narrow down the results further with "Filter" checkboxes.</p>
 
   <p>"Did not pass" query will exclude PASS and WONTFIX tests.</p>
 
-  <p>The results are shown in either plain text, or <a href="https://chromium.googlesource.com/chromium/src/+/master/docs/testing/layout_test_expectations.md">TestExpectations</a> format.</p>
-
-  <p>TestExpectations result lines usually looks like this:</p>
-
+  <h3>Displaying results.</h3>
+  <p>You can view the list of matched tests in several result formats.
+  Select format that works best for what you are trying to accomplish
+  using "format" popup. Following formats are available:</p>
+  <h4>1. Plain text</h4>
+  <pre>fast/forms/<a href="https://cs.chromium.org/chromium/src/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-rtl-ui.html?q=validation-bubble-appearance-rtl-ui.html&dr">validation-bubble-appearance-rtl-ui.html</a></pre>
+  <p>Plain text shows the test path.</p>
+  <h4>2. TestExpectations</a></h4>
 <pre><a href="#">crbug.com/bug</a> layout/test/path/<a href="#">test.html</a> [ Status ]</pre>
+  <p>TestExpectationsshow lines as they'd appear in <a
+    href="https://chromium.googlesource.com/chromium/src/+/master/docs/testing/layout_test_expectations.md">TestExpectations</a> file.</p>
 
   <p>The interesting part here is [ Status ]. Inside TestExpectations file, [ Status ]
   can have multiple values, representing all expected results. For example:</p>
@@ -194,19 +221,28 @@
   <p>If you are doing a lot of TestExpectation edits, the hope is that this will make
   your job as easy as copy and paste.</p>
 
-  <h3>Keyboard navigation</h3>
-
-  <ul>
-  <li><b>Tab</b> to select the next test.
-  <li><b>Enter</b> to see test details. This will automatically close other details.
-  <li><b>S</b> to select the full name of the test under the cursor
-  <li><b>ctrl A</b> to select text of all tests for easy copying.
-  </ul>
-  <p>Modifiers:</p>
-  <ul>
-  <li><b>Shift</b> hold shift key to keep other details open.
-  <li><b>Alt|Option</b> hold alt key to open details on all results (limit: 100)
-  </ul>
+  <h4>3. Crash site</h4>
+  <pre>
+### Crash site: Internals.cpp(3455)
+  editing/pasteboard/<a href="https://cs.chromium.org/chromium/src/third_party/WebKit/LayoutTests/editing/pasteboard/copy-paste-white-space.html?q=copy-paste-white-space.html&dr">copy-paste-white-space.html</a></pre>
+  <p>Crash site groups "Crash" tests with similar stack traces together. For best results, use it while filtering only crashes.</p>
+  <h4>4. Text mismatch</h4>
+  <pre>
+### Text mismatch failure: general text mismatch
+  accessibility/dimensions-include-descendants.html
+### Text mismatch failure: newlines only
+  accessibility/aria-controls-with-tabs.html
+### Text mismatch failure: spaces and tabs only
+  accessibility/aria-describedby-on-input.html
+</pre>
+  <p>Text mistmatch groups "Text failure" tests together.
+  </p>
+  <h3>Viewing results of a single test</h3>
+  <p>Click on images to zoom in. Select image viewing mode from the popup.</p>
+  <p>When viewing images for the first time, red flash highlights enclosing
+  rectangle that was colored red in the diff. Diff flash and color eyedropper
+  will not be available on file:// urls because of CSP.</p>
+  <h3>Bugs</h3>
   <p>If you are unhappy with results, please file a bug, or fix it <a href="https://cs.chromium.org/chromium/src/third_party/WebKit/LayoutTests/fast/harness/test-expectations.html">here</a>.</p>
 </div>
 <div id="summary">
@@ -284,21 +320,13 @@
   <pre id="rebaseline_script"></pre>
 </div>
 
-<template id="genericResult">
-<div class="result-frame">
-  <ul class="result-menu">
-  </ul>
-  <div class="result-output">
-  </div>
-</div>
-</template>
 <script>
 "use strict";
 
 // Results loaded from full_results_jsonp.js.
-let fullResults = {};
+let globalResults = {};
 
-let TestResultInformation = {
+const TestResultInformation = {
   "CRASH":      { index: 1, text: "Crash", isFailure: true, isSuccess: false },
   "FAIL":       { index: 2, text: "Failure", isFailure: true, isSuccess: false },
   "TEXT":       { index: 3, text: "Failure", isFailure: true, isSuccess: false },
@@ -311,39 +339,41 @@
   "WONTFIX":    { index: 10, text: "WontFix", isFailure: false, isSuccess: false },
   "NEEDSMANUALREBASELINE": { index: 11, text: "NeedsManualRebaseline", isFailure: false, isSuccess: false },
   "PASS":       { index: 12, text: "Pass", isFailure: false, isSuccess: true },
-}
+};
 
-// Sorted from worst to best
-let TestResultComparator = function (a, b) {
+// Sorted from worst to best.
+const TestResultComparator = function (a, b) {
   if (TestResultInformation[a].index > TestResultInformation[b].index)
     return 1;
   else if (TestResultInformation[a].index == TestResultInformation[b].index)
     return 0;
   else
     return -1;
-}
+};
 
 // Traversal traverses all the tests.
 // Use Traversal.traverse(filter, action) to perform action on selected tests.
-let Traversal = function(testRoot) {
-  this.root = testRoot;
-  this.reset();
-}
-Traversal.prototype = {
-  traverse: function(filter, action) {
+class Traversal {
+  constructor(testRoot) {
+    this.root = testRoot;
+    this.reset();
+  }
+
+  traverse(filter, action) {
     action = action || function() {};
     this._helper(this.root, "", filter, action);
-  },
-  reset: function() {
+  }
+
+  reset() {
     this.testCount = 0;
     this.filteredCount = 0;
     this.lastDir = "";
     this.html = [];
     this.resultCounts = {};
     return this;
-  },
+  }
 
-  _helper: function(node, path, filter, action) {
+  _helper(node, path, filter, action) {
     if ("actual" in node) {
       this.testCount++;
       if (filter(node, path)) {
@@ -360,44 +390,55 @@
         this._helper(node.get(p), path + "/" + p, filter, action);
     }
   }
-}
+} // class Traversal
 
-// Parses test path into parts: dir, extension, href.
-let PathParser = function(path) {
-  this.path = path;
-  let [href, dir, file] = path.match("/(.*)/(.*)");
-  this.dir = dir;
-  this.file = file;
-  let tmp;
-  [tmp, this.basename, this.extension] = file.match(/(.*)\.(\w+)/);
-  this.testHref = this.testBaseHref() + href.replace(/\/virtual\/[^\/]*/, "");
-}
-PathParser.prototype = {
-  resultLink: function(resultName) {
+const PathParserGlobals = {
+  layout_tests_dir: null,
+  chromium_revision: null
+};
+
+class PathParser {
+  constructor(path) {
+    this.path = path;
+    let [href, dir, file] = path.match("/(.*)/(.*)");
+    this.dir = dir;
+    this.file = file;
+    let tmp;
+    [tmp, this.basename, this.extension] = file.match(/(.*)\.(\w+)/);
+    this.testHref = this.testBaseHref() + href.replace(/\/virtual\/[^\/]*/, "");
+  }
+
+  static initGlobals(fullResults) {
+    for (let p in PathParserGlobals)
+      PathParserGlobals[p] = fullResults[p];
+  }
+
+  resultLink(resultName) {
     return this.dir + "/" + this.basename + resultName;
-  },
-  testBaseHref: function() {
+  }
+
+  testBaseHref() {
     if (window.localStorage.getItem("testLocationOverride")) {
       // Experimental preference.
       // Use "window.localStorage.setItem("testLocationOverride", "file://path/to/your/LayoutTests")
       return window.localStorage.getItem("testLocationOverride");
-    } else if (fullResults.layout_tests_dir) {
-      return fullResults.layout_tests_dir;
+    } else if (PathParserGlobals.layout_tests_dir) {
+      return PathParserGlobals.layout_tests_dir;
     } else if (location.toString().indexOf('file://') == 0) {
       // tests were run locally.
       return "../../../third_party/WebKit/LayoutTests";
-    } else if (fullResults.chromium_revision) {
+    } else if (PathParserGlobals.chromium_revision) {
       // Existing crrev list is incorrect:  https://crbug.com/750347
-      let correctedRevision = fullResults.chromium_revision.replace("refs/heads/master@{#", "").replace("}", "");
+      let correctedRevision = PathParserGlobals.chromium_revision.replace("refs/heads/master@{#", "").replace("}", "");
       return "https://crrev.com/" + correctedRevision + "/third_party/WebKit/LayoutTests";
     } else {
       return "https://chromium.googlesource.com/chromium/src/+/master/third_party/WebKit/LayoutTests";
     }
   }
-}
+} // class PathParser
 
 // Report deals with displaying a single test.
-let Report = {
+const Report = {
 
   getDefaultPrinter: () => {
     let val = document.querySelector("#report_format").value;
@@ -417,12 +458,12 @@
 
   printPlainTest: (test, path, traversal) => {
     let pathParser = new PathParser(path);
-    let html = ""
-      + "<input type='checkbox' class='rebaseline-checkbox' style='display:none'>"
-      + pathParser.dir + "/"
-      + "<a target='test' tabindex='-1' href='" + pathParser.testHref + "'>"
-      + pathParser.file + "</a>";
-    html = "<div class='expect' tabindex='0' data-id='"+ test.expectId +"'><div class='details'></div>" + html + "</div>";
+    let html = `
+    <div class='expect' tabindex='0' data-id='${test.expectId}'>
+      <div class='details'></div>
+      <input type='checkbox' class='rebaseline-checkbox' style='display:none'>
+     ${pathParser.dir}/<a target='test' tabindex='-1' href='${pathParser.testHref}'>${pathParser.file}</a>
+    </div>`;
     traversal.html.push(html);
   },
 
@@ -452,26 +493,24 @@
     let status = "";
     for (let key of statusMap.keys()) {
       if (statusMap.get(key) == "bold")
-        status += " <b>" + TestResultInformation[key].text + "</b>";
+        status += ` <b>${TestResultInformation[key].text}</b>`;
       else
-        status += " " + TestResultInformation[key].text;
+        status += ` ${TestResultInformation[key].text}`;
     }
     let bug = test.actualMap.has("PASS") ? "" : "<span class='warn'>NEEDBUG</span>";
     if (test.bugs && test.bugs.length > 0) {
       bug = "";
       for (let b of test.bugs) {
-        bug += "<a target='crbug' tabindex='-1' href='https://" + b + "'>" + b + "</a> ";
+        bug += `<a target='crbug' tabindex='-1' href='https://${b}'>${b}</a> `;
       }
     }
-    let html = "";
-    html += bug;
-    html += " "
-      + "<input type='checkbox' class='rebaseline-checkbox' style='display:none'>"
-      + pathParser.dir + "/"
-      + "<a target='test' tabindex='-1' href='" + pathParser.testHref + "'>"
-      + pathParser.file + "</a>";
-    html += " [ " + status + " ]";
-    html = "<div class='expect' tabindex='0' data-id='"+ test.expectId +"'><div class='details'></div>" + html + "</div>";
+    let html = `
+      <div class='expect' tabindex='0' data-id='${test.expectId}'><div class='details'></div>${bug}
+        <input type='checkbox' class='rebaseline-checkbox' style='display:none'>
+        ${pathParser.dir}/<a target='test' tabindex='-1' href='${pathParser.testHref}'>${pathParser.file}</a>
+        [ ${status} ]
+    </div>
+    `;
     traversal.html.push(html);
   },
 
@@ -495,13 +534,13 @@
     Report.printWithKey(test, path, traversal, "text_mismatch");
   },
 
-  indicateNone: function(report) {
+  indicateNone: (report) => {
     let pre = document.createElement("div");
     pre.innerHTML = "<i>None</i>";
     report.appendChild(pre);
   },
 
-  renderResultList: function(html) {
+  renderResultList: (html) => {
     let report = document.querySelector("#report");
     if (report.childNodes.length === 0 && html.length === 0) {
       Report.indicateNone(report);
@@ -513,7 +552,7 @@
     report.appendChild(pre);
   },
 
-  createContainerForGroup: function(report, key, keyed_title, null_title) {
+  createContainerForGroup: (report, key, keyed_title, null_title) => {
     let container = document.createElement("div");
     container.setAttribute("key", key);
     container.innerHTML = ""
@@ -543,7 +582,7 @@
     return container;
   },
 
-  renderGroup: function(html, keyed_title, null_title) {
+  renderGroup: (html, keyed_title, null_title) => {
     let report = document.querySelector("#report");
     if (report.childNodes.length === 0 && html.length === 0) {
       Report.indicateNone(report);
@@ -566,17 +605,17 @@
       renderMap[key].container.insertAdjacentHTML('beforeend', renderMap[key].html);
   },
 
-  renderGroupCrashSite: function(html) {
+  renderGroupCrashSite: (html) => {
     Report.renderGroup(html, "Crash site", "Didn't crash");
   },
 
-  renderGroupTextMismatch: function(html) {
+  renderGroupTextMismatch: (html) => {
     Report.renderGroup(html, "Text mismatch failure", "Didn't find text mismatch");
   },
 
-  getTestById: function(testId) {
+  getTestById: (testId) => {
     let test;
-    (new Traversal(fullResults.tests)).traverse(function(thisTest) {
+    (new Traversal(globalResults.tests)).traverse(function(thisTest) {
       if (thisTest.expectId == testId)
         test = thisTest;
         return false;
@@ -584,94 +623,73 @@
     return test;
   },
 
-  // Returns links to test results [ {text:, link:}, ... ]
-  getResultLinks: function (test) {
-    let links = [];
+   // Returns links to test results [ {text:, link:}, ... ]
+  getResultToolbars: (test) => {
+    let toolbars = [];
     let pathParser = new PathParser(test.expectPath);
-    links.push({text: test.actual});
+    toolbars.push(new PlainHtmlToolbar().createDom(test.actual));
     for (let result of test.actualMap.keys()) {
       switch(result) {
         case "PASS":
         case "SLOW":
           if (Filters.unexpectedPass(test))
-            links.push({text: "Expected: " + test.expected});
+            toolbars.push(new PlainHtmlToolbar().createDom("Expected: " + test.expected));
           if (!test.has_stderr)
-            links.push({text: "No errors"});
+            toolbars.push(new PlainHtmlToolbar().createDom("No errors"));
           break;
         case "SKIP":
-          links.push({text: "Test did not run."});
+          toolbars.push(new PlainHtmlToolbar().createDom("Test did not run."));
           break;
         case "CRASH":
-          links.push({text: "crash log", link: pathParser.resultLink("-crash-log.txt")});
+          toolbars.push(new SimpleLinkToolbar().createDom(
+            pathParser.resultLink("-crash-log.txt"), "Crash log", "crash log"));
           break;
         case "TIMEOUT":
-          links.push({text: "Test timed out. "
-            + ("time" in test ? `(${test.time}s)` : "")});
+          toolbars.push(new PlainHtmlToolbar().createDom("Test timed out. "
+            + ("time" in test ? `(${test.time}s)` : "")));
           if (test.text_mismatch)
-            links.push({text: "actual text", link: pathParser.resultLink('-actual.txt')});
+            toolbars.push(new TextResultsToolbar().createDom(test));
           break;
         case "TEXT":
-          links.push({text: "actual text", link: pathParser.resultLink('-actual.txt')});
-          if (!test.is_testharness_test) {
-            links.push({text: "expected text", link: pathParser.resultLink('-expected.txt')});
-            links.push({text: "diff", link: pathParser.resultLink('-diff.txt')});
-          }
+          toolbars.push(new TextResultsToolbar().createDom(test));
           break;
         case "IMAGE":
-          links.push({text: "actual image", link: pathParser.resultLink("-actual.png")});
-          links.push({text: "expected image ", link: pathParser.resultLink("-expected.png")});
-          links.push({text: "diff", link: pathParser.resultLink("-diff.png")});
+          toolbars.push(new ImageResultsToolbar().createDom(test));
           break;
         case "IMAGE+TEXT":
-          links.push({text: "actual image", link: pathParser.resultLink("-actual.png")});
-          links.push({text: "expected image ", link: pathParser.resultLink("-expected.png")});
-          links.push({text: "diff", link: pathParser.resultLink("-diff.png")});
-          links.push({text: "actual text", link: pathParser.resultLink('-actual.txt')});
-          if (!test.is_testharness_test) {
-            links.push({text: "expected text", link: pathParser.resultLink('-expected.txt')});
-            links.push({text: "diff", link: pathParser.resultLink('-diff.txt')});
-          }
+          toolbars.push(new ImageResultsToolbar().createDom(test));
+          toolbars.push(new TextResultsToolbar().createDom(test));
           break;
         case "MISSING":
-          links.push({text: "Test is missing."});
+          toolbars.push(new PlainHtmlToolbar().createDom("Baseline is missing."));
           break;
         default:
           console.error("unexpected actual", test.actual);
       }
     }
     if (test.has_stderr) {
-      links.push({text: "stderr", link: pathParser.resultLink("-stderr.txt")});
+      toolbars.push(new SimpleLinkToolbar().createDom(
+            pathParser.resultLink("-stderr.txt"), "standard error", "stderr"));
     }
-    return links;
+    return toolbars;
   },
-  getResultsDiv: function(test) {
-    let clone = document.importNode(
-      document.querySelector("#genericResult").content, true);
-    let div = clone.children[0];
-    // Initialize the results
+  getResultsDiv: (test) => {
+    let div = document.createElement("div");
+    div.classList.add("result-frame");
+    div.innerHTML = `
+      <ul class="result-menu"></ul>
+      <div class="result-output"></div>
+    `;
+    // Initialize the results.
     let menu = div.querySelector(".result-menu");
-    menu.innerHTML = "";
-    for (let link of Report.getResultLinks(test)) {
-      let li = document.createElement("li");
-      if (link.link) {
-        let anchor = document.createElement("a");
-        anchor.setAttribute("onclick", "return GUI.loadResult(this)");
-        anchor.setAttribute("href", link.link || "");
-        anchor.setAttribute("onfocus", "return GUI.loadResult(this)");
-        anchor.innerText = link.text;
-        li.appendChild(anchor);
-      }
-      else {
-        li.innerText = link.text;
-      }
-      menu.appendChild(li);
-    }
+    for (let toolbar of Report.getResultToolbars(test))
+      menu.appendChild(toolbar);
     return div;
   }
-}
+}; // Report
 
 // Query generates a report for a given query.
-let Query = {
+const Query = {
   lastReport: null,
   currentRAF: null,
   currentPromise: null,
@@ -698,7 +716,7 @@
   },
 
   resetFilters: function() {
-    // Reset all filters
+    // Reset all filters.
     for (let el of Array.from(
           document.querySelectorAll("#filters > label"))) {
       el.querySelector('input').checked = true;
@@ -752,8 +770,8 @@
       );
   },
 
-  // generateReport is async, returns promise
-  // promise if fullfilled when traversal completes. Display will continue async.
+  // generateReport is async, returns promise.
+  // promise id fullfilled when traversal completes. Display will continue async.
   generateReport: function(name, filter, report) {
     if (this.currentRAF)
       window.cancelAnimationFrame(this.currentRAF);
@@ -761,13 +779,13 @@
     filter = filter || this.lastReport.filter;
     name = name || this.lastReport.name;
 
-    // Store last report to redisplay
-    this.lastReport = { name: name, filter: filter };
+    // Store last report to redisplay.
+    this.lastReport = {name: name, filter: filter};
     this.createReportPromise();
 
     document.querySelector("#report").innerHTML = "";
     document.querySelector("#report_title").innerHTML = name;
-    let traversal = new Traversal(fullResults.tests);
+    let traversal = new Traversal(globalResults.tests);
 
     let chunkSize = 1000;
     let index = 0;
@@ -777,18 +795,18 @@
       index += chunkSize;
       if (index < traversal.html.length)
         this.currentRAF = window.requestAnimationFrame(callback);
-    }
+    };
     window.setTimeout( _ => {
       traversal.traverse(filter, report.print);
       this.completeReportPromise(traversal);
-      this.currentRAF = window.requestAnimationFrame(callback)
+      this.currentRAF = window.requestAnimationFrame(callback);
     }, 0);
     return this.currentPromise;
   }
-};
+}; // Query
 
 // Test filters for queries.
-let Filters = {
+const Filters = {
   containsPass: function (map) {
     return map.has("PASS") || map.has("SLOW");
   },
@@ -833,24 +851,25 @@
   actual: tag => {  // Returns comparator for tag.
     return function(test) {
       return test.actualMap.has(tag);
-    }
+    };
   },
   wontfix: test => test.expected == "WONTFIX",
   all: _ => true,
   flaky: test => test.actualMap.size > 1
-}
+}; // Filters
 
 // Event handling, initialization.
-let GUI = {
+const GUI = {
   initPage: function(results) {
     results.tests = GUI.convertToMap(results.tests);
-    fullResults = results;
+    globalResults = results;
     if (window.localStorage.getItem("reportFormat")) {
       document.querySelector("#report_format").value = window.localStorage.getItem("reportFormat");
     }
-    GUI.optimizeResults();
-    GUI.printSummary(fullResults);
+    GUI.optimizeResults(globalResults);
+    GUI.printSummary(globalResults);
     GUI.initEvents();
+    PathParser.initGlobals(results);
     // Show unexpected failures on startup.
     document.querySelector("#button_unexpected_fail").click();
   },
@@ -873,8 +892,8 @@
     }
   },
 
-  optimizeResults: function() {
-    // Optimizes fullResults for querying
+  optimizeResults: function(fullResults) {
+    // Optimizes fullResults for querying.
     let t = new Traversal(fullResults.tests);
     // To all tests add:
     // - test.expectId, a unique id
@@ -882,7 +901,7 @@
     // - test.actualMap, map of actual results
     // - test.actualFinal, last result
     // - test.expectedMap, maps of expected results
-    // For all crashing tests without crash_site, set crash_site to "Can't identify"
+    // For all crashing tests without crash_site, set crash_site to "Can't identify".
     let nextId = 1;
     t.traverse(
       test => true,
@@ -905,6 +924,48 @@
     );
   },
 
+  nextExpectation: function(expectation) {
+    let nextSiblingWithKeyedParentSkip = function(el) {
+      let sibling = el.nextElementSibling;
+      if (sibling == null && el.parentNode.hasAttribute("key")) {
+        let nextKey = el.parentNode.nextElementSibling;
+        if (nextKey)
+          sibling = nextKey.firstElementChild;
+      }
+      return sibling;
+    };
+    if (expectation == null)
+      return null;
+    let sibling = nextSiblingWithKeyedParentSkip(expectation);
+    while (sibling) {
+      if (sibling.classList.contains("expect"))
+        return sibling;
+      else
+        sibling = nextSiblingWithKeyedParentSkip(sibling);
+    }
+  },
+
+  previousExpectation: function(expectation) {
+    let previousSiblingWithKeyedParentSkip = function(el) {
+      let sibling = el.previousElementSibling;
+      if (sibling == null && el.parentNode.hasAttribute("key")) {
+        let nextKey = el.parentNode.previousElementSibling;
+        if (nextKey)
+          sibling = nextKey.lastElementChild;
+      }
+      return sibling;
+    };
+    if (expectation == null)
+      return null;
+    let sibling = previousSiblingWithKeyedParentSkip(expectation);
+    while (sibling) {
+      if (sibling.classList.contains("expect"))
+        return sibling;
+      else
+        sibling = previousSiblingWithKeyedParentSkip(sibling);
+    }
+  },
+
   initEvents: function() {
     document.addEventListener("click", function(ev) {
       if (GUI.isExpectation(ev.target)) {
@@ -913,30 +974,57 @@
         ev.stopPropagation();
       }
     });
-    document.addEventListener('keydown', ev => {
+    document.addEventListener("keydown", ev => {
       {
         switch(ev.key) {
+          case "Escape": // Close/hide divs.
+            for (let el of Array.from(document.querySelectorAll(".close-on-esc")))
+              el.remove();
+            for (let el of Array.from(document.querySelectorAll(".hide-on-esc")))
+              el.classList.add("hidden");
+            if (document.activeElement && document.activeElement.classList.contains("expect"))
+              GUI.hideResults(document.activeElement);
+            break;
+          case " ": // Scroll to next expectation.
+            let nextExpectation;
+            let openDetails = document.querySelector(".details.open");
+            if (openDetails) {
+              let openExpectation = GUI.closest(openDetails, "expect");
+              nextExpectation = ev.shiftKey ?
+                GUI.previousExpectation(openExpectation) :
+                GUI.nextExpectation(openExpectation);
+              GUI.hideResults(openExpectation);
+            } else {
+              if (document.activeElement && document.activeElement.classList.contains("expect"))
+                nextExpectation = document.activeElement;
+              else
+                nextExpectation = document.querySelector(".expect");
+            }
+            if (nextExpectation) {
+              nextExpectation.focus();
+              GUI.showResults(nextExpectation);
+            }
+            ev.preventDefault();
+            break;
           case "Enter":
             if (GUI.isExpectation(ev.target))
               GUI.toggleResults(ev.target, ev);
-          break;
-          case "s":
-          case "S":
+            break;
+          case "c":
+          case "C":
             if (GUI.isExpectation(ev.target))
               GUI.selectText(ev.altKey ? document.querySelector("#report") : ev.target);
             else {
               GUI.selectText(document.querySelector("#report"));
             }
-          break;
+            break;
           case "a":
           case "A":
             if (ev.ctrlKey) {
               GUI.selectText(document.querySelector("#report"));
               ev.preventDefault();
             }
-          break;
-          default:
-            ;
+            break;
         }
       }
     });
@@ -955,16 +1043,16 @@
   },
 
   isExpectation: function(el) {
-    return el.classList.contains("expect")
+    return el.classList.contains("expect");
   },
 
-  printSummary: function (r) {
-    if (r.builder_name)
-      document.querySelector("#builder_name").innerText = r.builder_name;
-    document.querySelector("#summary_total").innerText = r.num_passes + r.num_regressions;
-    document.querySelector("#summary_passed").innerText = r.num_passes;
-    document.querySelector("#summary_regressions").innerText = r.num_regressions;
-    let failures = r["num_failures_by_type"];
+  printSummary: function (fullResults) {
+    if (fullResults.builder_name)
+      document.querySelector("#builder_name").innerText = fullResults.builder_name;
+    document.querySelector("#summary_total").innerText = fullResults.num_passes + fullResults.num_regressions;
+    document.querySelector("#summary_passed").innerText = fullResults.num_passes;
+    document.querySelector("#summary_regressions").innerText = fullResults.num_regressions;
+    let failures = fullResults["num_failures_by_type"];
     var totalFailures = 0;
 
     let resultsText = "";
@@ -980,7 +1068,7 @@
       "count_unexpected_fail": 0,
       "count_testexpectations": 0,
       "count_flaky": 0
-    }
+    };
     var t = new Traversal(fullResults.tests);
     t.traverse( test => {
       if (Filters.unexpectedPass(test))
@@ -993,8 +1081,8 @@
         counts.count_flaky++;
     });
     for (let p in counts)
-      document.getElementById(p).innerText = counts[p];
-    document.querySelector("#count_all").innerText = r.num_passes + r.num_regressions;
+      document.querySelector("#" + p).innerText = counts[p];
+    document.querySelector("#count_all").innerText = fullResults.num_passes + fullResults.num_regressions;
   },
 
   toggleVisibility: function(id) {
@@ -1028,6 +1116,18 @@
     }
   },
 
+  getResultViewer: function(toolbar) {
+    let output = GUI.closest(toolbar, "result-frame").querySelector(".result-output");
+    if (output && output.children.length > 0)
+      return output.children[0];
+  },
+
+  setResultViewer: function(toolbar, viewer) {
+    let output = GUI.closest(toolbar, "result-frame").querySelector(".result-output");
+    output.innerHTML = "";
+    output.appendChild(viewer);
+  },
+
   closest: function (el, className) {
     while (el) {
       if (el.classList.contains(className))
@@ -1037,21 +1137,6 @@
     }
   },
 
-  loadResult: function(anchor) {
-    if (!anchor.getAttribute("href"))
-      return false;
-    let frame = GUI.closest(anchor, "result-frame");
-    let output = frame.querySelector(".result-output");
-    let iframe = output.querySelector("iframe");
-    if (!iframe) {
-      iframe = document.createElement("iframe");
-      output.appendChild(iframe);
-    }
-    iframe.src = anchor.href;
-    iframe.setAttribute("tabindex", -1);
-    return false;
-  },
-
   showResults: function(expectation, doNotScroll) {
     let details = expectation.querySelector(".details");
     if (details.classList.contains("open"))
@@ -1064,20 +1149,23 @@
     let results = Report.getResultsDiv(test);
     results.classList.add("results");
     expectation.parentNode.insertBefore(results, expectation.nextSibling);
-    let firstLink = results.querySelector(".result-menu a");
-    if (firstLink) {
-      firstLink.click();
+    for (let toolbar of Array.from(results.querySelectorAll(".tx-toolbar"))) {
+      if (toolbar.showDefault) {
+        toolbar.showDefault();
+        break;
+      }
     }
     if (doNotScroll) {
       return;
     }
-    // Scroll into view
-    let bottomDelta = results.offsetTop + results.offsetHeight - document.documentElement.clientHeight - window.scrollY + 48;
-    if (bottomDelta > 0)
-      window.scrollBy(0, bottomDelta);
-    let topDelta = results.offsetTop - document.documentElement.clientHeight - window.scrollY - 24;
-    if (topDelta > 0)
-      window.scrollBy(0, topDelta);
+    // Scroll result into view, leaving space for image zoom, and
+    // test title on top.
+    let zoomHeight = window.innerWidth / 3 + 10;
+    let resultHeight = Math.min(window.innerHeight - 80, 630) + 34;
+    let overflow = zoomHeight + resultHeight + expectation.offsetHeight - window.innerHeight;
+    if (overflow > 0)
+      zoomHeight = Math.max(0, zoomHeight - overflow);
+    window.scrollTo(0, expectation.offsetTop - zoomHeight);
   },
 
   hideResults: function(expectation) {
@@ -1087,15 +1175,15 @@
     expectation.querySelector(".details").classList.remove("open");
     expectation.nextSibling.remove();
   }
-}
+}; // GUI
 
-let RebaselineTool = {
+const RebaselineTool = {
   getCheckboxes: function() {
     return document.querySelectorAll(".rebaseline-checkbox");
   },
 
   selectAll: function() {
-    let scriptPre = document.getElementById('rebaseline_script');
+    let scriptPre = document.querySelector('#rebaseline_script');
     getSelection().selectAllChildren(scriptPre);
     document.execCommand('copy');
   },
@@ -1129,10 +1217,10 @@
         console.error("could not find test by id");
         return;
       }
-      for (let link of Report.getResultLinks(test)) {
-        if (!link.link || link.text.indexOf("actual") == -1)
-          continue;
-        rebaselinedTests.push(link.link);
+      for (let toolbar of Report.getResultToolbars(test)) {
+        for (let anchor of toolbar.querySelectorAll(".actual")) {
+          rebaselinedTests.push(anchor.href);
+        }
       }
     });
     return rebaselinedTests;
@@ -1170,14 +1258,756 @@
 
   doneRebaselineSelection: function() {
     RebaselineTool.hideRebaselineCheckboxes();
-    document.getElementById('rebaseline_script').innerHTML =
+    document.querySelector('#rebaseline_script').innerHTML =
         RebaselineTool.generateRebaselineScript(
             RebaselineTool.getRebaselineList());
     GUI.toggleVisibility('rebaseline');
     RebaselineTool.selectAll();
   }
-}
+}; // RebaselineTool
 
+</script>
+
+<script>
+// test-expectation components
+// These components are in a separate script tag.
+// They are independent of the rest of the page so they can be reused
+// in different pages in the future.
+//
+// Current components include toolbars, and viewers.
+// Toolbars control viewers.
+// Viewers present different views into test results.
+class TXToolbar {
+  importStyle() {
+    if (document.querySelector("#TXToolbarCSS"))
+      return;
+    let style = document.createElement("style");
+    style.setAttribute("type", "text/css");
+    style.setAttribute("id", "TXToolbarCSS");
+    style.innerText =
+    `.tx-toolbar a[data-selected] {
+      background-color: #DDD;
+      text-decoration-color: aquamarine;
+    }
+    .tx-toolbar a {
+      padding-left: 4px;
+      padding-right: 4px;
+    }
+    `;
+    document.head.appendChild(style);
+  }
+
+  getViewer() {
+    let viewer = GUI.getResultViewer(this.toolbar);
+    return (viewer && viewer.owner == this) ? viewer : null;
+  }
+
+  get defaultExtendSelection() {
+    return false;
+  }
+
+  selectAnchor(target, extendSelection) {
+    let toggle = false;
+    if (extendSelection === undefined) {
+      toggle = true;
+      extendSelection = this.defaultExtendSelection;
+    }
+    for (let anchor of Array.from(this.toolbar.querySelectorAll("a"))) {
+      if (anchor == target) {
+        if (toggle) {
+          if (anchor.hasAttribute("data-selected"))
+            anchor.removeAttribute("data-selected");
+          else
+            anchor.setAttribute("data-selected", "");
+        } else {
+          anchor.setAttribute("data-selected", "");
+        }
+      }
+      else if (!extendSelection)
+        anchor.removeAttribute("data-selected");
+    }
+    this.updateViewer(target);
+  }
+} // class TXToolbar
+
+class ImageResultsToolbar extends TXToolbar {
+  constructor() {
+    super();
+    this.boundViewOptionsChangeHandler = this.viewOptionsChangeHandler.bind(this);
+  }
+
+  createDom(test) {
+    this.importStyle();
+    let pathParser = new PathParser(test.expectPath);
+    this.toolbar = document.createElement("li");
+    this.toolbar.showDefault = _ => this.viewOptionsChangeHandler({target: this.toolbar.querySelector(".view-options")});
+    this.toolbar.classList.add("image-toolbar");
+    this.toolbar.classList.add("tx-toolbar");
+    this.toolbar.innerHTML = `
+      image:
+      <a class="actual" href="${pathParser.resultLink("-actual.png")}" title="Actual result">actual</a>
+      <a class="expected" href="${pathParser.resultLink("-expected.png")}" title="Expected result">expected</a>
+      <a class="diff" href="${pathParser.resultLink("-diff.png")}" title="Difference">diff</a>
+      <label><select class="view-options">
+        <option value="single">Single view</option>
+        <option value="animated">Animated view</option>
+        <option value="multiple">Side by side view</option>
+      </label>
+    `;
+    this.toolbar.addEventListener("click", ev => {
+      if (ev.target.tagName == "A") {
+        this.selectAnchor(ev.target);
+        ev.preventDefault();
+      }
+    });
+
+    let viewOptions = this.toolbar.querySelector(".view-options");
+    viewOptions.addEventListener("change", this.boundViewOptionsChangeHandler);
+    if (window.localStorage.getItem("ImageToolbarView"))
+      viewOptions.value = window.localStorage.getItem("ImageToolbarView");
+    else
+      viewOptions.value = "animated";
+    return this.toolbar;
+  }
+
+  viewOptionsChangeHandler(ev) {
+    let viewOptions = ev.target;
+    try {
+      window.localStorage.setItem("ImageToolbarView", viewOptions.value);
+    } catch(ex) {}
+
+    switch(viewOptions.value) {
+    case "animated": {
+      let selectedAnchors = Array.from(this.toolbar.querySelectorAll("a[data-selected]"));
+      if (selectedAnchors.length == 0)
+        this.selectAnchor(this.toolbar.querySelector("a"));
+      this.setAnimation(true);
+      }
+      break;
+    case "single": {
+      this.setAnimation(false);
+      // Make sure only one is selected.
+      let selectedAnchors = Array.from(this.toolbar.querySelectorAll("a[data-selected]"));
+      if (selectedAnchors.length == 0)
+        this.selectAnchor(this.toolbar.querySelector("a"));
+      else
+        this.selectAnchor(selectedAnchors[0]);
+      }
+      break;
+    case "multiple": {
+      this.setAnimation(false);
+      for (let anchor of Array.from(this.toolbar.querySelectorAll("a")))
+        this.selectAnchor(anchor, true);
+      }
+      break;
+    default:
+      console.error("unknown view option");
+    }
+  }
+
+  get defaultExtendSelection() {
+    return this.toolbar.querySelector(".view-options").value == "multiple";
+  }
+
+  updateViewer(element) {
+    // Find currently selected anchor.
+    let selectedAnchors = Array.from(this.toolbar.querySelectorAll("a[data-selected]"));
+    if (selectedAnchors.length == 0) {
+      selectedAnchors.push(this.toolbar.querySelector("a"));
+      selectedAnchors[0].setAttribute("data-selected", "");
+    }
+    let viewer = this.getViewer();
+    if (!viewer) {
+      let imgInfo = Array.from(this.toolbar.querySelectorAll("a")).map(
+        anchor => { return {src: anchor.href, title: anchor.title}; });
+      viewer = (new ImageResultsViewer()).createDom(imgInfo, this);
+      this.setAnimation(this.toolbar.querySelector(".view-options").value == "animated");
+      GUI.setResultViewer(element, viewer);
+    }
+    viewer.showImages(selectedAnchors.map(anchor => anchor.href));
+  }
+
+  setAnimation(animate) {
+    if (animate) {
+      if (!this.animationIntervalId)
+        this.animationIntervalId = window.setInterval(_ => {
+          if (!this.getViewer()) {
+            console.log("element is gone");
+            window.clearInterval(this.animationIntervalId);
+            this.animationIntervalId = null;
+            return;
+          }
+          // Find next anchor.
+          let allAnchors = Array.from(this.toolbar.querySelectorAll("a"));
+          let nextAnchor = allAnchors[0];
+          for (let i = 0; i < allAnchors.length; i++) {
+            if (allAnchors[i].hasAttribute("data-selected")) {
+              nextAnchor = allAnchors[(i + 1) % (allAnchors.length - 1)];
+              break;
+            }
+          }
+          this.selectAnchor(nextAnchor, false);
+        }, 400);
+    } else {
+      if (this.animationIntervalId) {
+        window.clearInterval(this.animationIntervalId);
+        this.animationIntervalId = null;
+      }
+    }
+  }
+} // class ImageResultsToolbar
+
+class ImageResultsViewer {
+  constructor() {
+    this.boundMouseMoveHandler = this.mouseMoveHandler.bind(this);
+    this.boundTileScrollHandler = this.tileScrollHandler.bind(this);
+    this.boundWheelHandler = this.tileWheelHandler.bind(this);
+  }
+
+  importStyle() {
+    if (document.querySelector("#ImageViewerCSS"))
+      return;
+    let style = document.createElement("style");
+    style.setAttribute("type", "text/css");
+    style.setAttribute("id", "ImageViewerCSS");
+    style.innerText =
+    ` .image-viewer {
+      position: relative;
+      display: flex;
+    }
+    .image-viewer-tile {
+      flex-shrink: 1;
+      border: 1px solid #EEE;
+      overflow: auto;
+      max-height: calc(100vh - 80px);
+      margin-right: 8px;
+    }
+    .image-viewer-highlight {
+      position: absolute;
+      background-color: red;
+      opacity: 0.5;
+      box-shadow: 0px 0px 8px 2px rgba(255,0,0,1);
+    }
+    .image-viewer-highlight.animate {
+      animation-name: highlight-animation;
+      animation-duration: 0.15s;
+      animation-timing-function: ease-out;
+      animation-delay: 0s;
+      animation-direction: alternate;
+      animation-iteration-count: 2;
+    }
+    .image-viewer-highlight.animate-long {
+      animation-iteration-count: 4;
+    }
+    @keyframes highlight-animation {
+      0% {
+        display: block;
+        opacity: 0;
+        transform: scale(1.0);
+      }
+      100% {
+        display: block;
+        opacity: 0.5;
+        transform: scale(1.1);
+      }
+    }`;
+    document.head.appendChild(style);
+  }
+
+  /* ImageResultsViewer dom
+    <div class="image-viewer">
+      <div class="image-viewer-tile">
+        <img src="...-actual" title="Actual result">
+      </div>
+      <div class="image-viewer-tile">
+        <img src="...-expected" title="Expected result">
+      </div>
+      <div class="image-viewer-tile">
+        <img src="...-diff" title="Difference">
+      </div>
+    </div>
+  */
+  createDom(imgInfo, owner) {
+    this.importStyle();
+    this.viewer = document.createElement("div");
+    // Viewer DOM API
+    this.viewer.showImages = this.showImages.bind(this);
+    this.viewer.owner = owner;
+
+    this.viewer.classList.add("image-viewer");
+    this.viewer.addEventListener("click", (ev) => {
+      this.toggleZoom({x: ev.offsetX, y: ev.offsetY}, ev.target);
+    });
+    for (let info of imgInfo) {
+      let imgTile = document.createElement("div");
+      imgTile.classList.add("image-viewer-tile");
+      imgTile.classList.add("hidden");
+      imgTile.innerHTML = `<img src="${info.src}" title="${info.title}">`;
+      imgTile.addEventListener("scroll", this.boundTileScrollHandler, {passive: true});
+      imgTile.addEventListener("wheel", this.boundWheelHandler);
+      this.viewer.appendChild(imgTile);
+      if (info.title == "Difference") {
+        let diffImage = new Image();
+        diffImage.addEventListener("load", function(ev) {
+          this.computeDiffRect(ev.target);
+        }.bind(this), false);
+        diffImage.src = info.src;
+      }
+    }
+    return this.viewer;
+  }
+
+  // public API
+  showImages(sources) {
+    let tiles = Array.from(this.viewer.querySelectorAll(".image-viewer-tile"));
+    // Newly shown tiles should have the same scroll position as existing tiles.
+    let scrollPosition;
+    for (let tile of tiles) {
+      if (!tile.classList.contains("hidden")) {
+        scrollPosition = {top: tile.scrollTop, left: tile.scrollLeft};
+        break;
+      }
+    }
+    for (let tile of tiles) {
+      let tileImage = tile.querySelector("img");
+      let visible = sources.includes(tileImage.src);
+      if (visible) {
+        tile.classList.remove("hidden");
+        if (scrollPosition) {
+          tile.scrollTop = scrollPosition.top;
+          tile.scrollLeft = scrollPosition.left;
+        }
+      }
+      else
+        tile.classList.add("hidden");
+    }
+  }
+
+  findVisibleImage(preferredImage) {
+    if (preferredImage && !preferredImage.parentNode.classList.contains("hidden"))
+      return preferredImage;
+    for (let image of Array.from(this.viewer.querySelectorAll("img")))
+      if (!image.parentNode.classList.contains("hidden") && image)
+        return image;
+  }
+
+  tileScrollHandler(ev) {
+    let sourceTile = ev.target;
+    if (sourceTile.classList.contains("hidden"))
+      return;
+    for (let tile of Array.from(this.viewer.querySelectorAll(".image-viewer-tile"))) {
+      if (tile != sourceTile) {
+        tile.scrollTop = sourceTile.scrollTop;
+        tile.scrollLeft = sourceTile.scrollLeft;
+      }
+    }
+  }
+
+  tileWheelHandler(ev) {
+    // Prevent page back/forward gestures when scrolling inside tiles.
+    if (Math.abs(ev.deltaY) > Math.abs(ev.deltaX))
+      return;
+    let target = ev.currentTarget;
+    let blockScrollRight = (target.scrollLeft + target.clientWidth) == target.scrollWidth;
+    let blockScrollLeft = target.scrollLeft == 0;
+    if (blockScrollRight && ev.deltaX > 0) {
+      ev.preventDefault();
+    }
+    if (blockScrollLeft && ev.deltaX < 0) {
+      ev.preventDefault();
+    }
+  }
+
+  mouseMoveHandler(ev) {
+    let imageRect = this.findVisibleImage(this.zoomTarget).getBoundingClientRect();
+    let zoom = this.viewer.querySelector(".image-viewer-zoom");
+    if (zoom)
+      zoom.showLocation({
+      x: ev.pageX - (imageRect.left +  window.scrollX),
+      y: ev.pageY - (imageRect.top + window.scrollY)
+    });
+  }
+
+  toggleZoom(location, zoomTarget) {
+    let zoom = this.viewer.querySelector(".image-viewer-zoom");
+    if (zoom) {
+      zoom.remove();
+      delete this.zoomTarget;
+      this.viewer.removeEventListener("mousemove", this.boundMouseMoveHandler);
+    } else {
+      this.zoomTarget = zoomTarget;
+      let zoomElement = (new ImageViewerZoom()).createDom(this.viewer, this.viewer.querySelectorAll("img"));
+      this.viewer.addEventListener("mousemove", this.boundMouseMoveHandler);
+      zoomElement.showLocation(location);
+    }
+  }
+
+  computeDiffRect(image) {
+    let canvas = document.createElement("canvas");
+    canvas.width = image.naturalWidth;
+    canvas.height = image.naturalHeight;
+    let ctx = canvas.getContext("2d");
+    ctx.drawImage(image, 0, 0);
+    let top = image.naturalHeight;
+    let bottom = 0;
+    let left = image.naturalWidth;
+    let right = 0;
+    try {
+      let imageData = ctx.getImageData(0, 0, image.naturalWidth, image.naturalHeight);
+      for (let x = 0; x < imageData.width; x++)
+        for (let y = 0; y < imageData.height; y++) {
+          let offset  = y * imageData.width * 4 + x * 4;
+          if (imageData.data[offset] == 255 && imageData.data[offset+1] == 0 && imageData.data[offset+2] == 0) {
+            if (x < left) left = x;
+            if (x > right) right = x;
+            if (y < top) top = y;
+            if (y > bottom) bottom = y;
+          }
+        }
+      if (bottom != 0 && right != 0)
+        this.animateDiffRect({top: top, left: left, width: Math.max(0, right - left), height: Math.max(0, bottom - top)}, image);
+    } catch(ex) {
+      console.error("cannot show error rect on local files because of cross origin taint");
+    }
+  }
+
+  animateDiffRect(diffRect, image) {
+    if (!image)
+      return;
+    if (!image.complete) {
+      image.addEventListener("load", _ => this.animateDiffRect(diffRect, image));
+      return;
+    }
+    let highlight = document.createElement("div");
+    highlight.classList.add("image-viewer-highlight");
+    highlight.style.top = image.offsetTop + diffRect.top + "px";
+    highlight.style.left = image.offsetLeft + diffRect.left  + "px";
+    highlight.style.width = Math.max(5, diffRect.width) + "px";
+    highlight.style.height = Math.max(5, diffRect.height) + "px";
+    this.viewer.appendChild(highlight);
+    highlight.addEventListener("animationend", _ => highlight.remove());
+    if (diffRect.width < 100 || diffRect.height < 100) {
+      highlight.classList.add("animate-long");
+    }
+    highlight.classList.add("animate");
+  }
+} // class ImageResultsViewer
+
+class ImageViewerZoom {
+  constructor(zoomFactor = 6) {
+    this.zoomFactor = zoomFactor;
+  }
+
+  importStyle() {
+    if (document.querySelector("#ImageViewerZoomCSS"))
+      return;
+    let style = document.createElement("style");
+    style.setAttribute("type", "text/css");
+    style.setAttribute("id", "ImageViewerZoomCSS");
+    style.innerText = `
+    .image-viewer-zoom {
+      display: flex;
+      background-color: #555;
+      position: fixed;
+      padding-left: 4px;
+      padding-right: 4px;
+      top: 20px;
+      left: 16px;
+      bottom: 16px;
+      right: 16px;
+      height: calc((100vw - 32px) / 3);
+      max-height: 50vh;
+      box-shadow: 0px 0px 10px 2px rgba(0,0,0,0.68);
+    }
+    .image-viewer-zoom-tile {
+      position: relative;
+      flex-grow: 1;
+      flex-shrink: 1;
+      margin: 16px 8px 16px 8px;
+    }
+    .image-viewer-zoom-tile > canvas {
+      width: 100%;
+      height: 100%;
+    }
+    .image-viewer-zoom-tile > .title {
+      position: absolute;
+      top: -36px;
+      left: -px;
+      background-color: white;
+      white-space: nowrap;
+      overflow: hidden;
+    }
+    .image-viewer-zoom-color {
+      font-size: smaller;
+    }
+    `;
+    document.head.appendChild(style);
+  }
+  /*
+    <div class="image-viewer-zoom">
+      <div class="image-viewer-zoom-tile"> // repeat for each image
+        <canvas></canvas>
+        <div class="title"><span class="color"></span></div>
+      </div>
+  */
+  createDom(container, images) {
+    this.importStyle();
+    this.images = Array.from(images);
+    this.zoomElement = document.createElement("div");
+    // ImageViewer DOM API
+    this.zoomElement.showLocation = this.showLocation.bind(this);
+
+    this.zoomElement.classList.add("image-viewer-zoom");
+    this.zoomElement.classList.add("close-on-esc");
+    container.appendChild(this.zoomElement);
+    // Add canvas for each image.
+    for (let img of this.images) {
+      let tile = document.createElement("div");
+      tile.classList.add("image-viewer-zoom-tile");
+      tile.innerHTML = `<canvas></canvas><div class="title">${img.title} <span class="image-viewer-zoom-color"></span></div>`;
+      this.zoomElement.appendChild(tile);
+    }
+    return this.zoomElement;
+  }
+
+  showLocation(location) {
+    let canvases = Array.from(this.zoomElement.querySelectorAll("canvas"));
+    let naturalSize;
+    // Find non-hidden image to determine size.
+    for (let image of this.images) {
+      if (image.complete && !image.classList.contains("hidden")) {
+        naturalSize = {width: image.naturalWidth, height: image.naturalHeight};
+        break;
+      }
+    }
+    if (!naturalSize) {
+      console.warn("image not loaded");
+      return;
+    }
+    for (let i = 0; i < canvases.length; i++) {
+      // Set canvas to right size if window resized.
+      let canvasWidth = canvases[i].clientWidth;
+      let canvasHeight = canvases[i].clientHeight;
+      canvases[i].width = canvasWidth;
+      canvases[i].height = canvasHeight;
+      let ctx = canvases[i].getContext("2d");
+      ctx.imageSmoothingEnabled = false;
+      // Copy over zoomed image.
+      let sWidth = canvasWidth / this.zoomFactor;
+      let sHeight = canvasHeight / this.zoomFactor;
+      let pad = 20;
+      let sx = Math.floor(Math.min(Math.max(-pad, location.x - sWidth / 2), naturalSize.width + pad - sWidth));
+      let sy = Math.floor(Math.min(Math.max(-pad, location.y - sHeight / 2), naturalSize.height + pad - sHeight));
+
+      ctx.drawImage(this.images[i], sx, sy, sWidth, sHeight, 0, 0, canvasWidth, canvasHeight);
+      // Draw grid.
+      ctx.strokeStyle = "rgba(0,0,0,0.05)";
+      let pixelSize = canvasWidth / sWidth;
+      ctx.beginPath();
+      for (let y = 1; y < sHeight; y++) {
+        ctx.moveTo(0, y * pixelSize);
+        ctx.lineTo(canvasWidth, y * pixelSize);
+      }
+      for (let x = 1; x < sWidth; x++) {
+        ctx.moveTo(x*pixelSize, 0);
+        ctx.lineTo(x*pixelSize, canvasHeight);
+      }
+      ctx.closePath();
+      ctx.stroke();
+
+      // Highlight middle pixel whose color is measured.
+
+      try { // getImageData throws on local file system.
+        let middleX = Math.floor(sWidth / 2);
+        let middleY = Math.floor(sHeight / 2);
+        let imageData = ctx.getImageData(middleX * pixelSize + 2, middleY * pixelSize + 2, 1, 1);
+        let r = imageData.data[0];
+        let g = imageData.data[1];
+        let b = imageData.data[2];
+        let a = imageData.data[3];
+        let colorSpan = canvases[i].parentNode.querySelector(".image-viewer-zoom-color");
+        let color = `rgba(${r}, ${g}, ${b}, ${a})`;
+        colorSpan.innerText = `(${sx + middleX}, ${sy + middleY}) ${color}`;
+        colorSpan.style.backgroundColor = color;
+        colorSpan.style.color =  ((r + g + b) > 300 ) ? "black" : "white";
+        ctx.beginPath();
+        ctx.moveTo(middleX * pixelSize, middleY * pixelSize);
+        ctx.lineTo((middleX + 1) * pixelSize, middleY * pixelSize);
+        ctx.lineTo((middleX + 1) * pixelSize, (middleY + 1) * pixelSize);
+        ctx.lineTo(middleX * pixelSize, (middleY + 1) * pixelSize);
+        ctx.lineTo(middleX * pixelSize, middleY * pixelSize);
+        ctx.strokeStyle = "rgba(0,0,0,0.2)";
+        ctx.closePath();
+        ctx.stroke();
+      } catch(ex) {}
+    }
+  }
+} // class ImageViewerZoom
+
+class TextResultsToolbar extends TXToolbar {
+  constructor() {
+    super();
+  }
+
+  createDom(test) {
+    this.importStyle();
+    let pathParser = new PathParser(test.expectPath);
+    this.toolbar = document.createElement("li");
+    this.toolbar.showDefault = (_ => {
+      this.selectAnchor(
+        this.toolbar.querySelector("a.pretty")  || this.toolbar.querySelector("a.actual"));
+    }).bind(this);
+    this.toolbar.classList.add("text-results-toolbar");
+    this.toolbar.classList.add("tx-toolbar");
+    let html = "text:";
+    if (!test.is_testharness_test)
+      html += `<a class="pretty" href="${pathParser.resultLink("-pretty-diff.html")}" title="Pretty difference">pretty</a>`;
+    html += `<a class="actual" href="${pathParser.resultLink("-actual.txt")}" title="Actual text">actual</a>`;
+    if (!test.is_testharness_test) {
+      html += `<a class="expected" href="${pathParser.resultLink("-expected.txt")}" title="Expected result">expected</a><a
+        class="diff" href="${pathParser.resultLink("-diff.txt")}" title="Difference">diff</a>
+      `;
+    }
+    this.toolbar.innerHTML = html;
+    this.toolbar.addEventListener("click", ev => {
+      if (ev.target.tagName == "A") {
+        this.selectAnchor(ev.target);
+        ev.preventDefault();
+      }
+    });
+    return this.toolbar;
+  }
+
+  updateViewer() {
+    // Find currently selected anchor.
+    let selectedAnchors = Array.from(this.toolbar.querySelectorAll("a[data-selected]"));
+    if (selectedAnchors.length == 0) {
+      selectedAnchors.push(this.toolbar.querySelector("a"));
+      selectedAnchors[0].setAttribute("data-selected", "");
+    }
+    let viewer = this.getViewer();
+    if (!viewer) {
+      let fileInfo = Array.from(this.toolbar.querySelectorAll("a")).map(
+        anchor => { return {src: anchor.href, title: anchor.title}; });
+      viewer = (new TextFileViewer()).createDom(fileInfo, this);
+      GUI.setResultViewer(this.toolbar, viewer);
+    }
+    viewer.showFile(selectedAnchors.map( anchor => anchor.href));
+  }
+} // class TextResultsToolbar
+
+class TextFileViewer {
+  importStyle() {
+    if (document.querySelector("#TextFileViewerCSS"))
+      return;
+    let style = document.createElement("style");
+    style.setAttribute("type", "text/css");
+    style.setAttribute("id", "TextFileViewerCSS");
+    style.innerText =
+    ` .text-file-viewer {
+      position: relative;
+      display: flex;
+    }
+    .text-file-viewer > iframe {
+      flex-shrink: 1;
+      flex-grow: 1;
+      border: 1px solid #888;
+      overflow: scroll;
+      max-height: calc(100vh - 80px);
+      margin-right: 8px;
+      height: 600px;
+    }
+    `;
+    document.head.appendChild(style);
+  }
+
+  /* TextFileViewer dom
+    <div class="text-file-viewer">
+      <iframe class="text-file-viewer-iframe" src="file..">
+      <iframe class="text-file-viewer-iframe" src="file..">
+      <iframe class="text-file-viewer-iframe" src="file..">
+    </div>
+  */
+  createDom(fileInfo, owner) {
+    this.importStyle();
+    this.viewer = document.createElement("div");
+    // TextFileViewer DOM API
+    this.viewer.owner = owner;
+    this.viewer.showFile = this.showFile.bind(this);
+
+    this.viewer.classList.add("text-file-viewer");
+    for (let info of fileInfo) {
+      let iframe = document.createElement("iframe");
+      iframe.classList.add("text-file-viewer-iframe");
+      iframe.classList.add("hidden");
+      iframe.src = info.src;
+      iframe.setAttribute("tabindex", -1);
+      this.viewer.appendChild(iframe);
+    }
+    return this.viewer;
+  }
+
+  showFile(sources) {
+    let iframes = Array.from(this.viewer.querySelectorAll(".text-file-viewer-iframe"));
+    for (let iframe of iframes) {
+      let visible = sources.includes(iframe.src);
+      if (visible) {
+        iframe.classList.remove("hidden");
+      } else {
+        iframe.classList.add("hidden");
+      }
+    }
+  }
+} // class TextFileViewer
+
+class PlainHtmlToolbar extends TXToolbar {
+  createDom(html) {
+    super.importStyle();
+    let dom = document.createElement("li");
+    dom.classList.add("tx-toolbar");
+    dom.innerHTML = html;
+    return dom;
+  }
+} // class PlainHtmlToolbar
+
+class SimpleLinkToolbar extends TXToolbar {
+  createDom(href, title, text) {
+    super.importStyle();
+    this.toolbar = document.createElement("li");
+    // Toolbar DOM API
+    this.toolbar.showDefault = (_ => {this.selectAnchor(this.toolbar.querySelector("a"));}).bind(this);
+
+    this.toolbar.classList.add("tx-toolbar");
+    this.toolbar.innerHTML = `<a href="${href}" title="${title}">${text}</a>`;
+    this.toolbar.addEventListener("click", ev => {
+      if (ev.target.tagName == "A") {
+        this.selectAnchor(ev.target);
+        ev.preventDefault();
+      }
+    });
+    return this.toolbar;
+  }
+
+  updateViewer() {
+    // Find currently selected anchor.
+    let selectedAnchors = Array.from(this.toolbar.querySelectorAll("a[data-selected]"));
+    if (selectedAnchors.length == 0) {
+      selectedAnchors.push(this.toolbar.querySelector("a"));
+      selectedAnchors[0].setAttribute("data-selected", "");
+    }
+    let viewer = this.getViewer();
+    if (!viewer) {
+      let fileInfo = Array.from(this.toolbar.querySelectorAll("a")).map(
+        anchor => { return {src: anchor.href, title: anchor.title};});
+      viewer = (new TextFileViewer()).createDom(fileInfo, this);
+      GUI.setResultViewer(this.toolbar, viewer);
+    }
+    viewer.showFile(selectedAnchors.map( anchor => anchor.href));
+  }
+} // class SimpleLinkToolbar
+
+</script>
+<script>
 // jsonp callback
 function ADD_FULL_RESULTS(results) {
   GUI.initPage(results);
diff --git a/third_party/WebKit/LayoutTests/fast/replaced/inline-box-wrapper-handover-expected.html b/third_party/WebKit/LayoutTests/fast/replaced/inline-box-wrapper-handover-expected.html
new file mode 100644
index 0000000..b6b8c74
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/replaced/inline-box-wrapper-handover-expected.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+    <title></title>
+    <style type="text/css">
+        div.ib { display: inline-block; width: 20px; height: 20px; }
+    </style>
+</head>
+<body>
+    <p>
+        This test checks for a regression against <i><a href="https://bugs.webkit.org/show_bug.cgi?id=6276">http://bugzilla.opendarwin.org/show_bug.cgi?id=6276</a>
+        Image thumbnails are misplaced on forum.2ostrov.ru</i>.
+    </p>
+    <hr>
+    <p>
+        Box 1 and box 2 should be identical.
+    </p>
+    Box 1:
+    <div style="border: 1px black solid; width: 55px; padding: 5px;">
+        <div class="ib" style="background: blue; width: 40px;"></div> A
+        <div class="ib" style="background: red; width: 35px;"></div> B
+        <div class="ib" style="background: green;"></div> C
+    </div>
+    <br>
+    Box 2:
+    <div style="border: 1px black solid; width: 55px; padding: 5px;">
+        <div class="ib" style="background: blue; width: 40px;"></div> A
+        <div class="ib" style="background: red; width: 35px;"></div> B
+        <div class="ib" style="background: green;"></div> C
+    </div>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/table/split-effective-column-visibility-collapse-crash.html b/third_party/WebKit/LayoutTests/fast/table/split-effective-column-visibility-collapse-crash.html
new file mode 100644
index 0000000..d5aba8d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/table/split-effective-column-visibility-collapse-crash.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+
+<table>
+  <colgroup></colgroup>
+  <colgroup style="visibility:collapse"></colgroup>
+  <tr>
+    <td colspan=5></td>
+  </tr>
+  <tr>
+    <td></td>
+  </tr>
+</table>
+
+<script>
+  test(() => {
+  }, "No crash or assertion failure. crbug.com/761192");
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/workers/worker-exception-during-navigation.html b/third_party/WebKit/LayoutTests/fast/workers/worker-exception-during-navigation.html
index 1ba3c22..02a1278 100644
--- a/third_party/WebKit/LayoutTests/fast/workers/worker-exception-during-navigation.html
+++ b/third_party/WebKit/LayoutTests/fast/workers/worker-exception-during-navigation.html
@@ -22,16 +22,16 @@
     }
 
     // Create sufficiently large number of workers in hopes that one of the exceptions they throw will be processed in short time interval in
-    // which it could case the crash from the bug.
+    // which it could cause the crash from the bug.
     var workers = [];
     console.log("Creating the workers.")
-    for (var i = 0; i < 30; i++) {
+    for (var i = 0; i < 20; i++) {
         setTimeout(function() {
             try {
                 var worker = new Worker('resources/worker-exception.js');
                 worker.onerror = function(evt) {
-                    // The number of worker exceptions that will be catched is not deterministic,
-                    // so let's make sire the excption is not written to console to have deterministic text output.
+                    // The number of worker exceptions that will be caught is not deterministic,
+                    // so let's make sure the exception is not written to console to have deterministic text output.
                     evt.preventDefault();
                 };
                 workers.push(worker);
diff --git a/third_party/WebKit/LayoutTests/fast/workers/worker-multi-startup-expected.txt b/third_party/WebKit/LayoutTests/fast/workers/worker-multi-startup-expected.txt
index aa5b17e4..d2142e09 100644
--- a/third_party/WebKit/LayoutTests/fast/workers/worker-multi-startup-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/workers/worker-multi-startup-expected.txt
@@ -20,15 +20,5 @@
 SUCCESS: Worker context initialized
 SUCCESS: Worker context initialized
 SUCCESS: Worker context initialized
-SUCCESS: Worker context initialized
-SUCCESS: Worker context initialized
-SUCCESS: Worker context initialized
-SUCCESS: Worker context initialized
-SUCCESS: Worker context initialized
-SUCCESS: Worker context initialized
-SUCCESS: Worker context initialized
-SUCCESS: Worker context initialized
-SUCCESS: Worker context initialized
-SUCCESS: Worker context initialized
 DONE
 
diff --git a/third_party/WebKit/LayoutTests/fast/workers/worker-multi-startup.html b/third_party/WebKit/LayoutTests/fast/workers/worker-multi-startup.html
index 331efc5..0cfc6c6 100644
--- a/third_party/WebKit/LayoutTests/fast/workers/worker-multi-startup.html
+++ b/third_party/WebKit/LayoutTests/fast/workers/worker-multi-startup.html
@@ -13,7 +13,7 @@
     document.getElementById("result").innerHTML += message + "<br>";
 }
 
-totalWorkers = 30;
+totalWorkers = 20;
 replies = 0;
 
 for (var i = 0; i < totalWorkers; i++) {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/compositing/layer-creation/fixed-position-nonscrollable-body-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/compositing/layer-creation/fixed-position-nonscrollable-body-expected.txt
new file mode 100644
index 0000000..d60b709
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/compositing/layer-creation/fixed-position-nonscrollable-body-expected.txt
@@ -0,0 +1,11 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/compositing/layer-creation/fixed-position-nonscrollable-body-overlap-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/compositing/layer-creation/fixed-position-nonscrollable-body-overlap-expected.txt
new file mode 100644
index 0000000..4710ed5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/compositing/layer-creation/fixed-position-nonscrollable-body-overlap-expected.txt
@@ -0,0 +1,38 @@
+Even though we can opt-out of fixed-position compositing for unscrollable fixed-position containers, we still need to composite fixed-position layers that need compositing for other reasons such as overlap.
+
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV class='absolute composited red box'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#FF0000",
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV class='fixed lime box'",
+      "position": [10, 100],
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#00FF00"
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [10, 100, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/absolute-position-change-containing-block-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/absolute-position-change-containing-block-expected.txt
index 8931b38..13630628 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/absolute-position-change-containing-block-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/absolute-position-change-containing-block-expected.txt
@@ -2,7 +2,7 @@
   "layers": [
     {
       "name": "LayoutView #document",
-      "bounds": [800, 2016],
+      "bounds": [800, 600],
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/absolute-position-moved-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/absolute-position-moved-expected.txt
index c6bf24f..2f504b4 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/absolute-position-moved-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/absolute-position-moved-expected.txt
@@ -2,7 +2,7 @@
   "layers": [
     {
       "name": "LayoutView #document",
-      "bounds": [800, 2016],
+      "bounds": [800, 600],
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/animated-gif-transformed-offscreen-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/animated-gif-transformed-offscreen-expected.txt
deleted file mode 100644
index 68632731..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/animated-gif-transformed-offscreen-expected.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [2008, 2016],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='targetDiv'",
-      "bounds": [50, 50],
-      "transform": 2
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 8, 0, 1]
-      ]
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -1000, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/border-radius-repaint-2-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/border-radius-repaint-2-expected.txt
index bbd88f3..dfd91c5 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/border-radius-repaint-2-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/border-radius-repaint-2-expected.txt
@@ -2,7 +2,7 @@
   "layers": [
     {
       "name": "LayoutView #document",
-      "bounds": [874, 600],
+      "bounds": [800, 600],
       "contentsOpaque": true,
       "backgroundColor": "#3F3F3F",
       "paintInvalidations": [
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-composite-1-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-composite-1-expected.txt
new file mode 100644
index 0000000..23b19887
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-composite-1-expected.txt
@@ -0,0 +1,24 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='before box'",
+          "rect": [128, 120, 100, 100],
+          "reason": "paint property change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV class='box'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-composite-2-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-composite-2-expected.txt
new file mode 100644
index 0000000..878badb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-composite-2-expected.txt
@@ -0,0 +1,24 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='before box'",
+          "rect": [128, 120, 200, 200],
+          "reason": "paint property change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV class='box'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-composite-3-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-composite-3-expected.txt
new file mode 100644
index 0000000..716b9320
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-composite-3-expected.txt
@@ -0,0 +1,24 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='before box'",
+          "rect": [-72, -80, 400, 400],
+          "reason": "paint property change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV class='box'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-composite-4-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-composite-4-expected.txt
new file mode 100644
index 0000000..878badb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-composite-4-expected.txt
@@ -0,0 +1,24 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='before box'",
+          "rect": [128, 120, 200, 200],
+          "reason": "paint property change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV class='box'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-composite-5-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-composite-5-expected.txt
new file mode 100644
index 0000000..23b19887
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-composite-5-expected.txt
@@ -0,0 +1,24 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='before box'",
+          "rect": [128, 120, 100, 100],
+          "reason": "paint property change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV class='box'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-composite-6-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-composite-6-expected.txt
new file mode 100644
index 0000000..77e9c14
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-composite-6-expected.txt
@@ -0,0 +1,24 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='before box'",
+          "rect": [28, 20, 300, 300],
+          "reason": "paint property change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV class='box'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-gaussianblur-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-gaussianblur-expected.txt
new file mode 100644
index 0000000..5c064cc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-gaussianblur-expected.txt
@@ -0,0 +1,24 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='box before'",
+          "rect": [-2, -10, 320, 320],
+          "reason": "paint property change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV class='box'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-gaussianblur-xonly-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-gaussianblur-xonly-expected.txt
new file mode 100644
index 0000000..20f8bf6e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-gaussianblur-xonly-expected.txt
@@ -0,0 +1,24 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='box before'",
+          "rect": [-2, 50, 320, 200],
+          "reason": "paint property change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV class='box'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-gaussianblur-yonly-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-gaussianblur-yonly-expected.txt
new file mode 100644
index 0000000..6be2e1f2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-gaussianblur-yonly-expected.txt
@@ -0,0 +1,24 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='box before'",
+          "rect": [58, -10, 200, 320],
+          "reason": "paint property change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV class='box'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-lighting-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-lighting-expected.txt
new file mode 100644
index 0000000..cfbc25e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-lighting-expected.txt
@@ -0,0 +1,24 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='box'",
+          "rect": [78, 70, 100, 100],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV class='box'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-merge-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-merge-expected.txt
new file mode 100644
index 0000000..77e9c14
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-merge-expected.txt
@@ -0,0 +1,24 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='before box'",
+          "rect": [28, 20, 300, 300],
+          "reason": "paint property change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV class='box'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-offset-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-offset-expected.txt
new file mode 100644
index 0000000..0faf0760
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/filters/effect-reference-repaint-offset-expected.txt
@@ -0,0 +1,24 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='box before'",
+          "rect": [198, 198, 110, 110],
+          "reason": "paint property change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV class='box'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/inline-focus-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/inline-focus-expected.txt
new file mode 100644
index 0000000..ef882205
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/inline-focus-expected.txt
@@ -0,0 +1,76 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "InlineTextBox 'crbug.com/424078: ensure inline elements get their outline painted'",
+          "rect": [0, 36, 419, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox 'crbug.com/424078: ensure inline elements get their outline painted'",
+          "rect": [0, 36, 419, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutInline A id='link'",
+          "rect": [585, -1, 216, 234],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox 'Home'",
+          "rect": [0, 0, 39, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox 'Home'",
+          "rect": [0, 0, 39, 19],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutInline A id='link'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox 'Home'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow P",
+      "reason": "geometry"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox 'crbug.com/424078: ensure inline elements get their outline painted'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/inline-outline-repaint-2-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/inline-outline-repaint-2-expected.txt
index 4f7a71f..0121190 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/inline-outline-repaint-2-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/inline-outline-repaint-2-expected.txt
@@ -2,18 +2,18 @@
   "layers": [
     {
       "name": "LayoutView #document",
-      "position": [0, -5],
-      "bounds": [800, 605],
+      "bounds": [800, 600],
+      "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
           "object": "LayoutInline SPAN",
-          "rect": [210, 0, 50, 20],
+          "rect": [210, -5, 50, 20],
           "reason": "outline"
         },
         {
           "object": "InlineTextBox 'Test'",
-          "rect": [215, 5, 40, 10],
+          "rect": [215, 0, 40, 10],
           "reason": "style change"
         }
       ]
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/mask-clip-change-stacking-child-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/mask-clip-change-stacking-child-expected.txt
index e7738583..68f094e3 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/mask-clip-change-stacking-child-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/mask-clip-change-stacking-child-expected.txt
@@ -9,7 +9,7 @@
     {
       "name": "LayoutBlockFlow DIV",
       "position": [8, 8],
-      "bounds": [500, 500],
+      "bounds": [300, 200],
       "contentsOpaque": true,
       "backgroundColor": "#ADD8E6"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/offset-change-wrong-invalidation-with-float-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/offset-change-wrong-invalidation-with-float-expected.txt
new file mode 100644
index 0000000..8f502db0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/offset-change-wrong-invalidation-with-float-expected.txt
@@ -0,0 +1,60 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) UL id='submenu'",
+          "rect": [48, 94, 40, 20],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) UL id='submenu'",
+          "rect": [48, -156, 40, 20],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutListMarker (anonymous)",
+          "rect": [70, 94, 7, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutListMarker (anonymous)",
+          "rect": [70, -156, 7, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutListMarker (anonymous)",
+          "rect": [30, 44, 7, 19],
+          "reason": "geometry"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutListMarker (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) UL id='submenu'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutListItem LI",
+      "reason": "geometry"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutListMarker (anonymous)",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/outline-change-in-scrollers-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/outline-change-in-scrollers-expected.txt
new file mode 100644
index 0000000..1f67327
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/outline-change-in-scrollers-expected.txt
@@ -0,0 +1,181 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='target'",
+          "rect": [172, 173, 75, 75],
+          "reason": "style change"
+        }
+      ]
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV class='scroll'",
+      "position": [10, 10],
+      "bounds": [110, 110],
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV class='scroll'",
+      "bounds": [130, 130],
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='target'",
+          "rect": [10, 10, 75, 75],
+          "reason": "style change"
+        }
+      ],
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV class='scroll'",
+      "position": [10, 10],
+      "bounds": [110, 110],
+      "transform": 2
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV class='scroll'",
+      "bounds": [130, 130],
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='target'",
+          "rect": [30, 10, 75, 75],
+          "reason": "style change"
+        }
+      ],
+      "transform": 2
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV class='scroll'",
+      "position": [10, 10],
+      "bounds": [110, 110],
+      "transform": 3
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV class='scroll'",
+      "bounds": [130, 130],
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='target'",
+          "rect": [10, 10, 75, 75],
+          "reason": "style change"
+        }
+      ],
+      "transform": 3
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV class='scroll'",
+      "position": [10, 10],
+      "bounds": [110, 110],
+      "transform": 4
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV class='scroll'",
+      "bounds": [130, 130],
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='target'",
+          "rect": [45, 10, 75, 75],
+          "reason": "style change"
+        }
+      ],
+      "transform": 4
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV class='scroll'",
+      "position": [10, 10],
+      "bounds": [110, 110],
+      "transform": 5
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV class='scroll'",
+      "bounds": [130, 130],
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='target'",
+          "rect": [10, 30, 75, 75],
+          "reason": "style change"
+        }
+      ],
+      "transform": 5
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [142, 8, 0, 1]
+      ]
+    },
+    {
+      "id": 3,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [276, 8, 0, 1]
+      ]
+    },
+    {
+      "id": 4,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 143, 0, 1]
+      ]
+    },
+    {
+      "id": 5,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [276, 143, 0, 1]
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV class='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow DIV class='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow DIV class='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow DIV class='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow DIV class='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow DIV class='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/outline-change-scrollable-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/outline-change-scrollable-expected.txt
new file mode 100644
index 0000000..330cf7e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/outline-change-scrollable-expected.txt
@@ -0,0 +1,34 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [1008, 585],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow HTML",
+      "bounds": [1008, 128],
+      "backgroundColor": "#008000",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV id='target'",
+          "rect": [-12, -12, 1040, 140],
+          "reason": "style change"
+        }
+      ]
+    },
+    {
+      "name": "LayoutView #document",
+      "position": [0, 585],
+      "bounds": [800, 15]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV id='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/outline-change-vertical-rl-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/outline-change-vertical-rl-expected.txt
new file mode 100644
index 0000000..8f71cd5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/outline-change-vertical-rl-expected.txt
@@ -0,0 +1,36 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "position": [-216, 0],
+      "bounds": [1016, 585],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow HTML",
+      "position": [-216, 0],
+      "bounds": [1016, 128],
+      "backgroundColor": "#008000",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV id='target'",
+          "rect": [-12, -12, 1040, 140],
+          "reason": "style change"
+        }
+      ]
+    },
+    {
+      "name": "LayoutView #document",
+      "position": [0, 585],
+      "bounds": [800, 15]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV id='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/overflow-flipped-writing-mode-block-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/overflow-flipped-writing-mode-block-expected.txt
new file mode 100644
index 0000000..c780d93
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/overflow-flipped-writing-mode-block-expected.txt
@@ -0,0 +1,24 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV id='target'",
+          "rect": [-92, 108, 50, 100],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV id='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/overflow-flipped-writing-mode-table-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/overflow-flipped-writing-mode-table-expected.txt
new file mode 100644
index 0000000..c780d93
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/overflow-flipped-writing-mode-table-expected.txt
@@ -0,0 +1,24 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV id='target'",
+          "rect": [-92, 108, 50, 100],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV id='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/overflow-hidden-in-overflow-hidden-scrolled-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/overflow-hidden-in-overflow-hidden-scrolled-expected.txt
index 03b5ee6..c325f758 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/overflow-hidden-in-overflow-hidden-scrolled-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/overflow-hidden-in-overflow-hidden-scrolled-expected.txt
@@ -22,15 +22,15 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow DIV class='innerWrapper'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow DIV class='red'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow DIV id='ucp' class='green'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/overflow-hide-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/overflow-hide-expected.txt
index aee8e6a..fac3b0c 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/overflow-hide-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/overflow-hide-expected.txt
@@ -2,7 +2,7 @@
   "layers": [
     {
       "name": "LayoutView #document",
-      "bounds": [800, 2016],
+      "bounds": [800, 600],
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/overflow-show-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/overflow-show-expected.txt
index 8dfdac5..b9f608e 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/overflow-show-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/overflow-show-expected.txt
@@ -2,7 +2,7 @@
   "layers": [
     {
       "name": "LayoutView #document",
-      "bounds": [800, 2016],
+      "bounds": [800, 600],
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/reflection-invalidation-after-display-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/reflection-invalidation-after-display-expected.txt
new file mode 100644
index 0000000..974c0ca
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/reflection-invalidation-after-display-expected.txt
@@ -0,0 +1,23 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='box' class='green reflected box'",
+          "rect": [300, 8, 450, 200],
+          "reason": "paint property change"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='box' class='green box'",
+          "rect": [300, 8, 200, 200],
+          "reason": "paint property change"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/repaint-overlay/layers-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/repaint-overlay/layers-expected.txt
deleted file mode 100644
index 1ec5435b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/repaint-overlay/layers-expected.txt
+++ /dev/null
@@ -1,110 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 2016],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF",
-      "transform": 1
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='container'",
-      "position": [40, 50],
-      "bounds": [100, 100],
-      "backgroundColor": "#0000FF80",
-      "paintInvalidations": [
-        {
-          "object": "LayoutBlockFlow (relative positioned) DIV id='child1'",
-          "rect": [20, 20, 10, 10],
-          "reason": "style change"
-        }
-      ],
-      "transform": 1
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='scrollable'",
-      "bounds": [302, 302],
-      "transform": 2
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='transform'",
-      "bounds": [200, 200],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFF00",
-      "paintInvalidations": [
-        {
-          "object": "LayoutBlockFlow (relative positioned) DIV id='child2'",
-          "rect": [20, 20, 10, 10],
-          "reason": "style change"
-        }
-      ],
-      "transform": 5
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -20, 0, 1]
-      ],
-      "flattenInheritedTransform": false
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [104, 103, 0, 1]
-      ]
-    },
-    {
-      "id": 3,
-      "parent": 2,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -30, 0, 1]
-      ]
-    },
-    {
-      "id": 4,
-      "parent": 3,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [89, 78, 0, 1]
-      ],
-      "flattenInheritedTransform": false
-    },
-    {
-      "id": 5,
-      "parent": 4,
-      "transform": [
-        [3.53553390593274, 3.53553390593274, 0, 0],
-        [-3.53553390593274, 3.53553390593274, 0, 0],
-        [0, 0, 1, 0],
-        [0, 0, 0, 1]
-      ],
-      "origin": [0, 0],
-      "flattenInheritedTransform": false
-    }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "LayoutBlockFlow (relative positioned) DIV id='child1'",
-      "reason": "style change"
-    },
-    {
-      "object": "LayoutBlockFlow (relative positioned) DIV id='child2'",
-      "reason": "style change"
-    }
-  ]
-}
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/scroll-in-clipped-layer-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/scroll-in-clipped-layer-expected.txt
index c280ca4..65ce730b 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/scroll-in-clipped-layer-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/scroll-in-clipped-layer-expected.txt
@@ -2,7 +2,7 @@
   "layers": [
     {
       "name": "LayoutView #document",
-      "bounds": [800, 2016],
+      "bounds": [800, 600],
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
@@ -22,15 +22,15 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='absolute clipped'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow (relative positioned) DIV class='relative green'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/scroll-in-transformed-layer-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/scroll-in-transformed-layer-expected.txt
index a11484a..6feda3ef 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/scroll-in-transformed-layer-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/scroll-in-transformed-layer-expected.txt
@@ -2,7 +2,7 @@
   "layers": [
     {
       "name": "LayoutView #document",
-      "bounds": [800, 2016],
+      "bounds": [800, 600],
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
@@ -22,15 +22,15 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='absolute clipped rotated'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/scroll-with-transformed-parent-layer-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/scroll-with-transformed-parent-layer-expected.txt
index 4ea7439..61dc38f2 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/scroll-with-transformed-parent-layer-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/scroll-with-transformed-parent-layer-expected.txt
@@ -2,7 +2,7 @@
   "layers": [
     {
       "name": "LayoutView #document",
-      "bounds": [800, 2016],
+      "bounds": [800, 600],
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
@@ -18,20 +18,6 @@
         }
       ]
     }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='absolute clipped'",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
-      "reason": "subtree"
-    }
   ]
 }
 
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/selection/invalidation-rect-includes-newline-for-rtl-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/selection/invalidation-rect-includes-newline-for-rtl-expected.txt
new file mode 100644
index 0000000..900ee2cb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/selection/invalidation-rect-includes-newline-for-rtl-expected.txt
@@ -0,0 +1,49 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "InlineTextBox 'xx'",
+          "rect": [-8, 8, 48, 33],
+          "reason": "geometry"
+        },
+        {
+          "object": "InlineTextBox 'y'",
+          "rect": [-8, 8, 48, 33],
+          "reason": "geometry"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow HTML",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutBlockFlow BODY",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutBlockFlow DIV id='container'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox 'xx'",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox 'y'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/add-outline-property-on-root-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/add-outline-property-on-root-expected.txt
new file mode 100644
index 0000000..dd3f8be
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/add-outline-property-on-root-expected.txt
@@ -0,0 +1,32 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutSVGRoot svg",
+          "rect": [-2, -2, 120, 120],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow BODY",
+      "reason": "geometry"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutSVGRoot svg",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/animated-svg-as-image-transformed-offscreen-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/animated-svg-as-image-transformed-offscreen-expected.txt
deleted file mode 100644
index 7699a0da..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/animated-svg-as-image-transformed-offscreen-expected.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [2008, 2016],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='targetDiv'",
-      "bounds": [480, 480],
-      "transform": 2
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 8, 0, 1]
-      ]
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -1000, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/relative-sized-document-scrollbars-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/relative-sized-document-scrollbars-expected.txt
new file mode 100644
index 0000000..fd6c84ac
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/relative-sized-document-scrollbars-expected.txt
@@ -0,0 +1,33 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutSVGRoot svg",
+          "rect": [6, 2, 788, 595],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGRoot svg",
+          "rect": [6, 4, 788, 592],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutSVGRoot svg",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutSVGRect rect",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/remove-outline-property-on-root-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/remove-outline-property-on-root-expected.txt
new file mode 100644
index 0000000..adfdd57
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/remove-outline-property-on-root-expected.txt
@@ -0,0 +1,32 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutSVGRoot svg",
+          "rect": [-2, -2, 120, 120],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow BODY",
+      "reason": "geometry"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutSVGRoot svg",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/transform-replaced-shadows-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/transform-replaced-shadows-expected.txt
new file mode 100644
index 0000000..f603d29
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/transform-replaced-shadows-expected.txt
@@ -0,0 +1,23 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutImage IMG id='box'",
+          "rect": [-10, 28, 276, 278],
+          "reason": "paint property change"
+        },
+        {
+          "object": "LayoutImage IMG id='box' class='smaller'",
+          "rect": [9, 28, 138, 139],
+          "reason": "paint property change"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/transform-rotate-and-remove-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/transform-rotate-and-remove-expected.txt
new file mode 100644
index 0000000..74b2bd51
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/transform-rotate-and-remove-expected.txt
@@ -0,0 +1,29 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow HTML",
+          "rect": [8, 8, 220, 70],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutBlockFlow DIV id='rel' class='rotated'",
+          "rect": [20, -64, 196, 214],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV id='rel'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/video-mute-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/video-mute-repaint-expected.txt
deleted file mode 100644
index 79ba6b0..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/video-mute-repaint-expected.txt
+++ /dev/null
@@ -1,74 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutFlexibleBox (relative positioned) DIV",
-      "position": [8, 501],
-      "bounds": [700, 32],
-      "contentsOpaque": true,
-      "backgroundColor": "#FAFAFA",
-      "paintInvalidations": [
-        {
-          "object": "LayoutSlider INPUT",
-          "rect": [580, 15, 70, 2],
-          "reason": "full"
-        },
-        {
-          "object": "LayoutBlockFlow DIV id='thumb'",
-          "rect": [632, 0, 36, 32],
-          "reason": "full"
-        },
-        {
-          "object": "LayoutBlockFlow DIV id='thumb'",
-          "rect": [562, 0, 36, 32],
-          "reason": "full"
-        },
-        {
-          "object": "LayoutButton INPUT",
-          "rect": [530, 0, 32, 32],
-          "reason": "full"
-        }
-      ]
-    }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "geometry"
-    },
-    {
-      "object": "RootInlineBox",
-      "reason": "geometry"
-    },
-    {
-      "object": "LayoutVideo VIDEO id='v'",
-      "reason": "style change"
-    },
-    {
-      "object": "LayoutFlexibleBox (relative positioned) DIV",
-      "reason": "geometry"
-    },
-    {
-      "object": "LayoutButton INPUT",
-      "reason": "full"
-    },
-    {
-      "object": "LayoutSlider INPUT",
-      "reason": "full"
-    },
-    {
-      "object": "LayoutFlexibleBox DIV",
-      "reason": "geometry"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='thumb'",
-      "reason": "full"
-    }
-  ]
-}
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/video-unmute-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/video-unmute-repaint-expected.txt
deleted file mode 100644
index 57b74141..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/video-unmute-repaint-expected.txt
+++ /dev/null
@@ -1,74 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutFlexibleBox (relative positioned) DIV",
-      "position": [8, 501],
-      "bounds": [700, 32],
-      "contentsOpaque": true,
-      "backgroundColor": "#FAFAFA",
-      "paintInvalidations": [
-        {
-          "object": "LayoutSlider INPUT",
-          "rect": [580, 15, 70, 2],
-          "reason": "full"
-        },
-        {
-          "object": "LayoutBlockFlow DIV id='thumb'",
-          "rect": [597, 0, 36, 32],
-          "reason": "full"
-        },
-        {
-          "object": "LayoutBlockFlow DIV id='thumb'",
-          "rect": [562, 0, 36, 32],
-          "reason": "full"
-        },
-        {
-          "object": "LayoutButton INPUT",
-          "rect": [530, 0, 32, 32],
-          "reason": "full"
-        }
-      ]
-    }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "LayoutBlockFlow (anonymous)",
-      "reason": "geometry"
-    },
-    {
-      "object": "RootInlineBox",
-      "reason": "geometry"
-    },
-    {
-      "object": "LayoutVideo VIDEO id='v'",
-      "reason": "style change"
-    },
-    {
-      "object": "LayoutFlexibleBox (relative positioned) DIV",
-      "reason": "geometry"
-    },
-    {
-      "object": "LayoutButton INPUT",
-      "reason": "full"
-    },
-    {
-      "object": "LayoutSlider INPUT",
-      "reason": "full"
-    },
-    {
-      "object": "LayoutFlexibleBox DIV",
-      "reason": "geometry"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='thumb'",
-      "reason": "full"
-    }
-  ]
-}
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/window-resize-no-layout-change1-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/window-resize-no-layout-change1-expected.txt
new file mode 100644
index 0000000..b3afdb1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/window-resize-no-layout-change1-expected.txt
@@ -0,0 +1,41 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [600, 250],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    }
+  ]
+}
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [400, 250],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    }
+  ]
+}
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [400, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    }
+  ]
+}
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/window-resize-no-layout-change2-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/window-resize-no-layout-change2-expected.txt
new file mode 100644
index 0000000..b3afdb1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/window-resize-no-layout-change2-expected.txt
@@ -0,0 +1,41 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [600, 250],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    }
+  ]
+}
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [400, 250],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    }
+  ]
+}
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [400, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    }
+  ]
+}
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/fullscreen/compositor-touch-hit-rects-fullscreen-video-controls-expected.txt b/third_party/WebKit/LayoutTests/fullscreen/compositor-touch-hit-rects-fullscreen-video-controls-expected.txt
index 07ccb4bc..cd1ef64 100644
--- a/third_party/WebKit/LayoutTests/fullscreen/compositor-touch-hit-rects-fullscreen-video-controls-expected.txt
+++ b/third_party/WebKit/LayoutTests/fullscreen/compositor-touch-hit-rects-fullscreen-video-controls-expected.txt
@@ -6,7 +6,6 @@
 EVENT(webkitfullscreenchange)
 Should keep rect on document
 handler: #document (0, 0, 800, 600)
-handler: #document (56, 600, 712, 8)
 
 END OF TEST
 
diff --git a/third_party/WebKit/LayoutTests/hittesting/touch-transformed-image-pseudo.html b/third_party/WebKit/LayoutTests/hittesting/touch-transformed-image-pseudo.html
new file mode 100644
index 0000000..d9ad1899
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/hittesting/touch-transformed-image-pseudo.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<style>
+  div.target {
+    display: inline-block;
+    overflow: hidden;
+  }
+  div.target:after {
+    display: inline-block;
+    content: url(../css3/background/resources/circle.png);
+    will-change: transform;
+  }
+</style>
+<script src='../resources/testharness.js'></script>
+<script src='../resources/testharnessreport.js'></script>
+<script>
+  function runTest() {
+    test(function() {
+      if (window.eventSender) {
+          eventSender.gestureShowPress(188, 150);
+      }
+    }, "Verify we do not assert when touching an image used with psuedo after");
+  }
+</script>
+<body onload="runTest()">
+<div class="target"></div>
+</body>
+
diff --git a/third_party/WebKit/LayoutTests/html/dialog/dialog-autofocus-expected.txt b/third_party/WebKit/LayoutTests/html/dialog/dialog-autofocus-expected.txt
deleted file mode 100644
index 7e2717b..0000000
--- a/third_party/WebKit/LayoutTests/html/dialog/dialog-autofocus-expected.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-Tests autofocus when a modal dialog is opened.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS document.activeElement is document.getElementById("outer-button")
-PASS document.activeElement is autofocusButton
-PASS document.activeElement is anotherButton
-Test that reattaching does not give focus back to a previously autofocused element.
-PASS document.activeElement is anotherButton
-Test that reinserting does not give focus back to a previously autofocused element.
-PASS document.activeElement is anotherButton
-Test that autofocus runs again when a dialog is reopened.
-PASS document.activeElement is autofocusButton
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/html/dialog/dialog-autofocus-multiple-times-expected.txt b/third_party/WebKit/LayoutTests/html/dialog/dialog-autofocus-multiple-times-expected.txt
deleted file mode 100644
index a7565e2..0000000
--- a/third_party/WebKit/LayoutTests/html/dialog/dialog-autofocus-multiple-times-expected.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-Tests autofocus is run every time a dialog is opened.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS document.activeElement is document.getElementById("outer-button")
-PASS document.activeElement is document.getElementById("input2")
-PASS document.activeElement is document.getElementById("input1")
-PASS document.activeElement is document.getElementById("input2")
-PASS document.activeElement is document.getElementById("input1")
-PASS document.activeElement is document.getElementById("input2")
-PASS document.activeElement is document.getElementById("input1")
-PASS 3 is 3
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/html/dialog/dialog-autofocus-multiple-times.html b/third_party/WebKit/LayoutTests/html/dialog/dialog-autofocus-multiple-times.html
deleted file mode 100644
index 90685e8e..0000000
--- a/third_party/WebKit/LayoutTests/html/dialog/dialog-autofocus-multiple-times.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script src="../../resources/js-test.js"></script>
-<script src="../../fast/forms/resources/common.js"></script>
-<script>
-description('Tests autofocus is run every time a dialog is opened.');
-
-function test() {
-    shouldBe('document.activeElement', 'document.getElementById("outer-button")');
-
-    var focusCount = 0;
-    input2.onfocus = function() { focusCount += 1 };
-
-    var expectedFocusCount = 3;
-    for (i = 0; i < expectedFocusCount; i++) {
-        dlg.show();
-        shouldBe('document.activeElement', 'document.getElementById("input2")');
-        input1.focus();
-        shouldBe('document.activeElement', 'document.getElementById("input1")');
-        dlg.close();
-    }
-
-    shouldBe(focusCount.toString(), expectedFocusCount.toString());
-
-    finishJSTest();
-}
-
-jsTestIsAsync = true;
-waitUntilLoadedAndAutofocused(test);
-</script>
-</head>
-<body>
-<button id="outer-button" autofocus></button>
-<dialog id="dlg">
-    <!-- Unfocusable elements with [autofocus] should be ignored. -->
-    <input autofocus disabled>
-    <textarea autofocus hidden></textarea>
-    <input id="input1"></input>
-    <input id="input2" autofocus></input>
-</dialog>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/html/dialog/dialog-autofocus.html b/third_party/WebKit/LayoutTests/html/dialog/dialog-autofocus.html
deleted file mode 100644
index 113eecc..0000000
--- a/third_party/WebKit/LayoutTests/html/dialog/dialog-autofocus.html
+++ /dev/null
@@ -1,68 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script src="../../resources/js-test.js"></script>
-<script src="../../fast/forms/resources/common.js"></script>
-<script>
-description('Tests autofocus when a modal dialog is opened.');
-
-function test() {
-    shouldBe('document.activeElement', 'document.getElementById("outer-button")');
-
-    var dialog = document.getElementById('dialog');
-    dialog.showModal();
-
-    autofocusButton = document.getElementById('autofocus-button');
-    shouldBe('document.activeElement', 'autofocusButton');
-
-    anotherButton = document.getElementById('another-button');
-    anotherButton.focus();
-    shouldBe('document.activeElement', 'anotherButton');
-
-    debug('Test that reattaching does not give focus back to a previously autofocused element.');
-    autofocusButton.style.display = 'none';
-    document.body.offsetHeight;
-    autofocusButton.style.display = 'block';
-    document.body.offsetHeight;
-    shouldBe('document.activeElement', 'anotherButton');
-
-    debug('Test that reinserting does not give focus back to a previously autofocused element.');
-    var parentNode = autofocusButton.parentNode;
-    parentNode.removeChild(autofocusButton);
-    document.body.offsetHeight;
-    parentNode.appendChild(autofocusButton);
-    document.body.offsetHeight;
-    shouldBe('document.activeElement', 'anotherButton');
-
-    dialog.close();
-    debug('Test that autofocus runs again when a dialog is reopened.');
-    dialog.showModal();
-    shouldBe('document.activeElement', 'autofocusButton');
-    dialog.close();
-
-    finishJSTest();
-}
-
-jsTestIsAsync = true;
-waitUntilLoadedAndAutofocused(test);
-</script>
-</head>
-<body>
-<button id="outer-button" autofocus></button>
-<dialog id="dialog">
-    <button></button>
-    <!-- Unfocusable elements with [autofocus] should be ignored. -->
-    <input autofocus disabled>
-    <textarea autofocus hidden></textarea>
-    <dialog>
-        <button autofocus></button>
-    </dialog>
-    <div>
-        <span>
-            <button id="autofocus-button" autofocus></button>
-        </span>
-    </div>
-    <button id="another-button" autofocus></button>
-</dialog>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/csspaint/hidpi/geometry-with-hidpi-zoom-expected.html b/third_party/WebKit/LayoutTests/http/tests/csspaint/hidpi/geometry-with-hidpi-zoom-expected.html
new file mode 100644
index 0000000..c8e50ead
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/csspaint/hidpi/geometry-with-hidpi-zoom-expected.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<style>
+html, body { margin: 0; padding: 0; }
+</style>
+<body>
+<canvas id ="canvas" width="187" height="187" style="position:relative;"></canvas>
+<script>
+document.body.style.zoom = "33%";
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'green';
+context.fillRect(0, 0, 187, 187);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/csspaint/hidpi/geometry-with-hidpi-zoom.html b/third_party/WebKit/LayoutTests/http/tests/csspaint/hidpi/geometry-with-hidpi-zoom.html
new file mode 100644
index 0000000..0be421e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/csspaint/hidpi/geometry-with-hidpi-zoom.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<script src="../../resources/run-after-layout-and-paint.js"></script>
+<script src="../resources/test-runner-paint-worklet.js"></script>
+<style>
+html, body { margin: 0; padding: 0; }
+.container {
+  width: 187px;
+  height: 187px;
+}
+
+#canvas-geometry {
+  background-image: paint(geometry);
+}
+</style>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+    paint(ctx, geom) {
+        if (geom.width == 187 && geom.height == 187)
+            ctx.fillStyle = 'green';
+        else
+            ctx.fillStyle = 'red';
+        ctx.fillRect(0, 0, geom.width, geom.height);
+    }
+});
+</script>
+
+<script>
+    document.body.style.zoom = "33%";
+    importPaintWorkletAndTerminateTestAfterAsyncPaint(document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-message-format-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-message-format-expected.txt
index 441557d9..992b933 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-message-format-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-message-format-expected.txt
@@ -1,8 +1,11 @@
 Tests that console logging uses proper message formatting.
 
-console-message-format.js:14 Message format number 1, 2 and 3.5
-console-message-format.js:15 Message format for string
-console-message-format.js:16 Object Object
+console-message-format.js:11 Message format number 1, 2 and 3.5
+console-message-format.js:12 Message format for string
+console-message-format.js:13 Object {foo: "bar"}
+console-message-format.js:14 Array (2) ["foo", "bar"]
+console-message-format.js:15 Object as object: Object
+console-message-format.js:16 Array as object: Array(2)
 console-message-format.js:17 Floating as integers: 42 42
 console-message-format.js:18 Floating as is: 42.5
 console-message-format.js:19 Non-numbers as numbers: NaN NaN NaN
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-message-format.js b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-message-format.js
index 6b2b15c7..a1f8921 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-message-format.js
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-message-format.js
@@ -7,13 +7,13 @@
 
   await TestRunner.loadModule('console_test_runner');
   await TestRunner.showPanel('console');
-  await TestRunner.loadHTML(`
-    <p id="p"></p>
-  `);
   await TestRunner.evaluateInPagePromise(`
     console.log('Message format number %i, %d and %f', 1, 2, 3.5);
     console.log('Message %s for %s', 'format', 'string');
     console.log('Object %o', {'foo' : 'bar' });
+    console.log('Array %o', ['foo', 'bar']);
+    console.log('Object as object: %O', {'foo' : 'bar' });
+    console.log('Array as object: %O', ['foo', 'bar']);
     console.log("Floating as integers: %d %i", 42.5, 42.5);
     console.log("Floating as is: %f", 42.5);
     console.log("Non-numbers as numbers: %d %i %f", document, null, "document");
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-choose-preview-view-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-choose-preview-view-expected.txt
index 020f2907..ec1be8c9 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-choose-preview-view-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-choose-preview-view-expected.txt
@@ -1,39 +1,122 @@
 Tests to make sure the proper view is used for the data that is received in network panel.
 
 Simple JSON
-Creating a NetworkRequest with mimeType: application/json
+Testing with MimeType: application/json, and StatusCode: 200
 Content: [533,3223]
-Its previewer type: SearchableView > widget vbox json-view
+
+ResourceType(xhr): SearchableView > widget vbox json-view
+ResourceType(fetch): SearchableView > widget vbox json-view
+ResourceType(document): SearchableView > widget vbox json-view
+ResourceType(other): SearchableView > widget vbox json-view
+
 MIME JSON
-Creating a NetworkRequest with mimeType: application/vnd.document+json
+Testing with MimeType: application/vnd.document+json, and StatusCode: 200
 Content: {foo0foo: 123}
-Its previewer type: SearchableView > widget vbox json-view
+
+ResourceType(xhr): SearchableView > widget vbox json-view
+ResourceType(fetch): SearchableView > widget vbox json-view
+ResourceType(document): SearchableView > widget vbox json-view
+ResourceType(other): SearchableView > widget vbox json-view
+
 Simple XML
-Creating a NetworkRequest with mimeType: text/xml
+Testing with MimeType: text/xml, and StatusCode: 200
 Content: <bar><foo/></bar>
-Its previewer type: SearchableView > widget shadow-xml-view source-code
+
+ResourceType(xhr): SearchableView > widget shadow-xml-view source-code
+ResourceType(fetch): SearchableView > widget shadow-xml-view source-code
+ResourceType(document): SearchableView > widget shadow-xml-view source-code
+ResourceType(other): SearchableView > widget shadow-xml-view source-code
+
 XML MIME But JSON
-Creating a NetworkRequest with mimeType: text/xml
+Testing with MimeType: text/xml, and StatusCode: 200
 Content: {foo0: 'barr', 'barr': 'fooo'}
-Its previewer type: SearchableView > widget vbox json-view
+
+ResourceType(xhr): SearchableView > widget vbox json-view
+ResourceType(fetch): SearchableView > widget vbox json-view
+ResourceType(document): SearchableView > widget vbox json-view
+ResourceType(other): SearchableView > widget vbox json-view
+
+HTML MIME But JSON
+Testing with MimeType: text/html, and StatusCode: 200
+Content: {hi: "hi"}
+
+ResourceType(xhr): SearchableView > widget vbox json-view
+ResourceType(fetch): SearchableView > widget vbox json-view
+ResourceType(document): SearchableView > widget vbox json-view
+ResourceType(other): SearchableView > widget vbox json-view
+
+TEXT MIME But JSON
+Testing with MimeType: text/html, and StatusCode: 200
+Content: {hi: "hi"}
+
+ResourceType(xhr): SearchableView > widget vbox json-view
+ResourceType(fetch): SearchableView > widget vbox json-view
+ResourceType(document): SearchableView > widget vbox json-view
+ResourceType(other): SearchableView > widget vbox json-view
+
+HTML MIME With 500 error
+Testing with MimeType: text/html, and StatusCode: 500
+Content: This
+<b>is a </b><br /><br />test.
+
+ResourceType(xhr): widget vbox html request-view
+ResourceType(fetch): widget vbox html request-view
+ResourceType(document): widget vbox html request-view
+ResourceType(other): widget vbox html request-view
+
+Plain Text MIME But HTML/XML
+Testing with MimeType: text/plain, and StatusCode: 200
+Content: This
+<b>is a </b><br /><br />test.
+
+ResourceType(xhr): SearchableView > widget vbox
+ResourceType(fetch): SearchableView > widget vbox
+ResourceType(document): SearchableView > widget vbox
+ResourceType(other): SearchableView > widget vbox
+
 XML With Unknown MIME
-Creating a NetworkRequest with mimeType: text/foobar
+Testing with MimeType: text/foobar, and StatusCode: 200
 Content: <bar><foo/></bar>
-Its previewer type: SearchableView > widget vbox
+
+ResourceType(xhr): SearchableView > widget vbox
+ResourceType(fetch): SearchableView > widget vbox
+ResourceType(document): SearchableView > widget vbox
+ResourceType(other): SearchableView > widget vbox
+
 XML With Error 500
-Creating a NetworkRequest with mimeType: text/xml
+Testing with MimeType: text/xml, and StatusCode: 500
 Content: <bar><foo/></bar>
-Its previewer type: SearchableView > widget shadow-xml-view source-code
+
+ResourceType(xhr): SearchableView > widget shadow-xml-view source-code
+ResourceType(fetch): SearchableView > widget shadow-xml-view source-code
+ResourceType(document): SearchableView > widget shadow-xml-view source-code
+ResourceType(other): SearchableView > widget shadow-xml-view source-code
+
 Unknown MIME Text With Error 500
-Creating a NetworkRequest with mimeType: text/foobar
+Testing with MimeType: text/foobar, and StatusCode: 500
 Content: Foo Bar
-Its previewer type: SearchableView > widget vbox
+
+ResourceType(xhr): SearchableView > widget vbox
+ResourceType(fetch): SearchableView > widget vbox
+ResourceType(document): SearchableView > widget vbox
+ResourceType(other): SearchableView > widget vbox
+
 Binary Image File
-Creating a NetworkRequest with mimeType: image/png
+Testing with MimeType: image/png, and StatusCode: 200
 Content: Bin**NULL**ary File**NULL****NULL**
-Its previewer type: SearchableView > widget vbox
+
+ResourceType(xhr): SearchableView > widget vbox
+ResourceType(fetch): SearchableView > widget vbox
+ResourceType(document): SearchableView > widget vbox
+ResourceType(other): SearchableView > widget vbox
+
 Binary Blank Image File
-Creating a NetworkRequest with mimeType: image/png
+Testing with MimeType: image/png, and StatusCode: 200
 Content: 
-Its previewer type: widget vbox empty-view-scroller
+
+ResourceType(xhr): widget vbox empty-view-scroller
+ResourceType(fetch): widget vbox empty-view-scroller
+ResourceType(document): widget vbox empty-view-scroller
+ResourceType(other): widget vbox empty-view-scroller
+
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-choose-preview-view.html b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-choose-preview-view.html
index 02849e4..b1ef47e 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-choose-preview-view.html
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-choose-preview-view.html
@@ -4,10 +4,9 @@
 <script src="../../inspector/network-test.js"></script>
 <script>
 async function test() {
-  function createNetworkRequest(mimeType, content, statusCode) {
-    TestRunner.addResult('Creating a NetworkRequest with mimeType: ' + mimeType);
+  function createNetworkRequest(mimeType, content, statusCode, resourceType) {
     var request = new SDK.NetworkRequest(0, 'http://localhost');
-    TestRunner.addResult('Content: ' + content.replace(/\0/g, '**NULL**'));
+    request._resourceType = resourceType;
     request.mimeType = mimeType;
     request._contentData = Promise.resolve({error: null, content: content, encoded: false});
     if (statusCode !== undefined)
@@ -23,11 +22,23 @@
     return previewer.contentElement.className;
   }
 
-  async function testPreviewer(contentType, content, statusCode) {
-    var request = createNetworkRequest(contentType, content, statusCode);
-    var previewView = new Network.RequestPreviewView(request, new Network.RequestResponseView(request));
-    previewView.wasShown();
-    TestRunner.addResult('Its previewer type: ' + getViewName(await previewView._contentViewPromise));
+  async function testPreviewer(mimeType, content, statusCode) {
+    var testResourceTypes = [
+      Common.resourceTypes.XHR,
+      Common.resourceTypes.Fetch,
+      Common.resourceTypes.Document,
+      Common.resourceTypes.Other
+    ];
+    TestRunner.addResult('Testing with MimeType: ' + mimeType + ', and StatusCode: ' + statusCode);
+    TestRunner.addResult('Content: ' + content.replace(/\0/g, '**NULL**'));
+    TestRunner.addResult('');
+    for (var resourceType of testResourceTypes) {
+      var request = createNetworkRequest(mimeType, content, statusCode, resourceType);
+      var previewView = new Network.RequestPreviewView(request, new Network.RequestResponseView(request));
+      previewView.wasShown();
+      TestRunner.addResult('ResourceType(' + resourceType.name() + '): ' + getViewName(await previewView._contentViewPromise));
+    }
+    TestRunner.addResult('');
   }
 
   TestRunner.addResult('Simple JSON');
@@ -42,6 +53,18 @@
   TestRunner.addResult('XML MIME But JSON');
   await testPreviewer('text/xml', '{foo0: \'barr\', \'barr\': \'fooo\'}', 200);
 
+  TestRunner.addResult('HTML MIME But JSON');
+  await testPreviewer('text/html', '{hi: "hi"}', 200);
+
+  TestRunner.addResult('TEXT MIME But JSON');
+  await testPreviewer('text/html', '{hi: "hi"}', 200);
+
+  TestRunner.addResult('HTML MIME With 500 error');
+  await testPreviewer('text/html', 'This\n<b>is a </b><br /><br />test.', 500);
+
+  TestRunner.addResult('Plain Text MIME But HTML/XML');
+  await testPreviewer('text/plain', 'This\n<b>is a </b><br /><br />test.', 200);
+
   TestRunner.addResult('XML With Unknown MIME');
   await testPreviewer('text/foobar', '<bar><foo/></bar>', 200);
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/subresource_filter/collapsed-image-style-crash.html b/third_party/WebKit/LayoutTests/http/tests/subresource_filter/collapsed-image-style-crash.html
new file mode 100644
index 0000000..82bf48a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/subresource_filter/collapsed-image-style-crash.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<body>
+<script type="text/javascript">
+// Tests that style resolution of an an out-of-flow image that is disallowed thus collapsed doesn't crash.
+
+if (window.testRunner) {
+  // Inject a subresource filter to disallow 'beta.png'.
+  testRunner.setDisallowedSubresourcePathSuffixes(["beta.png"]);
+}
+
+async_test(t => {
+  let i = document.createElement("img");
+  i.style.position = 'absolute';
+  i.onload = t.unreached_func();
+  i.onerror = t.step_func_done(_ => {
+    let style = window.getComputedStyle(i);
+    assert_equals(style.display, "none", "Images that are disallowed should be set to display:none");
+  });
+  i.src = "resources/beta.png";
+  document.body.append(i);
+}, "Style resolution does not crash with disallowed out-of-flow images.");
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/workers/resources/terminate-during-sync-operation.js b/third_party/WebKit/LayoutTests/http/tests/workers/resources/terminate-during-sync-operation.js
index 11a9cd5..5575d8f 100644
--- a/third_party/WebKit/LayoutTests/http/tests/workers/resources/terminate-during-sync-operation.js
+++ b/third_party/WebKit/LayoutTests/http/tests/workers/resources/terminate-during-sync-operation.js
@@ -1,7 +1,8 @@
 var workersStarted;
 var workersClosed;
-// 30 workers seemed to cause the crash to happen frequently.
-var workers = new Array(30);
+// More than 20 workers causes OOM crashes (hitting RLIMIT_DATA memory limits)
+// on Linux.
+var workers = new Array(20);
 
 function startWorkers(operationName)
 {
diff --git a/third_party/WebKit/LayoutTests/http/tests/workers/terminate-during-sync-operation-file-expected.txt b/third_party/WebKit/LayoutTests/http/tests/workers/terminate-during-sync-operation-file-expected.txt
index f9017c4..09112cd4 100644
--- a/third_party/WebKit/LayoutTests/http/tests/workers/terminate-during-sync-operation-file-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/workers/terminate-during-sync-operation-file-expected.txt
@@ -23,16 +23,6 @@
 Started worker count: 18
 Started worker count: 19
 Started worker count: 20
-Started worker count: 21
-Started worker count: 22
-Started worker count: 23
-Started worker count: 24
-Started worker count: 25
-Started worker count: 26
-Started worker count: 27
-Started worker count: 28
-Started worker count: 29
-Started worker count: 30
 Running operation.
 Closed worker count: 1
 Closed worker count: 2
@@ -54,15 +44,5 @@
 Closed worker count: 18
 Closed worker count: 19
 Closed worker count: 20
-Closed worker count: 21
-Closed worker count: 22
-Closed worker count: 23
-Closed worker count: 24
-Closed worker count: 25
-Closed worker count: 26
-Closed worker count: 27
-Closed worker count: 28
-Closed worker count: 29
-Closed worker count: 30
 DONE
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/workers/terminate-during-sync-operation-filesystem-expected.txt b/third_party/WebKit/LayoutTests/http/tests/workers/terminate-during-sync-operation-filesystem-expected.txt
index 1068286..c3fe46e 100644
--- a/third_party/WebKit/LayoutTests/http/tests/workers/terminate-during-sync-operation-filesystem-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/workers/terminate-during-sync-operation-filesystem-expected.txt
@@ -23,16 +23,6 @@
 Started worker count: 18
 Started worker count: 19
 Started worker count: 20
-Started worker count: 21
-Started worker count: 22
-Started worker count: 23
-Started worker count: 24
-Started worker count: 25
-Started worker count: 26
-Started worker count: 27
-Started worker count: 28
-Started worker count: 29
-Started worker count: 30
 Running operation.
 Closed worker count: 1
 Closed worker count: 2
@@ -54,15 +44,5 @@
 Closed worker count: 18
 Closed worker count: 19
 Closed worker count: 20
-Closed worker count: 21
-Closed worker count: 22
-Closed worker count: 23
-Closed worker count: 24
-Closed worker count: 25
-Closed worker count: 26
-Closed worker count: 27
-Closed worker count: 28
-Closed worker count: 29
-Closed worker count: 30
 DONE
 
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-layer-filter-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-layer-filter-expected.png
index 0328d65..3a67f62 100644
--- a/third_party/WebKit/LayoutTests/images/color-profile-layer-filter-expected.png
+++ b/third_party/WebKit/LayoutTests/images/color-profile-layer-filter-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/accessibility/accessibility-ignoredNodes-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/accessibility/accessibility-ignoredNodes-expected.txt
index b79b4355..41bd81f 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/accessibility/accessibility-ignoredNodes-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/accessibility/accessibility-ignoredNodes-expected.txt
@@ -340,6 +340,9 @@
   GenericContainer
   *combobox
     MenuListPopup
+      menuitem "Options should be"
+      menuitem "sent down even though"
+      menuitem "they are grandchildren"
 {
   "nodeId": "<string>",
   "ignored": false,
diff --git a/third_party/WebKit/LayoutTests/media/controls/closed-captions-single-track.html b/third_party/WebKit/LayoutTests/media/controls/closed-captions-single-track.html
index 4c58267..554c76fb 100644
--- a/third_party/WebKit/LayoutTests/media/controls/closed-captions-single-track.html
+++ b/third_party/WebKit/LayoutTests/media/controls/closed-captions-single-track.html
@@ -36,6 +36,7 @@
 
       // Captions track should become visible after the closed caption button is pressed.
       checkCaptionsVisible(video, captions);
+      checkButtonHasClass(toggleClosedCaptionsButton(video), "visible");
 
       // Click the closed captions button again and make sure the menu does not appear.
       clickCaptionButton(video);
@@ -43,6 +44,7 @@
 
       // Captions track should become invisible after the closed caption button is pressed.
       checkCaptionsHidden(video);
+      checkButtonNotHasClass(toggleClosedCaptionsButton(video), "visible");
     }));
   });
 
diff --git a/third_party/WebKit/LayoutTests/media/controls/repaint-on-resize-expected.html b/third_party/WebKit/LayoutTests/media/controls/repaint-on-resize-expected.html
new file mode 100644
index 0000000..4abf143574
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/media/controls/repaint-on-resize-expected.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>Test that the controls repaint correctly on resize.</title>
+<script src="../media-file.js"></script>
+<video controls width=300></video>
+<script>
+var video = document.querySelector("video");
+
+if (window.testRunner)
+  testRunner.waitUntilDone();
+
+video.onloadedmetadata = function() {
+  video.currentTime = 2;
+
+  if (window.testRunner)
+    testRunner.notifyDone();
+};
+
+video.src = findMediaFile("video", "../content/test");
+</script>
diff --git a/third_party/WebKit/LayoutTests/media/controls/repaint-on-resize.html b/third_party/WebKit/LayoutTests/media/controls/repaint-on-resize.html
new file mode 100644
index 0000000..42abd59
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/media/controls/repaint-on-resize.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title>Test that the controls repaint correctly on resize.</title>
+<script src="../media-file.js"></script>
+<video controls width=200></video>
+<script>
+var video = document.querySelector("video");
+
+if (window.testRunner)
+  testRunner.waitUntilDone();
+
+video.onloadedmetadata = function() {
+  video.currentTime = 2;
+  video.style.width = "300px";
+
+  if (window.testRunner)
+    testRunner.notifyDone();
+};
+
+video.src = findMediaFile("video", "../content/test");
+</script>
diff --git a/third_party/WebKit/LayoutTests/media/controls/toggle-class-with-state-cast.html b/third_party/WebKit/LayoutTests/media/controls/toggle-class-with-state-cast.html
new file mode 100644
index 0000000..ee37a61
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/media/controls/toggle-class-with-state-cast.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<title>Test that player state is reflected in CSS classes on the cast button.</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../media-controls.js"></script>
+<script src="../media-file.js"></script>
+<video controls width=400></video>
+<script>
+async_test(t => {
+  var video = document.querySelector('video');
+
+  video.onloadedmetadata = t.step_func_done(function() {
+    // Pretend we have a cast device.
+    internals.mediaPlayerRemoteRouteAvailabilityChanged(video, true);
+    checkButtonNotHasClass(castButton(video), 'on');
+
+    // Pretend we are casting.
+    internals.mediaPlayerPlayingRemotelyChanged(video, true);
+    checkButtonHasClass(castButton(video), 'on');
+  });
+
+  video.src = findMediaFile("video", "../content/counting");
+  video.play();
+});
+</script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/media/controls/toggle-class-with-state-fullscreen.html b/third_party/WebKit/LayoutTests/media/controls/toggle-class-with-state-fullscreen.html
new file mode 100644
index 0000000..ea43064
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/media/controls/toggle-class-with-state-fullscreen.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<title>Test that player state is reflected in CSS classes on the fullscreen button.</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../media-controls.js"></script>
+<script src="../media-file.js"></script>
+<video controls width=400></video>
+<script>
+async_test(t => {
+  var video = document.querySelector('video');
+
+  video.onwebkitfullscreenchange = t.step_func_done(_ => {
+    checkButtonHasClass(fullscreenButton(video), 'fullscreen');
+  });
+
+  document.onclick = t.step_func(_ => {
+    fullscreenButton(video).click();
+  });
+
+  video.onplay = t.step_func(_ => {
+    checkButtonNotHasClass(fullscreenButton(video), 'fullscreen');
+    clickAtCoordinates(1, 1);
+  });
+
+  video.src = findMediaFile("video", "../content/counting");
+  video.play();
+});
+</script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/media/controls/toggle-class-with-state-mute.html b/third_party/WebKit/LayoutTests/media/controls/toggle-class-with-state-mute.html
new file mode 100644
index 0000000..368e445
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/media/controls/toggle-class-with-state-mute.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<title>Test that player state is reflected in CSS classes on the mute button.</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../media-controls.js"></script>
+<script src="../media-file.js"></script>
+<video controls width=400></video>
+<script>
+async_test(t => {
+  var video = document.querySelector('video');
+  checkButtonNotHasClass(muteButton(video), 'muted');
+
+  t.step_func(_ => {
+    video.muted = true;
+
+    setTimeout(t.step_func_done(_ => {
+      checkButtonHasClass(muteButton(video), 'muted');
+    }));
+  })();
+});
+</script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/media/controls/toggle-class-with-state-overlay-cast.html b/third_party/WebKit/LayoutTests/media/controls/toggle-class-with-state-overlay-cast.html
new file mode 100644
index 0000000..4cebf33
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/media/controls/toggle-class-with-state-overlay-cast.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<title>Test that player state is reflected in CSS classes on the overlay cast button.</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../media-controls.js"></script>
+<script src="../media-file.js"></script>
+<video controls width=400></video>
+<script>
+async_test(t => {
+  var video = document.querySelector('video');
+
+  video.onloadedmetadata = t.step_func_done(function() {
+    // Pretend we have a cast device.
+    internals.mediaPlayerRemoteRouteAvailabilityChanged(video, true);
+    checkButtonNotHasClass(overlayCastButton(video), 'on');
+
+    // Pretend we are casting.
+    internals.mediaPlayerPlayingRemotelyChanged(video, true);
+    checkButtonHasClass(overlayCastButton(video), 'on');
+  });
+
+  video.src = findMediaFile("video", "../content/counting");
+  video.play();
+});
+</script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/media/controls/toggle-class-with-state-pause.html b/third_party/WebKit/LayoutTests/media/controls/toggle-class-with-state-pause.html
new file mode 100644
index 0000000..903f2ab
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/media/controls/toggle-class-with-state-pause.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<title>Test that player state is reflected in CSS classes on the play button.</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../media-controls.js"></script>
+<script src="../media-file.js"></script>
+<video controls width=400></video>
+<script>
+async_test(t => {
+  var video = document.querySelector('video');
+
+  video.onplay = t.step_func(_ => {
+    checkButtonNotHasClass(playButton(video), 'pause');
+    video.pause();
+  });
+
+  video.src = findMediaFile("video", "../content/counting");
+  video.play().catch(t.step_func_done(_ => {
+    checkButtonHasClass(playButton(video), 'pause');
+  }));
+});
+</script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/media/media-controls.js b/third_party/WebKit/LayoutTests/media/media-controls.js
index 31c02c6..99c14193 100644
--- a/third_party/WebKit/LayoutTests/media/media-controls.js
+++ b/third_party/WebKit/LayoutTests/media/media-controls.js
@@ -163,6 +163,18 @@
     return false;
 }
 
+function toggleClosedCaptionsButton(videoElement) {
+    return mediaControlsButton(videoElement, 'toggle-closed-captions-button');
+}
+
+function playButton(videoElement) {
+    return mediaControlsButton(videoElement, 'play-button');
+}
+
+function muteButton(videoElement) {
+    return mediaControlsButton(videoElement, 'mute-button');
+}
+
 function clickAtCoordinates(x, y)
 {
     eventSender.mouseMoveTo(x, y);
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-in-scrollers-expected.html b/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-in-scrollers-expected.html
new file mode 100644
index 0000000..4ba6db5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-in-scrollers-expected.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<style>
+.scroll {
+  position: relative;
+  width: 100px;
+  height: 100px;
+  display: inline-block;
+  border: 10px solid blue;
+  overflow: scroll;
+  padding: 5px;
+}
+.target {
+  width: 50px;
+  height: 50px;
+  outline: solid black 20px;
+}
+.space {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 150px;
+  height: 150px;
+}
+</style>
+<div class="scroll">
+  <div class="target"></div>
+  <div class="space"></div>
+</div>
+<div class="scroll" style="writing-mode: vertical-rl">
+  <div class="target"></div>
+  <div class="space"></div>
+</div>
+<div class="scroll" style="writing-mode: vertical-lr">
+  <div class="target"></div>
+  <div class="space"></div>
+</div>
+<br>
+<div class="scroll" style="direction: rtl">
+  <div class="target"></div>
+  <div class="space"></div>
+</div>
+<div class="scroll" style="direction: rtl; writing-mode: vertical-rl">
+  <div class="target"></div>
+  <div class="space"></div>
+</div>
+<div class="scroll" style="direction: rtl; writing-mode: vertical-lr">
+  <div class="target"></div>
+  <div class="space"></div>
+</div>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-in-scrollers-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-in-scrollers-expected.txt
new file mode 100644
index 0000000..c57f17d4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-in-scrollers-expected.txt
@@ -0,0 +1,69 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='target'",
+          "rect": [286, 173, 75, 75],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutBlockFlow DIV class='target'",
+          "rect": [286, 18, 75, 75],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutBlockFlow DIV class='target'",
+          "rect": [172, 173, 75, 75],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutBlockFlow DIV class='target'",
+          "rect": [172, 18, 75, 75],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutBlockFlow DIV class='target'",
+          "rect": [53, 153, 75, 75],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutBlockFlow DIV class='target'",
+          "rect": [18, 18, 75, 75],
+          "reason": "style change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV class='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow DIV class='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow DIV class='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow DIV class='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow DIV class='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow DIV class='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-in-scrollers.html b/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-in-scrollers.html
new file mode 100644
index 0000000..a3b9a34d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-in-scrollers.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML>
+<script src="resources/text-based-repaint.js"></script>
+<script>
+function repaintTest() {
+	document.querySelectorAll('.target').forEach(function(target) {
+		target.style.outline = 'solid black 20px';
+	});
+}
+onload = runRepaintAndPixelTest;
+</script>
+<style>
+.scroll {
+  position: relative;
+  width: 100px;
+  height: 100px;
+  display: inline-block;
+  border: 10px solid blue;
+  overflow: scroll;
+  padding: 5px;
+}
+.target {
+  width: 50px;
+  height: 50px;
+  outline: solid black 10px;
+}
+.space {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 150px;
+  height: 150px;
+}
+</style>
+<div class="scroll">
+  <div class="target"></div>
+  <div class="space"></div>
+</div>
+<div class="scroll" style="writing-mode: vertical-rl">
+  <div class="target"></div>
+  <div class="space"></div>
+</div>
+<div class="scroll" style="writing-mode: vertical-lr">
+  <div class="target"></div>
+  <div class="space"></div>
+</div>
+<br>
+<div class="scroll" style="direction: rtl">
+  <div class="target"></div>
+  <div class="space"></div>
+</div>
+<div class="scroll" style="direction: rtl; writing-mode: vertical-rl">
+  <div class="target"></div>
+  <div class="space"></div>
+</div>
+<div class="scroll" style="direction: rtl; writing-mode: vertical-lr">
+  <div class="target"></div>
+  <div class="space"></div>
+</div>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-scrollable-expected.html b/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-scrollable-expected.html
new file mode 100644
index 0000000..3ce4328
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-scrollable-expected.html
@@ -0,0 +1,2 @@
+<!DOCTYPE HTML>
+<div id="test" style="background-color: green; width: 1000px; height: 100px; outline: solid black 20px;"></div>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-scrollable-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-scrollable-expected.txt
new file mode 100644
index 0000000..d04d336
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-scrollable-expected.txt
@@ -0,0 +1,24 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [1008, 585],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV id='target'",
+          "rect": [-12, -12, 1040, 140],
+          "reason": "style change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV id='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-scrollable.html b/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-scrollable.html
new file mode 100644
index 0000000..b051fec
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-scrollable.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<script src="resources/text-based-repaint.js"></script>
+<script>
+function repaintTest() {
+  target.style.outline = 'solid black 20px';
+}
+onload = runRepaintAndPixelTest;
+</script>
+<div id="target" style="background-color: green; width: 1000px; height: 100px; outline: solid black 10px;"></div>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-vertical-rl-expected.html b/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-vertical-rl-expected.html
new file mode 100644
index 0000000..dbfe2a31
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-vertical-rl-expected.html
@@ -0,0 +1,3 @@
+<!DOCTYPE HTML>
+<style>body { writing-mode: vertical-rl; }</style>
+<div id="test" style="background-color: green; width: 1000px; height: 100px; outline: solid black 20px;"></div>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-vertical-rl-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-vertical-rl-expected.txt
new file mode 100644
index 0000000..a2a78fc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-vertical-rl-expected.txt
@@ -0,0 +1,36 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [1016, 585],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV id='target'",
+          "rect": [-12, -12, 1040, 140],
+          "reason": "style change"
+        }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [-216, 0, 0, 1]
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV id='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-vertical-rl.html b/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-vertical-rl.html
new file mode 100644
index 0000000..66601502
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/outline-change-vertical-rl.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<script src="resources/text-based-repaint.js"></script>
+<script>
+function repaintTest() {
+  target.style.outline = 'solid black 20px';
+}
+onload = runRepaintAndPixelTest;
+</script>
+<style>body { writing-mode: vertical-rl; }</style>
+<div id="target" style="background-color: green; width: 1000px; height: 100px; outline: solid black 10px;"></div>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/video-mute-repaint-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/video-mute-repaint-expected.txt
new file mode 100644
index 0000000..ddb2533
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/video-mute-repaint-expected.txt
@@ -0,0 +1,91 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutVideo VIDEO id='v'",
+      "position": [8, 8],
+      "bounds": [700, 525],
+      "drawsContent": false
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false
+    },
+    {
+      "name": "LayoutFlexibleBox (relative positioned) DIV class='phase-ready state-stopped'",
+      "position": [8, 8],
+      "bounds": [700, 525],
+      "paintInvalidations": [
+        {
+          "object": "LayoutFlexibleBox (relative positioned) DIV class='phase-ready state-stopped'",
+          "rect": [0, 0, 700, 525],
+          "reason": "geometry"
+        }
+      ]
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutFlexibleBox (relative positioned) DIV)",
+      "position": [8, 8],
+      "bounds": [700, 525],
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='-internal-track-segment-highlight-after'",
+          "rect": [580, 508, 70, 2],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutFlexibleBox DIV",
+          "rect": [580, 508, 70, 2],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='thumb'",
+          "rect": [632, 485, 36, 48],
+          "reason": "full"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='thumb'",
+          "rect": [562, 485, 36, 48],
+          "reason": "full"
+        },
+        {
+          "object": "LayoutButton INPUT class='muted'",
+          "rect": [530, 493, 32, 32],
+          "reason": "full"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutVideo VIDEO id='v'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutFlexibleBox (relative positioned) DIV class='phase-ready state-stopped'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutButton INPUT class='muted'",
+      "reason": "full"
+    },
+    {
+      "object": "LayoutFlexibleBox DIV",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='thumb'",
+      "reason": "full"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='-internal-track-segment-highlight-after'",
+      "reason": "disappeared"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/video-unmute-repaint-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/video-unmute-repaint-expected.txt
new file mode 100644
index 0000000..a8a8335e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/video-unmute-repaint-expected.txt
@@ -0,0 +1,91 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutVideo VIDEO id='v'",
+      "position": [8, 8],
+      "bounds": [700, 525],
+      "drawsContent": false
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false
+    },
+    {
+      "name": "LayoutFlexibleBox (relative positioned) DIV class='phase-ready state-stopped'",
+      "position": [8, 8],
+      "bounds": [700, 525],
+      "paintInvalidations": [
+        {
+          "object": "LayoutFlexibleBox (relative positioned) DIV class='phase-ready state-stopped'",
+          "rect": [0, 0, 700, 525],
+          "reason": "geometry"
+        }
+      ]
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutFlexibleBox (relative positioned) DIV)",
+      "position": [8, 8],
+      "bounds": [700, 525],
+      "paintInvalidations": [
+        {
+          "object": "LayoutFlexibleBox DIV",
+          "rect": [580, 508, 70, 2],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='thumb'",
+          "rect": [597, 485, 36, 48],
+          "reason": "full"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='thumb'",
+          "rect": [562, 485, 36, 48],
+          "reason": "full"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='-internal-track-segment-highlight-after'",
+          "rect": [580, 508, 35, 2],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutButton INPUT",
+          "rect": [530, 493, 32, 32],
+          "reason": "full"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutVideo VIDEO id='v'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutFlexibleBox (relative positioned) DIV class='phase-ready state-stopped'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutButton INPUT",
+      "reason": "full"
+    },
+    {
+      "object": "LayoutFlexibleBox DIV",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='thumb'",
+      "reason": "full"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='-internal-track-segment-highlight-after'",
+      "reason": "appeared"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/platform/linux/animations/rotate-transform-equivalent-expected.png b/third_party/WebKit/LayoutTests/platform/linux/animations/rotate-transform-equivalent-expected.png
index 6e8a77f5c..601284d7 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/animations/rotate-transform-equivalent-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/animations/rotate-transform-equivalent-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/animations/skew-notsequential-compositor-expected.png b/third_party/WebKit/LayoutTests/platform/linux/animations/skew-notsequential-compositor-expected.png
deleted file mode 100644
index f1fb3b5..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/animations/skew-notsequential-compositor-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/3d-corners-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/3d-corners-expected.png
deleted file mode 100644
index d0a0cb8b..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/3d-corners-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/backface-visibility-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/backface-visibility-transformed-expected.png
deleted file mode 100644
index bc9a785..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/backface-visibility-transformed-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/backface-visibility/backface-visibility-non3d-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/backface-visibility/backface-visibility-non3d-expected.png
deleted file mode 100644
index 25e6017..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/backface-visibility/backface-visibility-non3d-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/color-matching/image-color-matching-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/color-matching/image-color-matching-expected.png
index 7ff9f914..b36d906 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/color-matching/image-color-matching-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/color-matching/image-color-matching-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/composited-scaled-child-with-border-radius-parent-clip-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/composited-scaled-child-with-border-radius-parent-clip-expected.png
deleted file mode 100644
index e606756..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/composited-scaled-child-with-border-radius-parent-clip-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/composited-translated-child-with-border-radius-parent-clip-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/composited-translated-child-with-border-radius-parent-clip-expected.png
deleted file mode 100644
index 5bfd018..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/composited-translated-child-with-border-radius-parent-clip-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/culling/filter-occlusion-blur-large-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/culling/filter-occlusion-blur-large-expected.png
deleted file mode 100644
index 147f72f..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/culling/filter-occlusion-blur-large-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/direct-image-compositing-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/direct-image-compositing-expected.png
index 0c46d4069a..8fe6974 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/direct-image-compositing-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/direct-image-compositing-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/flat-with-transformed-child-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/flat-with-transformed-child-expected.png
deleted file mode 100644
index ba38a6eb..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/flat-with-transformed-child-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/clipping-foreground-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/clipping-foreground-expected.png
index 96bb0b0..0bc0909 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/clipping-foreground-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/clipping-foreground-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/fixed-position-transform-composited-page-scale-down-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/fixed-position-transform-composited-page-scale-down-expected.png
index 80d70b5..df09a173 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/fixed-position-transform-composited-page-scale-down-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/fixed-position-transform-composited-page-scale-down-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/fixed-position-transform-composited-page-scale-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/fixed-position-transform-composited-page-scale-expected.png
index 34321ee..49cd3c4 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/fixed-position-transform-composited-page-scale-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/fixed-position-transform-composited-page-scale-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/layer-due-to-layer-children-deep-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/layer-due-to-layer-children-deep-expected.png
index 175396f..6b346b9 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/layer-due-to-layer-children-deep-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/layer-due-to-layer-children-deep-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/layer-due-to-layer-children-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/layer-due-to-layer-children-expected.png
index d853ebf..c1a8906 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/layer-due-to-layer-children-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/layer-due-to-layer-children-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/vertical-scroll-composited-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/vertical-scroll-composited-expected.png
deleted file mode 100644
index 2f459985..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/vertical-scroll-composited-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/video-fixed-scrolling-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/video-fixed-scrolling-expected.png
index 99e2a33c..7bc93af 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/video-fixed-scrolling-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/video-fixed-scrolling-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/video-opacity-overlay-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/video-opacity-overlay-expected.png
index 258709e4..860cb96 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/video-opacity-overlay-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/video-opacity-overlay-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/gestures/gesture-tapHighlight-pixel-rotated-div-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/gestures/gesture-tapHighlight-pixel-rotated-div-expected.png
index 35e95006..300b9f3 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/gestures/gesture-tapHighlight-pixel-rotated-div-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/gestures/gesture-tapHighlight-pixel-rotated-div-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/gestures/gesture-tapHighlight-pixel-rotated-link-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/gestures/gesture-tapHighlight-pixel-rotated-link-expected.png
index 7a4c0e10..c83cdd6 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/gestures/gesture-tapHighlight-pixel-rotated-link-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/gestures/gesture-tapHighlight-pixel-rotated-link-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/layers-inside-overflow-scroll-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/layers-inside-overflow-scroll-expected.png
index 1238627..9b1e725 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/layers-inside-overflow-scroll-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/layers-inside-overflow-scroll-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/lots-of-img-layers-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/lots-of-img-layers-expected.png
deleted file mode 100644
index 1d5e388..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/lots-of-img-layers-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/lots-of-img-layers-with-opacity-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/lots-of-img-layers-with-opacity-expected.png
deleted file mode 100644
index 504660f..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/lots-of-img-layers-with-opacity-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/direct-image-mask-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/direct-image-mask-expected.png
index 0a42af3..5d33323 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/direct-image-mask-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/direct-image-mask-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/mask-with-added-filters-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/mask-with-added-filters-expected.png
index c8800e2..5119710 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/mask-with-added-filters-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/mask-with-added-filters-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/mask-with-removed-filters-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/mask-with-removed-filters-expected.png
index e01f792..2ca7f39 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/mask-with-removed-filters-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/mask-with-removed-filters-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/masked-ancestor-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/masked-ancestor-expected.png
index d565ad6..321cc1df 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/masked-ancestor-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/masked-ancestor-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/multiple-masks-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/multiple-masks-expected.png
index b55370f2..415fe63b 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/multiple-masks-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/multiple-masks-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/simple-composited-mask-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/simple-composited-mask-expected.png
index 7e2a08f..a624d4cc 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/simple-composited-mask-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/masks/simple-composited-mask-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/opacity-with-mask-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/opacity-with-mask-expected.png
deleted file mode 100644
index 7792efb..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/opacity-with-mask-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/accelerated-scrolling-with-clip-path-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/accelerated-scrolling-with-clip-path-expected.png
deleted file mode 100644
index 31ce3d9..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/accelerated-scrolling-with-clip-path-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/border-radius-on-grandparent-composited-grandchild-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/border-radius-on-grandparent-composited-grandchild-expected.png
deleted file mode 100644
index 2cee245..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/border-radius-on-grandparent-composited-grandchild-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/border-radius-on-parent-composited-grandchild-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/border-radius-on-parent-composited-grandchild-expected.png
deleted file mode 100644
index b60254a..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/border-radius-on-parent-composited-grandchild-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/border-radius-on-two-ancestors-composited-grandchild-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/border-radius-on-two-ancestors-composited-grandchild-expected.png
deleted file mode 100644
index b9fac482..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/border-radius-on-two-ancestors-composited-grandchild-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/border-radius-styles-with-composited-child-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/border-radius-styles-with-composited-child-expected.png
deleted file mode 100644
index 5fa2b0b..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/border-radius-styles-with-composited-child-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/grandchild-composited-with-border-radius-ancestor-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/grandchild-composited-with-border-radius-ancestor-expected.png
deleted file mode 100644
index f38a1b2..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/grandchild-composited-with-border-radius-ancestor-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/grandchild-with-border-radius-ancestor-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/grandchild-with-border-radius-ancestor-expected.png
deleted file mode 100644
index f38a1b2..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/grandchild-with-border-radius-ancestor-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/mask-with-filter-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/mask-with-filter-expected.png
deleted file mode 100644
index fff540df..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/mask-with-filter-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/nested-render-surfaces-with-intervening-clip-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/nested-render-surfaces-with-intervening-clip-expected.png
deleted file mode 100644
index ce412b6..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/nested-render-surfaces-with-intervening-clip-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/nested-render-surfaces-with-rotation-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/nested-render-surfaces-with-rotation-expected.png
deleted file mode 100644
index 7e616b7..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/nested-render-surfaces-with-rotation-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/overflow-compositing-descendant-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/overflow-compositing-descendant-expected.png
index 1e09c67..f5d9cd3 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/overflow-compositing-descendant-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/overflow-compositing-descendant-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/scaled-mask-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/scaled-mask-expected.png
index c98959e..f9d24e27 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/scaled-mask-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/scaled-mask-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/scaled-overflow-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/scaled-overflow-expected.png
deleted file mode 100644
index c1c4d7ff..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/scaled-overflow-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/scroll-ancestor-update-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/scroll-ancestor-update-expected.png
index 8916901..5d5a44a 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/scroll-ancestor-update-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/scroll-ancestor-update-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/siblings-composited-with-border-radius-ancestor-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/siblings-composited-with-border-radius-ancestor-expected.png
deleted file mode 100644
index f38a1b2..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/siblings-composited-with-border-radius-ancestor-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped-expected.png
deleted file mode 100644
index 00fa2b9..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/siblings-with-border-radius-ancestor-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/siblings-with-border-radius-ancestor-expected.png
deleted file mode 100644
index ff3a0270..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/siblings-with-border-radius-ancestor-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/tiled-mask-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/tiled-mask-expected.png
deleted file mode 100644
index ba320740..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/tiled-mask-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/overlap-blending/children-opacity-huge-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/overlap-blending/children-opacity-huge-expected.png
index 769cd76b..16ba49f6 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/overlap-blending/children-opacity-huge-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/overlap-blending/children-opacity-huge-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/overlap-blending/children-opacity-no-overlap-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/overlap-blending/children-opacity-no-overlap-expected.png
index eda3ec7..0cca7cab 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/overlap-blending/children-opacity-no-overlap-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/overlap-blending/children-opacity-no-overlap-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/overlap-blending/reflection-opacity-huge-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/overlap-blending/reflection-opacity-huge-expected.png
index 5188682d..e00a249 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/overlap-blending/reflection-opacity-huge-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/overlap-blending/reflection-opacity-huge-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/perpendicular-layer-sorting-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/perpendicular-layer-sorting-expected.png
deleted file mode 100644
index f6472ac..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/perpendicular-layer-sorting-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/animation-inside-reflection-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/animation-inside-reflection-expected.png
index e738eac..ca973d1 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/animation-inside-reflection-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/animation-inside-reflection-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/load-video-in-reflection-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/load-video-in-reflection-expected.png
index 62dcc8f..31cc698 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/load-video-in-reflection-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/load-video-in-reflection-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-mask-change-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-mask-change-expected.png
index 2c2cc64..b69a73e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-mask-change-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-mask-change-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-opacity-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-opacity-expected.png
index 6bc5112..0cd09ec 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-opacity-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-opacity-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/reflection-opacity-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/reflection-opacity-expected.png
index 95bb35b..c4f4808 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/reflection-opacity-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/reflection-opacity-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/transform-inside-reflection-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/transform-inside-reflection-expected.png
index d0f0e23..c603bb9 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/transform-inside-reflection-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/transform-inside-reflection-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/scaling/tiled-layer-recursion-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/scaling/tiled-layer-recursion-expected.png
deleted file mode 100644
index c2c43072..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/scaling/tiled-layer-recursion-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/self-painting-layers-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/self-painting-layers-expected.png
index 2d921e07..6c0d622e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/self-painting-layers-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/self-painting-layers-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/transitions/scale-transition-no-start-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/transitions/scale-transition-no-start-expected.png
index a6b62787..ed9d6db 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/transitions/scale-transition-no-start-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/transitions/scale-transition-no-start-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 ad074ba..667f5187 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/compositing/video/video-controls-layer-creation-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/video/video-controls-layer-creation-expected.png
index 2af8702..e0a1f07c 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/video/video-controls-layer-creation-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/video/video-controls-layer-creation-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/video/video-reflection-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/video/video-reflection-expected.png
deleted file mode 100644
index 635d07ac..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/video/video-reflection-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/visibility/visibility-image-layers-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/visibility/visibility-image-layers-expected.png
deleted file mode 100644
index 365ad04..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/visibility/visibility-image-layers-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/visibility/visibility-simple-video-layer-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/visibility/visibility-simple-video-layer-expected.png
deleted file mode 100644
index 3d2a91a..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/visibility/visibility-simple-video-layer-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/webgl/webgl-reflection-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/webgl/webgl-reflection-expected.png
index f90d16e5..5b050023 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/webgl/webgl-reflection-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/webgl/webgl-reflection-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css1/box_properties/float_elements_in_series-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css1/box_properties/float_elements_in_series-expected.png
index f0c1277..a6d4d61 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css1/box_properties/float_elements_in_series-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/css1/box_properties/float_elements_in_series-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css1/box_properties/padding_inline-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css1/box_properties/padding_inline-expected.png
index 4d33f7d..1901a6c 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css1/box_properties/padding_inline-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/css1/box_properties/padding_inline-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css1/pseudo/firstline-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css1/pseudo/firstline-expected.png
index 8fb0e49..a867f30b 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css1/pseudo/firstline-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/css1/pseudo/firstline-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css1/pseudo/pseudo_elements_in_selectors-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css1/pseudo/pseudo_elements_in_selectors-expected.png
index 33e24d83..e780cc7 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css1/pseudo/pseudo_elements_in_selectors-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/css1/pseudo/pseudo_elements_in_selectors-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css1/units/percentage_units-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css1/units/percentage_units-expected.png
index 05f2895..5f2ae23 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css1/units/percentage_units-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/css1/units/percentage_units-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css2.1/t0803-c5502-mrgn-r-02-c-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css2.1/t0803-c5502-mrgn-r-02-c-expected.png
index ac5b49c..102546dd 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css2.1/t0803-c5502-mrgn-r-02-c-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/css2.1/t0803-c5502-mrgn-r-02-c-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css2.1/t0803-c5505-mrgn-02-c-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css2.1/t0803-c5505-mrgn-02-c-expected.png
index f6036bc2..570392e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css2.1/t0803-c5505-mrgn-02-c-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/css2.1/t0803-c5505-mrgn-02-c-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css2.1/t1002-c5523-width-02-b-g-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css2.1/t1002-c5523-width-02-b-g-expected.png
index 65621b133..6d3dca24 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css2.1/t1002-c5523-width-02-b-g-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/css2.1/t1002-c5523-width-02-b-g-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png
index 43b6d39..bea958b 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-brightness-clamping-hw-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-brightness-clamping-hw-expected.png
deleted file mode 100644
index 359468a..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-brightness-clamping-hw-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-brightness-hw-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-brightness-hw-expected.png
deleted file mode 100644
index 4d27e489d..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-brightness-hw-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-combined-hw-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-combined-hw-expected.png
deleted file mode 100644
index c42e028..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-combined-hw-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-drop-shadow-hw-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-drop-shadow-hw-expected.png
deleted file mode 100644
index 91f798b..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-drop-shadow-hw-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-grayscale-hw-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-grayscale-hw-expected.png
deleted file mode 100644
index b5667035..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-grayscale-hw-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-hue-rotate-hw-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-hue-rotate-hw-expected.png
deleted file mode 100644
index a090534..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-hue-rotate-hw-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-saturate-hw-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-saturate-hw-expected.png
deleted file mode 100644
index 94d27c6..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-saturate-hw-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-sepia-hw-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-sepia-hw-expected.png
deleted file mode 100644
index 61e3630..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-sepia-hw-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/filter-change-repaint-composited-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/filter-change-repaint-composited-expected.png
deleted file mode 100644
index 3e6040d..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/filter-change-repaint-composited-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/filter-change-repaint-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/filter-change-repaint-expected.png
deleted file mode 100644
index 8495c55..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/filter-change-repaint-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/masking/mask-luminance-gradient-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/masking/mask-luminance-gradient-expected.png
deleted file mode 100644
index 1f638319..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/masking/mask-luminance-gradient-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/masking/mask-luminance-svg-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/masking/mask-luminance-svg-expected.png
deleted file mode 100644
index 8540526..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/masking/mask-luminance-svg-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/masking/mask-repeat-round-content-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/masking/mask-repeat-round-content-expected.png
deleted file mode 100644
index 6cfcdcf..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/masking/mask-repeat-round-content-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/masking/mask-repeat-space-border-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/masking/mask-repeat-space-border-expected.png
deleted file mode 100644
index a6775fa..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/masking/mask-repeat-space-border-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/masking/mask-repeat-space-content-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/masking/mask-repeat-space-content-expected.png
deleted file mode 100644
index de6fac53..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/masking/mask-repeat-space-content-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/masking/mask-repeat-space-padding-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/masking/mask-repeat-space-padding-expected.png
deleted file mode 100644
index 816d714..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/masking/mask-repeat-space-padding-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/external/wpt/offscreen-canvas/the-offscreen-canvas/offscreencanvas.getcontext-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/external/wpt/offscreen-canvas/the-offscreen-canvas/offscreencanvas.getcontext-expected.txt
deleted file mode 100644
index d1c9562..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/external/wpt/offscreen-canvas/the-offscreen-canvas/offscreencanvas.getcontext-expected.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-This is a testharness.js-based test.
-PASS Test that getContext with un-supported string throws a TypeError.
-FAIL Test that getContext with supported string returns correct results assert_true: expected true got false
-PASS Test that getContext twice with different context type returns null the second time
-PASS Test that 2dcontext.canvas should return the original OffscreenCanvas
-PASS Test that webglcontext.canvas should return the original OffscreenCanvas
-FAIL Test that OffscreenCanvasRenderingContext2D with alpha disabled makes the OffscreenCanvas opaque assert_approx_equals: Green channel of the pixel at (5, 5) expected 127 +/- 2 but got 255
-PASS Test that OffscreenCanvasRenderingContext2D with alpha enabled preserves the alpha
-PASS Test that 'alpha' context creation attribute is true by default
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/block/float/008-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/block/float/008-expected.png
deleted file mode 100644
index 54121bed..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/block/float/008-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/block/float/021-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/block/float/021-expected.png
index fa04624..821d7c4e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/block/float/021-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/block/float/021-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/block/margin-collapse/104-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/block/margin-collapse/104-expected.png
index 25d3074..e5a96215 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/block/margin-collapse/104-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/block/margin-collapse/104-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/relative-overflow-block-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/relative-overflow-block-expected.png
index 0a2c60b..0ef9c38 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/relative-overflow-block-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/relative-overflow-block-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/relative-overflow-replaced-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/relative-overflow-replaced-expected.png
index b0e8180c..0ad16d59 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/relative-overflow-replaced-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/relative-overflow-replaced-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/relative-overflow-replaced-float-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/relative-overflow-replaced-float-expected.png
index b026343..263be7f 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/relative-overflow-replaced-float-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/relative-overflow-replaced-float-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/vertical-lr/002-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/vertical-lr/002-expected.png
deleted file mode 100644
index b592b4df..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/vertical-lr/002-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/vertical-rl/002-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/vertical-rl/002-expected.png
deleted file mode 100644
index 7ab4b2b..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/vertical-rl/002-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/body-propagation/overflow/001-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/body-propagation/overflow/001-expected.png
index 81f3f975..af48641 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/body-propagation/overflow/001-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/body-propagation/overflow/001-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/body-propagation/overflow/001-xhtml-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/body-propagation/overflow/001-xhtml-expected.png
index 81f3f975..af48641 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/body-propagation/overflow/001-xhtml-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/body-propagation/overflow/001-xhtml-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/body-propagation/overflow/005-declarative-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/body-propagation/overflow/005-declarative-expected.png
index ea8ac8c..bb2ac67 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/body-propagation/overflow/005-declarative-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/body-propagation/overflow/005-declarative-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/body-propagation/overflow/005-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/body-propagation/overflow/005-expected.png
index ea8ac8c..bb2ac67 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/body-propagation/overflow/005-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/body-propagation/overflow/005-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/body-propagation/overflow/005-xhtml-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/body-propagation/overflow/005-xhtml-expected.png
index ea8ac8c..bb2ac67 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/body-propagation/overflow/005-xhtml-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/body-propagation/overflow/005-xhtml-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-canvas-border-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-canvas-border-expected.png
index bbe9bc26..2349e40 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-canvas-border-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-canvas-border-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-canvas-expected.png
index 1bb76e9..9da43fee 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-canvas-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-canvas-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-canvas-with-mask-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-canvas-with-mask-expected.png
index fe95cd4..b593f70e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-canvas-with-mask-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-canvas-with-mask-expected.png
Binary files differ
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 5fd3df6..b98e15b 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 c2adc3cd..6ea3eb3 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 5e17ebf..957b8fc9 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/borders/border-radius-with-composited-child-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-with-composited-child-expected.png
index f840e14..84c3456 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-with-composited-child-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-with-composited-child-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/rtl-border-01-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/rtl-border-01-expected.png
index 6a8899c2..43ebf48 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/rtl-border-01-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/rtl-border-01-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/rtl-border-02-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/rtl-border-02-expected.png
index c6d6c7d..302086d 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/rtl-border-02-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/rtl-border-02-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/rtl-border-03-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/rtl-border-03-expected.png
index f688ebc..4bfc994 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/rtl-border-03-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/rtl-border-03-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-composite-video-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-composite-video-expected.png
index 55b60e3..a39e5ac 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-composite-video-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-composite-video-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-composite-video-shadow-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-composite-video-shadow-expected.png
index ebe81ec..ee72053 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-composite-video-shadow-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-composite-video-shadow-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-drawImage-video-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-drawImage-video-expected.png
new file mode 100644
index 0000000..a58254b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-drawImage-video-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-pattern-video-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-pattern-video-expected.png
new file mode 100644
index 0000000..71553edf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-pattern-video-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/yuv-video-on-accelerated-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/yuv-video-on-accelerated-canvas-expected.png
new file mode 100644
index 0000000..f0411d4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/yuv-video-on-accelerated-canvas-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/clip/overflow-border-radius-composited-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/clip/overflow-border-radius-composited-expected.png
index fb12501b..178c76c 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/clip/overflow-border-radius-composited-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/clip/overflow-border-radius-composited-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/clip/overflow-border-radius-composited-parent-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/clip/overflow-border-radius-composited-parent-expected.png
index 77ee9f3d..34d1fcf 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/clip/overflow-border-radius-composited-parent-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/clip/overflow-border-radius-composited-parent-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
index 3c90c3f..2fa1145c 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/button-default-title-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/button-default-title-expected.png
index dba06e5..641bf6a1 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/button-default-title-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/button-default-title-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/huge-mac-input-clamped-width-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/huge-mac-input-clamped-width-expected.png
deleted file mode 100644
index ab190136..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/huge-mac-input-clamped-width-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/text/input-appearance-selection-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/text/input-appearance-selection-expected.png
index 87b158a..8868061 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/text/input-appearance-selection-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/text/input-appearance-selection-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/text/input-table-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/text/input-table-expected.png
index b65c1ee..34bd499803 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/text/input-table-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/text/input-table-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/frames/iframe-scrolling-attribute-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/frames/iframe-scrolling-attribute-expected.png
index 0fd08c9..9861b1f 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/frames/iframe-scrolling-attribute-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/frames/iframe-scrolling-attribute-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/gradients/css3-color-stop-units-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/gradients/css3-color-stop-units-expected.png
index d53ba47..904e2f20 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/gradients/css3-color-stop-units-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/gradients/css3-color-stop-units-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/scrollbar-appearance-increase-device-scale-factor-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/scrollbar-appearance-increase-device-scale-factor-expected.png
index 68b79b06..ed91b7c 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/scrollbar-appearance-increase-device-scale-factor-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/scrollbar-appearance-increase-device-scale-factor-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/inline/inline-borders-with-bidi-override-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/inline/inline-borders-with-bidi-override-expected.png
index 4abc6cc5..0660b531 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/inline/inline-borders-with-bidi-override-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/inline/inline-borders-with-bidi-override-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/lists/olstart-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/lists/olstart-expected.png
index ab03c8b3..b7d6af0 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/lists/olstart-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/lists/olstart-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/media/mq-color-gamut-picture-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/media/mq-color-gamut-picture-expected.png
deleted file mode 100644
index 32968d8..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/media/mq-color-gamut-picture-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/overflow/006-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/overflow/006-expected.png
index 6edcdb9..1e6159b8 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/overflow/006-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/overflow/006-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/replaced/inline-box-wrapper-handover-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/replaced/inline-box-wrapper-handover-expected.png
deleted file mode 100644
index 773892b..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/replaced/inline-box-wrapper-handover-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/replaced/inline-box-wrapper-handover-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/replaced/inline-box-wrapper-handover-expected.txt
deleted file mode 100644
index 6ebc333..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/replaced/inline-box-wrapper-handover-expected.txt
+++ /dev/null
@@ -1,49 +0,0 @@
-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 {P} at (0,0) size 784x40
-        LayoutText {#text} at (0,0) size 253x19
-          text run at (0,0) width 253: "This test checks for a regression against "
-        LayoutInline {I} at (0,0) size 743x39
-          LayoutInline {A} at (0,0) size 348x19 [color=#0000EE]
-            LayoutText {#text} at (253,0) size 348x19
-              text run at (253,0) width 348: "http://bugzilla.opendarwin.org/show_bug.cgi?id=6276"
-          LayoutText {#text} at (600,0) size 743x39
-            text run at (600,0) width 5: " "
-            text run at (604,0) width 139: "Image thumbnails are"
-            text run at (0,20) width 194: "misplaced on forum.2ostrov.ru"
-        LayoutText {#text} at (193,20) size 5x19
-          text run at (193,20) width 5: "."
-      LayoutBlockFlow {HR} at (0,56) size 784x2 [border: (1px inset #EEEEEE)]
-      LayoutBlockFlow {P} at (0,74) size 784x20
-        LayoutText {#text} at (0,0) size 232x19
-          text run at (0,0) width 232: "Box 1 and box 2 should be identical."
-      LayoutBlockFlow (anonymous) at (0,110) size 784x20
-        LayoutText {#text} at (0,0) size 43x19
-          text run at (0,0) width 43: "Box 1:"
-      LayoutBlockFlow {DIV} at (0,130) size 67x82 [border: (1px solid #000000)]
-        LayoutBlockFlow {DIV} at (6,6) size 40x20 [bgcolor=#0000FF]
-        LayoutText {#text} at (6,31) size 16x19
-          text run at (6,31) width 16: "A "
-        LayoutBlockFlow {DIV} at (22,26) size 35x20 [bgcolor=#FF0000]
-        LayoutText {#text} at (6,56) size 15x19
-          text run at (6,56) width 15: "B "
-        LayoutBlockFlow {DIV} at (21,51) size 20x20 [bgcolor=#008000]
-        LayoutText {#text} at (41,56) size 15x19
-          text run at (41,56) width 15: " C"
-      LayoutBlockFlow (anonymous) at (0,212) size 784x40
-        LayoutBR {BR} at (0,0) size 0x19
-        LayoutText {#text} at (0,20) size 43x19
-          text run at (0,20) width 43: "Box 2:"
-      LayoutBlockFlow {DIV} at (0,252) size 67x82 [border: (1px solid #000000)]
-        LayoutBlockFlow {DIV} at (6,6) size 40x20 [bgcolor=#0000FF]
-        LayoutText {#text} at (6,31) size 16x19
-          text run at (6,31) width 16: "A "
-        LayoutBlockFlow {DIV} at (22,26) size 35x20 [bgcolor=#FF0000]
-        LayoutText {#text} at (6,56) size 15x19
-          text run at (6,56) width 15: "B "
-        LayoutBlockFlow {DIV} at (21,51) size 20x20 [bgcolor=#008000]
-        LayoutText {#text} at (41,56) size 15x19
-          text run at (41,56) width 15: " C"
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png
index 6522f71..7bcef702 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/023-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/023-expected.png
index a007f79..1030ac3 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/023-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/023-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/040-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/040-expected.png
index 0ff5526..4b9c6716 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/040-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/040-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-cell-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-cell-expected.png
index a6ef896..84513c6 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-cell-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-cell-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-column-collapsed-border-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-column-collapsed-border-expected.png
index 6034610..4bd727e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-column-collapsed-border-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-column-collapsed-border-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-column-group-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-column-group-expected.png
index 05883dc..010ec78 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-column-group-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-column-group-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-expected.png
index 66c969a4..29c64ac15 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-row-collapsed-border-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-row-collapsed-border-expected.png
index 3cb3102..707b7f0 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-row-collapsed-border-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-row-collapsed-border-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-row-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-row-expected.png
index 8aa6930..535f451 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-row-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-row-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_layers-hide-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_layers-hide-expected.png
index 449a74d..4f8ea7b4 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_layers-hide-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_layers-hide-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_layers-show-collapsed-border-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_layers-show-collapsed-border-expected.png
index 59728f5..690b06a 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_layers-show-collapsed-border-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_layers-show-collapsed-border-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_layers-show-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_layers-show-expected.png
index 6fd0aba..718169d 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_layers-show-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_layers-show-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_position-table-column-group-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_position-table-column-group-expected.png
index 8c39206..0bc70bc 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_position-table-column-group-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_position-table-column-group-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_position-table-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_position-table-expected.png
index 4008f02..e18d8ac6 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_position-table-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_position-table-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_position-table-row-collapsed-border-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_position-table-row-collapsed-border-expected.png
index 0e3a429..93165f4 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_position-table-row-collapsed-border-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_position-table-row-collapsed-border-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_position-table-row-group-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_position-table-row-group-expected.png
index 61e56fc..97293ab7 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_position-table-row-group-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_position-table-row-group-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_simple-table-cell-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_simple-table-cell-expected.png
index 4996351..6d2f3e12 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_simple-table-cell-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_simple-table-cell-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_simple-table-column-collapsed-border-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_simple-table-column-collapsed-border-expected.png
index 2c9ea75e..78bdac9 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_simple-table-column-collapsed-border-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_simple-table-column-collapsed-border-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_simple-table-column-group-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_simple-table-column-group-expected.png
index 43c8a66..aaeb391 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_simple-table-column-group-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_simple-table-column-group-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_simple-table-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_simple-table-expected.png
index d6976ec7..6f613657 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_simple-table-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_simple-table-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_simple-table-row-collapsed-border-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_simple-table-row-collapsed-border-expected.png
index bd65d9e7c..ca82511 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_simple-table-row-collapsed-border-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_simple-table-row-collapsed-border-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/empty-cells-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/empty-cells-expected.png
index 9af691d..8d98f0a 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/empty-cells-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/empty-cells-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/text/font-stretch-variant-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/text/font-stretch-variant-expected.png
index 1118fa4f..d44170f4 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/text/font-stretch-variant-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/text/font-stretch-variant-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/vertical-text-glyph-test-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/vertical-text-glyph-test-expected.png
index bfbf484..1b71028 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/vertical-text-glyph-test-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/vertical-text-glyph-test-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/webgl/pixelated-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/webgl/pixelated-expected.png
deleted file mode 100644
index 4c356a19..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/webgl/pixelated-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/webgl/webgl-composite-modes-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/webgl/webgl-composite-modes-expected.png
deleted file mode 100644
index 22c1698..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/webgl/webgl-composite-modes-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/webgl/webgl-composite-modes-repaint-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/webgl/webgl-composite-modes-repaint-expected.png
deleted file mode 100644
index 1ead635..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/webgl/webgl-composite-modes-repaint-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/webgl/webgl-composite-modes-tabswitching-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/webgl/webgl-composite-modes-tabswitching-expected.png
deleted file mode 100644
index 329a790..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/webgl/webgl-composite-modes-tabswitching-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/writing-mode/border-radius-clipping-vertical-lr-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/writing-mode/border-radius-clipping-vertical-lr-expected.png
index 670713d..f1037c1 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/writing-mode/border-radius-clipping-vertical-lr-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/writing-mode/border-radius-clipping-vertical-lr-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/hdr/color-jpeg-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/linux/hdr/color-jpeg-with-color-profile-expected.png
deleted file mode 100644
index dc798e6..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/hdr/color-jpeg-with-color-profile-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/hdr/color-profile-video-expected.png b/third_party/WebKit/LayoutTests/platform/linux/hdr/color-profile-video-expected.png
deleted file mode 100644
index 85f7439..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/hdr/color-profile-video-expected.png
+++ /dev/null
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 1d92b9de..f4230b7 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/media/video-buffered-range-contains-currentTime-expected.png b/third_party/WebKit/LayoutTests/platform/linux/http/tests/media/video-buffered-range-contains-currentTime-expected.png
index ca0e28f..6558104 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/http/tests/media/video-buffered-range-contains-currentTime-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/http/tests/media/video-buffered-range-contains-currentTime-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/http/tests/media/video-buffered-range-contains-currentTime-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/http/tests/media/video-buffered-range-contains-currentTime-expected.txt
deleted file mode 100644
index b202525..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/http/tests/media/video-buffered-range-contains-currentTime-expected.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x171
-  LayoutBlockFlow {HTML} at (0,0) size 800x171
-    LayoutBlockFlow {BODY} at (8,8) size 784x155
-      LayoutText {#text} at (0,0) size 0x0
-layer at (8,8) size 300x150
-  LayoutVideo {VIDEO} at (0,0) size 300x150
-layer at (8,8) size 300x150
-  LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 300x150
-    LayoutBlockFlow {DIV} at (0,118) size 300x32
-layer at (8,8) size 300x108
-  LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 300x108
-layer at (8,126) size 300x32 scrollHeight 40
-  LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 300x32 [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:07"
-    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:07"
-    LayoutSlider {INPUT} at (108,15) size 49x2
-      LayoutFlexibleBox {DIV} at (0,0) size 49x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 85x48
-          LayoutBlockFlow {DIV} at (49,0) size 36x48
-    LayoutButton {INPUT} at (175,0) size 32x32
-    LayoutSlider {INPUT} at (225,15) size 25x2
-      LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
-    LayoutButton {INPUT} at (268,0) size 32x32
diff --git a/third_party/WebKit/LayoutTests/platform/linux/http/tests/misc/object-embedding-svg-delayed-size-negotiation-expected.png b/third_party/WebKit/LayoutTests/platform/linux/http/tests/misc/object-embedding-svg-delayed-size-negotiation-expected.png
deleted file mode 100644
index 52b7c89..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/http/tests/misc/object-embedding-svg-delayed-size-negotiation-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-layer-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-layer-expected.png
deleted file mode 100644
index 966445d7..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-layer-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/rendering-broken-0px-images-quirk-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/rendering-broken-0px-images-quirk-expected.png
index 4814771d..9e28c435 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/images/rendering-broken-0px-images-quirk-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/rendering-broken-0px-images-quirk-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/rendering-broken-block-flow-images-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/rendering-broken-block-flow-images-expected.png
index b8622059..3cf5565 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/images/rendering-broken-block-flow-images-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/rendering-broken-block-flow-images-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/color-profile-video-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/color-profile-video-expected.png
deleted file mode 100644
index 132ad68c..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/media/color-profile-video-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/color-profile-video-seek-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/color-profile-video-seek-expected.png
deleted file mode 100644
index 5b24f3e..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/media/color-profile-video-seek-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/color-profile-video-seek-filter-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/color-profile-video-seek-filter-expected.png
deleted file mode 100644
index 2b5e0b3..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/media/color-profile-video-seek-filter-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/color-profile-video-seek-object-fit-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/color-profile-video-seek-object-fit-expected.png
deleted file mode 100644
index c4a1a2f..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/media/color-profile-video-seek-object-fit-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png
index c0d1ed9..b855e4b0 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/controls/paint-controls-webkit-appearance-none-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/controls/paint-controls-webkit-appearance-none-expected.png
index a7d8a8d2..8e5f7434 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/controls/paint-controls-webkit-appearance-none-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/controls/paint-controls-webkit-appearance-none-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 6f1b9b4..ba4b97c 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-controls-with-cast-rendering-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/media/controls/video-controls-with-cast-rendering-expected.txt
index 57e32b07..02d33b2 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/controls/video-controls-with-cast-rendering-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/controls/video-controls-with-cast-rendering-expected.txt
@@ -29,16 +29,32 @@
           text run at (0,8) width 24: "0:00"
     LayoutSlider {INPUT} at (74,15) size 71x2
       LayoutFlexibleBox {DIV} at (0,0) size 71x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 107x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
     LayoutButton {INPUT} at (163,0) size 32x32
     LayoutSlider {INPUT} at (213,15) size 25x2
       LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
     LayoutButton {INPUT} at (288,0) size 32x32
 layer at (264,260) size 32x32
   LayoutButton {INPUT} at (256,0) size 32x32
+layer at (64,276) size 107x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 107x0
+layer at (82,275) size 71x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 71x2 [bgcolor=#DADADA]
+layer at (203,276) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+layer at (221,275) size 25x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (82,275) size 71x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 71x2 [bgcolor=#5A5A5A]
+layer at (82,275) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (221,275) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (221,275) size 25x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (64,252) size 36x48 backgroundClip at (8,260) size 320x32 clip at (8,260) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
+layer at (228,252) size 36x48 backgroundClip at (8,260) size 320x32 clip at (8,260) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
 layer at (8,297) size 320x240
   LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 320x240
     LayoutBlockFlow {DIV} at (0,208) size 320x32
@@ -53,16 +69,32 @@
           text run at (0,8) width 24: "0:00"
     LayoutSlider {INPUT} at (74,15) size 71x2
       LayoutFlexibleBox {DIV} at (0,0) size 71x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 107x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
     LayoutButton {INPUT} at (163,0) size 32x32
     LayoutSlider {INPUT} at (213,15) size 25x2
       LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
     LayoutButton {INPUT} at (288,0) size 32x32
 layer at (264,505) size 32x32
   LayoutButton {INPUT} at (256,0) size 32x32
+layer at (64,521) size 107x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 107x0
+layer at (82,520) size 71x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 71x2 [bgcolor=#DADADA]
+layer at (203,521) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+layer at (221,520) size 25x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (82,520) size 71x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 71x2 [bgcolor=#5A5A5A]
+layer at (82,520) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (221,520) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (221,520) size 25x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (64,497) size 36x48 backgroundClip at (8,505) size 320x32 clip at (8,505) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
+layer at (228,497) size 36x48 backgroundClip at (8,505) size 320x32 clip at (8,505) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
 layer at (8,542) size 320x240 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
   LayoutVideo (positioned) {VIDEO} at (8,542) size 320x240
 layer at (8,542) size 320x240 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
@@ -79,13 +111,29 @@
           text run at (0,8) width 24: "0:00"
     LayoutSlider {INPUT} at (74,15) size 71x2
       LayoutFlexibleBox {DIV} at (0,0) size 71x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 107x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
     LayoutButton {INPUT} at (163,0) size 32x32
     LayoutSlider {INPUT} at (213,15) size 25x2
       LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
     LayoutButton {INPUT} at (288,0) size 32x32
 layer at (264,750) size 32x32 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
   LayoutButton {INPUT} at (256,0) size 32x32
+layer at (64,766) size 107x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 107x0
+layer at (82,765) size 71x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 71x2 [bgcolor=#DADADA]
+layer at (203,766) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+layer at (221,765) size 25x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (82,765) size 71x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 71x2 [bgcolor=#5A5A5A]
+layer at (82,765) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (221,765) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (221,765) size 25x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (64,742) size 36x48 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
+layer at (228,742) size 36x48 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
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 21c7372e..6881c87 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/controls/video-overlay-cast-light-rendering-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/controls/video-overlay-cast-light-rendering-expected.png
index f0f58639..6f50ab8 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/controls/video-overlay-cast-light-rendering-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/controls/video-overlay-cast-light-rendering-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/media-document-audio-repaint-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/media-document-audio-repaint-expected.png
index fe0d905f..f6b4218e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/media-document-audio-repaint-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/media-document-audio-repaint-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/media-document-audio-repaint-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/media/media-document-audio-repaint-expected.txt
index 583daaa3..8307ff0 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/media-document-audio-repaint-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/media-document-audio-repaint-expected.txt
@@ -36,10 +36,26 @@
               text run at (0,8) width 30: "/ 0:01"
         LayoutSlider {INPUT} at (108,15) size 81x2
           LayoutFlexibleBox {DIV} at (0,0) size 81x2
-            LayoutBlockFlow {DIV} at (-18,-23) size 117x48
-              LayoutBlockFlow {DIV} at (40.48,0) size 36x48
         LayoutButton {INPUT} at (207,0) size 32x32
         LayoutSlider {INPUT} at (257,15) size 25x2
           LayoutFlexibleBox {DIV} at (0,0) size 25x2
-            LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-              LayoutBlockFlow {DIV} at (25,0) size 36x48
+    layer at (130,150) size 117x0
+      LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 117x0
+    layer at (148,149) size 81x2
+      LayoutBlockFlow (positioned) {DIV} at (18,-1) size 81x2 [bgcolor=#DADADA]
+    layer at (279,150) size 61x0
+      LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+    layer at (297,149) size 25x2
+      LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+    layer at (188,149) size 40x2
+      LayoutBlockFlow (positioned) zI: 1 {DIV} at (40,0) size 40x2 [bgcolor=#5A5A5A]
+    layer at (148,149) size 40x2
+      LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 40x2 [bgcolor=#4285F4]
+    layer at (297,149) size 0x2
+      LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+    layer at (297,149) size 25x2
+      LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+    layer at (170,126) size 36x48 backgroundClip at (40,134) size 300x32 clip at (40,134) size 300x32
+      LayoutBlockFlow (positioned) zI: 2 {DIV} at (40.48,-24) size 36x48
+    layer at (304,126) size 36x48 backgroundClip at (40,134) size 300x32 clip at (40,134) size 300x32
+      LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
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 7008413b..3df7c7c 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 1511e75e8..6c505bc 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 8524387..3cf5d65 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 6af9546..15149966 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-canvas-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/media/video-canvas-expected.txt
new file mode 100644
index 0000000..1540aa9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-canvas-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL Test "video" as a source for "canvas". assert_equals: expected 9 but got 8
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-colorspace-yuv420-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-colorspace-yuv420-expected.png
index ee15730..910ad86 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/video-colorspace-yuv420-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-colorspace-yuv420-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-colorspace-yuv422-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-colorspace-yuv422-expected.png
index e3dd67f4..da7b082 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/video-colorspace-yuv422-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-colorspace-yuv422-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 9381506..74ec71a 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-remove-insert-repaints-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-remove-insert-repaints-expected.png
deleted file mode 100644
index 47efc6a..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/media/video-remove-insert-repaints-expected.png
+++ /dev/null
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 f3cbb0b..06015ec 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 0f92355..4cd0d6a 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 d2673f5..a8f4e32 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 ae5b2dc..484c5b1 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/overflow/overflow-transform-perspective-expected.png b/third_party/WebKit/LayoutTests/platform/linux/overflow/overflow-transform-perspective-expected.png
index 9b31940b..799fdd2fb 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/overflow/overflow-transform-perspective-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/overflow/overflow-transform-perspective-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/compositing/new-stacking-context-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/compositing/new-stacking-context-expected.png
deleted file mode 100644
index dc85ee8..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/compositing/new-stacking-context-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/document-flipped-blocks-writing-mode-scroll-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/document-flipped-blocks-writing-mode-scroll-expected.png
deleted file mode 100644
index 068ca5d..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/document-flipped-blocks-writing-mode-scroll-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/inline-style-change-in-scrolled-view-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/inline-style-change-in-scrolled-view-expected.png
index c48d3b52..14644fad 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/inline-style-change-in-scrolled-view-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/inline-style-change-in-scrolled-view-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
index efe5660..4877c9a 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
@@ -49,10 +49,6 @@
       "reason": "subtree"
     },
     {
-      "object": "HorizontalScrollbar",
-      "reason": "scroll control"
-    },
-    {
       "object": "Caret",
       "reason": "caret"
     },
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/invalidate-caret-in-non-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/invalidate-caret-in-non-composited-scrolling-container-expected.txt
index efe5660..4877c9a 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/invalidate-caret-in-non-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/invalidate-caret-in-non-composited-scrolling-container-expected.txt
@@ -49,10 +49,6 @@
       "reason": "subtree"
     },
     {
-      "object": "HorizontalScrollbar",
-      "reason": "scroll control"
-    },
-    {
       "object": "Caret",
       "reason": "caret"
     },
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/overflow-move-after-scroll-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/overflow-move-after-scroll-expected.png
index ffb212d..4c8528e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/overflow-move-after-scroll-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/overflow-move-after-scroll-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/overflow-scroll-body-appear-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/overflow-scroll-body-appear-expected.png
index a55b4c5..ad3f31c 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/overflow-scroll-body-appear-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/overflow-scroll-body-appear-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
index ec9d881..c29ac216 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
@@ -46,10 +46,6 @@
       "reason": "subtree"
     },
     {
-      "object": "HorizontalScrollbar",
-      "reason": "scroll control"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "subtree"
     },
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
index ec9d881..c29ac216 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
@@ -46,10 +46,6 @@
       "reason": "subtree"
     },
     {
-      "object": "HorizontalScrollbar",
-      "reason": "scroll control"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "subtree"
     },
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/single-line-cells-repeating-thead-break-inside-on-thead-only-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/single-line-cells-repeating-thead-break-inside-on-thead-only-expected.png
index bfcc558..c59fdf3 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/single-line-cells-repeating-thead-break-inside-on-thead-only-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/single-line-cells-repeating-thead-break-inside-on-thead-only-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/repaint-in-scrolled-view-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/repaint-in-scrolled-view-expected.png
deleted file mode 100644
index 3e6b0b62..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/repaint-in-scrolled-view-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
index b547e78..cf11911 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/text-xy-updates-SVGList-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/text-xy-updates-SVGList-expected.png
index 991085e..3b126dbb 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/text-xy-updates-SVGList-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/text-xy-updates-SVGList-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/table/composited-table-background-col-span-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/table/composited-table-background-col-span-expected.png
index 7b758b0..dab4196 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/table/composited-table-background-col-span-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/table/composited-table-background-col-span-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/table/composited-table-background-col-span-initial-empty-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/table/composited-table-background-col-span-initial-empty-expected.png
index 7b758b0..dab4196 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/table/composited-table-background-col-span-initial-empty-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/table/composited-table-background-col-span-initial-empty-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/table/composited-table-background-section-composited-row-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/table/composited-table-background-section-composited-row-expected.png
index 37ed9c13..cfbd431 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/table/composited-table-background-section-composited-row-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/table/composited-table-background-section-composited-row-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/table/composited-table-background-section-composited-row-initial-empty-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/table/composited-table-background-section-composited-row-initial-empty-expected.png
index 37ed9c13..cfbd431 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/table/composited-table-background-section-composited-row-initial-empty-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/table/composited-table-background-section-composited-row-initial-empty-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/printing/return-from-printing-mode-expected.png b/third_party/WebKit/LayoutTests/platform/linux/printing/return-from-printing-mode-expected.png
index 773e4cf..a634b4002 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/printing/return-from-printing-mode-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/printing/return-from-printing-mode-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/bug45331-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/bug45331-expected.png
index f222469d..f6241b28 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/bug45331-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/bug45331-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/object-sizing-no-width-height-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/object-sizing-no-width-height-expected.png
deleted file mode 100644
index 52b7c89..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/object-sizing-no-width-height-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-objectBoundingBox-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-objectBoundingBox-expected.png
deleted file mode 100644
index bf174b54..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-objectBoundingBox-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-userSpaceOnUse-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-userSpaceOnUse-expected.png
deleted file mode 100644
index 65d6380..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-userSpaceOnUse-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/filters/feImage-filterUnits-userSpaceOnUse-primitiveUnits-objectBoundingBox-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/filters/feImage-filterUnits-userSpaceOnUse-primitiveUnits-objectBoundingBox-expected.png
deleted file mode 100644
index bf174b54..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/filters/feImage-filterUnits-userSpaceOnUse-primitiveUnits-objectBoundingBox-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/filters/feImage-filterUnits-userSpaceOnUse-primitiveUnits-userSpaceOnUse-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/filters/feImage-filterUnits-userSpaceOnUse-primitiveUnits-userSpaceOnUse-expected.png
deleted file mode 100644
index 65d6380..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/filters/feImage-filterUnits-userSpaceOnUse-primitiveUnits-userSpaceOnUse-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/overflow/overflow-on-outermost-svg-element-defaults-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/overflow/overflow-on-outermost-svg-element-defaults-expected.png
deleted file mode 100644
index 5c73f57..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/overflow/overflow-on-outermost-svg-element-defaults-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/overflow/overflow-on-outermost-svg-element-ignore-attribute-2-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/overflow/overflow-on-outermost-svg-element-ignore-attribute-2-expected.png
deleted file mode 100644
index 5c73f57..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/overflow/overflow-on-outermost-svg-element-ignore-attribute-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/overflow/overflow-on-outermost-svg-element-ignore-attribute-3-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/overflow/overflow-on-outermost-svg-element-ignore-attribute-3-expected.png
deleted file mode 100644
index 5c73f57..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/overflow/overflow-on-outermost-svg-element-ignore-attribute-3-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/overflow/overflow-on-outermost-svg-element-in-xhtml-defaults-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/overflow/overflow-on-outermost-svg-element-in-xhtml-defaults-expected.png
deleted file mode 100644
index 0c0220f..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/overflow/overflow-on-outermost-svg-element-in-xhtml-defaults-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/transformed-text-fill-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/transformed-text-fill-pattern-expected.png
deleted file mode 100644
index edafde3..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/transformed-text-fill-pattern-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/wicd/test-scalable-background-image1-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/wicd/test-scalable-background-image1-expected.png
index 91d8f01..d4feca9 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/wicd/test-scalable-background-image1-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/wicd/test-scalable-background-image1-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/absolute-sized-document-scrollbars-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/absolute-sized-document-scrollbars-expected.png
deleted file mode 100644
index 7d88073..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/absolute-sized-document-scrollbars-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-mask-with-percentages-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-mask-with-percentages-expected.png
index eb576f0..3a82b908 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-mask-with-percentages-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-mask-with-percentages-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-float-border-padding-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-float-border-padding-expected.png
index 935371c2..543d529e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-float-border-padding-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-float-border-padding-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/text/zoom-svg-float-border-padding-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/text/zoom-svg-float-border-padding-expected.png
index 3b3895a0..bd55409 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/text/zoom-svg-float-border-padding-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/text/zoom-svg-float-border-padding-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug11944-expected.png b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug11944-expected.png
index 06cf6c4..ae671af 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug11944-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug11944-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug137388-2-expected.png b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug137388-2-expected.png
index 01c17c7..782abb8d3 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug137388-2-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug137388-2-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug22019-expected.png b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug22019-expected.png
index 88634f44..5107ea7 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug22019-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug22019-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug2479-3-expected.png b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug2479-3-expected.png
index aecdbbd..4b028b4 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug2479-3-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug2479-3-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug46480-1-expected.png b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug46480-1-expected.png
index 7654882..8bdc814 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug46480-1-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug46480-1-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug50695-1-expected.png b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug50695-1-expected.png
index 0bd343b..852d61c 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug50695-1-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug50695-1-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/core/bloomberg-expected.png b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/core/bloomberg-expected.png
index c33a7dd..17eaac7 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/core/bloomberg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/core/bloomberg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/other/nestedTables-expected.png b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/other/nestedTables-expected.png
index cec8542..ec9435e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/other/nestedTables-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/other/nestedTables-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/bugs/bug10216-expected.png b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/bugs/bug10216-expected.png
index 4e48cfd2..48d0d28 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/bugs/bug10216-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/bugs/bug10216-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
index d6babf1..3bbbf80 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/marvin/table_overflow_dirty_reflow_tbody-expected.png b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/marvin/table_overflow_dirty_reflow_tbody-expected.png
index f6ba996..90e75f8 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/marvin/table_overflow_dirty_reflow_tbody-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/marvin/table_overflow_dirty_reflow_tbody-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/marvin/table_overflow_style_reflow_tbody_sibling-expected.png b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/marvin/table_overflow_style_reflow_tbody_sibling-expected.png
index d0e01fa..ffec628 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/marvin/table_overflow_style_reflow_tbody_sibling-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/marvin/table_overflow_style_reflow_tbody_sibling-expected.png
Binary files differ
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 dbef225..e2d31db 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/3d/general/cssmatrix-3d-zoom-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/general/cssmatrix-3d-zoom-expected.png
deleted file mode 100644
index ba6d122..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/general/cssmatrix-3d-zoom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/general/perspective-units-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/general/perspective-units-expected.png
index ee8ae7a9..f616e7d 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/general/perspective-units-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/general/perspective-units-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/general/transform-origin-z-change-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/general/transform-origin-z-change-expected.png
deleted file mode 100644
index d761571..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/general/transform-origin-z-change-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-2-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-2-expected.png
index 204fb52..a72f9457 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-2-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-2-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-3-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-3-expected.png
index 728737e..1387a47 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-3-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-3-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png
index d951566..25b2ffa 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
index d30d202..4043e9f 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-expected.png
index dc77e554..af5c408 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
index 277e6100f..bbe385a 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-overlapping-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-overlapping-expected.png
index f7653ee..e745925 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-overlapping-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-overlapping-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
index 63ab0ef..df0605e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transitions/opacity-transform-transitions-inside-iframe-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transitions/opacity-transform-transitions-inside-iframe-expected.png
deleted file mode 100644
index 65d5a58..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/transitions/opacity-transform-transitions-inside-iframe-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transitions/opacity-transition-zindex-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transitions/opacity-transition-zindex-expected.png
deleted file mode 100644
index 43c5d9c..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/transitions/opacity-transition-zindex-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/compositor-touch-hit-rects-fullscreen-video-controls-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/compositor-touch-hit-rects-fullscreen-video-controls-expected.txt
index e541818..74218e8f 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/compositor-touch-hit-rects-fullscreen-video-controls-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/compositor-touch-hit-rects-fullscreen-video-controls-expected.txt
@@ -5,7 +5,7 @@
 
 EVENT(webkitfullscreenchange)
 Should report another rect which is not on the document
-handler: DIV (56, -8, 712, 48)
+handler: no rects
 
 END OF TEST
 
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 abfb363..829b8c45 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 abfb363..829b8c45 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 abfb363..829b8c45 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/display_list_2d_canvas/fast/canvas/canvas-composite-video-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-expected.png
index 55b60e3..a39e5ac 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-shadow-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-shadow-expected.png
index ebe81ec..ee72053 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-shadow-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-shadow-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-drawImage-video-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-drawImage-video-expected.png
new file mode 100644
index 0000000..a58254b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-drawImage-video-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-pattern-video-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-pattern-video-expected.png
index f31bb59..71553edf 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-pattern-video-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-pattern-video-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/webgl/pixelated-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/webgl/pixelated-expected.png
deleted file mode 100644
index 4c356a19..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/webgl/pixelated-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/webgl/webgl-composite-modes-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/webgl/webgl-composite-modes-expected.png
deleted file mode 100644
index 22c1698..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/webgl/webgl-composite-modes-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/webgl/webgl-composite-modes-repaint-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/webgl/webgl-composite-modes-repaint-expected.png
deleted file mode 100644
index 1ead635..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/webgl/webgl-composite-modes-repaint-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/webgl/webgl-composite-modes-tabswitching-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/webgl/webgl-composite-modes-tabswitching-expected.png
deleted file mode 100644
index 329a790..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/webgl/webgl-composite-modes-tabswitching-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/yuv-video-on-accelerated-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/yuv-video-on-accelerated-canvas-expected.png
new file mode 100644
index 0000000..f0411d4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/yuv-video-on-accelerated-canvas-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/12-55-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/12-55-expected.png
index 72c2990..36618e9 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/12-55-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/12-55-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/182-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/182-expected.png
index ebb07cef..87fc45e7 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/182-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/182-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/2-comp-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/2-comp-expected.png
deleted file mode 100644
index 02dde9f..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/2-comp-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/2-dht-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/2-dht-expected.png
index 1cd57312..db69097b 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/2-dht-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/2-dht-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/23-55-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/23-55-expected.png
index 178e3905..0bba402 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/23-55-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/23-55-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/55-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/55-expected.png
index 66273619..3ef5d582 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/55-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/55-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/cHRM_color_spin-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/cHRM_color_spin-expected.png
deleted file mode 100644
index 4c304cbc..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/cHRM_color_spin-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-jpeg-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-jpeg-with-color-profile-expected.png
deleted file mode 100644
index c10cd0b..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-jpeg-with-color-profile-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-animate-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-animate-expected.png
deleted file mode 100644
index 874c69a..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-animate-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-animate-rotate-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-animate-rotate-expected.png
deleted file mode 100644
index 9623b7a..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-animate-rotate-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-background-clip-text-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-background-clip-text-expected.png
deleted file mode 100644
index 8ec4a0d..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-background-clip-text-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-background-image-cover-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-background-image-cover-expected.png
deleted file mode 100644
index dc931ce..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-background-image-cover-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-background-image-cross-fade-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-background-image-cross-fade-expected.png
deleted file mode 100644
index 2a47876..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-background-image-cross-fade-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-background-image-cross-fade-png-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-background-image-cross-fade-png-expected.png
deleted file mode 100644
index 2a47876..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-background-image-cross-fade-png-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-background-image-repeat-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-background-image-repeat-expected.png
deleted file mode 100644
index 6de6b5545..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-background-image-repeat-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png
deleted file mode 100644
index 9e5603dc..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-border-fade-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-border-fade-expected.png
deleted file mode 100644
index 2202536..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-border-fade-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-border-image-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-border-image-expected.png
deleted file mode 100644
index e27948c..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-border-image-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-border-image-source-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-border-image-source-expected.png
deleted file mode 100644
index 51f8501..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-border-image-source-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-border-radius-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-border-radius-expected.png
deleted file mode 100644
index ef3128d..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-border-radius-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-clip-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-clip-expected.png
deleted file mode 100644
index b208b128..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-clip-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-filter-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-filter-expected.png
deleted file mode 100644
index 695d466..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-filter-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-group-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-group-expected.png
deleted file mode 100644
index f32fb4b..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-group-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-iframe-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-iframe-expected.png
deleted file mode 100644
index 3814e41..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-iframe-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-canvas-expected.png
deleted file mode 100644
index ab7bb2da..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-canvas-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-canvas-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-canvas-pattern-expected.png
deleted file mode 100644
index 6e84da6..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-canvas-pattern-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png
deleted file mode 100644
index 4f0b1ca..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-expected.png
deleted file mode 100644
index 7ac8cac..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-filter-all-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-filter-all-expected.png
index 930406a..cbebdf2 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-filter-all-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-filter-all-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-object-fit-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-object-fit-expected.png
deleted file mode 100644
index 56bf0512..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-object-fit-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-profile-match-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-profile-match-expected.png
deleted file mode 100644
index 356bfef07a..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-profile-match-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-pseudo-content-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-pseudo-content-expected.png
deleted file mode 100644
index a931591..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-pseudo-content-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-shape-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-shape-expected.png
index 951b57f..fe02a6b1 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-shape-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-shape-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-svg-resource-url-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-svg-resource-url-expected.png
deleted file mode 100644
index 28870ea..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-svg-resource-url-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-layer-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-layer-expected.png
deleted file mode 100644
index 0cd64e5..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-layer-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-layer-filter-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-layer-filter-expected.png
deleted file mode 100644
index 56c7926..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-layer-filter-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-mask-image-svg-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-mask-image-svg-expected.png
deleted file mode 100644
index a03e7cd..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-mask-image-svg-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png
index c5c3efb7..535922d 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png
index 6f42dc9..4669db6c 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-object-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-object-expected.png
deleted file mode 100644
index 3c32c5a..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-object-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-svg-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-svg-expected.png
deleted file mode 100644
index 9ee60756..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-svg-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png
index 4be12c1..66498a7 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-svg-foreign-object-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-svg-foreign-object-expected.png
deleted file mode 100644
index 1d78a19..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-svg-foreign-object-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/cross-fade-background-size-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/cross-fade-background-size-expected.png
deleted file mode 100644
index 392819d..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/cross-fade-background-size-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/cross-fade-svg-size-diff-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/cross-fade-svg-size-diff-expected.png
index 374cbae..d53d4c6b 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/cross-fade-svg-size-diff-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/cross-fade-svg-size-diff-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/cross-fade-svg-size-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/cross-fade-svg-size-expected.png
index 6b147f2c..7f1965e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/cross-fade-svg-size-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/cross-fade-svg-size-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/exif-orientation-css-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/exif-orientation-css-expected.png
index ed78fd1..17b41b6 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/exif-orientation-css-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/exif-orientation-css-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/exif-orientation-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/exif-orientation-expected.png
index 529f7bb..e74ca10 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/exif-orientation-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/exif-orientation-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/exif-orientation-height-image-document-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/exif-orientation-height-image-document-expected.png
deleted file mode 100644
index 6366d72..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/exif-orientation-height-image-document-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/exif-orientation-image-document-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/exif-orientation-image-document-expected.png
index bdefba6fe..84a95e1 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/exif-orientation-image-document-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/exif-orientation-image-document-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/icon-0colors-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/icon-0colors-expected.png
deleted file mode 100644
index e51659c..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/icon-0colors-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/icon-decoding-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/icon-decoding-expected.png
deleted file mode 100644
index 07ff309..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/icon-decoding-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/image-map-anchor-children-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/image-map-anchor-children-expected.png
index 39f9010e..0232d9ef 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/image-map-anchor-children-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/image-map-anchor-children-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-circle-focus-ring-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-circle-focus-ring-expected.png
index d5a6a16..94279e8 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-circle-focus-ring-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-circle-focus-ring-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-in-positioned-container-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-in-positioned-container-expected.png
index e1b87ee6..9271b93 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-in-positioned-container-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-in-positioned-container-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-not-inherited-from-map-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-not-inherited-from-map-expected.png
index e479ae1..e405907 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-not-inherited-from-map-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-not-inherited-from-map-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-with-paint-root-offset-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-with-paint-root-offset-expected.png
index 3f0744b7..f92650c 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-with-paint-root-offset-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-with-paint-root-offset-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-with-scale-transform-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-with-scale-transform-expected.png
index c11b9d4..f780c29 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-with-scale-transform-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-with-scale-transform-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png
index 5880f18..cf6ce28 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-overflowing-polygon-focus-ring-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-overflowing-polygon-focus-ring-expected.png
index d42a2dbc..2f3eff0 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-overflowing-polygon-focus-ring-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-overflowing-polygon-focus-ring-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-polygon-focus-ring-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-polygon-focus-ring-expected.png
index f3a0d48f..a30781b 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-polygon-focus-ring-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/imagemap-polygon-focus-ring-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/jpeg-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/jpeg-with-color-profile-expected.png
index 64c5248..5b9db4ac9 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/jpeg-with-color-profile-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/jpeg-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/jpeg-yuv-image-decoding-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/jpeg-yuv-image-decoding-expected.png
index 41d34c5f..9322a516 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/jpeg-yuv-image-decoding-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/jpeg-yuv-image-decoding-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/jpeg-yuv-progressive-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/jpeg-yuv-progressive-canvas-expected.png
deleted file mode 100644
index 5eaf3fc..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/jpeg-yuv-progressive-canvas-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/jpeg-yuv-progressive-image-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/jpeg-yuv-progressive-image-expected.png
deleted file mode 100644
index d717325..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/jpeg-yuv-progressive-image-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/motion-jpeg-single-frame-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/motion-jpeg-single-frame-expected.png
deleted file mode 100644
index 5f3feea..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/motion-jpeg-single-frame-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/optimize-contrast-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/optimize-contrast-canvas-expected.png
deleted file mode 100644
index e934c35..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/optimize-contrast-canvas-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/optimize-contrast-image-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/optimize-contrast-image-expected.png
deleted file mode 100644
index c183378..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/optimize-contrast-image-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/paint-subrect-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/paint-subrect-expected.png
deleted file mode 100644
index e7d8dd3..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/paint-subrect-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/paletted-png-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/paletted-png-with-color-profile-expected.png
deleted file mode 100644
index 3789e07..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/paletted-png-with-color-profile-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/pdf-as-background-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/pdf-as-background-expected.png
deleted file mode 100644
index 7abc7f6..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/pdf-as-background-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/pdf-as-tiled-background-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/pdf-as-tiled-background-expected.png
deleted file mode 100644
index 7abc7f6..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/pdf-as-tiled-background-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/pixelated-background-image-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/pixelated-background-image-expected.png
deleted file mode 100644
index 20448ec..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/pixelated-background-image-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/pixelated-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/pixelated-canvas-expected.png
deleted file mode 100644
index f9f84b5..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/pixelated-canvas-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/pixelated-image-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/pixelated-image-expected.png
deleted file mode 100644
index 2764b3a9..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/pixelated-image-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/pixelated-svg-image-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/pixelated-svg-image-expected.png
deleted file mode 100644
index 2764b3a9..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/pixelated-svg-image-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/png-suite/test-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/png-suite/test-expected.png
deleted file mode 100644
index f44fe3b..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/png-suite/test-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/png-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/png-with-color-profile-expected.png
index 64c5248..5b9db4ac9 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/png-with-color-profile-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/png-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/png_per_row_alpha_decoding-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/png_per_row_alpha_decoding-expected.png
deleted file mode 100644
index 2a18e29..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/png_per_row_alpha_decoding-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/rendering-broken-0px-images-quirk-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/rendering-broken-0px-images-quirk-expected.png
index da0be55..6bfe8c2 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/rendering-broken-0px-images-quirk-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/rendering-broken-0px-images-quirk-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/rendering-broken-block-flow-images-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/rendering-broken-block-flow-images-expected.png
index 6d14458a..3fe7b5a 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/rendering-broken-block-flow-images-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/rendering-broken-block-flow-images-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/rgb-jpeg-with-adobe-marker-only-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/rgb-jpeg-with-adobe-marker-only-expected.png
deleted file mode 100644
index f8eb0237..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/rgb-jpeg-with-adobe-marker-only-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/rgb-png-with-cmyk-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/rgb-png-with-cmyk-color-profile-expected.png
deleted file mode 100644
index 2a330d9..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/rgb-png-with-cmyk-color-profile-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/sprite-no-bleed-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/sprite-no-bleed-expected.png
deleted file mode 100644
index 7cf8f27..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/sprite-no-bleed-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/webp-color-profile-lossless-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/webp-color-profile-lossless-expected.png
deleted file mode 100644
index 032e35e..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/webp-color-profile-lossless-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/webp-color-profile-lossy-alpha-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/webp-color-profile-lossy-alpha-expected.png
deleted file mode 100644
index cf8d19f..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/webp-color-profile-lossy-alpha-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/webp-color-profile-lossy-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/webp-color-profile-lossy-expected.png
deleted file mode 100644
index ccbd467..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/webp-color-profile-lossy-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/ycbcr-with-cmyk-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/ycbcr-with-cmyk-color-profile-expected.png
deleted file mode 100644
index 5609d55..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/ycbcr-with-cmyk-color-profile-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/feature-policy-permissions/external/wpt/mediacapture-streams/historical-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/virtual/feature-policy-permissions/external/wpt/mediacapture-streams/historical-expected.txt
new file mode 100644
index 0000000..21f1152
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/feature-policy-permissions/external/wpt/mediacapture-streams/historical-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+FAIL webkitMediaStream interface should not exist assert_false: expected false got true
+FAIL navigator.webkitGetUserMedia should not exist assert_false: expected false got true
+PASS navigator.mozGetUserMedia should not exist
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/12-55-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/12-55-expected.png
index 69c864e..b13a651b 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/12-55-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/12-55-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/182-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/182-expected.png
index 44823062..9712bd9 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/182-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/182-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/2-dht-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/2-dht-expected.png
index 37bd5e1..f2cc835f 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/2-dht-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/2-dht-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/23-55-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/23-55-expected.png
index 0925e715..cf48d29 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/23-55-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/23-55-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/55-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/55-expected.png
index 01b56ff..cc72599 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/55-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/55-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/cHRM_color_spin-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/cHRM_color_spin-expected.png
deleted file mode 100644
index 23ed1e4c..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/cHRM_color_spin-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-jpeg-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-jpeg-with-color-profile-expected.png
deleted file mode 100644
index 1d56780..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-jpeg-with-color-profile-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-animate-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-animate-expected.png
deleted file mode 100644
index d25115f..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-animate-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-animate-rotate-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-animate-rotate-expected.png
deleted file mode 100644
index 8a079e3..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-animate-rotate-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cover-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cover-expected.png
deleted file mode 100644
index 22dbbdf..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cover-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png
deleted file mode 100644
index 29613cd..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png
deleted file mode 100644
index 29613cd..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-repeat-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-repeat-expected.png
deleted file mode 100644
index 17cda7d..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-repeat-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-border-fade-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-border-fade-expected.png
deleted file mode 100644
index 7407960..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-border-fade-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-border-image-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-border-image-expected.png
deleted file mode 100644
index e523275..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-border-image-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-border-image-source-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-border-image-source-expected.png
deleted file mode 100644
index a1f66eb..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-border-image-source-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-border-radius-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-border-radius-expected.png
deleted file mode 100644
index a91be93..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-border-radius-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-clip-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-clip-expected.png
deleted file mode 100644
index e433f51..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-clip-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-filter-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-filter-expected.png
deleted file mode 100644
index 476e395b..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-filter-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-iframe-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-iframe-expected.png
deleted file mode 100644
index 268c768..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-iframe-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-canvas-expected.png
deleted file mode 100644
index c164551..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-canvas-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-canvas-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-canvas-pattern-expected.png
deleted file mode 100644
index 181b748..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-canvas-pattern-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png
deleted file mode 100644
index cbefd899..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-expected.png
deleted file mode 100644
index 669869dd..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png
index 02f1d5f..5953f52 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-object-fit-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-object-fit-expected.png
deleted file mode 100644
index 9398e0a4..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-object-fit-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-profile-match-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-profile-match-expected.png
deleted file mode 100644
index 1cf0831..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-profile-match-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-pseudo-content-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-pseudo-content-expected.png
deleted file mode 100644
index cb38667..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-pseudo-content-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-shape-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-shape-expected.png
index 49b5989..2e9b32ce 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-shape-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-shape-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-svg-resource-url-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-svg-resource-url-expected.png
deleted file mode 100644
index 33cf925..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-svg-resource-url-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
index 5d6ebd9..a0aee0a 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-munsell-srgb-to-srgb-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-munsell-srgb-to-srgb-expected.png
index f82f529..9dd17226 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-munsell-srgb-to-srgb-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-munsell-srgb-to-srgb-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-object-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-object-expected.png
deleted file mode 100644
index c6d91224..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-object-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-svg-foreign-object-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-svg-foreign-object-expected.png
deleted file mode 100644
index 66548d51..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-svg-foreign-object-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png
deleted file mode 100644
index 31ff33d..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/cross-fade-invalidation-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/cross-fade-invalidation-expected.png
deleted file mode 100644
index 03e8eef..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/cross-fade-invalidation-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/cross-fade-overflow-position-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/cross-fade-overflow-position-expected.png
deleted file mode 100644
index e49d2e89..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/cross-fade-overflow-position-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/exif-orientation-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/exif-orientation-expected.png
index 421d50f..cf791fa6 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/exif-orientation-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/exif-orientation-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/exif-orientation-height-image-document-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/exif-orientation-height-image-document-expected.png
deleted file mode 100644
index e2fc9cae..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/exif-orientation-height-image-document-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/exif-orientation-image-document-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/exif-orientation-image-document-expected.png
index 9b89d38..181028f7 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/exif-orientation-image-document-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/exif-orientation-image-document-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/gray-scale-jpeg-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/gray-scale-jpeg-with-color-profile-expected.png
deleted file mode 100644
index 8caaa7bd..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/gray-scale-jpeg-with-color-profile-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-circle-focus-ring-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-circle-focus-ring-expected.png
index 9947e82..d4f7e79 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-circle-focus-ring-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-circle-focus-ring-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-expected.png
index 120c622..0f4ff2a6 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-in-positioned-container-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-in-positioned-container-expected.png
index 17b62cf9..2eeb5d0 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-in-positioned-container-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-in-positioned-container-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-expected.png
index 54b9fca..cca3649 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map-expected.png
index 2ebf6b2..5e6d6ac 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-not-inherited-from-map-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-not-inherited-from-map-expected.png
index 1751c4b..7e3d20d 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-not-inherited-from-map-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-not-inherited-from-map-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-with-paint-root-offset-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-with-paint-root-offset-expected.png
index c77dc5fa..9498a91 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-with-paint-root-offset-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-with-paint-root-offset-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-with-scale-transform-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-with-scale-transform-expected.png
index b046dba..0ad634a 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-with-scale-transform-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-with-scale-transform-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-zero-outline-width-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-zero-outline-width-expected.png
index 51ccf93..d2b8d51 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-zero-outline-width-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-zero-outline-width-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-zoom-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-zoom-expected.png
index d4d0a98..d052bbc 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-zoom-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-focus-ring-zoom-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-overflowing-circle-focus-ring-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-overflowing-circle-focus-ring-expected.png
index c6223975..75afe18 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-overflowing-circle-focus-ring-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-overflowing-circle-focus-ring-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-overflowing-polygon-focus-ring-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-overflowing-polygon-focus-ring-expected.png
index ed41a17..2c9e772 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-overflowing-polygon-focus-ring-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-overflowing-polygon-focus-ring-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-polygon-focus-ring-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-polygon-focus-ring-expected.png
index 232540fc..cc4da1a 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-polygon-focus-ring-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/imagemap-polygon-focus-ring-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/jpeg-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/jpeg-with-color-profile-expected.png
index 8443216..dacadc04 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/jpeg-with-color-profile-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/jpeg-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/jpeg-yuv-progressive-image-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/jpeg-yuv-progressive-image-expected.png
deleted file mode 100644
index fec0280a..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/jpeg-yuv-progressive-image-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/motion-jpeg-single-frame-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/motion-jpeg-single-frame-expected.png
deleted file mode 100644
index 9dda35f..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/motion-jpeg-single-frame-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/optimize-contrast-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/optimize-contrast-canvas-expected.png
deleted file mode 100644
index c15e7eb2..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/optimize-contrast-canvas-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/optimize-contrast-image-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/optimize-contrast-image-expected.png
deleted file mode 100644
index c15e7eb2..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/optimize-contrast-image-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/pixel-crack-image-background-webkit-transform-scale-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/pixel-crack-image-background-webkit-transform-scale-expected.png
index 460e5d9..97ac605 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/pixel-crack-image-background-webkit-transform-scale-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/pixel-crack-image-background-webkit-transform-scale-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/png-suite/test-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/png-suite/test-expected.png
deleted file mode 100644
index 7eccc40..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/png-suite/test-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/png-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/png-with-color-profile-expected.png
index 8443216..dacadc04 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/png-with-color-profile-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/png-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/rendering-broken-0px-images-quirk-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/rendering-broken-0px-images-quirk-expected.png
index 7f290eb..acc5324 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/rendering-broken-0px-images-quirk-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/rendering-broken-0px-images-quirk-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/rendering-broken-block-flow-images-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/rendering-broken-block-flow-images-expected.png
index 41a9d19..a661f82 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/rendering-broken-block-flow-images-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/rendering-broken-block-flow-images-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/rgb-png-with-cmyk-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/rgb-png-with-cmyk-color-profile-expected.png
deleted file mode 100644
index 8025909..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/rgb-png-with-cmyk-color-profile-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/sprite-no-bleed-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/sprite-no-bleed-expected.png
deleted file mode 100644
index 80de5a89..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/sprite-no-bleed-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/webp-color-profile-lossless-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/webp-color-profile-lossless-expected.png
deleted file mode 100644
index 920523b..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/webp-color-profile-lossless-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/webp-color-profile-lossy-alpha-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/webp-color-profile-lossy-alpha-expected.png
deleted file mode 100644
index ef294951..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/webp-color-profile-lossy-alpha-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/webp-color-profile-lossy-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/webp-color-profile-lossy-expected.png
deleted file mode 100644
index b896e672..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/webp-color-profile-lossy-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/ycbcr-with-cmyk-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/ycbcr-with-cmyk-color-profile-expected.png
deleted file mode 100644
index d7efc45..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/ycbcr-with-cmyk-color-profile-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-arc-circumference-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-arc-circumference-expected.png
deleted file mode 100644
index 61f628a..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-arc-circumference-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-arc-circumference-fill-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-arc-circumference-fill-expected.png
deleted file mode 100644
index 0ce8cd4..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-arc-circumference-fill-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-composite-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-composite-expected.png
index 60043c2..d810784f 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-composite-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-composite-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-composite-shadow-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-composite-shadow-expected.png
index f9dbdb3..24a9022 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-composite-shadow-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-composite-shadow-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-composite-transformclip-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-composite-transformclip-expected.png
deleted file mode 100644
index dae93154..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-composite-transformclip-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-composite-video-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-composite-video-expected.png
index 1311c4d..dc6b5f8 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-composite-video-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-composite-video-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-composite-video-shadow-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-composite-video-shadow-expected.png
deleted file mode 100644
index 502b853..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-composite-video-shadow-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-drawImage-antiAlias-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-drawImage-antiAlias-expected.png
deleted file mode 100644
index 408324c..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-drawImage-antiAlias-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-drawImage-video-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-drawImage-video-expected.png
deleted file mode 100644
index 564b4dc..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-drawImage-video-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png
deleted file mode 100644
index 4801274..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png
deleted file mode 100644
index 9f4d81b0..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
index 1b78a18..736ddc8 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png
deleted file mode 100644
index d8fdd0c..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-pattern-video-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-pattern-video-expected.png
index f31bb59..71553edf 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-pattern-video-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-pattern-video-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
index 9f1f528a..233086c43 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-text-alignment-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-text-alignment-expected.png
index bc5c79f..6c38c2a 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-text-alignment-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-text-alignment-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-text-baseline-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-text-baseline-expected.png
index f8e9716..89cbb593 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-text-baseline-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-text-baseline-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-text-baseline-tiny-fonts-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-text-baseline-tiny-fonts-expected.png
index cc18a7df..1875c53f 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-text-baseline-tiny-fonts-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-text-baseline-tiny-fonts-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-toDataURL-jpeg-maximum-quality-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-toDataURL-jpeg-maximum-quality-expected.png
index be38e06..46a7bff 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-toDataURL-jpeg-maximum-quality-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-toDataURL-jpeg-maximum-quality-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-toDataURL-webp-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-toDataURL-webp-expected.png
deleted file mode 100644
index 159962c..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-toDataURL-webp-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-transforms-during-path-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-transforms-during-path-expected.png
index ed697ce..416fcc5 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-transforms-during-path-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-transforms-during-path-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-zero-length-lineCap-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-zero-length-lineCap-expected.png
deleted file mode 100644
index adf0a6d..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-zero-length-lineCap-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/fillrect_gradient-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/fillrect_gradient-expected.png
index 064078d..049947f 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/fillrect_gradient-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/fillrect_gradient-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/image-object-in-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/image-object-in-canvas-expected.png
index 030291a..7bc4765 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/image-object-in-canvas-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/image-object-in-canvas-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/pixelated-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/pixelated-expected.png
deleted file mode 100644
index e1e0e2d..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/pixelated-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/quadraticCurveTo-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/quadraticCurveTo-expected.png
index 59111ac..a962931 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/quadraticCurveTo-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/quadraticCurveTo-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/webgl/pixelated-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/webgl/pixelated-expected.png
deleted file mode 100644
index 4c356a19..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/webgl/pixelated-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/webgl/webgl-composite-modes-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/webgl/webgl-composite-modes-expected.png
deleted file mode 100644
index 22c1698..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/webgl/webgl-composite-modes-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/webgl/webgl-composite-modes-repaint-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/webgl/webgl-composite-modes-repaint-expected.png
deleted file mode 100644
index 1ead635..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/webgl/webgl-composite-modes-repaint-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/webgl/webgl-composite-modes-tabswitching-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/webgl/webgl-composite-modes-tabswitching-expected.png
deleted file mode 100644
index 329a790..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/webgl/webgl-composite-modes-tabswitching-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/yuv-video-on-accelerated-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/yuv-video-on-accelerated-canvas-expected.png
index a23bd9d..f0411d4 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/yuv-video-on-accelerated-canvas-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/yuv-video-on-accelerated-canvas-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/layout_ng/fast/block/float/008-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/layout_ng/fast/block/float/008-expected.png
deleted file mode 100644
index 54121bed..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/layout_ng/fast/block/float/008-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/layout_ng/fast/block/float/021-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/layout_ng/fast/block/float/021-expected.png
index fa04624..821d7c4e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/layout_ng/fast/block/float/021-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/layout_ng/fast/block/float/021-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/layout_ng/fast/block/margin-collapse/104-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/layout_ng/fast/block/margin-collapse/104-expected.png
index 25d3074..e5a96215 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/layout_ng/fast/block/margin-collapse/104-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/layout_ng/fast/block/margin-collapse/104-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/layout_ng/overflow/overflow-transform-perspective-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/layout_ng/overflow/overflow-transform-perspective-expected.png
index 9b31940b..799fdd2fb 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/layout_ng/overflow/overflow-transform-perspective-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/layout_ng/overflow/overflow-transform-perspective-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/css1/box_properties/float_elements_in_series-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/css1/box_properties/float_elements_in_series-expected.png
index f0c1277..a6d4d61 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/css1/box_properties/float_elements_in_series-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/css1/box_properties/float_elements_in_series-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/css1/box_properties/padding_inline-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/css1/box_properties/padding_inline-expected.png
index 4d33f7d..1901a6c 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/css1/box_properties/padding_inline-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/css1/box_properties/padding_inline-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/css1/pseudo/firstline-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/css1/pseudo/firstline-expected.png
index 8fb0e49..a867f30b 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/css1/pseudo/firstline-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/css1/pseudo/firstline-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/css1/pseudo/pseudo_elements_in_selectors-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/css1/pseudo/pseudo_elements_in_selectors-expected.png
index 33e24d83..e780cc7 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/css1/pseudo/pseudo_elements_in_selectors-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/css1/pseudo/pseudo_elements_in_selectors-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/css1/units/percentage_units-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/css1/units/percentage_units-expected.png
index 05f2895..5f2ae23 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/css1/units/percentage_units-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/css1/units/percentage_units-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/023-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/023-expected.png
index a007f79..1030ac3 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/023-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/023-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/040-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/040-expected.png
index 0ff5526..4b9c6716 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/040-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/040-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-cell-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-cell-expected.png
index a6ef896..84513c6 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-cell-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-cell-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-column-collapsed-border-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-column-collapsed-border-expected.png
index 6034610..4bd727e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-column-collapsed-border-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-column-collapsed-border-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-column-group-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-column-group-expected.png
index 05883dc..010ec78 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-column-group-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-column-group-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-expected.png
new file mode 100644
index 0000000..29c64ac15
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-row-collapsed-border-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-row-collapsed-border-expected.png
index 3cb3102..707b7f0 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-row-collapsed-border-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-row-collapsed-border-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-row-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-row-expected.png
index 8aa6930..535f451 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-row-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_border-table-row-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_layers-hide-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_layers-hide-expected.png
index 449a74d..4f8ea7b4 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_layers-hide-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_layers-hide-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_layers-show-collapsed-border-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_layers-show-collapsed-border-expected.png
index 59728f5..690b06a 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_layers-show-collapsed-border-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_layers-show-collapsed-border-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_layers-show-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_layers-show-expected.png
index 6fd0aba..718169d 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_layers-show-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_layers-show-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_position-table-column-group-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_position-table-column-group-expected.png
index 8c39206..0bc70bc 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_position-table-column-group-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_position-table-column-group-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_position-table-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_position-table-expected.png
index 4008f02..e18d8ac6 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_position-table-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_position-table-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_position-table-row-collapsed-border-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_position-table-row-collapsed-border-expected.png
index 0e3a429..93165f4 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_position-table-row-collapsed-border-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_position-table-row-collapsed-border-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_position-table-row-group-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_position-table-row-group-expected.png
index 61e56fc..97293ab7 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_position-table-row-group-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_position-table-row-group-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_simple-table-cell-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_simple-table-cell-expected.png
index 4996351..6d2f3e12 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_simple-table-cell-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_simple-table-cell-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_simple-table-column-collapsed-border-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_simple-table-column-collapsed-border-expected.png
index 2c9ea75e..78bdac9 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_simple-table-column-collapsed-border-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_simple-table-column-collapsed-border-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_simple-table-column-group-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_simple-table-column-group-expected.png
index 43c8a66..aaeb391 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_simple-table-column-group-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_simple-table-column-group-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_simple-table-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_simple-table-expected.png
index d6976ec7..6f613657 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_simple-table-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_simple-table-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_simple-table-row-collapsed-border-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_simple-table-row-collapsed-border-expected.png
index bd65d9e7c..ca82511 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_simple-table-row-collapsed-border-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_simple-table-row-collapsed-border-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/empty-cells-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/empty-cells-expected.png
index 9af691d..8d98f0a 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/empty-cells-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/empty-cells-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.png
index ca0e28f..6558104 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.txt
deleted file mode 100644
index b202525..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x171
-  LayoutBlockFlow {HTML} at (0,0) size 800x171
-    LayoutBlockFlow {BODY} at (8,8) size 784x155
-      LayoutText {#text} at (0,0) size 0x0
-layer at (8,8) size 300x150
-  LayoutVideo {VIDEO} at (0,0) size 300x150
-layer at (8,8) size 300x150
-  LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 300x150
-    LayoutBlockFlow {DIV} at (0,118) size 300x32
-layer at (8,8) size 300x108
-  LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 300x108
-layer at (8,126) size 300x32 scrollHeight 40
-  LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 300x32 [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:07"
-    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:07"
-    LayoutSlider {INPUT} at (108,15) size 49x2
-      LayoutFlexibleBox {DIV} at (0,0) size 49x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 85x48
-          LayoutBlockFlow {DIV} at (49,0) size 36x48
-    LayoutButton {INPUT} at (175,0) size 32x32
-    LayoutSlider {INPUT} at (225,15) size 25x2
-      LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
-    LayoutButton {INPUT} at (268,0) size 32x32
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/http/tests/misc/object-embedding-svg-delayed-size-negotiation-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/http/tests/misc/object-embedding-svg-delayed-size-negotiation-expected.png
deleted file mode 100644
index 52b7c89..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/http/tests/misc/object-embedding-svg-delayed-size-negotiation-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png
index c0d1ed9..b855e4b0 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-expected.png
index a7d8a8d2..8e5f7434 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-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 6f1b9b4..ba4b97c 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-controls-with-cast-rendering-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering-expected.txt
index 57e32b07..02d33b2 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering-expected.txt
@@ -29,16 +29,32 @@
           text run at (0,8) width 24: "0:00"
     LayoutSlider {INPUT} at (74,15) size 71x2
       LayoutFlexibleBox {DIV} at (0,0) size 71x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 107x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
     LayoutButton {INPUT} at (163,0) size 32x32
     LayoutSlider {INPUT} at (213,15) size 25x2
       LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
     LayoutButton {INPUT} at (288,0) size 32x32
 layer at (264,260) size 32x32
   LayoutButton {INPUT} at (256,0) size 32x32
+layer at (64,276) size 107x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 107x0
+layer at (82,275) size 71x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 71x2 [bgcolor=#DADADA]
+layer at (203,276) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+layer at (221,275) size 25x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (82,275) size 71x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 71x2 [bgcolor=#5A5A5A]
+layer at (82,275) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (221,275) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (221,275) size 25x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (64,252) size 36x48 backgroundClip at (8,260) size 320x32 clip at (8,260) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
+layer at (228,252) size 36x48 backgroundClip at (8,260) size 320x32 clip at (8,260) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
 layer at (8,297) size 320x240
   LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 320x240
     LayoutBlockFlow {DIV} at (0,208) size 320x32
@@ -53,16 +69,32 @@
           text run at (0,8) width 24: "0:00"
     LayoutSlider {INPUT} at (74,15) size 71x2
       LayoutFlexibleBox {DIV} at (0,0) size 71x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 107x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
     LayoutButton {INPUT} at (163,0) size 32x32
     LayoutSlider {INPUT} at (213,15) size 25x2
       LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
     LayoutButton {INPUT} at (288,0) size 32x32
 layer at (264,505) size 32x32
   LayoutButton {INPUT} at (256,0) size 32x32
+layer at (64,521) size 107x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 107x0
+layer at (82,520) size 71x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 71x2 [bgcolor=#DADADA]
+layer at (203,521) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+layer at (221,520) size 25x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (82,520) size 71x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 71x2 [bgcolor=#5A5A5A]
+layer at (82,520) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (221,520) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (221,520) size 25x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (64,497) size 36x48 backgroundClip at (8,505) size 320x32 clip at (8,505) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
+layer at (228,497) size 36x48 backgroundClip at (8,505) size 320x32 clip at (8,505) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
 layer at (8,542) size 320x240 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
   LayoutVideo (positioned) {VIDEO} at (8,542) size 320x240
 layer at (8,542) size 320x240 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
@@ -79,13 +111,29 @@
           text run at (0,8) width 24: "0:00"
     LayoutSlider {INPUT} at (74,15) size 71x2
       LayoutFlexibleBox {DIV} at (0,0) size 71x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 107x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
     LayoutButton {INPUT} at (163,0) size 32x32
     LayoutSlider {INPUT} at (213,15) size 25x2
       LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
     LayoutButton {INPUT} at (288,0) size 32x32
 layer at (264,750) size 32x32 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
   LayoutButton {INPUT} at (256,0) size 32x32
+layer at (64,766) size 107x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 107x0
+layer at (82,765) size 71x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 71x2 [bgcolor=#DADADA]
+layer at (203,766) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+layer at (221,765) size 25x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (82,765) size 71x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 71x2 [bgcolor=#5A5A5A]
+layer at (82,765) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (221,765) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (221,765) size 25x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (64,742) size 36x48 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
+layer at (228,742) size 36x48 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
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 21c7372e..6881c87 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/linux/virtual/new-remote-playback-pipeline/media/controls/video-overlay-cast-light-rendering-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/video-overlay-cast-light-rendering-expected.png
index f0f58639..6f50ab8 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/video-overlay-cast-light-rendering-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/video-overlay-cast-light-rendering-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/accelerated-scrolling-with-clip-path-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/accelerated-scrolling-with-clip-path-expected.png
deleted file mode 100644
index 31ce3d9..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/accelerated-scrolling-with-clip-path-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/border-radius-on-grandparent-composited-grandchild-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/border-radius-on-grandparent-composited-grandchild-expected.png
deleted file mode 100644
index 2cee245..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/border-radius-on-grandparent-composited-grandchild-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/border-radius-on-parent-composited-grandchild-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/border-radius-on-parent-composited-grandchild-expected.png
deleted file mode 100644
index b60254a..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/border-radius-on-parent-composited-grandchild-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/border-radius-on-two-ancestors-composited-grandchild-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/border-radius-on-two-ancestors-composited-grandchild-expected.png
deleted file mode 100644
index b9fac482..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/border-radius-on-two-ancestors-composited-grandchild-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/border-radius-styles-with-composited-child-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/border-radius-styles-with-composited-child-expected.png
deleted file mode 100644
index 5fa2b0b..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/border-radius-styles-with-composited-child-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/grandchild-composited-with-border-radius-ancestor-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/grandchild-composited-with-border-radius-ancestor-expected.png
deleted file mode 100644
index f38a1b2..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/grandchild-composited-with-border-radius-ancestor-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/grandchild-with-border-radius-ancestor-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/grandchild-with-border-radius-ancestor-expected.png
deleted file mode 100644
index f38a1b2..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/grandchild-with-border-radius-ancestor-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/mask-with-filter-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/mask-with-filter-expected.png
deleted file mode 100644
index fff540df..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/mask-with-filter-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-expected.png
deleted file mode 100644
index df1e8d1..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-intervening-clip-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-intervening-clip-expected.png
deleted file mode 100644
index ce412b6..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-intervening-clip-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-rotation-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-rotation-expected.png
deleted file mode 100644
index b474717..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-rotation-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-compositing-descendant-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-compositing-descendant-expected.png
index 1e09c67..f5d9cd3 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-compositing-descendant-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-compositing-descendant-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scaled-mask-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scaled-mask-expected.png
index c98959e..f9d24e27 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scaled-mask-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scaled-mask-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scaled-overflow-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scaled-overflow-expected.png
deleted file mode 100644
index c1c4d7ff..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scaled-overflow-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scroll-ancestor-update-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scroll-ancestor-update-expected.png
index 8916901..5d5a44a 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scroll-ancestor-update-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scroll-ancestor-update-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/siblings-composited-with-border-radius-ancestor-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/siblings-composited-with-border-radius-ancestor-expected.png
deleted file mode 100644
index f38a1b2..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/siblings-composited-with-border-radius-ancestor-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped-expected.png
deleted file mode 100644
index 00fa2b9..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/siblings-with-border-radius-ancestor-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/siblings-with-border-radius-ancestor-expected.png
deleted file mode 100644
index ff3a0270..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/siblings-with-border-radius-ancestor-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/tiled-mask-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/tiled-mask-expected.png
deleted file mode 100644
index ba320740..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/tiled-mask-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/scrollbars/scrollbars-on-positioned-content-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/scrollbars/scrollbars-on-positioned-content-expected.png
index 1f5c550..d559c37 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/scrollbars/scrollbars-on-positioned-content-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/scrollbars/scrollbars-on-positioned-content-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor150/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor150/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
index 1fee21c..3fa71a05 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor150/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor150/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
index 1864cbd..3669d2a 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
index 1864cbd..3669d2a 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/animations/rotate-transform-equivalent-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/animations/rotate-transform-equivalent-expected.png
index 867a086..0a3a04a 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/animations/rotate-transform-equivalent-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/animations/rotate-transform-equivalent-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/animations/skew-notsequential-compositor-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/animations/skew-notsequential-compositor-expected.png
deleted file mode 100644
index 7fdff4b..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/animations/skew-notsequential-compositor-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/compositing/visibility/visibility-image-layers-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/compositing/visibility/visibility-image-layers-expected.png
deleted file mode 100644
index 365ad04..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/compositing/visibility/visibility-image-layers-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/compositing/visibility/visibility-simple-video-layer-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/compositing/visibility/visibility-simple-video-layer-expected.png
deleted file mode 100644
index 3d2a91a..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/compositing/visibility/visibility-simple-video-layer-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/compositing/webgl/webgl-reflection-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/compositing/webgl/webgl-reflection-expected.png
index f90d16e5..5b050023 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/compositing/webgl/webgl-reflection-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/compositing/webgl/webgl-reflection-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/printing/return-from-printing-mode-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/printing/return-from-printing-mode-expected.png
index 773e4cf..a634b4002 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/printing/return-from-printing-mode-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/printing/return-from-printing-mode-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/transitions/opacity-transform-transitions-inside-iframe-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/transitions/opacity-transform-transitions-inside-iframe-expected.png
deleted file mode 100644
index 70fc03d6..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/transitions/opacity-transform-transitions-inside-iframe-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/transitions/opacity-transition-zindex-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/transitions/opacity-transition-zindex-expected.png
deleted file mode 100644
index 43c5d9c..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/transitions/opacity-transition-zindex-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/external/wpt/html/semantics/scripting-1/the-script-element/module/instantiation-error-5-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/external/wpt/html/semantics/scripting-1/the-script-element/module/instantiation-error-5-expected.txt
new file mode 100644
index 0000000..7df452b1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/external/wpt/html/semantics/scripting-1/the-script-element/module/instantiation-error-5-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL Test that loading a graph in which a module is already errored results in that module's error. assert_array_equals: property 2, expected object "SyntaxError: The requested module does not provide an export named 'something'" but got object "SyntaxError: The requested module does not provide an export named 'something'"
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/media/video-zoom-controls-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/media/video-zoom-controls-expected.png
index f4549b6b..d144fd2 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/media/video-zoom-controls-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/media/video-zoom-controls-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
index 922ac01..9791751 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
@@ -49,10 +49,6 @@
       "reason": "subtree"
     },
     {
-      "object": "HorizontalScrollbar",
-      "reason": "scroll control"
-    },
-    {
       "object": "Caret",
       "reason": "caret"
     },
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/invalidate-caret-in-non-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/invalidate-caret-in-non-composited-scrolling-container-expected.txt
index 922ac01..9791751 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/invalidate-caret-in-non-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/invalidate-caret-in-non-composited-scrolling-container-expected.txt
@@ -49,10 +49,6 @@
       "reason": "subtree"
     },
     {
-      "object": "HorizontalScrollbar",
-      "reason": "scroll control"
-    },
-    {
       "object": "Caret",
       "reason": "caret"
     },
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
index 087e597..f726577 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
@@ -46,10 +46,6 @@
       "reason": "subtree"
     },
     {
-      "object": "HorizontalScrollbar",
-      "reason": "scroll control"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "subtree"
     },
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
index 087e597..f726577 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
@@ -46,10 +46,6 @@
       "reason": "subtree"
     },
     {
-      "object": "HorizontalScrollbar",
-      "reason": "scroll control"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "subtree"
     },
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/external/wpt/html/semantics/scripting-1/the-script-element/module/instantiation-error-5-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-retina/external/wpt/html/semantics/scripting-1/the-script-element/module/instantiation-error-5-expected.txt
new file mode 100644
index 0000000..7df452b1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/external/wpt/html/semantics/scripting-1/the-script-element/module/instantiation-error-5-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL Test that loading a graph in which a module is already errored results in that module's error. assert_array_equals: property 2, expected object "SyntaxError: The requested module does not provide an export named 'something'" but got object "SyntaxError: The requested module does not provide an export named 'something'"
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/media/video-zoom-controls-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/media/video-zoom-controls-expected.png
index f4549b6b..d144fd2 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-retina/media/video-zoom-controls-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/media/video-zoom-controls-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/bluetooth/idl/idl-BluetoothDevice-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/bluetooth/idl/idl-BluetoothDevice-expected.txt
deleted file mode 100644
index 15f40882..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/bluetooth/idl/idl-BluetoothDevice-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This is a testharness.js-based test.
-FAIL BluetoothDevice IDL test Test bug: need to pass exception to assert_throws()
-PASS BluetoothDevice attributes.
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/culling/filter-occlusion-blur-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/culling/filter-occlusion-blur-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/linux/compositing/culling/filter-occlusion-blur-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac/compositing/culling/filter-occlusion-blur-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/video/video-controls-layer-creation-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/video/video-controls-layer-creation-expected.png
index 5f347be9..f7da7d4 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/compositing/video/video-controls-layer-creation-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/video/video-controls-layer-creation-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-blur-hw-expected.png b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-blur-hw-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-blur-hw-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-blur-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/filter-repaint-composited-fallback-crash-expected.png b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/filter-repaint-composited-fallback-crash-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/linux/css3/filters/filter-repaint-composited-fallback-crash-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac/css3/filters/filter-repaint-composited-fallback-crash-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/filter-repaint-composited-fallback-expected.png b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/filter-repaint-composited-fallback-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/linux/css3/filters/filter-repaint-composited-fallback-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac/css3/filters/filter-repaint-composited-fallback-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/replaced/inline-box-wrapper-handover-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/replaced/inline-box-wrapper-handover-expected.png
deleted file mode 100644
index 814ec43..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/replaced/inline-box-wrapper-handover-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/replaced/inline-box-wrapper-handover-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/replaced/inline-box-wrapper-handover-expected.txt
deleted file mode 100644
index 110e61aa..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/replaced/inline-box-wrapper-handover-expected.txt
+++ /dev/null
@@ -1,49 +0,0 @@
-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 {P} at (0,0) size 784x36
-        LayoutText {#text} at (0,0) size 260x18
-          text run at (0,0) width 260: "This test checks for a regression against "
-        LayoutInline {I} at (0,0) size 756x36
-          LayoutInline {A} at (0,0) size 353x18 [color=#0000EE]
-            LayoutText {#text} at (259,0) size 353x18
-              text run at (259,0) width 353: "http://bugzilla.opendarwin.org/show_bug.cgi?id=6276"
-          LayoutText {#text} at (611,0) size 756x36
-            text run at (611,0) width 5: " "
-            text run at (615,0) width 141: "Image thumbnails are"
-            text run at (0,18) width 196: "misplaced on forum.2ostrov.ru"
-        LayoutText {#text} at (195,18) size 5x18
-          text run at (195,18) width 5: "."
-      LayoutBlockFlow {HR} at (0,52) size 784x2 [border: (1px inset #EEEEEE)]
-      LayoutBlockFlow {P} at (0,70) size 784x18
-        LayoutText {#text} at (0,0) size 235x18
-          text run at (0,0) width 235: "Box 1 and box 2 should be identical."
-      LayoutBlockFlow (anonymous) at (0,104) size 784x18
-        LayoutText {#text} at (0,0) size 44x18
-          text run at (0,0) width 44: "Box 1:"
-      LayoutBlockFlow {DIV} at (0,122) size 67x80 [border: (1px solid #000000)]
-        LayoutBlockFlow {DIV} at (6,6) size 40x20 [bgcolor=#0000FF]
-        LayoutText {#text} at (6,32) size 16x18
-          text run at (6,32) width 16: "A "
-        LayoutBlockFlow {DIV} at (21.55,26) size 35x20 [bgcolor=#FF0000]
-        LayoutText {#text} at (6,56) size 15x18
-          text run at (6,56) width 15: "B "
-        LayoutBlockFlow {DIV} at (20.67,50) size 20x20 [bgcolor=#008000]
-        LayoutText {#text} at (40,56) size 16x18
-          text run at (40,56) width 16: " C"
-      LayoutBlockFlow (anonymous) at (0,202) size 784x36
-        LayoutBR {BR} at (0,0) size 0x18
-        LayoutText {#text} at (0,18) size 44x18
-          text run at (0,18) width 44: "Box 2:"
-      LayoutBlockFlow {DIV} at (0,238) size 67x80 [border: (1px solid #000000)]
-        LayoutBlockFlow {DIV} at (6,6) size 40x20 [bgcolor=#0000FF]
-        LayoutText {#text} at (6,32) size 16x18
-          text run at (6,32) width 16: "A "
-        LayoutBlockFlow {DIV} at (21.55,26) size 35x20 [bgcolor=#FF0000]
-        LayoutText {#text} at (6,56) size 15x18
-          text run at (6,56) width 15: "B "
-        LayoutBlockFlow {DIV} at (20.67,50) size 20x20 [bgcolor=#008000]
-        LayoutText {#text} at (40,56) size 16x18
-          text run at (40,56) width 16: " C"
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fullscreen/compositor-touch-hit-rects-fullscreen-video-controls-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fullscreen/compositor-touch-hit-rects-fullscreen-video-controls-expected.txt
deleted file mode 100644
index 86ee642..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/fullscreen/compositor-touch-hit-rects-fullscreen-video-controls-expected.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-This test makes sure that touch hit rects are reported for fullscreen HTML5 video control elements even when there is a document handler.
-
-Should have single rect on document before fullscreen
-handler: #document (0, 0, 800, 600)
-
-EVENT(webkitfullscreenchange)
-Should keep rect on document
-handler: #document (0, 0, 800, 600)
-handler: #document (55, 600, 713, 8)
-
-END OF TEST
-
diff --git a/third_party/WebKit/LayoutTests/platform/mac/http/tests/media/video-buffered-range-contains-currentTime-expected.png b/third_party/WebKit/LayoutTests/platform/mac/http/tests/media/video-buffered-range-contains-currentTime-expected.png
index bb528ee..1064fbb7 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/http/tests/media/video-buffered-range-contains-currentTime-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/http/tests/media/video-buffered-range-contains-currentTime-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/http/tests/media/video-buffered-range-contains-currentTime-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/http/tests/media/video-buffered-range-contains-currentTime-expected.txt
index 5ca85b6..bf59cdf 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/http/tests/media/video-buffered-range-contains-currentTime-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/http/tests/media/video-buffered-range-contains-currentTime-expected.txt
@@ -24,11 +24,27 @@
           text run at (0,9) width 31: "/ 0:07"
     LayoutSlider {INPUT} at (108.05,15) size 48.95x2
       LayoutFlexibleBox {DIV} at (0,0) size 48.95x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 84.95x48
-          LayoutBlockFlow {DIV} at (48.95,0) size 36x48
     LayoutButton {INPUT} at (175,0) size 32x32
     LayoutSlider {INPUT} at (225,15) size 25x2
       LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
     LayoutButton {INPUT} at (268,0) size 32x32
+layer at (98,142) size 85x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 84.95x0
+layer at (116,141) size 49x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 48.95x2 [bgcolor=#DADADA]
+layer at (215,142) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+layer at (233,141) size 25x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (165,141) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (49,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (116,141) size 49x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 49x2 [bgcolor=#4285F4]
+layer at (233,141) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (233,141) size 25x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (147,118) size 36x48 backgroundClip at (8,126) size 300x32 clip at (8,126) size 300x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (48.95,-24) size 36x48
+layer at (240,118) size 36x48 backgroundClip at (8,126) size 300x32 clip at (8,126) size 300x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-layer-filter-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-layer-filter-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/linux/images/color-profile-layer-filter-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac/images/color-profile-layer-filter-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png
index 1ac4141..14720be 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.txt
index 126bd1c1..c0eeef7 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.txt
@@ -24,7 +24,15 @@
           text run at (0,9) width 31: "/ 0:09"
     LayoutSlider {INPUT} at (108.05,15) size 241.95x2
       LayoutFlexibleBox {DIV} at (0,0) size 241.95x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 277.95x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
 layer at (376,303) size 32x32
   LayoutButton {INPUT} at (368,0) size 32x32
+layer at (98,319) size 278x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 277.95x0
+layer at (116,318) size 242x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 241.95x2 [bgcolor=#DADADA]
+layer at (116,318) size 242x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 242x2 [bgcolor=#5A5A5A]
+layer at (116,318) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (98,295) size 36x48 backgroundClip at (8,303) size 400x32 clip at (8,303) size 400x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/controls/paint-controls-webkit-appearance-none-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/controls/paint-controls-webkit-appearance-none-expected.png
index 80ba53f..867a28f 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/controls/paint-controls-webkit-appearance-none-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/controls/paint-controls-webkit-appearance-none-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/controls/paint-controls-webkit-appearance-none-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/media/controls/paint-controls-webkit-appearance-none-expected.txt
index 126bd1c1..c0eeef7 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/controls/paint-controls-webkit-appearance-none-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/controls/paint-controls-webkit-appearance-none-expected.txt
@@ -24,7 +24,15 @@
           text run at (0,9) width 31: "/ 0:09"
     LayoutSlider {INPUT} at (108.05,15) size 241.95x2
       LayoutFlexibleBox {DIV} at (0,0) size 241.95x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 277.95x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
 layer at (376,303) size 32x32
   LayoutButton {INPUT} at (368,0) size 32x32
+layer at (98,319) size 278x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 277.95x0
+layer at (116,318) size 242x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 241.95x2 [bgcolor=#DADADA]
+layer at (116,318) size 242x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 242x2 [bgcolor=#5A5A5A]
+layer at (116,318) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (98,295) size 36x48 backgroundClip at (8,303) size 400x32 clip at (8,303) size 400x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/controls/video-controls-with-cast-rendering-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/controls/video-controls-with-cast-rendering-expected.png
index 68a1145d..ca1b998 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/controls/video-controls-with-cast-rendering-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/controls/video-controls-with-cast-rendering-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/controls/video-controls-with-cast-rendering-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/media/controls/video-controls-with-cast-rendering-expected.txt
index 657f77fa..16cf988 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/controls/video-controls-with-cast-rendering-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/controls/video-controls-with-cast-rendering-expected.txt
@@ -29,16 +29,32 @@
           text run at (0,9) width 24: "0:00"
     LayoutSlider {INPUT} at (73.36,15) size 71.64x2
       LayoutFlexibleBox {DIV} at (0,0) size 71.64x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 107.64x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
     LayoutButton {INPUT} at (163,0) size 32x32
     LayoutSlider {INPUT} at (213,15) size 25x2
       LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
     LayoutButton {INPUT} at (288,0) size 32x32
 layer at (264,258) size 32x32
   LayoutButton {INPUT} at (256,0) size 32x32
+layer at (63,274) size 108x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 107.64x0
+layer at (81,273) size 72x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 71.64x2 [bgcolor=#DADADA]
+layer at (203,274) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+layer at (221,273) size 25x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (81,273) size 72x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 72x2 [bgcolor=#5A5A5A]
+layer at (81,273) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (221,273) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (221,273) size 25x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (63,250) size 36x48 backgroundClip at (8,258) size 320x32 clip at (8,258) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
+layer at (228,250) size 36x48 backgroundClip at (8,258) size 320x32 clip at (8,258) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
 layer at (8,294) size 320x240
   LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 320x240
     LayoutBlockFlow {DIV} at (0,208) size 320x32
@@ -53,16 +69,32 @@
           text run at (0,9) width 24: "0:00"
     LayoutSlider {INPUT} at (73.36,15) size 71.64x2
       LayoutFlexibleBox {DIV} at (0,0) size 71.64x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 107.64x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
     LayoutButton {INPUT} at (163,0) size 32x32
     LayoutSlider {INPUT} at (213,15) size 25x2
       LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
     LayoutButton {INPUT} at (288,0) size 32x32
 layer at (264,502) size 32x32
   LayoutButton {INPUT} at (256,0) size 32x32
+layer at (63,518) size 108x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 107.64x0
+layer at (81,517) size 72x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 71.64x2 [bgcolor=#DADADA]
+layer at (203,518) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+layer at (221,517) size 25x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (81,517) size 72x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 72x2 [bgcolor=#5A5A5A]
+layer at (81,517) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (221,517) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (221,517) size 25x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (63,494) size 36x48 backgroundClip at (8,502) size 320x32 clip at (8,502) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
+layer at (228,494) size 36x48 backgroundClip at (8,502) size 320x32 clip at (8,502) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
 layer at (8,538) size 320x240 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
   LayoutVideo (positioned) {VIDEO} at (8,538) size 320x240
 layer at (8,538) size 320x240 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
@@ -79,13 +111,29 @@
           text run at (0,9) width 24: "0:00"
     LayoutSlider {INPUT} at (73.36,15) size 71.64x2
       LayoutFlexibleBox {DIV} at (0,0) size 71.64x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 107.64x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
     LayoutButton {INPUT} at (163,0) size 32x32
     LayoutSlider {INPUT} at (213,15) size 25x2
       LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
     LayoutButton {INPUT} at (288,0) size 32x32
 layer at (264,746) size 32x32 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
   LayoutButton {INPUT} at (256,0) size 32x32
+layer at (63,762) size 108x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 107.64x0
+layer at (81,761) size 72x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 71.64x2 [bgcolor=#DADADA]
+layer at (203,762) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+layer at (221,761) size 25x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (81,761) size 72x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 72x2 [bgcolor=#5A5A5A]
+layer at (81,761) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (221,761) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (221,761) size 25x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (63,738) size 36x48 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
+layer at (228,738) size 36x48 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
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..0e8c2bd 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/controls/video-overlay-cast-light-rendering-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/controls/video-overlay-cast-light-rendering-expected.png
index 23d7968..360ea7a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/controls/video-overlay-cast-light-rendering-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/controls/video-overlay-cast-light-rendering-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/media-document-audio-repaint-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/media-document-audio-repaint-expected.png
index 92cee9c..4b71d29 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/media-document-audio-repaint-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/media-document-audio-repaint-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/media-document-audio-repaint-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/media/media-document-audio-repaint-expected.txt
index e9d56e2f..ed0a5fd2 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/media-document-audio-repaint-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/media-document-audio-repaint-expected.txt
@@ -36,10 +36,26 @@
               text run at (0,9) width 31: "/ 0:01"
         LayoutSlider {INPUT} at (108.05,15) size 80.95x2
           LayoutFlexibleBox {DIV} at (0,0) size 80.95x2
-            LayoutBlockFlow {DIV} at (-18,-23) size 116.95x48
-              LayoutBlockFlow {DIV} at (40.47,0) size 36x48
         LayoutButton {INPUT} at (207,0) size 32x32
         LayoutSlider {INPUT} at (257,15) size 25x2
           LayoutFlexibleBox {DIV} at (0,0) size 25x2
-            LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-              LayoutBlockFlow {DIV} at (25,0) size 36x48
+    layer at (130,150) size 117x0
+      LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 116.95x0
+    layer at (148,149) size 81x2
+      LayoutBlockFlow (positioned) {DIV} at (18,-1) size 80.95x2 [bgcolor=#DADADA]
+    layer at (279,150) size 61x0
+      LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+    layer at (297,149) size 25x2
+      LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+    layer at (188,149) size 40x2
+      LayoutBlockFlow (positioned) zI: 1 {DIV} at (40,0) size 40x2 [bgcolor=#5A5A5A]
+    layer at (148,149) size 40x2
+      LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 40x2 [bgcolor=#4285F4]
+    layer at (297,149) size 0x2
+      LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+    layer at (297,149) size 25x2
+      LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+    layer at (171,126) size 36x48 backgroundClip at (40,134) size 300x32 clip at (40,134) size 300x32
+      LayoutBlockFlow (positioned) zI: 2 {DIV} at (40.47,-24) size 36x48
+    layer at (304,126) size 36x48 backgroundClip at (40,134) size 300x32 clip at (40,134) size 300x32
+      LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
index 9ebe57b..522d15c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
@@ -49,10 +49,6 @@
       "reason": "subtree"
     },
     {
-      "object": "HorizontalScrollbar",
-      "reason": "scroll control"
-    },
-    {
       "object": "Caret",
       "reason": "caret"
     },
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/invalidate-caret-in-non-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/invalidate-caret-in-non-composited-scrolling-container-expected.txt
index 9ebe57b..522d15c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/invalidate-caret-in-non-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/invalidate-caret-in-non-composited-scrolling-container-expected.txt
@@ -49,10 +49,6 @@
       "reason": "subtree"
     },
     {
-      "object": "HorizontalScrollbar",
-      "reason": "scroll control"
-    },
-    {
       "object": "Caret",
       "reason": "caret"
     },
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/outline-change-in-scrollers-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/outline-change-in-scrollers-expected.txt
new file mode 100644
index 0000000..bc25455
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/outline-change-in-scrollers-expected.txt
@@ -0,0 +1,69 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='target'",
+          "rect": [286, 172, 75, 75],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutBlockFlow DIV class='target'",
+          "rect": [286, 18, 75, 75],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutBlockFlow DIV class='target'",
+          "rect": [172, 172, 75, 75],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutBlockFlow DIV class='target'",
+          "rect": [172, 18, 75, 75],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutBlockFlow DIV class='target'",
+          "rect": [53, 152, 75, 75],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutBlockFlow DIV class='target'",
+          "rect": [18, 18, 75, 75],
+          "reason": "style change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV class='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow DIV class='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow DIV class='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow DIV class='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow DIV class='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow DIV class='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
index 176b6cfc..936e1a2 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
@@ -46,10 +46,6 @@
       "reason": "subtree"
     },
     {
-      "object": "HorizontalScrollbar",
-      "reason": "scroll control"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "subtree"
     },
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
index 176b6cfc..936e1a2 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
@@ -46,10 +46,6 @@
       "reason": "subtree"
     },
     {
-      "object": "HorizontalScrollbar",
-      "reason": "scroll control"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "subtree"
     },
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/video-mute-repaint-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/video-mute-repaint-expected.txt
deleted file mode 100644
index d081c42..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/video-mute-repaint-expected.txt
+++ /dev/null
@@ -1,106 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF",
-      "paintInvalidations": [
-        {
-          "object": "LayoutBlockFlow BODY",
-          "rect": [8, 8, 784, 529],
-          "reason": "geometry"
-        }
-      ]
-    },
-    {
-      "name": "LayoutVideo VIDEO id='v'",
-      "position": [8, 8],
-      "bounds": [700, 525],
-      "drawsContent": false
-    },
-    {
-      "name": "Squashing Containment Layer",
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutFlexibleBox (relative positioned) DIV class='phase-ready state-stopped'",
-      "position": [8, 8],
-      "bounds": [700, 525],
-      "paintInvalidations": [
-        {
-          "object": "LayoutFlexibleBox (relative positioned) DIV class='phase-ready state-stopped'",
-          "rect": [0, 0, 700, 525],
-          "reason": "geometry"
-        }
-      ]
-    },
-    {
-      "name": "Squashing Layer (first squashed layer: LayoutFlexibleBox (relative positioned) DIV)",
-      "position": [8, 8],
-      "bounds": [700, 525],
-      "paintInvalidations": [
-        {
-          "object": "LayoutFlexibleBox DIV",
-          "rect": [580, 508, 70, 2],
-          "reason": "geometry"
-        },
-        {
-          "object": "LayoutSlider INPUT",
-          "rect": [580, 508, 70, 2],
-          "reason": "full"
-        },
-        {
-          "object": "LayoutBlockFlow DIV id='thumb'",
-          "rect": [632, 485, 36, 48],
-          "reason": "full"
-        },
-        {
-          "object": "LayoutBlockFlow DIV id='thumb'",
-          "rect": [562, 485, 36, 48],
-          "reason": "full"
-        },
-        {
-          "object": "LayoutButton INPUT",
-          "rect": [530, 493, 32, 32],
-          "reason": "full"
-        }
-      ]
-    }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "geometry"
-    },
-    {
-      "object": "RootInlineBox",
-      "reason": "geometry"
-    },
-    {
-      "object": "LayoutVideo VIDEO id='v'",
-      "reason": "style change"
-    },
-    {
-      "object": "LayoutFlexibleBox (relative positioned) DIV class='phase-ready state-stopped'",
-      "reason": "geometry"
-    },
-    {
-      "object": "LayoutButton INPUT",
-      "reason": "full"
-    },
-    {
-      "object": "LayoutSlider INPUT",
-      "reason": "full"
-    },
-    {
-      "object": "LayoutFlexibleBox DIV",
-      "reason": "geometry"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='thumb'",
-      "reason": "full"
-    }
-  ]
-}
-
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/video-unmute-repaint-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/video-unmute-repaint-expected.txt
deleted file mode 100644
index dd1a664..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/video-unmute-repaint-expected.txt
+++ /dev/null
@@ -1,106 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF",
-      "paintInvalidations": [
-        {
-          "object": "LayoutBlockFlow (anonymous)",
-          "rect": [8, 8, 784, 529],
-          "reason": "geometry"
-        }
-      ]
-    },
-    {
-      "name": "LayoutVideo VIDEO id='v'",
-      "position": [8, 8],
-      "bounds": [700, 525],
-      "drawsContent": false
-    },
-    {
-      "name": "Squashing Containment Layer",
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutFlexibleBox (relative positioned) DIV class='phase-ready state-stopped'",
-      "position": [8, 8],
-      "bounds": [700, 525],
-      "paintInvalidations": [
-        {
-          "object": "LayoutFlexibleBox (relative positioned) DIV class='phase-ready state-stopped'",
-          "rect": [0, 0, 700, 525],
-          "reason": "geometry"
-        }
-      ]
-    },
-    {
-      "name": "Squashing Layer (first squashed layer: LayoutFlexibleBox (relative positioned) DIV)",
-      "position": [8, 8],
-      "bounds": [700, 525],
-      "paintInvalidations": [
-        {
-          "object": "LayoutFlexibleBox DIV",
-          "rect": [580, 508, 70, 2],
-          "reason": "geometry"
-        },
-        {
-          "object": "LayoutSlider INPUT",
-          "rect": [580, 508, 70, 2],
-          "reason": "full"
-        },
-        {
-          "object": "LayoutBlockFlow DIV id='thumb'",
-          "rect": [597, 485, 36, 48],
-          "reason": "full"
-        },
-        {
-          "object": "LayoutBlockFlow DIV id='thumb'",
-          "rect": [562, 485, 36, 48],
-          "reason": "full"
-        },
-        {
-          "object": "LayoutButton INPUT",
-          "rect": [530, 493, 32, 32],
-          "reason": "full"
-        }
-      ]
-    }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "LayoutBlockFlow (anonymous)",
-      "reason": "geometry"
-    },
-    {
-      "object": "RootInlineBox",
-      "reason": "geometry"
-    },
-    {
-      "object": "LayoutVideo VIDEO id='v'",
-      "reason": "style change"
-    },
-    {
-      "object": "LayoutFlexibleBox (relative positioned) DIV class='phase-ready state-stopped'",
-      "reason": "geometry"
-    },
-    {
-      "object": "LayoutButton INPUT",
-      "reason": "full"
-    },
-    {
-      "object": "LayoutSlider INPUT",
-      "reason": "full"
-    },
-    {
-      "object": "LayoutFlexibleBox DIV",
-      "reason": "geometry"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='thumb'",
-      "reason": "full"
-    }
-  ]
-}
-
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/feature-policy-permissions/external/wpt/mediacapture-streams/historical-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/virtual/feature-policy-permissions/external/wpt/mediacapture-streams/historical-expected.txt
new file mode 100644
index 0000000..21f1152
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/feature-policy-permissions/external/wpt/mediacapture-streams/historical-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+FAIL webkitMediaStream interface should not exist assert_false: expected false got true
+FAIL navigator.webkitGetUserMedia should not exist assert_false: expected false got true
+PASS navigator.mozGetUserMedia should not exist
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.png
index bb528ee..1064fbb7 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.txt
index 5ca85b6..bf59cdf 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.txt
@@ -24,11 +24,27 @@
           text run at (0,9) width 31: "/ 0:07"
     LayoutSlider {INPUT} at (108.05,15) size 48.95x2
       LayoutFlexibleBox {DIV} at (0,0) size 48.95x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 84.95x48
-          LayoutBlockFlow {DIV} at (48.95,0) size 36x48
     LayoutButton {INPUT} at (175,0) size 32x32
     LayoutSlider {INPUT} at (225,15) size 25x2
       LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
     LayoutButton {INPUT} at (268,0) size 32x32
+layer at (98,142) size 85x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 84.95x0
+layer at (116,141) size 49x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 48.95x2 [bgcolor=#DADADA]
+layer at (215,142) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+layer at (233,141) size 25x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (165,141) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (49,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (116,141) size 49x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 49x2 [bgcolor=#4285F4]
+layer at (233,141) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (233,141) size 25x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (147,118) size 36x48 backgroundClip at (8,126) size 300x32 clip at (8,126) size 300x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (48.95,-24) size 36x48
+layer at (240,118) size 36x48 backgroundClip at (8,126) size 300x32 clip at (8,126) size 300x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png
index 1ac4141..14720be 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.txt
index 126bd1c1..c0eeef7 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.txt
@@ -24,7 +24,15 @@
           text run at (0,9) width 31: "/ 0:09"
     LayoutSlider {INPUT} at (108.05,15) size 241.95x2
       LayoutFlexibleBox {DIV} at (0,0) size 241.95x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 277.95x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
 layer at (376,303) size 32x32
   LayoutButton {INPUT} at (368,0) size 32x32
+layer at (98,319) size 278x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 277.95x0
+layer at (116,318) size 242x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 241.95x2 [bgcolor=#DADADA]
+layer at (116,318) size 242x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 242x2 [bgcolor=#5A5A5A]
+layer at (116,318) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (98,295) size 36x48 backgroundClip at (8,303) size 400x32 clip at (8,303) size 400x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-expected.png
index 80ba53f..867a28f 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-expected.txt
index 126bd1c1..c0eeef7 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-expected.txt
@@ -24,7 +24,15 @@
           text run at (0,9) width 31: "/ 0:09"
     LayoutSlider {INPUT} at (108.05,15) size 241.95x2
       LayoutFlexibleBox {DIV} at (0,0) size 241.95x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 277.95x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
 layer at (376,303) size 32x32
   LayoutButton {INPUT} at (368,0) size 32x32
+layer at (98,319) size 278x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 277.95x0
+layer at (116,318) size 242x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 241.95x2 [bgcolor=#DADADA]
+layer at (116,318) size 242x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 242x2 [bgcolor=#5A5A5A]
+layer at (116,318) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (98,295) size 36x48 backgroundClip at (8,303) size 400x32 clip at (8,303) size 400x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering-expected.png
index 68a1145d..ca1b998 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/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/mac/virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering-expected.txt
index 657f77fa..16cf988 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering-expected.txt
@@ -29,16 +29,32 @@
           text run at (0,9) width 24: "0:00"
     LayoutSlider {INPUT} at (73.36,15) size 71.64x2
       LayoutFlexibleBox {DIV} at (0,0) size 71.64x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 107.64x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
     LayoutButton {INPUT} at (163,0) size 32x32
     LayoutSlider {INPUT} at (213,15) size 25x2
       LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
     LayoutButton {INPUT} at (288,0) size 32x32
 layer at (264,258) size 32x32
   LayoutButton {INPUT} at (256,0) size 32x32
+layer at (63,274) size 108x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 107.64x0
+layer at (81,273) size 72x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 71.64x2 [bgcolor=#DADADA]
+layer at (203,274) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+layer at (221,273) size 25x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (81,273) size 72x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 72x2 [bgcolor=#5A5A5A]
+layer at (81,273) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (221,273) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (221,273) size 25x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (63,250) size 36x48 backgroundClip at (8,258) size 320x32 clip at (8,258) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
+layer at (228,250) size 36x48 backgroundClip at (8,258) size 320x32 clip at (8,258) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
 layer at (8,294) size 320x240
   LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 320x240
     LayoutBlockFlow {DIV} at (0,208) size 320x32
@@ -53,16 +69,32 @@
           text run at (0,9) width 24: "0:00"
     LayoutSlider {INPUT} at (73.36,15) size 71.64x2
       LayoutFlexibleBox {DIV} at (0,0) size 71.64x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 107.64x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
     LayoutButton {INPUT} at (163,0) size 32x32
     LayoutSlider {INPUT} at (213,15) size 25x2
       LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
     LayoutButton {INPUT} at (288,0) size 32x32
 layer at (264,502) size 32x32
   LayoutButton {INPUT} at (256,0) size 32x32
+layer at (63,518) size 108x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 107.64x0
+layer at (81,517) size 72x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 71.64x2 [bgcolor=#DADADA]
+layer at (203,518) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+layer at (221,517) size 25x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (81,517) size 72x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 72x2 [bgcolor=#5A5A5A]
+layer at (81,517) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (221,517) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (221,517) size 25x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (63,494) size 36x48 backgroundClip at (8,502) size 320x32 clip at (8,502) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
+layer at (228,494) size 36x48 backgroundClip at (8,502) size 320x32 clip at (8,502) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
 layer at (8,538) size 320x240 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
   LayoutVideo (positioned) {VIDEO} at (8,538) size 320x240
 layer at (8,538) size 320x240 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
@@ -79,13 +111,29 @@
           text run at (0,9) width 24: "0:00"
     LayoutSlider {INPUT} at (73.36,15) size 71.64x2
       LayoutFlexibleBox {DIV} at (0,0) size 71.64x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 107.64x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
     LayoutButton {INPUT} at (163,0) size 32x32
     LayoutSlider {INPUT} at (213,15) size 25x2
       LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
     LayoutButton {INPUT} at (288,0) size 32x32
 layer at (264,746) size 32x32 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
   LayoutButton {INPUT} at (256,0) size 32x32
+layer at (63,762) size 108x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 107.64x0
+layer at (81,761) size 72x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 71.64x2 [bgcolor=#DADADA]
+layer at (203,762) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+layer at (221,761) size 25x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (81,761) size 72x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 72x2 [bgcolor=#5A5A5A]
+layer at (81,761) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (221,761) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (221,761) size 25x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (63,738) size 36x48 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
+layer at (228,738) size 36x48 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/video-overlay-cast-dark-rendering-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/video-overlay-cast-dark-rendering-expected.png
index 65da69a..0e8c2bd 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/video-overlay-cast-dark-rendering-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/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/virtual/new-remote-playback-pipeline/media/controls/video-overlay-cast-light-rendering-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/video-overlay-cast-light-rendering-expected.png
index 23d7968..360ea7a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/video-overlay-cast-light-rendering-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/video-overlay-cast-light-rendering-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/bluetooth/idl/idl-BluetoothDevice-expected.txt b/third_party/WebKit/LayoutTests/platform/win/bluetooth/idl/idl-BluetoothDevice-expected.txt
deleted file mode 100644
index aef11cd..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/bluetooth/idl/idl-BluetoothDevice-expected.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-CONSOLE MESSAGE: line 169: Web Bluetooth is experimental on this platform. See https://github.com/WebBluetoothCG/web-bluetooth/blob/gh-pages/implementation-status.md
-This is a testharness.js-based test.
-FAIL BluetoothDevice IDL test Test bug: need to pass exception to assert_throws()
-PASS BluetoothDevice attributes.
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/culling/filter-occlusion-blur-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/culling/filter-occlusion-blur-expected.png
deleted file mode 100644
index 46428a3..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/compositing/culling/filter-occlusion-blur-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-blur-hw-expected.png b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-blur-hw-expected.png
deleted file mode 100644
index c0ab7c9..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-blur-hw-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/filter-repaint-composited-fallback-crash-expected.png b/third_party/WebKit/LayoutTests/platform/win/css3/filters/filter-repaint-composited-fallback-crash-expected.png
deleted file mode 100644
index 85fde79..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/css3/filters/filter-repaint-composited-fallback-crash-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/filter-repaint-composited-fallback-expected.png b/third_party/WebKit/LayoutTests/platform/win/css3/filters/filter-repaint-composited-fallback-expected.png
deleted file mode 100644
index 85fde79..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/css3/filters/filter-repaint-composited-fallback-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/replaced/inline-box-wrapper-handover-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/replaced/inline-box-wrapper-handover-expected.png
deleted file mode 100644
index 5bd088a..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/fast/replaced/inline-box-wrapper-handover-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/replaced/inline-box-wrapper-handover-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/replaced/inline-box-wrapper-handover-expected.txt
deleted file mode 100644
index 8bd5134..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/fast/replaced/inline-box-wrapper-handover-expected.txt
+++ /dev/null
@@ -1,49 +0,0 @@
-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 {P} at (0,0) size 784x40
-        LayoutText {#text} at (0,0) size 242x19
-          text run at (0,0) width 242: "This test checks for a regression against "
-        LayoutInline {I} at (0,0) size 735x39
-          LayoutInline {A} at (0,0) size 350x19 [color=#0000EE]
-            LayoutText {#text} at (242,0) size 350x19
-              text run at (242,0) width 350: "http://bugzilla.opendarwin.org/show_bug.cgi?id=6276"
-          LayoutText {#text} at (591,0) size 735x39
-            text run at (591,0) width 5: " "
-            text run at (595,0) width 140: "Image thumbnails are"
-            text run at (0,20) width 197: "misplaced on forum.2ostrov.ru"
-        LayoutText {#text} at (196,20) size 5x19
-          text run at (196,20) width 5: "."
-      LayoutBlockFlow {HR} at (0,56) size 784x2 [border: (1px inset #EEEEEE)]
-      LayoutBlockFlow {P} at (0,74) size 784x20
-        LayoutText {#text} at (0,0) size 221x19
-          text run at (0,0) width 221: "Box 1 and box 2 should be identical."
-      LayoutBlockFlow (anonymous) at (0,110) size 784x20
-        LayoutText {#text} at (0,0) size 40x19
-          text run at (0,0) width 40: "Box 1:"
-      LayoutBlockFlow {DIV} at (0,130) size 67x87 [border: (1px solid #000000)]
-        LayoutBlockFlow {DIV} at (6,6) size 40x20 [bgcolor=#0000FF]
-        LayoutText {#text} at (46,11) size 15x19
-          text run at (46,11) width 15: " A"
-        LayoutBlockFlow {DIV} at (6,31) size 35x20 [bgcolor=#FF0000]
-        LayoutText {#text} at (41,36) size 14x19
-          text run at (41,36) width 14: " B"
-        LayoutBlockFlow {DIV} at (6,56) size 20x20 [bgcolor=#008000]
-        LayoutText {#text} at (26,61) size 15x19
-          text run at (26,61) width 15: " C"
-      LayoutBlockFlow (anonymous) at (0,217) size 784x40
-        LayoutBR {BR} at (0,0) size 0x19
-        LayoutText {#text} at (0,20) size 40x19
-          text run at (0,20) width 40: "Box 2:"
-      LayoutBlockFlow {DIV} at (0,257) size 67x87 [border: (1px solid #000000)]
-        LayoutBlockFlow {DIV} at (6,6) size 40x20 [bgcolor=#0000FF]
-        LayoutText {#text} at (46,11) size 15x19
-          text run at (46,11) width 15: " A"
-        LayoutBlockFlow {DIV} at (6,31) size 35x20 [bgcolor=#FF0000]
-        LayoutText {#text} at (41,36) size 14x19
-          text run at (41,36) width 14: " B"
-        LayoutBlockFlow {DIV} at (6,56) size 20x20 [bgcolor=#008000]
-        LayoutText {#text} at (26,61) size 15x19
-          text run at (26,61) width 15: " C"
diff --git a/third_party/WebKit/LayoutTests/platform/win/http/tests/media/video-buffered-range-contains-currentTime-expected.png b/third_party/WebKit/LayoutTests/platform/win/http/tests/media/video-buffered-range-contains-currentTime-expected.png
index 6ad8a86..7c9ef09 100644
--- a/third_party/WebKit/LayoutTests/platform/win/http/tests/media/video-buffered-range-contains-currentTime-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/http/tests/media/video-buffered-range-contains-currentTime-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/http/tests/media/video-buffered-range-contains-currentTime-expected.txt b/third_party/WebKit/LayoutTests/platform/win/http/tests/media/video-buffered-range-contains-currentTime-expected.txt
index b202525..3abc4b1 100644
--- a/third_party/WebKit/LayoutTests/platform/win/http/tests/media/video-buffered-range-contains-currentTime-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/http/tests/media/video-buffered-range-contains-currentTime-expected.txt
@@ -24,11 +24,27 @@
           text run at (0,8) width 30: "/ 0:07"
     LayoutSlider {INPUT} at (108,15) size 49x2
       LayoutFlexibleBox {DIV} at (0,0) size 49x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 85x48
-          LayoutBlockFlow {DIV} at (49,0) size 36x48
     LayoutButton {INPUT} at (175,0) size 32x32
     LayoutSlider {INPUT} at (225,15) size 25x2
       LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
     LayoutButton {INPUT} at (268,0) size 32x32
+layer at (98,142) size 85x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 85x0
+layer at (116,141) size 49x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 49x2 [bgcolor=#DADADA]
+layer at (215,142) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+layer at (233,141) size 25x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (165,141) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (49,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (116,141) size 49x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 49x2 [bgcolor=#4285F4]
+layer at (233,141) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (233,141) size 25x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (147,118) size 36x48 backgroundClip at (8,126) size 300x32 clip at (8,126) size 300x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (49,-24) size 36x48
+layer at (240,118) size 36x48 backgroundClip at (8,126) size 300x32 clip at (8,126) size 300x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-layer-filter-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-layer-filter-expected.png
deleted file mode 100644
index 3a67f62..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-layer-filter-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png
index c93bd88..6c77e23 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.txt b/third_party/WebKit/LayoutTests/platform/win/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.txt
index 8ae6e283..0624009 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.txt
@@ -24,7 +24,15 @@
           text run at (0,8) width 30: "/ 0:09"
     LayoutSlider {INPUT} at (108,15) size 242x2
       LayoutFlexibleBox {DIV} at (0,0) size 242x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 278x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
 layer at (376,303) size 32x32
   LayoutButton {INPUT} at (368,0) size 32x32
+layer at (98,319) size 278x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 278x0
+layer at (116,318) size 242x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 242x2 [bgcolor=#DADADA]
+layer at (116,318) size 242x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 242x2 [bgcolor=#5A5A5A]
+layer at (116,318) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (98,295) size 36x48 backgroundClip at (8,303) size 400x32 clip at (8,303) size 400x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/controls/paint-controls-webkit-appearance-none-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/controls/paint-controls-webkit-appearance-none-expected.png
index 200355d..9084584 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/controls/paint-controls-webkit-appearance-none-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/controls/paint-controls-webkit-appearance-none-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/controls/paint-controls-webkit-appearance-none-expected.txt b/third_party/WebKit/LayoutTests/platform/win/media/controls/paint-controls-webkit-appearance-none-expected.txt
index 8ae6e283..0624009 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/controls/paint-controls-webkit-appearance-none-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/media/controls/paint-controls-webkit-appearance-none-expected.txt
@@ -24,7 +24,15 @@
           text run at (0,8) width 30: "/ 0:09"
     LayoutSlider {INPUT} at (108,15) size 242x2
       LayoutFlexibleBox {DIV} at (0,0) size 242x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 278x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
 layer at (376,303) size 32x32
   LayoutButton {INPUT} at (368,0) size 32x32
+layer at (98,319) size 278x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 278x0
+layer at (116,318) size 242x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 242x2 [bgcolor=#DADADA]
+layer at (116,318) size 242x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 242x2 [bgcolor=#5A5A5A]
+layer at (116,318) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (98,295) size 36x48 backgroundClip at (8,303) size 400x32 clip at (8,303) size 400x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/controls/video-controls-with-cast-rendering-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/controls/video-controls-with-cast-rendering-expected.png
index d2f382e..5ba393f 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/controls/video-controls-with-cast-rendering-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/controls/video-controls-with-cast-rendering-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/controls/video-controls-with-cast-rendering-expected.txt b/third_party/WebKit/LayoutTests/platform/win/media/controls/video-controls-with-cast-rendering-expected.txt
index f443612f..0938c6d0 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/controls/video-controls-with-cast-rendering-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/media/controls/video-controls-with-cast-rendering-expected.txt
@@ -29,16 +29,32 @@
           text run at (0,8) width 24: "0:00"
     LayoutSlider {INPUT} at (74,15) size 71x2
       LayoutFlexibleBox {DIV} at (0,0) size 71x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 107x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
     LayoutButton {INPUT} at (163,0) size 32x32
     LayoutSlider {INPUT} at (213,15) size 25x2
       LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
     LayoutButton {INPUT} at (288,0) size 32x32
 layer at (264,260) size 32x32
   LayoutButton {INPUT} at (256,0) size 32x32
+layer at (64,276) size 107x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 107x0
+layer at (82,275) size 71x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 71x2 [bgcolor=#DADADA]
+layer at (203,276) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+layer at (221,275) size 25x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (82,275) size 71x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 71x2 [bgcolor=#5A5A5A]
+layer at (82,275) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (221,275) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (221,275) size 25x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (64,252) size 36x48 backgroundClip at (8,260) size 320x32 clip at (8,260) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
+layer at (228,252) size 36x48 backgroundClip at (8,260) size 320x32 clip at (8,260) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
 layer at (8,297) size 320x240
   LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 320x240
     LayoutBlockFlow {DIV} at (0,208) size 320x32
@@ -53,16 +69,32 @@
           text run at (0,8) width 24: "0:00"
     LayoutSlider {INPUT} at (74,15) size 71x2
       LayoutFlexibleBox {DIV} at (0,0) size 71x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 107x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
     LayoutButton {INPUT} at (163,0) size 32x32
     LayoutSlider {INPUT} at (213,15) size 25x2
       LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
     LayoutButton {INPUT} at (288,0) size 32x32
 layer at (264,505) size 32x32
   LayoutButton {INPUT} at (256,0) size 32x32
+layer at (64,521) size 107x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 107x0
+layer at (82,520) size 71x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 71x2 [bgcolor=#DADADA]
+layer at (203,521) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+layer at (221,520) size 25x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (82,520) size 71x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 71x2 [bgcolor=#5A5A5A]
+layer at (82,520) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (221,520) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (221,520) size 25x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (64,497) size 36x48 backgroundClip at (8,505) size 320x32 clip at (8,505) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
+layer at (228,497) size 36x48 backgroundClip at (8,505) size 320x32 clip at (8,505) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
 layer at (8,542) size 320x240 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
   LayoutVideo (positioned) {VIDEO} at (8,542) size 320x240
 layer at (8,542) size 320x240 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
@@ -79,13 +111,29 @@
           text run at (0,8) width 24: "0:00"
     LayoutSlider {INPUT} at (74,15) size 71x2
       LayoutFlexibleBox {DIV} at (0,0) size 71x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 107x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
     LayoutButton {INPUT} at (163,0) size 32x32
     LayoutSlider {INPUT} at (213,15) size 25x2
       LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
     LayoutButton {INPUT} at (288,0) size 32x32
 layer at (264,750) size 32x32 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
   LayoutButton {INPUT} at (256,0) size 32x32
+layer at (64,766) size 107x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 107x0
+layer at (82,765) size 71x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 71x2 [bgcolor=#DADADA]
+layer at (203,766) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+layer at (221,765) size 25x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (82,765) size 71x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 71x2 [bgcolor=#5A5A5A]
+layer at (82,765) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (221,765) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (221,765) size 25x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (64,742) size 36x48 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
+layer at (228,742) size 36x48 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/media-document-audio-repaint-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/media-document-audio-repaint-expected.png
index 1b193a5..e723f9c2 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/media-document-audio-repaint-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/media-document-audio-repaint-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/media-document-audio-repaint-expected.txt b/third_party/WebKit/LayoutTests/platform/win/media/media-document-audio-repaint-expected.txt
index a779023..edbb277 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/media-document-audio-repaint-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/media/media-document-audio-repaint-expected.txt
@@ -36,10 +36,26 @@
               text run at (0,8) width 30: "/ 0:01"
         LayoutSlider {INPUT} at (108,15) size 81x2
           LayoutFlexibleBox {DIV} at (0,0) size 81x2
-            LayoutBlockFlow {DIV} at (-18,-23) size 117x48
-              LayoutBlockFlow {DIV} at (40.48,0) size 36x48
         LayoutButton {INPUT} at (207,0) size 32x32
         LayoutSlider {INPUT} at (257,15) size 25x2
           LayoutFlexibleBox {DIV} at (0,0) size 25x2
-            LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-              LayoutBlockFlow {DIV} at (25,0) size 36x48
+    layer at (130,150) size 117x0
+      LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 117x0
+    layer at (148,149) size 81x2
+      LayoutBlockFlow (positioned) {DIV} at (18,-1) size 81x2 [bgcolor=#DADADA]
+    layer at (279,150) size 61x0
+      LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+    layer at (297,149) size 25x2
+      LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+    layer at (188,149) size 40x2
+      LayoutBlockFlow (positioned) zI: 1 {DIV} at (40,0) size 40x2 [bgcolor=#5A5A5A]
+    layer at (148,149) size 40x2
+      LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 40x2 [bgcolor=#4285F4]
+    layer at (297,149) size 0x2
+      LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+    layer at (297,149) size 25x2
+      LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+    layer at (170,126) size 36x48 backgroundClip at (40,134) size 300x32 clip at (40,134) size 300x32
+      LayoutBlockFlow (positioned) zI: 2 {DIV} at (40.48,-24) size 36x48
+    layer at (304,126) size 36x48 backgroundClip at (40,134) size 300x32 clip at (40,134) size 300x32
+      LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
index 7ea961f8..c77aa72 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
@@ -49,10 +49,6 @@
       "reason": "subtree"
     },
     {
-      "object": "HorizontalScrollbar",
-      "reason": "scroll control"
-    },
-    {
       "object": "Caret",
       "reason": "caret"
     },
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/invalidate-caret-in-non-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/invalidate-caret-in-non-composited-scrolling-container-expected.txt
index 7ea961f8..c77aa72 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/invalidate-caret-in-non-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/invalidate-caret-in-non-composited-scrolling-container-expected.txt
@@ -49,10 +49,6 @@
       "reason": "subtree"
     },
     {
-      "object": "HorizontalScrollbar",
-      "reason": "scroll control"
-    },
-    {
       "object": "Caret",
       "reason": "caret"
     },
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
index 1facb06..a6c6f7b4 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
@@ -46,10 +46,6 @@
       "reason": "subtree"
     },
     {
-      "object": "HorizontalScrollbar",
-      "reason": "scroll control"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "subtree"
     },
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
index 1facb06..a6c6f7b4 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
@@ -46,10 +46,6 @@
       "reason": "subtree"
     },
     {
-      "object": "HorizontalScrollbar",
-      "reason": "scroll control"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "subtree"
     },
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/video-mute-repaint-expected.txt b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/video-mute-repaint-expected.txt
deleted file mode 100644
index fae52f9..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/video-mute-repaint-expected.txt
+++ /dev/null
@@ -1,106 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF",
-      "paintInvalidations": [
-        {
-          "object": "LayoutBlockFlow BODY",
-          "rect": [8, 8, 784, 530],
-          "reason": "geometry"
-        }
-      ]
-    },
-    {
-      "name": "LayoutVideo VIDEO id='v'",
-      "position": [8, 8],
-      "bounds": [700, 525],
-      "drawsContent": false
-    },
-    {
-      "name": "Squashing Containment Layer",
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutFlexibleBox (relative positioned) DIV class='phase-ready state-stopped'",
-      "position": [8, 8],
-      "bounds": [700, 525],
-      "paintInvalidations": [
-        {
-          "object": "LayoutFlexibleBox (relative positioned) DIV class='phase-ready state-stopped'",
-          "rect": [0, 0, 700, 525],
-          "reason": "geometry"
-        }
-      ]
-    },
-    {
-      "name": "Squashing Layer (first squashed layer: LayoutFlexibleBox (relative positioned) DIV)",
-      "position": [8, 8],
-      "bounds": [700, 525],
-      "paintInvalidations": [
-        {
-          "object": "LayoutFlexibleBox DIV",
-          "rect": [580, 508, 70, 2],
-          "reason": "geometry"
-        },
-        {
-          "object": "LayoutSlider INPUT",
-          "rect": [580, 508, 70, 2],
-          "reason": "full"
-        },
-        {
-          "object": "LayoutBlockFlow DIV id='thumb'",
-          "rect": [632, 485, 36, 48],
-          "reason": "full"
-        },
-        {
-          "object": "LayoutBlockFlow DIV id='thumb'",
-          "rect": [562, 485, 36, 48],
-          "reason": "full"
-        },
-        {
-          "object": "LayoutButton INPUT",
-          "rect": [530, 493, 32, 32],
-          "reason": "full"
-        }
-      ]
-    }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "geometry"
-    },
-    {
-      "object": "RootInlineBox",
-      "reason": "geometry"
-    },
-    {
-      "object": "LayoutVideo VIDEO id='v'",
-      "reason": "style change"
-    },
-    {
-      "object": "LayoutFlexibleBox (relative positioned) DIV class='phase-ready state-stopped'",
-      "reason": "geometry"
-    },
-    {
-      "object": "LayoutButton INPUT",
-      "reason": "full"
-    },
-    {
-      "object": "LayoutSlider INPUT",
-      "reason": "full"
-    },
-    {
-      "object": "LayoutFlexibleBox DIV",
-      "reason": "geometry"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='thumb'",
-      "reason": "full"
-    }
-  ]
-}
-
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/video-unmute-repaint-expected.txt b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/video-unmute-repaint-expected.txt
deleted file mode 100644
index ee56a55..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/video-unmute-repaint-expected.txt
+++ /dev/null
@@ -1,106 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF",
-      "paintInvalidations": [
-        {
-          "object": "LayoutBlockFlow (anonymous)",
-          "rect": [8, 8, 784, 530],
-          "reason": "geometry"
-        }
-      ]
-    },
-    {
-      "name": "LayoutVideo VIDEO id='v'",
-      "position": [8, 8],
-      "bounds": [700, 525],
-      "drawsContent": false
-    },
-    {
-      "name": "Squashing Containment Layer",
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutFlexibleBox (relative positioned) DIV class='phase-ready state-stopped'",
-      "position": [8, 8],
-      "bounds": [700, 525],
-      "paintInvalidations": [
-        {
-          "object": "LayoutFlexibleBox (relative positioned) DIV class='phase-ready state-stopped'",
-          "rect": [0, 0, 700, 525],
-          "reason": "geometry"
-        }
-      ]
-    },
-    {
-      "name": "Squashing Layer (first squashed layer: LayoutFlexibleBox (relative positioned) DIV)",
-      "position": [8, 8],
-      "bounds": [700, 525],
-      "paintInvalidations": [
-        {
-          "object": "LayoutFlexibleBox DIV",
-          "rect": [580, 508, 70, 2],
-          "reason": "geometry"
-        },
-        {
-          "object": "LayoutSlider INPUT",
-          "rect": [580, 508, 70, 2],
-          "reason": "full"
-        },
-        {
-          "object": "LayoutBlockFlow DIV id='thumb'",
-          "rect": [597, 485, 36, 48],
-          "reason": "full"
-        },
-        {
-          "object": "LayoutBlockFlow DIV id='thumb'",
-          "rect": [562, 485, 36, 48],
-          "reason": "full"
-        },
-        {
-          "object": "LayoutButton INPUT",
-          "rect": [530, 493, 32, 32],
-          "reason": "full"
-        }
-      ]
-    }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "LayoutBlockFlow (anonymous)",
-      "reason": "geometry"
-    },
-    {
-      "object": "RootInlineBox",
-      "reason": "geometry"
-    },
-    {
-      "object": "LayoutVideo VIDEO id='v'",
-      "reason": "style change"
-    },
-    {
-      "object": "LayoutFlexibleBox (relative positioned) DIV class='phase-ready state-stopped'",
-      "reason": "geometry"
-    },
-    {
-      "object": "LayoutButton INPUT",
-      "reason": "full"
-    },
-    {
-      "object": "LayoutSlider INPUT",
-      "reason": "full"
-    },
-    {
-      "object": "LayoutFlexibleBox DIV",
-      "reason": "geometry"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='thumb'",
-      "reason": "full"
-    }
-  ]
-}
-
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
deleted file mode 100644
index fffa76b..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-composite-video-shadow-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-composite-video-shadow-expected.png
deleted file mode 100644
index 748d85e..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-composite-video-shadow-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.png
index 6ad8a86..7c9ef09 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.txt b/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.txt
index b202525..3abc4b1 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.txt
@@ -24,11 +24,27 @@
           text run at (0,8) width 30: "/ 0:07"
     LayoutSlider {INPUT} at (108,15) size 49x2
       LayoutFlexibleBox {DIV} at (0,0) size 49x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 85x48
-          LayoutBlockFlow {DIV} at (49,0) size 36x48
     LayoutButton {INPUT} at (175,0) size 32x32
     LayoutSlider {INPUT} at (225,15) size 25x2
       LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
     LayoutButton {INPUT} at (268,0) size 32x32
+layer at (98,142) size 85x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 85x0
+layer at (116,141) size 49x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 49x2 [bgcolor=#DADADA]
+layer at (215,142) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+layer at (233,141) size 25x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (165,141) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (49,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (116,141) size 49x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 49x2 [bgcolor=#4285F4]
+layer at (233,141) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (233,141) size 25x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (147,118) size 36x48 backgroundClip at (8,126) size 300x32 clip at (8,126) size 300x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (49,-24) size 36x48
+layer at (240,118) size 36x48 backgroundClip at (8,126) size 300x32 clip at (8,126) size 300x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png
index c93bd88..6c77e23 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.txt b/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.txt
index 8ae6e283..0624009 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-custom-bg-expected.txt
@@ -24,7 +24,15 @@
           text run at (0,8) width 30: "/ 0:09"
     LayoutSlider {INPUT} at (108,15) size 242x2
       LayoutFlexibleBox {DIV} at (0,0) size 242x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 278x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
 layer at (376,303) size 32x32
   LayoutButton {INPUT} at (368,0) size 32x32
+layer at (98,319) size 278x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 278x0
+layer at (116,318) size 242x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 242x2 [bgcolor=#DADADA]
+layer at (116,318) size 242x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 242x2 [bgcolor=#5A5A5A]
+layer at (116,318) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (98,295) size 36x48 backgroundClip at (8,303) size 400x32 clip at (8,303) size 400x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-expected.png
index 200355d..9084584 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-expected.txt b/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-expected.txt
index 8ae6e283..0624009 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/paint-controls-webkit-appearance-none-expected.txt
@@ -24,7 +24,15 @@
           text run at (0,8) width 30: "/ 0:09"
     LayoutSlider {INPUT} at (108,15) size 242x2
       LayoutFlexibleBox {DIV} at (0,0) size 242x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 278x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
 layer at (376,303) size 32x32
   LayoutButton {INPUT} at (368,0) size 32x32
+layer at (98,319) size 278x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 278x0
+layer at (116,318) size 242x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 242x2 [bgcolor=#DADADA]
+layer at (116,318) size 242x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 242x2 [bgcolor=#5A5A5A]
+layer at (116,318) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (98,295) size 36x48 backgroundClip at (8,303) size 400x32 clip at (8,303) size 400x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering-expected.png
index d2f382e..5ba393f 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/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/win/virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering-expected.txt b/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering-expected.txt
index f443612f..0938c6d0 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering-expected.txt
@@ -29,16 +29,32 @@
           text run at (0,8) width 24: "0:00"
     LayoutSlider {INPUT} at (74,15) size 71x2
       LayoutFlexibleBox {DIV} at (0,0) size 71x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 107x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
     LayoutButton {INPUT} at (163,0) size 32x32
     LayoutSlider {INPUT} at (213,15) size 25x2
       LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
     LayoutButton {INPUT} at (288,0) size 32x32
 layer at (264,260) size 32x32
   LayoutButton {INPUT} at (256,0) size 32x32
+layer at (64,276) size 107x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 107x0
+layer at (82,275) size 71x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 71x2 [bgcolor=#DADADA]
+layer at (203,276) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+layer at (221,275) size 25x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (82,275) size 71x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 71x2 [bgcolor=#5A5A5A]
+layer at (82,275) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (221,275) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (221,275) size 25x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (64,252) size 36x48 backgroundClip at (8,260) size 320x32 clip at (8,260) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
+layer at (228,252) size 36x48 backgroundClip at (8,260) size 320x32 clip at (8,260) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
 layer at (8,297) size 320x240
   LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 320x240
     LayoutBlockFlow {DIV} at (0,208) size 320x32
@@ -53,16 +69,32 @@
           text run at (0,8) width 24: "0:00"
     LayoutSlider {INPUT} at (74,15) size 71x2
       LayoutFlexibleBox {DIV} at (0,0) size 71x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 107x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
     LayoutButton {INPUT} at (163,0) size 32x32
     LayoutSlider {INPUT} at (213,15) size 25x2
       LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
     LayoutButton {INPUT} at (288,0) size 32x32
 layer at (264,505) size 32x32
   LayoutButton {INPUT} at (256,0) size 32x32
+layer at (64,521) size 107x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 107x0
+layer at (82,520) size 71x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 71x2 [bgcolor=#DADADA]
+layer at (203,521) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+layer at (221,520) size 25x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (82,520) size 71x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 71x2 [bgcolor=#5A5A5A]
+layer at (82,520) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (221,520) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (221,520) size 25x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (64,497) size 36x48 backgroundClip at (8,505) size 320x32 clip at (8,505) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
+layer at (228,497) size 36x48 backgroundClip at (8,505) size 320x32 clip at (8,505) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
 layer at (8,542) size 320x240 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
   LayoutVideo (positioned) {VIDEO} at (8,542) size 320x240
 layer at (8,542) size 320x240 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
@@ -79,13 +111,29 @@
           text run at (0,8) width 24: "0:00"
     LayoutSlider {INPUT} at (74,15) size 71x2
       LayoutFlexibleBox {DIV} at (0,0) size 71x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 107x48
-          LayoutBlockFlow {DIV} at (0,0) size 36x48
     LayoutButton {INPUT} at (163,0) size 32x32
     LayoutSlider {INPUT} at (213,15) size 25x2
       LayoutFlexibleBox {DIV} at (0,0) size 25x2
-        LayoutBlockFlow {DIV} at (-18,-23) size 61x48
-          LayoutBlockFlow {DIV} at (25,0) size 36x48
     LayoutButton {INPUT} at (288,0) size 32x32
 layer at (264,750) size 32x32 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
   LayoutButton {INPUT} at (256,0) size 32x32
+layer at (64,766) size 107x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 107x0
+layer at (82,765) size 71x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 71x2 [bgcolor=#DADADA]
+layer at (203,766) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 61x0
+layer at (221,765) size 25x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (82,765) size 71x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 71x2 [bgcolor=#5A5A5A]
+layer at (82,765) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (221,765) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (221,765) size 25x2 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (64,742) size 36x48 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
+layer at (228,742) size 36x48 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
diff --git a/third_party/WebKit/LayoutTests/platform/win7/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.png b/third_party/WebKit/LayoutTests/platform/win7/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.png
new file mode 100644
index 0000000..6ad8a86
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win7/virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/reporting-observer/intervention.html b/third_party/WebKit/LayoutTests/reporting-observer/intervention.html
index 6e614f81..32139786 100644
--- a/third_party/WebKit/LayoutTests/reporting-observer/intervention.html
+++ b/third_party/WebKit/LayoutTests/reporting-observer/intervention.html
@@ -1,9 +1,32 @@
 <!doctype html>
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
+<script src="resources/intervention.js"></script>
 
 <div id="target" style="padding: 10px; background-color: blue;">
-<p>Testing intervention reports and ReportingObserver</p>
+  <p>Testing intervention reports and ReportingObserver</p>
 </div>
 
-<script src="resources/intervention.js"></script>
+<script>
+async_test(function(test) {
+  var observer = new ReportingObserver(function(reports, observer) {
+    test.step(function() {
+      assert_equals(reports.length, 1);
+
+      // Ensure that the contents of the report are valid.
+      assert_equals(reports[0].type, "intervention");
+      assert_true(reports[0].url.endsWith(
+          "reporting-observer/intervention.html"));
+      assert_true(reports[0].body.sourceFile.endsWith(
+          "reporting-observer/resources/intervention.js"));
+      assert_equals(typeof reports[0].body.lineNumber, "number");
+      assert_equals(typeof reports[0].body.message, "string");
+    });
+
+    test.done();
+  });
+  observer.observe();
+
+  causeIntervention();
+}, "Intervention report");
+</script>
diff --git a/third_party/WebKit/LayoutTests/reporting-observer/reporting-api.html b/third_party/WebKit/LayoutTests/reporting-observer/reporting-api.html
index 647ad935..ad3f886e 100644
--- a/third_party/WebKit/LayoutTests/reporting-observer/reporting-api.html
+++ b/third_party/WebKit/LayoutTests/reporting-observer/reporting-api.html
@@ -3,6 +3,12 @@
 <script src="../resources/testharnessreport.js"></script>
 <script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
 <script src="file:///gen/third_party/WebKit/public/platform/reporting.mojom.js"></script>
+<script src="resources/intervention.js"></script>
+
+<div id="target" style="padding: 10px; background-color: blue;">
+  <p>Testing Reporting API.</p>
+</div>
+
 <script>
 // Mock implementation of ReportingServiceProxy.
 // |promise| property is always a promise for the next report to be queued.
@@ -27,6 +33,11 @@
     this.resolve([url, message, sourceFile, lineNumber]);
     this.resetPromise();
   }
+
+  async queueInterventionReport(url, message, sourceFile, lineNumber) {
+    this.resolve([url, message, sourceFile, lineNumber]);
+    this.resetPromise();
+  }
 }
 
 // Make an instance and have it receive the request.
@@ -41,11 +52,26 @@
   // Use a deprecated feature.
   window.webkitStorageInfo;
 
-  // Ensure the report is generated and routed to the mojo interface.
+  // Ensure the deprecation report is generated and routed to the reporting mojo
+  // interface.
   let [url, message, sourceFile, lineNumber] = await promise;
   assert_true(url.url.endsWith("reporting-observer/reporting-api.html"));
   assert_equals(typeof message, "string");
   assert_true(sourceFile.endsWith("reporting-observer/reporting-api.html"));
   assert_equals(typeof lineNumber, "number");
 }, "Deprecation report");
+
+promise_test(async () => {
+  // Cause and wait for an intervention.
+  let promise = proxy.promise;
+  causeIntervention();
+
+  // Ensure the intervention report is generated and routed to the reporting
+  // mojo interface.
+  let [url, message, sourceFile, lineNumber] = await promise;
+  assert_true(url.url.endsWith("reporting-observer/reporting-api.html"));
+  assert_equals(typeof message, "string");
+  assert_true(sourceFile.endsWith("reporting-observer/resources/intervention.js"));
+  assert_equals(typeof lineNumber, "number");
+}, "Intervention report");
 </script>
diff --git a/third_party/WebKit/LayoutTests/reporting-observer/resources/intervention.js b/third_party/WebKit/LayoutTests/reporting-observer/resources/intervention.js
index 09796d8..cf8c2fc 100644
--- a/third_party/WebKit/LayoutTests/reporting-observer/resources/intervention.js
+++ b/third_party/WebKit/LayoutTests/reporting-observer/resources/intervention.js
@@ -1,31 +1,11 @@
-async_test(function(test) {
-  var observer = new ReportingObserver(function(reports, observer) {
-    test.step(function() {
-      assert_equals(reports.length, 1);
-
-      // Ensure that the contents of the report are valid.
-      assert_equals(report.type, "intervention");
-      assert_true(report.url.endsWith(
-          "reporting-observer/intervention.html"));
-      assert_true(report.body.sourceFile.endsWith(
-          "reporting-observer/resources/intervention.js"));
-      assert_equals(typeof reports[0].body.lineNumber, "number");
-      assert_equals(typeof reports[0].body.message, "string");
-    });
-
-    test.done();
-  });
-  observer.observe();
-
-  // Cause an intervention.
-
+function causeIntervention() {
   var target = document.getElementById('target');
   var rect = target.getBoundingClientRect();
   var targetX = rect.left + rect.width / 2;
   var targetY = rect.top + rect.height / 2;
+
   document.body.addEventListener('touchstart', function(e) {
     e.preventDefault();
-    test.done();
   });
 
   var touches = [new Touch({identifier: 1, clientX: targetX, clientY: targetY, target: target})];
@@ -38,10 +18,8 @@
   };
   var event = new TouchEvent('touchstart', touchEventInit);
 
-
   var deadline = performance.now() + 100;
   while (performance.now() < deadline) {};
 
-
   document.body.dispatchEvent(event);
-}, "Intervention report");
+}
diff --git a/third_party/WebKit/LayoutTests/resources/bluetooth/requestDevice-in-iframe.html b/third_party/WebKit/LayoutTests/resources/bluetooth/requestDevice-in-iframe.html
index 870e7a8..f392b69 100644
--- a/third_party/WebKit/LayoutTests/resources/bluetooth/requestDevice-in-iframe.html
+++ b/third_party/WebKit/LayoutTests/resources/bluetooth/requestDevice-in-iframe.html
@@ -1,21 +1,25 @@
 <!DOCTYPE html>
 <script>
-  window.onmessage = messageEvent => {
-    // For requestDevice to work, 'Go' should be sent while
-    // handling a user gesture.
-    if (messageEvent.data === 'Go') {
-      navigator.bluetooth.requestDevice({
-        filters: [{services: ['generic_access']}]
-      }).then(device => {
-        if (device.constructor.name === "BluetoothDevice") {
-          parent.postMessage('Success', '*');
-        } else {
-          parent.postMessage('FAIL: requestDevice in iframe returned ' + device, '*');
-        }
-      }).catch(err => {
-        parent.postMessage(err.name + ': ' + err.message, '*');
-      });
-    }
-  };
-  parent.postMessage("Ready", "*");
+window.onmessage = messageEvent => {
+  // For requestDevice to work, 'Go' should be sent while
+  // handling a user gesture.
+  if (messageEvent.data !== 'Go') {
+    consele.error(messageEvent.data);
+  }
+
+  navigator.bluetooth.requestDevice({
+    filters: [{services: ['generic_access']}],
+  })
+    .then(device => {
+      if (device.constructor.name === "BluetoothDevice") {
+        parent.postMessage('Success', '*');
+      } else {
+        parent.postMessage(
+            'FAIL: requestDevice in iframe returned ' + device, '*');
+      }
+    }).catch(err => {
+      parent.postMessage(err.name + ': ' + err.message, '*');
+    });
+};
+parent.postMessage("Ready", "*");
 </script>
diff --git a/third_party/WebKit/LayoutTests/resources/bluetooth/web-bluetooth-test.js b/third_party/WebKit/LayoutTests/resources/bluetooth/web-bluetooth-test.js
index a37ca6a..d752829 100644
--- a/third_party/WebKit/LayoutTests/resources/bluetooth/web-bluetooth-test.js
+++ b/third_party/WebKit/LayoutTests/resources/bluetooth/web-bluetooth-test.js
@@ -127,6 +127,12 @@
       return new FakeCentral(fake_central_ptr);
     }
 
+    // Returns true if there are no pending responses.
+    async allResponsesConsumed() {
+      let {consumed} = await this.fake_bluetooth_ptr_.allResponsesConsumed();
+      return consumed;
+    }
+
     async initFakeBluetoothInterfacePtr_() {
       if (typeof this.fake_bluetooth_ptr_ !== 'undefined') {
         return this.fake_bluetooth_ptr_;
diff --git a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-linear-rgb.html b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-linear-rgb.html
index 27de209..6c80522 100644
--- a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-linear-rgb.html
+++ b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-linear-rgb.html
@@ -258,26 +258,32 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 // HTMLImageElement - Opaque SRGB
+// File formats: Bitmap, GIF, ICO, JPEG, PNG, WEBP
 promise_test(function() {
-    return new Promise((resolve, reject) => {
-        var image = new Image();
-        image.onload = function() {
-            resolve(image);
-        }
-        image.src = 'resources/pattern-srgb.png'
-    }).then(testImageBitmapOpaque);
-}, 'createImageBitmap in linear RGB from an opaque SRGB HTMLImageElement with resize.');
+    return Promise.all(['bmp', 'gif', 'ico', 'jpg', 'png', 'webp'].map(
+        ext => new Promise((resolve,reject) => {
+            var image = new Image();
+            image.onload = function() {
+                resolve(image);
+            }
+            image.src = 'resources/pattern-srgb.' + ext;
+        }).then(testImageBitmapOpaque)));
+}, 'createImageBitmap in linear RGB from an opaque SRGB HTMLImageElement (BMP, \
+GIF, ICO, JPG, PNG, WEBP) with resize.');
 
 // HTMLImageElement - Transparent SRGB
+// File formats: Bitmap, GIF, ICO, PNG, WEBP
 promise_test(function() {
-    return new Promise((resolve, reject) => {
-        var image = new Image();
-        image.onload = function() {
-            resolve(image);
-        }
-        image.src = 'resources/pattern-srgb-transparent.png'
-    }).then(testImageBitmapTransparent);
-}, 'createImageBitmap in linear RGB from a transparent SRGB HTMLImageElement with resize.');
+    return Promise.all(['bmp', 'ico', 'png', 'webp'].map(
+        ext => new Promise((resolve,reject) => {
+            var image = new Image();
+            image.onload = function() {
+                resolve(image);
+            }
+            image.src = 'resources/pattern-srgb-transparent.' + ext;
+        }).then(testImageBitmapTransparent)));
+}, 'createImageBitmap in linear RGB from a transparent SRGB HTMLImageElement \
+(BMP, ICO, PNG, WEBP) with resize.');
 
 // TODO(zakerinasab): crbug.com/668547
 // Add at least two more test scenarios for loading the image element from P3
diff --git a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-p3.html b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-p3.html
index 7e17f78..ee4a6ddb 100644
--- a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-p3.html
+++ b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-p3.html
@@ -240,26 +240,32 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 // HTMLImageElement - Opaque SRGB
+// File formats: Bitmap, GIF, ICO, JPEG, PNG, WEBP
 promise_test(function() {
-    return new Promise((resolve, reject) => {
-        var image = new Image();
-        image.onload = function() {
-            resolve(image);
-        }
-        image.src = 'resources/pattern-srgb.png'
-    }).then(testImageBitmapOpaque);
-}, 'createImageBitmap in P3 from an opaque SRGB HTMLImageElement with resize.');
+    return Promise.all(['bmp', 'gif', 'ico', 'jpg', 'png', 'webp'].map(
+        ext => new Promise((resolve,reject) => {
+            var image = new Image();
+            image.onload = function() {
+                resolve(image);
+            }
+            image.src = 'resources/pattern-srgb.' + ext;
+        }).then(testImageBitmapOpaque)));
+}, 'createImageBitmap in P3 from an opaque SRGB HTMLImageElement (BMP, GIF, \
+ICO, JPG, PNG, WEBP) with resize.');
 
 // HTMLImageElement - Transparent SRGB
+// File formats: Bitmap, GIF, ICO, PNG, WEBP
 promise_test(function() {
-    return new Promise((resolve, reject) => {
-        var image = new Image();
-        image.onload = function() {
-            resolve(image);
-        }
-        image.src = 'resources/pattern-srgb-transparent.png'
-    }).then(testImageBitmapTransparent);
-}, 'createImageBitmap in P3 from a transparent SRGB HTMLImageElement with resize.');
+    return Promise.all(['bmp', 'ico', 'png', 'webp'].map(
+        ext => new Promise((resolve,reject) => {
+            var image = new Image();
+            image.onload = function() {
+                resolve(image);
+            }
+            image.src = 'resources/pattern-srgb-transparent.' + ext;
+        }).then(testImageBitmapTransparent)));
+}, 'createImageBitmap in P3 from a transparent SRGB HTMLImageElement (BMP, \
+ICO, PNG, WEBP) with resize.');
 
 // TODO(zakerinasab): crbug.com/668547
 // Add at least two more test scenarios for loading the image element from P3
diff --git a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-rec2020.html b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-rec2020.html
index 0cf6412..8abd8c5 100644
--- a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-rec2020.html
+++ b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-rec2020.html
@@ -254,26 +254,32 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 // HTMLImageElement - Opaque SRGB
+// File formats: Bitmap, GIF, ICO, JPEG, PNG, WEBP
 promise_test(function() {
-    return new Promise((resolve, reject) => {
-        var image = new Image();
-        image.onload = function() {
-            resolve(image);
-        }
-        image.src = 'resources/pattern-srgb.png'
-    }).then(testImageBitmapOpaque);
-}, 'createImageBitmap in Rec2020 from an opaque SRGB HTMLImageElement with resize.');
+    return Promise.all(['bmp', 'gif', 'ico', 'jpg', 'png', 'webp'].map(
+        ext => new Promise((resolve,reject) => {
+            var image = new Image();
+            image.onload = function() {
+                resolve(image);
+            }
+            image.src = 'resources/pattern-srgb.' + ext;
+        }).then(testImageBitmapOpaque)));
+}, 'createImageBitmap in Rec2020 from an opaque SRGB HTMLImageElement (BMP, \
+GIF, ICO, JPG, PNG, WEBP) with resize.');
 
 // HTMLImageElement - Transparent SRGB
+// File formats: Bitmap, GIF, ICO, PNG, WEBP
 promise_test(function() {
-    return new Promise((resolve, reject) => {
-        var image = new Image();
-        image.onload = function() {
-            resolve(image);
-        }
-        image.src = 'resources/pattern-srgb-transparent.png'
-    }).then(testImageBitmapTransparent);
-}, 'createImageBitmap in Rec2020 from a transparent SRGB HTMLImageElement with resize.');
+    return Promise.all(['bmp', 'ico', 'png', 'webp'].map(
+        ext => new Promise((resolve,reject) => {
+            var image = new Image();
+            image.onload = function() {
+                resolve(image);
+            }
+            image.src = 'resources/pattern-srgb-transparent.' + ext;
+        }).then(testImageBitmapTransparent)));
+}, 'createImageBitmap in Rec2020 from a transparent SRGB HTMLImageElement (BMP, \
+ICO, PNG, WEBP) with resize.');
 
 // TODO(zakerinasab): crbug.com/668547
 // Add at least two more test scenarios for loading the image element from P3
diff --git a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb-transparent.bmp b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb-transparent.bmp
new file mode 100644
index 0000000..9c9561c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb-transparent.bmp
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb-transparent.ico b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb-transparent.ico
new file mode 100644
index 0000000..87e8ff4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb-transparent.ico
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb-transparent.webp b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb-transparent.webp
new file mode 100644
index 0000000..9256460
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb-transparent.webp
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb.bmp b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb.bmp
new file mode 100644
index 0000000..465d203
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb.bmp
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb.gif b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb.gif
new file mode 100644
index 0000000..25bcefb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb.gif
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb.ico b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb.ico
new file mode 100644
index 0000000..e5375826
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb.ico
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb.jpg b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb.jpg
new file mode 100644
index 0000000..c4579e8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb.jpg
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb.webp b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb.webp
new file mode 100644
index 0000000..b7c0a42
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/resources/pattern-srgb.webp
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-layer-filter-expected.png b/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/color-profile-layer-filter-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-layer-filter-expected.png
rename to third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/color-profile-layer-filter-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
index 589b7dd..fffa76b 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-composite-video-shadow-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-composite-video-shadow-expected.png
new file mode 100644
index 0000000..89065d6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-composite-video-shadow-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/scalefactor200/http/tests/csspaint/hidpi/README.txt b/third_party/WebKit/LayoutTests/virtual/scalefactor200/http/tests/csspaint/hidpi/README.txt
new file mode 100644
index 0000000..db12efb2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/scalefactor200/http/tests/csspaint/hidpi/README.txt
@@ -0,0 +1,2 @@
+# This suite runs the tests in LayoutTests/http/tests/csspaint/hidpi/ with the
+# flag --force-device-scale-factor=2.
diff --git a/third_party/WebKit/LayoutTests/virtual/spv2/paint/invalidation/animated-gif-transformed-offscreen-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv2/paint/invalidation/animated-gif-transformed-offscreen-expected.txt
deleted file mode 100644
index 7c909e3a0..0000000
--- a/third_party/WebKit/LayoutTests/virtual/spv2/paint/invalidation/animated-gif-transformed-offscreen-expected.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "bounds": [2008, 2016],
-  "children": [
-    {
-      "bounds": [2008, 2016],
-      "contentsOpaque": true,
-      "drawsContent": true
-    }
-  ]
-}
-
diff --git a/third_party/WebKit/LayoutTests/vr/latest/events_session_end.html b/third_party/WebKit/LayoutTests/vr/latest/events_session_end.html
new file mode 100644
index 0000000..1a43cd6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/vr/latest/events_session_end.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../resources/fake-vr-displays.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/device/vr/vr_service.mojom.js"></script>
+<script src="../resources/mock-vr-service.js"></script>
+<canvas id="webgl-canvas"></canvas>
+<script src="../resources/presentation-setup.js"></script>
+<script>
+let fakeDisplays = fakeVRDisplays();
+
+vr_test((t, mockService) => {
+  let watcherDone = new Event("watcherdone");
+
+  navigator.vr.getDevices().then( (devices) => {
+    let pixel = devices[0];
+    runWithUserGesture( () => {
+      pixel.requestSession({ exclusive: true }).then( (session) => {
+        let eventWatcher = new EventWatcher(t, session, ["end", "watcherdone"]);
+        let eventPromise = eventWatcher.wait_for(["end", "watcherdone"]);
+
+        function onSessionEnd(event) {
+          t.step( () => {
+            assert_equals(event.session, session);
+            session.dispatchEvent(watcherDone);
+          });
+        }
+        session.addEventListener("end", onSessionEnd, false);
+        session.end();
+
+        return eventPromise;
+      }, (err) => {
+        t.step( () => {
+          assert_unreached("requestSession rejected");
+        });
+      }).then( () => {
+        t.done();
+      });
+    });
+  }, (err) => {
+    t.step( () => {
+      assert_unreached("getDevices rejected");
+    });
+  });
+}, [fakeDisplays["Pixel"]],
+"Test deviceconnect fires when devices are connected.");
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/vr/latest/vrDevice_requestSession_exclusive.html b/third_party/WebKit/LayoutTests/vr/latest/vrDevice_requestSession_exclusive.html
index 4de31e7c..f756bcb 100644
--- a/third_party/WebKit/LayoutTests/vr/latest/vrDevice_requestSession_exclusive.html
+++ b/third_party/WebKit/LayoutTests/vr/latest/vrDevice_requestSession_exclusive.html
@@ -31,10 +31,17 @@
             magicWindowOnly.requestSession({ exclusive: true }));
       }, "requestSession rejected for device that only supports non-exclusive sessions.");
 
-      // TODO: Once implemented, ensure that the pixel device can create an
-      // exclusive session.
-
-      t.done();
+      pixel.requestSession({ exclusive: true }).then( (session) => {
+        t.step( () => {
+          assert_true(session.exclusive);
+        }, "requestSession returned correct results");
+      }, (err) => {
+        t.step( () => {
+          assert_unreached("requestSession rejected");
+        });
+      }).then( () => {
+        t.done();
+      });
     });
   }, (err) => {
     t.step( () => {
diff --git a/third_party/WebKit/LayoutTests/vr/latest/vrSession_exclusive.html b/third_party/WebKit/LayoutTests/vr/latest/vrSession_exclusive.html
new file mode 100644
index 0000000..6ab5c54
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/vr/latest/vrSession_exclusive.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../resources/fake-vr-displays.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/device/vr/vr_service.mojom.js"></script>
+<script src="../resources/mock-vr-service.js"></script>
+<script src="../resources/test-constants.js"></script>
+<canvas id="webgl-canvas"></canvas>
+<script src="../resources/presentation-setup.js"></script>
+<script>
+let fakeDisplays = fakeVRDisplays();
+
+vr_test( (t) => {
+  return navigator.vr.getDevices().then( (devices) => {
+    let pixel = devices[0];
+    runWithUserGesture( () => {
+      pixel.requestSession({ exclusive: true }).then( (session) => {
+        t.step( () => {
+          assert_true(session.exclusive);
+          assert_equals(session.device, pixel);
+          assert_approx_equals(session.depthNear, 0.1, FLOAT_EPSILON);
+          assert_approx_equals(session.depthFar, 1000.0, FLOAT_EPSILON);
+        }, "requestSession returned correct results");
+      }, (err) => {
+        t.step( () => {
+          assert_unreached("requestSession rejected");
+        });
+      }).then( () => {
+        t.done();
+      });
+    });
+  }, (err) => {
+    t.step( () => {
+      assert_unreached("getDevices rejected");
+    });
+  });
+}, [fakeDisplays["Pixel"]],
+"supportsSession returns expected exclusive session");
+
+</script>
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 e6130b20..81c2484 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -7245,6 +7245,28 @@
     getter orientation
     getter position
     method constructor
+interface VRSession : EventTarget
+    attribute @@toStringTag
+    getter depthFar
+    getter depthNear
+    getter device
+    getter exclusive
+    getter onblur
+    getter onend
+    getter onfocus
+    getter onresetpose
+    method constructor
+    method end
+    setter depthFar
+    setter depthNear
+    setter onblur
+    setter onend
+    setter onfocus
+    setter onresetpose
+interface VRSessionEvent : Event
+    attribute @@toStringTag
+    getter session
+    method constructor
 interface VRStageParameters
     attribute @@toStringTag
     getter sittingToStandingTransform
diff --git a/third_party/WebKit/PRESUBMIT.py b/third_party/WebKit/PRESUBMIT.py
index 03e199a..dabc495 100644
--- a/third_party/WebKit/PRESUBMIT.py
+++ b/third_party/WebKit/PRESUBMIT.py
@@ -108,7 +108,7 @@
     def source_file_filter(path):
         return input_api.FilterSourceFile(path,
                                           white_list=[r'third_party/WebKit/Source/.*\.(h|cpp)$'],
-                                          black_list=[r'third_party/WebKit/Source/(platform|wtf|web|controller)/'])
+                                          black_list=[r'third_party/WebKit/Source/(platform|controller)/'])
 
     comment_re = input_api.re.compile(r'^\s*//')
     result = []
diff --git a/third_party/WebKit/PRESUBMIT_test.py b/third_party/WebKit/PRESUBMIT_test.py
index ffe89f2..c1df6a7 100644
--- a/third_party/WebKit/PRESUBMIT_test.py
+++ b/third_party/WebKit/PRESUBMIT_test.py
@@ -36,8 +36,7 @@
 
     @mock.patch('subprocess.Popen')
     def testCheckChangeOnUploadWithWebKitAndChromiumFiles(self, _):
-        """
-        This verifies that CheckChangeOnUpload will only call check-webkit-style
+        """This verifies that CheckChangeOnUpload will only call check-webkit-style
         on WebKit files.
         """
         diff_file_webkit_h = ['some diff']
@@ -58,8 +57,7 @@
 
     @mock.patch('subprocess.Popen')
     def testCheckChangeOnUploadWithEmptyAffectedFileList(self, _):
-        """
-        This verifies that CheckChangeOnUpload will skip calling
+        """This verifies that CheckChangeOnUpload will skip calling
         check-webkit-style if the affected file list is empty.
         """
         diff_file_chromium1_h = ['some diff']
@@ -76,5 +74,101 @@
         subprocess.Popen.assert_not_called()
 
 
+class CxxDependencyTest(unittest.TestCase):
+    allow_list = [
+        'gfx::ColorSpace',
+        'gfx::CubicBezier',
+        'gfx::ICCProfile',
+        'gfx::ScrollOffset',
+    ]
+    disallow_list = [
+        'scoped_refptr<base::SingleThreadTaskRunner>',
+        'base::Callback<void()>',
+        'base::OnceCallback<void()>',
+        'content::RenderFrame',
+        'gfx::Point',
+        'gfx::Rect',
+        'net::IPEndPoint',
+        'ui::Clipboard',
+    ]
+    disallow_message = [
+    ]
+
+    def runCheck(self, filename, file_contents):
+        mock_input_api = MockInputApi()
+        mock_input_api.files = [
+            MockAffectedFile(filename, file_contents),
+        ]
+        # Access to a protected member
+        # pylint: disable=W0212
+        return PRESUBMIT._CheckForForbiddenNamespace(mock_input_api, MockOutputApi())
+
+    # References in comments should never be checked.
+    def testCheckCommentsIgnored(self):
+        filename = 'third_party/WebKit/Source/core/frame/frame.cc'
+        for item in self.allow_list:
+            errors = self.runCheck(filename, ['// %s' % item])
+            self.assertEqual([], errors)
+
+        for item in self.disallow_list:
+            errors = self.runCheck(filename, ['// %s' % item])
+            self.assertEqual([], errors)
+
+    # core, modules, public, et cetera should all have dependency enforcement.
+    def testCheckCoreEnforcement(self):
+        filename = 'third_party/WebKit/Source/core/frame/frame.cc',
+        for item in self.allow_list:
+            errors = self.runCheck(filename, ['%s' % item])
+            self.assertEqual([], errors)
+
+        for item in self.disallow_list:
+            errors = self.runCheck(filename, ['%s' % item])
+            self.assertGreater(len(errors), 0)
+            self.assertRegexpMatches(
+                errors[0].message,
+                '^Do not use Chromium class from namespace [A-Za-z0-9_]+ inside Blink core:')
+            if len(errors) == 2:
+                self.assertRegexpMatches(errors[1].message, '^Do not use Chromium class [A-Za-z0-9_]+ inside Blink core:')
+            else:
+                self.assertEquals(1, len(errors))
+
+    def testCheckModulesEnforcement(self):
+        filename = 'third_party/WebKit/Source/modules/modules_initializer.cc',
+        for item in self.allow_list:
+            errors = self.runCheck(filename, ['%s' % item])
+            self.assertEqual([], errors)
+
+        for item in self.disallow_list:
+            errors = self.runCheck(filename, ['%s' % item])
+            self.assertGreater(len(errors), 0)
+            self.assertRegexpMatches(
+                errors[0].message,
+                '^Do not use Chromium class from namespace [A-Za-z0-9_]+ inside Blink core:')
+            if len(errors) == 2:
+                self.assertRegexpMatches(errors[1].message, '^Do not use Chromium class [A-Za-z0-9_]+ inside Blink core:')
+            else:
+                self.assertEquals(1, len(errors))
+
+    def testCheckPublicEnforcement(self):
+        filename = 'third_party/WebKit/Source/public/platform/WebThread.h',
+        for item in self.allow_list:
+            errors = self.runCheck(filename, ['%s' % item])
+            self.assertEqual([], errors)
+
+        for item in self.disallow_list:
+            errors = self.runCheck(filename, ['%s' % item])
+            self.assertGreater(len(errors), 0)
+            self.assertRegexpMatches(
+                errors[0].message,
+                '^Do not use Chromium class from namespace [A-Za-z0-9_]+ inside Blink core:')
+            if len(errors) == 2:
+                self.assertRegexpMatches(errors[1].message, '^Do not use Chromium class [A-Za-z0-9_]+ inside Blink core:')
+            else:
+                self.assertEquals(1, len(errors))
+
+    # platform and controller should be opted out of enforcement, but aren't
+    # currently checked because the PRESUBMIT test mocks are missing too
+    # much functionality...
+
 if __name__ == '__main__':
     unittest.main()
diff --git a/third_party/WebKit/PerformanceTests/Canvas/draw-video-to-hw-accelerated-canvas-2d.html b/third_party/WebKit/PerformanceTests/Canvas/draw-video-to-hw-accelerated-canvas-2d.html
index f8d5945..1884bad 100644
--- a/third_party/WebKit/PerformanceTests/Canvas/draw-video-to-hw-accelerated-canvas-2d.html
+++ b/third_party/WebKit/PerformanceTests/Canvas/draw-video-to-hw-accelerated-canvas-2d.html
@@ -44,7 +44,7 @@
     // and the dest canvas is HW accelerated Canvas when setting its size to 1024x1024.
     setSize(1024, 1024);
 
-    videoElement.src = "resources/bear-1280x720.mp4";
+    videoElement.src = "resources/bear-1280x720-long.mp4";
     if(!videoElement.canPlayType('video/mp4').replace(/no/, '')) {
       CanvasRunner.logFatalError("video/mp4 is unsupported");
     };
diff --git a/third_party/WebKit/PerformanceTests/Canvas/resources/bear-1280x720-long.mp4 b/third_party/WebKit/PerformanceTests/Canvas/resources/bear-1280x720-long.mp4
new file mode 100644
index 0000000..d2f48e96
--- /dev/null
+++ b/third_party/WebKit/PerformanceTests/Canvas/resources/bear-1280x720-long.mp4
Binary files differ
diff --git a/third_party/WebKit/PerformanceTests/Canvas/resources/bear-1280x720.mp4 b/third_party/WebKit/PerformanceTests/Canvas/resources/bear-1280x720.mp4
deleted file mode 100644
index b424a0f..0000000
--- a/third_party/WebKit/PerformanceTests/Canvas/resources/bear-1280x720.mp4
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/PerformanceTests/Canvas/upload-video-to-sub-texture.html b/third_party/WebKit/PerformanceTests/Canvas/upload-video-to-sub-texture.html
index 80d3e08..e86456a 100644
--- a/third_party/WebKit/PerformanceTests/Canvas/upload-video-to-sub-texture.html
+++ b/third_party/WebKit/PerformanceTests/Canvas/upload-video-to-sub-texture.html
@@ -58,7 +58,7 @@
 window.onload = function () {
     setSize(1, 1);
 
-    videoElement.src = "resources/bear-1280x720.mp4";
+    videoElement.src = "resources/bear-1280x720-long.mp4";
     if(!videoElement.canPlayType('video/mp4').replace(/no/, '')) {
       CanvasRunner.logFatalError("video/mp4 is unsupported");
     };
diff --git a/third_party/WebKit/PerformanceTests/Canvas/upload-video-to-texture.html b/third_party/WebKit/PerformanceTests/Canvas/upload-video-to-texture.html
index 55034ab..b594a56 100644
--- a/third_party/WebKit/PerformanceTests/Canvas/upload-video-to-texture.html
+++ b/third_party/WebKit/PerformanceTests/Canvas/upload-video-to-texture.html
@@ -57,7 +57,7 @@
 window.onload = function () {
     setSize(1, 1);
 
-    videoElement.src = "resources/bear-1280x720.mp4";
+    videoElement.src = "resources/bear-1280x720-long.mp4";
     if(!videoElement.canPlayType('video/mp4').replace(/no/, '')) {
       CanvasRunner.logFatalError("video/mp4 is unsupported");
     };
diff --git a/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp b/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp
index b0acd01f..0821d1b 100644
--- a/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp
@@ -71,13 +71,13 @@
   if (lifecycle_ != Lifecycle::kContextIsInitialized)
     return;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Local<v8::Context> context = script_state_->GetContext();
   // The embedder could run arbitrary code in response to the
   // willReleaseScriptContext callback, so all disposing should happen after
   // it returns.
   GetFrame()->Client()->WillReleaseScriptContext(context, world_->GetWorldId());
-  MainThreadDebugger::Instance()->ContextWillBeDestroyed(script_state_.Get());
+  MainThreadDebugger::Instance()->ContextWillBeDestroyed(script_state_.get());
 
   if (next_status == Lifecycle::kGlobalObjectIsDetached) {
     v8::Local<v8::Context> context = script_state_->GetContext();
@@ -132,7 +132,7 @@
 
   CreateContext();
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Local<v8::Context> context = script_state_->GetContext();
   if (global_proxy_.IsEmpty()) {
     global_proxy_.Set(GetIsolate(), context->Global());
@@ -165,12 +165,12 @@
   {
     TRACE_EVENT1("v8", "ContextCreatedNotification", "IsMainFrame",
                  GetFrame()->IsMainFrame());
-    MainThreadDebugger::Instance()->ContextCreated(script_state_.Get(),
+    MainThreadDebugger::Instance()->ContextCreated(script_state_.get(),
                                                    GetFrame(), origin);
     GetFrame()->Client()->DidCreateScriptContext(context, world_->GetWorldId());
 
     InstallConditionalFeaturesOnGlobal(&V8Window::wrapperTypeInfo,
-                                       script_state_.Get());
+                                       script_state_.get());
 
     if (world_->IsMainWorld()) {
       // For the main world, install any remaining conditional bindings (i.e.
@@ -178,7 +178,7 @@
       // bindings cannot be enabled until the execution context is available
       // (e.g. parsing the document, inspecting HTTP headers).
       InstallConditionalFeatures(&V8Window::wrapperTypeInfo,
-                                 script_state_.Get(), v8::Local<v8::Object>(),
+                                 script_state_.get(), v8::Local<v8::Object>(),
                                  v8::Local<v8::Function>());
       GetFrame()->Loader().DispatchDidClearWindowObjectInMainWorld();
     }
@@ -296,7 +296,7 @@
   TRACE_EVENT1("v8", "LocalWindowProxy::UpdateDocumentProperty", "IsMainFrame",
                GetFrame()->IsMainFrame());
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Local<v8::Context> context = script_state_->GetContext();
   v8::Local<v8::Value> document_wrapper =
       ToV8(GetFrame()->GetDocument(), context->Global(), GetIsolate());
@@ -432,11 +432,10 @@
   if (items->HasExactlyOneItem()) {
     HTMLElement* element = items->Item(0);
     DCHECK(element);
-    Frame* frame = isHTMLIFrameElement(*element)
-                       ? toHTMLIFrameElement(*element).ContentFrame()
-                       : 0;
-    if (frame)
-      return ToV8(frame->DomWindow(), creation_context, isolate);
+    if (auto* iframe = ToHTMLIFrameElementOrNull(*element)) {
+      if (Frame* frame = iframe->ContentFrame())
+        return ToV8(frame->DomWindow(), creation_context, isolate);
+    }
     return ToV8(element, creation_context, isolate);
   }
   return ToV8(items, creation_context, isolate);
@@ -477,7 +476,7 @@
   if (lifecycle_ != Lifecycle::kContextIsInitialized)
     return;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Local<v8::Object> document_wrapper =
       world_->DomDataStore().Get(document, GetIsolate());
   document_wrapper
@@ -501,7 +500,7 @@
 
   if (document->HasNamedItem(name))
     return;
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Local<v8::Object> document_wrapper =
       world_->DomDataStore().Get(document, GetIsolate());
   document_wrapper
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.cpp
index ad709cc..de06bcc 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.cpp
@@ -146,7 +146,7 @@
     const QualifiedName& tag_name) {
   if (!script_state_->ContextIsValid())
     return CustomElement::CreateFailedElement(document, tag_name);
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Isolate* isolate = script_state_->GetIsolate();
 
   ExceptionState exception_state(isolate, ExceptionState::kConstructionContext,
@@ -198,7 +198,7 @@
 bool ScriptCustomElementDefinition::RunConstructor(Element* element) {
   if (!script_state_->ContextIsValid())
     return false;
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Isolate* isolate = script_state_->GetIsolate();
 
   // Step 5 says to rethrow the exception; but there is no one to
@@ -231,7 +231,7 @@
   v8::Isolate* isolate = script_state_->GetIsolate();
   DCHECK(ScriptState::Current(isolate) == script_state_);
   ExecutionContext* execution_context =
-      ExecutionContext::From(script_state_.Get());
+      ExecutionContext::From(script_state_.get());
   v8::Local<v8::Value> result;
   if (!V8ScriptRunner::CallAsConstructor(isolate, Constructor(),
                                          execution_context, 0, nullptr)
@@ -248,7 +248,7 @@
 
 // CustomElementDefinition
 ScriptValue ScriptCustomElementDefinition::GetConstructorForScript() {
-  return ScriptValue(script_state_.Get(), Constructor());
+  return ScriptValue(script_state_.get(), Constructor());
 }
 
 bool ScriptCustomElementDefinition::HasConnectedCallback() const {
@@ -278,7 +278,7 @@
   try_catch.SetVerbose(true);
 
   ExecutionContext* execution_context =
-      ExecutionContext::From(script_state_.Get());
+      ExecutionContext::From(script_state_.get());
   v8::Local<v8::Value> element_handle =
       ToV8(element, script_state_->GetContext()->Global(), isolate);
   V8ScriptRunner::CallFunction(callback, execution_context, element_handle,
@@ -288,7 +288,7 @@
 void ScriptCustomElementDefinition::RunConnectedCallback(Element* element) {
   if (!script_state_->ContextIsValid())
     return;
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Isolate* isolate = script_state_->GetIsolate();
   RunCallback(connected_callback_.NewLocal(isolate), element);
 }
@@ -296,7 +296,7 @@
 void ScriptCustomElementDefinition::RunDisconnectedCallback(Element* element) {
   if (!script_state_->ContextIsValid())
     return;
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Isolate* isolate = script_state_->GetIsolate();
   RunCallback(disconnected_callback_.NewLocal(isolate), element);
 }
@@ -306,7 +306,7 @@
                                                        Document* new_owner) {
   if (!script_state_->ContextIsValid())
     return;
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Isolate* isolate = script_state_->GetIsolate();
   v8::Local<v8::Value> argv[] = {
       ToV8(old_owner, script_state_->GetContext()->Global(), isolate),
@@ -322,7 +322,7 @@
     const AtomicString& new_value) {
   if (!script_state_->ContextIsValid())
     return;
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Isolate* isolate = script_state_->GetIsolate();
   v8::Local<v8::Value> argv[] = {
       V8String(isolate, name.LocalName()), V8StringOrNull(isolate, old_value),
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinitionBuilder.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinitionBuilder.cpp
index 27cb8fa..cebc76a 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinitionBuilder.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinitionBuilder.cpp
@@ -44,7 +44,7 @@
 }
 
 bool ScriptCustomElementDefinitionBuilder::CheckConstructorNotRegistered() {
-  if (!ScriptCustomElementDefinition::ForConstructor(script_state_.Get(),
+  if (!ScriptCustomElementDefinition::ForConstructor(script_state_.get(),
                                                      registry_, constructor_))
     return true;
 
@@ -154,7 +154,7 @@
     const CustomElementDescriptor& descriptor,
     CustomElementDefinition::Id id) {
   return ScriptCustomElementDefinition::Create(
-      script_state_.Get(), registry_, descriptor, id, constructor_,
+      script_state_.get(), registry_, descriptor, id, constructor_,
       connected_callback_, disconnected_callback_, adopted_callback_,
       attribute_changed_callback_, std::move(observed_attributes_));
 }
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptFunction.h b/third_party/WebKit/Source/bindings/core/v8/ScriptFunction.h
index 0ff8a0d..65045ff 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptFunction.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptFunction.h
@@ -60,7 +60,7 @@
   explicit ScriptFunction(ScriptState* script_state)
       : script_state_(script_state) {}
 
-  ScriptState* GetScriptState() const { return script_state_.Get(); }
+  ScriptState* GetScriptState() const { return script_state_.get(); }
 
   v8::Local<v8::Function> BindToV8Function();
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptModule.h b/third_party/WebKit/Source/bindings/core/v8/ScriptModule.h
index c78f716..d0f690f 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptModule.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptModule.h
@@ -161,8 +161,8 @@
       HashTraits<ScriptModule>::IsDeletedValue(other))
     return false;
 
-  blink::SharedPersistent<v8::Module>* left = module_.Get();
-  blink::SharedPersistent<v8::Module>* right = other.module_.Get();
+  blink::SharedPersistent<v8::Module>* left = module_.get();
+  blink::SharedPersistent<v8::Module>* right = other.module_.get();
   if (left == right)
     return true;
   if (!left || !right)
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptPromise.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptPromise.cpp
index 5ccfac3..5cf5e9d 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptPromise.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptPromise.cpp
@@ -258,7 +258,7 @@
       return ScriptPromise();
   }
 
-  return ScriptPromise(script_state_.Get(), result_promise);
+  return ScriptPromise(script_state_.get(), result_promise);
 }
 
 ScriptPromise ScriptPromise::CastUndefined(ScriptState* script_state) {
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptPromisePropertyTest.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptPromisePropertyTest.cpp
index 2176069a..34268694 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptPromisePropertyTest.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptPromisePropertyTest.cpp
@@ -115,7 +115,7 @@
     return ToScriptStateForMainWorld(GetDocument().GetFrame());
   }
   DOMWrapperWorld& MainWorld() { return MainScriptState()->World(); }
-  ScriptState* OtherScriptState() { return other_script_state_.Get(); }
+  ScriptState* OtherScriptState() { return other_script_state_.get(); }
   DOMWrapperWorld& OtherWorld() { return other_script_state_->World(); }
   ScriptState* CurrentScriptState() {
     return ScriptState::Current(GetIsolate());
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptPromiseResolver.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptPromiseResolver.cpp
index f2bdd5d..c327ad2 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptPromiseResolver.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptPromiseResolver.cpp
@@ -64,7 +64,7 @@
     return;
   }
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   ResolveOrRejectImmediately();
 }
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptPromiseResolver.h b/third_party/WebKit/Source/bindings/core/v8/ScriptPromiseResolver.h
index 8085848d..b3c3fb5 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptPromiseResolver.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptPromiseResolver.h
@@ -73,7 +73,7 @@
   void Resolve() { Resolve(ToV8UndefinedGenerator()); }
   void Reject() { Reject(ToV8UndefinedGenerator()); }
 
-  ScriptState* GetScriptState() { return script_state_.Get(); }
+  ScriptState* GetScriptState() { return script_state_.get(); }
 
   // Note that an empty ScriptPromise will be returned after resolve or
   // reject is called.
@@ -84,7 +84,7 @@
     return resolver_.Promise();
   }
 
-  ScriptState* GetScriptState() const { return script_state_.Get(); }
+  ScriptState* GetScriptState() const { return script_state_.get(); }
 
   // SuspendableObject implementation.
   void Suspend() override;
@@ -125,7 +125,7 @@
     DCHECK(new_state == kResolving || new_state == kRejecting);
     state_ = new_state;
 
-    ScriptState::Scope scope(script_state_.Get());
+    ScriptState::Scope scope(script_state_.get());
 
     // Calling ToV8 in a ScriptForbiddenScope will trigger a CHECK and
     // cause a crash. ToV8 just invokes a constructor for wrapper creation,
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp
index 83d6b62..8b92eecf 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp
@@ -262,7 +262,7 @@
         cache_handler ? cache_handler->GetCachedMetadata(
                             V8ScriptRunner::TagForCodeCache(cache_handler))
                       : nullptr);
-    if (code_cache.Get()) {
+    if (code_cache.get()) {
       // The resource has a code cache, so it's unnecessary to stream and
       // parse the code. Cancel the streaming and resume the non-streaming
       // code path.
@@ -528,7 +528,7 @@
     source_ = WTF::WrapUnique(
         new v8::ScriptCompiler::StreamedSource(stream_, encoding_));
 
-    ScriptState::Scope scope(script_state_.Get());
+    ScriptState::Scope scope(script_state_.get());
     std::unique_ptr<v8::ScriptCompiler::ScriptStreamingTask>
         script_streaming_task(
             WTF::WrapUnique(v8::ScriptCompiler::StartStreamingScript(
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptValue.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptValue.cpp
index df7f20c..fa9f098 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptValue.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptValue.cpp
@@ -71,7 +71,7 @@
   if (IsEmpty())
     return false;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Local<v8::Value> string = V8Value();
   if (string.IsEmpty() || !string->IsString())
     return false;
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptValue.h b/third_party/WebKit/Source/bindings/core/v8/ScriptValue.h
index faa140a6..3804a7c 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptValue.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptValue.h
@@ -93,7 +93,7 @@
     DCHECK(IsEmpty() || script_state_);
   }
 
-  ScriptState* GetScriptState() const { return script_state_.Get(); }
+  ScriptState* GetScriptState() const { return script_state_.get(); }
 
   v8::Isolate* GetIsolate() const {
     return script_state_ ? script_state_->GetIsolate()
@@ -101,7 +101,7 @@
   }
 
   v8::Local<v8::Context> GetContext() const {
-    DCHECK(script_state_.Get());
+    DCHECK(script_state_.get());
     return script_state_->GetContext();
   }
 
@@ -155,7 +155,7 @@
     return !value.IsEmpty() && value->IsObject();
   }
 
-  bool IsEmpty() const { return !value_.Get() || value_->IsEmpty(); }
+  bool IsEmpty() const { return !value_.get() || value_->IsEmpty(); }
 
   void Clear() { value_ = nullptr; }
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/V0CustomElementConstructorBuilder.cpp b/third_party/WebKit/Source/bindings/core/v8/V0CustomElementConstructorBuilder.cpp
index ba2301c9..bfa7575 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V0CustomElementConstructorBuilder.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V0CustomElementConstructorBuilder.cpp
@@ -154,7 +154,7 @@
       RetrieveCallback("attributeChangedCallback");
 
   callbacks_ = V8V0CustomElementLifecycleCallbacks::Create(
-      script_state_.Get(), prototype_, created, attached, detached,
+      script_state_.get(), prototype_, created, attached, detached,
       attribute_changed);
   return callbacks_.Get();
 }
@@ -289,7 +289,7 @@
 }
 
 ScriptValue V0CustomElementConstructorBuilder::BindingsReturnValue() const {
-  return ScriptValue(script_state_.Get(), constructor_);
+  return ScriptValue(script_state_.get(), constructor_);
 }
 
 bool V0CustomElementConstructorBuilder::HasValidPrototypeChainFor(
@@ -346,7 +346,7 @@
   V0CustomElementProcessingStack::CallbackDeliveryScope delivery_scope;
   Element* element = document->createElementNS(
       namespace_uri, tag_name,
-      StringOrDictionary::fromString(maybe_type->IsNull() ? g_null_atom : type),
+      StringOrDictionary::FromString(maybe_type->IsNull() ? g_null_atom : type),
       exception_state);
   if (element) {
     UseCounter::Count(document, WebFeature::kV0CustomElementsConstruct);
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp b/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp
index 08fa5f2..7abdb96 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp
@@ -456,13 +456,13 @@
       v8::Context::New(isolate),
       DOMWrapperWorld::Create(isolate,
                               DOMWrapperWorld::WorldType::kGarbageCollector));
-  ScriptState::Scope scope(script_state.Get());
+  ScriptState::Scope scope(script_state.get());
   StringBuilder builder;
   builder.Append("if (gc) gc(");
   builder.Append(only_minor_gc ? "true" : "false");
   builder.Append(")");
   V8ScriptRunner::CompileAndRunInternalScript(
-      script_state.Get(), V8String(isolate, builder.ToString()), isolate);
+      script_state.get(), V8String(isolate, builder.ToString()), isolate);
   script_state->DisposePerContextData();
 }
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8IntersectionObserverDelegate.h b/third_party/WebKit/Source/bindings/core/v8/V8IntersectionObserverDelegate.h
index b80a891..9c97e13 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8IntersectionObserverDelegate.h
+++ b/third_party/WebKit/Source/bindings/core/v8/V8IntersectionObserverDelegate.h
@@ -30,7 +30,7 @@
                IntersectionObserver&) override;
 
   ExecutionContext* GetExecutionContext() const override {
-    return ExecutionContext::From(script_state_.Get());
+    return ExecutionContext::From(script_state_.get());
   }
 
  private:
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8NodeFilterCondition.cpp b/third_party/WebKit/Source/bindings/core/v8/V8NodeFilterCondition.cpp
index 3fccbf22..4847ac6 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8NodeFilterCondition.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8NodeFilterCondition.cpp
@@ -94,7 +94,7 @@
     receiver = filter;
   }
 
-  v8::Local<v8::Value> node_wrapper = ToV8(node, script_state_.Get());
+  v8::Local<v8::Value> node_wrapper = ToV8(node, script_state_.get());
   if (node_wrapper.IsEmpty()) {
     if (exception_catcher.HasCaught())
       exception_state.RethrowV8Exception(exception_catcher.Exception());
@@ -104,7 +104,7 @@
   v8::Local<v8::Value> result;
   v8::Local<v8::Value> args[] = {node_wrapper};
   if (!V8ScriptRunner::CallFunction(callback,
-                                    ExecutionContext::From(script_state_.Get()),
+                                    ExecutionContext::From(script_state_.get()),
                                     receiver, 1, args, isolate)
            .ToLocal(&result)) {
     exception_state.RethrowV8Exception(exception_catcher.Exception());
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ObjectBuilder.cpp b/third_party/WebKit/Source/bindings/core/v8/V8ObjectBuilder.cpp
index 3a14f96..1f2c3e1 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8ObjectBuilder.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8ObjectBuilder.cpp
@@ -53,7 +53,7 @@
 }
 
 ScriptValue V8ObjectBuilder::GetScriptValue() const {
-  return ScriptValue(script_state_.Get(), object_);
+  return ScriptValue(script_state_.get(), object_);
 }
 
 void V8ObjectBuilder::AddInternal(const StringView& name,
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ObjectBuilder.h b/third_party/WebKit/Source/bindings/core/v8/V8ObjectBuilder.h
index 28b08941..d8bceb1 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8ObjectBuilder.h
+++ b/third_party/WebKit/Source/bindings/core/v8/V8ObjectBuilder.h
@@ -22,7 +22,7 @@
  public:
   explicit V8ObjectBuilder(ScriptState*);
 
-  ScriptState* GetScriptState() const { return script_state_.Get(); }
+  ScriptState* GetScriptState() const { return script_state_.get(); }
 
   V8ObjectBuilder& Add(const StringView& name, const V8ObjectBuilder&);
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp
index cb4e780..5bfca45c 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp
@@ -219,7 +219,7 @@
     v8::Local<v8::String> code,
     v8::ScriptOrigin origin) {
   RefPtr<CachedMetadata> code_cache(cache_handler->GetCachedMetadata(tag));
-  return code_cache.Get()
+  return code_cache.get()
              ? CompileAndConsumeCache(cache_handler, code_cache,
                                       consume_options, isolate, code, origin)
              : CompileAndProduceCache(cache_handler, tag, produce_options,
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8V0CustomElementLifecycleCallbacks.cpp b/third_party/WebKit/Source/bindings/core/v8/V8V0CustomElementLifecycleCallbacks.cpp
index bbad2a0..3cf6a91 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8V0CustomElementLifecycleCallbacks.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8V0CustomElementLifecycleCallbacks.cpp
@@ -156,7 +156,7 @@
 
   element->SetV0CustomElementState(Element::kV0Upgraded);
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Isolate* isolate = script_state_->GetIsolate();
   v8::Local<v8::Context> context = script_state_->GetContext();
   v8::Local<v8::Value> receiver_value =
@@ -179,7 +179,7 @@
   v8::TryCatch exception_catcher(isolate);
   exception_catcher.SetVerbose(true);
   V8ScriptRunner::CallFunction(callback,
-                               ExecutionContext::From(script_state_.Get()),
+                               ExecutionContext::From(script_state_.get()),
                                receiver, 0, 0, isolate);
 }
 
@@ -201,7 +201,7 @@
   // Bug 329665 tracks similar behavior for other synchronous events.
   if (!script_state_->ContextIsValid())
     return;
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Isolate* isolate = script_state_->GetIsolate();
   v8::Local<v8::Context> context = script_state_->GetContext();
   v8::Local<v8::Value> receiver = ToV8(element, context->Global(), isolate);
@@ -222,7 +222,7 @@
   v8::TryCatch exception_catcher(isolate);
   exception_catcher.SetVerbose(true);
   V8ScriptRunner::CallFunction(callback,
-                               ExecutionContext::From(script_state_.Get()),
+                               ExecutionContext::From(script_state_.get()),
                                receiver, WTF_ARRAY_LENGTH(argv), argv, isolate);
 }
 
@@ -234,7 +234,7 @@
   // Bug 329665 tracks similar behavior for other synchronous events.
   if (!script_state_->ContextIsValid())
     return;
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Isolate* isolate = script_state_->GetIsolate();
   v8::Local<v8::Context> context = script_state_->GetContext();
   v8::Local<v8::Function> callback = weak_callback.NewLocal(isolate);
@@ -248,7 +248,7 @@
   v8::TryCatch exception_catcher(isolate);
   exception_catcher.SetVerbose(true);
   V8ScriptRunner::CallFunction(callback,
-                               ExecutionContext::From(script_state_.Get()),
+                               ExecutionContext::From(script_state_.get()),
                                receiver, 0, 0, isolate);
 }
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/WorkerOrWorkletScriptController.cpp b/third_party/WebKit/Source/bindings/core/v8/WorkerOrWorkletScriptController.cpp
index c00f376..1649c54 100644
--- a/third_party/WebKit/Source/bindings/core/v8/WorkerOrWorkletScriptController.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/WorkerOrWorkletScriptController.cpp
@@ -128,7 +128,7 @@
 
   if (global_scope_->IsWorkerGlobalScope() ||
       global_scope_->IsThreadedWorkletGlobalScope()) {
-    ScriptState::Scope scope(script_state_.Get());
+    ScriptState::Scope scope(script_state_.get());
     WorkerThreadDebugger* debugger = WorkerThreadDebugger::From(isolate_);
     debugger->ContextWillBeDestroyed(global_scope_->GetThread(),
                                      script_state_->GetContext());
@@ -179,7 +179,7 @@
 
   script_state_ = ScriptState::Create(context, world_);
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
 
   // Associate the global proxy object, the global object and the worker
   // instance (C++ object) as follows.
@@ -238,7 +238,7 @@
                                              human_readable_name);
   }
 
-  InstallConditionalFeaturesOnGlobal(wrapper_type_info, script_state_.Get());
+  InstallConditionalFeaturesOnGlobal(wrapper_type_info, script_state_.get());
 
   return true;
 }
@@ -255,7 +255,7 @@
   if (!InitializeContextIfNeeded(String()))
     return ScriptValue();
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
 
   if (!disable_eval_pending_.IsEmpty()) {
     script_state_->GetContext()->AllowCodeGenerationFromStrings(false);
@@ -272,7 +272,7 @@
   // - A work{er,let} script doesn't have a nonce, and
   // - a work{er,let} script is always "not parser inserted".
   ReferrerScriptInfo referrer_info;
-  if (V8ScriptRunner::CompileScript(script_state_.Get(), script, file_name,
+  if (V8ScriptRunner::CompileScript(script_state_.get(), script, file_name,
                                     String(), script_start_position,
                                     cache_handler, kSharableCrossOrigin,
                                     v8_cache_options, referrer_info)
@@ -290,9 +290,9 @@
     execution_state_->had_exception = true;
     execution_state_->error_message = ToCoreString(message->Get());
     execution_state_->location_ = SourceLocation::FromMessage(
-        isolate_, message, ExecutionContext::From(script_state_.Get()));
+        isolate_, message, ExecutionContext::From(script_state_.get()));
     execution_state_->exception =
-        ScriptValue(script_state_.Get(), block.Exception());
+        ScriptValue(script_state_.get(), block.Exception());
     block.Reset();
   } else {
     execution_state_->had_exception = false;
@@ -302,7 +302,7 @@
   if (!maybe_result.ToLocal(&result) || result->IsUndefined())
     return ScriptValue();
 
-  return ScriptValue(script_state_.Get(), result);
+  return ScriptValue(script_state_.get(), result);
 }
 
 bool WorkerOrWorkletScriptController::Evaluate(
@@ -319,7 +319,7 @@
   if (IsExecutionForbidden())
     return false;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   if (state.had_exception) {
     if (error_event) {
       if (state.error_event_from_imported_script_) {
@@ -329,14 +329,14 @@
       }
       if (global_scope_->ShouldSanitizeScriptError(state.location_->Url(),
                                                    kNotSharableCrossOrigin)) {
-        *error_event = ErrorEvent::CreateSanitizedError(world_.Get());
+        *error_event = ErrorEvent::CreateSanitizedError(world_.get());
       } else {
         *error_event =
             ErrorEvent::Create(state.error_message, state.location_->Clone(),
-                               state.exception, world_.Get());
+                               state.exception, world_.get());
       }
       V8ErrorHandler::StoreExceptionOnErrorEventWrapper(
-          script_state_.Get(), *error_event, state.exception.V8Value(),
+          script_state_.get(), *error_event, state.exception.V8Value(),
           script_state_->GetContext()->Global());
     } else {
       DCHECK(!global_scope_->ShouldSanitizeScriptError(
@@ -347,7 +347,7 @@
       } else {
         event =
             ErrorEvent::Create(state.error_message, state.location_->Clone(),
-                               state.exception, world_.Get());
+                               state.exception, world_.get());
       }
       global_scope_->DispatchErrorEvent(event, kNotSharableCrossOrigin);
     }
diff --git a/third_party/WebKit/Source/bindings/core/v8/WorkerOrWorkletScriptController.h b/third_party/WebKit/Source/bindings/core/v8/WorkerOrWorkletScriptController.h
index fbd45653..2dc0d09 100644
--- a/third_party/WebKit/Source/bindings/core/v8/WorkerOrWorkletScriptController.h
+++ b/third_party/WebKit/Source/bindings/core/v8/WorkerOrWorkletScriptController.h
@@ -78,7 +78,7 @@
   void DisableEval(const String&);
 
   // Used by Inspector agents:
-  ScriptState* GetScriptState() { return script_state_.Get(); }
+  ScriptState* GetScriptState() { return script_state_.get(); }
 
   // Used by V8 bindings:
   v8::Local<v8::Context> GetContext() {
@@ -87,7 +87,7 @@
   }
 
   RejectedPromises* GetRejectedPromises() const {
-    return rejected_promises_.Get();
+    return rejected_promises_.get();
   }
 
   DECLARE_TRACE();
diff --git a/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp b/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp
index 116571a..38233f3 100644
--- a/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp
@@ -250,7 +250,7 @@
     return;
 
   message->UnregisterMemoryAllocatedWithCurrentScriptContext();
-  window->postMessage(message.Get(), transferables.message_ports, target_origin,
+  window->postMessage(message.get(), transferables.message_ports, target_origin,
                       source, exception_state);
 }
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/UnpackedSerializedScriptValue.h b/third_party/WebKit/Source/bindings/core/v8/serialization/UnpackedSerializedScriptValue.h
index 3933501..9a666c0d 100644
--- a/third_party/WebKit/Source/bindings/core/v8/serialization/UnpackedSerializedScriptValue.h
+++ b/third_party/WebKit/Source/bindings/core/v8/serialization/UnpackedSerializedScriptValue.h
@@ -42,8 +42,8 @@
 
   DECLARE_TRACE();
 
-  SerializedScriptValue* Value() { return value_.Get(); }
-  const SerializedScriptValue* Value() const { return value_.Get(); }
+  SerializedScriptValue* Value() { return value_.get(); }
+  const SerializedScriptValue* Value() const { return value_.get(); }
 
   const HeapVector<Member<DOMArrayBufferBase>>& ArrayBuffers() const {
     return array_buffers_;
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueDeserializer.cpp b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueDeserializer.cpp
index a6ddaa0..f742194 100644
--- a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueDeserializer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueDeserializer.cpp
@@ -137,7 +137,7 @@
   v8::Local<v8::Context> context = script_state_->GetContext();
 
   size_t version_envelope_size =
-      ReadVersionEnvelope(serialized_script_value_.Get(), &version_);
+      ReadVersionEnvelope(serialized_script_value_.get(), &version_);
   if (version_envelope_size) {
     const void* blink_envelope;
     bool read_envelope = ReadRawBytes(version_envelope_size, &blink_envelope);
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueDeserializer.h b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueDeserializer.h
index 4acca19..33b7b54 100644
--- a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueDeserializer.h
+++ b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueDeserializer.h
@@ -47,7 +47,7 @@
  protected:
   virtual ScriptWrappable* ReadDOMObject(SerializationTag);
 
-  ScriptState* GetScriptState() const { return script_state_.Get(); }
+  ScriptState* GetScriptState() const { return script_state_.get(); }
 
   uint32_t Version() const { return version_; }
   bool ReadTag(SerializationTag* tag) {
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.cpp b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.cpp
index c05cdcd4..8ba62d17 100644
--- a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.cpp
@@ -117,7 +117,7 @@
   for (uint32_t i = 0; i < transferables_->array_buffers.size(); i++) {
     DOMArrayBufferBase* array_buffer = transferables_->array_buffers[i].Get();
     if (!array_buffer->IsShared()) {
-      v8::Local<v8::Value> wrapper = ToV8(array_buffer, script_state_.Get());
+      v8::Local<v8::Value> wrapper = ToV8(array_buffer, script_state_.get());
       serializer_.TransferArrayBuffer(
           i, v8::Local<v8::ArrayBuffer>::Cast(wrapper));
     } else {
diff --git a/third_party/WebKit/Source/bindings/modules/BUILD.gn b/third_party/WebKit/Source/bindings/modules/BUILD.gn
index 93997e4..e27d56b 100644
--- a/third_party/WebKit/Source/bindings/modules/BUILD.gn
+++ b/third_party/WebKit/Source/bindings/modules/BUILD.gn
@@ -56,6 +56,7 @@
     "//third_party/WebKit/Source/modules/storage/StorageEvent.idl",
     "//third_party/WebKit/Source/modules/vr/VRDisplayEvent.idl",
     "//third_party/WebKit/Source/modules/vr/latest/VRDeviceEvent.idl",
+    "//third_party/WebKit/Source/modules/vr/latest/VRSessionEvent.idl",
     "//third_party/WebKit/Source/modules/webaudio/AudioProcessingEvent.idl",
     "//third_party/WebKit/Source/modules/webaudio/OfflineAudioCompletionEvent.idl",
     "//third_party/WebKit/Source/modules/webgl/WebGLContextEvent.idl",
diff --git a/third_party/WebKit/Source/bindings/modules/v8/V8BindingForModules.cpp b/third_party/WebKit/Source/bindings/modules/v8/V8BindingForModules.cpp
index 2fbc9e3e..c650cd7 100644
--- a/third_party/WebKit/Source/bindings/modules/v8/V8BindingForModules.cpp
+++ b/third_party/WebKit/Source/bindings/modules/v8/V8BindingForModules.cpp
@@ -445,7 +445,7 @@
   v8::Local<v8::Array> array = v8::Array::New(isolate, values->size());
   for (size_t i = 0; i < values->size(); ++i) {
     v8::Local<v8::Value> v8_value =
-        DeserializeIDBValue(isolate, creation_context, values->at(i).Get());
+        DeserializeIDBValue(isolate, creation_context, values->at(i).get());
     if (v8_value.IsEmpty())
       v8_value = v8::Undefined(isolate);
     if (!V8CallBoolean(array->CreateDataProperty(context, i, v8_value)))
diff --git a/third_party/WebKit/Source/bindings/modules/v8/V8BindingForModulesTest.cpp b/third_party/WebKit/Source/bindings/modules/v8/V8BindingForModulesTest.cpp
index 312e570..4e3f3751 100644
--- a/third_party/WebKit/Source/bindings/modules/v8/V8BindingForModulesTest.cpp
+++ b/third_party/WebKit/Source/bindings/modules/v8/V8BindingForModulesTest.cpp
@@ -317,7 +317,7 @@
       CreateIDBValue(isolate, object_bytes, 42.0, "foo");
 
   v8::Local<v8::Value> v8_value = DeserializeIDBValue(
-      isolate, scope.GetContext()->Global(), idb_value.Get());
+      isolate, scope.GetContext()->Global(), idb_value.get());
   EXPECT_TRUE(!scope.GetExceptionState().HadException());
 
   ASSERT_TRUE(v8_value->IsObject());
@@ -349,7 +349,7 @@
       CreateIDBValue(isolate, object_bytes, 42.0, "foo");
 
   v8::Local<v8::Value> v8_value = DeserializeIDBValue(
-      isolate, scope.GetContext()->Global(), idb_value.Get());
+      isolate, scope.GetContext()->Global(), idb_value.get());
   EXPECT_TRUE(!scope.GetExceptionState().HadException());
   EXPECT_TRUE(v8_value->IsNull());
 }
@@ -367,7 +367,7 @@
       CreateIDBValue(isolate, object_bytes, 42.0, "foo");
 
   v8::Local<v8::Value> v8_value = DeserializeIDBValue(
-      isolate, scope.GetContext()->Global(), idb_value.Get());
+      isolate, scope.GetContext()->Global(), idb_value.get());
   EXPECT_TRUE(!scope.GetExceptionState().HadException());
   ASSERT_TRUE(v8_value->IsNumber());
   v8::Local<v8::Number> v8_number = v8_value.As<v8::Number>();
@@ -387,7 +387,7 @@
       CreateIDBValue(isolate, object_bytes, 42.0, "foo.bar");
 
   v8::Local<v8::Value> v8_value = DeserializeIDBValue(
-      isolate, scope.GetContext()->Global(), idb_value.Get());
+      isolate, scope.GetContext()->Global(), idb_value.get());
   EXPECT_TRUE(!scope.GetExceptionState().HadException());
   ASSERT_TRUE(v8_value->IsNumber());
   v8::Local<v8::Number> v8_number = v8_value.As<v8::Number>();
diff --git a/third_party/WebKit/Source/bindings/modules/v8/custom/V8CustomSQLStatementErrorCallback.cpp b/third_party/WebKit/Source/bindings/modules/v8/custom/V8CustomSQLStatementErrorCallback.cpp
index 0e83f93..3da3c7d 100644
--- a/third_party/WebKit/Source/bindings/modules/v8/custom/V8CustomSQLStatementErrorCallback.cpp
+++ b/third_party/WebKit/Source/bindings/modules/v8/custom/V8CustomSQLStatementErrorCallback.cpp
@@ -42,13 +42,13 @@
                                               SQLError* error) {
   v8::Isolate* isolate = script_state_->GetIsolate();
   ExecutionContext* execution_context =
-      ExecutionContext::From(script_state_.Get());
+      ExecutionContext::From(script_state_.get());
   if (!execution_context || execution_context->IsContextSuspended() ||
       execution_context->IsContextDestroyed())
     return true;
   if (!script_state_->ContextIsValid())
     return true;
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
 
   v8::Local<v8::Value> transaction_handle =
       ToV8(transaction, script_state_->GetContext()->Global(), isolate);
@@ -70,7 +70,7 @@
   // the error callback did not return false, or there was no error callback.
   // Jump to the last step in the overall steps.
   if (!V8ScriptRunner::CallFunction(callback_.NewLocal(isolate),
-                                    ExecutionContext::From(script_state_.Get()),
+                                    ExecutionContext::From(script_state_.get()),
                                     script_state_->GetContext()->Global(),
                                     WTF_ARRAY_LENGTH(argv), argv, isolate)
            .ToLocal(&result))
diff --git a/third_party/WebKit/Source/bindings/modules/v8/wasm/WasmResponseExtensions.cpp b/third_party/WebKit/Source/bindings/modules/v8/wasm/WasmResponseExtensions.cpp
index 24d6da9..208903e 100644
--- a/third_party/WebKit/Source/bindings/modules/v8/wasm/WasmResponseExtensions.cpp
+++ b/third_party/WebKit/Source/bindings/modules/v8/wasm/WasmResponseExtensions.cpp
@@ -64,7 +64,7 @@
           break;
         }
         case BytesConsumer::Result::kDone: {
-          ScriptState::Scope scope(script_state_.Get());
+          ScriptState::Scope scope(script_state_.get());
           builder_.Finish();
           client_->DidFetchDataLoadedCustomFormat();
           return;
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_dictionary.py b/third_party/WebKit/Source/bindings/scripts/v8_dictionary.py
index 17df959..0909d114 100644
--- a/third_party/WebKit/Source/bindings/scripts/v8_dictionary.py
+++ b/third_party/WebKit/Source/bindings/scripts/v8_dictionary.py
@@ -208,16 +208,13 @@
     def has_method_expression():
         if nullable_indicator_name:
             return nullable_indicator_name
-        elif idl_type.is_union_type:
-            return '!%s_.isNull()' % cpp_name
-        elif idl_type.is_enum or idl_type.is_string_type:
+        if idl_type.is_union_type or idl_type.is_enum or idl_type.is_string_type:
             return '!%s_.IsNull()' % cpp_name
-        elif idl_type.name in ['Any', 'Object']:
+        if idl_type.name in ['Any', 'Object']:
             return '!({0}_.IsEmpty() || {0}_.IsNull() || {0}_.IsUndefined())'.format(cpp_name)
-        elif idl_type.name == 'Dictionary':
+        if idl_type.name == 'Dictionary':
             return '!%s_.IsUndefinedOrNull()' % cpp_name
-        else:
-            return '%s_' % cpp_name
+        return '%s_' % cpp_name
 
     cpp_default_value = None
     if member.default_value and not member.default_value.is_null:
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_interface.py b/third_party/WebKit/Source/bindings/scripts/v8_interface.py
index 7c948d3e..254be609 100644
--- a/third_party/WebKit/Source/bindings/scripts/v8_interface.py
+++ b/third_party/WebKit/Source/bindings/scripts/v8_interface.py
@@ -1410,9 +1410,7 @@
         return None
 
     def is_null_expression(idl_type):
-        if idl_type.use_output_parameter_for_result:
-            return 'result.isNull()'
-        if idl_type.is_string_type:
+        if idl_type.use_output_parameter_for_result or idl_type.is_string_type:
             return 'result.IsNull()'
         if idl_type.is_interface_type:
             return '!result'
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_methods.py b/third_party/WebKit/Source/bindings/scripts/v8_methods.py
index 81a09e5..b199947 100644
--- a/third_party/WebKit/Source/bindings/scripts/v8_methods.py
+++ b/third_party/WebKit/Source/bindings/scripts/v8_methods.py
@@ -491,7 +491,7 @@
         member_type_name = (member_type.inner_type.name
                             if member_type.is_nullable else
                             member_type.name)
-        return '%s.set%s(%s)' % (argument.name, member_type_name,
+        return '%s.Set%s(%s)' % (argument.name, member_type_name,
                                  member_type.literal_cpp_value(default_value))
     return '%s = %s' % (argument.name,
                         idl_type.literal_cpp_value(default_value))
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_types.py b/third_party/WebKit/Source/bindings/scripts/v8_types.py
index c44b26c..7c56ebecf 100644
--- a/third_party/WebKit/Source/bindings/scripts/v8_types.py
+++ b/third_party/WebKit/Source/bindings/scripts/v8_types.py
@@ -1036,7 +1036,7 @@
     else:
         raise ValueError('Unsupported literal type: ' + idl_literal.idl_type)
 
-    return '%s::from%s(%s)' % (idl_type.name, member_type.name,
+    return '%s::From%s(%s)' % (idl_type.name, member_type.name,
                                member_type.literal_cpp_value(idl_literal))
 
 
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_union.py b/third_party/WebKit/Source/bindings/scripts/v8_union.py
index 57b1d94..7778c88 100644
--- a/third_party/WebKit/Source/bindings/scripts/v8_union.py
+++ b/third_party/WebKit/Source/bindings/scripts/v8_union.py
@@ -148,14 +148,14 @@
         'cpp_type': member.cpp_type_args(used_in_cpp_sequence=True),
         'cpp_local_type': member.cpp_type,
         'cpp_value_to_v8_value': member.cpp_value_to_v8_value(
-            cpp_value='impl.getAs%s()' % member.name, isolate='isolate',
+            cpp_value='impl.GetAs%s()' % member.name, isolate='isolate',
             creation_context='creationContext'),
         'enum_values': member.enum_values,
         'is_array_buffer_or_view_type': member.is_array_buffer_or_view,
         'is_array_buffer_view_or_typed_array': member.is_array_buffer_view_or_typed_array,
         'is_traceable': member.is_traceable,
         'rvalue_cpp_type': member.cpp_type_args(used_as_rvalue_type=True),
-        'specific_type_enum': 'SpecificType' + member.name,
+        'specific_type_enum': 'k' + member.name,
         'type_name': member.name,
         'v8_value_to_local_cpp_value': member.v8_value_to_local_cpp_value(
             {}, 'v8Value', 'cppValue', isolate='isolate',
diff --git a/third_party/WebKit/Source/bindings/templates/callback_function.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/callback_function.cpp.tmpl
index adab1f0d..25f3a054 100644
--- a/third_party/WebKit/Source/bindings/templates/callback_function.cpp.tmpl
+++ b/third_party/WebKit/Source/bindings/templates/callback_function.cpp.tmpl
@@ -48,12 +48,12 @@
   }
   {% endfor %}
 
-  ExecutionContext* context = ExecutionContext::From(script_state_.Get());
+  ExecutionContext* context = ExecutionContext::From(script_state_.get());
   DCHECK(context);
   if (context->IsContextSuspended() || context->IsContextDestroyed())
     return false;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Isolate* isolate = script_state_->GetIsolate();
 
   v8::Local<v8::Value> thisValue = ToV8(
diff --git a/third_party/WebKit/Source/bindings/templates/callback_interface.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/callback_interface.cpp.tmpl
index 28615cd..aad3f1c15 100644
--- a/third_party/WebKit/Source/bindings/templates/callback_interface.cpp.tmpl
+++ b/third_party/WebKit/Source/bindings/templates/callback_interface.cpp.tmpl
@@ -27,12 +27,12 @@
   if (!script_state_->ContextIsValid())
     {{return_default}};
   ExecutionContext* executionContext =
-      ExecutionContext::From(script_state_.Get());
+      ExecutionContext::From(script_state_.get());
   DCHECK(!executionContext->IsContextSuspended());
   if (!executionContext || executionContext->IsContextDestroyed())
     {{return_default}};
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   {% if method.call_with_this_handle %}
   v8::Local<v8::Value> thisHandle = thisValue.V8Value();
   {% endif %}
@@ -62,7 +62,7 @@
   return !exceptionCatcher.HasCaught();
   {% else %}{# void #}
   V8ScriptRunner::CallFunction(callback_.NewLocal(isolate),
-                               ExecutionContext::From(script_state_.Get()),
+                               ExecutionContext::From(script_state_.get()),
                                {{this_handle_parameter}},
                                {{method.arguments | length}},
                                argv,
diff --git a/third_party/WebKit/Source/bindings/templates/methods.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/methods.cpp.tmpl
index b29ec7cc..4c65cd3 100644
--- a/third_party/WebKit/Source/bindings/templates/methods.cpp.tmpl
+++ b/third_party/WebKit/Source/bindings/templates/methods.cpp.tmpl
@@ -491,7 +491,7 @@
   // FIXME: Only pass scriptState/exceptionState if instance really requires it.
   ScriptState* scriptState = ScriptState::Current(info.GetIsolate());
   message->UnregisterMemoryAllocatedWithCurrentScriptContext();
-  instance->postMessage(scriptState, message.Get(), transferables.message_ports, exceptionState);
+  instance->postMessage(scriptState, message.get(), transferables.message_ports, exceptionState);
 }
 {% endmacro %}
 
diff --git a/third_party/WebKit/Source/bindings/templates/union_container.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/union_container.cpp.tmpl
index 03aa0ff..4420b8a 100644
--- a/third_party/WebKit/Source/bindings/templates/union_container.cpp.tmpl
+++ b/third_party/WebKit/Source/bindings/templates/union_container.cpp.tmpl
@@ -14,7 +14,7 @@
 {% else %}
   {{member.cpp_local_type}} cppValue = V8{{member.type_name}}::ToImpl(v8::Local<v8::Object>::Cast(v8Value));
 {% endif %}
-  impl.set{{member.type_name}}(cppValue);
+  impl.Set{{member.type_name}}(cppValue);
   return;
 }
 {% endmacro %}
@@ -29,16 +29,16 @@
 
 namespace blink {
 
-{{cpp_class}}::{{cpp_class}}() : type_(SpecificTypeNone) {}
+{{cpp_class}}::{{cpp_class}}() : type_(SpecificType::kNone) {}
 
 {% for member in members %}
-{{member.rvalue_cpp_type}} {{cpp_class}}::getAs{{member.type_name}}() const {
-  DCHECK(is{{member.type_name}}());
+{{member.rvalue_cpp_type}} {{cpp_class}}::GetAs{{member.type_name}}() const {
+  DCHECK(Is{{member.type_name}}());
   return {{member.cpp_name}}_;
 }
 
-void {{cpp_class}}::set{{member.type_name}}({{member.rvalue_cpp_type}} value) {
-  DCHECK(isNull());
+void {{cpp_class}}::Set{{member.type_name}}({{member.rvalue_cpp_type}} value) {
+  DCHECK(IsNull());
   {% if member.enum_values %}
   NonThrowableExceptionState exceptionState;
   {{declare_enum_validation_variable(member.enum_values) | indent(2)}}
@@ -52,12 +52,12 @@
   {% else %}
   {{member.cpp_name}}_ = value;
   {% endif %}
-  type_ = {{member.specific_type_enum}};
+  type_ = SpecificType::{{member.specific_type_enum}};
 }
 
-{{cpp_class}} {{cpp_class}}::from{{member.type_name}}({{member.rvalue_cpp_type}} value) {
+{{cpp_class}} {{cpp_class}}::From{{member.type_name}}({{member.rvalue_cpp_type}} value) {
   {{cpp_class}} container;
-  container.set{{member.type_name}}(value);
+  container.Set{{member.type_name}}(value);
   return container;
 }
 
@@ -86,7 +86,7 @@
   {# 3. Dictionaries for null or undefined #}
   if (IsUndefinedOrNull(v8Value)) {
     {{v8_value_to_local_cpp_value(dictionary_type) | indent}}
-    impl.set{{dictionary_type.type_name}}(cppValue);
+    impl.Set{{dictionary_type.type_name}}(cppValue);
     return;
   }
 
@@ -111,7 +111,7 @@
   {# 11.1, 11.2. Sequences and frozen arrays #}
   if (HasCallableIteratorSymbol(isolate, v8Value, exceptionState)) {
     {{v8_value_to_local_cpp_value(array_or_sequence_type) | indent}}
-    impl.set{{array_or_sequence_type.type_name}}(cppValue);
+    impl.Set{{array_or_sequence_type.type_name}}(cppValue);
     return;
   }
 
@@ -120,7 +120,7 @@
   {# 11.3. Dictionaries #}
   if (v8Value->IsObject()) {
     {{v8_value_to_local_cpp_value(dictionary_type) | indent}}
-    impl.set{{dictionary_type.type_name}}(cppValue);
+    impl.Set{{dictionary_type.type_name}}(cppValue);
     return;
   }
 
@@ -129,7 +129,7 @@
   {% if record_type %}
   if (v8Value->IsObject()) {
     {{v8_value_to_local_cpp_value(record_type) | indent}}
-    impl.set{{record_type.type_name}}(cppValue);
+    impl.Set{{record_type.type_name}}(cppValue);
     return;
   }
 
@@ -139,7 +139,7 @@
   {% if object_type %}
   if (IsUndefinedOrNull(v8Value) || v8Value->IsObject()) {
     {{v8_value_to_local_cpp_value(object_type) | indent}}
-    impl.set{{object_type.type_name}}(cppValue);
+    impl.Set{{object_type.type_name}}(cppValue);
     return;
   }
 
@@ -149,7 +149,7 @@
   {% if boolean_type %}
   {# 12. Boolean #}
   if (v8Value->IsBoolean()) {
-    impl.setBoolean(v8Value.As<v8::Boolean>()->Value());
+    impl.SetBoolean(v8Value.As<v8::Boolean>()->Value());
     return;
   }
 
@@ -158,7 +158,7 @@
   {# 13. Number #}
   if (v8Value->IsNumber()) {
     {{v8_value_to_local_cpp_value(numeric_type) | indent}}
-    impl.set{{numeric_type.type_name}}(cppValue);
+    impl.Set{{numeric_type.type_name}}(cppValue);
     return;
   }
 
@@ -172,7 +172,7 @@
     if (!IsValidEnum(cppValue, validValues, WTF_ARRAY_LENGTH(validValues), "{{string_type.type_name}}", exceptionState))
       return;
     {% endif %}
-    impl.set{{string_type.type_name}}(cppValue);
+    impl.Set{{string_type.type_name}}(cppValue);
     return;
   }
 
@@ -180,14 +180,14 @@
   {% elif numeric_type %}
   {
     {{v8_value_to_local_cpp_value(numeric_type) | indent}}
-    impl.set{{numeric_type.type_name}}(cppValue);
+    impl.Set{{numeric_type.type_name}}(cppValue);
     return;
   }
 
   {# 16. Boolean (fallback) #}
   {% elif boolean_type %}
   {
-    impl.setBoolean(v8Value->BooleanValue());
+    impl.SetBoolean(v8Value->BooleanValue());
     return;
   }
 
@@ -199,11 +199,11 @@
 
 v8::Local<v8::Value> ToV8(const {{cpp_class}}& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case {{cpp_class}}::SpecificTypeNone:
+    case {{cpp_class}}::SpecificType::kNone:
       {# FIXME: We might want to return undefined in some cases #}
       return v8::Null(isolate);
     {% for member in members %}
-    case {{cpp_class}}::{{member.specific_type_enum}}:
+    case {{cpp_class}}::SpecificType::{{member.specific_type_enum}}:
       return {{member.cpp_value_to_v8_value}};
     {% endfor %}
     default:
diff --git a/third_party/WebKit/Source/bindings/templates/union_container.h.tmpl b/third_party/WebKit/Source/bindings/templates/union_container.h.tmpl
index 44dec7e..10b283f5 100644
--- a/third_party/WebKit/Source/bindings/templates/union_container.h.tmpl
+++ b/third_party/WebKit/Source/bindings/templates/union_container.h.tmpl
@@ -18,13 +18,13 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   {{cpp_class}}();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
   {% for member in members %}
-  bool is{{member.type_name}}() const { return type_ == {{member.specific_type_enum}}; }
-  {{member.rvalue_cpp_type}} getAs{{member.type_name}}() const;
-  void set{{member.type_name}}({{member.rvalue_cpp_type}});
-  static {{cpp_class}} from{{member.type_name}}({{member.rvalue_cpp_type}});
+  bool Is{{member.type_name}}() const { return type_ == SpecificType::{{member.specific_type_enum}}; }
+  {{member.rvalue_cpp_type}} GetAs{{member.type_name}}() const;
+  void Set{{member.type_name}}({{member.rvalue_cpp_type}});
+  static {{cpp_class}} From{{member.type_name}}({{member.rvalue_cpp_type}});
 
   {% endfor %}
   {{cpp_class}}(const {{cpp_class}}&);
@@ -33,13 +33,13 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
+  enum class SpecificType {
+    kNone,
     {% for member in members %}
     {{member.specific_type_enum}},
     {% endfor %}
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   {% for member in members %}
   {{member.cpp_type}} {{member.cpp_name}}_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/TestDictionary.cpp b/third_party/WebKit/Source/bindings/tests/results/core/TestDictionary.cpp
index 38abc17..ada07e5 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/TestDictionary.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/TestDictionary.cpp
@@ -21,10 +21,10 @@
 namespace blink {
 
 TestDictionary::TestDictionary() {
-  setDoubleOrStringMember(DoubleOrString::fromDouble(3.14));
+  setDoubleOrStringMember(DoubleOrString::FromDouble(3.14));
   setEnumMember("foo");
   setLongMember(1);
-  setOtherDoubleOrStringMember(DoubleOrString::fromString("default string value"));
+  setOtherDoubleOrStringMember(DoubleOrString::FromString("default string value"));
   setRestrictedDoubleMember(3.14);
   setStringOrNullMember("default string value");
   setStringSequenceMember(Vector<String>());
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/TestDictionary.h b/third_party/WebKit/Source/bindings/tests/results/core/TestDictionary.h
index fd0f732..a465e56 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/TestDictionary.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/TestDictionary.h
@@ -98,7 +98,7 @@
   inline void setDoubleOrNullMember(double);
   inline void setDoubleOrNullMemberToNull();
 
-  bool hasDoubleOrStringMember() const { return !double_or_string_member_.isNull(); }
+  bool hasDoubleOrStringMember() const { return !double_or_string_member_.IsNull(); }
   const DoubleOrString& doubleOrStringMember() const {
     return double_or_string_member_;
   }
@@ -178,7 +178,7 @@
   void setObjectOrNullMember(ScriptValue);
   void setObjectOrNullMemberToNull();
 
-  bool hasOtherDoubleOrStringMember() const { return !other_double_or_string_member_.isNull(); }
+  bool hasOtherDoubleOrStringMember() const { return !other_double_or_string_member_.IsNull(); }
   const DoubleOrString& otherDoubleOrStringMember() const {
     return other_double_or_string_member_;
   }
@@ -225,7 +225,7 @@
   }
   void setStringSequenceMember(const Vector<String>&);
 
-  bool hasTestInterface2OrUint8ArrayMember() const { return !test_interface_2_or_uint8_array_member_.isNull(); }
+  bool hasTestInterface2OrUint8ArrayMember() const { return !test_interface_2_or_uint8_array_member_.IsNull(); }
   const TestInterface2OrUint8Array& testInterface2OrUint8ArrayMember() const {
     return test_interface_2_or_uint8_array_member_;
   }
@@ -298,7 +298,7 @@
   }
   void setUnionInRecordMember(const HeapVector<std::pair<String, LongOrBoolean>>&);
 
-  bool hasUnionWithTypedefs() const { return !union_with_typedefs_.isNull(); }
+  bool hasUnionWithTypedefs() const { return !union_with_typedefs_.IsNull(); }
   const FloatOrBoolean& unionWithTypedefs() const {
     return union_with_typedefs_;
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackInterface.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackInterface.cpp
index 6512d10..ec12f73 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackInterface.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackInterface.cpp
@@ -38,18 +38,18 @@
   if (!script_state_->ContextIsValid())
     return;
   ExecutionContext* executionContext =
-      ExecutionContext::From(script_state_.Get());
+      ExecutionContext::From(script_state_.get());
   DCHECK(!executionContext->IsContextSuspended());
   if (!executionContext || executionContext->IsContextDestroyed())
     return;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
 
   v8::Local<v8::Value> *argv = 0;
 
   v8::Isolate* isolate = script_state_->GetIsolate();
   V8ScriptRunner::CallFunction(callback_.NewLocal(isolate),
-                               ExecutionContext::From(script_state_.Get()),
+                               ExecutionContext::From(script_state_.get()),
                                v8::Undefined(isolate),
                                0,
                                argv,
@@ -60,12 +60,12 @@
   if (!script_state_->ContextIsValid())
     return true;
   ExecutionContext* executionContext =
-      ExecutionContext::From(script_state_.Get());
+      ExecutionContext::From(script_state_.get());
   DCHECK(!executionContext->IsContextSuspended());
   if (!executionContext || executionContext->IsContextDestroyed())
     return true;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
 
   v8::Local<v8::Value> *argv = 0;
 
@@ -85,19 +85,19 @@
   if (!script_state_->ContextIsValid())
     return;
   ExecutionContext* executionContext =
-      ExecutionContext::From(script_state_.Get());
+      ExecutionContext::From(script_state_.get());
   DCHECK(!executionContext->IsContextSuspended());
   if (!executionContext || executionContext->IsContextDestroyed())
     return;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
 
   v8::Local<v8::Value> boolArgHandle = v8::Boolean::New(script_state_->GetIsolate(), boolArg);
   v8::Local<v8::Value> argv[] = { boolArgHandle };
 
   v8::Isolate* isolate = script_state_->GetIsolate();
   V8ScriptRunner::CallFunction(callback_.NewLocal(isolate),
-                               ExecutionContext::From(script_state_.Get()),
+                               ExecutionContext::From(script_state_.get()),
                                v8::Undefined(isolate),
                                1,
                                argv,
@@ -108,19 +108,19 @@
   if (!script_state_->ContextIsValid())
     return;
   ExecutionContext* executionContext =
-      ExecutionContext::From(script_state_.Get());
+      ExecutionContext::From(script_state_.get());
   DCHECK(!executionContext->IsContextSuspended());
   if (!executionContext || executionContext->IsContextDestroyed())
     return;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
 
   v8::Local<v8::Value> sequenceArgHandle = ToV8(sequenceArg, script_state_->GetContext()->Global(), script_state_->GetIsolate());
   v8::Local<v8::Value> argv[] = { sequenceArgHandle };
 
   v8::Isolate* isolate = script_state_->GetIsolate();
   V8ScriptRunner::CallFunction(callback_.NewLocal(isolate),
-                               ExecutionContext::From(script_state_.Get()),
+                               ExecutionContext::From(script_state_.get()),
                                v8::Undefined(isolate),
                                1,
                                argv,
@@ -131,19 +131,19 @@
   if (!script_state_->ContextIsValid())
     return;
   ExecutionContext* executionContext =
-      ExecutionContext::From(script_state_.Get());
+      ExecutionContext::From(script_state_.get());
   DCHECK(!executionContext->IsContextSuspended());
   if (!executionContext || executionContext->IsContextDestroyed())
     return;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
 
   v8::Local<v8::Value> floatArgHandle = v8::Number::New(script_state_->GetIsolate(), floatArg);
   v8::Local<v8::Value> argv[] = { floatArgHandle };
 
   v8::Isolate* isolate = script_state_->GetIsolate();
   V8ScriptRunner::CallFunction(callback_.NewLocal(isolate),
-                               ExecutionContext::From(script_state_.Get()),
+                               ExecutionContext::From(script_state_.get()),
                                v8::Undefined(isolate),
                                1,
                                argv,
@@ -154,19 +154,19 @@
   if (!script_state_->ContextIsValid())
     return;
   ExecutionContext* executionContext =
-      ExecutionContext::From(script_state_.Get());
+      ExecutionContext::From(script_state_.get());
   DCHECK(!executionContext->IsContextSuspended());
   if (!executionContext || executionContext->IsContextDestroyed())
     return;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
 
   v8::Local<v8::Value> testInterfaceEmptyArgHandle = ToV8(testInterfaceEmptyArg, script_state_->GetContext()->Global(), script_state_->GetIsolate());
   v8::Local<v8::Value> argv[] = { testInterfaceEmptyArgHandle };
 
   v8::Isolate* isolate = script_state_->GetIsolate();
   V8ScriptRunner::CallFunction(callback_.NewLocal(isolate),
-                               ExecutionContext::From(script_state_.Get()),
+                               ExecutionContext::From(script_state_.get()),
                                v8::Undefined(isolate),
                                1,
                                argv,
@@ -177,12 +177,12 @@
   if (!script_state_->ContextIsValid())
     return;
   ExecutionContext* executionContext =
-      ExecutionContext::From(script_state_.Get());
+      ExecutionContext::From(script_state_.get());
   DCHECK(!executionContext->IsContextSuspended());
   if (!executionContext || executionContext->IsContextDestroyed())
     return;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
 
   v8::Local<v8::Value> testInterfaceEmptyArgHandle = ToV8(testInterfaceEmptyArg, script_state_->GetContext()->Global(), script_state_->GetIsolate());
   v8::Local<v8::Value> stringArgHandle = V8String(script_state_->GetIsolate(), stringArg);
@@ -190,7 +190,7 @@
 
   v8::Isolate* isolate = script_state_->GetIsolate();
   V8ScriptRunner::CallFunction(callback_.NewLocal(isolate),
-                               ExecutionContext::From(script_state_.Get()),
+                               ExecutionContext::From(script_state_.get()),
                                v8::Undefined(isolate),
                                2,
                                argv,
@@ -201,12 +201,12 @@
   if (!script_state_->ContextIsValid())
     return;
   ExecutionContext* executionContext =
-      ExecutionContext::From(script_state_.Get());
+      ExecutionContext::From(script_state_.get());
   DCHECK(!executionContext->IsContextSuspended());
   if (!executionContext || executionContext->IsContextDestroyed())
     return;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Local<v8::Value> thisHandle = thisValue.V8Value();
 
   v8::Local<v8::Value> stringArgHandle = V8String(script_state_->GetIsolate(), stringArg);
@@ -214,7 +214,7 @@
 
   v8::Isolate* isolate = script_state_->GetIsolate();
   V8ScriptRunner::CallFunction(callback_.NewLocal(isolate),
-                               ExecutionContext::From(script_state_.Get()),
+                               ExecutionContext::From(script_state_.get()),
                                thisHandle,
                                1,
                                argv,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestDictionary.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestDictionary.cpp
index 2c2471b..24d9991 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestDictionary.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestDictionary.cpp
@@ -848,7 +848,7 @@
     doubleOrStringMemberValue = ToV8(impl.doubleOrStringMember(), creationContext, isolate);
     doubleOrStringMemberHasValueOrDefault = true;
   } else {
-    doubleOrStringMemberValue = ToV8(DoubleOrString::fromDouble(3.14), creationContext, isolate);
+    doubleOrStringMemberValue = ToV8(DoubleOrString::FromDouble(3.14), creationContext, isolate);
     doubleOrStringMemberHasValueOrDefault = true;
   }
   if (doubleOrStringMemberHasValueOrDefault &&
@@ -986,7 +986,7 @@
     otherDoubleOrStringMemberValue = ToV8(impl.otherDoubleOrStringMember(), creationContext, isolate);
     otherDoubleOrStringMemberHasValueOrDefault = true;
   } else {
-    otherDoubleOrStringMemberValue = ToV8(DoubleOrString::fromString("default string value"), creationContext, isolate);
+    otherDoubleOrStringMemberValue = ToV8(DoubleOrString::FromString("default string value"), creationContext, isolate);
     otherDoubleOrStringMemberHasValueOrDefault = true;
   }
   if (otherDoubleOrStringMemberHasValueOrDefault &&
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
index de78eb2..a4ae896 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
@@ -6450,14 +6450,14 @@
     if (exceptionState.HadException())
       return;
   } else {
-    defaultLongArg.setDouble(10);
+    defaultLongArg.SetDouble(10);
   }
   if (!info[1]->IsUndefined()) {
     V8DoubleOrStringOrNull::ToImpl(info.GetIsolate(), info[1], defaultStringArg, UnionTypeConversionMode::kNullable, exceptionState);
     if (exceptionState.HadException())
       return;
   } else {
-    defaultStringArg.setString("foo");
+    defaultStringArg.SetString("foo");
   }
   if (!info[2]->IsUndefined()) {
     V8DoubleOrString::ToImpl(info.GetIsolate(), info[2], defaultNullArg, UnionTypeConversionMode::kNullable, exceptionState);
@@ -8460,7 +8460,7 @@
   // FIXME: Only pass scriptState/exceptionState if instance really requires it.
   ScriptState* scriptState = ScriptState::Current(info.GetIsolate());
   message->UnregisterMemoryAllocatedWithCurrentScriptContext();
-  instance->postMessage(scriptState, message.Get(), transferables.message_ports, exceptionState);
+  instance->postMessage(scriptState, message.get(), transferables.message_ports, exceptionState);
 }
 
 static void activityLoggingForAllWorldsPerWorldBindingsVoidMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp
index ff5131f..8db100c 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp
@@ -94,7 +94,7 @@
   TestSpecialOperations* impl = V8TestSpecialOperations::ToImpl(info.Holder());
   NodeOrNodeList result;
   impl->getItem(name, result);
-  if (result.isNull())
+  if (result.IsNull())
     return;
   V8SetReturnValue(info, result);
 }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/array_buffer_or_array_buffer_view_or_dictionary.cc b/third_party/WebKit/Source/bindings/tests/results/core/array_buffer_or_array_buffer_view_or_dictionary.cc
index 459fdf7..c123299 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/array_buffer_or_array_buffer_view_or_dictionary.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/array_buffer_or_array_buffer_view_or_dictionary.cc
@@ -17,56 +17,56 @@
 
 namespace blink {
 
-ArrayBufferOrArrayBufferViewOrDictionary::ArrayBufferOrArrayBufferViewOrDictionary() : type_(SpecificTypeNone) {}
+ArrayBufferOrArrayBufferViewOrDictionary::ArrayBufferOrArrayBufferViewOrDictionary() : type_(SpecificType::kNone) {}
 
-TestArrayBuffer* ArrayBufferOrArrayBufferViewOrDictionary::getAsArrayBuffer() const {
-  DCHECK(isArrayBuffer());
+TestArrayBuffer* ArrayBufferOrArrayBufferViewOrDictionary::GetAsArrayBuffer() const {
+  DCHECK(IsArrayBuffer());
   return array_buffer_;
 }
 
-void ArrayBufferOrArrayBufferViewOrDictionary::setArrayBuffer(TestArrayBuffer* value) {
-  DCHECK(isNull());
+void ArrayBufferOrArrayBufferViewOrDictionary::SetArrayBuffer(TestArrayBuffer* value) {
+  DCHECK(IsNull());
   array_buffer_ = value;
-  type_ = SpecificTypeArrayBuffer;
+  type_ = SpecificType::kArrayBuffer;
 }
 
-ArrayBufferOrArrayBufferViewOrDictionary ArrayBufferOrArrayBufferViewOrDictionary::fromArrayBuffer(TestArrayBuffer* value) {
+ArrayBufferOrArrayBufferViewOrDictionary ArrayBufferOrArrayBufferViewOrDictionary::FromArrayBuffer(TestArrayBuffer* value) {
   ArrayBufferOrArrayBufferViewOrDictionary container;
-  container.setArrayBuffer(value);
+  container.SetArrayBuffer(value);
   return container;
 }
 
-NotShared<TestArrayBufferView> ArrayBufferOrArrayBufferViewOrDictionary::getAsArrayBufferView() const {
-  DCHECK(isArrayBufferView());
+NotShared<TestArrayBufferView> ArrayBufferOrArrayBufferViewOrDictionary::GetAsArrayBufferView() const {
+  DCHECK(IsArrayBufferView());
   return array_buffer_view_;
 }
 
-void ArrayBufferOrArrayBufferViewOrDictionary::setArrayBufferView(NotShared<TestArrayBufferView> value) {
-  DCHECK(isNull());
+void ArrayBufferOrArrayBufferViewOrDictionary::SetArrayBufferView(NotShared<TestArrayBufferView> value) {
+  DCHECK(IsNull());
   array_buffer_view_ = Member<TestArrayBufferView>(value.View());
-  type_ = SpecificTypeArrayBufferView;
+  type_ = SpecificType::kArrayBufferView;
 }
 
-ArrayBufferOrArrayBufferViewOrDictionary ArrayBufferOrArrayBufferViewOrDictionary::fromArrayBufferView(NotShared<TestArrayBufferView> value) {
+ArrayBufferOrArrayBufferViewOrDictionary ArrayBufferOrArrayBufferViewOrDictionary::FromArrayBufferView(NotShared<TestArrayBufferView> value) {
   ArrayBufferOrArrayBufferViewOrDictionary container;
-  container.setArrayBufferView(value);
+  container.SetArrayBufferView(value);
   return container;
 }
 
-Dictionary ArrayBufferOrArrayBufferViewOrDictionary::getAsDictionary() const {
-  DCHECK(isDictionary());
+Dictionary ArrayBufferOrArrayBufferViewOrDictionary::GetAsDictionary() const {
+  DCHECK(IsDictionary());
   return dictionary_;
 }
 
-void ArrayBufferOrArrayBufferViewOrDictionary::setDictionary(Dictionary value) {
-  DCHECK(isNull());
+void ArrayBufferOrArrayBufferViewOrDictionary::SetDictionary(Dictionary value) {
+  DCHECK(IsNull());
   dictionary_ = value;
-  type_ = SpecificTypeDictionary;
+  type_ = SpecificType::kDictionary;
 }
 
-ArrayBufferOrArrayBufferViewOrDictionary ArrayBufferOrArrayBufferViewOrDictionary::fromDictionary(Dictionary value) {
+ArrayBufferOrArrayBufferViewOrDictionary ArrayBufferOrArrayBufferViewOrDictionary::FromDictionary(Dictionary value) {
   ArrayBufferOrArrayBufferViewOrDictionary container;
-  container.setDictionary(value);
+  container.SetDictionary(value);
   return container;
 }
 
@@ -88,7 +88,7 @@
 
   if (v8Value->IsArrayBuffer()) {
     TestArrayBuffer* cppValue = V8ArrayBuffer::ToImpl(v8::Local<v8::Object>::Cast(v8Value));
-    impl.setArrayBuffer(cppValue);
+    impl.SetArrayBuffer(cppValue);
     return;
   }
 
@@ -96,7 +96,7 @@
     NotShared<TestArrayBufferView> cppValue = ToNotShared<NotShared<TestArrayBufferView>>(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setArrayBufferView(cppValue);
+    impl.SetArrayBufferView(cppValue);
     return;
   }
 
@@ -104,7 +104,7 @@
     Dictionary cppValue = NativeValueTraits<Dictionary>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setDictionary(cppValue);
+    impl.SetDictionary(cppValue);
     return;
   }
 
@@ -113,14 +113,14 @@
 
 v8::Local<v8::Value> ToV8(const ArrayBufferOrArrayBufferViewOrDictionary& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case ArrayBufferOrArrayBufferViewOrDictionary::SpecificTypeNone:
+    case ArrayBufferOrArrayBufferViewOrDictionary::SpecificType::kNone:
       return v8::Null(isolate);
-    case ArrayBufferOrArrayBufferViewOrDictionary::SpecificTypeArrayBuffer:
-      return ToV8(impl.getAsArrayBuffer(), creationContext, isolate);
-    case ArrayBufferOrArrayBufferViewOrDictionary::SpecificTypeArrayBufferView:
-      return ToV8(impl.getAsArrayBufferView(), creationContext, isolate);
-    case ArrayBufferOrArrayBufferViewOrDictionary::SpecificTypeDictionary:
-      return impl.getAsDictionary().V8Value();
+    case ArrayBufferOrArrayBufferViewOrDictionary::SpecificType::kArrayBuffer:
+      return ToV8(impl.GetAsArrayBuffer(), creationContext, isolate);
+    case ArrayBufferOrArrayBufferViewOrDictionary::SpecificType::kArrayBufferView:
+      return ToV8(impl.GetAsArrayBufferView(), creationContext, isolate);
+    case ArrayBufferOrArrayBufferViewOrDictionary::SpecificType::kDictionary:
+      return impl.GetAsDictionary().V8Value();
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/array_buffer_or_array_buffer_view_or_dictionary.h b/third_party/WebKit/Source/bindings/tests/results/core/array_buffer_or_array_buffer_view_or_dictionary.h
index 70e41e7..a298ddb 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/array_buffer_or_array_buffer_view_or_dictionary.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/array_buffer_or_array_buffer_view_or_dictionary.h
@@ -30,22 +30,22 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   ArrayBufferOrArrayBufferViewOrDictionary();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isArrayBuffer() const { return type_ == SpecificTypeArrayBuffer; }
-  TestArrayBuffer* getAsArrayBuffer() const;
-  void setArrayBuffer(TestArrayBuffer*);
-  static ArrayBufferOrArrayBufferViewOrDictionary fromArrayBuffer(TestArrayBuffer*);
+  bool IsArrayBuffer() const { return type_ == SpecificType::kArrayBuffer; }
+  TestArrayBuffer* GetAsArrayBuffer() const;
+  void SetArrayBuffer(TestArrayBuffer*);
+  static ArrayBufferOrArrayBufferViewOrDictionary FromArrayBuffer(TestArrayBuffer*);
 
-  bool isArrayBufferView() const { return type_ == SpecificTypeArrayBufferView; }
-  NotShared<TestArrayBufferView> getAsArrayBufferView() const;
-  void setArrayBufferView(NotShared<TestArrayBufferView>);
-  static ArrayBufferOrArrayBufferViewOrDictionary fromArrayBufferView(NotShared<TestArrayBufferView>);
+  bool IsArrayBufferView() const { return type_ == SpecificType::kArrayBufferView; }
+  NotShared<TestArrayBufferView> GetAsArrayBufferView() const;
+  void SetArrayBufferView(NotShared<TestArrayBufferView>);
+  static ArrayBufferOrArrayBufferViewOrDictionary FromArrayBufferView(NotShared<TestArrayBufferView>);
 
-  bool isDictionary() const { return type_ == SpecificTypeDictionary; }
-  Dictionary getAsDictionary() const;
-  void setDictionary(Dictionary);
-  static ArrayBufferOrArrayBufferViewOrDictionary fromDictionary(Dictionary);
+  bool IsDictionary() const { return type_ == SpecificType::kDictionary; }
+  Dictionary GetAsDictionary() const;
+  void SetDictionary(Dictionary);
+  static ArrayBufferOrArrayBufferViewOrDictionary FromDictionary(Dictionary);
 
   ArrayBufferOrArrayBufferViewOrDictionary(const ArrayBufferOrArrayBufferViewOrDictionary&);
   ~ArrayBufferOrArrayBufferViewOrDictionary();
@@ -53,13 +53,13 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeArrayBuffer,
-    SpecificTypeArrayBufferView,
-    SpecificTypeDictionary,
+  enum class SpecificType {
+    kNone,
+    kArrayBuffer,
+    kArrayBufferView,
+    kDictionary,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   Member<TestArrayBuffer> array_buffer_;
   Member<TestArrayBufferView> array_buffer_view_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_element_sequence.cc b/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_element_sequence.cc
index 3f4e8f7..de7d9296 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_element_sequence.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_element_sequence.cc
@@ -23,39 +23,39 @@
 
 namespace blink {
 
-BooleanOrElementSequence::BooleanOrElementSequence() : type_(SpecificTypeNone) {}
+BooleanOrElementSequence::BooleanOrElementSequence() : type_(SpecificType::kNone) {}
 
-bool BooleanOrElementSequence::getAsBoolean() const {
-  DCHECK(isBoolean());
+bool BooleanOrElementSequence::GetAsBoolean() const {
+  DCHECK(IsBoolean());
   return boolean_;
 }
 
-void BooleanOrElementSequence::setBoolean(bool value) {
-  DCHECK(isNull());
+void BooleanOrElementSequence::SetBoolean(bool value) {
+  DCHECK(IsNull());
   boolean_ = value;
-  type_ = SpecificTypeBoolean;
+  type_ = SpecificType::kBoolean;
 }
 
-BooleanOrElementSequence BooleanOrElementSequence::fromBoolean(bool value) {
+BooleanOrElementSequence BooleanOrElementSequence::FromBoolean(bool value) {
   BooleanOrElementSequence container;
-  container.setBoolean(value);
+  container.SetBoolean(value);
   return container;
 }
 
-const HeapVector<Member<Element>>& BooleanOrElementSequence::getAsElementSequence() const {
-  DCHECK(isElementSequence());
+const HeapVector<Member<Element>>& BooleanOrElementSequence::GetAsElementSequence() const {
+  DCHECK(IsElementSequence());
   return element_sequence_;
 }
 
-void BooleanOrElementSequence::setElementSequence(const HeapVector<Member<Element>>& value) {
-  DCHECK(isNull());
+void BooleanOrElementSequence::SetElementSequence(const HeapVector<Member<Element>>& value) {
+  DCHECK(IsNull());
   element_sequence_ = value;
-  type_ = SpecificTypeElementSequence;
+  type_ = SpecificType::kElementSequence;
 }
 
-BooleanOrElementSequence BooleanOrElementSequence::fromElementSequence(const HeapVector<Member<Element>>& value) {
+BooleanOrElementSequence BooleanOrElementSequence::FromElementSequence(const HeapVector<Member<Element>>& value) {
   BooleanOrElementSequence container;
-  container.setElementSequence(value);
+  container.SetElementSequence(value);
   return container;
 }
 
@@ -78,29 +78,29 @@
     HeapVector<Member<Element>> cppValue = NativeValueTraits<IDLSequence<Element>>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setElementSequence(cppValue);
+    impl.SetElementSequence(cppValue);
     return;
   }
 
   if (v8Value->IsBoolean()) {
-    impl.setBoolean(v8Value.As<v8::Boolean>()->Value());
+    impl.SetBoolean(v8Value.As<v8::Boolean>()->Value());
     return;
   }
 
   {
-    impl.setBoolean(v8Value->BooleanValue());
+    impl.SetBoolean(v8Value->BooleanValue());
     return;
   }
 }
 
 v8::Local<v8::Value> ToV8(const BooleanOrElementSequence& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case BooleanOrElementSequence::SpecificTypeNone:
+    case BooleanOrElementSequence::SpecificType::kNone:
       return v8::Null(isolate);
-    case BooleanOrElementSequence::SpecificTypeBoolean:
-      return v8::Boolean::New(isolate, impl.getAsBoolean());
-    case BooleanOrElementSequence::SpecificTypeElementSequence:
-      return ToV8(impl.getAsElementSequence(), creationContext, isolate);
+    case BooleanOrElementSequence::SpecificType::kBoolean:
+      return v8::Boolean::New(isolate, impl.GetAsBoolean());
+    case BooleanOrElementSequence::SpecificType::kElementSequence:
+      return ToV8(impl.GetAsElementSequence(), creationContext, isolate);
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_element_sequence.h b/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_element_sequence.h
index d2a11bf9..46d07d6 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_element_sequence.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_element_sequence.h
@@ -27,17 +27,17 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   BooleanOrElementSequence();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isBoolean() const { return type_ == SpecificTypeBoolean; }
-  bool getAsBoolean() const;
-  void setBoolean(bool);
-  static BooleanOrElementSequence fromBoolean(bool);
+  bool IsBoolean() const { return type_ == SpecificType::kBoolean; }
+  bool GetAsBoolean() const;
+  void SetBoolean(bool);
+  static BooleanOrElementSequence FromBoolean(bool);
 
-  bool isElementSequence() const { return type_ == SpecificTypeElementSequence; }
-  const HeapVector<Member<Element>>& getAsElementSequence() const;
-  void setElementSequence(const HeapVector<Member<Element>>&);
-  static BooleanOrElementSequence fromElementSequence(const HeapVector<Member<Element>>&);
+  bool IsElementSequence() const { return type_ == SpecificType::kElementSequence; }
+  const HeapVector<Member<Element>>& GetAsElementSequence() const;
+  void SetElementSequence(const HeapVector<Member<Element>>&);
+  static BooleanOrElementSequence FromElementSequence(const HeapVector<Member<Element>>&);
 
   BooleanOrElementSequence(const BooleanOrElementSequence&);
   ~BooleanOrElementSequence();
@@ -45,12 +45,12 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeBoolean,
-    SpecificTypeElementSequence,
+  enum class SpecificType {
+    kNone,
+    kBoolean,
+    kElementSequence,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   bool boolean_;
   HeapVector<Member<Element>> element_sequence_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_string_or_unrestricted_double.cc b/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_string_or_unrestricted_double.cc
index 5d1c7f35..dd106a1 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_string_or_unrestricted_double.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_string_or_unrestricted_double.cc
@@ -17,56 +17,56 @@
 
 namespace blink {
 
-BooleanOrStringOrUnrestrictedDouble::BooleanOrStringOrUnrestrictedDouble() : type_(SpecificTypeNone) {}
+BooleanOrStringOrUnrestrictedDouble::BooleanOrStringOrUnrestrictedDouble() : type_(SpecificType::kNone) {}
 
-bool BooleanOrStringOrUnrestrictedDouble::getAsBoolean() const {
-  DCHECK(isBoolean());
+bool BooleanOrStringOrUnrestrictedDouble::GetAsBoolean() const {
+  DCHECK(IsBoolean());
   return boolean_;
 }
 
-void BooleanOrStringOrUnrestrictedDouble::setBoolean(bool value) {
-  DCHECK(isNull());
+void BooleanOrStringOrUnrestrictedDouble::SetBoolean(bool value) {
+  DCHECK(IsNull());
   boolean_ = value;
-  type_ = SpecificTypeBoolean;
+  type_ = SpecificType::kBoolean;
 }
 
-BooleanOrStringOrUnrestrictedDouble BooleanOrStringOrUnrestrictedDouble::fromBoolean(bool value) {
+BooleanOrStringOrUnrestrictedDouble BooleanOrStringOrUnrestrictedDouble::FromBoolean(bool value) {
   BooleanOrStringOrUnrestrictedDouble container;
-  container.setBoolean(value);
+  container.SetBoolean(value);
   return container;
 }
 
-const String& BooleanOrStringOrUnrestrictedDouble::getAsString() const {
-  DCHECK(isString());
+const String& BooleanOrStringOrUnrestrictedDouble::GetAsString() const {
+  DCHECK(IsString());
   return string_;
 }
 
-void BooleanOrStringOrUnrestrictedDouble::setString(const String& value) {
-  DCHECK(isNull());
+void BooleanOrStringOrUnrestrictedDouble::SetString(const String& value) {
+  DCHECK(IsNull());
   string_ = value;
-  type_ = SpecificTypeString;
+  type_ = SpecificType::kString;
 }
 
-BooleanOrStringOrUnrestrictedDouble BooleanOrStringOrUnrestrictedDouble::fromString(const String& value) {
+BooleanOrStringOrUnrestrictedDouble BooleanOrStringOrUnrestrictedDouble::FromString(const String& value) {
   BooleanOrStringOrUnrestrictedDouble container;
-  container.setString(value);
+  container.SetString(value);
   return container;
 }
 
-double BooleanOrStringOrUnrestrictedDouble::getAsUnrestrictedDouble() const {
-  DCHECK(isUnrestrictedDouble());
+double BooleanOrStringOrUnrestrictedDouble::GetAsUnrestrictedDouble() const {
+  DCHECK(IsUnrestrictedDouble());
   return unrestricted_double_;
 }
 
-void BooleanOrStringOrUnrestrictedDouble::setUnrestrictedDouble(double value) {
-  DCHECK(isNull());
+void BooleanOrStringOrUnrestrictedDouble::SetUnrestrictedDouble(double value) {
+  DCHECK(IsNull());
   unrestricted_double_ = value;
-  type_ = SpecificTypeUnrestrictedDouble;
+  type_ = SpecificType::kUnrestrictedDouble;
 }
 
-BooleanOrStringOrUnrestrictedDouble BooleanOrStringOrUnrestrictedDouble::fromUnrestrictedDouble(double value) {
+BooleanOrStringOrUnrestrictedDouble BooleanOrStringOrUnrestrictedDouble::FromUnrestrictedDouble(double value) {
   BooleanOrStringOrUnrestrictedDouble container;
-  container.setUnrestrictedDouble(value);
+  container.SetUnrestrictedDouble(value);
   return container;
 }
 
@@ -85,7 +85,7 @@
     return;
 
   if (v8Value->IsBoolean()) {
-    impl.setBoolean(v8Value.As<v8::Boolean>()->Value());
+    impl.SetBoolean(v8Value.As<v8::Boolean>()->Value());
     return;
   }
 
@@ -93,7 +93,7 @@
     double cppValue = NativeValueTraits<IDLUnrestrictedDouble>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setUnrestrictedDouble(cppValue);
+    impl.SetUnrestrictedDouble(cppValue);
     return;
   }
 
@@ -101,21 +101,21 @@
     V8StringResource<> cppValue = v8Value;
     if (!cppValue.Prepare(exceptionState))
       return;
-    impl.setString(cppValue);
+    impl.SetString(cppValue);
     return;
   }
 }
 
 v8::Local<v8::Value> ToV8(const BooleanOrStringOrUnrestrictedDouble& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case BooleanOrStringOrUnrestrictedDouble::SpecificTypeNone:
+    case BooleanOrStringOrUnrestrictedDouble::SpecificType::kNone:
       return v8::Null(isolate);
-    case BooleanOrStringOrUnrestrictedDouble::SpecificTypeBoolean:
-      return v8::Boolean::New(isolate, impl.getAsBoolean());
-    case BooleanOrStringOrUnrestrictedDouble::SpecificTypeString:
-      return V8String(isolate, impl.getAsString());
-    case BooleanOrStringOrUnrestrictedDouble::SpecificTypeUnrestrictedDouble:
-      return v8::Number::New(isolate, impl.getAsUnrestrictedDouble());
+    case BooleanOrStringOrUnrestrictedDouble::SpecificType::kBoolean:
+      return v8::Boolean::New(isolate, impl.GetAsBoolean());
+    case BooleanOrStringOrUnrestrictedDouble::SpecificType::kString:
+      return V8String(isolate, impl.GetAsString());
+    case BooleanOrStringOrUnrestrictedDouble::SpecificType::kUnrestrictedDouble:
+      return v8::Number::New(isolate, impl.GetAsUnrestrictedDouble());
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_string_or_unrestricted_double.h b/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_string_or_unrestricted_double.h
index e076d41f..ab73ad0 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_string_or_unrestricted_double.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_string_or_unrestricted_double.h
@@ -25,22 +25,22 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   BooleanOrStringOrUnrestrictedDouble();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isBoolean() const { return type_ == SpecificTypeBoolean; }
-  bool getAsBoolean() const;
-  void setBoolean(bool);
-  static BooleanOrStringOrUnrestrictedDouble fromBoolean(bool);
+  bool IsBoolean() const { return type_ == SpecificType::kBoolean; }
+  bool GetAsBoolean() const;
+  void SetBoolean(bool);
+  static BooleanOrStringOrUnrestrictedDouble FromBoolean(bool);
 
-  bool isString() const { return type_ == SpecificTypeString; }
-  const String& getAsString() const;
-  void setString(const String&);
-  static BooleanOrStringOrUnrestrictedDouble fromString(const String&);
+  bool IsString() const { return type_ == SpecificType::kString; }
+  const String& GetAsString() const;
+  void SetString(const String&);
+  static BooleanOrStringOrUnrestrictedDouble FromString(const String&);
 
-  bool isUnrestrictedDouble() const { return type_ == SpecificTypeUnrestrictedDouble; }
-  double getAsUnrestrictedDouble() const;
-  void setUnrestrictedDouble(double);
-  static BooleanOrStringOrUnrestrictedDouble fromUnrestrictedDouble(double);
+  bool IsUnrestrictedDouble() const { return type_ == SpecificType::kUnrestrictedDouble; }
+  double GetAsUnrestrictedDouble() const;
+  void SetUnrestrictedDouble(double);
+  static BooleanOrStringOrUnrestrictedDouble FromUnrestrictedDouble(double);
 
   BooleanOrStringOrUnrestrictedDouble(const BooleanOrStringOrUnrestrictedDouble&);
   ~BooleanOrStringOrUnrestrictedDouble();
@@ -48,13 +48,13 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeBoolean,
-    SpecificTypeString,
-    SpecificTypeUnrestrictedDouble,
+  enum class SpecificType {
+    kNone,
+    kBoolean,
+    kString,
+    kUnrestrictedDouble,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   bool boolean_;
   String string_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_test_callback_interface.cc b/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_test_callback_interface.cc
index 501615d..706dd6bf 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_test_callback_interface.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_test_callback_interface.cc
@@ -18,39 +18,39 @@
 
 namespace blink {
 
-BooleanOrTestCallbackInterface::BooleanOrTestCallbackInterface() : type_(SpecificTypeNone) {}
+BooleanOrTestCallbackInterface::BooleanOrTestCallbackInterface() : type_(SpecificType::kNone) {}
 
-bool BooleanOrTestCallbackInterface::getAsBoolean() const {
-  DCHECK(isBoolean());
+bool BooleanOrTestCallbackInterface::GetAsBoolean() const {
+  DCHECK(IsBoolean());
   return boolean_;
 }
 
-void BooleanOrTestCallbackInterface::setBoolean(bool value) {
-  DCHECK(isNull());
+void BooleanOrTestCallbackInterface::SetBoolean(bool value) {
+  DCHECK(IsNull());
   boolean_ = value;
-  type_ = SpecificTypeBoolean;
+  type_ = SpecificType::kBoolean;
 }
 
-BooleanOrTestCallbackInterface BooleanOrTestCallbackInterface::fromBoolean(bool value) {
+BooleanOrTestCallbackInterface BooleanOrTestCallbackInterface::FromBoolean(bool value) {
   BooleanOrTestCallbackInterface container;
-  container.setBoolean(value);
+  container.SetBoolean(value);
   return container;
 }
 
-TestCallbackInterface* BooleanOrTestCallbackInterface::getAsTestCallbackInterface() const {
-  DCHECK(isTestCallbackInterface());
+TestCallbackInterface* BooleanOrTestCallbackInterface::GetAsTestCallbackInterface() const {
+  DCHECK(IsTestCallbackInterface());
   return test_callback_interface_;
 }
 
-void BooleanOrTestCallbackInterface::setTestCallbackInterface(TestCallbackInterface* value) {
-  DCHECK(isNull());
+void BooleanOrTestCallbackInterface::SetTestCallbackInterface(TestCallbackInterface* value) {
+  DCHECK(IsNull());
   test_callback_interface_ = value;
-  type_ = SpecificTypeTestCallbackInterface;
+  type_ = SpecificType::kTestCallbackInterface;
 }
 
-BooleanOrTestCallbackInterface BooleanOrTestCallbackInterface::fromTestCallbackInterface(TestCallbackInterface* value) {
+BooleanOrTestCallbackInterface BooleanOrTestCallbackInterface::FromTestCallbackInterface(TestCallbackInterface* value) {
   BooleanOrTestCallbackInterface container;
-  container.setTestCallbackInterface(value);
+  container.SetTestCallbackInterface(value);
   return container;
 }
 
@@ -71,29 +71,29 @@
 
   if (V8TestCallbackInterface::hasInstance(v8Value, isolate)) {
     TestCallbackInterface* cppValue = V8TestCallbackInterface::ToImpl(v8::Local<v8::Object>::Cast(v8Value));
-    impl.setTestCallbackInterface(cppValue);
+    impl.SetTestCallbackInterface(cppValue);
     return;
   }
 
   if (v8Value->IsBoolean()) {
-    impl.setBoolean(v8Value.As<v8::Boolean>()->Value());
+    impl.SetBoolean(v8Value.As<v8::Boolean>()->Value());
     return;
   }
 
   {
-    impl.setBoolean(v8Value->BooleanValue());
+    impl.SetBoolean(v8Value->BooleanValue());
     return;
   }
 }
 
 v8::Local<v8::Value> ToV8(const BooleanOrTestCallbackInterface& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case BooleanOrTestCallbackInterface::SpecificTypeNone:
+    case BooleanOrTestCallbackInterface::SpecificType::kNone:
       return v8::Null(isolate);
-    case BooleanOrTestCallbackInterface::SpecificTypeBoolean:
-      return v8::Boolean::New(isolate, impl.getAsBoolean());
-    case BooleanOrTestCallbackInterface::SpecificTypeTestCallbackInterface:
-      return ToV8(impl.getAsTestCallbackInterface(), creationContext, isolate);
+    case BooleanOrTestCallbackInterface::SpecificType::kBoolean:
+      return v8::Boolean::New(isolate, impl.GetAsBoolean());
+    case BooleanOrTestCallbackInterface::SpecificType::kTestCallbackInterface:
+      return ToV8(impl.GetAsTestCallbackInterface(), creationContext, isolate);
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_test_callback_interface.h b/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_test_callback_interface.h
index 799e074f..eea53dc 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_test_callback_interface.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/boolean_or_test_callback_interface.h
@@ -27,17 +27,17 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   BooleanOrTestCallbackInterface();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isBoolean() const { return type_ == SpecificTypeBoolean; }
-  bool getAsBoolean() const;
-  void setBoolean(bool);
-  static BooleanOrTestCallbackInterface fromBoolean(bool);
+  bool IsBoolean() const { return type_ == SpecificType::kBoolean; }
+  bool GetAsBoolean() const;
+  void SetBoolean(bool);
+  static BooleanOrTestCallbackInterface FromBoolean(bool);
 
-  bool isTestCallbackInterface() const { return type_ == SpecificTypeTestCallbackInterface; }
-  TestCallbackInterface* getAsTestCallbackInterface() const;
-  void setTestCallbackInterface(TestCallbackInterface*);
-  static BooleanOrTestCallbackInterface fromTestCallbackInterface(TestCallbackInterface*);
+  bool IsTestCallbackInterface() const { return type_ == SpecificType::kTestCallbackInterface; }
+  TestCallbackInterface* GetAsTestCallbackInterface() const;
+  void SetTestCallbackInterface(TestCallbackInterface*);
+  static BooleanOrTestCallbackInterface FromTestCallbackInterface(TestCallbackInterface*);
 
   BooleanOrTestCallbackInterface(const BooleanOrTestCallbackInterface&);
   ~BooleanOrTestCallbackInterface();
@@ -45,12 +45,12 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeBoolean,
-    SpecificTypeTestCallbackInterface,
+  enum class SpecificType {
+    kNone,
+    kBoolean,
+    kTestCallbackInterface,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   bool boolean_;
   Member<TestCallbackInterface> test_callback_interface_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/byte_string_or_node_list.cc b/third_party/WebKit/Source/bindings/tests/results/core/byte_string_or_node_list.cc
index d65a09aa..7ccde3a 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/byte_string_or_node_list.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/byte_string_or_node_list.cc
@@ -22,39 +22,39 @@
 
 namespace blink {
 
-ByteStringOrNodeList::ByteStringOrNodeList() : type_(SpecificTypeNone) {}
+ByteStringOrNodeList::ByteStringOrNodeList() : type_(SpecificType::kNone) {}
 
-const String& ByteStringOrNodeList::getAsByteString() const {
-  DCHECK(isByteString());
+const String& ByteStringOrNodeList::GetAsByteString() const {
+  DCHECK(IsByteString());
   return byte_string_;
 }
 
-void ByteStringOrNodeList::setByteString(const String& value) {
-  DCHECK(isNull());
+void ByteStringOrNodeList::SetByteString(const String& value) {
+  DCHECK(IsNull());
   byte_string_ = value;
-  type_ = SpecificTypeByteString;
+  type_ = SpecificType::kByteString;
 }
 
-ByteStringOrNodeList ByteStringOrNodeList::fromByteString(const String& value) {
+ByteStringOrNodeList ByteStringOrNodeList::FromByteString(const String& value) {
   ByteStringOrNodeList container;
-  container.setByteString(value);
+  container.SetByteString(value);
   return container;
 }
 
-NodeList* ByteStringOrNodeList::getAsNodeList() const {
-  DCHECK(isNodeList());
+NodeList* ByteStringOrNodeList::GetAsNodeList() const {
+  DCHECK(IsNodeList());
   return node_list_;
 }
 
-void ByteStringOrNodeList::setNodeList(NodeList* value) {
-  DCHECK(isNull());
+void ByteStringOrNodeList::SetNodeList(NodeList* value) {
+  DCHECK(IsNull());
   node_list_ = value;
-  type_ = SpecificTypeNodeList;
+  type_ = SpecificType::kNodeList;
 }
 
-ByteStringOrNodeList ByteStringOrNodeList::fromNodeList(NodeList* value) {
+ByteStringOrNodeList ByteStringOrNodeList::FromNodeList(NodeList* value) {
   ByteStringOrNodeList container;
-  container.setNodeList(value);
+  container.SetNodeList(value);
   return container;
 }
 
@@ -75,7 +75,7 @@
 
   if (V8NodeList::hasInstance(v8Value, isolate)) {
     NodeList* cppValue = V8NodeList::ToImpl(v8::Local<v8::Object>::Cast(v8Value));
-    impl.setNodeList(cppValue);
+    impl.SetNodeList(cppValue);
     return;
   }
 
@@ -83,19 +83,19 @@
     V8StringResource<> cppValue = NativeValueTraits<IDLByteString>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setByteString(cppValue);
+    impl.SetByteString(cppValue);
     return;
   }
 }
 
 v8::Local<v8::Value> ToV8(const ByteStringOrNodeList& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case ByteStringOrNodeList::SpecificTypeNone:
+    case ByteStringOrNodeList::SpecificType::kNone:
       return v8::Null(isolate);
-    case ByteStringOrNodeList::SpecificTypeByteString:
-      return V8String(isolate, impl.getAsByteString());
-    case ByteStringOrNodeList::SpecificTypeNodeList:
-      return ToV8(impl.getAsNodeList(), creationContext, isolate);
+    case ByteStringOrNodeList::SpecificType::kByteString:
+      return V8String(isolate, impl.GetAsByteString());
+    case ByteStringOrNodeList::SpecificType::kNodeList:
+      return ToV8(impl.GetAsNodeList(), creationContext, isolate);
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/byte_string_or_node_list.h b/third_party/WebKit/Source/bindings/tests/results/core/byte_string_or_node_list.h
index acd8b0e..9c446af 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/byte_string_or_node_list.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/byte_string_or_node_list.h
@@ -27,17 +27,17 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   ByteStringOrNodeList();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isByteString() const { return type_ == SpecificTypeByteString; }
-  const String& getAsByteString() const;
-  void setByteString(const String&);
-  static ByteStringOrNodeList fromByteString(const String&);
+  bool IsByteString() const { return type_ == SpecificType::kByteString; }
+  const String& GetAsByteString() const;
+  void SetByteString(const String&);
+  static ByteStringOrNodeList FromByteString(const String&);
 
-  bool isNodeList() const { return type_ == SpecificTypeNodeList; }
-  NodeList* getAsNodeList() const;
-  void setNodeList(NodeList*);
-  static ByteStringOrNodeList fromNodeList(NodeList*);
+  bool IsNodeList() const { return type_ == SpecificType::kNodeList; }
+  NodeList* GetAsNodeList() const;
+  void SetNodeList(NodeList*);
+  static ByteStringOrNodeList FromNodeList(NodeList*);
 
   ByteStringOrNodeList(const ByteStringOrNodeList&);
   ~ByteStringOrNodeList();
@@ -45,12 +45,12 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeByteString,
-    SpecificTypeNodeList,
+  enum class SpecificType {
+    kNone,
+    kByteString,
+    kNodeList,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   String byte_string_;
   Member<NodeList> node_list_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/byte_string_sequence_sequence_or_byte_string_byte_string_record.cc b/third_party/WebKit/Source/bindings/tests/results/core/byte_string_sequence_sequence_or_byte_string_byte_string_record.cc
index b4797f4..9ab0bb0 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/byte_string_sequence_sequence_or_byte_string_byte_string_record.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/byte_string_sequence_sequence_or_byte_string_byte_string_record.cc
@@ -17,39 +17,39 @@
 
 namespace blink {
 
-ByteStringSequenceSequenceOrByteStringByteStringRecord::ByteStringSequenceSequenceOrByteStringByteStringRecord() : type_(SpecificTypeNone) {}
+ByteStringSequenceSequenceOrByteStringByteStringRecord::ByteStringSequenceSequenceOrByteStringByteStringRecord() : type_(SpecificType::kNone) {}
 
-const Vector<std::pair<String, String>>& ByteStringSequenceSequenceOrByteStringByteStringRecord::getAsByteStringByteStringRecord() const {
-  DCHECK(isByteStringByteStringRecord());
+const Vector<std::pair<String, String>>& ByteStringSequenceSequenceOrByteStringByteStringRecord::GetAsByteStringByteStringRecord() const {
+  DCHECK(IsByteStringByteStringRecord());
   return byte_string_byte_string_record_;
 }
 
-void ByteStringSequenceSequenceOrByteStringByteStringRecord::setByteStringByteStringRecord(const Vector<std::pair<String, String>>& value) {
-  DCHECK(isNull());
+void ByteStringSequenceSequenceOrByteStringByteStringRecord::SetByteStringByteStringRecord(const Vector<std::pair<String, String>>& value) {
+  DCHECK(IsNull());
   byte_string_byte_string_record_ = value;
-  type_ = SpecificTypeByteStringByteStringRecord;
+  type_ = SpecificType::kByteStringByteStringRecord;
 }
 
-ByteStringSequenceSequenceOrByteStringByteStringRecord ByteStringSequenceSequenceOrByteStringByteStringRecord::fromByteStringByteStringRecord(const Vector<std::pair<String, String>>& value) {
+ByteStringSequenceSequenceOrByteStringByteStringRecord ByteStringSequenceSequenceOrByteStringByteStringRecord::FromByteStringByteStringRecord(const Vector<std::pair<String, String>>& value) {
   ByteStringSequenceSequenceOrByteStringByteStringRecord container;
-  container.setByteStringByteStringRecord(value);
+  container.SetByteStringByteStringRecord(value);
   return container;
 }
 
-const Vector<Vector<String>>& ByteStringSequenceSequenceOrByteStringByteStringRecord::getAsByteStringSequenceSequence() const {
-  DCHECK(isByteStringSequenceSequence());
+const Vector<Vector<String>>& ByteStringSequenceSequenceOrByteStringByteStringRecord::GetAsByteStringSequenceSequence() const {
+  DCHECK(IsByteStringSequenceSequence());
   return byte_string_sequence_sequence_;
 }
 
-void ByteStringSequenceSequenceOrByteStringByteStringRecord::setByteStringSequenceSequence(const Vector<Vector<String>>& value) {
-  DCHECK(isNull());
+void ByteStringSequenceSequenceOrByteStringByteStringRecord::SetByteStringSequenceSequence(const Vector<Vector<String>>& value) {
+  DCHECK(IsNull());
   byte_string_sequence_sequence_ = value;
-  type_ = SpecificTypeByteStringSequenceSequence;
+  type_ = SpecificType::kByteStringSequenceSequence;
 }
 
-ByteStringSequenceSequenceOrByteStringByteStringRecord ByteStringSequenceSequenceOrByteStringByteStringRecord::fromByteStringSequenceSequence(const Vector<Vector<String>>& value) {
+ByteStringSequenceSequenceOrByteStringByteStringRecord ByteStringSequenceSequenceOrByteStringByteStringRecord::FromByteStringSequenceSequence(const Vector<Vector<String>>& value) {
   ByteStringSequenceSequenceOrByteStringByteStringRecord container;
-  container.setByteStringSequenceSequence(value);
+  container.SetByteStringSequenceSequence(value);
   return container;
 }
 
@@ -71,7 +71,7 @@
     Vector<Vector<String>> cppValue = NativeValueTraits<IDLSequence<IDLSequence<IDLByteString>>>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setByteStringSequenceSequence(cppValue);
+    impl.SetByteStringSequenceSequence(cppValue);
     return;
   }
 
@@ -79,7 +79,7 @@
     Vector<std::pair<String, String>> cppValue = NativeValueTraits<IDLRecord<IDLByteString, IDLByteString>>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setByteStringByteStringRecord(cppValue);
+    impl.SetByteStringByteStringRecord(cppValue);
     return;
   }
 
@@ -88,12 +88,12 @@
 
 v8::Local<v8::Value> ToV8(const ByteStringSequenceSequenceOrByteStringByteStringRecord& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case ByteStringSequenceSequenceOrByteStringByteStringRecord::SpecificTypeNone:
+    case ByteStringSequenceSequenceOrByteStringByteStringRecord::SpecificType::kNone:
       return v8::Null(isolate);
-    case ByteStringSequenceSequenceOrByteStringByteStringRecord::SpecificTypeByteStringByteStringRecord:
-      return ToV8(impl.getAsByteStringByteStringRecord(), creationContext, isolate);
-    case ByteStringSequenceSequenceOrByteStringByteStringRecord::SpecificTypeByteStringSequenceSequence:
-      return ToV8(impl.getAsByteStringSequenceSequence(), creationContext, isolate);
+    case ByteStringSequenceSequenceOrByteStringByteStringRecord::SpecificType::kByteStringByteStringRecord:
+      return ToV8(impl.GetAsByteStringByteStringRecord(), creationContext, isolate);
+    case ByteStringSequenceSequenceOrByteStringByteStringRecord::SpecificType::kByteStringSequenceSequence:
+      return ToV8(impl.GetAsByteStringSequenceSequence(), creationContext, isolate);
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/byte_string_sequence_sequence_or_byte_string_byte_string_record.h b/third_party/WebKit/Source/bindings/tests/results/core/byte_string_sequence_sequence_or_byte_string_byte_string_record.h
index 53c55a05..00016a3 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/byte_string_sequence_sequence_or_byte_string_byte_string_record.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/byte_string_sequence_sequence_or_byte_string_byte_string_record.h
@@ -25,17 +25,17 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   ByteStringSequenceSequenceOrByteStringByteStringRecord();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isByteStringByteStringRecord() const { return type_ == SpecificTypeByteStringByteStringRecord; }
-  const Vector<std::pair<String, String>>& getAsByteStringByteStringRecord() const;
-  void setByteStringByteStringRecord(const Vector<std::pair<String, String>>&);
-  static ByteStringSequenceSequenceOrByteStringByteStringRecord fromByteStringByteStringRecord(const Vector<std::pair<String, String>>&);
+  bool IsByteStringByteStringRecord() const { return type_ == SpecificType::kByteStringByteStringRecord; }
+  const Vector<std::pair<String, String>>& GetAsByteStringByteStringRecord() const;
+  void SetByteStringByteStringRecord(const Vector<std::pair<String, String>>&);
+  static ByteStringSequenceSequenceOrByteStringByteStringRecord FromByteStringByteStringRecord(const Vector<std::pair<String, String>>&);
 
-  bool isByteStringSequenceSequence() const { return type_ == SpecificTypeByteStringSequenceSequence; }
-  const Vector<Vector<String>>& getAsByteStringSequenceSequence() const;
-  void setByteStringSequenceSequence(const Vector<Vector<String>>&);
-  static ByteStringSequenceSequenceOrByteStringByteStringRecord fromByteStringSequenceSequence(const Vector<Vector<String>>&);
+  bool IsByteStringSequenceSequence() const { return type_ == SpecificType::kByteStringSequenceSequence; }
+  const Vector<Vector<String>>& GetAsByteStringSequenceSequence() const;
+  void SetByteStringSequenceSequence(const Vector<Vector<String>>&);
+  static ByteStringSequenceSequenceOrByteStringByteStringRecord FromByteStringSequenceSequence(const Vector<Vector<String>>&);
 
   ByteStringSequenceSequenceOrByteStringByteStringRecord(const ByteStringSequenceSequenceOrByteStringByteStringRecord&);
   ~ByteStringSequenceSequenceOrByteStringByteStringRecord();
@@ -43,12 +43,12 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeByteStringByteStringRecord,
-    SpecificTypeByteStringSequenceSequence,
+  enum class SpecificType {
+    kNone,
+    kByteStringByteStringRecord,
+    kByteStringSequenceSequence,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   Vector<std::pair<String, String>> byte_string_byte_string_record_;
   Vector<Vector<String>> byte_string_sequence_sequence_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/double_or_long_or_boolean_sequence.cc b/third_party/WebKit/Source/bindings/tests/results/core/double_or_long_or_boolean_sequence.cc
index 5dc33d27..545e41c 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/double_or_long_or_boolean_sequence.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/double_or_long_or_boolean_sequence.cc
@@ -18,39 +18,39 @@
 
 namespace blink {
 
-DoubleOrLongOrBooleanSequence::DoubleOrLongOrBooleanSequence() : type_(SpecificTypeNone) {}
+DoubleOrLongOrBooleanSequence::DoubleOrLongOrBooleanSequence() : type_(SpecificType::kNone) {}
 
-double DoubleOrLongOrBooleanSequence::getAsDouble() const {
-  DCHECK(isDouble());
+double DoubleOrLongOrBooleanSequence::GetAsDouble() const {
+  DCHECK(IsDouble());
   return double_;
 }
 
-void DoubleOrLongOrBooleanSequence::setDouble(double value) {
-  DCHECK(isNull());
+void DoubleOrLongOrBooleanSequence::SetDouble(double value) {
+  DCHECK(IsNull());
   double_ = value;
-  type_ = SpecificTypeDouble;
+  type_ = SpecificType::kDouble;
 }
 
-DoubleOrLongOrBooleanSequence DoubleOrLongOrBooleanSequence::fromDouble(double value) {
+DoubleOrLongOrBooleanSequence DoubleOrLongOrBooleanSequence::FromDouble(double value) {
   DoubleOrLongOrBooleanSequence container;
-  container.setDouble(value);
+  container.SetDouble(value);
   return container;
 }
 
-const HeapVector<LongOrBoolean>& DoubleOrLongOrBooleanSequence::getAsLongOrBooleanSequence() const {
-  DCHECK(isLongOrBooleanSequence());
+const HeapVector<LongOrBoolean>& DoubleOrLongOrBooleanSequence::GetAsLongOrBooleanSequence() const {
+  DCHECK(IsLongOrBooleanSequence());
   return long_or_boolean_sequence_;
 }
 
-void DoubleOrLongOrBooleanSequence::setLongOrBooleanSequence(const HeapVector<LongOrBoolean>& value) {
-  DCHECK(isNull());
+void DoubleOrLongOrBooleanSequence::SetLongOrBooleanSequence(const HeapVector<LongOrBoolean>& value) {
+  DCHECK(IsNull());
   long_or_boolean_sequence_ = value;
-  type_ = SpecificTypeLongOrBooleanSequence;
+  type_ = SpecificType::kLongOrBooleanSequence;
 }
 
-DoubleOrLongOrBooleanSequence DoubleOrLongOrBooleanSequence::fromLongOrBooleanSequence(const HeapVector<LongOrBoolean>& value) {
+DoubleOrLongOrBooleanSequence DoubleOrLongOrBooleanSequence::FromLongOrBooleanSequence(const HeapVector<LongOrBoolean>& value) {
   DoubleOrLongOrBooleanSequence container;
-  container.setLongOrBooleanSequence(value);
+  container.SetLongOrBooleanSequence(value);
   return container;
 }
 
@@ -73,7 +73,7 @@
     HeapVector<LongOrBoolean> cppValue = NativeValueTraits<IDLSequence<LongOrBoolean>>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setLongOrBooleanSequence(cppValue);
+    impl.SetLongOrBooleanSequence(cppValue);
     return;
   }
 
@@ -81,7 +81,7 @@
     double cppValue = NativeValueTraits<IDLDouble>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setDouble(cppValue);
+    impl.SetDouble(cppValue);
     return;
   }
 
@@ -89,19 +89,19 @@
     double cppValue = NativeValueTraits<IDLDouble>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setDouble(cppValue);
+    impl.SetDouble(cppValue);
     return;
   }
 }
 
 v8::Local<v8::Value> ToV8(const DoubleOrLongOrBooleanSequence& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case DoubleOrLongOrBooleanSequence::SpecificTypeNone:
+    case DoubleOrLongOrBooleanSequence::SpecificType::kNone:
       return v8::Null(isolate);
-    case DoubleOrLongOrBooleanSequence::SpecificTypeDouble:
-      return v8::Number::New(isolate, impl.getAsDouble());
-    case DoubleOrLongOrBooleanSequence::SpecificTypeLongOrBooleanSequence:
-      return ToV8(impl.getAsLongOrBooleanSequence(), creationContext, isolate);
+    case DoubleOrLongOrBooleanSequence::SpecificType::kDouble:
+      return v8::Number::New(isolate, impl.GetAsDouble());
+    case DoubleOrLongOrBooleanSequence::SpecificType::kLongOrBooleanSequence:
+      return ToV8(impl.GetAsLongOrBooleanSequence(), creationContext, isolate);
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/double_or_long_or_boolean_sequence.h b/third_party/WebKit/Source/bindings/tests/results/core/double_or_long_or_boolean_sequence.h
index cd55ea9..26c2b06 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/double_or_long_or_boolean_sequence.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/double_or_long_or_boolean_sequence.h
@@ -27,17 +27,17 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   DoubleOrLongOrBooleanSequence();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isDouble() const { return type_ == SpecificTypeDouble; }
-  double getAsDouble() const;
-  void setDouble(double);
-  static DoubleOrLongOrBooleanSequence fromDouble(double);
+  bool IsDouble() const { return type_ == SpecificType::kDouble; }
+  double GetAsDouble() const;
+  void SetDouble(double);
+  static DoubleOrLongOrBooleanSequence FromDouble(double);
 
-  bool isLongOrBooleanSequence() const { return type_ == SpecificTypeLongOrBooleanSequence; }
-  const HeapVector<LongOrBoolean>& getAsLongOrBooleanSequence() const;
-  void setLongOrBooleanSequence(const HeapVector<LongOrBoolean>&);
-  static DoubleOrLongOrBooleanSequence fromLongOrBooleanSequence(const HeapVector<LongOrBoolean>&);
+  bool IsLongOrBooleanSequence() const { return type_ == SpecificType::kLongOrBooleanSequence; }
+  const HeapVector<LongOrBoolean>& GetAsLongOrBooleanSequence() const;
+  void SetLongOrBooleanSequence(const HeapVector<LongOrBoolean>&);
+  static DoubleOrLongOrBooleanSequence FromLongOrBooleanSequence(const HeapVector<LongOrBoolean>&);
 
   DoubleOrLongOrBooleanSequence(const DoubleOrLongOrBooleanSequence&);
   ~DoubleOrLongOrBooleanSequence();
@@ -45,12 +45,12 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeDouble,
-    SpecificTypeLongOrBooleanSequence,
+  enum class SpecificType {
+    kNone,
+    kDouble,
+    kLongOrBooleanSequence,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   double double_;
   HeapVector<LongOrBoolean> long_or_boolean_sequence_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/double_or_string.cc b/third_party/WebKit/Source/bindings/tests/results/core/double_or_string.cc
index 4afd326..97c8987 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/double_or_string.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/double_or_string.cc
@@ -17,39 +17,39 @@
 
 namespace blink {
 
-DoubleOrString::DoubleOrString() : type_(SpecificTypeNone) {}
+DoubleOrString::DoubleOrString() : type_(SpecificType::kNone) {}
 
-double DoubleOrString::getAsDouble() const {
-  DCHECK(isDouble());
+double DoubleOrString::GetAsDouble() const {
+  DCHECK(IsDouble());
   return double_;
 }
 
-void DoubleOrString::setDouble(double value) {
-  DCHECK(isNull());
+void DoubleOrString::SetDouble(double value) {
+  DCHECK(IsNull());
   double_ = value;
-  type_ = SpecificTypeDouble;
+  type_ = SpecificType::kDouble;
 }
 
-DoubleOrString DoubleOrString::fromDouble(double value) {
+DoubleOrString DoubleOrString::FromDouble(double value) {
   DoubleOrString container;
-  container.setDouble(value);
+  container.SetDouble(value);
   return container;
 }
 
-const String& DoubleOrString::getAsString() const {
-  DCHECK(isString());
+const String& DoubleOrString::GetAsString() const {
+  DCHECK(IsString());
   return string_;
 }
 
-void DoubleOrString::setString(const String& value) {
-  DCHECK(isNull());
+void DoubleOrString::SetString(const String& value) {
+  DCHECK(IsNull());
   string_ = value;
-  type_ = SpecificTypeString;
+  type_ = SpecificType::kString;
 }
 
-DoubleOrString DoubleOrString::fromString(const String& value) {
+DoubleOrString DoubleOrString::FromString(const String& value) {
   DoubleOrString container;
-  container.setString(value);
+  container.SetString(value);
   return container;
 }
 
@@ -71,7 +71,7 @@
     double cppValue = NativeValueTraits<IDLDouble>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setDouble(cppValue);
+    impl.SetDouble(cppValue);
     return;
   }
 
@@ -79,19 +79,19 @@
     V8StringResource<> cppValue = v8Value;
     if (!cppValue.Prepare(exceptionState))
       return;
-    impl.setString(cppValue);
+    impl.SetString(cppValue);
     return;
   }
 }
 
 v8::Local<v8::Value> ToV8(const DoubleOrString& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case DoubleOrString::SpecificTypeNone:
+    case DoubleOrString::SpecificType::kNone:
       return v8::Null(isolate);
-    case DoubleOrString::SpecificTypeDouble:
-      return v8::Number::New(isolate, impl.getAsDouble());
-    case DoubleOrString::SpecificTypeString:
-      return V8String(isolate, impl.getAsString());
+    case DoubleOrString::SpecificType::kDouble:
+      return v8::Number::New(isolate, impl.GetAsDouble());
+    case DoubleOrString::SpecificType::kString:
+      return V8String(isolate, impl.GetAsString());
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/double_or_string.h b/third_party/WebKit/Source/bindings/tests/results/core/double_or_string.h
index b0f702f..080a7f78 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/double_or_string.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/double_or_string.h
@@ -25,17 +25,17 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   DoubleOrString();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isDouble() const { return type_ == SpecificTypeDouble; }
-  double getAsDouble() const;
-  void setDouble(double);
-  static DoubleOrString fromDouble(double);
+  bool IsDouble() const { return type_ == SpecificType::kDouble; }
+  double GetAsDouble() const;
+  void SetDouble(double);
+  static DoubleOrString FromDouble(double);
 
-  bool isString() const { return type_ == SpecificTypeString; }
-  const String& getAsString() const;
-  void setString(const String&);
-  static DoubleOrString fromString(const String&);
+  bool IsString() const { return type_ == SpecificType::kString; }
+  const String& GetAsString() const;
+  void SetString(const String&);
+  static DoubleOrString FromString(const String&);
 
   DoubleOrString(const DoubleOrString&);
   ~DoubleOrString();
@@ -43,12 +43,12 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeDouble,
-    SpecificTypeString,
+  enum class SpecificType {
+    kNone,
+    kDouble,
+    kString,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   double double_;
   String string_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/double_or_string_or_double_or_string_sequence.cc b/third_party/WebKit/Source/bindings/tests/results/core/double_or_string_or_double_or_string_sequence.cc
index b93f2314..b5b3c5ae 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/double_or_string_or_double_or_string_sequence.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/double_or_string_or_double_or_string_sequence.cc
@@ -18,56 +18,56 @@
 
 namespace blink {
 
-DoubleOrStringOrDoubleOrStringSequence::DoubleOrStringOrDoubleOrStringSequence() : type_(SpecificTypeNone) {}
+DoubleOrStringOrDoubleOrStringSequence::DoubleOrStringOrDoubleOrStringSequence() : type_(SpecificType::kNone) {}
 
-double DoubleOrStringOrDoubleOrStringSequence::getAsDouble() const {
-  DCHECK(isDouble());
+double DoubleOrStringOrDoubleOrStringSequence::GetAsDouble() const {
+  DCHECK(IsDouble());
   return double_;
 }
 
-void DoubleOrStringOrDoubleOrStringSequence::setDouble(double value) {
-  DCHECK(isNull());
+void DoubleOrStringOrDoubleOrStringSequence::SetDouble(double value) {
+  DCHECK(IsNull());
   double_ = value;
-  type_ = SpecificTypeDouble;
+  type_ = SpecificType::kDouble;
 }
 
-DoubleOrStringOrDoubleOrStringSequence DoubleOrStringOrDoubleOrStringSequence::fromDouble(double value) {
+DoubleOrStringOrDoubleOrStringSequence DoubleOrStringOrDoubleOrStringSequence::FromDouble(double value) {
   DoubleOrStringOrDoubleOrStringSequence container;
-  container.setDouble(value);
+  container.SetDouble(value);
   return container;
 }
 
-const HeapVector<DoubleOrString>& DoubleOrStringOrDoubleOrStringSequence::getAsDoubleOrStringSequence() const {
-  DCHECK(isDoubleOrStringSequence());
+const HeapVector<DoubleOrString>& DoubleOrStringOrDoubleOrStringSequence::GetAsDoubleOrStringSequence() const {
+  DCHECK(IsDoubleOrStringSequence());
   return double_or_string_sequence_;
 }
 
-void DoubleOrStringOrDoubleOrStringSequence::setDoubleOrStringSequence(const HeapVector<DoubleOrString>& value) {
-  DCHECK(isNull());
+void DoubleOrStringOrDoubleOrStringSequence::SetDoubleOrStringSequence(const HeapVector<DoubleOrString>& value) {
+  DCHECK(IsNull());
   double_or_string_sequence_ = value;
-  type_ = SpecificTypeDoubleOrStringSequence;
+  type_ = SpecificType::kDoubleOrStringSequence;
 }
 
-DoubleOrStringOrDoubleOrStringSequence DoubleOrStringOrDoubleOrStringSequence::fromDoubleOrStringSequence(const HeapVector<DoubleOrString>& value) {
+DoubleOrStringOrDoubleOrStringSequence DoubleOrStringOrDoubleOrStringSequence::FromDoubleOrStringSequence(const HeapVector<DoubleOrString>& value) {
   DoubleOrStringOrDoubleOrStringSequence container;
-  container.setDoubleOrStringSequence(value);
+  container.SetDoubleOrStringSequence(value);
   return container;
 }
 
-const String& DoubleOrStringOrDoubleOrStringSequence::getAsString() const {
-  DCHECK(isString());
+const String& DoubleOrStringOrDoubleOrStringSequence::GetAsString() const {
+  DCHECK(IsString());
   return string_;
 }
 
-void DoubleOrStringOrDoubleOrStringSequence::setString(const String& value) {
-  DCHECK(isNull());
+void DoubleOrStringOrDoubleOrStringSequence::SetString(const String& value) {
+  DCHECK(IsNull());
   string_ = value;
-  type_ = SpecificTypeString;
+  type_ = SpecificType::kString;
 }
 
-DoubleOrStringOrDoubleOrStringSequence DoubleOrStringOrDoubleOrStringSequence::fromString(const String& value) {
+DoubleOrStringOrDoubleOrStringSequence DoubleOrStringOrDoubleOrStringSequence::FromString(const String& value) {
   DoubleOrStringOrDoubleOrStringSequence container;
-  container.setString(value);
+  container.SetString(value);
   return container;
 }
 
@@ -90,7 +90,7 @@
     HeapVector<DoubleOrString> cppValue = NativeValueTraits<IDLSequence<DoubleOrString>>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setDoubleOrStringSequence(cppValue);
+    impl.SetDoubleOrStringSequence(cppValue);
     return;
   }
 
@@ -98,7 +98,7 @@
     double cppValue = NativeValueTraits<IDLDouble>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setDouble(cppValue);
+    impl.SetDouble(cppValue);
     return;
   }
 
@@ -106,21 +106,21 @@
     V8StringResource<> cppValue = v8Value;
     if (!cppValue.Prepare(exceptionState))
       return;
-    impl.setString(cppValue);
+    impl.SetString(cppValue);
     return;
   }
 }
 
 v8::Local<v8::Value> ToV8(const DoubleOrStringOrDoubleOrStringSequence& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case DoubleOrStringOrDoubleOrStringSequence::SpecificTypeNone:
+    case DoubleOrStringOrDoubleOrStringSequence::SpecificType::kNone:
       return v8::Null(isolate);
-    case DoubleOrStringOrDoubleOrStringSequence::SpecificTypeDouble:
-      return v8::Number::New(isolate, impl.getAsDouble());
-    case DoubleOrStringOrDoubleOrStringSequence::SpecificTypeDoubleOrStringSequence:
-      return ToV8(impl.getAsDoubleOrStringSequence(), creationContext, isolate);
-    case DoubleOrStringOrDoubleOrStringSequence::SpecificTypeString:
-      return V8String(isolate, impl.getAsString());
+    case DoubleOrStringOrDoubleOrStringSequence::SpecificType::kDouble:
+      return v8::Number::New(isolate, impl.GetAsDouble());
+    case DoubleOrStringOrDoubleOrStringSequence::SpecificType::kDoubleOrStringSequence:
+      return ToV8(impl.GetAsDoubleOrStringSequence(), creationContext, isolate);
+    case DoubleOrStringOrDoubleOrStringSequence::SpecificType::kString:
+      return V8String(isolate, impl.GetAsString());
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/double_or_string_or_double_or_string_sequence.h b/third_party/WebKit/Source/bindings/tests/results/core/double_or_string_or_double_or_string_sequence.h
index 816ff645..16086ae 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/double_or_string_or_double_or_string_sequence.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/double_or_string_or_double_or_string_sequence.h
@@ -27,22 +27,22 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   DoubleOrStringOrDoubleOrStringSequence();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isDouble() const { return type_ == SpecificTypeDouble; }
-  double getAsDouble() const;
-  void setDouble(double);
-  static DoubleOrStringOrDoubleOrStringSequence fromDouble(double);
+  bool IsDouble() const { return type_ == SpecificType::kDouble; }
+  double GetAsDouble() const;
+  void SetDouble(double);
+  static DoubleOrStringOrDoubleOrStringSequence FromDouble(double);
 
-  bool isDoubleOrStringSequence() const { return type_ == SpecificTypeDoubleOrStringSequence; }
-  const HeapVector<DoubleOrString>& getAsDoubleOrStringSequence() const;
-  void setDoubleOrStringSequence(const HeapVector<DoubleOrString>&);
-  static DoubleOrStringOrDoubleOrStringSequence fromDoubleOrStringSequence(const HeapVector<DoubleOrString>&);
+  bool IsDoubleOrStringSequence() const { return type_ == SpecificType::kDoubleOrStringSequence; }
+  const HeapVector<DoubleOrString>& GetAsDoubleOrStringSequence() const;
+  void SetDoubleOrStringSequence(const HeapVector<DoubleOrString>&);
+  static DoubleOrStringOrDoubleOrStringSequence FromDoubleOrStringSequence(const HeapVector<DoubleOrString>&);
 
-  bool isString() const { return type_ == SpecificTypeString; }
-  const String& getAsString() const;
-  void setString(const String&);
-  static DoubleOrStringOrDoubleOrStringSequence fromString(const String&);
+  bool IsString() const { return type_ == SpecificType::kString; }
+  const String& GetAsString() const;
+  void SetString(const String&);
+  static DoubleOrStringOrDoubleOrStringSequence FromString(const String&);
 
   DoubleOrStringOrDoubleOrStringSequence(const DoubleOrStringOrDoubleOrStringSequence&);
   ~DoubleOrStringOrDoubleOrStringSequence();
@@ -50,13 +50,13 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeDouble,
-    SpecificTypeDoubleOrStringSequence,
-    SpecificTypeString,
+  enum class SpecificType {
+    kNone,
+    kDouble,
+    kDoubleOrStringSequence,
+    kString,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   double double_;
   HeapVector<DoubleOrString> double_or_string_sequence_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/element_sequence_or_byte_string_double_or_string_record.cc b/third_party/WebKit/Source/bindings/tests/results/core/element_sequence_or_byte_string_double_or_string_record.cc
index b8ab6864..b2bd6e8 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/element_sequence_or_byte_string_double_or_string_record.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/element_sequence_or_byte_string_double_or_string_record.cc
@@ -24,39 +24,39 @@
 
 namespace blink {
 
-ElementSequenceOrByteStringDoubleOrStringRecord::ElementSequenceOrByteStringDoubleOrStringRecord() : type_(SpecificTypeNone) {}
+ElementSequenceOrByteStringDoubleOrStringRecord::ElementSequenceOrByteStringDoubleOrStringRecord() : type_(SpecificType::kNone) {}
 
-const HeapVector<std::pair<String, DoubleOrString>>& ElementSequenceOrByteStringDoubleOrStringRecord::getAsByteStringDoubleOrStringRecord() const {
-  DCHECK(isByteStringDoubleOrStringRecord());
+const HeapVector<std::pair<String, DoubleOrString>>& ElementSequenceOrByteStringDoubleOrStringRecord::GetAsByteStringDoubleOrStringRecord() const {
+  DCHECK(IsByteStringDoubleOrStringRecord());
   return byte_string_double_or_string_record_;
 }
 
-void ElementSequenceOrByteStringDoubleOrStringRecord::setByteStringDoubleOrStringRecord(const HeapVector<std::pair<String, DoubleOrString>>& value) {
-  DCHECK(isNull());
+void ElementSequenceOrByteStringDoubleOrStringRecord::SetByteStringDoubleOrStringRecord(const HeapVector<std::pair<String, DoubleOrString>>& value) {
+  DCHECK(IsNull());
   byte_string_double_or_string_record_ = value;
-  type_ = SpecificTypeByteStringDoubleOrStringRecord;
+  type_ = SpecificType::kByteStringDoubleOrStringRecord;
 }
 
-ElementSequenceOrByteStringDoubleOrStringRecord ElementSequenceOrByteStringDoubleOrStringRecord::fromByteStringDoubleOrStringRecord(const HeapVector<std::pair<String, DoubleOrString>>& value) {
+ElementSequenceOrByteStringDoubleOrStringRecord ElementSequenceOrByteStringDoubleOrStringRecord::FromByteStringDoubleOrStringRecord(const HeapVector<std::pair<String, DoubleOrString>>& value) {
   ElementSequenceOrByteStringDoubleOrStringRecord container;
-  container.setByteStringDoubleOrStringRecord(value);
+  container.SetByteStringDoubleOrStringRecord(value);
   return container;
 }
 
-const HeapVector<Member<Element>>& ElementSequenceOrByteStringDoubleOrStringRecord::getAsElementSequence() const {
-  DCHECK(isElementSequence());
+const HeapVector<Member<Element>>& ElementSequenceOrByteStringDoubleOrStringRecord::GetAsElementSequence() const {
+  DCHECK(IsElementSequence());
   return element_sequence_;
 }
 
-void ElementSequenceOrByteStringDoubleOrStringRecord::setElementSequence(const HeapVector<Member<Element>>& value) {
-  DCHECK(isNull());
+void ElementSequenceOrByteStringDoubleOrStringRecord::SetElementSequence(const HeapVector<Member<Element>>& value) {
+  DCHECK(IsNull());
   element_sequence_ = value;
-  type_ = SpecificTypeElementSequence;
+  type_ = SpecificType::kElementSequence;
 }
 
-ElementSequenceOrByteStringDoubleOrStringRecord ElementSequenceOrByteStringDoubleOrStringRecord::fromElementSequence(const HeapVector<Member<Element>>& value) {
+ElementSequenceOrByteStringDoubleOrStringRecord ElementSequenceOrByteStringDoubleOrStringRecord::FromElementSequence(const HeapVector<Member<Element>>& value) {
   ElementSequenceOrByteStringDoubleOrStringRecord container;
-  container.setElementSequence(value);
+  container.SetElementSequence(value);
   return container;
 }
 
@@ -80,7 +80,7 @@
     HeapVector<Member<Element>> cppValue = NativeValueTraits<IDLSequence<Element>>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setElementSequence(cppValue);
+    impl.SetElementSequence(cppValue);
     return;
   }
 
@@ -88,7 +88,7 @@
     HeapVector<std::pair<String, DoubleOrString>> cppValue = NativeValueTraits<IDLRecord<IDLByteString, DoubleOrString>>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setByteStringDoubleOrStringRecord(cppValue);
+    impl.SetByteStringDoubleOrStringRecord(cppValue);
     return;
   }
 
@@ -97,12 +97,12 @@
 
 v8::Local<v8::Value> ToV8(const ElementSequenceOrByteStringDoubleOrStringRecord& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case ElementSequenceOrByteStringDoubleOrStringRecord::SpecificTypeNone:
+    case ElementSequenceOrByteStringDoubleOrStringRecord::SpecificType::kNone:
       return v8::Null(isolate);
-    case ElementSequenceOrByteStringDoubleOrStringRecord::SpecificTypeByteStringDoubleOrStringRecord:
-      return ToV8(impl.getAsByteStringDoubleOrStringRecord(), creationContext, isolate);
-    case ElementSequenceOrByteStringDoubleOrStringRecord::SpecificTypeElementSequence:
-      return ToV8(impl.getAsElementSequence(), creationContext, isolate);
+    case ElementSequenceOrByteStringDoubleOrStringRecord::SpecificType::kByteStringDoubleOrStringRecord:
+      return ToV8(impl.GetAsByteStringDoubleOrStringRecord(), creationContext, isolate);
+    case ElementSequenceOrByteStringDoubleOrStringRecord::SpecificType::kElementSequence:
+      return ToV8(impl.GetAsElementSequence(), creationContext, isolate);
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/element_sequence_or_byte_string_double_or_string_record.h b/third_party/WebKit/Source/bindings/tests/results/core/element_sequence_or_byte_string_double_or_string_record.h
index 1d336fd..ba3f573 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/element_sequence_or_byte_string_double_or_string_record.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/element_sequence_or_byte_string_double_or_string_record.h
@@ -28,17 +28,17 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   ElementSequenceOrByteStringDoubleOrStringRecord();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isByteStringDoubleOrStringRecord() const { return type_ == SpecificTypeByteStringDoubleOrStringRecord; }
-  const HeapVector<std::pair<String, DoubleOrString>>& getAsByteStringDoubleOrStringRecord() const;
-  void setByteStringDoubleOrStringRecord(const HeapVector<std::pair<String, DoubleOrString>>&);
-  static ElementSequenceOrByteStringDoubleOrStringRecord fromByteStringDoubleOrStringRecord(const HeapVector<std::pair<String, DoubleOrString>>&);
+  bool IsByteStringDoubleOrStringRecord() const { return type_ == SpecificType::kByteStringDoubleOrStringRecord; }
+  const HeapVector<std::pair<String, DoubleOrString>>& GetAsByteStringDoubleOrStringRecord() const;
+  void SetByteStringDoubleOrStringRecord(const HeapVector<std::pair<String, DoubleOrString>>&);
+  static ElementSequenceOrByteStringDoubleOrStringRecord FromByteStringDoubleOrStringRecord(const HeapVector<std::pair<String, DoubleOrString>>&);
 
-  bool isElementSequence() const { return type_ == SpecificTypeElementSequence; }
-  const HeapVector<Member<Element>>& getAsElementSequence() const;
-  void setElementSequence(const HeapVector<Member<Element>>&);
-  static ElementSequenceOrByteStringDoubleOrStringRecord fromElementSequence(const HeapVector<Member<Element>>&);
+  bool IsElementSequence() const { return type_ == SpecificType::kElementSequence; }
+  const HeapVector<Member<Element>>& GetAsElementSequence() const;
+  void SetElementSequence(const HeapVector<Member<Element>>&);
+  static ElementSequenceOrByteStringDoubleOrStringRecord FromElementSequence(const HeapVector<Member<Element>>&);
 
   ElementSequenceOrByteStringDoubleOrStringRecord(const ElementSequenceOrByteStringDoubleOrStringRecord&);
   ~ElementSequenceOrByteStringDoubleOrStringRecord();
@@ -46,12 +46,12 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeByteStringDoubleOrStringRecord,
-    SpecificTypeElementSequence,
+  enum class SpecificType {
+    kNone,
+    kByteStringDoubleOrStringRecord,
+    kElementSequence,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   HeapVector<std::pair<String, DoubleOrString>> byte_string_double_or_string_record_;
   HeapVector<Member<Element>> element_sequence_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/float_or_boolean.cc b/third_party/WebKit/Source/bindings/tests/results/core/float_or_boolean.cc
index ac6e9fe..0b66f235 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/float_or_boolean.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/float_or_boolean.cc
@@ -17,39 +17,39 @@
 
 namespace blink {
 
-FloatOrBoolean::FloatOrBoolean() : type_(SpecificTypeNone) {}
+FloatOrBoolean::FloatOrBoolean() : type_(SpecificType::kNone) {}
 
-bool FloatOrBoolean::getAsBoolean() const {
-  DCHECK(isBoolean());
+bool FloatOrBoolean::GetAsBoolean() const {
+  DCHECK(IsBoolean());
   return boolean_;
 }
 
-void FloatOrBoolean::setBoolean(bool value) {
-  DCHECK(isNull());
+void FloatOrBoolean::SetBoolean(bool value) {
+  DCHECK(IsNull());
   boolean_ = value;
-  type_ = SpecificTypeBoolean;
+  type_ = SpecificType::kBoolean;
 }
 
-FloatOrBoolean FloatOrBoolean::fromBoolean(bool value) {
+FloatOrBoolean FloatOrBoolean::FromBoolean(bool value) {
   FloatOrBoolean container;
-  container.setBoolean(value);
+  container.SetBoolean(value);
   return container;
 }
 
-float FloatOrBoolean::getAsFloat() const {
-  DCHECK(isFloat());
+float FloatOrBoolean::GetAsFloat() const {
+  DCHECK(IsFloat());
   return float_;
 }
 
-void FloatOrBoolean::setFloat(float value) {
-  DCHECK(isNull());
+void FloatOrBoolean::SetFloat(float value) {
+  DCHECK(IsNull());
   float_ = value;
-  type_ = SpecificTypeFloat;
+  type_ = SpecificType::kFloat;
 }
 
-FloatOrBoolean FloatOrBoolean::fromFloat(float value) {
+FloatOrBoolean FloatOrBoolean::FromFloat(float value) {
   FloatOrBoolean container;
-  container.setFloat(value);
+  container.SetFloat(value);
   return container;
 }
 
@@ -68,7 +68,7 @@
     return;
 
   if (v8Value->IsBoolean()) {
-    impl.setBoolean(v8Value.As<v8::Boolean>()->Value());
+    impl.SetBoolean(v8Value.As<v8::Boolean>()->Value());
     return;
   }
 
@@ -76,7 +76,7 @@
     float cppValue = NativeValueTraits<IDLFloat>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setFloat(cppValue);
+    impl.SetFloat(cppValue);
     return;
   }
 
@@ -84,19 +84,19 @@
     float cppValue = NativeValueTraits<IDLFloat>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setFloat(cppValue);
+    impl.SetFloat(cppValue);
     return;
   }
 }
 
 v8::Local<v8::Value> ToV8(const FloatOrBoolean& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case FloatOrBoolean::SpecificTypeNone:
+    case FloatOrBoolean::SpecificType::kNone:
       return v8::Null(isolate);
-    case FloatOrBoolean::SpecificTypeBoolean:
-      return v8::Boolean::New(isolate, impl.getAsBoolean());
-    case FloatOrBoolean::SpecificTypeFloat:
-      return v8::Number::New(isolate, impl.getAsFloat());
+    case FloatOrBoolean::SpecificType::kBoolean:
+      return v8::Boolean::New(isolate, impl.GetAsBoolean());
+    case FloatOrBoolean::SpecificType::kFloat:
+      return v8::Number::New(isolate, impl.GetAsFloat());
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/float_or_boolean.h b/third_party/WebKit/Source/bindings/tests/results/core/float_or_boolean.h
index 6764fa3..9e4801a 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/float_or_boolean.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/float_or_boolean.h
@@ -25,17 +25,17 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   FloatOrBoolean();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isBoolean() const { return type_ == SpecificTypeBoolean; }
-  bool getAsBoolean() const;
-  void setBoolean(bool);
-  static FloatOrBoolean fromBoolean(bool);
+  bool IsBoolean() const { return type_ == SpecificType::kBoolean; }
+  bool GetAsBoolean() const;
+  void SetBoolean(bool);
+  static FloatOrBoolean FromBoolean(bool);
 
-  bool isFloat() const { return type_ == SpecificTypeFloat; }
-  float getAsFloat() const;
-  void setFloat(float);
-  static FloatOrBoolean fromFloat(float);
+  bool IsFloat() const { return type_ == SpecificType::kFloat; }
+  float GetAsFloat() const;
+  void SetFloat(float);
+  static FloatOrBoolean FromFloat(float);
 
   FloatOrBoolean(const FloatOrBoolean&);
   ~FloatOrBoolean();
@@ -43,12 +43,12 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeBoolean,
-    SpecificTypeFloat,
+  enum class SpecificType {
+    kNone,
+    kBoolean,
+    kFloat,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   bool boolean_;
   float float_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/long_or_boolean.cc b/third_party/WebKit/Source/bindings/tests/results/core/long_or_boolean.cc
index cef6e0a..eb260994 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/long_or_boolean.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/long_or_boolean.cc
@@ -17,39 +17,39 @@
 
 namespace blink {
 
-LongOrBoolean::LongOrBoolean() : type_(SpecificTypeNone) {}
+LongOrBoolean::LongOrBoolean() : type_(SpecificType::kNone) {}
 
-bool LongOrBoolean::getAsBoolean() const {
-  DCHECK(isBoolean());
+bool LongOrBoolean::GetAsBoolean() const {
+  DCHECK(IsBoolean());
   return boolean_;
 }
 
-void LongOrBoolean::setBoolean(bool value) {
-  DCHECK(isNull());
+void LongOrBoolean::SetBoolean(bool value) {
+  DCHECK(IsNull());
   boolean_ = value;
-  type_ = SpecificTypeBoolean;
+  type_ = SpecificType::kBoolean;
 }
 
-LongOrBoolean LongOrBoolean::fromBoolean(bool value) {
+LongOrBoolean LongOrBoolean::FromBoolean(bool value) {
   LongOrBoolean container;
-  container.setBoolean(value);
+  container.SetBoolean(value);
   return container;
 }
 
-int32_t LongOrBoolean::getAsLong() const {
-  DCHECK(isLong());
+int32_t LongOrBoolean::GetAsLong() const {
+  DCHECK(IsLong());
   return long_;
 }
 
-void LongOrBoolean::setLong(int32_t value) {
-  DCHECK(isNull());
+void LongOrBoolean::SetLong(int32_t value) {
+  DCHECK(IsNull());
   long_ = value;
-  type_ = SpecificTypeLong;
+  type_ = SpecificType::kLong;
 }
 
-LongOrBoolean LongOrBoolean::fromLong(int32_t value) {
+LongOrBoolean LongOrBoolean::FromLong(int32_t value) {
   LongOrBoolean container;
-  container.setLong(value);
+  container.SetLong(value);
   return container;
 }
 
@@ -68,7 +68,7 @@
     return;
 
   if (v8Value->IsBoolean()) {
-    impl.setBoolean(v8Value.As<v8::Boolean>()->Value());
+    impl.SetBoolean(v8Value.As<v8::Boolean>()->Value());
     return;
   }
 
@@ -76,7 +76,7 @@
     int32_t cppValue = NativeValueTraits<IDLLong>::NativeValue(isolate, v8Value, exceptionState, kNormalConversion);
     if (exceptionState.HadException())
       return;
-    impl.setLong(cppValue);
+    impl.SetLong(cppValue);
     return;
   }
 
@@ -84,19 +84,19 @@
     int32_t cppValue = NativeValueTraits<IDLLong>::NativeValue(isolate, v8Value, exceptionState, kNormalConversion);
     if (exceptionState.HadException())
       return;
-    impl.setLong(cppValue);
+    impl.SetLong(cppValue);
     return;
   }
 }
 
 v8::Local<v8::Value> ToV8(const LongOrBoolean& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case LongOrBoolean::SpecificTypeNone:
+    case LongOrBoolean::SpecificType::kNone:
       return v8::Null(isolate);
-    case LongOrBoolean::SpecificTypeBoolean:
-      return v8::Boolean::New(isolate, impl.getAsBoolean());
-    case LongOrBoolean::SpecificTypeLong:
-      return v8::Integer::New(isolate, impl.getAsLong());
+    case LongOrBoolean::SpecificType::kBoolean:
+      return v8::Boolean::New(isolate, impl.GetAsBoolean());
+    case LongOrBoolean::SpecificType::kLong:
+      return v8::Integer::New(isolate, impl.GetAsLong());
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/long_or_boolean.h b/third_party/WebKit/Source/bindings/tests/results/core/long_or_boolean.h
index 91d3c505..9ab64a4 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/long_or_boolean.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/long_or_boolean.h
@@ -25,17 +25,17 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   LongOrBoolean();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isBoolean() const { return type_ == SpecificTypeBoolean; }
-  bool getAsBoolean() const;
-  void setBoolean(bool);
-  static LongOrBoolean fromBoolean(bool);
+  bool IsBoolean() const { return type_ == SpecificType::kBoolean; }
+  bool GetAsBoolean() const;
+  void SetBoolean(bool);
+  static LongOrBoolean FromBoolean(bool);
 
-  bool isLong() const { return type_ == SpecificTypeLong; }
-  int32_t getAsLong() const;
-  void setLong(int32_t);
-  static LongOrBoolean fromLong(int32_t);
+  bool IsLong() const { return type_ == SpecificType::kLong; }
+  int32_t GetAsLong() const;
+  void SetLong(int32_t);
+  static LongOrBoolean FromLong(int32_t);
 
   LongOrBoolean(const LongOrBoolean&);
   ~LongOrBoolean();
@@ -43,12 +43,12 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeBoolean,
-    SpecificTypeLong,
+  enum class SpecificType {
+    kNone,
+    kBoolean,
+    kLong,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   bool boolean_;
   int32_t long_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/long_or_test_dictionary.cc b/third_party/WebKit/Source/bindings/tests/results/core/long_or_test_dictionary.cc
index 5d23d48e..daba7ec 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/long_or_test_dictionary.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/long_or_test_dictionary.cc
@@ -17,39 +17,39 @@
 
 namespace blink {
 
-LongOrTestDictionary::LongOrTestDictionary() : type_(SpecificTypeNone) {}
+LongOrTestDictionary::LongOrTestDictionary() : type_(SpecificType::kNone) {}
 
-int32_t LongOrTestDictionary::getAsLong() const {
-  DCHECK(isLong());
+int32_t LongOrTestDictionary::GetAsLong() const {
+  DCHECK(IsLong());
   return long_;
 }
 
-void LongOrTestDictionary::setLong(int32_t value) {
-  DCHECK(isNull());
+void LongOrTestDictionary::SetLong(int32_t value) {
+  DCHECK(IsNull());
   long_ = value;
-  type_ = SpecificTypeLong;
+  type_ = SpecificType::kLong;
 }
 
-LongOrTestDictionary LongOrTestDictionary::fromLong(int32_t value) {
+LongOrTestDictionary LongOrTestDictionary::FromLong(int32_t value) {
   LongOrTestDictionary container;
-  container.setLong(value);
+  container.SetLong(value);
   return container;
 }
 
-const TestDictionary& LongOrTestDictionary::getAsTestDictionary() const {
-  DCHECK(isTestDictionary());
+const TestDictionary& LongOrTestDictionary::GetAsTestDictionary() const {
+  DCHECK(IsTestDictionary());
   return test_dictionary_;
 }
 
-void LongOrTestDictionary::setTestDictionary(const TestDictionary& value) {
-  DCHECK(isNull());
+void LongOrTestDictionary::SetTestDictionary(const TestDictionary& value) {
+  DCHECK(IsNull());
   test_dictionary_ = value;
-  type_ = SpecificTypeTestDictionary;
+  type_ = SpecificType::kTestDictionary;
 }
 
-LongOrTestDictionary LongOrTestDictionary::fromTestDictionary(const TestDictionary& value) {
+LongOrTestDictionary LongOrTestDictionary::FromTestDictionary(const TestDictionary& value) {
   LongOrTestDictionary container;
-  container.setTestDictionary(value);
+  container.SetTestDictionary(value);
   return container;
 }
 
@@ -73,7 +73,7 @@
     V8TestDictionary::ToImpl(isolate, v8Value, cppValue, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setTestDictionary(cppValue);
+    impl.SetTestDictionary(cppValue);
     return;
   }
 
@@ -82,7 +82,7 @@
     V8TestDictionary::ToImpl(isolate, v8Value, cppValue, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setTestDictionary(cppValue);
+    impl.SetTestDictionary(cppValue);
     return;
   }
 
@@ -90,7 +90,7 @@
     int32_t cppValue = NativeValueTraits<IDLLong>::NativeValue(isolate, v8Value, exceptionState, kNormalConversion);
     if (exceptionState.HadException())
       return;
-    impl.setLong(cppValue);
+    impl.SetLong(cppValue);
     return;
   }
 
@@ -98,19 +98,19 @@
     int32_t cppValue = NativeValueTraits<IDLLong>::NativeValue(isolate, v8Value, exceptionState, kNormalConversion);
     if (exceptionState.HadException())
       return;
-    impl.setLong(cppValue);
+    impl.SetLong(cppValue);
     return;
   }
 }
 
 v8::Local<v8::Value> ToV8(const LongOrTestDictionary& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case LongOrTestDictionary::SpecificTypeNone:
+    case LongOrTestDictionary::SpecificType::kNone:
       return v8::Null(isolate);
-    case LongOrTestDictionary::SpecificTypeLong:
-      return v8::Integer::New(isolate, impl.getAsLong());
-    case LongOrTestDictionary::SpecificTypeTestDictionary:
-      return ToV8(impl.getAsTestDictionary(), creationContext, isolate);
+    case LongOrTestDictionary::SpecificType::kLong:
+      return v8::Integer::New(isolate, impl.GetAsLong());
+    case LongOrTestDictionary::SpecificType::kTestDictionary:
+      return ToV8(impl.GetAsTestDictionary(), creationContext, isolate);
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/long_or_test_dictionary.h b/third_party/WebKit/Source/bindings/tests/results/core/long_or_test_dictionary.h
index e3c1806..06c0824 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/long_or_test_dictionary.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/long_or_test_dictionary.h
@@ -26,17 +26,17 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   LongOrTestDictionary();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isLong() const { return type_ == SpecificTypeLong; }
-  int32_t getAsLong() const;
-  void setLong(int32_t);
-  static LongOrTestDictionary fromLong(int32_t);
+  bool IsLong() const { return type_ == SpecificType::kLong; }
+  int32_t GetAsLong() const;
+  void SetLong(int32_t);
+  static LongOrTestDictionary FromLong(int32_t);
 
-  bool isTestDictionary() const { return type_ == SpecificTypeTestDictionary; }
-  const TestDictionary& getAsTestDictionary() const;
-  void setTestDictionary(const TestDictionary&);
-  static LongOrTestDictionary fromTestDictionary(const TestDictionary&);
+  bool IsTestDictionary() const { return type_ == SpecificType::kTestDictionary; }
+  const TestDictionary& GetAsTestDictionary() const;
+  void SetTestDictionary(const TestDictionary&);
+  static LongOrTestDictionary FromTestDictionary(const TestDictionary&);
 
   LongOrTestDictionary(const LongOrTestDictionary&);
   ~LongOrTestDictionary();
@@ -44,12 +44,12 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeLong,
-    SpecificTypeTestDictionary,
+  enum class SpecificType {
+    kNone,
+    kLong,
+    kTestDictionary,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   int32_t long_;
   TestDictionary test_dictionary_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/long_sequence_or_event.cc b/third_party/WebKit/Source/bindings/tests/results/core/long_sequence_or_event.cc
index 95ee92b..3ee4136 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/long_sequence_or_event.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/long_sequence_or_event.cc
@@ -18,39 +18,39 @@
 
 namespace blink {
 
-LongSequenceOrEvent::LongSequenceOrEvent() : type_(SpecificTypeNone) {}
+LongSequenceOrEvent::LongSequenceOrEvent() : type_(SpecificType::kNone) {}
 
-Event* LongSequenceOrEvent::getAsEvent() const {
-  DCHECK(isEvent());
+Event* LongSequenceOrEvent::GetAsEvent() const {
+  DCHECK(IsEvent());
   return event_;
 }
 
-void LongSequenceOrEvent::setEvent(Event* value) {
-  DCHECK(isNull());
+void LongSequenceOrEvent::SetEvent(Event* value) {
+  DCHECK(IsNull());
   event_ = value;
-  type_ = SpecificTypeEvent;
+  type_ = SpecificType::kEvent;
 }
 
-LongSequenceOrEvent LongSequenceOrEvent::fromEvent(Event* value) {
+LongSequenceOrEvent LongSequenceOrEvent::FromEvent(Event* value) {
   LongSequenceOrEvent container;
-  container.setEvent(value);
+  container.SetEvent(value);
   return container;
 }
 
-const Vector<int32_t>& LongSequenceOrEvent::getAsLongSequence() const {
-  DCHECK(isLongSequence());
+const Vector<int32_t>& LongSequenceOrEvent::GetAsLongSequence() const {
+  DCHECK(IsLongSequence());
   return long_sequence_;
 }
 
-void LongSequenceOrEvent::setLongSequence(const Vector<int32_t>& value) {
-  DCHECK(isNull());
+void LongSequenceOrEvent::SetLongSequence(const Vector<int32_t>& value) {
+  DCHECK(IsNull());
   long_sequence_ = value;
-  type_ = SpecificTypeLongSequence;
+  type_ = SpecificType::kLongSequence;
 }
 
-LongSequenceOrEvent LongSequenceOrEvent::fromLongSequence(const Vector<int32_t>& value) {
+LongSequenceOrEvent LongSequenceOrEvent::FromLongSequence(const Vector<int32_t>& value) {
   LongSequenceOrEvent container;
-  container.setLongSequence(value);
+  container.SetLongSequence(value);
   return container;
 }
 
@@ -71,7 +71,7 @@
 
   if (V8Event::hasInstance(v8Value, isolate)) {
     Event* cppValue = V8Event::ToImpl(v8::Local<v8::Object>::Cast(v8Value));
-    impl.setEvent(cppValue);
+    impl.SetEvent(cppValue);
     return;
   }
 
@@ -79,7 +79,7 @@
     Vector<int32_t> cppValue = NativeValueTraits<IDLSequence<IDLLong>>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setLongSequence(cppValue);
+    impl.SetLongSequence(cppValue);
     return;
   }
 
@@ -88,12 +88,12 @@
 
 v8::Local<v8::Value> ToV8(const LongSequenceOrEvent& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case LongSequenceOrEvent::SpecificTypeNone:
+    case LongSequenceOrEvent::SpecificType::kNone:
       return v8::Null(isolate);
-    case LongSequenceOrEvent::SpecificTypeEvent:
-      return ToV8(impl.getAsEvent(), creationContext, isolate);
-    case LongSequenceOrEvent::SpecificTypeLongSequence:
-      return ToV8(impl.getAsLongSequence(), creationContext, isolate);
+    case LongSequenceOrEvent::SpecificType::kEvent:
+      return ToV8(impl.GetAsEvent(), creationContext, isolate);
+    case LongSequenceOrEvent::SpecificType::kLongSequence:
+      return ToV8(impl.GetAsLongSequence(), creationContext, isolate);
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/long_sequence_or_event.h b/third_party/WebKit/Source/bindings/tests/results/core/long_sequence_or_event.h
index 8c36cbe..81a2e73 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/long_sequence_or_event.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/long_sequence_or_event.h
@@ -27,17 +27,17 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   LongSequenceOrEvent();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isEvent() const { return type_ == SpecificTypeEvent; }
-  Event* getAsEvent() const;
-  void setEvent(Event*);
-  static LongSequenceOrEvent fromEvent(Event*);
+  bool IsEvent() const { return type_ == SpecificType::kEvent; }
+  Event* GetAsEvent() const;
+  void SetEvent(Event*);
+  static LongSequenceOrEvent FromEvent(Event*);
 
-  bool isLongSequence() const { return type_ == SpecificTypeLongSequence; }
-  const Vector<int32_t>& getAsLongSequence() const;
-  void setLongSequence(const Vector<int32_t>&);
-  static LongSequenceOrEvent fromLongSequence(const Vector<int32_t>&);
+  bool IsLongSequence() const { return type_ == SpecificType::kLongSequence; }
+  const Vector<int32_t>& GetAsLongSequence() const;
+  void SetLongSequence(const Vector<int32_t>&);
+  static LongSequenceOrEvent FromLongSequence(const Vector<int32_t>&);
 
   LongSequenceOrEvent(const LongSequenceOrEvent&);
   ~LongSequenceOrEvent();
@@ -45,12 +45,12 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeEvent,
-    SpecificTypeLongSequence,
+  enum class SpecificType {
+    kNone,
+    kEvent,
+    kLongSequence,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   Member<Event> event_;
   Vector<int32_t> long_sequence_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/nested_union_type.cc b/third_party/WebKit/Source/bindings/tests/results/core/nested_union_type.cc
index a36dea0..f41ab18 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/nested_union_type.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/nested_union_type.cc
@@ -26,107 +26,107 @@
 
 namespace blink {
 
-NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord() : type_(SpecificTypeNone) {}
+NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord() : type_(SpecificType::kNone) {}
 
-Event* NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::getAsEvent() const {
-  DCHECK(isEvent());
+Event* NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::GetAsEvent() const {
+  DCHECK(IsEvent());
   return event_;
 }
 
-void NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::setEvent(Event* value) {
-  DCHECK(isNull());
+void NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::SetEvent(Event* value) {
+  DCHECK(IsNull());
   event_ = value;
-  type_ = SpecificTypeEvent;
+  type_ = SpecificType::kEvent;
 }
 
-NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::fromEvent(Event* value) {
+NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::FromEvent(Event* value) {
   NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord container;
-  container.setEvent(value);
+  container.SetEvent(value);
   return container;
 }
 
-const Vector<int32_t>& NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::getAsLongSequence() const {
-  DCHECK(isLongSequence());
+const Vector<int32_t>& NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::GetAsLongSequence() const {
+  DCHECK(IsLongSequence());
   return long_sequence_;
 }
 
-void NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::setLongSequence(const Vector<int32_t>& value) {
-  DCHECK(isNull());
+void NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::SetLongSequence(const Vector<int32_t>& value) {
+  DCHECK(IsNull());
   long_sequence_ = value;
-  type_ = SpecificTypeLongSequence;
+  type_ = SpecificType::kLongSequence;
 }
 
-NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::fromLongSequence(const Vector<int32_t>& value) {
+NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::FromLongSequence(const Vector<int32_t>& value) {
   NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord container;
-  container.setLongSequence(value);
+  container.SetLongSequence(value);
   return container;
 }
 
-Node* NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::getAsNode() const {
-  DCHECK(isNode());
+Node* NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::GetAsNode() const {
+  DCHECK(IsNode());
   return node_;
 }
 
-void NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::setNode(Node* value) {
-  DCHECK(isNull());
+void NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::SetNode(Node* value) {
+  DCHECK(IsNull());
   node_ = value;
-  type_ = SpecificTypeNode;
+  type_ = SpecificType::kNode;
 }
 
-NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::fromNode(Node* value) {
+NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::FromNode(Node* value) {
   NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord container;
-  container.setNode(value);
+  container.SetNode(value);
   return container;
 }
 
-const String& NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::getAsString() const {
-  DCHECK(isString());
+const String& NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::GetAsString() const {
+  DCHECK(IsString());
   return string_;
 }
 
-void NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::setString(const String& value) {
-  DCHECK(isNull());
+void NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::SetString(const String& value) {
+  DCHECK(IsNull());
   string_ = value;
-  type_ = SpecificTypeString;
+  type_ = SpecificType::kString;
 }
 
-NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::fromString(const String& value) {
+NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::FromString(const String& value) {
   NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord container;
-  container.setString(value);
+  container.SetString(value);
   return container;
 }
 
-const HeapVector<std::pair<String, ByteStringOrNodeList>>& NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::getAsStringByteStringOrNodeListRecord() const {
-  DCHECK(isStringByteStringOrNodeListRecord());
+const HeapVector<std::pair<String, ByteStringOrNodeList>>& NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::GetAsStringByteStringOrNodeListRecord() const {
+  DCHECK(IsStringByteStringOrNodeListRecord());
   return string_byte_string_or_node_list_record_;
 }
 
-void NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::setStringByteStringOrNodeListRecord(const HeapVector<std::pair<String, ByteStringOrNodeList>>& value) {
-  DCHECK(isNull());
+void NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::SetStringByteStringOrNodeListRecord(const HeapVector<std::pair<String, ByteStringOrNodeList>>& value) {
+  DCHECK(IsNull());
   string_byte_string_or_node_list_record_ = value;
-  type_ = SpecificTypeStringByteStringOrNodeListRecord;
+  type_ = SpecificType::kStringByteStringOrNodeListRecord;
 }
 
-NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::fromStringByteStringOrNodeListRecord(const HeapVector<std::pair<String, ByteStringOrNodeList>>& value) {
+NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::FromStringByteStringOrNodeListRecord(const HeapVector<std::pair<String, ByteStringOrNodeList>>& value) {
   NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord container;
-  container.setStringByteStringOrNodeListRecord(value);
+  container.SetStringByteStringOrNodeListRecord(value);
   return container;
 }
 
-XMLHttpRequest* NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::getAsXMLHttpRequest() const {
-  DCHECK(isXMLHttpRequest());
+XMLHttpRequest* NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::GetAsXMLHttpRequest() const {
+  DCHECK(IsXMLHttpRequest());
   return xml_http_request_;
 }
 
-void NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::setXMLHttpRequest(XMLHttpRequest* value) {
-  DCHECK(isNull());
+void NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::SetXMLHttpRequest(XMLHttpRequest* value) {
+  DCHECK(IsNull());
   xml_http_request_ = value;
-  type_ = SpecificTypeXMLHttpRequest;
+  type_ = SpecificType::kXMLHttpRequest;
 }
 
-NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::fromXMLHttpRequest(XMLHttpRequest* value) {
+NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::FromXMLHttpRequest(XMLHttpRequest* value) {
   NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord container;
-  container.setXMLHttpRequest(value);
+  container.SetXMLHttpRequest(value);
   return container;
 }
 
@@ -150,19 +150,19 @@
 
   if (V8Event::hasInstance(v8Value, isolate)) {
     Event* cppValue = V8Event::ToImpl(v8::Local<v8::Object>::Cast(v8Value));
-    impl.setEvent(cppValue);
+    impl.SetEvent(cppValue);
     return;
   }
 
   if (V8Node::hasInstance(v8Value, isolate)) {
     Node* cppValue = V8Node::ToImpl(v8::Local<v8::Object>::Cast(v8Value));
-    impl.setNode(cppValue);
+    impl.SetNode(cppValue);
     return;
   }
 
   if (V8XMLHttpRequest::hasInstance(v8Value, isolate)) {
     XMLHttpRequest* cppValue = V8XMLHttpRequest::ToImpl(v8::Local<v8::Object>::Cast(v8Value));
-    impl.setXMLHttpRequest(cppValue);
+    impl.SetXMLHttpRequest(cppValue);
     return;
   }
 
@@ -170,7 +170,7 @@
     Vector<int32_t> cppValue = NativeValueTraits<IDLSequence<IDLLong>>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setLongSequence(cppValue);
+    impl.SetLongSequence(cppValue);
     return;
   }
 
@@ -178,7 +178,7 @@
     HeapVector<std::pair<String, ByteStringOrNodeList>> cppValue = NativeValueTraits<IDLRecord<IDLString, ByteStringOrNodeList>>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setStringByteStringOrNodeListRecord(cppValue);
+    impl.SetStringByteStringOrNodeListRecord(cppValue);
     return;
   }
 
@@ -186,27 +186,27 @@
     V8StringResource<> cppValue = v8Value;
     if (!cppValue.Prepare(exceptionState))
       return;
-    impl.setString(cppValue);
+    impl.SetString(cppValue);
     return;
   }
 }
 
 v8::Local<v8::Value> ToV8(const NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::SpecificTypeNone:
+    case NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::SpecificType::kNone:
       return v8::Null(isolate);
-    case NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::SpecificTypeEvent:
-      return ToV8(impl.getAsEvent(), creationContext, isolate);
-    case NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::SpecificTypeLongSequence:
-      return ToV8(impl.getAsLongSequence(), creationContext, isolate);
-    case NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::SpecificTypeNode:
-      return ToV8(impl.getAsNode(), creationContext, isolate);
-    case NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::SpecificTypeString:
-      return V8String(isolate, impl.getAsString());
-    case NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::SpecificTypeStringByteStringOrNodeListRecord:
-      return ToV8(impl.getAsStringByteStringOrNodeListRecord(), creationContext, isolate);
-    case NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::SpecificTypeXMLHttpRequest:
-      return ToV8(impl.getAsXMLHttpRequest(), creationContext, isolate);
+    case NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::SpecificType::kEvent:
+      return ToV8(impl.GetAsEvent(), creationContext, isolate);
+    case NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::SpecificType::kLongSequence:
+      return ToV8(impl.GetAsLongSequence(), creationContext, isolate);
+    case NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::SpecificType::kNode:
+      return ToV8(impl.GetAsNode(), creationContext, isolate);
+    case NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::SpecificType::kString:
+      return V8String(isolate, impl.GetAsString());
+    case NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::SpecificType::kStringByteStringOrNodeListRecord:
+      return ToV8(impl.GetAsStringByteStringOrNodeListRecord(), creationContext, isolate);
+    case NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord::SpecificType::kXMLHttpRequest:
+      return ToV8(impl.GetAsXMLHttpRequest(), creationContext, isolate);
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/nested_union_type.h b/third_party/WebKit/Source/bindings/tests/results/core/nested_union_type.h
index 51491c7..386ff9dd 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/nested_union_type.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/nested_union_type.h
@@ -30,37 +30,37 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isEvent() const { return type_ == SpecificTypeEvent; }
-  Event* getAsEvent() const;
-  void setEvent(Event*);
-  static NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord fromEvent(Event*);
+  bool IsEvent() const { return type_ == SpecificType::kEvent; }
+  Event* GetAsEvent() const;
+  void SetEvent(Event*);
+  static NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord FromEvent(Event*);
 
-  bool isLongSequence() const { return type_ == SpecificTypeLongSequence; }
-  const Vector<int32_t>& getAsLongSequence() const;
-  void setLongSequence(const Vector<int32_t>&);
-  static NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord fromLongSequence(const Vector<int32_t>&);
+  bool IsLongSequence() const { return type_ == SpecificType::kLongSequence; }
+  const Vector<int32_t>& GetAsLongSequence() const;
+  void SetLongSequence(const Vector<int32_t>&);
+  static NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord FromLongSequence(const Vector<int32_t>&);
 
-  bool isNode() const { return type_ == SpecificTypeNode; }
-  Node* getAsNode() const;
-  void setNode(Node*);
-  static NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord fromNode(Node*);
+  bool IsNode() const { return type_ == SpecificType::kNode; }
+  Node* GetAsNode() const;
+  void SetNode(Node*);
+  static NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord FromNode(Node*);
 
-  bool isString() const { return type_ == SpecificTypeString; }
-  const String& getAsString() const;
-  void setString(const String&);
-  static NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord fromString(const String&);
+  bool IsString() const { return type_ == SpecificType::kString; }
+  const String& GetAsString() const;
+  void SetString(const String&);
+  static NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord FromString(const String&);
 
-  bool isStringByteStringOrNodeListRecord() const { return type_ == SpecificTypeStringByteStringOrNodeListRecord; }
-  const HeapVector<std::pair<String, ByteStringOrNodeList>>& getAsStringByteStringOrNodeListRecord() const;
-  void setStringByteStringOrNodeListRecord(const HeapVector<std::pair<String, ByteStringOrNodeList>>&);
-  static NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord fromStringByteStringOrNodeListRecord(const HeapVector<std::pair<String, ByteStringOrNodeList>>&);
+  bool IsStringByteStringOrNodeListRecord() const { return type_ == SpecificType::kStringByteStringOrNodeListRecord; }
+  const HeapVector<std::pair<String, ByteStringOrNodeList>>& GetAsStringByteStringOrNodeListRecord() const;
+  void SetStringByteStringOrNodeListRecord(const HeapVector<std::pair<String, ByteStringOrNodeList>>&);
+  static NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord FromStringByteStringOrNodeListRecord(const HeapVector<std::pair<String, ByteStringOrNodeList>>&);
 
-  bool isXMLHttpRequest() const { return type_ == SpecificTypeXMLHttpRequest; }
-  XMLHttpRequest* getAsXMLHttpRequest() const;
-  void setXMLHttpRequest(XMLHttpRequest*);
-  static NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord fromXMLHttpRequest(XMLHttpRequest*);
+  bool IsXMLHttpRequest() const { return type_ == SpecificType::kXMLHttpRequest; }
+  XMLHttpRequest* GetAsXMLHttpRequest() const;
+  void SetXMLHttpRequest(XMLHttpRequest*);
+  static NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord FromXMLHttpRequest(XMLHttpRequest*);
 
   NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord(const NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord&);
   ~NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord();
@@ -68,16 +68,16 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeEvent,
-    SpecificTypeLongSequence,
-    SpecificTypeNode,
-    SpecificTypeString,
-    SpecificTypeStringByteStringOrNodeListRecord,
-    SpecificTypeXMLHttpRequest,
+  enum class SpecificType {
+    kNone,
+    kEvent,
+    kLongSequence,
+    kNode,
+    kString,
+    kStringByteStringOrNodeListRecord,
+    kXMLHttpRequest,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   Member<Event> event_;
   Vector<int32_t> long_sequence_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/node_or_node_list.cc b/third_party/WebKit/Source/bindings/tests/results/core/node_or_node_list.cc
index befa903..0d917062 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/node_or_node_list.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/node_or_node_list.cc
@@ -21,39 +21,39 @@
 
 namespace blink {
 
-NodeOrNodeList::NodeOrNodeList() : type_(SpecificTypeNone) {}
+NodeOrNodeList::NodeOrNodeList() : type_(SpecificType::kNone) {}
 
-Node* NodeOrNodeList::getAsNode() const {
-  DCHECK(isNode());
+Node* NodeOrNodeList::GetAsNode() const {
+  DCHECK(IsNode());
   return node_;
 }
 
-void NodeOrNodeList::setNode(Node* value) {
-  DCHECK(isNull());
+void NodeOrNodeList::SetNode(Node* value) {
+  DCHECK(IsNull());
   node_ = value;
-  type_ = SpecificTypeNode;
+  type_ = SpecificType::kNode;
 }
 
-NodeOrNodeList NodeOrNodeList::fromNode(Node* value) {
+NodeOrNodeList NodeOrNodeList::FromNode(Node* value) {
   NodeOrNodeList container;
-  container.setNode(value);
+  container.SetNode(value);
   return container;
 }
 
-NodeList* NodeOrNodeList::getAsNodeList() const {
-  DCHECK(isNodeList());
+NodeList* NodeOrNodeList::GetAsNodeList() const {
+  DCHECK(IsNodeList());
   return node_list_;
 }
 
-void NodeOrNodeList::setNodeList(NodeList* value) {
-  DCHECK(isNull());
+void NodeOrNodeList::SetNodeList(NodeList* value) {
+  DCHECK(IsNull());
   node_list_ = value;
-  type_ = SpecificTypeNodeList;
+  type_ = SpecificType::kNodeList;
 }
 
-NodeOrNodeList NodeOrNodeList::fromNodeList(NodeList* value) {
+NodeOrNodeList NodeOrNodeList::FromNodeList(NodeList* value) {
   NodeOrNodeList container;
-  container.setNodeList(value);
+  container.SetNodeList(value);
   return container;
 }
 
@@ -75,13 +75,13 @@
 
   if (V8Node::hasInstance(v8Value, isolate)) {
     Node* cppValue = V8Node::ToImpl(v8::Local<v8::Object>::Cast(v8Value));
-    impl.setNode(cppValue);
+    impl.SetNode(cppValue);
     return;
   }
 
   if (V8NodeList::hasInstance(v8Value, isolate)) {
     NodeList* cppValue = V8NodeList::ToImpl(v8::Local<v8::Object>::Cast(v8Value));
-    impl.setNodeList(cppValue);
+    impl.SetNodeList(cppValue);
     return;
   }
 
@@ -90,12 +90,12 @@
 
 v8::Local<v8::Value> ToV8(const NodeOrNodeList& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case NodeOrNodeList::SpecificTypeNone:
+    case NodeOrNodeList::SpecificType::kNone:
       return v8::Null(isolate);
-    case NodeOrNodeList::SpecificTypeNode:
-      return ToV8(impl.getAsNode(), creationContext, isolate);
-    case NodeOrNodeList::SpecificTypeNodeList:
-      return ToV8(impl.getAsNodeList(), creationContext, isolate);
+    case NodeOrNodeList::SpecificType::kNode:
+      return ToV8(impl.GetAsNode(), creationContext, isolate);
+    case NodeOrNodeList::SpecificType::kNodeList:
+      return ToV8(impl.GetAsNodeList(), creationContext, isolate);
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/node_or_node_list.h b/third_party/WebKit/Source/bindings/tests/results/core/node_or_node_list.h
index 162d1a7..080a81e 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/node_or_node_list.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/node_or_node_list.h
@@ -28,17 +28,17 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   NodeOrNodeList();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isNode() const { return type_ == SpecificTypeNode; }
-  Node* getAsNode() const;
-  void setNode(Node*);
-  static NodeOrNodeList fromNode(Node*);
+  bool IsNode() const { return type_ == SpecificType::kNode; }
+  Node* GetAsNode() const;
+  void SetNode(Node*);
+  static NodeOrNodeList FromNode(Node*);
 
-  bool isNodeList() const { return type_ == SpecificTypeNodeList; }
-  NodeList* getAsNodeList() const;
-  void setNodeList(NodeList*);
-  static NodeOrNodeList fromNodeList(NodeList*);
+  bool IsNodeList() const { return type_ == SpecificType::kNodeList; }
+  NodeList* GetAsNodeList() const;
+  void SetNodeList(NodeList*);
+  static NodeOrNodeList FromNodeList(NodeList*);
 
   NodeOrNodeList(const NodeOrNodeList&);
   ~NodeOrNodeList();
@@ -46,12 +46,12 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeNode,
-    SpecificTypeNodeList,
+  enum class SpecificType {
+    kNone,
+    kNode,
+    kNodeList,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   Member<Node> node_;
   Member<NodeList> node_list_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/string_or_array_buffer_or_array_buffer_view.cc b/third_party/WebKit/Source/bindings/tests/results/core/string_or_array_buffer_or_array_buffer_view.cc
index 502676e..98857dd 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/string_or_array_buffer_or_array_buffer_view.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/string_or_array_buffer_or_array_buffer_view.cc
@@ -18,56 +18,56 @@
 
 namespace blink {
 
-StringOrArrayBufferOrArrayBufferView::StringOrArrayBufferOrArrayBufferView() : type_(SpecificTypeNone) {}
+StringOrArrayBufferOrArrayBufferView::StringOrArrayBufferOrArrayBufferView() : type_(SpecificType::kNone) {}
 
-TestArrayBuffer* StringOrArrayBufferOrArrayBufferView::getAsArrayBuffer() const {
-  DCHECK(isArrayBuffer());
+TestArrayBuffer* StringOrArrayBufferOrArrayBufferView::GetAsArrayBuffer() const {
+  DCHECK(IsArrayBuffer());
   return array_buffer_;
 }
 
-void StringOrArrayBufferOrArrayBufferView::setArrayBuffer(TestArrayBuffer* value) {
-  DCHECK(isNull());
+void StringOrArrayBufferOrArrayBufferView::SetArrayBuffer(TestArrayBuffer* value) {
+  DCHECK(IsNull());
   array_buffer_ = value;
-  type_ = SpecificTypeArrayBuffer;
+  type_ = SpecificType::kArrayBuffer;
 }
 
-StringOrArrayBufferOrArrayBufferView StringOrArrayBufferOrArrayBufferView::fromArrayBuffer(TestArrayBuffer* value) {
+StringOrArrayBufferOrArrayBufferView StringOrArrayBufferOrArrayBufferView::FromArrayBuffer(TestArrayBuffer* value) {
   StringOrArrayBufferOrArrayBufferView container;
-  container.setArrayBuffer(value);
+  container.SetArrayBuffer(value);
   return container;
 }
 
-NotShared<TestArrayBufferView> StringOrArrayBufferOrArrayBufferView::getAsArrayBufferView() const {
-  DCHECK(isArrayBufferView());
+NotShared<TestArrayBufferView> StringOrArrayBufferOrArrayBufferView::GetAsArrayBufferView() const {
+  DCHECK(IsArrayBufferView());
   return array_buffer_view_;
 }
 
-void StringOrArrayBufferOrArrayBufferView::setArrayBufferView(NotShared<TestArrayBufferView> value) {
-  DCHECK(isNull());
+void StringOrArrayBufferOrArrayBufferView::SetArrayBufferView(NotShared<TestArrayBufferView> value) {
+  DCHECK(IsNull());
   array_buffer_view_ = Member<TestArrayBufferView>(value.View());
-  type_ = SpecificTypeArrayBufferView;
+  type_ = SpecificType::kArrayBufferView;
 }
 
-StringOrArrayBufferOrArrayBufferView StringOrArrayBufferOrArrayBufferView::fromArrayBufferView(NotShared<TestArrayBufferView> value) {
+StringOrArrayBufferOrArrayBufferView StringOrArrayBufferOrArrayBufferView::FromArrayBufferView(NotShared<TestArrayBufferView> value) {
   StringOrArrayBufferOrArrayBufferView container;
-  container.setArrayBufferView(value);
+  container.SetArrayBufferView(value);
   return container;
 }
 
-const String& StringOrArrayBufferOrArrayBufferView::getAsString() const {
-  DCHECK(isString());
+const String& StringOrArrayBufferOrArrayBufferView::GetAsString() const {
+  DCHECK(IsString());
   return string_;
 }
 
-void StringOrArrayBufferOrArrayBufferView::setString(const String& value) {
-  DCHECK(isNull());
+void StringOrArrayBufferOrArrayBufferView::SetString(const String& value) {
+  DCHECK(IsNull());
   string_ = value;
-  type_ = SpecificTypeString;
+  type_ = SpecificType::kString;
 }
 
-StringOrArrayBufferOrArrayBufferView StringOrArrayBufferOrArrayBufferView::fromString(const String& value) {
+StringOrArrayBufferOrArrayBufferView StringOrArrayBufferOrArrayBufferView::FromString(const String& value) {
   StringOrArrayBufferOrArrayBufferView container;
-  container.setString(value);
+  container.SetString(value);
   return container;
 }
 
@@ -89,7 +89,7 @@
 
   if (v8Value->IsArrayBuffer()) {
     TestArrayBuffer* cppValue = V8ArrayBuffer::ToImpl(v8::Local<v8::Object>::Cast(v8Value));
-    impl.setArrayBuffer(cppValue);
+    impl.SetArrayBuffer(cppValue);
     return;
   }
 
@@ -97,7 +97,7 @@
     NotShared<TestArrayBufferView> cppValue = ToNotShared<NotShared<TestArrayBufferView>>(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setArrayBufferView(cppValue);
+    impl.SetArrayBufferView(cppValue);
     return;
   }
 
@@ -105,21 +105,21 @@
     V8StringResource<> cppValue = v8Value;
     if (!cppValue.Prepare(exceptionState))
       return;
-    impl.setString(cppValue);
+    impl.SetString(cppValue);
     return;
   }
 }
 
 v8::Local<v8::Value> ToV8(const StringOrArrayBufferOrArrayBufferView& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case StringOrArrayBufferOrArrayBufferView::SpecificTypeNone:
+    case StringOrArrayBufferOrArrayBufferView::SpecificType::kNone:
       return v8::Null(isolate);
-    case StringOrArrayBufferOrArrayBufferView::SpecificTypeArrayBuffer:
-      return ToV8(impl.getAsArrayBuffer(), creationContext, isolate);
-    case StringOrArrayBufferOrArrayBufferView::SpecificTypeArrayBufferView:
-      return ToV8(impl.getAsArrayBufferView(), creationContext, isolate);
-    case StringOrArrayBufferOrArrayBufferView::SpecificTypeString:
-      return V8String(isolate, impl.getAsString());
+    case StringOrArrayBufferOrArrayBufferView::SpecificType::kArrayBuffer:
+      return ToV8(impl.GetAsArrayBuffer(), creationContext, isolate);
+    case StringOrArrayBufferOrArrayBufferView::SpecificType::kArrayBufferView:
+      return ToV8(impl.GetAsArrayBufferView(), creationContext, isolate);
+    case StringOrArrayBufferOrArrayBufferView::SpecificType::kString:
+      return V8String(isolate, impl.GetAsString());
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/string_or_array_buffer_or_array_buffer_view.h b/third_party/WebKit/Source/bindings/tests/results/core/string_or_array_buffer_or_array_buffer_view.h
index b434355d..d2f67e1 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/string_or_array_buffer_or_array_buffer_view.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/string_or_array_buffer_or_array_buffer_view.h
@@ -30,22 +30,22 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   StringOrArrayBufferOrArrayBufferView();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isArrayBuffer() const { return type_ == SpecificTypeArrayBuffer; }
-  TestArrayBuffer* getAsArrayBuffer() const;
-  void setArrayBuffer(TestArrayBuffer*);
-  static StringOrArrayBufferOrArrayBufferView fromArrayBuffer(TestArrayBuffer*);
+  bool IsArrayBuffer() const { return type_ == SpecificType::kArrayBuffer; }
+  TestArrayBuffer* GetAsArrayBuffer() const;
+  void SetArrayBuffer(TestArrayBuffer*);
+  static StringOrArrayBufferOrArrayBufferView FromArrayBuffer(TestArrayBuffer*);
 
-  bool isArrayBufferView() const { return type_ == SpecificTypeArrayBufferView; }
-  NotShared<TestArrayBufferView> getAsArrayBufferView() const;
-  void setArrayBufferView(NotShared<TestArrayBufferView>);
-  static StringOrArrayBufferOrArrayBufferView fromArrayBufferView(NotShared<TestArrayBufferView>);
+  bool IsArrayBufferView() const { return type_ == SpecificType::kArrayBufferView; }
+  NotShared<TestArrayBufferView> GetAsArrayBufferView() const;
+  void SetArrayBufferView(NotShared<TestArrayBufferView>);
+  static StringOrArrayBufferOrArrayBufferView FromArrayBufferView(NotShared<TestArrayBufferView>);
 
-  bool isString() const { return type_ == SpecificTypeString; }
-  const String& getAsString() const;
-  void setString(const String&);
-  static StringOrArrayBufferOrArrayBufferView fromString(const String&);
+  bool IsString() const { return type_ == SpecificType::kString; }
+  const String& GetAsString() const;
+  void SetString(const String&);
+  static StringOrArrayBufferOrArrayBufferView FromString(const String&);
 
   StringOrArrayBufferOrArrayBufferView(const StringOrArrayBufferOrArrayBufferView&);
   ~StringOrArrayBufferOrArrayBufferView();
@@ -53,13 +53,13 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeArrayBuffer,
-    SpecificTypeArrayBufferView,
-    SpecificTypeString,
+  enum class SpecificType {
+    kNone,
+    kArrayBuffer,
+    kArrayBufferView,
+    kString,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   Member<TestArrayBuffer> array_buffer_;
   Member<TestArrayBufferView> array_buffer_view_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/string_or_double.cc b/third_party/WebKit/Source/bindings/tests/results/core/string_or_double.cc
index d7d0be0..5a202f4 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/string_or_double.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/string_or_double.cc
@@ -17,39 +17,39 @@
 
 namespace blink {
 
-StringOrDouble::StringOrDouble() : type_(SpecificTypeNone) {}
+StringOrDouble::StringOrDouble() : type_(SpecificType::kNone) {}
 
-double StringOrDouble::getAsDouble() const {
-  DCHECK(isDouble());
+double StringOrDouble::GetAsDouble() const {
+  DCHECK(IsDouble());
   return double_;
 }
 
-void StringOrDouble::setDouble(double value) {
-  DCHECK(isNull());
+void StringOrDouble::SetDouble(double value) {
+  DCHECK(IsNull());
   double_ = value;
-  type_ = SpecificTypeDouble;
+  type_ = SpecificType::kDouble;
 }
 
-StringOrDouble StringOrDouble::fromDouble(double value) {
+StringOrDouble StringOrDouble::FromDouble(double value) {
   StringOrDouble container;
-  container.setDouble(value);
+  container.SetDouble(value);
   return container;
 }
 
-const String& StringOrDouble::getAsString() const {
-  DCHECK(isString());
+const String& StringOrDouble::GetAsString() const {
+  DCHECK(IsString());
   return string_;
 }
 
-void StringOrDouble::setString(const String& value) {
-  DCHECK(isNull());
+void StringOrDouble::SetString(const String& value) {
+  DCHECK(IsNull());
   string_ = value;
-  type_ = SpecificTypeString;
+  type_ = SpecificType::kString;
 }
 
-StringOrDouble StringOrDouble::fromString(const String& value) {
+StringOrDouble StringOrDouble::FromString(const String& value) {
   StringOrDouble container;
-  container.setString(value);
+  container.SetString(value);
   return container;
 }
 
@@ -71,7 +71,7 @@
     double cppValue = NativeValueTraits<IDLDouble>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setDouble(cppValue);
+    impl.SetDouble(cppValue);
     return;
   }
 
@@ -79,19 +79,19 @@
     V8StringResource<> cppValue = v8Value;
     if (!cppValue.Prepare(exceptionState))
       return;
-    impl.setString(cppValue);
+    impl.SetString(cppValue);
     return;
   }
 }
 
 v8::Local<v8::Value> ToV8(const StringOrDouble& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case StringOrDouble::SpecificTypeNone:
+    case StringOrDouble::SpecificType::kNone:
       return v8::Null(isolate);
-    case StringOrDouble::SpecificTypeDouble:
-      return v8::Number::New(isolate, impl.getAsDouble());
-    case StringOrDouble::SpecificTypeString:
-      return V8String(isolate, impl.getAsString());
+    case StringOrDouble::SpecificType::kDouble:
+      return v8::Number::New(isolate, impl.GetAsDouble());
+    case StringOrDouble::SpecificType::kString:
+      return V8String(isolate, impl.GetAsString());
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/string_or_double.h b/third_party/WebKit/Source/bindings/tests/results/core/string_or_double.h
index be115bd..0c4137dd 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/string_or_double.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/string_or_double.h
@@ -25,17 +25,17 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   StringOrDouble();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isDouble() const { return type_ == SpecificTypeDouble; }
-  double getAsDouble() const;
-  void setDouble(double);
-  static StringOrDouble fromDouble(double);
+  bool IsDouble() const { return type_ == SpecificType::kDouble; }
+  double GetAsDouble() const;
+  void SetDouble(double);
+  static StringOrDouble FromDouble(double);
 
-  bool isString() const { return type_ == SpecificTypeString; }
-  const String& getAsString() const;
-  void setString(const String&);
-  static StringOrDouble fromString(const String&);
+  bool IsString() const { return type_ == SpecificType::kString; }
+  const String& GetAsString() const;
+  void SetString(const String&);
+  static StringOrDouble FromString(const String&);
 
   StringOrDouble(const StringOrDouble&);
   ~StringOrDouble();
@@ -43,12 +43,12 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeDouble,
-    SpecificTypeString,
+  enum class SpecificType {
+    kNone,
+    kDouble,
+    kString,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   double double_;
   String string_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/string_or_string_sequence.cc b/third_party/WebKit/Source/bindings/tests/results/core/string_or_string_sequence.cc
index ee0ee3c..b813475c 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/string_or_string_sequence.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/string_or_string_sequence.cc
@@ -17,39 +17,39 @@
 
 namespace blink {
 
-StringOrStringSequence::StringOrStringSequence() : type_(SpecificTypeNone) {}
+StringOrStringSequence::StringOrStringSequence() : type_(SpecificType::kNone) {}
 
-const String& StringOrStringSequence::getAsString() const {
-  DCHECK(isString());
+const String& StringOrStringSequence::GetAsString() const {
+  DCHECK(IsString());
   return string_;
 }
 
-void StringOrStringSequence::setString(const String& value) {
-  DCHECK(isNull());
+void StringOrStringSequence::SetString(const String& value) {
+  DCHECK(IsNull());
   string_ = value;
-  type_ = SpecificTypeString;
+  type_ = SpecificType::kString;
 }
 
-StringOrStringSequence StringOrStringSequence::fromString(const String& value) {
+StringOrStringSequence StringOrStringSequence::FromString(const String& value) {
   StringOrStringSequence container;
-  container.setString(value);
+  container.SetString(value);
   return container;
 }
 
-const Vector<String>& StringOrStringSequence::getAsStringSequence() const {
-  DCHECK(isStringSequence());
+const Vector<String>& StringOrStringSequence::GetAsStringSequence() const {
+  DCHECK(IsStringSequence());
   return string_sequence_;
 }
 
-void StringOrStringSequence::setStringSequence(const Vector<String>& value) {
-  DCHECK(isNull());
+void StringOrStringSequence::SetStringSequence(const Vector<String>& value) {
+  DCHECK(IsNull());
   string_sequence_ = value;
-  type_ = SpecificTypeStringSequence;
+  type_ = SpecificType::kStringSequence;
 }
 
-StringOrStringSequence StringOrStringSequence::fromStringSequence(const Vector<String>& value) {
+StringOrStringSequence StringOrStringSequence::FromStringSequence(const Vector<String>& value) {
   StringOrStringSequence container;
-  container.setStringSequence(value);
+  container.SetStringSequence(value);
   return container;
 }
 
@@ -71,7 +71,7 @@
     Vector<String> cppValue = NativeValueTraits<IDLSequence<IDLString>>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setStringSequence(cppValue);
+    impl.SetStringSequence(cppValue);
     return;
   }
 
@@ -79,19 +79,19 @@
     V8StringResource<> cppValue = v8Value;
     if (!cppValue.Prepare(exceptionState))
       return;
-    impl.setString(cppValue);
+    impl.SetString(cppValue);
     return;
   }
 }
 
 v8::Local<v8::Value> ToV8(const StringOrStringSequence& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case StringOrStringSequence::SpecificTypeNone:
+    case StringOrStringSequence::SpecificType::kNone:
       return v8::Null(isolate);
-    case StringOrStringSequence::SpecificTypeString:
-      return V8String(isolate, impl.getAsString());
-    case StringOrStringSequence::SpecificTypeStringSequence:
-      return ToV8(impl.getAsStringSequence(), creationContext, isolate);
+    case StringOrStringSequence::SpecificType::kString:
+      return V8String(isolate, impl.GetAsString());
+    case StringOrStringSequence::SpecificType::kStringSequence:
+      return ToV8(impl.GetAsStringSequence(), creationContext, isolate);
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/string_or_string_sequence.h b/third_party/WebKit/Source/bindings/tests/results/core/string_or_string_sequence.h
index 362de49..b055a1b2 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/string_or_string_sequence.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/string_or_string_sequence.h
@@ -25,17 +25,17 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   StringOrStringSequence();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isString() const { return type_ == SpecificTypeString; }
-  const String& getAsString() const;
-  void setString(const String&);
-  static StringOrStringSequence fromString(const String&);
+  bool IsString() const { return type_ == SpecificType::kString; }
+  const String& GetAsString() const;
+  void SetString(const String&);
+  static StringOrStringSequence FromString(const String&);
 
-  bool isStringSequence() const { return type_ == SpecificTypeStringSequence; }
-  const Vector<String>& getAsStringSequence() const;
-  void setStringSequence(const Vector<String>&);
-  static StringOrStringSequence fromStringSequence(const Vector<String>&);
+  bool IsStringSequence() const { return type_ == SpecificType::kStringSequence; }
+  const Vector<String>& GetAsStringSequence() const;
+  void SetStringSequence(const Vector<String>&);
+  static StringOrStringSequence FromStringSequence(const Vector<String>&);
 
   StringOrStringSequence(const StringOrStringSequence&);
   ~StringOrStringSequence();
@@ -43,12 +43,12 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeString,
-    SpecificTypeStringSequence,
+  enum class SpecificType {
+    kNone,
+    kString,
+    kStringSequence,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   String string_;
   Vector<String> string_sequence_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/test_enum_or_double.cc b/third_party/WebKit/Source/bindings/tests/results/core/test_enum_or_double.cc
index 95b6643..0b65609f 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/test_enum_or_double.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/test_enum_or_double.cc
@@ -17,32 +17,32 @@
 
 namespace blink {
 
-TestEnumOrDouble::TestEnumOrDouble() : type_(SpecificTypeNone) {}
+TestEnumOrDouble::TestEnumOrDouble() : type_(SpecificType::kNone) {}
 
-double TestEnumOrDouble::getAsDouble() const {
-  DCHECK(isDouble());
+double TestEnumOrDouble::GetAsDouble() const {
+  DCHECK(IsDouble());
   return double_;
 }
 
-void TestEnumOrDouble::setDouble(double value) {
-  DCHECK(isNull());
+void TestEnumOrDouble::SetDouble(double value) {
+  DCHECK(IsNull());
   double_ = value;
-  type_ = SpecificTypeDouble;
+  type_ = SpecificType::kDouble;
 }
 
-TestEnumOrDouble TestEnumOrDouble::fromDouble(double value) {
+TestEnumOrDouble TestEnumOrDouble::FromDouble(double value) {
   TestEnumOrDouble container;
-  container.setDouble(value);
+  container.SetDouble(value);
   return container;
 }
 
-const String& TestEnumOrDouble::getAsTestEnum() const {
-  DCHECK(isTestEnum());
+const String& TestEnumOrDouble::GetAsTestEnum() const {
+  DCHECK(IsTestEnum());
   return test_enum_;
 }
 
-void TestEnumOrDouble::setTestEnum(const String& value) {
-  DCHECK(isNull());
+void TestEnumOrDouble::SetTestEnum(const String& value) {
+  DCHECK(IsNull());
   NonThrowableExceptionState exceptionState;
   const char* validValues[] = {
       "",
@@ -55,12 +55,12 @@
     return;
   }
   test_enum_ = value;
-  type_ = SpecificTypeTestEnum;
+  type_ = SpecificType::kTestEnum;
 }
 
-TestEnumOrDouble TestEnumOrDouble::fromTestEnum(const String& value) {
+TestEnumOrDouble TestEnumOrDouble::FromTestEnum(const String& value) {
   TestEnumOrDouble container;
-  container.setTestEnum(value);
+  container.SetTestEnum(value);
   return container;
 }
 
@@ -82,7 +82,7 @@
     double cppValue = NativeValueTraits<IDLDouble>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setDouble(cppValue);
+    impl.SetDouble(cppValue);
     return;
   }
 
@@ -98,19 +98,19 @@
     };
     if (!IsValidEnum(cppValue, validValues, WTF_ARRAY_LENGTH(validValues), "TestEnum", exceptionState))
       return;
-    impl.setTestEnum(cppValue);
+    impl.SetTestEnum(cppValue);
     return;
   }
 }
 
 v8::Local<v8::Value> ToV8(const TestEnumOrDouble& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case TestEnumOrDouble::SpecificTypeNone:
+    case TestEnumOrDouble::SpecificType::kNone:
       return v8::Null(isolate);
-    case TestEnumOrDouble::SpecificTypeDouble:
-      return v8::Number::New(isolate, impl.getAsDouble());
-    case TestEnumOrDouble::SpecificTypeTestEnum:
-      return V8String(isolate, impl.getAsTestEnum());
+    case TestEnumOrDouble::SpecificType::kDouble:
+      return v8::Number::New(isolate, impl.GetAsDouble());
+    case TestEnumOrDouble::SpecificType::kTestEnum:
+      return V8String(isolate, impl.GetAsTestEnum());
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/test_enum_or_double.h b/third_party/WebKit/Source/bindings/tests/results/core/test_enum_or_double.h
index bee07762..bb57aa9 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/test_enum_or_double.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/test_enum_or_double.h
@@ -25,17 +25,17 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   TestEnumOrDouble();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isDouble() const { return type_ == SpecificTypeDouble; }
-  double getAsDouble() const;
-  void setDouble(double);
-  static TestEnumOrDouble fromDouble(double);
+  bool IsDouble() const { return type_ == SpecificType::kDouble; }
+  double GetAsDouble() const;
+  void SetDouble(double);
+  static TestEnumOrDouble FromDouble(double);
 
-  bool isTestEnum() const { return type_ == SpecificTypeTestEnum; }
-  const String& getAsTestEnum() const;
-  void setTestEnum(const String&);
-  static TestEnumOrDouble fromTestEnum(const String&);
+  bool IsTestEnum() const { return type_ == SpecificType::kTestEnum; }
+  const String& GetAsTestEnum() const;
+  void SetTestEnum(const String&);
+  static TestEnumOrDouble FromTestEnum(const String&);
 
   TestEnumOrDouble(const TestEnumOrDouble&);
   ~TestEnumOrDouble();
@@ -43,12 +43,12 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeDouble,
-    SpecificTypeTestEnum,
+  enum class SpecificType {
+    kNone,
+    kDouble,
+    kTestEnum,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   double double_;
   String test_enum_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/test_interface_2_or_uint8_array.cc b/third_party/WebKit/Source/bindings/tests/results/core/test_interface_2_or_uint8_array.cc
index fa22926..603bd85 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/test_interface_2_or_uint8_array.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/test_interface_2_or_uint8_array.cc
@@ -16,39 +16,39 @@
 
 namespace blink {
 
-TestInterface2OrUint8Array::TestInterface2OrUint8Array() : type_(SpecificTypeNone) {}
+TestInterface2OrUint8Array::TestInterface2OrUint8Array() : type_(SpecificType::kNone) {}
 
-TestInterface2* TestInterface2OrUint8Array::getAsTestInterface2() const {
-  DCHECK(isTestInterface2());
+TestInterface2* TestInterface2OrUint8Array::GetAsTestInterface2() const {
+  DCHECK(IsTestInterface2());
   return test_interface_2_;
 }
 
-void TestInterface2OrUint8Array::setTestInterface2(TestInterface2* value) {
-  DCHECK(isNull());
+void TestInterface2OrUint8Array::SetTestInterface2(TestInterface2* value) {
+  DCHECK(IsNull());
   test_interface_2_ = value;
-  type_ = SpecificTypeTestInterface2;
+  type_ = SpecificType::kTestInterface2;
 }
 
-TestInterface2OrUint8Array TestInterface2OrUint8Array::fromTestInterface2(TestInterface2* value) {
+TestInterface2OrUint8Array TestInterface2OrUint8Array::FromTestInterface2(TestInterface2* value) {
   TestInterface2OrUint8Array container;
-  container.setTestInterface2(value);
+  container.SetTestInterface2(value);
   return container;
 }
 
-NotShared<DOMUint8Array> TestInterface2OrUint8Array::getAsUint8Array() const {
-  DCHECK(isUint8Array());
+NotShared<DOMUint8Array> TestInterface2OrUint8Array::GetAsUint8Array() const {
+  DCHECK(IsUint8Array());
   return uint8_array_;
 }
 
-void TestInterface2OrUint8Array::setUint8Array(NotShared<DOMUint8Array> value) {
-  DCHECK(isNull());
+void TestInterface2OrUint8Array::SetUint8Array(NotShared<DOMUint8Array> value) {
+  DCHECK(IsNull());
   uint8_array_ = Member<DOMUint8Array>(value.View());
-  type_ = SpecificTypeUint8Array;
+  type_ = SpecificType::kUint8Array;
 }
 
-TestInterface2OrUint8Array TestInterface2OrUint8Array::fromUint8Array(NotShared<DOMUint8Array> value) {
+TestInterface2OrUint8Array TestInterface2OrUint8Array::FromUint8Array(NotShared<DOMUint8Array> value) {
   TestInterface2OrUint8Array container;
-  container.setUint8Array(value);
+  container.SetUint8Array(value);
   return container;
 }
 
@@ -70,7 +70,7 @@
 
   if (V8TestInterface2::hasInstance(v8Value, isolate)) {
     TestInterface2* cppValue = V8TestInterface2::ToImpl(v8::Local<v8::Object>::Cast(v8Value));
-    impl.setTestInterface2(cppValue);
+    impl.SetTestInterface2(cppValue);
     return;
   }
 
@@ -78,7 +78,7 @@
     NotShared<DOMUint8Array> cppValue = ToNotShared<NotShared<DOMUint8Array>>(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setUint8Array(cppValue);
+    impl.SetUint8Array(cppValue);
     return;
   }
 
@@ -87,12 +87,12 @@
 
 v8::Local<v8::Value> ToV8(const TestInterface2OrUint8Array& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case TestInterface2OrUint8Array::SpecificTypeNone:
+    case TestInterface2OrUint8Array::SpecificType::kNone:
       return v8::Null(isolate);
-    case TestInterface2OrUint8Array::SpecificTypeTestInterface2:
-      return ToV8(impl.getAsTestInterface2(), creationContext, isolate);
-    case TestInterface2OrUint8Array::SpecificTypeUint8Array:
-      return ToV8(impl.getAsUint8Array(), creationContext, isolate);
+    case TestInterface2OrUint8Array::SpecificType::kTestInterface2:
+      return ToV8(impl.GetAsTestInterface2(), creationContext, isolate);
+    case TestInterface2OrUint8Array::SpecificType::kUint8Array:
+      return ToV8(impl.GetAsUint8Array(), creationContext, isolate);
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/test_interface_2_or_uint8_array.h b/third_party/WebKit/Source/bindings/tests/results/core/test_interface_2_or_uint8_array.h
index 9167038..c135600 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/test_interface_2_or_uint8_array.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/test_interface_2_or_uint8_array.h
@@ -31,17 +31,17 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   TestInterface2OrUint8Array();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isTestInterface2() const { return type_ == SpecificTypeTestInterface2; }
-  TestInterface2* getAsTestInterface2() const;
-  void setTestInterface2(TestInterface2*);
-  static TestInterface2OrUint8Array fromTestInterface2(TestInterface2*);
+  bool IsTestInterface2() const { return type_ == SpecificType::kTestInterface2; }
+  TestInterface2* GetAsTestInterface2() const;
+  void SetTestInterface2(TestInterface2*);
+  static TestInterface2OrUint8Array FromTestInterface2(TestInterface2*);
 
-  bool isUint8Array() const { return type_ == SpecificTypeUint8Array; }
-  NotShared<DOMUint8Array> getAsUint8Array() const;
-  void setUint8Array(NotShared<DOMUint8Array>);
-  static TestInterface2OrUint8Array fromUint8Array(NotShared<DOMUint8Array>);
+  bool IsUint8Array() const { return type_ == SpecificType::kUint8Array; }
+  NotShared<DOMUint8Array> GetAsUint8Array() const;
+  void SetUint8Array(NotShared<DOMUint8Array>);
+  static TestInterface2OrUint8Array FromUint8Array(NotShared<DOMUint8Array>);
 
   TestInterface2OrUint8Array(const TestInterface2OrUint8Array&);
   ~TestInterface2OrUint8Array();
@@ -49,12 +49,12 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeTestInterface2,
-    SpecificTypeUint8Array,
+  enum class SpecificType {
+    kNone,
+    kTestInterface2,
+    kUint8Array,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   Member<TestInterface2> test_interface_2_;
   Member<DOMUint8Array> uint8_array_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/test_interface_garbage_collected_or_string.cc b/third_party/WebKit/Source/bindings/tests/results/core/test_interface_garbage_collected_or_string.cc
index 25fecbb..6e806298 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/test_interface_garbage_collected_or_string.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/test_interface_garbage_collected_or_string.cc
@@ -18,39 +18,39 @@
 
 namespace blink {
 
-TestInterfaceGarbageCollectedOrString::TestInterfaceGarbageCollectedOrString() : type_(SpecificTypeNone) {}
+TestInterfaceGarbageCollectedOrString::TestInterfaceGarbageCollectedOrString() : type_(SpecificType::kNone) {}
 
-const String& TestInterfaceGarbageCollectedOrString::getAsString() const {
-  DCHECK(isString());
+const String& TestInterfaceGarbageCollectedOrString::GetAsString() const {
+  DCHECK(IsString());
   return string_;
 }
 
-void TestInterfaceGarbageCollectedOrString::setString(const String& value) {
-  DCHECK(isNull());
+void TestInterfaceGarbageCollectedOrString::SetString(const String& value) {
+  DCHECK(IsNull());
   string_ = value;
-  type_ = SpecificTypeString;
+  type_ = SpecificType::kString;
 }
 
-TestInterfaceGarbageCollectedOrString TestInterfaceGarbageCollectedOrString::fromString(const String& value) {
+TestInterfaceGarbageCollectedOrString TestInterfaceGarbageCollectedOrString::FromString(const String& value) {
   TestInterfaceGarbageCollectedOrString container;
-  container.setString(value);
+  container.SetString(value);
   return container;
 }
 
-TestInterfaceGarbageCollected* TestInterfaceGarbageCollectedOrString::getAsTestInterfaceGarbageCollected() const {
-  DCHECK(isTestInterfaceGarbageCollected());
+TestInterfaceGarbageCollected* TestInterfaceGarbageCollectedOrString::GetAsTestInterfaceGarbageCollected() const {
+  DCHECK(IsTestInterfaceGarbageCollected());
   return test_interface_garbage_collected_;
 }
 
-void TestInterfaceGarbageCollectedOrString::setTestInterfaceGarbageCollected(TestInterfaceGarbageCollected* value) {
-  DCHECK(isNull());
+void TestInterfaceGarbageCollectedOrString::SetTestInterfaceGarbageCollected(TestInterfaceGarbageCollected* value) {
+  DCHECK(IsNull());
   test_interface_garbage_collected_ = value;
-  type_ = SpecificTypeTestInterfaceGarbageCollected;
+  type_ = SpecificType::kTestInterfaceGarbageCollected;
 }
 
-TestInterfaceGarbageCollectedOrString TestInterfaceGarbageCollectedOrString::fromTestInterfaceGarbageCollected(TestInterfaceGarbageCollected* value) {
+TestInterfaceGarbageCollectedOrString TestInterfaceGarbageCollectedOrString::FromTestInterfaceGarbageCollected(TestInterfaceGarbageCollected* value) {
   TestInterfaceGarbageCollectedOrString container;
-  container.setTestInterfaceGarbageCollected(value);
+  container.SetTestInterfaceGarbageCollected(value);
   return container;
 }
 
@@ -71,7 +71,7 @@
 
   if (V8TestInterfaceGarbageCollected::hasInstance(v8Value, isolate)) {
     TestInterfaceGarbageCollected* cppValue = V8TestInterfaceGarbageCollected::ToImpl(v8::Local<v8::Object>::Cast(v8Value));
-    impl.setTestInterfaceGarbageCollected(cppValue);
+    impl.SetTestInterfaceGarbageCollected(cppValue);
     return;
   }
 
@@ -79,19 +79,19 @@
     V8StringResource<> cppValue = v8Value;
     if (!cppValue.Prepare(exceptionState))
       return;
-    impl.setString(cppValue);
+    impl.SetString(cppValue);
     return;
   }
 }
 
 v8::Local<v8::Value> ToV8(const TestInterfaceGarbageCollectedOrString& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case TestInterfaceGarbageCollectedOrString::SpecificTypeNone:
+    case TestInterfaceGarbageCollectedOrString::SpecificType::kNone:
       return v8::Null(isolate);
-    case TestInterfaceGarbageCollectedOrString::SpecificTypeString:
-      return V8String(isolate, impl.getAsString());
-    case TestInterfaceGarbageCollectedOrString::SpecificTypeTestInterfaceGarbageCollected:
-      return ToV8(impl.getAsTestInterfaceGarbageCollected(), creationContext, isolate);
+    case TestInterfaceGarbageCollectedOrString::SpecificType::kString:
+      return V8String(isolate, impl.GetAsString());
+    case TestInterfaceGarbageCollectedOrString::SpecificType::kTestInterfaceGarbageCollected:
+      return ToV8(impl.GetAsTestInterfaceGarbageCollected(), creationContext, isolate);
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/test_interface_garbage_collected_or_string.h b/third_party/WebKit/Source/bindings/tests/results/core/test_interface_garbage_collected_or_string.h
index c7668cdf..6dab2c86 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/test_interface_garbage_collected_or_string.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/test_interface_garbage_collected_or_string.h
@@ -27,17 +27,17 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   TestInterfaceGarbageCollectedOrString();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isString() const { return type_ == SpecificTypeString; }
-  const String& getAsString() const;
-  void setString(const String&);
-  static TestInterfaceGarbageCollectedOrString fromString(const String&);
+  bool IsString() const { return type_ == SpecificType::kString; }
+  const String& GetAsString() const;
+  void SetString(const String&);
+  static TestInterfaceGarbageCollectedOrString FromString(const String&);
 
-  bool isTestInterfaceGarbageCollected() const { return type_ == SpecificTypeTestInterfaceGarbageCollected; }
-  TestInterfaceGarbageCollected* getAsTestInterfaceGarbageCollected() const;
-  void setTestInterfaceGarbageCollected(TestInterfaceGarbageCollected*);
-  static TestInterfaceGarbageCollectedOrString fromTestInterfaceGarbageCollected(TestInterfaceGarbageCollected*);
+  bool IsTestInterfaceGarbageCollected() const { return type_ == SpecificType::kTestInterfaceGarbageCollected; }
+  TestInterfaceGarbageCollected* GetAsTestInterfaceGarbageCollected() const;
+  void SetTestInterfaceGarbageCollected(TestInterfaceGarbageCollected*);
+  static TestInterfaceGarbageCollectedOrString FromTestInterfaceGarbageCollected(TestInterfaceGarbageCollected*);
 
   TestInterfaceGarbageCollectedOrString(const TestInterfaceGarbageCollectedOrString&);
   ~TestInterfaceGarbageCollectedOrString();
@@ -45,12 +45,12 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeString,
-    SpecificTypeTestInterfaceGarbageCollected,
+  enum class SpecificType {
+    kNone,
+    kString,
+    kTestInterfaceGarbageCollected,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   String string_;
   Member<TestInterfaceGarbageCollected> test_interface_garbage_collected_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/test_interface_or_long.cc b/third_party/WebKit/Source/bindings/tests/results/core/test_interface_or_long.cc
index 7c9944ae..90f4e75f 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/test_interface_or_long.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/test_interface_or_long.cc
@@ -23,39 +23,39 @@
 
 namespace blink {
 
-TestInterfaceOrLong::TestInterfaceOrLong() : type_(SpecificTypeNone) {}
+TestInterfaceOrLong::TestInterfaceOrLong() : type_(SpecificType::kNone) {}
 
-int32_t TestInterfaceOrLong::getAsLong() const {
-  DCHECK(isLong());
+int32_t TestInterfaceOrLong::GetAsLong() const {
+  DCHECK(IsLong());
   return long_;
 }
 
-void TestInterfaceOrLong::setLong(int32_t value) {
-  DCHECK(isNull());
+void TestInterfaceOrLong::SetLong(int32_t value) {
+  DCHECK(IsNull());
   long_ = value;
-  type_ = SpecificTypeLong;
+  type_ = SpecificType::kLong;
 }
 
-TestInterfaceOrLong TestInterfaceOrLong::fromLong(int32_t value) {
+TestInterfaceOrLong TestInterfaceOrLong::FromLong(int32_t value) {
   TestInterfaceOrLong container;
-  container.setLong(value);
+  container.SetLong(value);
   return container;
 }
 
-TestInterfaceImplementation* TestInterfaceOrLong::getAsTestInterface() const {
-  DCHECK(isTestInterface());
+TestInterfaceImplementation* TestInterfaceOrLong::GetAsTestInterface() const {
+  DCHECK(IsTestInterface());
   return test_interface_;
 }
 
-void TestInterfaceOrLong::setTestInterface(TestInterfaceImplementation* value) {
-  DCHECK(isNull());
+void TestInterfaceOrLong::SetTestInterface(TestInterfaceImplementation* value) {
+  DCHECK(IsNull());
   test_interface_ = value;
-  type_ = SpecificTypeTestInterface;
+  type_ = SpecificType::kTestInterface;
 }
 
-TestInterfaceOrLong TestInterfaceOrLong::fromTestInterface(TestInterfaceImplementation* value) {
+TestInterfaceOrLong TestInterfaceOrLong::FromTestInterface(TestInterfaceImplementation* value) {
   TestInterfaceOrLong container;
-  container.setTestInterface(value);
+  container.SetTestInterface(value);
   return container;
 }
 
@@ -76,7 +76,7 @@
 
   if (V8TestInterface::hasInstance(v8Value, isolate)) {
     TestInterfaceImplementation* cppValue = V8TestInterface::ToImpl(v8::Local<v8::Object>::Cast(v8Value));
-    impl.setTestInterface(cppValue);
+    impl.SetTestInterface(cppValue);
     return;
   }
 
@@ -84,7 +84,7 @@
     int32_t cppValue = NativeValueTraits<IDLLong>::NativeValue(isolate, v8Value, exceptionState, kNormalConversion);
     if (exceptionState.HadException())
       return;
-    impl.setLong(cppValue);
+    impl.SetLong(cppValue);
     return;
   }
 
@@ -92,19 +92,19 @@
     int32_t cppValue = NativeValueTraits<IDLLong>::NativeValue(isolate, v8Value, exceptionState, kNormalConversion);
     if (exceptionState.HadException())
       return;
-    impl.setLong(cppValue);
+    impl.SetLong(cppValue);
     return;
   }
 }
 
 v8::Local<v8::Value> ToV8(const TestInterfaceOrLong& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case TestInterfaceOrLong::SpecificTypeNone:
+    case TestInterfaceOrLong::SpecificType::kNone:
       return v8::Null(isolate);
-    case TestInterfaceOrLong::SpecificTypeLong:
-      return v8::Integer::New(isolate, impl.getAsLong());
-    case TestInterfaceOrLong::SpecificTypeTestInterface:
-      return ToV8(impl.getAsTestInterface(), creationContext, isolate);
+    case TestInterfaceOrLong::SpecificType::kLong:
+      return v8::Integer::New(isolate, impl.GetAsLong());
+    case TestInterfaceOrLong::SpecificType::kTestInterface:
+      return ToV8(impl.GetAsTestInterface(), creationContext, isolate);
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/test_interface_or_long.h b/third_party/WebKit/Source/bindings/tests/results/core/test_interface_or_long.h
index d1b9885d..3604b73b 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/test_interface_or_long.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/test_interface_or_long.h
@@ -27,17 +27,17 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   TestInterfaceOrLong();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isLong() const { return type_ == SpecificTypeLong; }
-  int32_t getAsLong() const;
-  void setLong(int32_t);
-  static TestInterfaceOrLong fromLong(int32_t);
+  bool IsLong() const { return type_ == SpecificType::kLong; }
+  int32_t GetAsLong() const;
+  void SetLong(int32_t);
+  static TestInterfaceOrLong FromLong(int32_t);
 
-  bool isTestInterface() const { return type_ == SpecificTypeTestInterface; }
-  TestInterfaceImplementation* getAsTestInterface() const;
-  void setTestInterface(TestInterfaceImplementation*);
-  static TestInterfaceOrLong fromTestInterface(TestInterfaceImplementation*);
+  bool IsTestInterface() const { return type_ == SpecificType::kTestInterface; }
+  TestInterfaceImplementation* GetAsTestInterface() const;
+  void SetTestInterface(TestInterfaceImplementation*);
+  static TestInterfaceOrLong FromTestInterface(TestInterfaceImplementation*);
 
   TestInterfaceOrLong(const TestInterfaceOrLong&);
   ~TestInterfaceOrLong();
@@ -45,12 +45,12 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeLong,
-    SpecificTypeTestInterface,
+  enum class SpecificType {
+    kNone,
+    kLong,
+    kTestInterface,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   int32_t long_;
   Member<TestInterfaceImplementation> test_interface_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/test_interface_or_test_interface_empty.cc b/third_party/WebKit/Source/bindings/tests/results/core/test_interface_or_test_interface_empty.cc
index 4ea37f9..fc379fc 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/test_interface_or_test_interface_empty.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/test_interface_or_test_interface_empty.cc
@@ -22,39 +22,39 @@
 
 namespace blink {
 
-TestInterfaceOrTestInterfaceEmpty::TestInterfaceOrTestInterfaceEmpty() : type_(SpecificTypeNone) {}
+TestInterfaceOrTestInterfaceEmpty::TestInterfaceOrTestInterfaceEmpty() : type_(SpecificType::kNone) {}
 
-TestInterfaceImplementation* TestInterfaceOrTestInterfaceEmpty::getAsTestInterface() const {
-  DCHECK(isTestInterface());
+TestInterfaceImplementation* TestInterfaceOrTestInterfaceEmpty::GetAsTestInterface() const {
+  DCHECK(IsTestInterface());
   return test_interface_;
 }
 
-void TestInterfaceOrTestInterfaceEmpty::setTestInterface(TestInterfaceImplementation* value) {
-  DCHECK(isNull());
+void TestInterfaceOrTestInterfaceEmpty::SetTestInterface(TestInterfaceImplementation* value) {
+  DCHECK(IsNull());
   test_interface_ = value;
-  type_ = SpecificTypeTestInterface;
+  type_ = SpecificType::kTestInterface;
 }
 
-TestInterfaceOrTestInterfaceEmpty TestInterfaceOrTestInterfaceEmpty::fromTestInterface(TestInterfaceImplementation* value) {
+TestInterfaceOrTestInterfaceEmpty TestInterfaceOrTestInterfaceEmpty::FromTestInterface(TestInterfaceImplementation* value) {
   TestInterfaceOrTestInterfaceEmpty container;
-  container.setTestInterface(value);
+  container.SetTestInterface(value);
   return container;
 }
 
-TestInterfaceEmpty* TestInterfaceOrTestInterfaceEmpty::getAsTestInterfaceEmpty() const {
-  DCHECK(isTestInterfaceEmpty());
+TestInterfaceEmpty* TestInterfaceOrTestInterfaceEmpty::GetAsTestInterfaceEmpty() const {
+  DCHECK(IsTestInterfaceEmpty());
   return test_interface_empty_;
 }
 
-void TestInterfaceOrTestInterfaceEmpty::setTestInterfaceEmpty(TestInterfaceEmpty* value) {
-  DCHECK(isNull());
+void TestInterfaceOrTestInterfaceEmpty::SetTestInterfaceEmpty(TestInterfaceEmpty* value) {
+  DCHECK(IsNull());
   test_interface_empty_ = value;
-  type_ = SpecificTypeTestInterfaceEmpty;
+  type_ = SpecificType::kTestInterfaceEmpty;
 }
 
-TestInterfaceOrTestInterfaceEmpty TestInterfaceOrTestInterfaceEmpty::fromTestInterfaceEmpty(TestInterfaceEmpty* value) {
+TestInterfaceOrTestInterfaceEmpty TestInterfaceOrTestInterfaceEmpty::FromTestInterfaceEmpty(TestInterfaceEmpty* value) {
   TestInterfaceOrTestInterfaceEmpty container;
-  container.setTestInterfaceEmpty(value);
+  container.SetTestInterfaceEmpty(value);
   return container;
 }
 
@@ -76,13 +76,13 @@
 
   if (V8TestInterface::hasInstance(v8Value, isolate)) {
     TestInterfaceImplementation* cppValue = V8TestInterface::ToImpl(v8::Local<v8::Object>::Cast(v8Value));
-    impl.setTestInterface(cppValue);
+    impl.SetTestInterface(cppValue);
     return;
   }
 
   if (V8TestInterfaceEmpty::hasInstance(v8Value, isolate)) {
     TestInterfaceEmpty* cppValue = V8TestInterfaceEmpty::ToImpl(v8::Local<v8::Object>::Cast(v8Value));
-    impl.setTestInterfaceEmpty(cppValue);
+    impl.SetTestInterfaceEmpty(cppValue);
     return;
   }
 
@@ -91,12 +91,12 @@
 
 v8::Local<v8::Value> ToV8(const TestInterfaceOrTestInterfaceEmpty& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case TestInterfaceOrTestInterfaceEmpty::SpecificTypeNone:
+    case TestInterfaceOrTestInterfaceEmpty::SpecificType::kNone:
       return v8::Null(isolate);
-    case TestInterfaceOrTestInterfaceEmpty::SpecificTypeTestInterface:
-      return ToV8(impl.getAsTestInterface(), creationContext, isolate);
-    case TestInterfaceOrTestInterfaceEmpty::SpecificTypeTestInterfaceEmpty:
-      return ToV8(impl.getAsTestInterfaceEmpty(), creationContext, isolate);
+    case TestInterfaceOrTestInterfaceEmpty::SpecificType::kTestInterface:
+      return ToV8(impl.GetAsTestInterface(), creationContext, isolate);
+    case TestInterfaceOrTestInterfaceEmpty::SpecificType::kTestInterfaceEmpty:
+      return ToV8(impl.GetAsTestInterfaceEmpty(), creationContext, isolate);
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/test_interface_or_test_interface_empty.h b/third_party/WebKit/Source/bindings/tests/results/core/test_interface_or_test_interface_empty.h
index e4a6bca..2c4168b 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/test_interface_or_test_interface_empty.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/test_interface_or_test_interface_empty.h
@@ -28,17 +28,17 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   TestInterfaceOrTestInterfaceEmpty();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isTestInterface() const { return type_ == SpecificTypeTestInterface; }
-  TestInterfaceImplementation* getAsTestInterface() const;
-  void setTestInterface(TestInterfaceImplementation*);
-  static TestInterfaceOrTestInterfaceEmpty fromTestInterface(TestInterfaceImplementation*);
+  bool IsTestInterface() const { return type_ == SpecificType::kTestInterface; }
+  TestInterfaceImplementation* GetAsTestInterface() const;
+  void SetTestInterface(TestInterfaceImplementation*);
+  static TestInterfaceOrTestInterfaceEmpty FromTestInterface(TestInterfaceImplementation*);
 
-  bool isTestInterfaceEmpty() const { return type_ == SpecificTypeTestInterfaceEmpty; }
-  TestInterfaceEmpty* getAsTestInterfaceEmpty() const;
-  void setTestInterfaceEmpty(TestInterfaceEmpty*);
-  static TestInterfaceOrTestInterfaceEmpty fromTestInterfaceEmpty(TestInterfaceEmpty*);
+  bool IsTestInterfaceEmpty() const { return type_ == SpecificType::kTestInterfaceEmpty; }
+  TestInterfaceEmpty* GetAsTestInterfaceEmpty() const;
+  void SetTestInterfaceEmpty(TestInterfaceEmpty*);
+  static TestInterfaceOrTestInterfaceEmpty FromTestInterfaceEmpty(TestInterfaceEmpty*);
 
   TestInterfaceOrTestInterfaceEmpty(const TestInterfaceOrTestInterfaceEmpty&);
   ~TestInterfaceOrTestInterfaceEmpty();
@@ -46,12 +46,12 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeTestInterface,
-    SpecificTypeTestInterfaceEmpty,
+  enum class SpecificType {
+    kNone,
+    kTestInterface,
+    kTestInterfaceEmpty,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   Member<TestInterfaceImplementation> test_interface_;
   Member<TestInterfaceEmpty> test_interface_empty_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/unrestricted_double_or_string.cc b/third_party/WebKit/Source/bindings/tests/results/core/unrestricted_double_or_string.cc
index bcf41c8..4f7067a 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/unrestricted_double_or_string.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/unrestricted_double_or_string.cc
@@ -17,39 +17,39 @@
 
 namespace blink {
 
-UnrestrictedDoubleOrString::UnrestrictedDoubleOrString() : type_(SpecificTypeNone) {}
+UnrestrictedDoubleOrString::UnrestrictedDoubleOrString() : type_(SpecificType::kNone) {}
 
-const String& UnrestrictedDoubleOrString::getAsString() const {
-  DCHECK(isString());
+const String& UnrestrictedDoubleOrString::GetAsString() const {
+  DCHECK(IsString());
   return string_;
 }
 
-void UnrestrictedDoubleOrString::setString(const String& value) {
-  DCHECK(isNull());
+void UnrestrictedDoubleOrString::SetString(const String& value) {
+  DCHECK(IsNull());
   string_ = value;
-  type_ = SpecificTypeString;
+  type_ = SpecificType::kString;
 }
 
-UnrestrictedDoubleOrString UnrestrictedDoubleOrString::fromString(const String& value) {
+UnrestrictedDoubleOrString UnrestrictedDoubleOrString::FromString(const String& value) {
   UnrestrictedDoubleOrString container;
-  container.setString(value);
+  container.SetString(value);
   return container;
 }
 
-double UnrestrictedDoubleOrString::getAsUnrestrictedDouble() const {
-  DCHECK(isUnrestrictedDouble());
+double UnrestrictedDoubleOrString::GetAsUnrestrictedDouble() const {
+  DCHECK(IsUnrestrictedDouble());
   return unrestricted_double_;
 }
 
-void UnrestrictedDoubleOrString::setUnrestrictedDouble(double value) {
-  DCHECK(isNull());
+void UnrestrictedDoubleOrString::SetUnrestrictedDouble(double value) {
+  DCHECK(IsNull());
   unrestricted_double_ = value;
-  type_ = SpecificTypeUnrestrictedDouble;
+  type_ = SpecificType::kUnrestrictedDouble;
 }
 
-UnrestrictedDoubleOrString UnrestrictedDoubleOrString::fromUnrestrictedDouble(double value) {
+UnrestrictedDoubleOrString UnrestrictedDoubleOrString::FromUnrestrictedDouble(double value) {
   UnrestrictedDoubleOrString container;
-  container.setUnrestrictedDouble(value);
+  container.SetUnrestrictedDouble(value);
   return container;
 }
 
@@ -71,7 +71,7 @@
     double cppValue = NativeValueTraits<IDLUnrestrictedDouble>::NativeValue(isolate, v8Value, exceptionState);
     if (exceptionState.HadException())
       return;
-    impl.setUnrestrictedDouble(cppValue);
+    impl.SetUnrestrictedDouble(cppValue);
     return;
   }
 
@@ -79,19 +79,19 @@
     V8StringResource<> cppValue = v8Value;
     if (!cppValue.Prepare(exceptionState))
       return;
-    impl.setString(cppValue);
+    impl.SetString(cppValue);
     return;
   }
 }
 
 v8::Local<v8::Value> ToV8(const UnrestrictedDoubleOrString& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case UnrestrictedDoubleOrString::SpecificTypeNone:
+    case UnrestrictedDoubleOrString::SpecificType::kNone:
       return v8::Null(isolate);
-    case UnrestrictedDoubleOrString::SpecificTypeString:
-      return V8String(isolate, impl.getAsString());
-    case UnrestrictedDoubleOrString::SpecificTypeUnrestrictedDouble:
-      return v8::Number::New(isolate, impl.getAsUnrestrictedDouble());
+    case UnrestrictedDoubleOrString::SpecificType::kString:
+      return V8String(isolate, impl.GetAsString());
+    case UnrestrictedDoubleOrString::SpecificType::kUnrestrictedDouble:
+      return v8::Number::New(isolate, impl.GetAsUnrestrictedDouble());
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/unrestricted_double_or_string.h b/third_party/WebKit/Source/bindings/tests/results/core/unrestricted_double_or_string.h
index 8cdf18b0..a4957f2 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/unrestricted_double_or_string.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/unrestricted_double_or_string.h
@@ -25,17 +25,17 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   UnrestrictedDoubleOrString();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isString() const { return type_ == SpecificTypeString; }
-  const String& getAsString() const;
-  void setString(const String&);
-  static UnrestrictedDoubleOrString fromString(const String&);
+  bool IsString() const { return type_ == SpecificType::kString; }
+  const String& GetAsString() const;
+  void SetString(const String&);
+  static UnrestrictedDoubleOrString FromString(const String&);
 
-  bool isUnrestrictedDouble() const { return type_ == SpecificTypeUnrestrictedDouble; }
-  double getAsUnrestrictedDouble() const;
-  void setUnrestrictedDouble(double);
-  static UnrestrictedDoubleOrString fromUnrestrictedDouble(double);
+  bool IsUnrestrictedDouble() const { return type_ == SpecificType::kUnrestrictedDouble; }
+  double GetAsUnrestrictedDouble() const;
+  void SetUnrestrictedDouble(double);
+  static UnrestrictedDoubleOrString FromUnrestrictedDouble(double);
 
   UnrestrictedDoubleOrString(const UnrestrictedDoubleOrString&);
   ~UnrestrictedDoubleOrString();
@@ -43,12 +43,12 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeString,
-    SpecificTypeUnrestrictedDouble,
+  enum class SpecificType {
+    kNone,
+    kString,
+    kUnrestrictedDouble,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   String string_;
   double unrestricted_double_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/unsigned_long_long_or_boolean_or_test_callback_interface.cc b/third_party/WebKit/Source/bindings/tests/results/core/unsigned_long_long_or_boolean_or_test_callback_interface.cc
index 5f697214..7be0860 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/unsigned_long_long_or_boolean_or_test_callback_interface.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/unsigned_long_long_or_boolean_or_test_callback_interface.cc
@@ -18,56 +18,56 @@
 
 namespace blink {
 
-UnsignedLongLongOrBooleanOrTestCallbackInterface::UnsignedLongLongOrBooleanOrTestCallbackInterface() : type_(SpecificTypeNone) {}
+UnsignedLongLongOrBooleanOrTestCallbackInterface::UnsignedLongLongOrBooleanOrTestCallbackInterface() : type_(SpecificType::kNone) {}
 
-bool UnsignedLongLongOrBooleanOrTestCallbackInterface::getAsBoolean() const {
-  DCHECK(isBoolean());
+bool UnsignedLongLongOrBooleanOrTestCallbackInterface::GetAsBoolean() const {
+  DCHECK(IsBoolean());
   return boolean_;
 }
 
-void UnsignedLongLongOrBooleanOrTestCallbackInterface::setBoolean(bool value) {
-  DCHECK(isNull());
+void UnsignedLongLongOrBooleanOrTestCallbackInterface::SetBoolean(bool value) {
+  DCHECK(IsNull());
   boolean_ = value;
-  type_ = SpecificTypeBoolean;
+  type_ = SpecificType::kBoolean;
 }
 
-UnsignedLongLongOrBooleanOrTestCallbackInterface UnsignedLongLongOrBooleanOrTestCallbackInterface::fromBoolean(bool value) {
+UnsignedLongLongOrBooleanOrTestCallbackInterface UnsignedLongLongOrBooleanOrTestCallbackInterface::FromBoolean(bool value) {
   UnsignedLongLongOrBooleanOrTestCallbackInterface container;
-  container.setBoolean(value);
+  container.SetBoolean(value);
   return container;
 }
 
-TestCallbackInterface* UnsignedLongLongOrBooleanOrTestCallbackInterface::getAsTestCallbackInterface() const {
-  DCHECK(isTestCallbackInterface());
+TestCallbackInterface* UnsignedLongLongOrBooleanOrTestCallbackInterface::GetAsTestCallbackInterface() const {
+  DCHECK(IsTestCallbackInterface());
   return test_callback_interface_;
 }
 
-void UnsignedLongLongOrBooleanOrTestCallbackInterface::setTestCallbackInterface(TestCallbackInterface* value) {
-  DCHECK(isNull());
+void UnsignedLongLongOrBooleanOrTestCallbackInterface::SetTestCallbackInterface(TestCallbackInterface* value) {
+  DCHECK(IsNull());
   test_callback_interface_ = value;
-  type_ = SpecificTypeTestCallbackInterface;
+  type_ = SpecificType::kTestCallbackInterface;
 }
 
-UnsignedLongLongOrBooleanOrTestCallbackInterface UnsignedLongLongOrBooleanOrTestCallbackInterface::fromTestCallbackInterface(TestCallbackInterface* value) {
+UnsignedLongLongOrBooleanOrTestCallbackInterface UnsignedLongLongOrBooleanOrTestCallbackInterface::FromTestCallbackInterface(TestCallbackInterface* value) {
   UnsignedLongLongOrBooleanOrTestCallbackInterface container;
-  container.setTestCallbackInterface(value);
+  container.SetTestCallbackInterface(value);
   return container;
 }
 
-uint64_t UnsignedLongLongOrBooleanOrTestCallbackInterface::getAsUnsignedLongLong() const {
-  DCHECK(isUnsignedLongLong());
+uint64_t UnsignedLongLongOrBooleanOrTestCallbackInterface::GetAsUnsignedLongLong() const {
+  DCHECK(IsUnsignedLongLong());
   return unsigned_long_long_;
 }
 
-void UnsignedLongLongOrBooleanOrTestCallbackInterface::setUnsignedLongLong(uint64_t value) {
-  DCHECK(isNull());
+void UnsignedLongLongOrBooleanOrTestCallbackInterface::SetUnsignedLongLong(uint64_t value) {
+  DCHECK(IsNull());
   unsigned_long_long_ = value;
-  type_ = SpecificTypeUnsignedLongLong;
+  type_ = SpecificType::kUnsignedLongLong;
 }
 
-UnsignedLongLongOrBooleanOrTestCallbackInterface UnsignedLongLongOrBooleanOrTestCallbackInterface::fromUnsignedLongLong(uint64_t value) {
+UnsignedLongLongOrBooleanOrTestCallbackInterface UnsignedLongLongOrBooleanOrTestCallbackInterface::FromUnsignedLongLong(uint64_t value) {
   UnsignedLongLongOrBooleanOrTestCallbackInterface container;
-  container.setUnsignedLongLong(value);
+  container.SetUnsignedLongLong(value);
   return container;
 }
 
@@ -88,12 +88,12 @@
 
   if (V8TestCallbackInterface::hasInstance(v8Value, isolate)) {
     TestCallbackInterface* cppValue = V8TestCallbackInterface::ToImpl(v8::Local<v8::Object>::Cast(v8Value));
-    impl.setTestCallbackInterface(cppValue);
+    impl.SetTestCallbackInterface(cppValue);
     return;
   }
 
   if (v8Value->IsBoolean()) {
-    impl.setBoolean(v8Value.As<v8::Boolean>()->Value());
+    impl.SetBoolean(v8Value.As<v8::Boolean>()->Value());
     return;
   }
 
@@ -101,7 +101,7 @@
     uint64_t cppValue = NativeValueTraits<IDLUnsignedLongLong>::NativeValue(isolate, v8Value, exceptionState, kNormalConversion);
     if (exceptionState.HadException())
       return;
-    impl.setUnsignedLongLong(cppValue);
+    impl.SetUnsignedLongLong(cppValue);
     return;
   }
 
@@ -109,21 +109,21 @@
     uint64_t cppValue = NativeValueTraits<IDLUnsignedLongLong>::NativeValue(isolate, v8Value, exceptionState, kNormalConversion);
     if (exceptionState.HadException())
       return;
-    impl.setUnsignedLongLong(cppValue);
+    impl.SetUnsignedLongLong(cppValue);
     return;
   }
 }
 
 v8::Local<v8::Value> ToV8(const UnsignedLongLongOrBooleanOrTestCallbackInterface& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case UnsignedLongLongOrBooleanOrTestCallbackInterface::SpecificTypeNone:
+    case UnsignedLongLongOrBooleanOrTestCallbackInterface::SpecificType::kNone:
       return v8::Null(isolate);
-    case UnsignedLongLongOrBooleanOrTestCallbackInterface::SpecificTypeBoolean:
-      return v8::Boolean::New(isolate, impl.getAsBoolean());
-    case UnsignedLongLongOrBooleanOrTestCallbackInterface::SpecificTypeTestCallbackInterface:
-      return ToV8(impl.getAsTestCallbackInterface(), creationContext, isolate);
-    case UnsignedLongLongOrBooleanOrTestCallbackInterface::SpecificTypeUnsignedLongLong:
-      return v8::Number::New(isolate, static_cast<double>(impl.getAsUnsignedLongLong()));
+    case UnsignedLongLongOrBooleanOrTestCallbackInterface::SpecificType::kBoolean:
+      return v8::Boolean::New(isolate, impl.GetAsBoolean());
+    case UnsignedLongLongOrBooleanOrTestCallbackInterface::SpecificType::kTestCallbackInterface:
+      return ToV8(impl.GetAsTestCallbackInterface(), creationContext, isolate);
+    case UnsignedLongLongOrBooleanOrTestCallbackInterface::SpecificType::kUnsignedLongLong:
+      return v8::Number::New(isolate, static_cast<double>(impl.GetAsUnsignedLongLong()));
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/unsigned_long_long_or_boolean_or_test_callback_interface.h b/third_party/WebKit/Source/bindings/tests/results/core/unsigned_long_long_or_boolean_or_test_callback_interface.h
index 839743c..eaa8868 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/unsigned_long_long_or_boolean_or_test_callback_interface.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/unsigned_long_long_or_boolean_or_test_callback_interface.h
@@ -27,22 +27,22 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   UnsignedLongLongOrBooleanOrTestCallbackInterface();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isBoolean() const { return type_ == SpecificTypeBoolean; }
-  bool getAsBoolean() const;
-  void setBoolean(bool);
-  static UnsignedLongLongOrBooleanOrTestCallbackInterface fromBoolean(bool);
+  bool IsBoolean() const { return type_ == SpecificType::kBoolean; }
+  bool GetAsBoolean() const;
+  void SetBoolean(bool);
+  static UnsignedLongLongOrBooleanOrTestCallbackInterface FromBoolean(bool);
 
-  bool isTestCallbackInterface() const { return type_ == SpecificTypeTestCallbackInterface; }
-  TestCallbackInterface* getAsTestCallbackInterface() const;
-  void setTestCallbackInterface(TestCallbackInterface*);
-  static UnsignedLongLongOrBooleanOrTestCallbackInterface fromTestCallbackInterface(TestCallbackInterface*);
+  bool IsTestCallbackInterface() const { return type_ == SpecificType::kTestCallbackInterface; }
+  TestCallbackInterface* GetAsTestCallbackInterface() const;
+  void SetTestCallbackInterface(TestCallbackInterface*);
+  static UnsignedLongLongOrBooleanOrTestCallbackInterface FromTestCallbackInterface(TestCallbackInterface*);
 
-  bool isUnsignedLongLong() const { return type_ == SpecificTypeUnsignedLongLong; }
-  uint64_t getAsUnsignedLongLong() const;
-  void setUnsignedLongLong(uint64_t);
-  static UnsignedLongLongOrBooleanOrTestCallbackInterface fromUnsignedLongLong(uint64_t);
+  bool IsUnsignedLongLong() const { return type_ == SpecificType::kUnsignedLongLong; }
+  uint64_t GetAsUnsignedLongLong() const;
+  void SetUnsignedLongLong(uint64_t);
+  static UnsignedLongLongOrBooleanOrTestCallbackInterface FromUnsignedLongLong(uint64_t);
 
   UnsignedLongLongOrBooleanOrTestCallbackInterface(const UnsignedLongLongOrBooleanOrTestCallbackInterface&);
   ~UnsignedLongLongOrBooleanOrTestCallbackInterface();
@@ -50,13 +50,13 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeBoolean,
-    SpecificTypeTestCallbackInterface,
-    SpecificTypeUnsignedLongLong,
+  enum class SpecificType {
+    kNone,
+    kBoolean,
+    kTestCallbackInterface,
+    kUnsignedLongLong,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   bool boolean_;
   Member<TestCallbackInterface> test_callback_interface_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_any_callback_function_optional_any_arg.cc b/third_party/WebKit/Source/bindings/tests/results/core/v8_any_callback_function_optional_any_arg.cc
index 3030121..066d69fe6 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/v8_any_callback_function_optional_any_arg.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_any_callback_function_optional_any_arg.cc
@@ -51,12 +51,12 @@
   // crbug.com/653769
   DummyExceptionStateForTesting exceptionState;
 
-  ExecutionContext* context = ExecutionContext::From(script_state_.Get());
+  ExecutionContext* context = ExecutionContext::From(script_state_.get());
   DCHECK(context);
   if (context->IsContextSuspended() || context->IsContextDestroyed())
     return false;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Isolate* isolate = script_state_->GetIsolate();
 
   v8::Local<v8::Value> thisValue = ToV8(
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_long_callback_function.cc b/third_party/WebKit/Source/bindings/tests/results/core/v8_long_callback_function.cc
index 7c333d7..8747ca7 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/v8_long_callback_function.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_long_callback_function.cc
@@ -51,12 +51,12 @@
   // crbug.com/653769
   DummyExceptionStateForTesting exceptionState;
 
-  ExecutionContext* context = ExecutionContext::From(script_state_.Get());
+  ExecutionContext* context = ExecutionContext::From(script_state_.get());
   DCHECK(context);
   if (context->IsContextSuspended() || context->IsContextDestroyed())
     return false;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Isolate* isolate = script_state_->GetIsolate();
 
   v8::Local<v8::Value> thisValue = ToV8(
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_string_sequence_callback_function_long_sequence_arg.cc b/third_party/WebKit/Source/bindings/tests/results/core/v8_string_sequence_callback_function_long_sequence_arg.cc
index 023b1711..adb2248 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/v8_string_sequence_callback_function_long_sequence_arg.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_string_sequence_callback_function_long_sequence_arg.cc
@@ -51,12 +51,12 @@
   // crbug.com/653769
   DummyExceptionStateForTesting exceptionState;
 
-  ExecutionContext* context = ExecutionContext::From(script_state_.Get());
+  ExecutionContext* context = ExecutionContext::From(script_state_.get());
   DCHECK(context);
   if (context->IsContextSuspended() || context->IsContextDestroyed())
     return false;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Isolate* isolate = script_state_->GetIsolate();
 
   v8::Local<v8::Value> thisValue = ToV8(
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function.cc b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function.cc
index cfce88b7..fa927a7 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function.cc
@@ -50,12 +50,12 @@
   // crbug.com/653769
   DummyExceptionStateForTesting exceptionState;
 
-  ExecutionContext* context = ExecutionContext::From(script_state_.Get());
+  ExecutionContext* context = ExecutionContext::From(script_state_.get());
   DCHECK(context);
   if (context->IsContextSuspended() || context->IsContextDestroyed())
     return false;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Isolate* isolate = script_state_->GetIsolate();
 
   v8::Local<v8::Value> thisValue = ToV8(
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_dictionary_arg.cc b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_dictionary_arg.cc
index ba788d30..afee841e4 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_dictionary_arg.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_dictionary_arg.cc
@@ -51,12 +51,12 @@
   // crbug.com/653769
   DummyExceptionStateForTesting exceptionState;
 
-  ExecutionContext* context = ExecutionContext::From(script_state_.Get());
+  ExecutionContext* context = ExecutionContext::From(script_state_.get());
   DCHECK(context);
   if (context->IsContextSuspended() || context->IsContextDestroyed())
     return false;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Isolate* isolate = script_state_->GetIsolate();
 
   v8::Local<v8::Value> thisValue = ToV8(
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_enum_arg.cc b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_enum_arg.cc
index 23df150..bf91d47 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_enum_arg.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_enum_arg.cc
@@ -62,12 +62,12 @@
     return false;
   }
 
-  ExecutionContext* context = ExecutionContext::From(script_state_.Get());
+  ExecutionContext* context = ExecutionContext::From(script_state_.get());
   DCHECK(context);
   if (context->IsContextSuspended() || context->IsContextDestroyed())
     return false;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Isolate* isolate = script_state_->GetIsolate();
 
   v8::Local<v8::Value> thisValue = ToV8(
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_interface_arg.cc b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_interface_arg.cc
index 5acec7e..f636ad9 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_interface_arg.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_interface_arg.cc
@@ -51,12 +51,12 @@
   // crbug.com/653769
   DummyExceptionStateForTesting exceptionState;
 
-  ExecutionContext* context = ExecutionContext::From(script_state_.Get());
+  ExecutionContext* context = ExecutionContext::From(script_state_.get());
   DCHECK(context);
   if (context->IsContextSuspended() || context->IsContextDestroyed())
     return false;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Isolate* isolate = script_state_->GetIsolate();
 
   v8::Local<v8::Value> thisValue = ToV8(
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_test_interface_sequence_arg.cc b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_test_interface_sequence_arg.cc
index 76dd61f..8c2f46c9 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_test_interface_sequence_arg.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_test_interface_sequence_arg.cc
@@ -52,12 +52,12 @@
   // crbug.com/653769
   DummyExceptionStateForTesting exceptionState;
 
-  ExecutionContext* context = ExecutionContext::From(script_state_.Get());
+  ExecutionContext* context = ExecutionContext::From(script_state_.get());
   DCHECK(context);
   if (context->IsContextSuspended() || context->IsContextDestroyed())
     return false;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Isolate* isolate = script_state_->GetIsolate();
 
   v8::Local<v8::Value> thisValue = ToV8(
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_typedef.cc b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_typedef.cc
index 1fa7cd5..0ab0d1a9 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_typedef.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_typedef.cc
@@ -51,12 +51,12 @@
   // crbug.com/653769
   DummyExceptionStateForTesting exceptionState;
 
-  ExecutionContext* context = ExecutionContext::From(script_state_.Get());
+  ExecutionContext* context = ExecutionContext::From(script_state_.get());
   DCHECK(context);
   if (context->IsContextSuspended() || context->IsContextDestroyed())
     return false;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Isolate* isolate = script_state_->GetIsolate();
 
   v8::Local<v8::Value> thisValue = ToV8(
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/xml_http_request_or_string.cc b/third_party/WebKit/Source/bindings/tests/results/core/xml_http_request_or_string.cc
index 6101b62..81ee50c 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/xml_http_request_or_string.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/core/xml_http_request_or_string.cc
@@ -18,39 +18,39 @@
 
 namespace blink {
 
-XMLHttpRequestOrString::XMLHttpRequestOrString() : type_(SpecificTypeNone) {}
+XMLHttpRequestOrString::XMLHttpRequestOrString() : type_(SpecificType::kNone) {}
 
-const String& XMLHttpRequestOrString::getAsString() const {
-  DCHECK(isString());
+const String& XMLHttpRequestOrString::GetAsString() const {
+  DCHECK(IsString());
   return string_;
 }
 
-void XMLHttpRequestOrString::setString(const String& value) {
-  DCHECK(isNull());
+void XMLHttpRequestOrString::SetString(const String& value) {
+  DCHECK(IsNull());
   string_ = value;
-  type_ = SpecificTypeString;
+  type_ = SpecificType::kString;
 }
 
-XMLHttpRequestOrString XMLHttpRequestOrString::fromString(const String& value) {
+XMLHttpRequestOrString XMLHttpRequestOrString::FromString(const String& value) {
   XMLHttpRequestOrString container;
-  container.setString(value);
+  container.SetString(value);
   return container;
 }
 
-XMLHttpRequest* XMLHttpRequestOrString::getAsXMLHttpRequest() const {
-  DCHECK(isXMLHttpRequest());
+XMLHttpRequest* XMLHttpRequestOrString::GetAsXMLHttpRequest() const {
+  DCHECK(IsXMLHttpRequest());
   return xml_http_request_;
 }
 
-void XMLHttpRequestOrString::setXMLHttpRequest(XMLHttpRequest* value) {
-  DCHECK(isNull());
+void XMLHttpRequestOrString::SetXMLHttpRequest(XMLHttpRequest* value) {
+  DCHECK(IsNull());
   xml_http_request_ = value;
-  type_ = SpecificTypeXMLHttpRequest;
+  type_ = SpecificType::kXMLHttpRequest;
 }
 
-XMLHttpRequestOrString XMLHttpRequestOrString::fromXMLHttpRequest(XMLHttpRequest* value) {
+XMLHttpRequestOrString XMLHttpRequestOrString::FromXMLHttpRequest(XMLHttpRequest* value) {
   XMLHttpRequestOrString container;
-  container.setXMLHttpRequest(value);
+  container.SetXMLHttpRequest(value);
   return container;
 }
 
@@ -71,7 +71,7 @@
 
   if (V8XMLHttpRequest::hasInstance(v8Value, isolate)) {
     XMLHttpRequest* cppValue = V8XMLHttpRequest::ToImpl(v8::Local<v8::Object>::Cast(v8Value));
-    impl.setXMLHttpRequest(cppValue);
+    impl.SetXMLHttpRequest(cppValue);
     return;
   }
 
@@ -79,19 +79,19 @@
     V8StringResource<> cppValue = v8Value;
     if (!cppValue.Prepare(exceptionState))
       return;
-    impl.setString(cppValue);
+    impl.SetString(cppValue);
     return;
   }
 }
 
 v8::Local<v8::Value> ToV8(const XMLHttpRequestOrString& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case XMLHttpRequestOrString::SpecificTypeNone:
+    case XMLHttpRequestOrString::SpecificType::kNone:
       return v8::Null(isolate);
-    case XMLHttpRequestOrString::SpecificTypeString:
-      return V8String(isolate, impl.getAsString());
-    case XMLHttpRequestOrString::SpecificTypeXMLHttpRequest:
-      return ToV8(impl.getAsXMLHttpRequest(), creationContext, isolate);
+    case XMLHttpRequestOrString::SpecificType::kString:
+      return V8String(isolate, impl.GetAsString());
+    case XMLHttpRequestOrString::SpecificType::kXMLHttpRequest:
+      return ToV8(impl.GetAsXMLHttpRequest(), creationContext, isolate);
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/xml_http_request_or_string.h b/third_party/WebKit/Source/bindings/tests/results/core/xml_http_request_or_string.h
index 6e9ec7a1..713a9ba 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/xml_http_request_or_string.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/xml_http_request_or_string.h
@@ -27,17 +27,17 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   XMLHttpRequestOrString();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isString() const { return type_ == SpecificTypeString; }
-  const String& getAsString() const;
-  void setString(const String&);
-  static XMLHttpRequestOrString fromString(const String&);
+  bool IsString() const { return type_ == SpecificType::kString; }
+  const String& GetAsString() const;
+  void SetString(const String&);
+  static XMLHttpRequestOrString FromString(const String&);
 
-  bool isXMLHttpRequest() const { return type_ == SpecificTypeXMLHttpRequest; }
-  XMLHttpRequest* getAsXMLHttpRequest() const;
-  void setXMLHttpRequest(XMLHttpRequest*);
-  static XMLHttpRequestOrString fromXMLHttpRequest(XMLHttpRequest*);
+  bool IsXMLHttpRequest() const { return type_ == SpecificType::kXMLHttpRequest; }
+  XMLHttpRequest* GetAsXMLHttpRequest() const;
+  void SetXMLHttpRequest(XMLHttpRequest*);
+  static XMLHttpRequestOrString FromXMLHttpRequest(XMLHttpRequest*);
 
   XMLHttpRequestOrString(const XMLHttpRequestOrString&);
   ~XMLHttpRequestOrString();
@@ -45,12 +45,12 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeString,
-    SpecificTypeXMLHttpRequest,
+  enum class SpecificType {
+    kNone,
+    kString,
+    kXMLHttpRequest,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   String string_;
   Member<XMLHttpRequest> xml_http_request_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/boolean_or_string.cc b/third_party/WebKit/Source/bindings/tests/results/modules/boolean_or_string.cc
index 35ec8c82..26ecfa3a 100644
--- a/third_party/WebKit/Source/bindings/tests/results/modules/boolean_or_string.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/boolean_or_string.cc
@@ -17,39 +17,39 @@
 
 namespace blink {
 
-BooleanOrString::BooleanOrString() : type_(SpecificTypeNone) {}
+BooleanOrString::BooleanOrString() : type_(SpecificType::kNone) {}
 
-bool BooleanOrString::getAsBoolean() const {
-  DCHECK(isBoolean());
+bool BooleanOrString::GetAsBoolean() const {
+  DCHECK(IsBoolean());
   return boolean_;
 }
 
-void BooleanOrString::setBoolean(bool value) {
-  DCHECK(isNull());
+void BooleanOrString::SetBoolean(bool value) {
+  DCHECK(IsNull());
   boolean_ = value;
-  type_ = SpecificTypeBoolean;
+  type_ = SpecificType::kBoolean;
 }
 
-BooleanOrString BooleanOrString::fromBoolean(bool value) {
+BooleanOrString BooleanOrString::FromBoolean(bool value) {
   BooleanOrString container;
-  container.setBoolean(value);
+  container.SetBoolean(value);
   return container;
 }
 
-const String& BooleanOrString::getAsString() const {
-  DCHECK(isString());
+const String& BooleanOrString::GetAsString() const {
+  DCHECK(IsString());
   return string_;
 }
 
-void BooleanOrString::setString(const String& value) {
-  DCHECK(isNull());
+void BooleanOrString::SetString(const String& value) {
+  DCHECK(IsNull());
   string_ = value;
-  type_ = SpecificTypeString;
+  type_ = SpecificType::kString;
 }
 
-BooleanOrString BooleanOrString::fromString(const String& value) {
+BooleanOrString BooleanOrString::FromString(const String& value) {
   BooleanOrString container;
-  container.setString(value);
+  container.SetString(value);
   return container;
 }
 
@@ -68,7 +68,7 @@
     return;
 
   if (v8Value->IsBoolean()) {
-    impl.setBoolean(v8Value.As<v8::Boolean>()->Value());
+    impl.SetBoolean(v8Value.As<v8::Boolean>()->Value());
     return;
   }
 
@@ -76,19 +76,19 @@
     V8StringResource<> cppValue = v8Value;
     if (!cppValue.Prepare(exceptionState))
       return;
-    impl.setString(cppValue);
+    impl.SetString(cppValue);
     return;
   }
 }
 
 v8::Local<v8::Value> ToV8(const BooleanOrString& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
   switch (impl.type_) {
-    case BooleanOrString::SpecificTypeNone:
+    case BooleanOrString::SpecificType::kNone:
       return v8::Null(isolate);
-    case BooleanOrString::SpecificTypeBoolean:
-      return v8::Boolean::New(isolate, impl.getAsBoolean());
-    case BooleanOrString::SpecificTypeString:
-      return V8String(isolate, impl.getAsString());
+    case BooleanOrString::SpecificType::kBoolean:
+      return v8::Boolean::New(isolate, impl.GetAsBoolean());
+    case BooleanOrString::SpecificType::kString:
+      return V8String(isolate, impl.GetAsString());
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/boolean_or_string.h b/third_party/WebKit/Source/bindings/tests/results/modules/boolean_or_string.h
index 7891e7b..629c508 100644
--- a/third_party/WebKit/Source/bindings/tests/results/modules/boolean_or_string.h
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/boolean_or_string.h
@@ -25,17 +25,17 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  public:
   BooleanOrString();
-  bool isNull() const { return type_ == SpecificTypeNone; }
+  bool IsNull() const { return type_ == SpecificType::kNone; }
 
-  bool isBoolean() const { return type_ == SpecificTypeBoolean; }
-  bool getAsBoolean() const;
-  void setBoolean(bool);
-  static BooleanOrString fromBoolean(bool);
+  bool IsBoolean() const { return type_ == SpecificType::kBoolean; }
+  bool GetAsBoolean() const;
+  void SetBoolean(bool);
+  static BooleanOrString FromBoolean(bool);
 
-  bool isString() const { return type_ == SpecificTypeString; }
-  const String& getAsString() const;
-  void setString(const String&);
-  static BooleanOrString fromString(const String&);
+  bool IsString() const { return type_ == SpecificType::kString; }
+  const String& GetAsString() const;
+  void SetString(const String&);
+  static BooleanOrString FromString(const String&);
 
   BooleanOrString(const BooleanOrString&);
   ~BooleanOrString();
@@ -43,12 +43,12 @@
   DECLARE_TRACE();
 
  private:
-  enum SpecificTypes {
-    SpecificTypeNone,
-    SpecificTypeBoolean,
-    SpecificTypeString,
+  enum class SpecificType {
+    kNone,
+    kBoolean,
+    kString,
   };
-  SpecificTypes type_;
+  SpecificType type_;
 
   bool boolean_;
   String string_;
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/v8_void_callback_function_modules.cc b/third_party/WebKit/Source/bindings/tests/results/modules/v8_void_callback_function_modules.cc
index c4889ba..9c7661f 100644
--- a/third_party/WebKit/Source/bindings/tests/results/modules/v8_void_callback_function_modules.cc
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/v8_void_callback_function_modules.cc
@@ -50,12 +50,12 @@
   // crbug.com/653769
   DummyExceptionStateForTesting exceptionState;
 
-  ExecutionContext* context = ExecutionContext::From(script_state_.Get());
+  ExecutionContext* context = ExecutionContext::From(script_state_.get());
   DCHECK(context);
   if (context->IsContextSuspended() || context->IsContextDestroyed())
     return false;
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   v8::Isolate* isolate = script_state_->GetIsolate();
 
   v8::Local<v8::Value> thisValue = ToV8(
diff --git a/third_party/WebKit/Source/build/scripts/templates/ElementLookupTrie.cpp.tmpl b/third_party/WebKit/Source/build/scripts/templates/ElementLookupTrie.cpp.tmpl
index 78e3f24..4c12f74 100644
--- a/third_party/WebKit/Source/build/scripts/templates/ElementLookupTrie.cpp.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/ElementLookupTrie.cpp.tmpl
@@ -13,12 +13,12 @@
 
 using namespace {{namespace}}Names;
 
-StringImpl* lookup{{namespace}}Tag(const UChar* data, unsigned length) {
+const AtomicString& lookup{{namespace}}Tag(const UChar* data, unsigned length) {
   DCHECK(data);
   DCHECK(length);
-  {% macro trie_return_statement(tag) %}{{tag}}Tag.LocalName().Impl(){% endmacro %}
+  {% macro trie_return_statement(tag) %}{{tag}}Tag.LocalName(){% endmacro %}
   {{ trie_length_switch(length_tries, trie_return_statement, false) | indent(4) }}
-  return nullptr;
+  return g_null_atom;
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/build/scripts/templates/ElementLookupTrie.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/ElementLookupTrie.h.tmpl
index a54fe96..ce1aac8 100644
--- a/third_party/WebKit/Source/build/scripts/templates/ElementLookupTrie.h.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/ElementLookupTrie.h.tmpl
@@ -7,11 +7,11 @@
 #define {{namespace}}ElementLookupTrie_h
 
 #include "core/CoreExport.h"
-#include "platform/wtf/text/StringImpl.h"
+#include "platform/wtf/text/AtomicString.h"
 
 namespace blink {
 
-CORE_EXPORT StringImpl* lookup{{namespace}}Tag(const UChar* data, unsigned length);
+CORE_EXPORT const AtomicString& lookup{{namespace}}Tag(const UChar* data, unsigned length);
 
 } // namespace blink
 
diff --git a/third_party/WebKit/Source/build/scripts/templates/ElementTypeHelpers.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/ElementTypeHelpers.h.tmpl
index a7fe4a5..71ab171e 100644
--- a/third_party/WebKit/Source/build/scripts/templates/ElementTypeHelpers.h.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/ElementTypeHelpers.h.tmpl
@@ -15,32 +15,32 @@
 {% for tag in tags|sort if not tag.multipleTagNames and not tag.noTypeHelpers %}
 class {{tag.interface}};
 // Catch unnecessary runtime check of type known at compile time.
-void is{{tag.interface}}(const {{tag.interface}}&);
-void is{{tag.interface}}(const {{tag.interface}}*);
+void Is{{tag.interface}}(const {{tag.interface}}&);
+void Is{{tag.interface}}(const {{tag.interface}}*);
 
-inline bool is{{tag.interface}}(const {{namespace}}Element& element) {
+inline bool Is{{tag.interface}}(const {{namespace}}Element& element) {
   {% if tag.runtimeEnabled %}
   if (!RuntimeEnabledFeatures::{{tag.runtimeEnabled}}Enabled())
     return false;
   {% endif %}
   return element.HasTagName({{namespace}}Names::{{tag|symbol}}Tag);
 }
-inline bool is{{tag.interface}}(const {{namespace}}Element* element) {
-  return element && is{{tag.interface}}(*element);
+inline bool Is{{tag.interface}}(const {{namespace}}Element* element) {
+  return element && Is{{tag.interface}}(*element);
 }
-inline bool is{{tag.interface}}(const Node& node) {
-  return node.Is{{namespace}}Element() && is{{tag.interface}}(To{{namespace}}Element(node));
+inline bool Is{{tag.interface}}(const Node& node) {
+  return node.Is{{namespace}}Element() && Is{{tag.interface}}(To{{namespace}}Element(node));
 }
-inline bool is{{tag.interface}}(const Node* node) {
-  return node && is{{tag.interface}}(*node);
+inline bool Is{{tag.interface}}(const Node* node) {
+  return node && Is{{tag.interface}}(*node);
 }
 template <>
 inline bool IsElementOfType<const {{tag.interface}}>(const Node& node) {
-  return is{{tag.interface}}(node);
+  return Is{{tag.interface}}(node);
 }
 template <>
 inline bool IsElementOfType<const {{tag.interface}}>(const {{namespace}}Element& element) {
-  return is{{tag.interface}}(element);
+  return Is{{tag.interface}}(element);
 }
 
 {% endfor %}
diff --git a/third_party/WebKit/Source/build/scripts/templates/fields/pointer.tmpl b/third_party/WebKit/Source/build/scripts/templates/fields/pointer.tmpl
index 4895640..eed1079 100644
--- a/third_party/WebKit/Source/build/scripts/templates/fields/pointer.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/fields/pointer.tmpl
@@ -6,7 +6,7 @@
   return {{field.default_value}};
 }
 {{field.type_name}}* {{field.getter_method_name}}() const {
-  return {{decode(field, getter_expression(field))}}.Get();
+  return {{decode(field, getter_expression(field))}}.get();
 }
 
 void {{field.setter_method_name}}({{field.wrapper_pointer_name}}<{{field.type_name}}> v) {
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn
index 44c35598..8c44d0a 100644
--- a/third_party/WebKit/Source/core/BUILD.gn
+++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -1548,6 +1548,7 @@
     "layout/LayoutBlockTest.cpp",
     "layout/LayoutBoxModelObjectTest.cpp",
     "layout/LayoutBoxTest.cpp",
+    "layout/LayoutCountTest.cpp",
     "layout/LayoutEmbeddedContentTest.cpp",
     "layout/LayoutGeometryMapTest.cpp",
     "layout/LayoutInlineTest.cpp",
diff --git a/third_party/WebKit/Source/core/animation/AnimationEffectReadOnly.cpp b/third_party/WebKit/Source/core/animation/AnimationEffectReadOnly.cpp
index b1a46760..e3b6ebf 100644
--- a/third_party/WebKit/Source/core/animation/AnimationEffectReadOnly.cpp
+++ b/third_party/WebKit/Source/core/animation/AnimationEffectReadOnly.cpp
@@ -119,7 +119,7 @@
   computed_timing.setIterations(SpecifiedTiming().iteration_count);
 
   UnrestrictedDoubleOrString duration;
-  duration.setUnrestrictedDouble(IterationDuration() * 1000);
+  duration.SetUnrestrictedDouble(IterationDuration() * 1000);
   computed_timing.setDuration(duration);
 
   computed_timing.setDirection(
diff --git a/third_party/WebKit/Source/core/animation/AnimationEffectTimingReadOnly.cpp b/third_party/WebKit/Source/core/animation/AnimationEffectTimingReadOnly.cpp
index b6f2a5a..89b53b2 100644
--- a/third_party/WebKit/Source/core/animation/AnimationEffectTimingReadOnly.cpp
+++ b/third_party/WebKit/Source/core/animation/AnimationEffectTimingReadOnly.cpp
@@ -43,9 +43,9 @@
 void AnimationEffectTimingReadOnly::duration(
     UnrestrictedDoubleOrString& return_value) {
   if (std::isnan(parent_->SpecifiedTiming().iteration_duration)) {
-    return_value.setString("auto");
+    return_value.SetString("auto");
   } else {
-    return_value.setUnrestrictedDouble(
+    return_value.SetUnrestrictedDouble(
         parent_->SpecifiedTiming().iteration_duration * 1000);
   }
 }
diff --git a/third_party/WebKit/Source/core/animation/CSSBasicShapeInterpolationType.cpp b/third_party/WebKit/Source/core/animation/CSSBasicShapeInterpolationType.cpp
index 7000ce0..2009881 100644
--- a/third_party/WebKit/Source/core/animation/CSSBasicShapeInterpolationType.cpp
+++ b/third_party/WebKit/Source/core/animation/CSSBasicShapeInterpolationType.cpp
@@ -59,7 +59,7 @@
 
   bool IsValid(const StyleResolverState& state,
                const InterpolationValue&) const final {
-    return DataEquivalent(inherited_shape_.Get(),
+    return DataEquivalent(inherited_shape_.get(),
                           BasicShapePropertyFunctions::GetBasicShape(
                               property_, *state.ParentStyle()));
   }
@@ -76,7 +76,7 @@
   // const_cast is for taking refs.
   NonInterpolableValue* non_interpolable_value =
       const_cast<NonInterpolableValue*>(
-          underlying.non_interpolable_value.Get());
+          underlying.non_interpolable_value.get());
   conversion_checkers.push_back(
       UnderlyingCompatibilityChecker::Create(non_interpolable_value));
   return InterpolationValue(
diff --git a/third_party/WebKit/Source/core/animation/CSSBorderImageLengthBoxInterpolationType.cpp b/third_party/WebKit/Source/core/animation/CSSBorderImageLengthBoxInterpolationType.cpp
index 78af5dc6..4f7ec16 100644
--- a/third_party/WebKit/Source/core/animation/CSSBorderImageLengthBoxInterpolationType.cpp
+++ b/third_party/WebKit/Source/core/animation/CSSBorderImageLengthBoxInterpolationType.cpp
@@ -357,7 +357,7 @@
         LengthInterpolationFunctions::Composite(
             underlying_list.GetMutable(i),
             underlying_side_non_interpolable_values[i], underlying_fraction,
-            *list.Get(i), side_non_interpolable_values[i].Get());
+            *list.Get(i), side_non_interpolable_values[i].get());
         break;
       case SideType::kAuto:
         break;
@@ -390,7 +390,7 @@
         return Length(kAuto);
       case SideType::kLength:
         return LengthInterpolationFunctions::CreateLength(
-            *list.Get(index), non_interpolable_values[index].Get(),
+            *list.Get(index), non_interpolable_values[index].get(),
             state.CssToLengthConversionData(), kValueRangeNonNegative);
       default:
         NOTREACHED();
diff --git a/third_party/WebKit/Source/core/animation/CSSFilterListInterpolationType.cpp b/third_party/WebKit/Source/core/animation/CSSFilterListInterpolationType.cpp
index b553788..0b62f7e 100644
--- a/third_party/WebKit/Source/core/animation/CSSFilterListInterpolationType.cpp
+++ b/third_party/WebKit/Source/core/animation/CSSFilterListInterpolationType.cpp
@@ -272,7 +272,7 @@
       std::move(extended_interpolable_list);
   // const_cast to take a ref.
   underlying_value_owner.MutableValue().non_interpolable_value =
-      const_cast<NonInterpolableValue*>(value.non_interpolable_value.Get());
+      const_cast<NonInterpolableValue*>(value.non_interpolable_value.get());
 }
 
 void CSSFilterListInterpolationType::ApplyStandardPropertyValue(
diff --git a/third_party/WebKit/Source/core/animation/CSSFontVariationSettingsInterpolationType.cpp b/third_party/WebKit/Source/core/animation/CSSFontVariationSettingsInterpolationType.cpp
index 37efba5..2a8fa8d 100644
--- a/third_party/WebKit/Source/core/animation/CSSFontVariationSettingsInterpolationType.cpp
+++ b/third_party/WebKit/Source/core/animation/CSSFontVariationSettingsInterpolationType.cpp
@@ -87,7 +87,7 @@
   bool IsValid(const StyleResolverState& state,
                const InterpolationValue&) const final {
     return DataEquivalent(
-        settings_.Get(),
+        settings_.get(),
         state.ParentStyle()->GetFontDescription().VariationSettings());
   }
 
diff --git a/third_party/WebKit/Source/core/animation/CSSImageInterpolationType.cpp b/third_party/WebKit/Source/core/animation/CSSImageInterpolationType.cpp
index a82638a4..8ce2c55 100644
--- a/third_party/WebKit/Source/core/animation/CSSImageInterpolationType.cpp
+++ b/third_party/WebKit/Source/core/animation/CSSImageInterpolationType.cpp
@@ -160,8 +160,8 @@
     return underlying_.interpolable_value->Equals(
                *underlying.interpolable_value) &&
            CSSImageInterpolationType::EqualNonInterpolableValues(
-               underlying_.non_interpolable_value.Get(),
-               underlying.non_interpolable_value.Get());
+               underlying_.non_interpolable_value.get(),
+               underlying.non_interpolable_value.get());
   }
 
   const InterpolationValue underlying_;
diff --git a/third_party/WebKit/Source/core/animation/CSSInterpolationType.cpp b/third_party/WebKit/Source/core/animation/CSSInterpolationType.cpp
index 5ef84537..5ef42121 100644
--- a/third_party/WebKit/Source/core/animation/CSSInterpolationType.cpp
+++ b/third_party/WebKit/Source/core/animation/CSSInterpolationType.cpp
@@ -301,10 +301,12 @@
   // TODO(alancutter): Defer tokenization of the CSSValue until it is needed.
   String string_value = css_value->CssText();
   CSSTokenizer tokenizer(string_value);
+  const auto tokens = tokenizer.TokenizeToEOF();
   bool is_animation_tainted = true;
   bool needs_variable_resolution = false;
-  RefPtr<CSSVariableData> variable_data = CSSVariableData::Create(
-      tokenizer.TokenRange(), is_animation_tainted, needs_variable_resolution);
+  RefPtr<CSSVariableData> variable_data =
+      CSSVariableData::Create(CSSParserTokenRange(tokens), is_animation_tainted,
+                              needs_variable_resolution);
   ComputedStyle& style = *state.Style();
   const PropertyHandle property = GetProperty();
   const AtomicString& property_name = property.CustomPropertyName();
diff --git a/third_party/WebKit/Source/core/animation/CSSLengthInterpolationType.cpp b/third_party/WebKit/Source/core/animation/CSSLengthInterpolationType.cpp
index 124d5d3..c288176c 100644
--- a/third_party/WebKit/Source/core/animation/CSSLengthInterpolationType.cpp
+++ b/third_party/WebKit/Source/core/animation/CSSLengthInterpolationType.cpp
@@ -139,7 +139,7 @@
   LengthInterpolationFunctions::Composite(
       underlying.interpolable_value, underlying.non_interpolable_value,
       underlying_fraction, *value.interpolable_value,
-      value.non_interpolable_value.Get());
+      value.non_interpolable_value.get());
 }
 
 void CSSLengthInterpolationType::ApplyStandardPropertyValue(
diff --git a/third_party/WebKit/Source/core/animation/CSSPathInterpolationType.cpp b/third_party/WebKit/Source/core/animation/CSSPathInterpolationType.cpp
index 52f44d2..5f7a6b04 100644
--- a/third_party/WebKit/Source/core/animation/CSSPathInterpolationType.cpp
+++ b/third_party/WebKit/Source/core/animation/CSSPathInterpolationType.cpp
@@ -64,7 +64,7 @@
 
   bool IsValid(const StyleResolverState& state,
                const InterpolationValue& underlying) const final {
-    return state.ParentStyle()->SvgStyle().D() == style_path_.Get();
+    return state.ParentStyle()->SvgStyle().D() == style_path_.get();
   }
 
   const RefPtr<StylePath> style_path_;
diff --git a/third_party/WebKit/Source/core/animation/CSSTextIndentInterpolationType.cpp b/third_party/WebKit/Source/core/animation/CSSTextIndentInterpolationType.cpp
index a58a93c..2b9446d 100644
--- a/third_party/WebKit/Source/core/animation/CSSTextIndentInterpolationType.cpp
+++ b/third_party/WebKit/Source/core/animation/CSSTextIndentInterpolationType.cpp
@@ -44,7 +44,7 @@
   }
 
   const NonInterpolableValue* LengthNonInterpolableValue() const {
-    return length_non_interpolable_value_.Get();
+    return length_non_interpolable_value_.get();
   }
   RefPtr<NonInterpolableValue>& LengthNonInterpolableValue() {
     return length_non_interpolable_value_;
diff --git a/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp b/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp
index 194b72bb..2ef8b4103 100644
--- a/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp
+++ b/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp
@@ -610,7 +610,7 @@
 template <typename PlatformAnimationCurveType>
 void AddKeyframesToCurve(PlatformAnimationCurveType& curve,
                          const PropertySpecificKeyframeVector& keyframes) {
-  auto* last_keyframe = keyframes.back().Get();
+  auto* last_keyframe = keyframes.back().get();
   for (const auto& keyframe : keyframes) {
     const TimingFunction* keyframe_timing_function = 0;
     // Ignore timing function of last frame.
@@ -620,7 +620,7 @@
       keyframe_timing_function = &keyframe->Easing();
 
     const AnimatableValue* value = keyframe->GetAnimatableValue();
-    AddKeyframeToCurve(curve, keyframe.Get(), value, *keyframe_timing_function);
+    AddKeyframeToCurve(curve, keyframe.get(), value, *keyframe_timing_function);
   }
 }
 
diff --git a/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp b/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp
index 9d9c8c8..8c9624d 100644
--- a/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp
+++ b/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp
@@ -153,7 +153,7 @@
     RefPtr<Keyframe> second = frame->CloneWithOffset(1);
 
     frames.push_back(frame);
-    frames.push_back(ToAnimatableValueKeyframe(second.Get()));
+    frames.push_back(ToAnimatableValueKeyframe(second.get()));
     return CanStartEffectOnCompositor(
         timing_, *AnimatableValueKeyframeEffectModel::Create(frames));
   }
@@ -197,7 +197,7 @@
       value = AnimatableDouble::Create(10.0);
 
     RefPtr<AnimatableValueKeyframe> keyframe =
-        CreateReplaceOpKeyframe(id, value.Get(), offset);
+        CreateReplaceOpKeyframe(id, value.get(), offset);
     keyframe->SetComposite(op);
     return keyframe;
   }
@@ -219,8 +219,8 @@
       double offset = 1.0 / (values.size() - 1) * i;
       RefPtr<AnimatableDouble> value = AnimatableDouble::Create(values[i]);
       frames->push_back(
-          CreateReplaceOpKeyframe(CSSPropertyOpacity, value.Get(), offset)
-              .Get());
+          CreateReplaceOpKeyframe(CSSPropertyOpacity, value.get(), offset)
+              .get());
     }
     return frames;
   }
@@ -235,8 +235,8 @@
       RefPtr<AnimatableTransform> value =
           AnimatableTransform::Create(values[i], 1);
       frames->push_back(
-          CreateReplaceOpKeyframe(CSSPropertyTransform, value.Get(), offset)
-              .Get());
+          CreateReplaceOpKeyframe(CSSPropertyTransform, value.get(), offset)
+              .get());
     }
     return frames;
   }
@@ -326,16 +326,16 @@
       CreateDefaultKeyframe(CSSPropertyOpacity, EffectModel::kCompositeReplace);
   keyframe_good_multiple->SetPropertyValue(
       CSSPropertyTransform,
-      AnimatableTransform::Create(TransformOperations(), 1).Get());
+      AnimatableTransform::Create(TransformOperations(), 1).get());
   EXPECT_TRUE(DuplicateSingleKeyframeAndTestIsCandidateOnResult(
-      keyframe_good_multiple.Get()));
+      keyframe_good_multiple.get()));
 
   RefPtr<AnimatableValueKeyframe> keyframe_bad_multiple_id =
       CreateDefaultKeyframe(CSSPropertyColor, EffectModel::kCompositeReplace);
   keyframe_bad_multiple_id->SetPropertyValue(
-      CSSPropertyOpacity, AnimatableDouble::Create(10.0).Get());
+      CSSPropertyOpacity, AnimatableDouble::Create(10.0).get());
   EXPECT_FALSE(DuplicateSingleKeyframeAndTestIsCandidateOnResult(
-      keyframe_bad_multiple_id.Get()));
+      keyframe_bad_multiple_id.get()));
 }
 
 TEST_F(AnimationCompositorAnimationsTest,
@@ -344,17 +344,17 @@
   ops.Operations().push_back(TranslateTransformOperation::Create(
       Length(2, kFixed), Length(2, kFixed), TransformOperation::kTranslateX));
   RefPtr<AnimatableValueKeyframe> good_keyframe = CreateReplaceOpKeyframe(
-      CSSPropertyTransform, AnimatableTransform::Create(ops, 1).Get());
+      CSSPropertyTransform, AnimatableTransform::Create(ops, 1).get());
   EXPECT_TRUE(
-      DuplicateSingleKeyframeAndTestIsCandidateOnResult(good_keyframe.Get()));
+      DuplicateSingleKeyframeAndTestIsCandidateOnResult(good_keyframe.get()));
 
   ops.Operations().push_back(TranslateTransformOperation::Create(
       Length(50, kPercent), Length(2, kFixed),
       TransformOperation::kTranslateX));
   RefPtr<AnimatableValueKeyframe> bad_keyframe = CreateReplaceOpKeyframe(
-      CSSPropertyTransform, AnimatableTransform::Create(ops, 1).Get());
+      CSSPropertyTransform, AnimatableTransform::Create(ops, 1).get());
   EXPECT_FALSE(
-      DuplicateSingleKeyframeAndTestIsCandidateOnResult(bad_keyframe.Get()));
+      DuplicateSingleKeyframeAndTestIsCandidateOnResult(bad_keyframe.get()));
 
   TransformOperations ops2;
   Length calc_length =
@@ -362,9 +362,9 @@
   ops2.Operations().push_back(TranslateTransformOperation::Create(
       calc_length, Length(0, kFixed), TransformOperation::kTranslateX));
   RefPtr<AnimatableValueKeyframe> bad_keyframe2 = CreateReplaceOpKeyframe(
-      CSSPropertyTransform, AnimatableTransform::Create(ops2, 1).Get());
+      CSSPropertyTransform, AnimatableTransform::Create(ops2, 1).get());
   EXPECT_FALSE(
-      DuplicateSingleKeyframeAndTestIsCandidateOnResult(bad_keyframe2.Get()));
+      DuplicateSingleKeyframeAndTestIsCandidateOnResult(bad_keyframe2.get()));
 }
 
 TEST_F(AnimationCompositorAnimationsTest,
@@ -373,11 +373,11 @@
   frames_same.push_back(CreateDefaultKeyframe(CSSPropertyColor,
                                               EffectModel::kCompositeReplace,
                                               0.0)
-                            .Get());
+                            .get());
   frames_same.push_back(CreateDefaultKeyframe(CSSPropertyColor,
                                               EffectModel::kCompositeReplace,
                                               1.0)
-                            .Get());
+                            .get());
   EXPECT_FALSE(CanStartEffectOnCompositor(
       timing_, *AnimatableValueKeyframeEffectModel::Create(frames_same)));
 
@@ -625,11 +625,11 @@
 
 TEST_F(AnimationCompositorAnimationsTest,
        CanStartEffectOnCompositorNonLinearTimingFunctionOnFirstOrLastFrame) {
-  (*keyframe_vector2_)[0]->SetEasing(cubic_ease_timing_function_.Get());
+  (*keyframe_vector2_)[0]->SetEasing(cubic_ease_timing_function_.get());
   keyframe_animation_effect2_ =
       AnimatableValueKeyframeEffectModel::Create(*keyframe_vector2_);
 
-  (*keyframe_vector5_)[3]->SetEasing(cubic_ease_timing_function_.Get());
+  (*keyframe_vector5_)[3]->SetEasing(cubic_ease_timing_function_.get());
   keyframe_animation_effect5_ =
       AnimatableValueKeyframeEffectModel::Create(*keyframe_vector5_);
 
@@ -648,22 +648,22 @@
 
 TEST_F(AnimationCompositorAnimationsTest,
        CanStartEffectOnCompositorTimingFunctionChainedCubicMatchingOffsets) {
-  (*keyframe_vector2_)[0]->SetEasing(cubic_ease_timing_function_.Get());
+  (*keyframe_vector2_)[0]->SetEasing(cubic_ease_timing_function_.get());
   keyframe_animation_effect2_ =
       AnimatableValueKeyframeEffectModel::Create(*keyframe_vector2_);
   EXPECT_TRUE(
       CanStartEffectOnCompositor(timing_, *keyframe_animation_effect2_));
 
-  (*keyframe_vector2_)[0]->SetEasing(cubic_custom_timing_function_.Get());
+  (*keyframe_vector2_)[0]->SetEasing(cubic_custom_timing_function_.get());
   keyframe_animation_effect2_ =
       AnimatableValueKeyframeEffectModel::Create(*keyframe_vector2_);
   EXPECT_TRUE(
       CanStartEffectOnCompositor(timing_, *keyframe_animation_effect2_));
 
-  (*keyframe_vector5_)[0]->SetEasing(cubic_ease_timing_function_.Get());
-  (*keyframe_vector5_)[1]->SetEasing(cubic_custom_timing_function_.Get());
-  (*keyframe_vector5_)[2]->SetEasing(cubic_custom_timing_function_.Get());
-  (*keyframe_vector5_)[3]->SetEasing(cubic_custom_timing_function_.Get());
+  (*keyframe_vector5_)[0]->SetEasing(cubic_ease_timing_function_.get());
+  (*keyframe_vector5_)[1]->SetEasing(cubic_custom_timing_function_.get());
+  (*keyframe_vector5_)[2]->SetEasing(cubic_custom_timing_function_.get());
+  (*keyframe_vector5_)[3]->SetEasing(cubic_custom_timing_function_.get());
   keyframe_animation_effect5_ =
       AnimatableValueKeyframeEffectModel::Create(*keyframe_vector5_);
   EXPECT_TRUE(
@@ -672,10 +672,10 @@
 
 TEST_F(AnimationCompositorAnimationsTest,
        CanStartEffectOnCompositorTimingFunctionMixedGood) {
-  (*keyframe_vector5_)[0]->SetEasing(linear_timing_function_.Get());
-  (*keyframe_vector5_)[1]->SetEasing(cubic_ease_timing_function_.Get());
-  (*keyframe_vector5_)[2]->SetEasing(cubic_ease_timing_function_.Get());
-  (*keyframe_vector5_)[3]->SetEasing(linear_timing_function_.Get());
+  (*keyframe_vector5_)[0]->SetEasing(linear_timing_function_.get());
+  (*keyframe_vector5_)[1]->SetEasing(cubic_ease_timing_function_.get());
+  (*keyframe_vector5_)[2]->SetEasing(cubic_ease_timing_function_.get());
+  (*keyframe_vector5_)[3]->SetEasing(linear_timing_function_.get());
   keyframe_animation_effect5_ =
       AnimatableValueKeyframeEffectModel::Create(*keyframe_vector5_);
   EXPECT_TRUE(
@@ -684,40 +684,40 @@
 
 TEST_F(AnimationCompositorAnimationsTest,
        CanStartEffectOnCompositorTimingFunctionWithStepOrFrameOkay) {
-  (*keyframe_vector2_)[0]->SetEasing(step_timing_function_.Get());
+  (*keyframe_vector2_)[0]->SetEasing(step_timing_function_.get());
   keyframe_animation_effect2_ =
       AnimatableValueKeyframeEffectModel::Create(*keyframe_vector2_);
   EXPECT_TRUE(
       CanStartEffectOnCompositor(timing_, *keyframe_animation_effect2_));
 
-  (*keyframe_vector2_)[0]->SetEasing(frames_timing_function_.Get());
+  (*keyframe_vector2_)[0]->SetEasing(frames_timing_function_.get());
   keyframe_animation_effect2_ =
       AnimatableValueKeyframeEffectModel::Create(*keyframe_vector2_);
   EXPECT_TRUE(
       CanStartEffectOnCompositor(timing_, *keyframe_animation_effect2_));
 
-  (*keyframe_vector5_)[0]->SetEasing(step_timing_function_.Get());
-  (*keyframe_vector5_)[1]->SetEasing(linear_timing_function_.Get());
-  (*keyframe_vector5_)[2]->SetEasing(cubic_ease_timing_function_.Get());
-  (*keyframe_vector5_)[3]->SetEasing(frames_timing_function_.Get());
+  (*keyframe_vector5_)[0]->SetEasing(step_timing_function_.get());
+  (*keyframe_vector5_)[1]->SetEasing(linear_timing_function_.get());
+  (*keyframe_vector5_)[2]->SetEasing(cubic_ease_timing_function_.get());
+  (*keyframe_vector5_)[3]->SetEasing(frames_timing_function_.get());
   keyframe_animation_effect5_ =
       AnimatableValueKeyframeEffectModel::Create(*keyframe_vector5_);
   EXPECT_TRUE(
       CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_));
 
-  (*keyframe_vector5_)[0]->SetEasing(frames_timing_function_.Get());
-  (*keyframe_vector5_)[1]->SetEasing(step_timing_function_.Get());
-  (*keyframe_vector5_)[2]->SetEasing(cubic_ease_timing_function_.Get());
-  (*keyframe_vector5_)[3]->SetEasing(linear_timing_function_.Get());
+  (*keyframe_vector5_)[0]->SetEasing(frames_timing_function_.get());
+  (*keyframe_vector5_)[1]->SetEasing(step_timing_function_.get());
+  (*keyframe_vector5_)[2]->SetEasing(cubic_ease_timing_function_.get());
+  (*keyframe_vector5_)[3]->SetEasing(linear_timing_function_.get());
   keyframe_animation_effect5_ =
       AnimatableValueKeyframeEffectModel::Create(*keyframe_vector5_);
   EXPECT_TRUE(
       CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_));
 
-  (*keyframe_vector5_)[0]->SetEasing(linear_timing_function_.Get());
-  (*keyframe_vector5_)[1]->SetEasing(frames_timing_function_.Get());
-  (*keyframe_vector5_)[2]->SetEasing(cubic_ease_timing_function_.Get());
-  (*keyframe_vector5_)[3]->SetEasing(step_timing_function_.Get());
+  (*keyframe_vector5_)[0]->SetEasing(linear_timing_function_.get());
+  (*keyframe_vector5_)[1]->SetEasing(frames_timing_function_.get());
+  (*keyframe_vector5_)[2]->SetEasing(cubic_ease_timing_function_.get());
+  (*keyframe_vector5_)[3]->SetEasing(step_timing_function_.get());
   keyframe_animation_effect5_ =
       AnimatableValueKeyframeEffectModel::Create(*keyframe_vector5_);
   EXPECT_TRUE(
@@ -729,27 +729,27 @@
   basic_frames_vector.push_back(
       CreateDefaultKeyframe(CSSPropertyOpacity, EffectModel::kCompositeReplace,
                             0.0)
-          .Get());
+          .get());
   basic_frames_vector.push_back(
       CreateDefaultKeyframe(CSSPropertyOpacity, EffectModel::kCompositeReplace,
                             1.0)
-          .Get());
+          .get());
 
   AnimatableValueKeyframeVector non_basic_frames_vector;
   non_basic_frames_vector.push_back(
       CreateDefaultKeyframe(CSSPropertyOpacity, EffectModel::kCompositeReplace,
                             0.0)
-          .Get());
+          .get());
   non_basic_frames_vector.push_back(
       CreateDefaultKeyframe(CSSPropertyOpacity, EffectModel::kCompositeReplace,
                             0.5)
-          .Get());
+          .get());
   non_basic_frames_vector.push_back(
       CreateDefaultKeyframe(CSSPropertyOpacity, EffectModel::kCompositeReplace,
                             1.0)
-          .Get());
+          .get());
 
-  basic_frames_vector[0]->SetEasing(linear_timing_function_.Get());
+  basic_frames_vector[0]->SetEasing(linear_timing_function_.get());
   AnimatableValueKeyframeEffectModel* basic_frames =
       AnimatableValueKeyframeEffectModel::Create(basic_frames_vector);
   EXPECT_TRUE(CanStartEffectOnCompositor(timing_, *basic_frames));
@@ -760,7 +760,7 @@
       AnimatableValueKeyframeEffectModel::Create(basic_frames_vector);
   EXPECT_TRUE(CanStartEffectOnCompositor(timing_, *basic_frames));
 
-  non_basic_frames_vector[0]->SetEasing(linear_timing_function_.Get());
+  non_basic_frames_vector[0]->SetEasing(linear_timing_function_.get());
   non_basic_frames_vector[1]->SetEasing(CubicBezierTimingFunction::Preset(
       CubicBezierTimingFunction::EaseType::EASE_IN));
   AnimatableValueKeyframeEffectModel* non_basic_frames =
@@ -775,9 +775,9 @@
   // KeyframeEffect to convert
   AnimatableValueKeyframeEffectModel* effect = CreateKeyframeEffectModel(
       CreateReplaceOpKeyframe(CSSPropertyOpacity,
-                              AnimatableDouble::Create(2.0).Get(), 0),
+                              AnimatableDouble::Create(2.0).get(), 0),
       CreateReplaceOpKeyframe(CSSPropertyOpacity,
-                              AnimatableDouble::Create(5.0).Get(), 1.0));
+                              AnimatableDouble::Create(5.0).get(), 1.0));
 
   std::unique_ptr<CompositorAnimation> animation =
       ConvertToCompositorAnimation(*effect);
@@ -810,9 +810,9 @@
   // KeyframeEffect to convert
   AnimatableValueKeyframeEffectModel* effect = CreateKeyframeEffectModel(
       CreateReplaceOpKeyframe(CSSPropertyOpacity,
-                              AnimatableDouble::Create(2.0).Get(), 0),
+                              AnimatableDouble::Create(2.0).get(), 0),
       CreateReplaceOpKeyframe(CSSPropertyOpacity,
-                              AnimatableDouble::Create(5.0).Get(), 1.0));
+                              AnimatableDouble::Create(5.0).get(), 1.0));
 
   const double kDuration = 10.0;
   timing_.iteration_duration = kDuration;
@@ -834,13 +834,13 @@
   // KeyframeEffect to convert
   AnimatableValueKeyframeEffectModel* effect = CreateKeyframeEffectModel(
       CreateReplaceOpKeyframe(CSSPropertyOpacity,
-                              AnimatableDouble::Create(2.0).Get(), 0),
+                              AnimatableDouble::Create(2.0).get(), 0),
       CreateReplaceOpKeyframe(CSSPropertyOpacity,
-                              AnimatableDouble::Create(-1.0).Get(), 0.25),
+                              AnimatableDouble::Create(-1.0).get(), 0.25),
       CreateReplaceOpKeyframe(CSSPropertyOpacity,
-                              AnimatableDouble::Create(20.0).Get(), 0.5),
+                              AnimatableDouble::Create(20.0).get(), 0.5),
       CreateReplaceOpKeyframe(CSSPropertyOpacity,
-                              AnimatableDouble::Create(5.0).Get(), 1.0));
+                              AnimatableDouble::Create(5.0).get(), 1.0));
 
   timing_.iteration_count = 5;
   timing_.direction = Timing::PlaybackDirection::ALTERNATE_NORMAL;
@@ -888,9 +888,9 @@
   // KeyframeEffect to convert
   AnimatableValueKeyframeEffectModel* effect = CreateKeyframeEffectModel(
       CreateReplaceOpKeyframe(CSSPropertyOpacity,
-                              AnimatableDouble::Create(2.0).Get(), 0),
+                              AnimatableDouble::Create(2.0).get(), 0),
       CreateReplaceOpKeyframe(CSSPropertyOpacity,
-                              AnimatableDouble::Create(5.0).Get(), 1.0));
+                              AnimatableDouble::Create(5.0).get(), 1.0));
 
   const double kStartDelay = 3.25;
 
@@ -921,20 +921,20 @@
   // KeyframeEffect to convert
   AnimatableValueKeyframeVector frames;
   frames.push_back(CreateReplaceOpKeyframe(
-      CSSPropertyOpacity, AnimatableDouble::Create(2.0).Get(), 0));
+      CSSPropertyOpacity, AnimatableDouble::Create(2.0).get(), 0));
   frames.push_back(CreateReplaceOpKeyframe(
-      CSSPropertyOpacity, AnimatableDouble::Create(-1.0).Get(), 0.25));
+      CSSPropertyOpacity, AnimatableDouble::Create(-1.0).get(), 0.25));
   frames.push_back(CreateReplaceOpKeyframe(
-      CSSPropertyOpacity, AnimatableDouble::Create(20.0).Get(), 0.5));
+      CSSPropertyOpacity, AnimatableDouble::Create(20.0).get(), 0.5));
   frames.push_back(CreateReplaceOpKeyframe(
-      CSSPropertyOpacity, AnimatableDouble::Create(5.0).Get(), 1.0));
-  frames[0]->SetEasing(cubic_ease_timing_function_.Get());
-  frames[1]->SetEasing(linear_timing_function_.Get());
-  frames[2]->SetEasing(cubic_custom_timing_function_.Get());
+      CSSPropertyOpacity, AnimatableDouble::Create(5.0).get(), 1.0));
+  frames[0]->SetEasing(cubic_ease_timing_function_.get());
+  frames[1]->SetEasing(linear_timing_function_.get());
+  frames[2]->SetEasing(cubic_custom_timing_function_.get());
   AnimatableValueKeyframeEffectModel* effect =
       AnimatableValueKeyframeEffectModel::Create(frames);
 
-  timing_.timing_function = linear_timing_function_.Get();
+  timing_.timing_function = linear_timing_function_.get();
   timing_.iteration_duration = 2.0;
   timing_.iteration_count = 10;
   timing_.direction = Timing::PlaybackDirection::ALTERNATE_NORMAL;
@@ -983,21 +983,21 @@
   // KeyframeEffect to convert
   AnimatableValueKeyframeVector frames;
   frames.push_back(CreateReplaceOpKeyframe(
-      CSSPropertyOpacity, AnimatableDouble::Create(2.0).Get(), 0));
+      CSSPropertyOpacity, AnimatableDouble::Create(2.0).get(), 0));
   frames.push_back(CreateReplaceOpKeyframe(
-      CSSPropertyOpacity, AnimatableDouble::Create(-1.0).Get(), 0.25));
+      CSSPropertyOpacity, AnimatableDouble::Create(-1.0).get(), 0.25));
   frames.push_back(CreateReplaceOpKeyframe(
-      CSSPropertyOpacity, AnimatableDouble::Create(20.0).Get(), 0.5));
+      CSSPropertyOpacity, AnimatableDouble::Create(20.0).get(), 0.5));
   frames.push_back(CreateReplaceOpKeyframe(
-      CSSPropertyOpacity, AnimatableDouble::Create(5.0).Get(), 1.0));
+      CSSPropertyOpacity, AnimatableDouble::Create(5.0).get(), 1.0));
   frames[0]->SetEasing(CubicBezierTimingFunction::Preset(
       CubicBezierTimingFunction::EaseType::EASE_IN));
-  frames[1]->SetEasing(linear_timing_function_.Get());
-  frames[2]->SetEasing(cubic_easy_flip_timing_function.Get());
+  frames[1]->SetEasing(linear_timing_function_.get());
+  frames[2]->SetEasing(cubic_easy_flip_timing_function.get());
   AnimatableValueKeyframeEffectModel* effect =
       AnimatableValueKeyframeEffectModel::Create(frames);
 
-  timing_.timing_function = linear_timing_function_.Get();
+  timing_.timing_function = linear_timing_function_.get();
   timing_.iteration_count = 10;
   timing_.direction = Timing::PlaybackDirection::ALTERNATE_REVERSE;
 
@@ -1046,9 +1046,9 @@
   // KeyframeEffect to convert
   AnimatableValueKeyframeEffectModel* effect = CreateKeyframeEffectModel(
       CreateReplaceOpKeyframe(CSSPropertyOpacity,
-                              AnimatableDouble::Create(2.0).Get(), 0),
+                              AnimatableDouble::Create(2.0).get(), 0),
       CreateReplaceOpKeyframe(CSSPropertyOpacity,
-                              AnimatableDouble::Create(5.0).Get(), 1.0));
+                              AnimatableDouble::Create(5.0).get(), 1.0));
 
   const double kNegativeStartDelay = -3;
 
@@ -1079,9 +1079,9 @@
   // KeyframeEffect to convert
   AnimatableValueKeyframeEffectModel* effect = CreateKeyframeEffectModel(
       CreateReplaceOpKeyframe(CSSPropertyOpacity,
-                              AnimatableDouble::Create(2.0).Get(), 0),
+                              AnimatableDouble::Create(2.0).get(), 0),
       CreateReplaceOpKeyframe(CSSPropertyOpacity,
-                              AnimatableDouble::Create(5.0).Get(), 1.0));
+                              AnimatableDouble::Create(5.0).get(), 1.0));
 
   const double kPlaybackRate = 2;
   const double kPlayerPlaybackRate = -1.5;
@@ -1109,9 +1109,9 @@
   // KeyframeEffect to convert
   AnimatableValueKeyframeEffectModel* effect = CreateKeyframeEffectModel(
       CreateReplaceOpKeyframe(CSSPropertyOpacity,
-                              AnimatableDouble::Create(2.0).Get(), 0),
+                              AnimatableDouble::Create(2.0).get(), 0),
       CreateReplaceOpKeyframe(CSSPropertyOpacity,
-                              AnimatableDouble::Create(5.0).Get(), 1.0));
+                              AnimatableDouble::Create(5.0).get(), 1.0));
 
   timing_.fill_mode = Timing::FillMode::NONE;
 
@@ -1125,9 +1125,9 @@
   // KeyframeEffect to convert
   AnimatableValueKeyframeEffectModel* effect = CreateKeyframeEffectModel(
       CreateReplaceOpKeyframe(CSSPropertyOpacity,
-                              AnimatableDouble::Create(2.0).Get(), 0),
+                              AnimatableDouble::Create(2.0).get(), 0),
       CreateReplaceOpKeyframe(CSSPropertyOpacity,
-                              AnimatableDouble::Create(5.0).Get(), 1.0));
+                              AnimatableDouble::Create(5.0).get(), 1.0));
 
   timing_.fill_mode = Timing::FillMode::AUTO;
 
@@ -1146,9 +1146,9 @@
   // KeyframeEffect to convert
   AnimatableValueKeyframeEffectModel* effect = CreateKeyframeEffectModel(
       CreateReplaceOpKeyframe(CSSPropertyOpacity,
-                              AnimatableDouble::Create(2.0).Get(), 0),
+                              AnimatableDouble::Create(2.0).get(), 0),
       CreateReplaceOpKeyframe(CSSPropertyOpacity,
-                              AnimatableDouble::Create(5.0).Get(), 1.0));
+                              AnimatableDouble::Create(5.0).get(), 1.0));
 
   timing_.timing_function = cubic_custom_timing_function_;
 
@@ -1197,11 +1197,11 @@
   key_frames.push_back(CreateDefaultKeyframe(CSSPropertyOpacity,
                                              EffectModel::kCompositeReplace,
                                              0.0)
-                           .Get());
+                           .get());
   key_frames.push_back(CreateDefaultKeyframe(CSSPropertyOpacity,
                                              EffectModel::kCompositeReplace,
                                              1.0)
-                           .Get());
+                           .get());
   EffectModel* animation_effect1 =
       AnimatableValueKeyframeEffectModel::Create(key_frames);
   EffectModel* animation_effect2 =
diff --git a/third_party/WebKit/Source/core/animation/CustomCompositorAnimations.cpp b/third_party/WebKit/Source/core/animation/CustomCompositorAnimations.cpp
index 8a14548..4a1478c4 100644
--- a/third_party/WebKit/Source/core/animation/CustomCompositorAnimations.cpp
+++ b/third_party/WebKit/Source/core/animation/CustomCompositorAnimations.cpp
@@ -32,10 +32,10 @@
   AnimatableValueKeyframeVector keyframes(2);
   keyframes[0] = AnimatableValueKeyframe::Create();
   keyframes[0]->SetOffset(0.0);
-  keyframes[0]->SetPropertyValue(property_id, value.Get());
+  keyframes[0]->SetPropertyValue(property_id, value.get());
   keyframes[1] = AnimatableValueKeyframe::Create();
   keyframes[1]->SetOffset(1.0);
-  keyframes[1]->SetPropertyValue(property_id, value.Get());
+  keyframes[1]->SetPropertyValue(property_id, value.get());
   keyframes[1]->SetComposite(EffectModel::kCompositeReplace);
 
   Timing timing;
@@ -55,10 +55,10 @@
       ToAnimatableValueKeyframeEffectModel(keyframe_effect.Model())
           ->GetFrames();
   AnimatableValueKeyframeVector keyframes(2);
-  keyframes[0] = ToAnimatableValueKeyframe(old_frames[0]->Clone().Get());
-  keyframes[1] = ToAnimatableValueKeyframe(old_frames[1]->Clone().Get());
-  keyframes[0]->SetPropertyValue(property_id, value.Get());
-  keyframes[1]->SetPropertyValue(property_id, value.Get());
+  keyframes[0] = ToAnimatableValueKeyframe(old_frames[0]->Clone().get());
+  keyframes[1] = ToAnimatableValueKeyframe(old_frames[1]->Clone().get());
+  keyframes[0]->SetPropertyValue(property_id, value.get());
+  keyframes[1]->SetPropertyValue(property_id, value.get());
 
   AnimatableValueKeyframeEffectModel* effect_model =
       AnimatableValueKeyframeEffectModel::Create(keyframes);
diff --git a/third_party/WebKit/Source/core/animation/EffectInput.cpp b/third_party/WebKit/Source/core/animation/EffectInput.cpp
index 5936041..8647824 100644
--- a/third_party/WebKit/Source/core/animation/EffectInput.cpp
+++ b/third_party/WebKit/Source/core/animation/EffectInput.cpp
@@ -180,15 +180,15 @@
     const DictionarySequenceOrDictionary& effect_input,
     ExecutionContext* execution_context,
     ExceptionState& exception_state) {
-  if (effect_input.isNull() || !element)
+  if (effect_input.IsNull() || !element)
     return nullptr;
 
-  if (effect_input.isDictionarySequence()) {
-    return ConvertArrayForm(*element, effect_input.getAsDictionarySequence(),
+  if (effect_input.IsDictionarySequence()) {
+    return ConvertArrayForm(*element, effect_input.GetAsDictionarySequence(),
                             execution_context, exception_state);
   }
 
-  const Dictionary& dictionary = effect_input.getAsDictionary();
+  const Dictionary& dictionary = effect_input.GetAsDictionary();
   DictionaryIterator iterator = dictionary.GetIterator(execution_context);
   if (!iterator.IsNull()) {
     // TODO(alancutter): Convert keyframes during iteration rather than after to
@@ -264,7 +264,7 @@
       String value;
       DictionaryHelper::Get(keyframe_dictionary, property, value);
 
-      SetKeyframeValue(element, *keyframe.Get(), property, value,
+      SetKeyframeValue(element, *keyframe.get(), property, value,
                        execution_context);
     }
     keyframes.push_back(keyframe);
@@ -381,7 +381,7 @@
         keyframe->SetComposite(EffectModel::kCompositeAdd);
       // TODO(alancutter): Support "accumulate" keyframe composition.
 
-      SetKeyframeValue(element, *keyframe.Get(), property, values[i],
+      SetKeyframeValue(element, *keyframe.get(), property, values[i],
                        execution_context);
       keyframes.push_back(keyframe);
     }
diff --git a/third_party/WebKit/Source/core/animation/EffectInputTest.cpp b/third_party/WebKit/Source/core/animation/EffectInputTest.cpp
index 8eeda73..ce24b74 100644
--- a/third_party/WebKit/Source/core/animation/EffectInputTest.cpp
+++ b/third_party/WebKit/Source/core/animation/EffectInputTest.cpp
@@ -45,7 +45,7 @@
   Element* element = AppendElement(scope.GetDocument());
   EffectModel* animation_effect = EffectInput::Convert(
       element,
-      DictionarySequenceOrDictionary::fromDictionarySequence(js_keyframes),
+      DictionarySequenceOrDictionary::FromDictionarySequence(js_keyframes),
       nullptr, scope.GetExceptionState());
   EXPECT_FALSE(scope.GetExceptionState().HadException());
   const KeyframeEffectModelBase& keyframe_effect =
@@ -72,7 +72,7 @@
   Element* element = AppendElement(scope.GetDocument());
   EffectInput::Convert(
       element,
-      DictionarySequenceOrDictionary::fromDictionarySequence(js_keyframes),
+      DictionarySequenceOrDictionary::FromDictionarySequence(js_keyframes),
       nullptr, scope.GetExceptionState());
   EXPECT_TRUE(scope.GetExceptionState().HadException());
   EXPECT_EQ(kV8TypeError, scope.GetExceptionState().Code());
@@ -101,7 +101,7 @@
   Element* element = AppendElement(scope.GetDocument());
   EffectModel* animation_effect = EffectInput::Convert(
       element,
-      DictionarySequenceOrDictionary::fromDictionarySequence(js_keyframes),
+      DictionarySequenceOrDictionary::FromDictionarySequence(js_keyframes),
       nullptr, scope.GetExceptionState());
   EXPECT_FALSE(scope.GetExceptionState().HadException());
   const KeyframeEffectModelBase& keyframe_effect =
@@ -137,7 +137,7 @@
   Element* element = AppendElement(scope.GetDocument());
   EffectInput::Convert(
       element,
-      DictionarySequenceOrDictionary::fromDictionarySequence(js_keyframes),
+      DictionarySequenceOrDictionary::FromDictionarySequence(js_keyframes),
       nullptr, scope.GetExceptionState());
   EXPECT_TRUE(scope.GetExceptionState().HadException());
 }
@@ -166,7 +166,7 @@
   Element* element = AppendElement(scope.GetDocument());
   EffectInput::Convert(
       element,
-      DictionarySequenceOrDictionary::fromDictionarySequence(js_keyframes),
+      DictionarySequenceOrDictionary::FromDictionarySequence(js_keyframes),
       nullptr, scope.GetExceptionState());
   EXPECT_TRUE(scope.GetExceptionState().HadException());
   EXPECT_EQ(kV8TypeError, scope.GetExceptionState().Code());
diff --git a/third_party/WebKit/Source/core/animation/EffectStack.cpp b/third_party/WebKit/Source/core/animation/EffectStack.cpp
index 57c1905d..53803f2a 100644
--- a/third_party/WebKit/Source/core/animation/EffectStack.cpp
+++ b/third_party/WebKit/Source/core/animation/EffectStack.cpp
@@ -58,9 +58,9 @@
         interpolation->IsInvalidatableInterpolation() &&
         ToInvalidatableInterpolation(*interpolation)
             .DependsOnUnderlyingValue()) {
-      active_interpolations.push_back(interpolation.Get());
+      active_interpolations.push_back(interpolation.get());
     } else {
-      active_interpolations.at(0) = interpolation.Get();
+      active_interpolations.at(0) = interpolation.get();
     }
   }
 }
diff --git a/third_party/WebKit/Source/core/animation/EffectStackTest.cpp b/third_party/WebKit/Source/core/animation/EffectStackTest.cpp
index fc8cd7f78..f4281a81 100644
--- a/third_party/WebKit/Source/core/animation/EffectStackTest.cpp
+++ b/third_party/WebKit/Source/core/animation/EffectStackTest.cpp
@@ -51,10 +51,10 @@
     AnimatableValueKeyframeVector keyframes(2);
     keyframes[0] = AnimatableValueKeyframe::Create();
     keyframes[0]->SetOffset(0.0);
-    keyframes[0]->SetPropertyValue(id, value.Get());
+    keyframes[0]->SetPropertyValue(id, value.get());
     keyframes[1] = AnimatableValueKeyframe::Create();
     keyframes[1]->SetOffset(1.0);
-    keyframes[1]->SetPropertyValue(id, value.Get());
+    keyframes[1]->SetPropertyValue(id, value.get());
     return AnimatableValueKeyframeEffectModel::Create(keyframes);
   }
 
@@ -77,7 +77,7 @@
     Interpolation& interpolation =
         *active_interpolations.at(PropertyHandle(id)).at(0);
     AnimatableValue* animatable_value =
-        ToLegacyStyleInterpolation(interpolation).CurrentValue().Get();
+        ToLegacyStyleInterpolation(interpolation).CurrentValue().get();
     return ToAnimatableDouble(animatable_value)->ToDouble();
   }
 
diff --git a/third_party/WebKit/Source/core/animation/ElementAnimation.h b/third_party/WebKit/Source/core/animation/ElementAnimation.h
index 57c83a2..b945b5d 100644
--- a/third_party/WebKit/Source/core/animation/ElementAnimation.h
+++ b/third_party/WebKit/Source/core/animation/ElementAnimation.h
@@ -71,9 +71,9 @@
                               exception_state))
       return nullptr;
 
-    if (options.isKeyframeAnimationOptions()) {
+    if (options.IsKeyframeAnimationOptions()) {
       Animation* animation = animateInternal(element, effect, timing);
-      animation->setId(options.getAsKeyframeAnimationOptions().id());
+      animation->setId(options.GetAsKeyframeAnimationOptions().id());
       return animation;
     }
     return animateInternal(element, effect, timing);
diff --git a/third_party/WebKit/Source/core/animation/ElementAnimations.cpp b/third_party/WebKit/Source/core/animation/ElementAnimations.cpp
index 10315fd5..8311178 100644
--- a/third_party/WebKit/Source/core/animation/ElementAnimations.cpp
+++ b/third_party/WebKit/Source/core/animation/ElementAnimations.cpp
@@ -98,7 +98,7 @@
 const ComputedStyle* ElementAnimations::BaseComputedStyle() const {
 #if !DCHECK_IS_ON()
   if (IsAnimationStyleChange())
-    return base_computed_style_.Get();
+    return base_computed_style_.get();
 #endif
   return nullptr;
 }
diff --git a/third_party/WebKit/Source/core/animation/FilterInterpolationFunctions.cpp b/third_party/WebKit/Source/core/animation/FilterInterpolationFunctions.cpp
index 0bdf0c2..cba1e41 100644
--- a/third_party/WebKit/Source/core/animation/FilterInterpolationFunctions.cpp
+++ b/third_party/WebKit/Source/core/animation/FilterInterpolationFunctions.cpp
@@ -27,7 +27,7 @@
 
   FilterOperation::OperationType GetOperationType() const { return type_; }
   const NonInterpolableValue* TypeNonInterpolableValue() const {
-    return type_non_interpolable_value_.Get();
+    return type_non_interpolable_value_.get();
   }
 
   DECLARE_NON_INTERPOLABLE_VALUE_TYPE();
diff --git a/third_party/WebKit/Source/core/animation/InterpolableValue.cpp b/third_party/WebKit/Source/core/animation/InterpolableValue.cpp
index a2bf9e6..e780850 100644
--- a/third_party/WebKit/Source/core/animation/InterpolableValue.cpp
+++ b/third_party/WebKit/Source/core/animation/InterpolableValue.cpp
@@ -96,7 +96,7 @@
   if (progress == 1)
     result_value.value_ = to_value.value_;
   result_value.value_ = AnimatableValue::Interpolate(
-      value_.Get(), to_value.value_.Get(), progress);
+      value_.get(), to_value.value_.get(), progress);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/animation/InterpolableValue.h b/third_party/WebKit/Source/core/animation/InterpolableValue.h
index 381c2ad..98d3d4d8 100644
--- a/third_party/WebKit/Source/core/animation/InterpolableValue.h
+++ b/third_party/WebKit/Source/core/animation/InterpolableValue.h
@@ -140,7 +140,7 @@
   }
 
   bool IsAnimatableValue() const final { return true; }
-  AnimatableValue* Value() const { return value_.Get(); }
+  AnimatableValue* Value() const { return value_.get(); }
   bool Equals(const InterpolableValue&) const final {
     NOTREACHED();
     return false;
diff --git a/third_party/WebKit/Source/core/animation/InterpolableValueTest.cpp b/third_party/WebKit/Source/core/animation/InterpolableValueTest.cpp
index c8039ab8..de25fdec 100644
--- a/third_party/WebKit/Source/core/animation/InterpolableValueTest.cpp
+++ b/third_party/WebKit/Source/core/animation/InterpolableValueTest.cpp
@@ -21,7 +21,7 @@
     RefPtr<LegacyStyleInterpolation> i = SampleTestInterpolation::Create(
         InterpolableNumber::Create(a), InterpolableNumber::Create(b));
     i->Interpolate(0, progress);
-    return ToInterpolableNumber(InterpolationValue(*i.Get()))->Value();
+    return ToInterpolableNumber(InterpolationValue(*i.get()))->Value();
   }
 
   void ScaleAndAdd(InterpolableValue& base,
@@ -63,7 +63,7 @@
 
   RefPtr<LegacyStyleInterpolation> i =
       InterpolateLists(std::move(list_a), std::move(list_b), 0.3);
-  InterpolableList* out_list = ToInterpolableList(InterpolationValue(*i.Get()));
+  InterpolableList* out_list = ToInterpolableList(InterpolationValue(*i.get()));
   EXPECT_FLOAT_EQ(30, ToInterpolableNumber(out_list->Get(0))->Value());
   EXPECT_FLOAT_EQ(-30.6f, ToInterpolableNumber(out_list->Get(1))->Value());
   EXPECT_FLOAT_EQ(104.35f, ToInterpolableNumber(out_list->Get(2))->Value());
@@ -86,7 +86,7 @@
 
   RefPtr<LegacyStyleInterpolation> i =
       InterpolateLists(std::move(list_a), std::move(list_b), 0.5);
-  InterpolableList* out_list = ToInterpolableList(InterpolationValue(*i.Get()));
+  InterpolableList* out_list = ToInterpolableList(InterpolationValue(*i.get()));
   EXPECT_FLOAT_EQ(50, ToInterpolableNumber(out_list->Get(0))->Value());
   EXPECT_FLOAT_EQ(
       75, ToInterpolableNumber(ToInterpolableList(out_list->Get(1))->Get(0))
diff --git a/third_party/WebKit/Source/core/animation/InterpolationEffectTest.cpp b/third_party/WebKit/Source/core/animation/InterpolationEffectTest.cpp
index f5ecda8..44623ec 100644
--- a/third_party/WebKit/Source/core/animation/InterpolationEffectTest.cpp
+++ b/third_party/WebKit/Source/core/animation/InterpolationEffectTest.cpp
@@ -25,7 +25,7 @@
 
   double GetInterpolableNumber(RefPtr<Interpolation> value) {
     LegacyStyleInterpolation& interpolation =
-        ToLegacyStyleInterpolation(*value.Get());
+        ToLegacyStyleInterpolation(*value.get());
     return ToInterpolableNumber(InterpolationValue(interpolation))->Value();
   }
 };
diff --git a/third_party/WebKit/Source/core/animation/InvalidatableInterpolation.cpp b/third_party/WebKit/Source/core/animation/InvalidatableInterpolation.cpp
index dec72a74..d786dde 100644
--- a/third_party/WebKit/Source/core/animation/InvalidatableInterpolation.cpp
+++ b/third_party/WebKit/Source/core/animation/InvalidatableInterpolation.cpp
@@ -282,7 +282,7 @@
   if (should_apply && underlying_value_owner)
     underlying_value_owner.GetType().Apply(
         *underlying_value_owner.Value().interpolable_value,
-        underlying_value_owner.Value().non_interpolable_value.Get(),
+        underlying_value_owner.Value().non_interpolable_value.get(),
         environment);
 }
 
diff --git a/third_party/WebKit/Source/core/animation/KeyframeEffectModelTest.cpp b/third_party/WebKit/Source/core/animation/KeyframeEffectModelTest.cpp
index b0fb113..9dc72bbb 100644
--- a/third_party/WebKit/Source/core/animation/KeyframeEffectModelTest.cpp
+++ b/third_party/WebKit/Source/core/animation/KeyframeEffectModelTest.cpp
@@ -52,34 +52,34 @@
   AnimatableValueKeyframeVector keyframes(2);
   keyframes[0] = AnimatableValueKeyframe::Create();
   keyframes[0]->SetOffset(0.0);
-  keyframes[0]->SetPropertyValue(CSSPropertyLeft, zero_value.Get());
+  keyframes[0]->SetPropertyValue(CSSPropertyLeft, zero_value.get());
   keyframes[1] = AnimatableValueKeyframe::Create();
   keyframes[1]->SetOffset(1.0);
-  keyframes[1]->SetPropertyValue(CSSPropertyLeft, one_value.Get());
+  keyframes[1]->SetPropertyValue(CSSPropertyLeft, one_value.get());
   return keyframes;
 }
 
 void ExpectProperty(CSSPropertyID property,
                     RefPtr<Interpolation> interpolation_value) {
   LegacyStyleInterpolation* interpolation =
-      ToLegacyStyleInterpolation(interpolation_value.Get());
+      ToLegacyStyleInterpolation(interpolation_value.get());
   ASSERT_EQ(property, interpolation->Id());
 }
 
 void ExpectDoubleValue(double expected_value,
                        RefPtr<Interpolation> interpolation_value) {
   LegacyStyleInterpolation* interpolation =
-      ToLegacyStyleInterpolation(interpolation_value.Get());
+      ToLegacyStyleInterpolation(interpolation_value.get());
   RefPtr<AnimatableValue> value = interpolation->CurrentValue();
 
   ASSERT_TRUE(value->IsDouble() || value->IsUnknown());
 
   double actual_value;
   if (value->IsDouble())
-    actual_value = ToAnimatableDouble(value.Get())->ToDouble();
+    actual_value = ToAnimatableDouble(value.get())->ToDouble();
   else
     actual_value =
-        ToCSSPrimitiveValue(ToAnimatableUnknown(value.Get())->ToCSSValue())
+        ToCSSPrimitiveValue(ToAnimatableUnknown(value.get())->ToCSSValue())
             ->GetDoubleValue();
 
   EXPECT_FLOAT_EQ(static_cast<float>(expected_value), actual_value);
@@ -88,8 +88,8 @@
 Interpolation* FindValue(Vector<RefPtr<Interpolation>>& values,
                          CSSPropertyID id) {
   for (auto& value : values) {
-    if (ToLegacyStyleInterpolation(value.Get())->Id() == id)
-      return value.Get();
+    if (ToLegacyStyleInterpolation(value.get())->Id() == id)
+      return value.get();
   }
   return 0;
 }
@@ -226,7 +226,7 @@
   keyframes[0] = AnimatableValueKeyframe::Create();
   keyframes[0]->SetOffset(0.0);
   keyframes[0]->SetPropertyValue(CSSPropertyLeft,
-                                 UnknownAnimatableValue(3.0).Get());
+                                 UnknownAnimatableValue(3.0).get());
 
   AnimatableValueKeyframeEffectModel* effect =
       AnimatableValueKeyframeEffectModel::Create(keyframes);
@@ -241,7 +241,7 @@
   keyframes[0] = AnimatableValueKeyframe::Create();
   keyframes[0]->SetOffset(1.0);
   keyframes[0]->SetPropertyValue(CSSPropertyLeft,
-                                 AnimatableDouble::Create(5.0).Get());
+                                 AnimatableDouble::Create(5.0).get());
 
   AnimatableValueKeyframeEffectModel* effect =
       AnimatableValueKeyframeEffectModel::Create(keyframes);
@@ -255,15 +255,15 @@
   keyframes[0] = AnimatableValueKeyframe::Create();
   keyframes[0]->SetOffset(0.0);
   keyframes[0]->SetPropertyValue(CSSPropertyLeft,
-                                 UnknownAnimatableValue(3.0).Get());
+                                 UnknownAnimatableValue(3.0).get());
   keyframes[1] = AnimatableValueKeyframe::Create();
   keyframes[1]->SetOffset(0.5);
   keyframes[1]->SetPropertyValue(CSSPropertyLeft,
-                                 UnknownAnimatableValue(4.0).Get());
+                                 UnknownAnimatableValue(4.0).get());
   keyframes[2] = AnimatableValueKeyframe::Create();
   keyframes[2]->SetOffset(1.0);
   keyframes[2]->SetPropertyValue(CSSPropertyLeft,
-                                 UnknownAnimatableValue(5.0).Get());
+                                 UnknownAnimatableValue(5.0).get());
 
   AnimatableValueKeyframeEffectModel* effect =
       AnimatableValueKeyframeEffectModel::Create(keyframes);
@@ -278,14 +278,14 @@
   AnimatableValueKeyframeVector keyframes(3);
   keyframes[0] = AnimatableValueKeyframe::Create();
   keyframes[0]->SetPropertyValue(CSSPropertyLeft,
-                                 UnknownAnimatableValue(3.0).Get());
+                                 UnknownAnimatableValue(3.0).get());
   keyframes[1] = AnimatableValueKeyframe::Create();
   keyframes[1]->SetOffset(0.5);
   keyframes[1]->SetPropertyValue(CSSPropertyLeft,
-                                 UnknownAnimatableValue(4.0).Get());
+                                 UnknownAnimatableValue(4.0).get());
   keyframes[2] = AnimatableValueKeyframe::Create();
   keyframes[2]->SetPropertyValue(CSSPropertyLeft,
-                                 UnknownAnimatableValue(5.0).Get());
+                                 UnknownAnimatableValue(5.0).get());
 
   AnimatableValueKeyframeEffectModel* effect =
       AnimatableValueKeyframeEffectModel::Create(keyframes);
@@ -303,15 +303,15 @@
   keyframes[0] = AnimatableValueKeyframe::Create();
   keyframes[0]->SetOffset(0.0);
   keyframes[0]->SetPropertyValue(CSSPropertyLeft,
-                                 UnknownAnimatableValue(3.0).Get());
+                                 UnknownAnimatableValue(3.0).get());
   keyframes[1] = AnimatableValueKeyframe::Create();
   keyframes[1]->SetOffset(0.5);
   keyframes[1]->SetPropertyValue(CSSPropertyLeft,
-                                 UnknownAnimatableValue(4.0).Get());
+                                 UnknownAnimatableValue(4.0).get());
   keyframes[2] = AnimatableValueKeyframe::Create();
   keyframes[2]->SetOffset(1.0);
   keyframes[2]->SetPropertyValue(CSSPropertyLeft,
-                                 UnknownAnimatableValue(5.0).Get());
+                                 UnknownAnimatableValue(5.0).get());
 
   AnimatableValueKeyframeEffectModel* effect =
       AnimatableValueKeyframeEffectModel::Create(keyframes);
@@ -329,39 +329,39 @@
   keyframes[0] = AnimatableValueKeyframe::Create();
   keyframes[0]->SetOffset(0.0);
   keyframes[0]->SetPropertyValue(CSSPropertyLeft,
-                                 UnknownAnimatableValue(0.0).Get());
+                                 UnknownAnimatableValue(0.0).get());
   keyframes[1] = AnimatableValueKeyframe::Create();
   keyframes[1]->SetOffset(0.1);
   keyframes[1]->SetPropertyValue(CSSPropertyLeft,
-                                 UnknownAnimatableValue(1.0).Get());
+                                 UnknownAnimatableValue(1.0).get());
   keyframes[2] = AnimatableValueKeyframe::Create();
   keyframes[2]->SetOffset(0.1);
   keyframes[2]->SetPropertyValue(CSSPropertyLeft,
-                                 UnknownAnimatableValue(2.0).Get());
+                                 UnknownAnimatableValue(2.0).get());
   keyframes[3] = AnimatableValueKeyframe::Create();
   keyframes[3]->SetOffset(0.5);
   keyframes[3]->SetPropertyValue(CSSPropertyLeft,
-                                 UnknownAnimatableValue(3.0).Get());
+                                 UnknownAnimatableValue(3.0).get());
   keyframes[4] = AnimatableValueKeyframe::Create();
   keyframes[4]->SetOffset(0.5);
   keyframes[4]->SetPropertyValue(CSSPropertyLeft,
-                                 UnknownAnimatableValue(4.0).Get());
+                                 UnknownAnimatableValue(4.0).get());
   keyframes[5] = AnimatableValueKeyframe::Create();
   keyframes[5]->SetOffset(0.5);
   keyframes[5]->SetPropertyValue(CSSPropertyLeft,
-                                 UnknownAnimatableValue(5.0).Get());
+                                 UnknownAnimatableValue(5.0).get());
   keyframes[6] = AnimatableValueKeyframe::Create();
   keyframes[6]->SetOffset(0.9);
   keyframes[6]->SetPropertyValue(CSSPropertyLeft,
-                                 UnknownAnimatableValue(6.0).Get());
+                                 UnknownAnimatableValue(6.0).get());
   keyframes[7] = AnimatableValueKeyframe::Create();
   keyframes[7]->SetOffset(0.9);
   keyframes[7]->SetPropertyValue(CSSPropertyLeft,
-                                 UnknownAnimatableValue(7.0).Get());
+                                 UnknownAnimatableValue(7.0).get());
   keyframes[8] = AnimatableValueKeyframe::Create();
   keyframes[8]->SetOffset(1.0);
   keyframes[8]->SetPropertyValue(CSSPropertyLeft,
-                                 UnknownAnimatableValue(7.0).Get());
+                                 UnknownAnimatableValue(7.0).get());
 
   AnimatableValueKeyframeEffectModel* effect =
       AnimatableValueKeyframeEffectModel::Create(keyframes);
@@ -388,11 +388,11 @@
   keyframes[0] = AnimatableValueKeyframe::Create();
   keyframes[0]->SetOffset(0.0);
   keyframes[0]->SetPropertyValue(CSSPropertyLeft,
-                                 AnimatableDouble::Create(3.0).Get());
+                                 AnimatableDouble::Create(3.0).get());
   keyframes[1] = AnimatableValueKeyframe::Create();
   keyframes[1]->SetOffset(1.0);
   keyframes[1]->SetPropertyValue(CSSPropertyLeft,
-                                 AnimatableDouble::Create(5.0).Get());
+                                 AnimatableDouble::Create(5.0).get());
   keyframes[1]->SetComposite(EffectModel::kCompositeAdd);
 
   AnimatableValueKeyframeEffectModel* effect =
@@ -407,15 +407,15 @@
   keyframes[0] = AnimatableValueKeyframe::Create();
   keyframes[0]->SetOffset(0.0);
   keyframes[0]->SetPropertyValue(CSSPropertyLeft,
-                                 UnknownAnimatableValue(3.0).Get());
+                                 UnknownAnimatableValue(3.0).get());
   keyframes[0]->SetPropertyValue(CSSPropertyRight,
-                                 UnknownAnimatableValue(4.0).Get());
+                                 UnknownAnimatableValue(4.0).get());
   keyframes[1] = AnimatableValueKeyframe::Create();
   keyframes[1]->SetOffset(1.0);
   keyframes[1]->SetPropertyValue(CSSPropertyLeft,
-                                 UnknownAnimatableValue(5.0).Get());
+                                 UnknownAnimatableValue(5.0).get());
   keyframes[1]->SetPropertyValue(CSSPropertyRight,
-                                 UnknownAnimatableValue(6.0).Get());
+                                 UnknownAnimatableValue(6.0).get());
 
   AnimatableValueKeyframeEffectModel* effect =
       AnimatableValueKeyframeEffectModel::Create(keyframes);
@@ -464,16 +464,16 @@
   keyframes[0] = AnimatableValueKeyframe::Create();
   keyframes[0]->SetOffset(0.0);
   keyframes[0]->SetPropertyValue(CSSPropertyLeft,
-                                 AnimatableDouble::Create(1.0).Get());
+                                 AnimatableDouble::Create(1.0).get());
   keyframes[0]->SetComposite(EffectModel::kCompositeAdd);
   keyframes[1] = AnimatableValueKeyframe::Create();
   keyframes[1]->SetOffset(0.5);
   keyframes[1]->SetPropertyValue(CSSPropertyLeft,
-                                 AnimatableDouble::Create(1.0).Get());
+                                 AnimatableDouble::Create(1.0).get());
   keyframes[2] = AnimatableValueKeyframe::Create();
   keyframes[2]->SetOffset(1.0);
   keyframes[2]->SetPropertyValue(CSSPropertyLeft,
-                                 AnimatableDouble::Create(1.0).Get());
+                                 AnimatableDouble::Create(1.0).get());
 
   AnimatableValueKeyframeEffectModel* effect =
       AnimatableValueKeyframeEffectModel::Create(keyframes);
diff --git a/third_party/WebKit/Source/core/animation/KeyframeEffectTest.cpp b/third_party/WebKit/Source/core/animation/KeyframeEffectTest.cpp
index bcf3d75..3bd1dde3 100644
--- a/third_party/WebKit/Source/core/animation/KeyframeEffectTest.cpp
+++ b/third_party/WebKit/Source/core/animation/KeyframeEffectTest.cpp
@@ -51,9 +51,9 @@
     NonThrowableExceptionState exception_state;
     return KeyframeEffect::Create(
         nullptr, element,
-        DictionarySequenceOrDictionary::fromDictionarySequence(
+        DictionarySequenceOrDictionary::FromDictionarySequence(
             keyframe_dictionary_vector),
-        UnrestrictedDoubleOrKeyframeEffectOptions::fromUnrestrictedDouble(
+        UnrestrictedDoubleOrKeyframeEffectOptions::FromUnrestrictedDouble(
             timing_input),
         exception_state);
   }
@@ -64,9 +64,9 @@
     NonThrowableExceptionState exception_state;
     return KeyframeEffect::Create(
         nullptr, element,
-        DictionarySequenceOrDictionary::fromDictionarySequence(
+        DictionarySequenceOrDictionary::FromDictionarySequence(
             keyframe_dictionary_vector),
-        UnrestrictedDoubleOrKeyframeEffectOptions::fromKeyframeEffectOptions(
+        UnrestrictedDoubleOrKeyframeEffectOptions::FromKeyframeEffectOptions(
             timing_input),
         exception_state);
   }
@@ -76,7 +76,7 @@
     NonThrowableExceptionState exception_state;
     return KeyframeEffect::Create(
         nullptr, element,
-        DictionarySequenceOrDictionary::fromDictionarySequence(
+        DictionarySequenceOrDictionary::FromDictionarySequence(
             keyframe_dictionary_vector),
         exception_state);
   }
@@ -124,10 +124,10 @@
   EXPECT_EQ(1, keyframes[1]->Offset());
 
   const CSSValue& keyframe1_width =
-      ToStringKeyframe(keyframes[0].Get())
+      ToStringKeyframe(keyframes[0].get())
           ->CssPropertyValue(PropertyHandle(CSSPropertyWidth));
   const CSSValue& keyframe2_width =
-      ToStringKeyframe(keyframes[1].Get())
+      ToStringKeyframe(keyframes[1].get())
           ->CssPropertyValue(PropertyHandle(CSSPropertyWidth));
 
   EXPECT_EQ("100px", keyframe1_width.CssText());
@@ -136,7 +136,7 @@
   EXPECT_EQ(*(CubicBezierTimingFunction::Preset(
                 CubicBezierTimingFunction::EaseType::EASE_IN_OUT)),
             keyframes[0]->Easing());
-  EXPECT_EQ(*(CubicBezierTimingFunction::Create(1, 1, 0.3, 0.3).Get()),
+  EXPECT_EQ(*(CubicBezierTimingFunction::Create(1, 1, 0.3, 0.3).get()),
             keyframes[1]->Easing());
 }
 
@@ -215,9 +215,9 @@
       animation_with_duration->timing();
   UnrestrictedDoubleOrString duration;
   specified_with_duration->duration(duration);
-  EXPECT_TRUE(duration.isUnrestrictedDouble());
-  EXPECT_EQ(2.5, duration.getAsUnrestrictedDouble());
-  EXPECT_FALSE(duration.isString());
+  EXPECT_TRUE(duration.IsUnrestrictedDouble());
+  EXPECT_EQ(2.5, duration.GetAsUnrestrictedDouble());
+  EXPECT_FALSE(duration.IsString());
 
   v8::Local<v8::Object> timing_input_no_duration =
       v8::Object::New(scope.GetIsolate());
@@ -234,9 +234,9 @@
       animation_no_duration->timing();
   UnrestrictedDoubleOrString duration2;
   specified_no_duration->duration(duration2);
-  EXPECT_FALSE(duration2.isUnrestrictedDouble());
-  EXPECT_TRUE(duration2.isString());
-  EXPECT_EQ("auto", duration2.getAsString());
+  EXPECT_FALSE(duration2.IsUnrestrictedDouble());
+  EXPECT_TRUE(duration2.IsString());
+  EXPECT_EQ("auto", duration2.GetAsString());
 }
 
 TEST_F(AnimationKeyframeEffectV8Test, SpecifiedSetters) {
@@ -305,19 +305,19 @@
 
   UnrestrictedDoubleOrString duration;
   specified->duration(duration);
-  EXPECT_FALSE(duration.isUnrestrictedDouble());
-  EXPECT_TRUE(duration.isString());
-  EXPECT_EQ("auto", duration.getAsString());
+  EXPECT_FALSE(duration.IsUnrestrictedDouble());
+  EXPECT_TRUE(duration.IsString());
+  EXPECT_EQ("auto", duration.GetAsString());
 
   UnrestrictedDoubleOrString in_duration;
-  in_duration.setUnrestrictedDouble(2.5);
+  in_duration.SetUnrestrictedDouble(2.5);
   specified->setDuration(in_duration, exception_state);
   ASSERT_FALSE(exception_state.HadException());
   UnrestrictedDoubleOrString duration2;
   specified->duration(duration2);
-  EXPECT_TRUE(duration2.isUnrestrictedDouble());
-  EXPECT_EQ(2.5, duration2.getAsUnrestrictedDouble());
-  EXPECT_FALSE(duration2.isString());
+  EXPECT_TRUE(duration2.IsUnrestrictedDouble());
+  EXPECT_EQ(2.5, duration2.GetAsUnrestrictedDouble());
+  EXPECT_FALSE(duration2.IsString());
 }
 
 TEST_F(KeyframeEffectTest, TimeToEffectChange) {
diff --git a/third_party/WebKit/Source/core/animation/LegacyStyleInterpolation.cpp b/third_party/WebKit/Source/core/animation/LegacyStyleInterpolation.cpp
index 1190f7d..9d2a8d8c 100644
--- a/third_party/WebKit/Source/core/animation/LegacyStyleInterpolation.cpp
+++ b/third_party/WebKit/Source/core/animation/LegacyStyleInterpolation.cpp
@@ -53,7 +53,7 @@
 
 void LegacyStyleInterpolation::Apply(StyleResolverState& state) const {
   AnimatedStyleBuilder::ApplyProperty(Id(), *state.Style(),
-                                      CurrentValue().Get());
+                                      CurrentValue().get());
 }
 
 void LegacyStyleInterpolation::Interpolate(int iteration, double fraction) {
diff --git a/third_party/WebKit/Source/core/animation/LengthInterpolationFunctions.cpp b/third_party/WebKit/Source/core/animation/LengthInterpolationFunctions.cpp
index 4fa7707..2902e65 100644
--- a/third_party/WebKit/Source/core/animation/LengthInterpolationFunctions.cpp
+++ b/third_party/WebKit/Source/core/animation/LengthInterpolationFunctions.cpp
@@ -120,8 +120,8 @@
     InterpolationValue&& end) {
   return PairwiseInterpolationValue(
       std::move(start.interpolable_value), std::move(end.interpolable_value),
-      CSSLengthNonInterpolableValue::Merge(start.non_interpolable_value.Get(),
-                                           end.non_interpolable_value.Get()));
+      CSSLengthNonInterpolableValue::Merge(start.non_interpolable_value.get(),
+                                           end.non_interpolable_value.get()));
 }
 
 bool LengthInterpolationFunctions::NonInterpolableValuesAreCompatible(
@@ -141,7 +141,7 @@
   underlying_interpolable_value->ScaleAndAdd(underlying_fraction,
                                              interpolable_value);
   underlying_non_interpolable_value = CSSLengthNonInterpolableValue::Merge(
-      underlying_non_interpolable_value.Get(), non_interpolable_value);
+      underlying_non_interpolable_value.get(), non_interpolable_value);
 }
 
 void LengthInterpolationFunctions::SubtractFromOneHundredPercent(
diff --git a/third_party/WebKit/Source/core/animation/ListInterpolationFunctions.h b/third_party/WebKit/Source/core/animation/ListInterpolationFunctions.h
index 0f720ff..e58c7d58 100644
--- a/third_party/WebKit/Source/core/animation/ListInterpolationFunctions.h
+++ b/third_party/WebKit/Source/core/animation/ListInterpolationFunctions.h
@@ -70,9 +70,9 @@
 
   size_t length() const { return list_.size(); }
   const NonInterpolableValue* Get(size_t index) const {
-    return list_[index].Get();
+    return list_[index].get();
   }
-  NonInterpolableValue* Get(size_t index) { return list_[index].Get(); }
+  NonInterpolableValue* Get(size_t index) { return list_[index].get(); }
   RefPtr<NonInterpolableValue>& GetMutable(size_t index) {
     return list_[index];
   }
diff --git a/third_party/WebKit/Source/core/animation/PathInterpolationFunctions.cpp b/third_party/WebKit/Source/core/animation/PathInterpolationFunctions.cpp
index 6cd4395..1bb4787 100644
--- a/third_party/WebKit/Source/core/animation/PathInterpolationFunctions.cpp
+++ b/third_party/WebKit/Source/core/animation/PathInterpolationFunctions.cpp
@@ -128,7 +128,7 @@
                                   ->CloneAndZero());
   result->Set(kPathNeutralIndex, InterpolableNumber::Create(1));
   return InterpolationValue(std::move(result),
-                            underlying.non_interpolable_value.Get());
+                            underlying.non_interpolable_value.get());
 }
 
 static bool PathSegTypesMatch(const Vector<SVGPathSegType>& a,
@@ -183,7 +183,7 @@
   underlying_value_owner.MutableValue().interpolable_value->ScaleAndAdd(
       neutral_component, *value.interpolable_value);
   underlying_value_owner.MutableValue().non_interpolable_value =
-      value.non_interpolable_value.Get();
+      value.non_interpolable_value.get();
 }
 
 std::unique_ptr<SVGPathByteStream> PathInterpolationFunctions::AppliedValue(
diff --git a/third_party/WebKit/Source/core/animation/PrimitiveInterpolation.h b/third_party/WebKit/Source/core/animation/PrimitiveInterpolation.h
index 4dc1708..db803c7e 100644
--- a/third_party/WebKit/Source/core/animation/PrimitiveInterpolation.h
+++ b/third_party/WebKit/Source/core/animation/PrimitiveInterpolation.h
@@ -79,7 +79,7 @@
       std::unique_ptr<TypedInterpolationValue>& result) const final {
     DCHECK(result);
     DCHECK_EQ(&result->GetType(), &type_);
-    DCHECK_EQ(result->GetNonInterpolableValue(), non_interpolable_value_.Get());
+    DCHECK_EQ(result->GetNonInterpolableValue(), non_interpolable_value_.get());
     start_->Interpolate(*end_, fraction,
                         *result->MutableValue().interpolable_value);
   }
diff --git a/third_party/WebKit/Source/core/animation/ScrollTimeline.cpp b/third_party/WebKit/Source/core/animation/ScrollTimeline.cpp
index 37e0a9dc..352d37b 100644
--- a/third_party/WebKit/Source/core/animation/ScrollTimeline.cpp
+++ b/third_party/WebKit/Source/core/animation/ScrollTimeline.cpp
@@ -40,14 +40,14 @@
   }
 
   // TODO(smcgruer): Support 'auto' value.
-  if (options.timeRange().isScrollTimelineAutoKeyword()) {
+  if (options.timeRange().IsScrollTimelineAutoKeyword()) {
     exception_state.ThrowDOMException(
         kNotSupportedError, "'auto' value for timeRange not yet supported");
     return nullptr;
   }
 
   return new ScrollTimeline(document, scroll_source, orientation,
-                            options.timeRange().getAsDouble());
+                            options.timeRange().GetAsDouble());
 }
 
 ScrollTimeline::ScrollTimeline(const Document& document,
@@ -138,7 +138,7 @@
 }
 
 void ScrollTimeline::timeRange(DoubleOrScrollTimelineAutoKeyword& result) {
-  result.setDouble(time_range_);
+  result.SetDouble(time_range_);
 }
 
 DEFINE_TRACE(ScrollTimeline) {
diff --git a/third_party/WebKit/Source/core/animation/ShadowInterpolationFunctions.cpp b/third_party/WebKit/Source/core/animation/ShadowInterpolationFunctions.cpp
index c0dcdf0..1539956 100644
--- a/third_party/WebKit/Source/core/animation/ShadowInterpolationFunctions.cpp
+++ b/third_party/WebKit/Source/core/animation/ShadowInterpolationFunctions.cpp
@@ -57,8 +57,8 @@
 PairwiseInterpolationValue ShadowInterpolationFunctions::MaybeMergeSingles(
     InterpolationValue&& start,
     InterpolationValue&& end) {
-  if (!NonInterpolableValuesAreCompatible(start.non_interpolable_value.Get(),
-                                          end.non_interpolable_value.Get()))
+  if (!NonInterpolableValuesAreCompatible(start.non_interpolable_value.get(),
+                                          end.non_interpolable_value.get()))
     return nullptr;
   return PairwiseInterpolationValue(std::move(start.interpolable_value),
                                     std::move(end.interpolable_value),
@@ -155,7 +155,7 @@
     const InterpolableValue& interpolable_value,
     const NonInterpolableValue* non_interpolable_value) {
   DCHECK(NonInterpolableValuesAreCompatible(
-      underlying_non_interpolable_value.Get(), non_interpolable_value));
+      underlying_non_interpolable_value.get(), non_interpolable_value));
   InterpolableList& underlying_interpolable_list =
       ToInterpolableList(*underlying_interpolable_value);
   const InterpolableList& interpolable_list =
diff --git a/third_party/WebKit/Source/core/animation/SizeInterpolationFunctions.cpp b/third_party/WebKit/Source/core/animation/SizeInterpolationFunctions.cpp
index 0921b32..994768b 100644
--- a/third_party/WebKit/Source/core/animation/SizeInterpolationFunctions.cpp
+++ b/third_party/WebKit/Source/core/animation/SizeInterpolationFunctions.cpp
@@ -32,7 +32,7 @@
 
   const NonInterpolableValue* LengthNonInterpolableValue() const {
     DCHECK(!IsKeyword());
-    return length_non_interpolable_value_.Get();
+    return length_non_interpolable_value_.get();
   }
   RefPtr<NonInterpolableValue>& LengthNonInterpolableValue() {
     DCHECK(!IsKeyword());
@@ -126,8 +126,8 @@
 PairwiseInterpolationValue SizeInterpolationFunctions::MaybeMergeSingles(
     InterpolationValue&& start,
     InterpolationValue&& end) {
-  if (!NonInterpolableValuesAreCompatible(start.non_interpolable_value.Get(),
-                                          end.non_interpolable_value.Get()))
+  if (!NonInterpolableValuesAreCompatible(start.non_interpolable_value.get(),
+                                          end.non_interpolable_value.get()))
     return nullptr;
   return PairwiseInterpolationValue(std::move(start.interpolable_value),
                                     std::move(end.interpolable_value),
diff --git a/third_party/WebKit/Source/core/animation/StringKeyframe.h b/third_party/WebKit/Source/core/animation/StringKeyframe.h
index 53fe63e..1aa2fdc0 100644
--- a/third_party/WebKit/Source/core/animation/StringKeyframe.h
+++ b/third_party/WebKit/Source/core/animation/StringKeyframe.h
@@ -79,7 +79,7 @@
                                  const ComputedStyle& base_style,
                                  const ComputedStyle* parent_style) const final;
     const AnimatableValue* GetAnimatableValue() const final {
-      return animatable_value_cache_.Get();
+      return animatable_value_cache_.get();
     }
 
     bool IsNeutral() const final { return !value_; }
diff --git a/third_party/WebKit/Source/core/animation/Timing.h b/third_party/WebKit/Source/core/animation/Timing.h
index 1505927..7e4ab68 100644
--- a/third_party/WebKit/Source/core/animation/Timing.h
+++ b/third_party/WebKit/Source/core/animation/Timing.h
@@ -87,7 +87,7 @@
             iteration_duration == other.iteration_duration) &&
            playback_rate == other.playback_rate &&
            direction == other.direction &&
-           DataEquivalent(timing_function.Get(), other.timing_function.Get());
+           DataEquivalent(timing_function.get(), other.timing_function.get());
   }
 
   bool operator!=(const Timing& other) const { return !(*this == other); }
diff --git a/third_party/WebKit/Source/core/animation/TimingInput.cpp b/third_party/WebKit/Source/core/animation/TimingInput.cpp
index f2b3930..f48203d6 100644
--- a/third_party/WebKit/Source/core/animation/TimingInput.cpp
+++ b/third_party/WebKit/Source/core/animation/TimingInput.cpp
@@ -69,8 +69,8 @@
     ExceptionState& exception_state) {
   static const char* error_message = "duration must be non-negative or auto.";
 
-  if (iteration_duration.isUnrestrictedDouble()) {
-    double duration_number = iteration_duration.getAsUnrestrictedDouble();
+  if (iteration_duration.IsUnrestrictedDouble()) {
+    double duration_number = iteration_duration.GetAsUnrestrictedDouble();
     if (std::isnan(duration_number) || duration_number < 0) {
       exception_state.ThrowTypeError(error_message);
       return false;
@@ -79,7 +79,7 @@
     return true;
   }
 
-  if (iteration_duration.getAsString() != "auto") {
+  if (iteration_duration.GetAsString() != "auto") {
     exception_state.ThrowTypeError(error_message);
     return false;
   }
@@ -126,13 +126,13 @@
     Timing& timing_output,
     Document* document,
     ExceptionState& exception_state) {
-  if (options.isKeyframeEffectOptions()) {
-    return Convert(options.getAsKeyframeEffectOptions(), timing_output,
+  if (options.IsKeyframeEffectOptions()) {
+    return Convert(options.GetAsKeyframeEffectOptions(), timing_output,
                    document, exception_state);
-  } else if (options.isUnrestrictedDouble()) {
-    return Convert(options.getAsUnrestrictedDouble(), timing_output,
+  } else if (options.IsUnrestrictedDouble()) {
+    return Convert(options.GetAsUnrestrictedDouble(), timing_output,
                    exception_state);
-  } else if (options.isNull()) {
+  } else if (options.IsNull()) {
     return true;
   }
   NOTREACHED();
@@ -144,13 +144,13 @@
     Timing& timing_output,
     Document* document,
     ExceptionState& exception_state) {
-  if (options.isKeyframeAnimationOptions()) {
-    return Convert(options.getAsKeyframeAnimationOptions(), timing_output,
+  if (options.IsKeyframeAnimationOptions()) {
+    return Convert(options.GetAsKeyframeAnimationOptions(), timing_output,
                    document, exception_state);
-  } else if (options.isUnrestrictedDouble()) {
-    return Convert(options.getAsUnrestrictedDouble(), timing_output,
+  } else if (options.IsUnrestrictedDouble()) {
+    return Convert(options.GetAsUnrestrictedDouble(), timing_output,
                    exception_state);
-  } else if (options.isNull()) {
+  } else if (options.IsNull()) {
     return true;
   }
   NOTREACHED();
@@ -204,7 +204,7 @@
   DCHECK(timing_output == Timing::Defaults());
   return SetIterationDuration(
       timing_output,
-      UnrestrictedDoubleOrString::fromUnrestrictedDouble(duration),
+      UnrestrictedDoubleOrString::FromUnrestrictedDouble(duration),
       exception_state);
 }
 
diff --git a/third_party/WebKit/Source/core/animation/TransitionInterpolation.cpp b/third_party/WebKit/Source/core/animation/TransitionInterpolation.cpp
index 29875ba3..499d679 100644
--- a/third_party/WebKit/Source/core/animation/TransitionInterpolation.cpp
+++ b/third_party/WebKit/Source/core/animation/TransitionInterpolation.cpp
@@ -37,12 +37,12 @@
 NonInterpolableValue* TransitionInterpolation::CurrentNonInterpolableValue()
     const {
   if (cached_fraction_ == 0) {
-    return start_.non_interpolable_value.Get();
+    return start_.non_interpolable_value.get();
   }
   if (cached_fraction_ == 1) {
-    return end_.non_interpolable_value.Get();
+    return end_.non_interpolable_value.get();
   }
-  return merge_.non_interpolable_value.Get();
+  return merge_.non_interpolable_value.get();
 }
 
 void TransitionInterpolation::Apply(StyleResolverState& state) const {
@@ -60,8 +60,8 @@
 
 RefPtr<AnimatableValue>
 TransitionInterpolation::GetInterpolatedCompositorValue() const {
-  return AnimatableValue::Interpolate(compositor_start_.Get(),
-                                      compositor_end_.Get(), cached_fraction_);
+  return AnimatableValue::Interpolate(compositor_start_.get(),
+                                      compositor_end_.get(), cached_fraction_);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/animation/TransitionKeyframe.cpp b/third_party/WebKit/Source/core/animation/TransitionKeyframe.cpp
index d8eafab7..92b6784 100644
--- a/third_party/WebKit/Source/core/animation/TransitionKeyframe.cpp
+++ b/third_party/WebKit/Source/core/animation/TransitionKeyframe.cpp
@@ -15,7 +15,7 @@
     RefPtr<AnimatableValue> compositor_value) {
   DCHECK_EQ(
       CompositorAnimations::IsCompositableProperty(property_.CssProperty()),
-      static_cast<bool>(compositor_value.Get()));
+      static_cast<bool>(compositor_value.get()));
   compositor_value_ = std::move(compositor_value);
 }
 
diff --git a/third_party/WebKit/Source/core/animation/TransitionKeyframe.h b/third_party/WebKit/Source/core/animation/TransitionKeyframe.h
index 5524e104..b9e1dec 100644
--- a/third_party/WebKit/Source/core/animation/TransitionKeyframe.h
+++ b/third_party/WebKit/Source/core/animation/TransitionKeyframe.h
@@ -37,7 +37,7 @@
     }
 
     const AnimatableValue* GetAnimatableValue() const final {
-      return compositor_value_.Get();
+      return compositor_value_.get();
     }
 
     bool IsNeutral() const final { return false; }
diff --git a/third_party/WebKit/Source/core/animation/TypedInterpolationValue.h b/third_party/WebKit/Source/core/animation/TypedInterpolationValue.h
index cba06db..a941c19a 100644
--- a/third_party/WebKit/Source/core/animation/TypedInterpolationValue.h
+++ b/third_party/WebKit/Source/core/animation/TypedInterpolationValue.h
@@ -37,7 +37,7 @@
     return *value_.interpolable_value;
   }
   const NonInterpolableValue* GetNonInterpolableValue() const {
-    return value_.non_interpolable_value.Get();
+    return value_.non_interpolable_value.get();
   }
   const InterpolationValue& Value() const { return value_; }
 
diff --git a/third_party/WebKit/Source/core/animation/animatable/AnimatableValueKeyframe.cpp b/third_party/WebKit/Source/core/animation/animatable/AnimatableValueKeyframe.cpp
index 8589f03..2d16c20 100644
--- a/third_party/WebKit/Source/core/animation/animatable/AnimatableValueKeyframe.cpp
+++ b/third_party/WebKit/Source/core/animation/animatable/AnimatableValueKeyframe.cpp
@@ -14,7 +14,7 @@
   for (PropertyValueMap::const_iterator iter =
            copy_from.property_values_.begin();
        iter != copy_from.property_values_.end(); ++iter)
-    SetPropertyValue(iter->key, iter->value.Get());
+    SetPropertyValue(iter->key, iter->value.get());
 }
 
 PropertyHandleSet AnimatableValueKeyframe::Properties() const {
diff --git a/third_party/WebKit/Source/core/animation/animatable/AnimatableValueKeyframe.h b/third_party/WebKit/Source/core/animation/animatable/AnimatableValueKeyframe.h
index 772b1ee85..270837e 100644
--- a/third_party/WebKit/Source/core/animation/animatable/AnimatableValueKeyframe.h
+++ b/third_party/WebKit/Source/core/animation/animatable/AnimatableValueKeyframe.h
@@ -42,9 +42,9 @@
           offset, std::move(easing), std::move(value), composite));
     }
 
-    AnimatableValue* Value() const { return value_.Get(); }
+    AnimatableValue* Value() const { return value_.get(); }
     const AnimatableValue* GetAnimatableValue() const final {
-      return value_.Get();
+      return value_.get();
     }
 
     bool IsNeutral() const final { return false; }
diff --git a/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp b/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp
index 6c1bad6..3963673 100644
--- a/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp
+++ b/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp
@@ -129,7 +129,7 @@
     // The last keyframe specified at a given offset is used.
     for (size_t j = 1; j < offsets.size(); ++j) {
       keyframes.push_back(
-          ToStringKeyframe(keyframe->CloneWithOffset(offsets[j]).Get()));
+          ToStringKeyframe(keyframe->CloneWithOffset(offsets[j]).get()));
     }
   }
 
@@ -375,7 +375,7 @@
               *InertEffect::Create(
                   CreateKeyframeEffectModel(resolver, animating_element,
                                             element, &style, parent_style, name,
-                                            keyframe_timing_function.Get(), i),
+                                            keyframe_timing_function.get(), i),
                   timing, is_paused, animation->UnlimitedCurrentTimeInternal()),
               specified_timing, keyframes_rule);
         }
@@ -391,7 +391,7 @@
             *InertEffect::Create(
                 CreateKeyframeEffectModel(resolver, animating_element, element,
                                           &style, parent_style, name,
-                                          keyframe_timing_function.Get(), i),
+                                          keyframe_timing_function.get(), i),
                 timing, is_paused, 0),
             specified_timing, keyframes_rule);
       }
@@ -584,9 +584,9 @@
       const KeyframeVector& frames = old_effect->GetFrames();
 
       TransitionKeyframeVector new_frames;
-      new_frames.push_back(ToTransitionKeyframe(frames[0]->Clone().Get()));
-      new_frames.push_back(ToTransitionKeyframe(frames[1]->Clone().Get()));
-      new_frames.push_back(ToTransitionKeyframe(frames[2]->Clone().Get()));
+      new_frames.push_back(ToTransitionKeyframe(frames[0]->Clone().get()));
+      new_frames.push_back(ToTransitionKeyframe(frames[1]->Clone().get()));
+      new_frames.push_back(ToTransitionKeyframe(frames[2]->Clone().get()));
 
       InertEffect* inert_animation_for_sampling = InertEffect::Create(
           old_animation->Model(), old_animation->SpecifiedTiming(), false,
@@ -751,7 +751,7 @@
     const double interrupted_progress =
         interrupted_transition->animation->effect()->Progress();
     if (!std::isnan(interrupted_progress)) {
-      reversing_adjusted_start_value = interrupted_transition->to.Get();
+      reversing_adjusted_start_value = interrupted_transition->to.get();
       reversing_shortening_factor =
           clampTo((interrupted_progress *
                    interrupted_transition->reversing_shortening_factor) +
diff --git a/third_party/WebKit/Source/core/clipboard/ClipboardPromise.cpp b/third_party/WebKit/Source/core/clipboard/ClipboardPromise.cpp
index 4a0739a..8218bc1 100644
--- a/third_party/WebKit/Source/core/clipboard/ClipboardPromise.cpp
+++ b/third_party/WebKit/Source/core/clipboard/ClipboardPromise.cpp
@@ -60,7 +60,7 @@
   // TODO(garykac): Replace MiscPlatformAPI with TaskType specific to clipboard.
   return TaskRunnerHelper::Get(TaskType::kMiscPlatformAPI,
                                GetExecutionContext())
-      .Get();
+      .get();
 }
 
 // TODO(garykac): This currently only handles plain text.
diff --git a/third_party/WebKit/Source/core/clipboard/DataTransfer.cpp b/third_party/WebKit/Source/core/clipboard/DataTransfer.cpp
index 2c53e6a..a30d7d27 100644
--- a/third_party/WebKit/Source/core/clipboard/DataTransfer.cpp
+++ b/third_party/WebKit/Source/core/clipboard/DataTransfer.cpp
@@ -327,7 +327,7 @@
     return;
 
   IntPoint location(x, y);
-  if (isHTMLImageElement(*image) && !image->isConnected())
+  if (IsHTMLImageElement(*image) && !image->isConnected())
     SetDragImageResource(toHTMLImageElement(*image).CachedImage(), location);
   else
     SetDragImageElement(image, location);
@@ -407,7 +407,7 @@
   float screen_device_scale_factor =
       frame.GetPage()->GetChromeClient().GetScreenInfo().device_scale_factor;
 
-  return DragImage::Create(image.Get(), image_orientation,
+  return DragImage::Create(image.get(), image_orientation,
                            screen_device_scale_factor, kInterpolationHigh,
                            opacity);
 }
diff --git a/third_party/WebKit/Source/core/css/BUILD.gn b/third_party/WebKit/Source/core/css/BUILD.gn
index 63b26d9..751e3507 100644
--- a/third_party/WebKit/Source/core/css/BUILD.gn
+++ b/third_party/WebKit/Source/core/css/BUILD.gn
@@ -371,10 +371,12 @@
     "parser/CSSParserObserver.h",
     "parser/CSSParserObserverWrapper.cpp",
     "parser/CSSParserObserverWrapper.h",
+    "parser/CSSParserScopedTokenBuffer.h",
     "parser/CSSParserSelector.cpp",
     "parser/CSSParserSelector.h",
     "parser/CSSParserToken.cpp",
     "parser/CSSParserToken.h",
+    "parser/CSSParserTokenBuffer.h",
     "parser/CSSParserTokenRange.cpp",
     "parser/CSSParserTokenRange.h",
     "parser/CSSParserTokenStream.cpp",
diff --git a/third_party/WebKit/Source/core/css/BinaryDataFontFaceSource.cpp b/third_party/WebKit/Source/core/css/BinaryDataFontFaceSource.cpp
index 84a3191..2439335 100644
--- a/third_party/WebKit/Source/core/css/BinaryDataFontFaceSource.cpp
+++ b/third_party/WebKit/Source/core/css/BinaryDataFontFaceSource.cpp
@@ -19,7 +19,7 @@
 BinaryDataFontFaceSource::~BinaryDataFontFaceSource() {}
 
 bool BinaryDataFontFaceSource::IsValid() const {
-  return custom_platform_data_.Get();
+  return custom_platform_data_.get();
 }
 
 RefPtr<SimpleFontData> BinaryDataFontFaceSource::CreateFontData(
diff --git a/third_party/WebKit/Source/core/css/CSSCalculationValueTest.cpp b/third_party/WebKit/Source/core/css/CSSCalculationValueTest.cpp
index df605cf..8d20361 100644
--- a/third_party/WebKit/Source/core/css/CSSCalculationValueTest.cpp
+++ b/third_party/WebKit/Source/core/css/CSSCalculationValueTest.cpp
@@ -79,7 +79,7 @@
 TEST(CSSCalculationValue, AccumulatePixelsAndPercent) {
   RefPtr<ComputedStyle> style = ComputedStyle::Create();
   style->SetEffectiveZoom(5);
-  CSSToLengthConversionData conversion_data(style.Get(), style.Get(),
+  CSSToLengthConversionData conversion_data(style.get(), style.get(),
                                             LayoutViewItem(nullptr),
                                             style->EffectiveZoom());
 
diff --git a/third_party/WebKit/Source/core/css/CSSCustomPropertyDeclaration.h b/third_party/WebKit/Source/core/css/CSSCustomPropertyDeclaration.h
index d1ce350d..fc622dd 100644
--- a/third_party/WebKit/Source/core/css/CSSCustomPropertyDeclaration.h
+++ b/third_party/WebKit/Source/core/css/CSSCustomPropertyDeclaration.h
@@ -25,7 +25,7 @@
   }
 
   const AtomicString& GetName() const { return name_; }
-  CSSVariableData* Value() const { return value_.Get(); }
+  CSSVariableData* Value() const { return value_.get(); }
 
   bool IsInherit(bool is_inherited_property) const {
     return value_id_ == CSSValueInherit ||
diff --git a/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.cpp b/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.cpp
index 411e5797..9d2643b2 100644
--- a/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.cpp
+++ b/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.cpp
@@ -38,6 +38,7 @@
 #include "core/html/HTMLHtmlElement.h"
 #include "core/layout/LayoutTheme.h"
 #include "platform/DataResourceHelper.h"
+#include "platform/runtime_enabled_features.h"
 #include "platform/wtf/LeakAnnotations.h"
 
 namespace blink {
@@ -161,9 +162,14 @@
   // FIXME: We should assert that this sheet only contains rules for <video> and
   // <audio>.
   if (!media_controls_style_sheet_ &&
-      (isHTMLVideoElement(element) || isHTMLAudioElement(element))) {
-    String media_rules = GetDataResourceAsASCIIString("mediaControls.css") +
-                         LayoutTheme::GetTheme().ExtraMediaControlsStyleSheet();
+      (IsHTMLVideoElement(element) || IsHTMLAudioElement(element))) {
+    String media_rules;
+    if (RuntimeEnabledFeatures::ModernMediaControlsEnabled()) {
+      media_rules = GetDataResourceAsASCIIString("modernMediaControls.css");
+    } else {
+      media_rules = GetDataResourceAsASCIIString("legacyMediaControls.css") +
+                    LayoutTheme::GetTheme().ExtraMediaControlsStyleSheet();
+    }
     media_controls_style_sheet_ = ParseUASheet(media_rules);
     default_style_->AddRulesFromSheet(MediaControlsStyleSheet(), ScreenEval());
     default_print_style_->AddRulesFromSheet(MediaControlsStyleSheet(),
diff --git a/third_party/WebKit/Source/core/css/CSSFontFace.cpp b/third_party/WebKit/Source/core/css/CSSFontFace.cpp
index aef7708..b68e3d2 100644
--- a/third_party/WebKit/Source/core/css/CSSFontFace.cpp
+++ b/third_party/WebKit/Source/core/css/CSSFontFace.cpp
@@ -53,15 +53,17 @@
     SetLoadStatus(FontFace::kLoading);
 }
 
-void CSSFontFace::FontLoaded(RemoteFontFaceSource* source) {
+void CSSFontFace::FontLoaded(RemoteFontFaceSource* source,
+                             LoadFinishReason reason) {
   if (!IsValid() || source != sources_.front())
     return;
 
   if (LoadStatus() == FontFace::kLoading) {
     if (source->IsValid()) {
       SetLoadStatus(FontFace::kLoaded);
-    } else if (source->GetDisplayPeriod() ==
-               RemoteFontFaceSource::kFailurePeriod) {
+    } else if (reason == LoadFinishReason::WasCancelled ||
+               source->GetDisplayPeriod() ==
+                   RemoteFontFaceSource::kFailurePeriod) {
       sources_.clear();
       SetLoadStatus(FontFace::kError);
     } else {
diff --git a/third_party/WebKit/Source/core/css/CSSFontFace.h b/third_party/WebKit/Source/core/css/CSSFontFace.h
index 9b19d96..94ea3dac 100644
--- a/third_party/WebKit/Source/core/css/CSSFontFace.h
+++ b/third_party/WebKit/Source/core/css/CSSFontFace.h
@@ -68,7 +68,8 @@
   void AddSource(CSSFontFaceSource*);
 
   void DidBeginLoad();
-  void FontLoaded(RemoteFontFaceSource*);
+  enum class LoadFinishReason { WasCancelled, NormalFinish };
+  void FontLoaded(RemoteFontFaceSource*, LoadFinishReason);
   void DidBecomeVisibleFallback(RemoteFontFaceSource*);
 
   RefPtr<SimpleFontData> GetFontData(const FontDescription&);
diff --git a/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp b/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp
index fe707da..22e63151 100644
--- a/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp
@@ -123,21 +123,24 @@
     const ImageResourceObserver& client,
     const Document& document,
     const ComputedStyle& style,
-    const IntSize& size) {
+    const IntSize& container_size,
+    const LayoutSize* logical_size) {
   switch (GetClassType()) {
     case kCrossfadeClass:
-      return ToCSSCrossfadeValue(this)->GetImage(client, document, style, size);
+      return ToCSSCrossfadeValue(this)->GetImage(client, document, style,
+                                                 container_size);
     case kLinearGradientClass:
       return ToCSSLinearGradientValue(this)->GetImage(client, document, style,
-                                                      size);
+                                                      container_size);
     case kPaintClass:
-      return ToCSSPaintValue(this)->GetImage(client, document, style, size);
+      return ToCSSPaintValue(this)->GetImage(client, document, style,
+                                             container_size, logical_size);
     case kRadialGradientClass:
       return ToCSSRadialGradientValue(this)->GetImage(client, document, style,
-                                                      size);
+                                                      container_size);
     case kConicGradientClass:
       return ToCSSConicGradientValue(this)->GetImage(client, document, style,
-                                                     size);
+                                                     container_size);
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h b/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h
index a0996c4..2c55688c 100644
--- a/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h
+++ b/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h
@@ -29,6 +29,7 @@
 #include "core/CoreExport.h"
 #include "core/css/CSSValue.h"
 #include "platform/geometry/IntSizeHash.h"
+#include "platform/geometry/LayoutSize.h"
 #include "platform/heap/SelfKeepAlive.h"
 #include "platform/wtf/HashCountedSet.h"
 #include "platform/wtf/RefPtr.h"
@@ -58,10 +59,13 @@
 
   void AddClient(const ImageResourceObserver*, const IntSize&);
   void RemoveClient(const ImageResourceObserver*);
+  // The |container_size| is the container size with subpixel snapping, where
+  // the |logical_size| is without it. Both sizes include zoom.
   RefPtr<Image> GetImage(const ImageResourceObserver&,
                          const Document&,
                          const ComputedStyle&,
-                         const IntSize&);
+                         const IntSize& container_size,
+                         const LayoutSize* logical_size);
 
   bool IsFixedSize() const;
   IntSize FixedSize(const Document&, const FloatSize& default_object_size);
diff --git a/third_party/WebKit/Source/core/css/CSSPaintImageGenerator.h b/third_party/WebKit/Source/core/css/CSSPaintImageGenerator.h
index 0ad8ebd..8b2ea28 100644
--- a/third_party/WebKit/Source/core/css/CSSPaintImageGenerator.h
+++ b/third_party/WebKit/Source/core/css/CSSPaintImageGenerator.h
@@ -9,6 +9,7 @@
 #include "core/CoreExport.h"
 #include "core/css/cssom/CSSStyleValue.h"
 #include "platform/geometry/IntSize.h"
+#include "platform/geometry/LayoutSize.h"
 #include "platform/heap/Handle.h"
 
 namespace blink {
@@ -47,9 +48,12 @@
 
   // Invokes the CSS Paint API 'paint' callback. May return a nullptr
   // representing an invalid image if an error occurred.
+  // The |container_size| is the container size with subpixel snapping, where
+  // the |logical_size| is without it. Both sizes include zoom.
   virtual RefPtr<Image> Paint(const ImageResourceObserver&,
-                              const IntSize&,
-                              const CSSStyleValueVector*) = 0;
+                              const IntSize& container_size,
+                              const CSSStyleValueVector*,
+                              const LayoutSize* logical_size) = 0;
 
   virtual const Vector<CSSPropertyID>& NativeInvalidationProperties() const = 0;
   virtual const Vector<AtomicString>& CustomInvalidationProperties() const = 0;
diff --git a/third_party/WebKit/Source/core/css/CSSPaintValue.cpp b/third_party/WebKit/Source/core/css/CSSPaintValue.cpp
index a311aa8..dd7c79b 100644
--- a/third_party/WebKit/Source/core/css/CSSPaintValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSPaintValue.cpp
@@ -32,7 +32,7 @@
   result.Append(name_->CustomCSSText());
   for (const auto& variable_data : argument_variable_data_) {
     result.Append(", ");
-    result.Append(variable_data.Get()->TokenRange().Serialize());
+    result.Append(variable_data.get()->TokenRange().Serialize());
   }
   result.Append(')');
   return result.ToString();
@@ -45,7 +45,8 @@
 RefPtr<Image> CSSPaintValue::GetImage(const ImageResourceObserver& client,
                                       const Document& document,
                                       const ComputedStyle&,
-                                      const IntSize& size) {
+                                      const IntSize& container_size,
+                                      const LayoutSize* logical_size) {
   if (!generator_) {
     generator_ = CSSPaintImageGenerator::Create(
         GetName(), document, paint_image_generator_observer_);
@@ -54,7 +55,8 @@
   if (!ParseInputArguments())
     return nullptr;
 
-  return generator_->Paint(client, size, parsed_input_arguments_);
+  return generator_->Paint(client, container_size, parsed_input_arguments_,
+                           logical_size);
 }
 
 bool CSSPaintValue::ParseInputArguments() {
diff --git a/third_party/WebKit/Source/core/css/CSSPaintValue.h b/third_party/WebKit/Source/core/css/CSSPaintValue.h
index fe505d5b..e549c35 100644
--- a/third_party/WebKit/Source/core/css/CSSPaintValue.h
+++ b/third_party/WebKit/Source/core/css/CSSPaintValue.h
@@ -31,10 +31,13 @@
 
   String GetName() const;
 
+  // The |container_size| is container size with subpixel snapping, where the
+  // |logical_size| is without it. Both sizes include zoom.
   RefPtr<Image> GetImage(const ImageResourceObserver&,
                          const Document&,
                          const ComputedStyle&,
-                         const IntSize&);
+                         const IntSize& container_size,
+                         const LayoutSize* logical_size);
   bool IsFixedSize() const { return false; }
   IntSize FixedSize(const Document&) { return IntSize(); }
 
diff --git a/third_party/WebKit/Source/core/css/CSSPathValue.h b/third_party/WebKit/Source/core/css/CSSPathValue.h
index 2d59894..081dd24 100644
--- a/third_party/WebKit/Source/core/css/CSSPathValue.h
+++ b/third_party/WebKit/Source/core/css/CSSPathValue.h
@@ -24,7 +24,7 @@
 
   static CSSPathValue& EmptyPathValue();
 
-  StylePath* GetStylePath() const { return style_path_.Get(); }
+  StylePath* GetStylePath() const { return style_path_.get(); }
   String CustomCSSText() const;
 
   bool Equals(const CSSPathValue&) const;
diff --git a/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp b/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp
index 402c2bb0..ae4b4f2 100644
--- a/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp
+++ b/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp
@@ -74,8 +74,8 @@
   // Only these nodes can be parents of StyleSheets, and they need to call
   // clearOwnerNode() when moved out of document. Note that destructor of
   // the nodes don't call clearOwnerNode() with Oilpan.
-  return parent_node.IsDocumentNode() || isHTMLLinkElement(parent_node) ||
-         isHTMLStyleElement(parent_node) || isSVGStyleElement(parent_node) ||
+  return parent_node.IsDocumentNode() || IsHTMLLinkElement(parent_node) ||
+         IsHTMLStyleElement(parent_node) || IsSVGStyleElement(parent_node) ||
          parent_node.getNodeType() == Node::kProcessingInstructionNode;
 }
 #endif
@@ -208,7 +208,7 @@
 void CSSStyleSheet::SetMediaQueries(RefPtr<MediaQuerySet> media_queries) {
   media_queries_ = std::move(media_queries);
   if (media_cssom_wrapper_ && media_queries_)
-    media_cssom_wrapper_->Reattach(media_queries_.Get());
+    media_cssom_wrapper_->Reattach(media_queries_.get());
 }
 
 bool CSSStyleSheet::MatchesMediaQueries(const MediaQueryEvaluator& evaluator) {
@@ -261,7 +261,7 @@
     return true;
   if (allow_rule_access_from_origin_ &&
       document->GetSecurityOrigin()->CanAccess(
-          allow_rule_access_from_origin_.Get())) {
+          allow_rule_access_from_origin_.get())) {
     return true;
   }
   return false;
@@ -388,7 +388,7 @@
     return nullptr;
 
   if (!media_cssom_wrapper_)
-    media_cssom_wrapper_ = MediaList::Create(media_queries_.Get(),
+    media_cssom_wrapper_ = MediaList::Create(media_queries_.get(),
                                              const_cast<CSSStyleSheet*>(this));
   return media_cssom_wrapper_.Get();
 }
diff --git a/third_party/WebKit/Source/core/css/CSSStyleSheet.h b/third_party/WebKit/Source/core/css/CSSStyleSheet.h
index da7c020..aad4b14 100644
--- a/third_party/WebKit/Source/core/css/CSSStyleSheet.h
+++ b/third_party/WebKit/Source/core/css/CSSStyleSheet.h
@@ -100,7 +100,7 @@
 
   void ClearOwnerRule() { owner_rule_ = nullptr; }
   Document* OwnerDocument() const;
-  const MediaQuerySet* MediaQueries() const { return media_queries_.Get(); }
+  const MediaQuerySet* MediaQueries() const { return media_queries_.get(); }
   void SetMediaQueries(RefPtr<MediaQuerySet>);
   bool MatchesMediaQueries(const MediaQueryEvaluator&);
   bool HasMediaQueryResults() const {
diff --git a/third_party/WebKit/Source/core/css/CSSVariableReferenceValue.h b/third_party/WebKit/Source/core/css/CSSVariableReferenceValue.h
index 89b222b..d9afc1d 100644
--- a/third_party/WebKit/Source/core/css/CSSVariableReferenceValue.h
+++ b/third_party/WebKit/Source/core/css/CSSVariableReferenceValue.h
@@ -19,7 +19,7 @@
     return new CSSVariableReferenceValue(std::move(data), context);
   }
 
-  CSSVariableData* VariableDataValue() const { return data_.Get(); }
+  CSSVariableData* VariableDataValue() const { return data_.get(); }
   const CSSParserContext* ParserContext() const {
     return parser_context_.Get();
   }
diff --git a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
index ebe174f..3a4209e 100644
--- a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
+++ b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
@@ -1455,12 +1455,13 @@
     const CSSTimingData* timing_data) {
   CSSValueList* list = CSSValueList::CreateCommaSeparated();
   if (timing_data) {
-    for (size_t i = 0; i < timing_data->TimingFunctionList().size(); ++i)
+    for (size_t i = 0; i < timing_data->TimingFunctionList().size(); ++i) {
       list->Append(*CreateTimingFunctionValue(
-          timing_data->TimingFunctionList()[i].Get()));
+          timing_data->TimingFunctionList()[i].get()));
+    }
   } else {
     list->Append(*CreateTimingFunctionValue(
-        CSSTimingData::InitialTimingFunction().Get()));
+        CSSTimingData::InitialTimingFunction().get()));
   }
   return list;
 }
@@ -3233,7 +3234,7 @@
           list->Append(*CreateTimingFunctionValue(
               CSSTimingData::GetRepeated(animation_data->TimingFunctionList(),
                                          i)
-                  .Get()));
+                  .get()));
           list->Append(*CSSPrimitiveValue::Create(
               CSSTimingData::GetRepeated(animation_data->DelayList(), i),
               CSSPrimitiveValue::UnitType::kSeconds));
@@ -3258,7 +3259,7 @@
           *CSSPrimitiveValue::Create(CSSAnimationData::InitialDuration(),
                                      CSSPrimitiveValue::UnitType::kSeconds));
       list->Append(*CreateTimingFunctionValue(
-          CSSAnimationData::InitialTimingFunction().Get()));
+          CSSAnimationData::InitialTimingFunction().get()));
       list->Append(
           *CSSPrimitiveValue::Create(CSSAnimationData::InitialDelay(),
                                      CSSPrimitiveValue::UnitType::kSeconds));
@@ -3432,7 +3433,7 @@
           list->Append(*CreateTimingFunctionValue(
               CSSTimingData::GetRepeated(transition_data->TimingFunctionList(),
                                          i)
-                  .Get()));
+                  .get()));
           list->Append(*CSSPrimitiveValue::Create(
               CSSTimingData::GetRepeated(transition_data->DelayList(), i),
               CSSPrimitiveValue::UnitType::kSeconds));
@@ -3448,7 +3449,7 @@
           *CSSPrimitiveValue::Create(CSSTransitionData::InitialDuration(),
                                      CSSPrimitiveValue::UnitType::kSeconds));
       list->Append(*CreateTimingFunctionValue(
-          CSSTransitionData::InitialTimingFunction().Get()));
+          CSSTransitionData::InitialTimingFunction().get()));
       list->Append(
           *CSSPrimitiveValue::Create(CSSTransitionData::InitialDelay(),
                                      CSSPrimitiveValue::UnitType::kSeconds));
diff --git a/third_party/WebKit/Source/core/css/ElementRuleCollector.cpp b/third_party/WebKit/Source/core/css/ElementRuleCollector.cpp
index 4ee804f..7419f8cc 100644
--- a/third_party/WebKit/Source/core/css/ElementRuleCollector.cpp
+++ b/third_party/WebKit/Source/core/css/ElementRuleCollector.cpp
@@ -123,7 +123,7 @@
   SelectorChecker::Init init;
   init.mode = mode_;
   init.is_ua_rule = matching_ua_rules_;
-  init.element_style = style_.Get();
+  init.element_style = style_.get();
   init.scrollbar = pseudo_style_request_.scrollbar;
   init.scrollbar_part = pseudo_style_request_.scrollbar_part;
   SelectorChecker checker(init);
diff --git a/third_party/WebKit/Source/core/css/FontFace.cpp b/third_party/WebKit/Source/core/css/FontFace.cpp
index 45037f6e..81030b9 100644
--- a/third_party/WebKit/Source/core/css/FontFace.cpp
+++ b/third_party/WebKit/Source/core/css/FontFace.cpp
@@ -79,12 +79,12 @@
                            const AtomicString& family,
                            StringOrArrayBufferOrArrayBufferView& source,
                            const FontFaceDescriptors& descriptors) {
-  if (source.isString())
-    return Create(context, family, source.getAsString(), descriptors);
-  if (source.isArrayBuffer())
-    return Create(context, family, source.getAsArrayBuffer(), descriptors);
-  if (source.isArrayBufferView()) {
-    return Create(context, family, source.getAsArrayBufferView().View(),
+  if (source.IsString())
+    return Create(context, family, source.GetAsString(), descriptors);
+  if (source.IsArrayBuffer())
+    return Create(context, family, source.GetAsArrayBuffer(), descriptors);
+  if (source.IsArrayBufferView()) {
+    return Create(context, family, source.GetAsArrayBufferView().View(),
                   descriptors);
   }
   NOTREACHED();
@@ -396,7 +396,7 @@
 WebTaskRunner* FontFace::GetTaskRunner() {
   return TaskRunnerHelper::Get(TaskType::kDOMManipulation,
                                GetExecutionContext())
-      .Get();
+      .get();
 }
 
 void FontFace::RunCallbacks() {
@@ -724,7 +724,7 @@
 
   RefPtr<SharedBuffer> buffer = SharedBuffer::Create(data, size);
   BinaryDataFontFaceSource* source =
-      new BinaryDataFontFaceSource(buffer.Get(), ots_parse_message_);
+      new BinaryDataFontFaceSource(buffer.get(), ots_parse_message_);
   if (source->IsValid())
     SetLoadStatus(kLoaded);
   else
diff --git a/third_party/WebKit/Source/core/css/FontFace.h b/third_party/WebKit/Source/core/css/FontFace.h
index a226b31..a5e988b 100644
--- a/third_party/WebKit/Source/core/css/FontFace.h
+++ b/third_party/WebKit/Source/core/css/FontFace.h
@@ -152,7 +152,7 @@
   void SetPropertyFromString(const Document*,
                              const String&,
                              CSSPropertyID,
-                             ExceptionState* = 0);
+                             ExceptionState* = nullptr);
   bool SetPropertyFromStyle(const StylePropertySet&, CSSPropertyID);
   bool SetPropertyValue(const CSSValue*, CSSPropertyID);
   bool SetFamilyValue(const CSSValue&);
diff --git a/third_party/WebKit/Source/core/css/FontFaceSetDocument.cpp b/third_party/WebKit/Source/core/css/FontFaceSetDocument.cpp
index 23f3abcd..efe9ab8 100644
--- a/third_party/WebKit/Source/core/css/FontFaceSetDocument.cpp
+++ b/third_party/WebKit/Source/core/css/FontFaceSetDocument.cpp
@@ -479,7 +479,7 @@
   style->GetFont().Update(style->GetFont().GetFontSelector());
 
   GetDocument()->UpdateActiveStyle();
-  GetDocument()->EnsureStyleResolver().ComputeFont(style.Get(), *parsed_style);
+  GetDocument()->EnsureStyleResolver().ComputeFont(style.get(), *parsed_style);
 
   font = style->GetFont();
   font.Update(GetDocument()->GetStyleEngine().GetFontSelector());
diff --git a/third_party/WebKit/Source/core/css/LocalFontFaceSource.cpp b/third_party/WebKit/Source/core/css/LocalFontFaceSource.cpp
index d0c1a0a9..4945e5a 100644
--- a/third_party/WebKit/Source/core/css/LocalFontFaceSource.cpp
+++ b/third_party/WebKit/Source/core/css/LocalFontFaceSource.cpp
@@ -32,7 +32,7 @@
   RefPtr<SimpleFontData> font_data = FontCache::GetFontCache()->GetFontData(
       description_without_styling, font_name_,
       AlternateFontName::kLocalUniqueFace);
-  histograms_.Record(font_data.Get());
+  histograms_.Record(font_data.get());
   return font_data;
 }
 
diff --git a/third_party/WebKit/Source/core/css/MediaList.h b/third_party/WebKit/Source/core/css/MediaList.h
index 9a3b208..ad85c2a 100644
--- a/third_party/WebKit/Source/core/css/MediaList.h
+++ b/third_party/WebKit/Source/core/css/MediaList.h
@@ -96,7 +96,7 @@
   CSSRule* ParentRule() const { return parent_rule_; }
   CSSStyleSheet* ParentStyleSheet() const { return parent_style_sheet_; }
 
-  const MediaQuerySet* Queries() const { return media_queries_.Get(); }
+  const MediaQuerySet* Queries() const { return media_queries_.get(); }
 
   void Reattach(RefPtr<MediaQuerySet>);
 
diff --git a/third_party/WebKit/Source/core/css/MediaQueryList.cpp b/third_party/WebKit/Source/core/css/MediaQueryList.cpp
index 5c4f66b6..35e41bb 100644
--- a/third_party/WebKit/Source/core/css/MediaQueryList.cpp
+++ b/third_party/WebKit/Source/core/css/MediaQueryList.cpp
@@ -102,7 +102,7 @@
 
 bool MediaQueryList::UpdateMatches() {
   matches_dirty_ = false;
-  if (matches_ != matcher_->Evaluate(media_.Get())) {
+  if (matches_ != matcher_->Evaluate(media_.get())) {
     matches_ = !matches_;
     return true;
   }
diff --git a/third_party/WebKit/Source/core/css/MediaQueryMatcherTest.cpp b/third_party/WebKit/Source/core/css/MediaQueryMatcherTest.cpp
index 6b2d275..51301a5 100644
--- a/third_party/WebKit/Source/core/css/MediaQueryMatcherTest.cpp
+++ b/third_party/WebKit/Source/core/css/MediaQueryMatcherTest.cpp
@@ -18,10 +18,10 @@
   MediaQueryMatcher* matcher =
       MediaQueryMatcher::Create(page_holder->GetDocument());
   RefPtr<MediaQuerySet> query_set = MediaQuerySet::Create(MediaTypeNames::all);
-  ASSERT_TRUE(matcher->Evaluate(query_set.Get()));
+  ASSERT_TRUE(matcher->Evaluate(query_set.get()));
 
   matcher->DocumentDetached();
-  ASSERT_FALSE(matcher->Evaluate(query_set.Get()));
+  ASSERT_FALSE(matcher->Evaluate(query_set.get()));
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/PropertyRegistration.cpp b/third_party/WebKit/Source/core/css/PropertyRegistration.cpp
index 738368a7..a403e2c0 100644
--- a/third_party/WebKit/Source/core/css/PropertyRegistration.cpp
+++ b/third_party/WebKit/Source/core/css/PropertyRegistration.cpp
@@ -114,9 +114,10 @@
   RefPtr<CSSVariableData> initial_variable_data;
   if (descriptor.hasInitialValue()) {
     CSSTokenizer tokenizer(descriptor.initialValue());
+    const auto tokens = tokenizer.TokenizeToEOF();
     bool is_animation_tainted = false;
     initial = syntax_descriptor.Parse(
-        tokenizer.TokenRange(),
+        CSSParserTokenRange(tokens),
         document->ElementSheet().Contents()->ParserContext(),
         is_animation_tainted);
     if (!initial) {
@@ -134,7 +135,7 @@
     initial =
         &StyleBuilderConverter::ConvertRegisteredPropertyInitialValue(*initial);
     initial_variable_data = CSSVariableData::Create(
-        tokenizer.TokenRange(), is_animation_tainted, false);
+        CSSParserTokenRange(tokens), is_animation_tainted, false);
   } else {
     if (!syntax_descriptor.IsTokenStream()) {
       exception_state.ThrowDOMException(
diff --git a/third_party/WebKit/Source/core/css/PropertyRegistration.h b/third_party/WebKit/Source/core/css/PropertyRegistration.h
index ee9541b..0847039 100644
--- a/third_party/WebKit/Source/core/css/PropertyRegistration.h
+++ b/third_party/WebKit/Source/core/css/PropertyRegistration.h
@@ -33,7 +33,7 @@
   bool Inherits() const { return inherits_; }
   const CSSValue* Initial() const { return initial_; }
   CSSVariableData* InitialVariableData() const {
-    return initial_variable_data_.Get();
+    return initial_variable_data_.get();
   }
   const InterpolationTypes& GetInterpolationTypes() const {
     return interpolation_types_;
diff --git a/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp b/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp
index 5e92dad..79af364 100644
--- a/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp
+++ b/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp
@@ -96,7 +96,7 @@
     return;
 
   for (const auto& item : font_data_table_) {
-    SimpleFontData* font_data = item.value.Get();
+    SimpleFontData* font_data = item.value.get();
     if (font_data && font_data->GetCustomFontData())
       font_data->GetCustomFontData()->ClearFontFaceSource();
   }
@@ -140,13 +140,17 @@
           "OTS parsing error: " + font_->OtsParsingMessage()));
   }
 
+  CSSFontFace::LoadFinishReason load_finish_reason =
+      font_->GetResourceError().IsCancellation()
+          ? CSSFontFace::LoadFinishReason::WasCancelled
+          : CSSFontFace::LoadFinishReason::NormalFinish;
   font_->RemoveClient(this);
   font_ = nullptr;
 
   PruneTable();
   if (face_) {
     font_selector_->FontFaceInvalidated();
-    face_->FontLoaded(this);
+    face_->FontLoaded(this, load_finish_reason);
   }
 }
 
diff --git a/third_party/WebKit/Source/core/css/RuleFeature.cpp b/third_party/WebKit/Source/core/css/RuleFeature.cpp
index d261095..2bdf66f 100644
--- a/third_party/WebKit/Source/core/css/RuleFeature.cpp
+++ b/third_party/WebKit/Source/core/css/RuleFeature.cpp
@@ -226,7 +226,7 @@
 
   RefPtr<InvalidationSet> descendants = invalidation_set;
   invalidation_set = SiblingInvalidationSet::Create(
-      ToDescendantInvalidationSet(descendants.Get()));
+      ToDescendantInvalidationSet(descendants.get()));
   return *invalidation_set;
 }
 
@@ -454,7 +454,7 @@
   return nullptr;
 }
 
-void RuleFeatureSet::UpdateInvalidationSets(const RuleData& rule_data) {
+void RuleFeatureSet::UpdateInvalidationSets(RuleData& rule_data) {
   // Given a rule, update the descendant invalidation sets for the features
   // found in its selector. The first step is to extract the features from the
   // rightmost compound selector (extractInvalidationSetFeaturesFromCompound).
@@ -479,7 +479,7 @@
     AddFeaturesToInvalidationSet(EnsureNthInvalidationSet(), features);
   if (features.has_before_or_after) {
     if (rule_data.Rule()->LazyParser())
-      rule_data.Rule()->LazyParser()->LazyState()->SetHasBeforeOrAfter();
+      rule_data.Rule()->LazyParser()->SetHasBeforeOrAfter();
     UpdateInvalidationSetsForContentAttribute(
         rule_data.Rule()->ParsedProperties());
   }
@@ -806,7 +806,7 @@
 }
 
 RuleFeatureSet::SelectorPreMatch RuleFeatureSet::CollectFeaturesFromRuleData(
-    const RuleData& rule_data) {
+    RuleData& rule_data) {
   CHECK(is_alive_);
   FeatureMetadata metadata;
   if (CollectFeaturesFromSelector(rule_data.Selector(), metadata) ==
@@ -955,7 +955,7 @@
 
   DescendantInvalidationSet* descendants;
   SiblingInvalidationSet* siblings;
-  ExtractInvalidationSets(it->value.Get(), descendants, siblings);
+  ExtractInvalidationSets(it->value.get(), descendants, siblings);
 
   if (descendants) {
     TRACE_SCHEDULE_STYLE_INVALIDATION(element, *descendants, ClassChange,
@@ -980,7 +980,7 @@
   if (it == class_invalidation_sets_.end())
     return;
 
-  InvalidationSet* invalidation_set = it->value.Get();
+  InvalidationSet* invalidation_set = it->value.get();
   if (invalidation_set->GetType() == kInvalidateDescendants)
     return;
 
@@ -1004,7 +1004,7 @@
 
   DescendantInvalidationSet* descendants;
   SiblingInvalidationSet* siblings;
-  ExtractInvalidationSets(it->value.Get(), descendants, siblings);
+  ExtractInvalidationSets(it->value.get(), descendants, siblings);
 
   if (descendants) {
     TRACE_SCHEDULE_STYLE_INVALIDATION(element, *descendants, IdChange, id);
@@ -1026,7 +1026,7 @@
   if (it == id_invalidation_sets_.end())
     return;
 
-  InvalidationSet* invalidation_set = it->value.Get();
+  InvalidationSet* invalidation_set = it->value.get();
   if (invalidation_set->GetType() == kInvalidateDescendants)
     return;
 
@@ -1050,7 +1050,7 @@
 
   DescendantInvalidationSet* descendants;
   SiblingInvalidationSet* siblings;
-  ExtractInvalidationSets(it->value.Get(), descendants, siblings);
+  ExtractInvalidationSets(it->value.get(), descendants, siblings);
 
   if (descendants) {
     TRACE_SCHEDULE_STYLE_INVALIDATION(element, *descendants, AttributeChange,
@@ -1075,7 +1075,7 @@
   if (it == attribute_invalidation_sets_.end())
     return;
 
-  InvalidationSet* invalidation_set = it->value.Get();
+  InvalidationSet* invalidation_set = it->value.get();
   if (invalidation_set->GetType() == kInvalidateDescendants)
     return;
 
@@ -1100,7 +1100,7 @@
 
   DescendantInvalidationSet* descendants;
   SiblingInvalidationSet* siblings;
-  ExtractInvalidationSets(it->value.Get(), descendants, siblings);
+  ExtractInvalidationSets(it->value.get(), descendants, siblings);
 
   if (descendants) {
     TRACE_SCHEDULE_STYLE_INVALIDATION(element, *descendants, PseudoChange,
diff --git a/third_party/WebKit/Source/core/css/RuleFeature.h b/third_party/WebKit/Source/core/css/RuleFeature.h
index 06cffc6..815c18c 100644
--- a/third_party/WebKit/Source/core/css/RuleFeature.h
+++ b/third_party/WebKit/Source/core/css/RuleFeature.h
@@ -53,7 +53,7 @@
 
   enum SelectorPreMatch { kSelectorNeverMatches, kSelectorMayMatch };
 
-  SelectorPreMatch CollectFeaturesFromRuleData(const RuleData&);
+  SelectorPreMatch CollectFeaturesFromRuleData(RuleData&);
   void UpdateInvalidationSetsForContentAttribute(const StylePropertySet*);
 
   bool UsesFirstLineRules() const { return metadata_.uses_first_line_rules; }
@@ -178,7 +178,7 @@
   DescendantInvalidationSet& EnsureNthInvalidationSet();
   DescendantInvalidationSet& EnsureTypeRuleInvalidationSet();
 
-  void UpdateInvalidationSets(const RuleData&);
+  void UpdateInvalidationSets(RuleData&);
 
   struct InvalidationSetFeatures {
     DISALLOW_NEW();
diff --git a/third_party/WebKit/Source/core/css/SelectorChecker.cpp b/third_party/WebKit/Source/core/css/SelectorChecker.cpp
index 44efdf4..7f78130 100644
--- a/third_party/WebKit/Source/core/css/SelectorChecker.cpp
+++ b/third_party/WebKit/Source/core/css/SelectorChecker.cpp
@@ -74,13 +74,13 @@
 }
 
 static bool MatchesSpatialNavigationFocusPseudoClass(const Element& element) {
-  return isHTMLOptionElement(element) &&
+  return IsHTMLOptionElement(element) &&
          toHTMLOptionElement(element).SpatialNavigationFocused() &&
          IsFrameFocused(element);
 }
 
 static bool MatchesListBoxPseudoClass(const Element& element) {
-  return isHTMLSelectElement(element) &&
+  return IsHTMLSelectElement(element) &&
          !toHTMLSelectElement(element).UsesMenuList();
 }
 
@@ -985,17 +985,16 @@
       return element.MatchesValidityPseudoClasses() &&
              !element.IsValidElement();
     case CSSSelector::kPseudoChecked: {
-      if (isHTMLInputElement(element)) {
-        HTMLInputElement& input_element = toHTMLInputElement(element);
+      if (auto* input_element = ToHTMLInputElementOrNull(element)) {
         // Even though WinIE allows checked and indeterminate to
         // co-exist, the CSS selector spec says that you can't be
         // both checked and indeterminate. We will behave like WinIE
         // behind the scenes and just obey the CSS spec here in the
         // test for matching the pseudo.
-        if (input_element.ShouldAppearChecked() &&
-            !input_element.ShouldAppearIndeterminate())
+        if (input_element->ShouldAppearChecked() &&
+            !input_element->ShouldAppearIndeterminate())
           return true;
-      } else if (isHTMLOptionElement(element) &&
+      } else if (IsHTMLOptionElement(element) &&
                  toHTMLOptionElement(element).Selected()) {
         return true;
       }
@@ -1036,7 +1035,7 @@
       return element.ContainsFullScreenElement();
     case CSSSelector::kPseudoVideoPersistent:
       DCHECK(is_ua_rule_);
-      return isHTMLVideoElement(element) &&
+      return IsHTMLVideoElement(element) &&
              toHTMLVideoElement(element).IsPersistent();
     case CSSSelector::kPseudoVideoPersistentAncestor:
       DCHECK(is_ua_rule_);
diff --git a/third_party/WebKit/Source/core/css/StyleEngine.cpp b/third_party/WebKit/Source/core/css/StyleEngine.cpp
index ee073b9..7e6e683 100644
--- a/third_party/WebKit/Source/core/css/StyleEngine.cpp
+++ b/third_party/WebKit/Source/core/css/StyleEngine.cpp
@@ -960,7 +960,7 @@
   Element* element = ElementTraversal::FirstChild(*stay_within);
   while (element) {
     ScheduleRuleSetInvalidationsForElement(*element, rule_sets);
-    if (invalidate_slotted && isHTMLSlotElement(element))
+    if (invalidate_slotted && IsHTMLSlotElement(element))
       InvalidateSlottedElements(toHTMLSlotElement(*element));
 
     if (element->GetStyleChangeType() < kSubtreeStyleChange)
diff --git a/third_party/WebKit/Source/core/css/StylePropertySet.h b/third_party/WebKit/Source/core/css/StylePropertySet.h
index 171f53f6..d7f8440 100644
--- a/third_party/WebKit/Source/core/css/StylePropertySet.h
+++ b/third_party/WebKit/Source/core/css/StylePropertySet.h
@@ -36,7 +36,6 @@
 namespace blink {
 
 class CSSStyleDeclaration;
-class CSSLazyParsingState;
 class ImmutableStylePropertySet;
 class MutableStylePropertySet;
 class PropertyRegistry;
@@ -166,7 +165,7 @@
   CSSLazyPropertyParser() {}
   virtual ~CSSLazyPropertyParser() {}
   virtual StylePropertySet* ParseProperties() = 0;
-  virtual CSSLazyParsingState* LazyState() const = 0;
+  virtual void SetHasBeforeOrAfter() = 0;
 
   DECLARE_VIRTUAL_TRACE();
 };
diff --git a/third_party/WebKit/Source/core/css/StyleRule.h b/third_party/WebKit/Source/core/css/StyleRule.h
index 2bdbdf8..b7f2d6e 100644
--- a/third_party/WebKit/Source/core/css/StyleRule.h
+++ b/third_party/WebKit/Source/core/css/StyleRule.h
@@ -68,7 +68,7 @@
   StyleRuleBase* Copy() const;
 
   // FIXME: There shouldn't be any need for the null parent version.
-  CSSRule* CreateCSSOMWrapper(CSSStyleSheet* parent_sheet = 0) const;
+  CSSRule* CreateCSSOMWrapper(CSSStyleSheet* parent_sheet = nullptr) const;
   CSSRule* CreateCSSOMWrapper(CSSRule* parent_rule) const;
 
   DECLARE_TRACE();
@@ -110,9 +110,7 @@
   const StylePropertySet& Properties() const;
   const StylePropertySet* ParsedProperties() const { return properties_; }
   MutableStylePropertySet& MutableProperties();
-  const CSSLazyPropertyParser* LazyParser() const {
-    return lazy_property_parser_.Get();
-  }
+  CSSLazyPropertyParser* LazyParser() { return lazy_property_parser_.Get(); }
 
   void WrapperAdoptSelectorList(CSSSelectorList selectors) {
     selector_list_ = std::move(selectors);
@@ -248,7 +246,7 @@
     return new StyleRuleMedia(media, adopt_rules);
   }
 
-  MediaQuerySet* MediaQueries() const { return media_queries_.Get(); }
+  MediaQuerySet* MediaQueries() const { return media_queries_.get(); }
 
   StyleRuleMedia* Copy() const { return new StyleRuleMedia(*this); }
 
diff --git a/third_party/WebKit/Source/core/css/StyleRuleImport.h b/third_party/WebKit/Source/core/css/StyleRuleImport.h
index d52b793..6e1d7891 100644
--- a/third_party/WebKit/Source/core/css/StyleRuleImport.h
+++ b/third_party/WebKit/Source/core/css/StyleRuleImport.h
@@ -51,7 +51,7 @@
   StyleSheetContents* GetStyleSheet() const { return style_sheet_.Get(); }
 
   bool IsLoading() const;
-  MediaQuerySet* MediaQueries() { return media_queries_.Get(); }
+  MediaQuerySet* MediaQueries() { return media_queries_.get(); }
 
   void RequestStyleSheet();
 
diff --git a/third_party/WebKit/Source/core/css/StyleSheetCandidate.cpp b/third_party/WebKit/Source/core/css/StyleSheetCandidate.cpp
index e65db91..151df88 100644
--- a/third_party/WebKit/Source/core/css/StyleSheetCandidate.cpp
+++ b/third_party/WebKit/Source/core/css/StyleSheetCandidate.cpp
@@ -105,16 +105,16 @@
     return kPi;
 
   if (node.IsHTMLElement()) {
-    if (isHTMLLinkElement(node))
+    if (IsHTMLLinkElement(node))
       return kHTMLLink;
-    if (isHTMLStyleElement(node))
+    if (IsHTMLStyleElement(node))
       return kHTMLStyle;
 
     NOTREACHED();
     return kInvalid;
   }
 
-  if (isSVGStyleElement(node))
+  if (IsSVGStyleElement(node))
     return kSVGStyle;
 
   NOTREACHED();
diff --git a/third_party/WebKit/Source/core/css/StyleSheetList.cpp b/third_party/WebKit/Source/core/css/StyleSheetList.cpp
index 5d40171..9942798 100644
--- a/third_party/WebKit/Source/core/css/StyleSheetList.cpp
+++ b/third_party/WebKit/Source/core/css/StyleSheetList.cpp
@@ -57,7 +57,7 @@
   // practice anyway ;)
   // FIXME: We should figure out if we should change this or fix the spec.
   Element* element = tree_scope_->getElementById(name);
-  return isHTMLStyleElement(element) ? toHTMLStyleElement(element) : nullptr;
+  return IsHTMLStyleElement(element) ? toHTMLStyleElement(element) : nullptr;
 }
 
 CSSStyleSheet* StyleSheetList::AnonymousNamedGetter(const AtomicString& name) {
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.cpp b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.cpp
index bf292ea6..ebb4dc7 100644
--- a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.cpp
+++ b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.cpp
@@ -29,7 +29,7 @@
   CSSStyleVariableReferenceValue* variable_reference =
       CSSStyleVariableReferenceValue::Create(variable_name.ToString(),
                                              unparsed_value);
-  return StringOrCSSVariableReferenceValue::fromCSSVariableReferenceValue(
+  return StringOrCSSVariableReferenceValue::FromCSSVariableReferenceValue(
       variable_reference);
 }
 
@@ -41,7 +41,7 @@
     if (range.Peek().FunctionId() == CSSValueVar) {
       if (!builder.IsEmpty()) {
         fragments.push_back(
-            StringOrCSSVariableReferenceValue::fromString(builder.ToString()));
+            StringOrCSSVariableReferenceValue::FromString(builder.ToString()));
         builder.Clear();
       }
       CSSParserTokenRange block = range.ConsumeBlock();
@@ -57,7 +57,7 @@
   }
   if (!builder.IsEmpty()) {
     fragments.push_back(
-        StringOrCSSVariableReferenceValue::fromString(builder.ToString()));
+        StringOrCSSVariableReferenceValue::FromString(builder.ToString()));
   }
   return fragments;
 }
@@ -71,26 +71,27 @@
 }
 
 const CSSValue* CSSUnparsedValue::ToCSSValue() const {
-  StringBuilder tokens;
+  StringBuilder input;
 
   for (unsigned i = 0; i < fragments_.size(); i++) {
     if (i) {
-      tokens.Append("/**/");
+      input.Append("/**/");
     }
-    if (fragments_[i].isString()) {
-      tokens.Append(fragments_[i].getAsString());
-    } else if (fragments_[i].isCSSVariableReferenceValue()) {
-      tokens.Append(fragments_[i].getAsCSSVariableReferenceValue()->variable());
+    if (fragments_[i].IsString()) {
+      input.Append(fragments_[i].GetAsString());
+    } else if (fragments_[i].IsCSSVariableReferenceValue()) {
+      input.Append(fragments_[i].GetAsCSSVariableReferenceValue()->variable());
     } else {
       NOTREACHED();
     }
   }
 
-  CSSTokenizer tokenizer(tokens.ToString());
+  CSSTokenizer tokenizer(input.ToString());
+  const auto tokens = tokenizer.TokenizeToEOF();
   // TODO(alancutter): This should be using a real parser context instead of
   // StrictCSSParserContext.
   return CSSVariableReferenceValue::Create(
-      CSSVariableData::Create(tokenizer.TokenRange(),
+      CSSVariableData::Create(CSSParserTokenRange(tokens),
                               false /* isAnimationTainted */,
                               true /* needsVariableResolution */),
       *StrictCSSParserContext());
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.h b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.h
index f348c3a..76d9045 100644
--- a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.h
+++ b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.h
@@ -47,7 +47,7 @@
  private:
   static CSSUnparsedValue* FromString(String string) {
     HeapVector<StringOrCSSVariableReferenceValue> fragments;
-    fragments.push_back(StringOrCSSVariableReferenceValue::fromString(string));
+    fragments.push_back(StringOrCSSVariableReferenceValue::FromString(string));
     return Create(fragments);
   }
 
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValueTest.cpp b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValueTest.cpp
index bbac11e..038d2cd 100644
--- a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValueTest.cpp
+++ b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValueTest.cpp
@@ -15,7 +15,7 @@
     CSSStyleVariableReferenceValue* variable_reference_value) {
   HeapVector<StringOrCSSVariableReferenceValue> fragments;
   fragments.push_back(
-      StringOrCSSVariableReferenceValue::fromCSSVariableReferenceValue(
+      StringOrCSSVariableReferenceValue::FromCSSVariableReferenceValue(
           variable_reference_value));
   return CSSUnparsedValue::Create(fragments);
 }
@@ -34,12 +34,12 @@
 
   EXPECT_EQ(unparsed_value->length(), 1UL);
 
-  EXPECT_TRUE(unparsed_value->fragmentAtIndex(0).isString());
-  EXPECT_FALSE(unparsed_value->fragmentAtIndex(0).isNull());
+  EXPECT_TRUE(unparsed_value->fragmentAtIndex(0).IsString());
+  EXPECT_FALSE(unparsed_value->fragmentAtIndex(0).IsNull());
   EXPECT_FALSE(
-      unparsed_value->fragmentAtIndex(0).isCSSVariableReferenceValue());
+      unparsed_value->fragmentAtIndex(0).IsCSSVariableReferenceValue());
 
-  EXPECT_EQ(unparsed_value->fragmentAtIndex(0).getAsString(), "string");
+  EXPECT_EQ(unparsed_value->fragmentAtIndex(0).GetAsString(), "string");
 }
 
 TEST(CSSUnparsedValueTest, ListOfCSSVariableReferenceValues) {
@@ -52,11 +52,11 @@
 
   EXPECT_EQ(unparsed_value->length(), 1UL);
 
-  EXPECT_FALSE(unparsed_value->fragmentAtIndex(0).isString());
-  EXPECT_FALSE(unparsed_value->fragmentAtIndex(0).isNull());
-  EXPECT_TRUE(unparsed_value->fragmentAtIndex(0).isCSSVariableReferenceValue());
+  EXPECT_FALSE(unparsed_value->fragmentAtIndex(0).IsString());
+  EXPECT_FALSE(unparsed_value->fragmentAtIndex(0).IsNull());
+  EXPECT_TRUE(unparsed_value->fragmentAtIndex(0).IsCSSVariableReferenceValue());
 
-  EXPECT_EQ(unparsed_value->fragmentAtIndex(0).getAsCSSVariableReferenceValue(),
+  EXPECT_EQ(unparsed_value->fragmentAtIndex(0).GetAsCSSVariableReferenceValue(),
             variable_reference_value);
 }
 
@@ -66,9 +66,9 @@
           "Ref", CSSUnparsedValue::FromString("string"));
 
   HeapVector<StringOrCSSVariableReferenceValue> fragments;
-  fragments.push_back(StringOrCSSVariableReferenceValue::fromString("string"));
+  fragments.push_back(StringOrCSSVariableReferenceValue::FromString("string"));
   fragments.push_back(
-      StringOrCSSVariableReferenceValue::fromCSSVariableReferenceValue(
+      StringOrCSSVariableReferenceValue::FromCSSVariableReferenceValue(
           variable_reference_value));
   fragments.push_back(StringOrCSSVariableReferenceValue());
 
@@ -76,17 +76,17 @@
 
   EXPECT_EQ(unparsed_value->length(), fragments.size());
 
-  EXPECT_TRUE(unparsed_value->fragmentAtIndex(0).isString());
+  EXPECT_TRUE(unparsed_value->fragmentAtIndex(0).IsString());
   EXPECT_FALSE(
-      unparsed_value->fragmentAtIndex(0).isCSSVariableReferenceValue());
-  EXPECT_EQ(unparsed_value->fragmentAtIndex(0).getAsString(), "string");
+      unparsed_value->fragmentAtIndex(0).IsCSSVariableReferenceValue());
+  EXPECT_EQ(unparsed_value->fragmentAtIndex(0).GetAsString(), "string");
 
-  EXPECT_TRUE(unparsed_value->fragmentAtIndex(1).isCSSVariableReferenceValue());
-  EXPECT_FALSE(unparsed_value->fragmentAtIndex(1).isString());
-  EXPECT_EQ(unparsed_value->fragmentAtIndex(1).getAsCSSVariableReferenceValue(),
+  EXPECT_TRUE(unparsed_value->fragmentAtIndex(1).IsCSSVariableReferenceValue());
+  EXPECT_FALSE(unparsed_value->fragmentAtIndex(1).IsString());
+  EXPECT_EQ(unparsed_value->fragmentAtIndex(1).GetAsCSSVariableReferenceValue(),
             variable_reference_value);
 
-  EXPECT_TRUE(unparsed_value->fragmentAtIndex(2).isNull());
+  EXPECT_TRUE(unparsed_value->fragmentAtIndex(2).IsNull());
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSVariableReferenceValueTest.cpp b/third_party/WebKit/Source/core/css/cssom/CSSVariableReferenceValueTest.cpp
index 3791d984e..7bc7cb22 100644
--- a/third_party/WebKit/Source/core/css/cssom/CSSVariableReferenceValueTest.cpp
+++ b/third_party/WebKit/Source/core/css/cssom/CSSVariableReferenceValueTest.cpp
@@ -22,9 +22,9 @@
 
 TEST(CSSVariableReferenceValueTest, MixedList) {
   HeapVector<StringOrCSSVariableReferenceValue> fragments;
-  fragments.push_back(StringOrCSSVariableReferenceValue::fromString("string"));
+  fragments.push_back(StringOrCSSVariableReferenceValue::FromString("string"));
   fragments.push_back(
-      StringOrCSSVariableReferenceValue::fromCSSVariableReferenceValue(
+      StringOrCSSVariableReferenceValue::FromCSSVariableReferenceValue(
           CSSStyleVariableReferenceValue::Create(
               "Variable", CSSUnparsedValue::FromString("Fallback"))));
   fragments.push_back(StringOrCSSVariableReferenceValue());
diff --git a/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.cpp b/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.cpp
index 815e7f3..4af7444b 100644
--- a/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.cpp
+++ b/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.cpp
@@ -127,19 +127,19 @@
     CSSStyleValueOrCSSStyleValueSequenceOrString& item,
     ExceptionState& exception_state) {
   const CSSValue* css_value = nullptr;
-  if (item.isCSSStyleValue()) {
+  if (item.IsCSSStyleValue()) {
     css_value =
-        SingleStyleValueAsCSSValue(property_id, *item.getAsCSSStyleValue());
-  } else if (item.isCSSStyleValueSequence()) {
+        SingleStyleValueAsCSSValue(property_id, *item.GetAsCSSStyleValue());
+  } else if (item.IsCSSStyleValueSequence()) {
     if (!CSSPropertyAPI::Get(property_id).IsRepeated()) {
       exception_state.ThrowTypeError(
           "Property does not support multiple values");
       return;
     }
-    css_value = AsCSSValueList(property_id, item.getAsCSSStyleValueSequence());
+    css_value = AsCSSValueList(property_id, item.GetAsCSSStyleValueSequence());
   } else {
     // Parse it.
-    DCHECK(item.isString());
+    DCHECK(item.IsString());
     // TODO(meade): Implement this.
     exception_state.ThrowTypeError("Not implemented yet");
     return;
@@ -174,16 +174,16 @@
     return;
   }
 
-  if (item.isCSSStyleValue()) {
+  if (item.IsCSSStyleValue()) {
     const CSSValue* css_value =
-        StyleValueToCSSValue(property_id, *item.getAsCSSStyleValue());
+        StyleValueToCSSValue(property_id, *item.GetAsCSSStyleValue());
     if (!css_value) {
       exception_state.ThrowTypeError("Invalid type for property");
       return;
     }
     css_value_list->Append(*css_value);
-  } else if (item.isCSSStyleValueSequence()) {
-    for (CSSStyleValue* style_value : item.getAsCSSStyleValueSequence()) {
+  } else if (item.IsCSSStyleValueSequence()) {
+    for (CSSStyleValue* style_value : item.GetAsCSSStyleValueSequence()) {
       const CSSValue* css_value =
           StyleValueToCSSValue(property_id, *style_value);
       if (!css_value) {
@@ -194,7 +194,7 @@
     }
   } else {
     // Parse it.
-    DCHECK(item.isString());
+    DCHECK(item.IsString());
     // TODO(meade): Implement this.
     exception_state.ThrowTypeError("Not implemented yet");
     return;
@@ -227,11 +227,11 @@
       // TODO(meade): Eventually custom properties will support other types, so
       // actually return them instead of always returning a
       // CSSUnsupportedStyleValue.
-      value.setCSSStyleValue(
+      value.SetCSSStyleValue(
           CSSUnsupportedStyleValue::Create(custom_declaration.CustomCSSText()));
     } else if (property_id == CSSPropertyApplyAtRule) {
       name = kAtApply;
-      value.setCSSStyleValue(CSSUnsupportedStyleValue::Create(
+      value.SetCSSStyleValue(CSSUnsupportedStyleValue::Create(
           ToCSSCustomIdentValue(property_reference.Value()).Value()));
     } else {
       name = getPropertyNameString(property_id);
@@ -239,9 +239,9 @@
           StyleValueFactory::CssValueToStyleValueVector(
               property_id, property_reference.Value());
       if (style_value_vector.size() == 1)
-        value.setCSSStyleValue(style_value_vector[0]);
+        value.SetCSSStyleValue(style_value_vector[0]);
       else
-        value.setCSSStyleValueSequence(style_value_vector);
+        value.SetCSSStyleValueSequence(style_value_vector);
     }
     result.push_back(std::make_pair(name, value));
   }
diff --git a/third_party/WebKit/Source/core/css/invalidation/InvalidationSet.h b/third_party/WebKit/Source/core/css/invalidation/InvalidationSet.h
index 375be6e3..7d57487 100644
--- a/third_party/WebKit/Source/core/css/invalidation/InvalidationSet.h
+++ b/third_party/WebKit/Source/core/css/invalidation/InvalidationSet.h
@@ -240,12 +240,12 @@
   }
 
   DescendantInvalidationSet* SiblingDescendants() const {
-    return sibling_descendant_invalidation_set_.Get();
+    return sibling_descendant_invalidation_set_.get();
   }
   DescendantInvalidationSet& EnsureSiblingDescendants();
 
   DescendantInvalidationSet* Descendants() const {
-    return descendant_invalidation_set_.Get();
+    return descendant_invalidation_set_.get();
   }
   DescendantInvalidationSet& EnsureDescendants();
 
diff --git a/third_party/WebKit/Source/core/css/invalidation/StyleInvalidator.cpp b/third_party/WebKit/Source/core/css/invalidation/StyleInvalidator.cpp
index 35f31dd..94ead6c 100644
--- a/third_party/WebKit/Source/core/css/invalidation/StyleInvalidator.cpp
+++ b/third_party/WebKit/Source/core/css/invalidation/StyleInvalidator.cpp
@@ -406,7 +406,7 @@
     element.SetNeedsStyleRecalc(kSubtreeStyleChange,
                                 StyleChangeReasonForTracing::Create(
                                     StyleChangeReason::kStyleInvalidator));
-  if (recursion_data.InvalidatesSlotted() && isHTMLSlotElement(element))
+  if (recursion_data.InvalidatesSlotted() && IsHTMLSlotElement(element))
     InvalidateSlotDistributedElements(toHTMLSlotElement(element),
                                       recursion_data);
 
diff --git a/third_party/WebKit/Source/core/css/parser/CSSLazyParsingState.cpp b/third_party/WebKit/Source/core/css/parser/CSSLazyParsingState.cpp
index c5e4785..b2b8358 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSLazyParsingState.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSLazyParsingState.cpp
@@ -4,7 +4,7 @@
 
 #include "core/css/parser/CSSLazyParsingState.h"
 #include "core/css/parser/CSSLazyPropertyParserImpl.h"
-#include "core/css/parser/CSSParserTokenRange.h"
+#include "core/css/parser/CSSParserTokenStream.h"
 #include "core/dom/Document.h"
 #include "core/frame/UseCounter.h"
 #include "platform/Histogram.h"
@@ -12,11 +12,9 @@
 namespace blink {
 
 CSSLazyParsingState::CSSLazyParsingState(const CSSParserContext* context,
-                                         Vector<String> escaped_strings,
                                          const String& sheet_text,
                                          StyleSheetContents* contents)
     : context_(context),
-      escaped_strings_(std::move(escaped_strings)),
       sheet_text_(sheet_text),
       owning_contents_(contents),
       parsed_style_rules_(0),
@@ -30,9 +28,9 @@
 }
 
 CSSLazyPropertyParserImpl* CSSLazyParsingState::CreateLazyParser(
-    const CSSParserTokenRange& block) {
+    const size_t offset) {
   ++total_style_rules_;
-  return new CSSLazyPropertyParserImpl(std::move(block), this);
+  return new CSSLazyPropertyParserImpl(offset, this);
 }
 
 const CSSParserContext* CSSLazyParsingState::Context() {
@@ -70,17 +68,6 @@
   }
 }
 
-bool CSSLazyParsingState::IsEmptyBlock(const CSSParserTokenRange& block) const {
-  // Simple heuristic for an empty block. Note that |block| here does not
-  // include {} brackets. We avoid lazy parsing empty blocks so we can avoid
-  // considering them when possible for matching. Lazy blocks must always be
-  // considered. Three tokens is a reasonable minimum for a block:
-  // ident ':' <value>.
-  if (block.end() - block.begin() <= 2)
-    return true;
-  return false;
-}
-
 void CSSLazyParsingState::RecordUsageMetrics() {
   DEFINE_STATIC_LOCAL(EnumerationHistogram, usage_histogram,
                       ("Style.LazyUsage.Percent", kUsageLastValue));
diff --git a/third_party/WebKit/Source/core/css/parser/CSSLazyParsingState.h b/third_party/WebKit/Source/core/css/parser/CSSLazyParsingState.h
index 2821b88..e2019d8d 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSLazyParsingState.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSLazyParsingState.h
@@ -16,7 +16,6 @@
 namespace blink {
 
 class CSSLazyPropertyParserImpl;
-class CSSParserTokenRange;
 
 // This class helps lazy parsing by retaining necessary state. It should not
 // outlive the StyleSheetContents that initiated the parse, as it retains a raw
@@ -25,7 +24,6 @@
     : public GarbageCollectedFinalized<CSSLazyParsingState> {
  public:
   CSSLazyParsingState(const CSSParserContext*,
-                      Vector<String> escaped_strings,
                       const String& sheet_text,
                       StyleSheetContents*);
 
@@ -33,13 +31,11 @@
   // know the total number of style rules that deferred parsing.
   void FinishInitialParsing();
 
-  void SetHasBeforeOrAfter() { has_before_or_after = true; }
-  bool HasBeforeOrAfter() { return has_before_or_after; }
-
   // Helper method used to bump total_style_rules_.
-  CSSLazyPropertyParserImpl* CreateLazyParser(const CSSParserTokenRange& block);
+  CSSLazyPropertyParserImpl* CreateLazyParser(size_t offset);
 
   const CSSParserContext* Context();
+  const String& SheetText() const { return sheet_text_; }
   StyleEngine& GetStyleEngine();
 
   RuleSet& GetRuleSet() { return owning_contents_->GetRuleSet(); }
@@ -47,8 +43,6 @@
 
   void CountRuleParsed();
 
-  bool IsEmptyBlock(const CSSParserTokenRange& block) const;
-
   DECLARE_TRACE();
 
   // Exposed for tests. This enum is used to back a histogram, so new values
@@ -70,7 +64,6 @@
   void RecordUsageMetrics();
 
   Member<const CSSParserContext> context_;
-  Vector<String> escaped_strings_;
   // Also referenced on the css resource.
   String sheet_text_;
 
@@ -90,10 +83,6 @@
 
   int usage_;
 
-  // Used to enable lazy parsing for content attributes inside ::before/::after
-  // blocks
-  bool has_before_or_after = false;
-
   // Whether or not use counting is enabled for parsing. This will usually be
   // true, except for when stylesheets with @imports are removed from the page.
   // See StyleRuleImport::setCSSStyleSheet.
diff --git a/third_party/WebKit/Source/core/css/parser/CSSLazyParsingTest.cpp b/third_party/WebKit/Source/core/css/parser/CSSLazyParsingTest.cpp
index ef96520a..237d6cb 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSLazyParsingTest.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSLazyParsingTest.cpp
@@ -45,21 +45,6 @@
   EXPECT_TRUE(HasParsedProperties(rule));
 }
 
-// Avoiding lazy parsing for trivially empty blocks helps us perform the
-// shouldConsiderForMatchingRules optimization.
-TEST_F(CSSLazyParsingTest, DontLazyParseEmpty) {
-  CSSParserContext* context = CSSParserContext::Create(kHTMLStandardMode);
-  StyleSheetContents* style_sheet = StyleSheetContents::Create(context);
-
-  String sheet_text = "body {  }";
-  CSSParser::ParseSheet(context, style_sheet, sheet_text,
-                        true /* lazy parse */);
-  StyleRule* rule = RuleAt(style_sheet, 0);
-  EXPECT_TRUE(HasParsedProperties(rule));
-  EXPECT_FALSE(
-      rule->ShouldConsiderForMatchingRules(false /* includeEmptyRules */));
-}
-
 // Avoid parsing rules with ::before or ::after to avoid causing
 // collectFeatures() when we trigger parsing for attr();
 TEST_F(CSSLazyParsingTest, LazyParseBeforeAfter) {
diff --git a/third_party/WebKit/Source/core/css/parser/CSSLazyPropertyParserImpl.cpp b/third_party/WebKit/Source/core/css/parser/CSSLazyPropertyParserImpl.cpp
index 4f813ed..879cadd4 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSLazyPropertyParserImpl.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSLazyPropertyParserImpl.cpp
@@ -10,22 +10,17 @@
 
 namespace blink {
 
-CSSLazyPropertyParserImpl::CSSLazyPropertyParserImpl(CSSParserTokenRange block,
+CSSLazyPropertyParserImpl::CSSLazyPropertyParserImpl(size_t offset,
                                                      CSSLazyParsingState* state)
-    : CSSLazyPropertyParser(), lazy_state_(state) {
-  // Reserve capacity to minimize heap bloat.
-  size_t length = block.end() - block.begin();
-  tokens_.ReserveCapacity(length);
-  tokens_.Append(block.begin(), length);
-}
+    : CSSLazyPropertyParser(), offset_(offset), lazy_state_(state) {}
 
 StylePropertySet* CSSLazyPropertyParserImpl::ParseProperties() {
   lazy_state_->CountRuleParsed();
   StylePropertySet* property_set =
-      CSSParserImpl::ParseDeclarationListForLazyStyle(tokens_,
-                                                      lazy_state_->Context());
-  if (property_set->FindPropertyIndex(CSSPropertyContent) != -1 &&
-      lazy_state_->HasBeforeOrAfter() && lazy_state_->HasRuleSet()) {
+      CSSParserImpl::ParseDeclarationListForLazyStyle(
+          lazy_state_->SheetText(), offset_, lazy_state_->Context());
+  if (has_before_or_after_ && lazy_state_->HasRuleSet() &&
+      property_set->FindPropertyIndex(CSSPropertyContent) != -1) {
     lazy_state_->GetRuleSet().UpdateInvalidationSetsForContentAttribute(
         property_set);
     lazy_state_->GetStyleEngine().MarkGlobalRuleSetDirty();
diff --git a/third_party/WebKit/Source/core/css/parser/CSSLazyPropertyParserImpl.h b/third_party/WebKit/Source/core/css/parser/CSSLazyPropertyParserImpl.h
index 4988198b..1727fde 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSLazyPropertyParserImpl.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSLazyPropertyParserImpl.h
@@ -17,11 +17,11 @@
 // This class is responsible for lazily parsing a single CSS declaration list.
 class CSSLazyPropertyParserImpl : public CSSLazyPropertyParser {
  public:
-  CSSLazyPropertyParserImpl(CSSParserTokenRange block, CSSLazyParsingState*);
+  CSSLazyPropertyParserImpl(size_t offset, CSSLazyParsingState*);
 
   // CSSLazyPropertyParser:
   StylePropertySet* ParseProperties() override;
-  CSSLazyParsingState* LazyState() const override { return lazy_state_.Get(); }
+  void SetHasBeforeOrAfter() override { has_before_or_after_ = true; }
 
   DEFINE_INLINE_TRACE() {
     visitor->Trace(lazy_state_);
@@ -29,8 +29,9 @@
   }
 
  private:
-  Vector<CSSParserToken> tokens_;
+  size_t offset_;
   Member<CSSLazyParsingState> lazy_state_;
+  bool has_before_or_after_ = false;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSParser.cpp
index b7071f8..d6bf0299 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSParser.cpp
@@ -43,7 +43,8 @@
     StyleSheetContents* style_sheet_contents,
     const String& selector) {
   CSSTokenizer tokenizer(selector);
-  return CSSSelectorParser::ParseSelector(tokenizer.TokenRange(), context,
+  const auto tokens = tokenizer.TokenizeToEOF();
+  return CSSSelectorParser::ParseSelector(CSSParserTokenRange(tokens), context,
                                           style_sheet_contents);
 }
 
@@ -52,7 +53,8 @@
     StyleSheetContents* style_sheet_contents,
     const String& selector) {
   CSSTokenizer tokenizer(selector);
-  return CSSParserImpl::ParsePageSelector(tokenizer.TokenRange(),
+  const auto tokens = tokenizer.TokenizeToEOF();
+  return CSSParserImpl::ParsePageSelector(CSSParserTokenRange(tokens),
                                           style_sheet_contents);
 }
 
@@ -172,8 +174,9 @@
                                                             context->Mode()))
     return value;
   CSSTokenizer tokenizer(string);
-  return CSSPropertyParser::ParseSingleValue(property_id,
-                                             tokenizer.TokenRange(), context);
+  const auto tokens = tokenizer.TokenizeToEOF();
+  return CSSPropertyParser::ParseSingleValue(
+      property_id, CSSParserTokenRange(tokens), context);
 }
 
 ImmutableStylePropertySet* CSSParser::ParseInlineStyleDeclaration(
@@ -196,9 +199,10 @@
 
 bool CSSParser::ParseSupportsCondition(const String& condition) {
   CSSTokenizer tokenizer(condition);
+  const auto tokens = tokenizer.TokenizeToEOF();
   CSSParserImpl parser(StrictCSSParserContext());
   return CSSSupportsParser::SupportsCondition(
-             tokenizer.TokenRange(), parser,
+             CSSParserTokenRange(tokens), parser,
              CSSSupportsParser::kForWindowCSS) == CSSSupportsParser::kSupported;
 }
 
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
index 4b441c2..768d713 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
@@ -20,6 +20,7 @@
 #include "core/css/parser/CSSLazyPropertyParserImpl.h"
 #include "core/css/parser/CSSParserObserver.h"
 #include "core/css/parser/CSSParserObserverWrapper.h"
+#include "core/css/parser/CSSParserScopedTokenBuffer.h"
 #include "core/css/parser/CSSParserSelector.h"
 #include "core/css/parser/CSSParserTokenStream.h"
 #include "core/css/parser/CSSPropertyParser.h"
@@ -37,6 +38,29 @@
 
 namespace blink {
 
+namespace {
+
+// This may still consume tokens if it fails
+AtomicString ConsumeStringOrURI(CSSParserTokenStream& stream) {
+  const CSSParserToken& token = stream.Peek();
+
+  if (token.GetType() == kStringToken || token.GetType() == kUrlToken)
+    return stream.ConsumeIncludingWhitespace().Value().ToAtomicString();
+
+  if (token.GetType() != kFunctionToken ||
+      !EqualIgnoringASCIICase(token.Value(), "url"))
+    return AtomicString();
+
+  CSSParserTokenStream::BlockGuard guard(stream);
+  const CSSParserToken& uri = stream.ConsumeIncludingWhitespace();
+  if (uri.GetType() == kBadStringToken || !stream.UncheckedAtEnd())
+    return AtomicString();
+  DCHECK_EQ(uri.GetType(), kStringToken);
+  return uri.Value().ToAtomicString();
+}
+
+}  // namespace
+
 CSSParserImpl::CSSParserImpl(const CSSParserContext* context,
                              StyleSheetContents* style_sheet)
     : context_(context),
@@ -56,10 +80,9 @@
   else if (declaration->CssParserMode() == kCSSFontFaceRuleMode)
     rule_type = StyleRule::kFontFace;
   CSSTokenizer tokenizer(string);
-  CSSParserTokenStream stream(tokenizer);
   // TODO(shend): Use streams instead of ranges
-  parser.ConsumeDeclarationValue(stream.MakeRangeToEOF(), unresolved_property,
-                                 important, rule_type);
+  parser.ConsumeDeclarationValue(CSSParserTokenRange(tokenizer.TokenizeToEOF()),
+                                 unresolved_property, important, rule_type);
   bool did_parse = false;
   bool did_change = false;
   if (!parser.parsed_properties_.IsEmpty()) {
@@ -79,9 +102,9 @@
     bool is_animation_tainted) {
   CSSParserImpl parser(context);
   CSSTokenizer tokenizer(value);
-  CSSParserTokenStream stream(tokenizer);
   // TODO(shend): Use streams instead of ranges
-  const CSSParserTokenRange range = stream.MakeRangeToEOF();
+  const auto tokens = tokenizer.TokenizeToEOF();
+  const CSSParserTokenRange range(tokens);
   parser.ConsumeVariableValue(range, property_name, important,
                               is_animation_tainted);
   bool did_parse = false;
@@ -206,20 +229,18 @@
   CSSParserImpl parser(context, style_sheet);
   CSSTokenizer tokenizer(string);
   CSSParserTokenStream stream(tokenizer);
-  // TODO(shend): Use streams instead of ranges
-  CSSParserTokenRange range = stream.MakeRangeToEOF();
-  range.ConsumeWhitespace();
-  if (range.AtEnd())
+  stream.ConsumeWhitespace();
+  if (stream.UncheckedAtEnd())
     return nullptr;  // Parse error, empty rule
   StyleRuleBase* rule;
-  if (range.Peek().GetType() == kAtKeywordToken)
-    rule = parser.ConsumeAtRule(range, allowed_rules);
+  if (stream.UncheckedPeek().GetType() == kAtKeywordToken)
+    rule = parser.ConsumeAtRule(stream, allowed_rules);
   else
-    rule = parser.ConsumeQualifiedRule(range, allowed_rules);
+    rule = parser.ConsumeQualifiedRule(stream, allowed_rules);
   if (!rule)
     return nullptr;  // Parse error, failed to consume rule
-  range.ConsumeWhitespace();
-  if (!rule || !range.AtEnd())
+  stream.ConsumeWhitespace();
+  if (!rule || !stream.UncheckedAtEnd())
     return nullptr;  // Parse error, trailing garbage
   return rule;
 }
@@ -236,17 +257,13 @@
                      "CSSParserImpl::parseStyleSheet.parse");
   CSSTokenizer tokenizer(string);
   CSSParserTokenStream stream(tokenizer);
-  // TODO(shend): Use streams instead of ranges. Streams will ruin
-  // tokenize/parse metrics as we will be tokenizing on demand.
-  const CSSParserTokenRange range = stream.MakeRangeToEOF();
-
   CSSParserImpl parser(context, style_sheet);
   if (defer_property_parsing) {
-    parser.lazy_state_ = new CSSLazyParsingState(
-        context, tokenizer.TakeEscapedStrings(), string, parser.style_sheet_);
+    parser.lazy_state_ =
+        new CSSLazyParsingState(context, string, parser.style_sheet_);
   }
   bool first_rule_valid = parser.ConsumeRuleList(
-      range, kTopLevelRuleList, [&style_sheet](StyleRuleBase* rule) {
+      stream, kTopLevelRuleList, [&style_sheet](StyleRuleBase* rule) {
         if (rule->IsCharsetRule())
           return;
         style_sheet->ParserAppendRule(rule);
@@ -318,29 +335,61 @@
   if (!range.AtEnd())
     return nullptr;
   CSSParserImpl parser(StrictCSSParserContext());
-  parser.ConsumeDeclarationList(block, StyleRule::kStyle);
-
-  // Drop nested @apply rules. Seems nicer to do this here instead of making
-  // a different StyleRule type
-  for (size_t i = parser.parsed_properties_.size(); i--;) {
-    if (parser.parsed_properties_[i].Id() == CSSPropertyApplyAtRule)
-      parser.parsed_properties_.EraseAt(i);
-  }
-
+  parser.ConsumeDeclarationListForAtApply(block);
   return CreateStylePropertySet(parser.parsed_properties_, kHTMLStandardMode);
 }
 
+void CSSParserImpl::ConsumeDeclarationListForAtApply(
+    CSSParserTokenRange range) {
+  DCHECK(parsed_properties_.IsEmpty());
+  DCHECK(RuntimeEnabledFeatures::CSSApplyAtRulesEnabled());
+  DCHECK(!observer_wrapper_);
+
+  while (!range.AtEnd()) {
+    switch (range.Peek().GetType()) {
+      case kWhitespaceToken:
+      case kSemicolonToken:
+        range.Consume();
+        break;
+      case kIdentToken: {
+        const CSSParserToken* declaration_start = &range.Peek();
+
+        while (!range.AtEnd() && range.Peek().GetType() != kSemicolonToken)
+          range.ConsumeComponentValue();
+
+        ConsumeDeclaration(range.MakeSubRange(declaration_start, &range.Peek()),
+                           RangeOffset::Ignore(), StyleRule::kStyle);
+
+        break;
+      }
+      case kAtKeywordToken: {
+        range.Consume();
+        while (!range.AtEnd() && range.Peek().GetType() != kLeftBraceToken &&
+               range.Peek().GetType() != kSemicolonToken)
+          range.ConsumeComponentValue();
+        range.ConsumeComponentValue();
+        break;
+      }
+      default:  // Parse error, unexpected token in declaration list
+        while (!range.AtEnd() && range.Peek().GetType() != kSemicolonToken)
+          range.ConsumeComponentValue();
+        break;
+    }
+  }
+}
+
 std::unique_ptr<Vector<double>> CSSParserImpl::ParseKeyframeKeyList(
     const String& key_list) {
   CSSTokenizer tokenizer(key_list);
   // TODO(shend): Use streams instead of ranges
-  return ConsumeKeyframeKeyList(
-      CSSParserTokenStream(tokenizer).MakeRangeToEOF());
+  return ConsumeKeyframeKeyList(CSSParserTokenRange(tokenizer.TokenizeToEOF()));
 }
 
 bool CSSParserImpl::SupportsDeclaration(CSSParserTokenRange& range) {
   DCHECK(parsed_properties_.IsEmpty());
-  ConsumeDeclaration(range, StyleRule::kStyle);
+  // Even though we might use an observer here, this is just to test if we
+  // successfully parse the range, so we can pass RangeOffset::Ignore() here.
+  ConsumeDeclaration(range, RangeOffset::Ignore(), StyleRule::kStyle);
   bool result = !parsed_properties_.IsEmpty();
   parsed_properties_.clear();
   return result;
@@ -353,7 +402,7 @@
   CSSParserImpl parser(context);
   CSSParserObserverWrapper wrapper(observer);
   parser.observer_wrapper_ = &wrapper;
-  CSSTokenizer tokenizer(declaration, wrapper);
+  CSSTokenizer tokenizer(declaration);
   observer.StartRuleHeader(StyleRule::kStyle, 0);
   observer.EndRuleHeader(1);
   CSSParserTokenStream stream(tokenizer);
@@ -367,23 +416,26 @@
   CSSParserImpl parser(context, style_sheet);
   CSSParserObserverWrapper wrapper(observer);
   parser.observer_wrapper_ = &wrapper;
-  CSSTokenizer tokenizer(string, wrapper);
-  // TODO(shend): Use streams instead of ranges
-  bool first_rule_valid =
-      parser.ConsumeRuleList(tokenizer.TokenRange(), kTopLevelRuleList,
-                             [&style_sheet](StyleRuleBase* rule) {
-                               if (rule->IsCharsetRule())
-                                 return;
-                               style_sheet->ParserAppendRule(rule);
-                             });
+  CSSTokenizer tokenizer(string);
+  CSSParserTokenStream stream(tokenizer);
+  bool first_rule_valid = parser.ConsumeRuleList(
+      stream, kTopLevelRuleList, [&style_sheet](StyleRuleBase* rule) {
+        if (rule->IsCharsetRule())
+          return;
+        style_sheet->ParserAppendRule(rule);
+      });
   style_sheet->SetHasSyntacticallyValidCSSHeader(first_rule_valid);
 }
 
 StylePropertySet* CSSParserImpl::ParseDeclarationListForLazyStyle(
-    CSSParserTokenRange block,
+    const String& string,
+    size_t offset,
     const CSSParserContext* context) {
+  CSSTokenizer tokenizer(string, offset);
+  CSSParserTokenStream stream(tokenizer);
+  CSSParserTokenStream::BlockGuard guard(stream);
   CSSParserImpl parser(context);
-  parser.ConsumeDeclarationList(std::move(block), StyleRule::kStyle);
+  parser.ConsumeDeclarationList(stream, StyleRule::kStyle);
   return CreateStylePropertySet(parser.parsed_properties_, context->Mode());
 }
 
@@ -402,7 +454,7 @@
 }
 
 template <typename T>
-bool CSSParserImpl::ConsumeRuleList(CSSParserTokenRange range,
+bool CSSParserImpl::ConsumeRuleList(CSSParserTokenStream& stream,
                                     RuleListType rule_list_type,
                                     const T callback) {
   AllowedRulesType allowed_rules = kRegularRules;
@@ -422,24 +474,24 @@
 
   bool seen_rule = false;
   bool first_rule_valid = false;
-  while (!range.AtEnd()) {
+  while (!stream.AtEnd()) {
     StyleRuleBase* rule;
-    switch (range.Peek().GetType()) {
+    switch (stream.UncheckedPeek().GetType()) {
       case kWhitespaceToken:
-        range.ConsumeWhitespace();
+        stream.UncheckedConsume();
         continue;
       case kAtKeywordToken:
-        rule = ConsumeAtRule(range, allowed_rules);
+        rule = ConsumeAtRule(stream, allowed_rules);
         break;
       case kCDOToken:
       case kCDCToken:
         if (rule_list_type == kTopLevelRuleList) {
-          range.Consume();
+          stream.UncheckedConsume();
           continue;
         }
       // fallthrough
       default:
-        rule = ConsumeQualifiedRule(range, allowed_rules);
+        rule = ConsumeQualifiedRule(stream, allowed_rules);
         break;
     }
     if (!seen_rule) {
@@ -461,23 +513,34 @@
   const StringView name = stream.ConsumeIncludingWhitespace().Value();
   const CSSAtRuleID id = CssAtRuleID(name);
 
-  const auto prelude_start = stream.Position();
-  while (!stream.AtEnd() &&
+  // @import rules have a URI component that is not technically part of the
+  // prelude.
+  AtomicString import_prelude_uri;
+  if (allowed_rules <= kAllowImportRules && id == kCSSAtRuleImport)
+    import_prelude_uri = ConsumeStringOrURI(stream);
+
+  stream.EnsureLookAhead();
+  CSSParserScopedTokenBuffer prelude_buffer(stream);
+  const size_t prelude_offset_start = stream.LookAheadOffset();
+  while (!stream.UncheckedAtEnd() &&
          stream.UncheckedPeek().GetType() != kLeftBraceToken &&
          stream.UncheckedPeek().GetType() != kSemicolonToken)
-    stream.UncheckedConsumeComponentValue();
+    stream.UncheckedConsumeComponentValue(prelude_buffer);
 
-  CSSParserTokenRange prelude =
-      stream.MakeSubRange(prelude_start, stream.Position());
+  const CSSParserTokenRange prelude = prelude_buffer.Range();
+  const RangeOffset prelude_offset(prelude_offset_start, stream.Offset());
+
   if (id != kCSSAtRuleInvalid && context_->IsUseCounterRecordingEnabled())
     CountAtRule(context_, id);
 
-  if (stream.AtEnd() || stream.Peek().GetType() == kSemicolonToken) {
-    stream.Consume();
+  if (stream.AtEnd() || stream.UncheckedPeek().GetType() == kSemicolonToken) {
+    stream.UncheckedConsume();
     if (allowed_rules == kAllowCharsetRules && id == kCSSAtRuleCharset)
       return ConsumeCharsetRule(prelude);
-    if (allowed_rules <= kAllowImportRules && id == kCSSAtRuleImport)
-      return ConsumeImportRule(prelude);
+    if (allowed_rules <= kAllowImportRules && id == kCSSAtRuleImport) {
+      return ConsumeImportRule(std::move(import_prelude_uri), prelude,
+                               prelude_offset);
+    }
     if (allowed_rules <= kAllowNamespaceRules && id == kCSSAtRuleNamespace)
       return ConsumeNamespaceRule(prelude);
     if (allowed_rules == kApplyRules && id == kCSSAtRuleApply) {
@@ -487,9 +550,6 @@
     return nullptr;  // Parse error, unrecognised at-rule without block
   }
 
-  // TODO(shend): Use streams instead of ranges
-  CSSParserTokenRange range = stream.MakeRangeToEOF();
-  CSSParserTokenRange block = range.ConsumeBlock();
   CSSParserTokenStream::BlockGuard guard(stream);
 
   if (allowed_rules == kKeyframeRules)
@@ -502,101 +562,72 @@
 
   switch (id) {
     case kCSSAtRuleMedia:
-      return ConsumeMediaRule(prelude, block);
+      return ConsumeMediaRule(std::move(prelude_buffer), prelude_offset,
+                              stream);
     case kCSSAtRuleSupports:
-      return ConsumeSupportsRule(prelude, block);
+      return ConsumeSupportsRule(std::move(prelude_buffer), prelude_offset,
+                                 stream);
     case kCSSAtRuleViewport:
-      return ConsumeViewportRule(prelude, block);
+      return ConsumeViewportRule(std::move(prelude_buffer), prelude_offset,
+                                 stream);
     case kCSSAtRuleFontFace:
-      return ConsumeFontFaceRule(prelude, stream);
+      return ConsumeFontFaceRule(std::move(prelude_buffer), prelude_offset,
+                                 stream);
     case kCSSAtRuleWebkitKeyframes:
-      return ConsumeKeyframesRule(true, prelude, block);
+      return ConsumeKeyframesRule(true, std::move(prelude_buffer),
+                                  prelude_offset, stream);
     case kCSSAtRuleKeyframes:
-      return ConsumeKeyframesRule(false, prelude, block);
+      return ConsumeKeyframesRule(false, std::move(prelude_buffer),
+                                  prelude_offset, stream);
     case kCSSAtRulePage:
-      return ConsumePageRule(prelude, block);
-    default:
-      return nullptr;  // Parse error, unrecognised at-rule with block
-  }
-}
-
-StyleRuleBase* CSSParserImpl::ConsumeAtRule(CSSParserTokenRange& range,
-                                            AllowedRulesType allowed_rules) {
-  DCHECK_EQ(range.Peek().GetType(), kAtKeywordToken);
-  const StringView name = range.ConsumeIncludingWhitespace().Value();
-  const CSSParserToken* prelude_start = &range.Peek();
-  while (!range.AtEnd() && range.Peek().GetType() != kLeftBraceToken &&
-         range.Peek().GetType() != kSemicolonToken)
-    range.ConsumeComponentValue();
-
-  CSSParserTokenRange prelude =
-      range.MakeSubRange(prelude_start, &range.Peek());
-  CSSAtRuleID id = CssAtRuleID(name);
-  if (id != kCSSAtRuleInvalid && context_->IsUseCounterRecordingEnabled())
-    CountAtRule(context_, id);
-
-  if (range.AtEnd() || range.Peek().GetType() == kSemicolonToken) {
-    range.Consume();
-    if (allowed_rules == kAllowCharsetRules && id == kCSSAtRuleCharset)
-      return ConsumeCharsetRule(prelude);
-    if (allowed_rules <= kAllowImportRules && id == kCSSAtRuleImport)
-      return ConsumeImportRule(prelude);
-    if (allowed_rules <= kAllowNamespaceRules && id == kCSSAtRuleNamespace)
-      return ConsumeNamespaceRule(prelude);
-    if (allowed_rules == kApplyRules && id == kCSSAtRuleApply) {
-      ConsumeApplyRule(prelude);
-      return nullptr;  // ConsumeApplyRule just updates parsed_properties_
-    }
-    return nullptr;  // Parse error, unrecognised at-rule without block
-  }
-
-  CSSParserTokenRange block = range.ConsumeBlock();
-  if (allowed_rules == kKeyframeRules)
-    return nullptr;  // Parse error, no at-rules supported inside @keyframes
-  if (allowed_rules == kNoRules || allowed_rules == kApplyRules)
-    return nullptr;  // Parse error, no at-rules with blocks supported inside
-                     // declaration lists
-
-  DCHECK_LE(allowed_rules, kRegularRules);
-
-  switch (id) {
-    case kCSSAtRuleMedia:
-      return ConsumeMediaRule(prelude, block);
-    case kCSSAtRuleSupports:
-      return ConsumeSupportsRule(prelude, block);
-    case kCSSAtRuleViewport:
-      return ConsumeViewportRule(prelude, block);
-    case kCSSAtRuleFontFace:
-      return ConsumeFontFaceRule(prelude, block);
-    case kCSSAtRuleWebkitKeyframes:
-      return ConsumeKeyframesRule(true, prelude, block);
-    case kCSSAtRuleKeyframes:
-      return ConsumeKeyframesRule(false, prelude, block);
-    case kCSSAtRulePage:
-      return ConsumePageRule(prelude, block);
+      return ConsumePageRule(std::move(prelude_buffer), prelude_offset, stream);
     default:
       return nullptr;  // Parse error, unrecognised at-rule with block
   }
 }
 
 StyleRuleBase* CSSParserImpl::ConsumeQualifiedRule(
-    CSSParserTokenRange& range,
+    CSSParserTokenStream& stream,
     AllowedRulesType allowed_rules) {
-  const CSSParserToken* prelude_start = &range.Peek();
-  while (!range.AtEnd() && range.Peek().GetType() != kLeftBraceToken)
-    range.ConsumeComponentValue();
+  DCHECK(stream.HasLookAhead());
+  const size_t prelude_offset_start = stream.LookAheadOffset();
+  CSSParserScopedTokenBuffer prelude_buffer(stream);
 
-  if (range.AtEnd())
+  if (observer_wrapper_) {
+    // TODO(shend): We need to store token offsets here because ConsumeStyleRule
+    // needs them in ObserveSelectors. We can get rid of this by making
+    // ConsumeStyleRule parse the prelude in a streaming fashion.
+    observer_wrapper_->StartConstruction();
+    while (!stream.UncheckedAtEnd() &&
+           stream.UncheckedPeek().GetType() != kLeftBraceToken) {
+      stream.UncheckedConsumeComponentValueWithOffsets(*observer_wrapper_,
+                                                       prelude_buffer);
+    }
+    // We want the offset of the kLeftBraceToken, which is peeked but not
+    // consumed.
+    observer_wrapper_->AddToken(stream.LookAheadOffset());
+  } else {
+    while (!stream.UncheckedAtEnd() &&
+           stream.UncheckedPeek().GetType() != kLeftBraceToken)
+      stream.UncheckedConsumeComponentValue(prelude_buffer);
+  }
+
+  if (stream.AtEnd())
     return nullptr;  // Parse error, EOF instead of qualified rule block
 
-  CSSParserTokenRange prelude =
-      range.MakeSubRange(prelude_start, &range.Peek());
-  CSSParserTokenRange block = range.ConsumeBlock();
+  const RangeOffset prelude_offset(prelude_offset_start, stream.Offset());
+
+  if (observer_wrapper_)
+    observer_wrapper_->FinalizeConstruction(prelude_buffer.Range().begin());
+
+  CSSParserTokenStream::BlockGuard guard(stream);
 
   if (allowed_rules <= kRegularRules)
-    return ConsumeStyleRule(prelude, block);
-  if (allowed_rules == kKeyframeRules)
-    return ConsumeKeyframeStyleRule(prelude, block);
+    return ConsumeStyleRule(std::move(prelude_buffer), prelude_offset, stream);
+  if (allowed_rules == kKeyframeRules) {
+    return ConsumeKeyframeStyleRule(std::move(prelude_buffer), prelude_offset,
+                                    stream);
+  }
 
   NOTREACHED();
   return nullptr;
@@ -629,18 +660,19 @@
   return StyleRuleCharset::Create();
 }
 
-StyleRuleImport* CSSParserImpl::ConsumeImportRule(CSSParserTokenRange prelude) {
-  AtomicString uri(ConsumeStringOrURI(prelude));
+StyleRuleImport* CSSParserImpl::ConsumeImportRule(
+    AtomicString uri,
+    CSSParserTokenRange prelude,
+    const RangeOffset& prelude_offset) {
   if (uri.IsNull())
     return nullptr;  // Parse error, expected string or URI
 
   if (observer_wrapper_) {
-    unsigned end_offset = observer_wrapper_->EndOffset(prelude);
-    observer_wrapper_->Observer().StartRuleHeader(
-        StyleRule::kImport, observer_wrapper_->StartOffset(prelude));
-    observer_wrapper_->Observer().EndRuleHeader(end_offset);
-    observer_wrapper_->Observer().StartRuleBody(end_offset);
-    observer_wrapper_->Observer().EndRuleBody(end_offset);
+    observer_wrapper_->Observer().StartRuleHeader(StyleRule::kImport,
+                                                  prelude_offset.start);
+    observer_wrapper_->Observer().EndRuleHeader(prelude_offset.end);
+    observer_wrapper_->Observer().StartRuleBody(prelude_offset.end);
+    observer_wrapper_->Observer().EndRuleBody(prelude_offset.end);
   }
 
   return StyleRuleImport::Create(uri,
@@ -661,36 +693,40 @@
   return StyleRuleNamespace::Create(namespace_prefix, uri);
 }
 
-StyleRuleMedia* CSSParserImpl::ConsumeMediaRule(CSSParserTokenRange prelude,
-                                                CSSParserTokenRange block) {
+StyleRuleMedia* CSSParserImpl::ConsumeMediaRule(
+    CSSParserScopedTokenBuffer prelude_buffer,
+    const RangeOffset& prelude_offset,
+    CSSParserTokenStream& block) {
   HeapVector<Member<StyleRuleBase>> rules;
 
   if (observer_wrapper_) {
-    observer_wrapper_->Observer().StartRuleHeader(
-        StyleRule::kMedia, observer_wrapper_->StartOffset(prelude));
-    observer_wrapper_->Observer().EndRuleHeader(
-        observer_wrapper_->EndOffset(prelude));
-    observer_wrapper_->Observer().StartRuleBody(
-        observer_wrapper_->PreviousTokenStartOffset(block));
+    observer_wrapper_->Observer().StartRuleHeader(StyleRule::kMedia,
+                                                  prelude_offset.start);
+    observer_wrapper_->Observer().EndRuleHeader(prelude_offset.end);
+    observer_wrapper_->Observer().StartRuleBody(block.Offset());
   }
 
   if (style_sheet_)
     style_sheet_->SetHasMediaQueries();
 
+  const auto media =
+      MediaQueryParser::ParseMediaQuerySet(prelude_buffer.Range());
+
+  prelude_buffer.Release();
   ConsumeRuleList(block, kRegularRuleList,
                   [&rules](StyleRuleBase* rule) { rules.push_back(rule); });
 
   if (observer_wrapper_)
-    observer_wrapper_->Observer().EndRuleBody(
-        observer_wrapper_->EndOffset(block));
+    observer_wrapper_->Observer().EndRuleBody(block.Offset());
 
-  return StyleRuleMedia::Create(MediaQueryParser::ParseMediaQuerySet(prelude),
-                                rules);
+  return StyleRuleMedia::Create(media, rules);
 }
 
 StyleRuleSupports* CSSParserImpl::ConsumeSupportsRule(
-    CSSParserTokenRange prelude,
-    CSSParserTokenRange block) {
+    CSSParserScopedTokenBuffer prelude_buffer,
+    const RangeOffset& prelude_offset,
+    CSSParserTokenStream& block) {
+  const CSSParserTokenRange prelude = prelude_buffer.Range();
   CSSSupportsParser::SupportsResult supported =
       CSSSupportsParser::SupportsCondition(prelude, *this,
                                            CSSSupportsParser::kForAtRule);
@@ -698,29 +734,30 @@
     return nullptr;  // Parse error, invalid @supports condition
 
   if (observer_wrapper_) {
-    observer_wrapper_->Observer().StartRuleHeader(
-        StyleRule::kSupports, observer_wrapper_->StartOffset(prelude));
-    observer_wrapper_->Observer().EndRuleHeader(
-        observer_wrapper_->EndOffset(prelude));
-    observer_wrapper_->Observer().StartRuleBody(
-        observer_wrapper_->PreviousTokenStartOffset(block));
+    observer_wrapper_->Observer().StartRuleHeader(StyleRule::kSupports,
+                                                  prelude_offset.start);
+    observer_wrapper_->Observer().EndRuleHeader(prelude_offset.end);
+    observer_wrapper_->Observer().StartRuleBody(block.Offset());
   }
 
+  const auto prelude_serialized = prelude.Serialize().StripWhiteSpace();
+  prelude_buffer.Release();
+
   HeapVector<Member<StyleRuleBase>> rules;
   ConsumeRuleList(block, kRegularRuleList,
                   [&rules](StyleRuleBase* rule) { rules.push_back(rule); });
 
   if (observer_wrapper_)
-    observer_wrapper_->Observer().EndRuleBody(
-        observer_wrapper_->EndOffset(block));
+    observer_wrapper_->Observer().EndRuleBody(block.Offset());
 
-  return StyleRuleSupports::Create(prelude.Serialize().StripWhiteSpace(),
-                                   supported, rules);
+  return StyleRuleSupports::Create(prelude_serialized, supported, rules);
 }
 
 StyleRuleViewport* CSSParserImpl::ConsumeViewportRule(
-    CSSParserTokenRange prelude,
-    CSSParserTokenRange block) {
+    CSSParserScopedTokenBuffer prelude_buffer,
+    const RangeOffset& prelude_offset,
+    CSSParserTokenStream& block) {
+  const CSSParserTokenRange prelude = prelude_buffer.Range();
   // Allow @viewport rules from UA stylesheets even if the feature is disabled.
   if (!RuntimeEnabledFeatures::CSSViewportEnabled() &&
       !IsUASheetBehavior(context_->Mode()))
@@ -730,73 +767,53 @@
     return nullptr;  // Parser error; @viewport prelude should be empty
 
   if (observer_wrapper_) {
-    unsigned end_offset = observer_wrapper_->EndOffset(prelude);
-    observer_wrapper_->Observer().StartRuleHeader(
-        StyleRule::kViewport, observer_wrapper_->StartOffset(prelude));
-    observer_wrapper_->Observer().EndRuleHeader(end_offset);
-    observer_wrapper_->Observer().StartRuleBody(end_offset);
-    observer_wrapper_->Observer().EndRuleBody(end_offset);
+    observer_wrapper_->Observer().StartRuleHeader(StyleRule::kViewport,
+                                                  prelude_offset.start);
+    observer_wrapper_->Observer().EndRuleHeader(prelude_offset.end);
+    observer_wrapper_->Observer().StartRuleBody(prelude_offset.end);
+    observer_wrapper_->Observer().EndRuleBody(prelude_offset.end);
   }
 
   if (style_sheet_)
     style_sheet_->SetHasViewportRule();
 
+  prelude_buffer.Release();
   ConsumeDeclarationList(block, StyleRule::kViewport);
   return StyleRuleViewport::Create(
       CreateStylePropertySet(parsed_properties_, kCSSViewportRuleMode));
 }
 
 StyleRuleFontFace* CSSParserImpl::ConsumeFontFaceRule(
-    CSSParserTokenRange prelude,
+    CSSParserScopedTokenBuffer prelude_buffer,
+    const RangeOffset& prelude_offset,
     CSSParserTokenStream& stream) {
+  const CSSParserTokenRange prelude = prelude_buffer.Range();
   if (!prelude.AtEnd())
     return nullptr;  // Parse error; @font-face prelude should be empty
 
   if (observer_wrapper_) {
-    unsigned end_offset = observer_wrapper_->EndOffset(prelude);
-    observer_wrapper_->Observer().StartRuleHeader(
-        StyleRule::kFontFace, observer_wrapper_->StartOffset(prelude));
-    observer_wrapper_->Observer().EndRuleHeader(end_offset);
-    observer_wrapper_->Observer().StartRuleBody(end_offset);
-    observer_wrapper_->Observer().EndRuleBody(end_offset);
+    observer_wrapper_->Observer().StartRuleHeader(StyleRule::kFontFace,
+                                                  prelude_offset.start);
+    observer_wrapper_->Observer().EndRuleHeader(prelude_offset.end);
+    observer_wrapper_->Observer().StartRuleBody(prelude_offset.end);
+    observer_wrapper_->Observer().EndRuleBody(prelude_offset.end);
   }
 
   if (style_sheet_)
     style_sheet_->SetHasFontFaceRule();
 
+  prelude_buffer.Release();
   ConsumeDeclarationList(stream, StyleRule::kFontFace);
   return StyleRuleFontFace::Create(
       CreateStylePropertySet(parsed_properties_, kCSSFontFaceRuleMode));
 }
 
-StyleRuleFontFace* CSSParserImpl::ConsumeFontFaceRule(
-    CSSParserTokenRange prelude,
-    CSSParserTokenRange block) {
-  if (!prelude.AtEnd())
-    return nullptr;  // Parse error; @font-face prelude should be empty
-
-  if (observer_wrapper_) {
-    unsigned end_offset = observer_wrapper_->EndOffset(prelude);
-    observer_wrapper_->Observer().StartRuleHeader(
-        StyleRule::kFontFace, observer_wrapper_->StartOffset(prelude));
-    observer_wrapper_->Observer().EndRuleHeader(end_offset);
-    observer_wrapper_->Observer().StartRuleBody(end_offset);
-    observer_wrapper_->Observer().EndRuleBody(end_offset);
-  }
-
-  if (style_sheet_)
-    style_sheet_->SetHasFontFaceRule();
-
-  ConsumeDeclarationList(block, StyleRule::kFontFace);
-  return StyleRuleFontFace::Create(
-      CreateStylePropertySet(parsed_properties_, kCSSFontFaceRuleMode));
-}
-
 StyleRuleKeyframes* CSSParserImpl::ConsumeKeyframesRule(
     bool webkit_prefixed,
-    CSSParserTokenRange prelude,
-    CSSParserTokenRange block) {
-  CSSParserTokenRange range_copy = prelude;  // For inspector callbacks
+    CSSParserScopedTokenBuffer prelude_buffer,
+    const RangeOffset& prelude_offset,
+    CSSParserTokenStream& block) {
+  auto prelude = prelude_buffer.Range();
   const CSSParserToken& name_token = prelude.ConsumeIncludingWhitespace();
   if (!prelude.AtEnd())
     return nullptr;  // Parse error; expected single non-whitespace token in
@@ -813,16 +830,14 @@
   }
 
   if (observer_wrapper_) {
-    observer_wrapper_->Observer().StartRuleHeader(
-        StyleRule::kKeyframes, observer_wrapper_->StartOffset(range_copy));
-    observer_wrapper_->Observer().EndRuleHeader(
-        observer_wrapper_->EndOffset(prelude));
-    observer_wrapper_->Observer().StartRuleBody(
-        observer_wrapper_->PreviousTokenStartOffset(block));
-    observer_wrapper_->Observer().EndRuleBody(
-        observer_wrapper_->EndOffset(block));
+    observer_wrapper_->Observer().StartRuleHeader(StyleRule::kKeyframes,
+                                                  prelude_offset.start);
+    observer_wrapper_->Observer().EndRuleHeader(prelude_offset.end);
+    observer_wrapper_->Observer().StartRuleBody(block.Offset());
   }
 
+  prelude_buffer.Release();
+
   StyleRuleKeyframes* keyframe_rule = StyleRuleKeyframes::Create();
   ConsumeRuleList(
       block, kKeyframesRuleList, [keyframe_rule](StyleRuleBase* keyframe) {
@@ -830,22 +845,29 @@
       });
   keyframe_rule->SetName(name);
   keyframe_rule->SetVendorPrefixed(webkit_prefixed);
+
+  if (observer_wrapper_)
+    observer_wrapper_->Observer().EndRuleBody(block.Offset());
+
   return keyframe_rule;
 }
 
-StyleRulePage* CSSParserImpl::ConsumePageRule(CSSParserTokenRange prelude,
-                                              CSSParserTokenRange block) {
+StyleRulePage* CSSParserImpl::ConsumePageRule(
+    CSSParserScopedTokenBuffer prelude_buffer,
+    const RangeOffset& prelude_offset,
+    CSSParserTokenStream& block) {
+  const CSSParserTokenRange prelude = prelude_buffer.Range();
   CSSSelectorList selector_list = ParsePageSelector(prelude, style_sheet_);
   if (!selector_list.IsValid())
     return nullptr;  // Parse error, invalid @page selector
 
   if (observer_wrapper_) {
-    unsigned end_offset = observer_wrapper_->EndOffset(prelude);
-    observer_wrapper_->Observer().StartRuleHeader(
-        StyleRule::kPage, observer_wrapper_->StartOffset(prelude));
-    observer_wrapper_->Observer().EndRuleHeader(end_offset);
+    observer_wrapper_->Observer().StartRuleHeader(StyleRule::kPage,
+                                                  prelude_offset.start);
+    observer_wrapper_->Observer().EndRuleHeader(prelude_offset.end);
   }
 
+  prelude_buffer.Release();
   ConsumeDeclarationList(block, StyleRule::kStyle);
 
   return StyleRulePage::Create(
@@ -865,20 +887,23 @@
 }
 
 StyleRuleKeyframe* CSSParserImpl::ConsumeKeyframeStyleRule(
-    CSSParserTokenRange prelude,
-    CSSParserTokenRange block) {
+    CSSParserScopedTokenBuffer prelude_buffer,
+    const RangeOffset& prelude_offset,
+    CSSParserTokenStream& block) {
+  const CSSParserTokenRange prelude = prelude_buffer.Range();
   std::unique_ptr<Vector<double>> key_list = ConsumeKeyframeKeyList(prelude);
   if (!key_list)
     return nullptr;
 
   if (observer_wrapper_) {
-    observer_wrapper_->Observer().StartRuleHeader(
-        StyleRule::kKeyframe, observer_wrapper_->StartOffset(prelude));
-    observer_wrapper_->Observer().EndRuleHeader(
-        observer_wrapper_->EndOffset(prelude));
+    observer_wrapper_->Observer().StartRuleHeader(StyleRule::kKeyframe,
+                                                  prelude_offset.start);
+    observer_wrapper_->Observer().EndRuleHeader(prelude_offset.end);
   }
 
+  prelude_buffer.Release();
   ConsumeDeclarationList(block, StyleRule::kKeyframe);
+
   return StyleRuleKeyframe::Create(
       std::move(key_list),
       CreateStylePropertySet(parsed_properties_, context_->Mode()));
@@ -907,8 +932,11 @@
   wrapper.Observer().EndRuleHeader(wrapper.EndOffset(original_range));
 }
 
-StyleRule* CSSParserImpl::ConsumeStyleRule(CSSParserTokenRange prelude,
-                                           CSSParserTokenRange block) {
+StyleRule* CSSParserImpl::ConsumeStyleRule(
+    CSSParserScopedTokenBuffer prelude_buffer,
+    const RangeOffset& prelude_offset,
+    CSSParserTokenStream& block) {
+  const CSSParserTokenRange prelude = prelude_buffer.Range();
   CSSSelectorList selector_list =
       CSSSelectorParser::ParseSelector(prelude, context_, style_sheet_);
   if (!selector_list.IsValid())
@@ -917,11 +945,15 @@
   // TODO(csharrison): How should we lazily parse css that needs the observer?
   if (observer_wrapper_) {
     ObserveSelectors(*observer_wrapper_, prelude);
-  } else if (lazy_state_ && !lazy_state_->IsEmptyBlock(block)) {
+  } else if (lazy_state_) {
+    // TODO(shend): Don't lazily parse empty blocks.
     DCHECK(style_sheet_);
-    return StyleRule::CreateLazy(std::move(selector_list),
-                                 lazy_state_->CreateLazyParser(block));
+    return StyleRule::CreateLazy(
+        std::move(selector_list),
+        lazy_state_->CreateLazyParser(block.Offset() - 1));
   }
+
+  prelude_buffer.Release();
   ConsumeDeclarationList(block, StyleRule::kStyle);
 
   return StyleRule::Create(
@@ -936,33 +968,49 @@
   bool use_observer = observer_wrapper_ && (rule_type == StyleRule::kStyle ||
                                             rule_type == StyleRule::kKeyframe);
   if (use_observer) {
-    observer_wrapper_->Observer().StartRuleBody(
-        observer_wrapper_->PreviousTokenStartOffset(stream));
-    observer_wrapper_->SkipCommentsBefore(stream, true);
+    observer_wrapper_->Observer().StartRuleBody(stream.Offset());
   }
 
-  while (!stream.AtEnd()) {
+  while (true) {
+    // Having a lookahead may skip comments, which are used by the observer.
+    DCHECK(!stream.HasLookAhead() || stream.AtEnd());
+
+    if (use_observer && !stream.HasLookAhead()) {
+      while (true) {
+        size_t start_offset = stream.Offset();
+        if (!stream.ConsumeCommentOrNothing())
+          break;
+        observer_wrapper_->Observer().ObserveComment(start_offset,
+                                                     stream.Offset());
+      }
+    }
+
+    if (stream.AtEnd())
+      break;
+
     switch (stream.UncheckedPeek().GetType()) {
       case kWhitespaceToken:
       case kSemicolonToken:
         stream.UncheckedConsume();
         break;
       case kIdentToken: {
-        if (use_observer)
-          observer_wrapper_->YieldCommentsBefore(stream);
-
-        const auto declaration_start = stream.Position();
-        while (!stream.AtEnd() &&
-               stream.UncheckedPeek().GetType() != kSemicolonToken)
-          stream.UncheckedConsumeComponentValue();
+        const size_t decl_offset_start = stream.Offset();
+        CSSParserScopedTokenBuffer decl_buffer(stream);
+        while (!stream.UncheckedAtEnd() &&
+               stream.UncheckedPeek().GetType() != kSemicolonToken) {
+          stream.UncheckedConsumeComponentValue(decl_buffer);
+        }
 
         // TODO(shend): Use streams instead of ranges
-        ConsumeDeclaration(
-            stream.MakeSubRange(declaration_start, stream.Position()),
-            rule_type);
+        // We want the offset of the kSemicolonToken, which is peeked but not
+        // consumed.
+        const RangeOffset decl_offset(decl_offset_start,
+                                      stream.LookAheadOffset());
+        ConsumeDeclaration(decl_buffer.Range(), decl_offset, rule_type);
 
-        if (use_observer)
-          observer_wrapper_->SkipCommentsBefore(stream, false);
+        if (!stream.AtEnd())
+          stream.UncheckedConsume();  // kSemicolonToken
+
         break;
       }
       case kAtKeywordToken: {
@@ -976,85 +1024,26 @@
         DCHECK(!rule);
         break;
       }
-      default:  // Parse error, unexpected token in declaration list
-        while (!stream.AtEnd() &&
-               stream.UncheckedPeek().GetType() != kSemicolonToken)
+      default:
+        while (!stream.UncheckedAtEnd() &&
+               stream.UncheckedPeek().GetType() != kSemicolonToken) {
           stream.UncheckedConsumeComponentValue();
+        }
+
+        if (!stream.UncheckedAtEnd())
+          stream.UncheckedConsume();  // kSemicolonToken
+
         break;
     }
   }
 
-  // Yield remaining comments
-  if (use_observer) {
-    observer_wrapper_->YieldCommentsBefore(stream);
-    observer_wrapper_->Observer().EndRuleBody(
-        observer_wrapper_->EndOffset(stream));
-  }
-}
-
-void CSSParserImpl::ConsumeDeclarationList(CSSParserTokenRange range,
-                                           StyleRule::RuleType rule_type) {
-  DCHECK(parsed_properties_.IsEmpty());
-
-  bool use_observer = observer_wrapper_ && (rule_type == StyleRule::kStyle ||
-                                            rule_type == StyleRule::kKeyframe);
-  if (use_observer) {
-    observer_wrapper_->Observer().StartRuleBody(
-        observer_wrapper_->PreviousTokenStartOffset(range));
-    observer_wrapper_->SkipCommentsBefore(range, true);
-  }
-
-  while (!range.AtEnd()) {
-    switch (range.Peek().GetType()) {
-      case kWhitespaceToken:
-      case kSemicolonToken:
-        range.Consume();
-        break;
-      case kIdentToken: {
-        const CSSParserToken* declaration_start = &range.Peek();
-
-        if (use_observer)
-          observer_wrapper_->YieldCommentsBefore(range);
-
-        while (!range.AtEnd() && range.Peek().GetType() != kSemicolonToken)
-          range.ConsumeComponentValue();
-
-        ConsumeDeclaration(range.MakeSubRange(declaration_start, &range.Peek()),
-                           rule_type);
-
-        if (use_observer)
-          observer_wrapper_->SkipCommentsBefore(range, false);
-        break;
-      }
-      case kAtKeywordToken: {
-        AllowedRulesType allowed_rules =
-            rule_type == StyleRule::kStyle &&
-                    RuntimeEnabledFeatures::CSSApplyAtRulesEnabled()
-                ? kApplyRules
-                : kNoRules;
-        StyleRuleBase* rule = ConsumeAtRule(range, allowed_rules);
-        DCHECK(!rule);
-        break;
-      }
-      default:  // Parse error, unexpected token in declaration list
-        while (!range.AtEnd() && range.Peek().GetType() != kSemicolonToken)
-          range.ConsumeComponentValue();
-        break;
-    }
-  }
-
-  // Yield remaining comments
-  if (use_observer) {
-    observer_wrapper_->YieldCommentsBefore(range);
-    observer_wrapper_->Observer().EndRuleBody(
-        observer_wrapper_->EndOffset(range));
-  }
+  if (use_observer)
+    observer_wrapper_->Observer().EndRuleBody(stream.LookAheadOffset());
 }
 
 void CSSParserImpl::ConsumeDeclaration(CSSParserTokenRange range,
+                                       const RangeOffset& decl_offset,
                                        StyleRule::RuleType rule_type) {
-  CSSParserTokenRange range_copy = range;  // For inspector callbacks
-
   DCHECK_EQ(range.Peek().GetType(), kIdentToken);
   const CSSParserToken& token = range.ConsumeIncludingWhitespace();
   CSSPropertyID unresolved_property = token.ParseAsUnresolvedCSSPropertyID();
@@ -1103,8 +1092,7 @@
   if (observer_wrapper_ &&
       (rule_type == StyleRule::kStyle || rule_type == StyleRule::kKeyframe)) {
     observer_wrapper_->Observer().ObserveProperty(
-        observer_wrapper_->StartOffset(range_copy),
-        observer_wrapper_->EndOffset(range_copy), important,
+        decl_offset.start, decl_offset.end, important,
         parsed_properties_.size() != properties_count);
   }
 }
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h
index f7499de..3b75a7c 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h
@@ -21,6 +21,7 @@
 class CSSParserContext;
 class CSSParserObserver;
 class CSSParserObserverWrapper;
+class CSSParserScopedTokenBuffer;
 class CSSParserTokenStream;
 class StyleRule;
 class StyleRuleBase;
@@ -59,6 +60,19 @@
     kNoRules,     // For parsing at-rules inside declaration lists
   };
 
+  // Represents the start and end offsets of a CSSParserTokenRange.
+  struct RangeOffset {
+    size_t start, end;
+
+    RangeOffset(size_t start, size_t end) : start(start), end(end) {
+      DCHECK(start <= end);
+    }
+
+    // Used when we don't care what the offset is (typically when we don't have
+    // an observer).
+    static RangeOffset Ignore() { return {0, 0}; }
+  };
+
   static MutableStylePropertySet::SetResult ParseValue(MutableStylePropertySet*,
                                                        CSSPropertyID,
                                                        const String&,
@@ -89,6 +103,10 @@
                                            StyleSheetContents*);
 
   static ImmutableStylePropertySet* ParseCustomPropertySet(CSSParserTokenRange);
+  // TODO(shend): Remove this when crbug.com/661854 is fixed. We need to use a
+  // stream for parsing @apply blocks so we can correctly store custom
+  // property values.
+  void ConsumeDeclarationListForAtApply(CSSParserTokenRange);
 
   static std::unique_ptr<Vector<double>> ParseKeyframeKeyList(const String&);
 
@@ -103,7 +121,8 @@
                                           CSSParserObserver&);
 
   static StylePropertySet* ParseDeclarationListForLazyStyle(
-      CSSParserTokenRange block,
+      const String&,
+      size_t offset,
       const CSSParserContext*);
 
  private:
@@ -111,45 +130,55 @@
 
   // Returns whether the first encountered rule was valid
   template <typename T>
-  bool ConsumeRuleList(CSSParserTokenRange, RuleListType, T callback);
+  bool ConsumeRuleList(CSSParserTokenStream&, RuleListType, T callback);
 
   // These functions update the range/stream they're given
   StyleRuleBase* ConsumeAtRule(CSSParserTokenStream&, AllowedRulesType);
-  // TODO(shend): Remove this overload once we switch over to streams.
-  StyleRuleBase* ConsumeAtRule(CSSParserTokenRange&, AllowedRulesType);
-  StyleRuleBase* ConsumeQualifiedRule(CSSParserTokenRange&, AllowedRulesType);
+  StyleRuleBase* ConsumeQualifiedRule(CSSParserTokenStream&, AllowedRulesType);
 
   static StyleRuleCharset* ConsumeCharsetRule(CSSParserTokenRange prelude);
-  StyleRuleImport* ConsumeImportRule(CSSParserTokenRange prelude);
+  StyleRuleImport* ConsumeImportRule(AtomicString prelude_uri,
+                                     CSSParserTokenRange prelude,
+                                     const RangeOffset& prelude_offset);
   StyleRuleNamespace* ConsumeNamespaceRule(CSSParserTokenRange prelude);
-  StyleRuleMedia* ConsumeMediaRule(CSSParserTokenRange prelude,
-                                   CSSParserTokenRange block);
-  StyleRuleSupports* ConsumeSupportsRule(CSSParserTokenRange prelude,
-                                         CSSParserTokenRange block);
-  StyleRuleViewport* ConsumeViewportRule(CSSParserTokenRange prelude,
-                                         CSSParserTokenRange block);
-  StyleRuleFontFace* ConsumeFontFaceRule(CSSParserTokenRange prelude,
-                                         CSSParserTokenStream& block);
-  // TODO(shend): Remove this overload once we switch over to streams.
-  StyleRuleFontFace* ConsumeFontFaceRule(CSSParserTokenRange prelude,
-                                         CSSParserTokenRange block);
-  StyleRuleKeyframes* ConsumeKeyframesRule(bool webkit_prefixed,
-                                           CSSParserTokenRange prelude,
-                                           CSSParserTokenRange block);
-  StyleRulePage* ConsumePageRule(CSSParserTokenRange prelude,
-                                 CSSParserTokenRange block);
+  StyleRuleMedia* ConsumeMediaRule(CSSParserScopedTokenBuffer prelude_buffer,
+                                   const RangeOffset& prelude_offset,
+                                   CSSParserTokenStream& block);
+  StyleRuleSupports* ConsumeSupportsRule(
+      CSSParserScopedTokenBuffer prelude_buffer,
+      const RangeOffset& prelude_offset,
+      CSSParserTokenStream& block);
+  StyleRuleViewport* ConsumeViewportRule(
+      CSSParserScopedTokenBuffer prelude_buffer,
+      const RangeOffset& prelude_offset,
+      CSSParserTokenStream& block);
+  StyleRuleFontFace* ConsumeFontFaceRule(
+      CSSParserScopedTokenBuffer prelude_buffer,
+      const RangeOffset& prelude_offset,
+      CSSParserTokenStream& block);
+  StyleRuleKeyframes* ConsumeKeyframesRule(
+      bool webkit_prefixed,
+      CSSParserScopedTokenBuffer prelude_buffer,
+      const RangeOffset& prelude_offset,
+      CSSParserTokenStream& block);
+  StyleRulePage* ConsumePageRule(CSSParserScopedTokenBuffer prelude_buffer,
+                                 const RangeOffset& prelude_offset,
+                                 CSSParserTokenStream& block);
   // Updates parsed_properties_
   void ConsumeApplyRule(CSSParserTokenRange prelude);
 
-  StyleRuleKeyframe* ConsumeKeyframeStyleRule(CSSParserTokenRange prelude,
-                                              CSSParserTokenRange block);
-  StyleRule* ConsumeStyleRule(CSSParserTokenRange prelude,
-                              CSSParserTokenRange block);
+  StyleRuleKeyframe* ConsumeKeyframeStyleRule(
+      CSSParserScopedTokenBuffer prelude_buffer,
+      const RangeOffset& prelude_offset,
+      CSSParserTokenStream& block);
+  StyleRule* ConsumeStyleRule(CSSParserScopedTokenBuffer prelude_buffer,
+                              const RangeOffset& prelude_offset,
+                              CSSParserTokenStream& block);
 
   void ConsumeDeclarationList(CSSParserTokenStream&, StyleRule::RuleType);
-  // TODO(shend): Remove this overload once we switch over to streams.
-  void ConsumeDeclarationList(CSSParserTokenRange, StyleRule::RuleType);
-  void ConsumeDeclaration(CSSParserTokenRange, StyleRule::RuleType);
+  void ConsumeDeclaration(CSSParserTokenRange,
+                          const RangeOffset& decl_offset,
+                          StyleRule::RuleType);
   void ConsumeDeclarationValue(CSSParserTokenRange,
                                CSSPropertyID,
                                bool important,
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserObserverWrapper.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserObserverWrapper.cpp
index ec40e1e..030fb811 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserObserverWrapper.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserObserverWrapper.cpp
@@ -10,40 +10,15 @@
 
 unsigned CSSParserObserverWrapper::StartOffset(
     const CSSParserTokenRange& range) {
+  const size_t index = range.begin() - first_parser_token_;
+  DCHECK_LT(index, token_offsets_.size());
   return token_offsets_[range.begin() - first_parser_token_];
 }
 
-unsigned CSSParserObserverWrapper::PreviousTokenStartOffset(
-    const CSSParserTokenRange& range) {
-  if (range.begin() == first_parser_token_)
-    return 0;
-  return token_offsets_[range.begin() - first_parser_token_ - 1];
-}
-
 unsigned CSSParserObserverWrapper::EndOffset(const CSSParserTokenRange& range) {
-  return token_offsets_[range.end() - first_parser_token_];
-}
-
-void CSSParserObserverWrapper::SkipCommentsBefore(
-    const CSSParserTokenRange& range,
-    bool leave_directly_before) {
-  unsigned start_index = range.begin() - first_parser_token_;
-  if (!leave_directly_before)
-    start_index++;
-  while (comment_iterator_ < comment_offsets_.end() &&
-         comment_iterator_->tokens_before < start_index)
-    comment_iterator_++;
-}
-
-void CSSParserObserverWrapper::YieldCommentsBefore(
-    const CSSParserTokenRange& range) {
-  unsigned start_index = range.begin() - first_parser_token_;
-  while (comment_iterator_ < comment_offsets_.end() &&
-         comment_iterator_->tokens_before <= start_index) {
-    observer_.ObserveComment(comment_iterator_->start_offset,
-                             comment_iterator_->end_offset);
-    comment_iterator_++;
-  }
+  size_t index = range.end() - first_parser_token_;
+  DCHECK_LT(index, token_offsets_.size());
+  return token_offsets_[index];
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserObserverWrapper.h b/third_party/WebKit/Source/core/css/parser/CSSParserObserverWrapper.h
index c4502e5..2dd6b24 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserObserverWrapper.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserObserverWrapper.h
@@ -24,62 +24,26 @@
       : observer_(observer) {}
 
   unsigned StartOffset(const CSSParserTokenRange&);
-  unsigned PreviousTokenStartOffset(const CSSParserTokenRange&);
-  unsigned EndOffset(const CSSParserTokenRange&);  // Includes trailing comments
-
-  void SkipCommentsBefore(const CSSParserTokenRange&,
-                          bool leave_directly_before);
-  void YieldCommentsBefore(const CSSParserTokenRange&);
-
-  // Overloads that work with streams
-  unsigned StartOffset(CSSParserTokenStream& stream) {
-    return StartOffset(stream.MakeSubRangeAtCurrentPosition());
-  }
-  unsigned PreviousTokenStartOffset(CSSParserTokenStream& stream) {
-    return PreviousTokenStartOffset(stream.MakeSubRangeAtCurrentPosition());
-  }
-  unsigned EndOffset(CSSParserTokenStream& stream) {
-    return EndOffset(stream.MakeSubRangeAtCurrentPosition());
-  }
-
-  void SkipCommentsBefore(CSSParserTokenStream& stream,
-                          bool leave_directly_before) {
-    return SkipCommentsBefore(stream.MakeSubRangeAtCurrentPosition(),
-                              leave_directly_before);
-  }
-  void YieldCommentsBefore(CSSParserTokenStream& stream) {
-    return YieldCommentsBefore(stream.MakeSubRangeAtCurrentPosition());
-  }
+  unsigned EndOffset(const CSSParserTokenRange&);
 
   CSSParserObserver& Observer() { return observer_; }
-  void AddComment(unsigned start_offset,
-                  unsigned end_offset,
-                  unsigned tokens_before) {
-    CommentPosition position = {start_offset, end_offset, tokens_before};
-    comment_offsets_.push_back(position);
-  }
+
   void AddToken(unsigned start_offset) {
     token_offsets_.push_back(start_offset);
   }
-  void FinalizeConstruction(CSSParserToken* first_parser_token) {
+
+  void StartConstruction() {
+    token_offsets_.clear();
+    first_parser_token_ = nullptr;
+  }
+  void FinalizeConstruction(const CSSParserToken* first_parser_token) {
     first_parser_token_ = first_parser_token;
-    comment_iterator_ = comment_offsets_.begin();
   }
 
  private:
   CSSParserObserver& observer_;
   Vector<unsigned> token_offsets_;
-  CSSParserToken* first_parser_token_;
-
-  struct CommentPosition {
-    DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
-    unsigned start_offset;
-    unsigned end_offset;
-    unsigned tokens_before;
-  };
-
-  Vector<CommentPosition> comment_offsets_;
-  Vector<CommentPosition>::iterator comment_iterator_;
+  const CSSParserToken* first_parser_token_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserScopedTokenBuffer.h b/third_party/WebKit/Source/core/css/parser/CSSParserScopedTokenBuffer.h
new file mode 100644
index 0000000..28df5fdd
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserScopedTokenBuffer.h
@@ -0,0 +1,58 @@
+// 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 CSSParserScopedTokenBuffer_h
+#define CSSParserScopedTokenBuffer_h
+
+#include "core/css/parser/CSSParserTokenStream.h"
+
+namespace blink {
+
+// Represents a vector of CSSParserTokens, used to create CSSParserTokenRanges.
+// This class owns the tokens that it stores, destroying them when it goes out
+// of scope.
+//
+// Only one CSSParserScopedTokenBuffer can be active at any point in time per
+// stream.
+// TODO(shend): Remove this class completely when selector parsing is done using
+// streams.
+class CSSParserScopedTokenBuffer {
+  WTF_MAKE_NONCOPYABLE(CSSParserScopedTokenBuffer);
+
+ public:
+  CSSParserScopedTokenBuffer(CSSParserTokenStream& stream)
+      : buffer_(stream.buffer_) {
+    DCHECK_EQ(buffer_.size(), 0U);
+  }
+
+  CSSParserScopedTokenBuffer(CSSParserScopedTokenBuffer&& other)
+      : buffer_(other.buffer_), num_tokens_(other.num_tokens_) {
+    other.num_tokens_ = 0;
+  }
+
+  ~CSSParserScopedTokenBuffer() { Release(); }
+
+  // This invalidates any ranges created from this buffer.
+  void Append(const CSSParserToken& token) {
+    DCHECK_EQ(buffer_.size(), num_tokens_);
+    buffer_.push_back(token);
+    ++num_tokens_;
+  }
+
+  CSSParserTokenRange Range() const { return buffer_.Range(); }
+
+  void Release() {
+    DCHECK_EQ(buffer_.size(), num_tokens_);
+    buffer_.clear();
+    num_tokens_ = 0;
+  }
+
+ private:
+  CSSParserTokenBuffer& buffer_;
+  size_t num_tokens_ = 0;  // For DCHECKs
+};
+
+}  // namespace blink
+
+#endif  // CSSParserScopedTokenBuffer_h
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserTokenBuffer.h b/third_party/WebKit/Source/core/css/parser/CSSParserTokenBuffer.h
new file mode 100644
index 0000000..6b966d3a
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserTokenBuffer.h
@@ -0,0 +1,47 @@
+// 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 CSSParserTokenBuffer_h
+#define CSSParserTokenBuffer_h
+
+#include "core/css/parser/CSSParserTokenRange.h"
+
+namespace blink {
+
+// Represents a container of CSSParserTokens which is designed to work
+// efficiently with CSSTokenRangeBuffers. Most notably, clearing the container
+// doesn't deallocate the tokens to avoid memory churn.
+// TODO(shend): Move this class to be nested inside CSSParserTokenStream once
+// CSSParserScopedTokenBuffer is gone.
+class CSSParserTokenBuffer {
+ public:
+  CSSParserTokenBuffer(size_t reserve = 0) : size_(0) {
+    tokens_.ReserveInitialCapacity(reserve);
+  }
+
+  void push_back(const CSSParserToken& token) {
+    if (size_ == tokens_.size())
+      tokens_.push_back(token);
+    else
+      tokens_[size_] = token;
+    size_++;
+  }
+
+  void clear() { size_ = 0; }
+
+  size_t size() const { return size_; }
+
+  CSSParserTokenRange Range() const {
+    return CSSParserTokenRange(tokens_).MakeSubRange(tokens_.begin(),
+                                                     tokens_.begin() + size_);
+  }
+
+ private:
+  Vector<CSSParserToken, 32> tokens_;
+  size_t size_;
+};
+
+}  // namespace blink
+
+#endif  // CSSParserTokenBuffer_h
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserTokenRange.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserTokenRange.cpp
index 832c467..43a4211 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserTokenRange.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserTokenRange.cpp
@@ -18,12 +18,12 @@
 CSSParserTokenRange CSSParserTokenRange::MakeSubRange(
     const CSSParserToken* first,
     const CSSParserToken* last) const {
-  // Convert first and last pointers into indices.
-  size_t sub_range_first =
-      (first == &g_static_eof_token) ? last_ : first - buffer_->begin();
-  size_t sub_range_last =
-      (last == &g_static_eof_token) ? last_ : last - buffer_->begin();
-  return CSSParserTokenRange(*buffer_, sub_range_first, sub_range_last);
+  if (first == &g_static_eof_token)
+    first = last_;
+  if (last == &g_static_eof_token)
+    last = last_;
+  DCHECK_LE(first, last);
+  return CSSParserTokenRange(first, last);
 }
 
 CSSParserTokenRange CSSParserTokenRange::ConsumeBlock() {
@@ -39,8 +39,8 @@
   } while (nesting_level && first_ < last_);
 
   if (nesting_level)
-    return MakeSubRange(start, begin());  // Ended at EOF
-  return MakeSubRange(start, begin() - 1);
+    return MakeSubRange(start, first_);  // Ended at EOF
+  return MakeSubRange(start, first_ - 1);
 }
 
 void CSSParserTokenRange::ConsumeComponentValue() {
@@ -62,7 +62,7 @@
   // as per spec, but since this is currently only used for @supports CSSOM
   // we just get these cases wrong and avoid the additional complexity.
   StringBuilder builder;
-  for (const CSSParserToken* it = begin(); it != end(); ++it)
+  for (const CSSParserToken* it = first_; it != last_; ++it)
     it->Serialize(builder);
   return builder.ToString();
 }
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserTokenRange.h b/third_party/WebKit/Source/core/css/parser/CSSParserTokenRange.h
index ab12976..7cff5d4 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserTokenRange.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserTokenRange.h
@@ -21,26 +21,27 @@
   DISALLOW_NEW();
 
  public:
-  CSSParserTokenRange(const Vector<CSSParserToken>& buffer)
-      : buffer_(&buffer), first_(0), last_(buffer.size()) {}
+  template <size_t InlineBuffer>
+  CSSParserTokenRange(const Vector<CSSParserToken, InlineBuffer>& vector)
+      : first_(vector.begin()), last_(vector.end()) {}
 
   // This should be called on a range with tokens returned by that range.
   CSSParserTokenRange MakeSubRange(const CSSParserToken* first,
                                    const CSSParserToken* last) const;
 
   bool AtEnd() const { return first_ == last_; }
-  const CSSParserToken* end() const { return buffer_->begin() + last_; }
+  const CSSParserToken* end() const { return last_; }
 
   const CSSParserToken& Peek(unsigned offset = 0) const {
     if (first_ + offset >= last_)
       return g_static_eof_token;
-    return (*buffer_)[first_ + offset];
+    return *(first_ + offset);
   }
 
   const CSSParserToken& Consume() {
     if (first_ == last_)
       return g_static_eof_token;
-    return (*buffer_)[first_++];
+    return *first_++;
   }
 
   const CSSParserToken& ConsumeIncludingWhitespace() {
@@ -61,24 +62,16 @@
 
   String Serialize() const;
 
-  const CSSParserToken* begin() const { return buffer_->begin() + first_; }
+  const CSSParserToken* begin() const { return first_; }
 
   static void InitStaticEOFToken();
 
  private:
-  CSSParserTokenRange(const Vector<CSSParserToken>& buffer,
-                      size_t first,
-                      size_t last)
-      : buffer_(&buffer), first_(first), last_(last) {
-    DCHECK_LE(first_, buffer_->size());
-    DCHECK_LE(last_, buffer_->size());
-    DCHECK_LE(first_, last_);
-  }
+  CSSParserTokenRange(const CSSParserToken* first, const CSSParserToken* last)
+      : first_(first), last_(last) {}
 
-  // This is a non-null pointer to make this class copy-assignable
-  const Vector<CSSParserToken>* buffer_;
-  size_t first_;
-  size_t last_;
+  const CSSParserToken* first_;
+  const CSSParserToken* last_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.cpp
index 9deff1e..1ed67fa 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.cpp
@@ -3,6 +3,8 @@
 // found in the LICENSE file.
 
 #include "core/css/parser/CSSParserTokenStream.h"
+#include "core/css/parser/CSSParserObserverWrapper.h"
+#include "core/css/parser/CSSParserScopedTokenBuffer.h"
 
 namespace blink {
 
@@ -17,12 +19,74 @@
   return result;
 }
 
-void CSSParserTokenStream::UncheckedConsumeComponentValue(
-    unsigned nesting_level) {
+bool CSSParserTokenStream::ConsumeCommentOrNothing() {
+  DCHECK(!HasLookAhead());
+  const auto token = tokenizer_.TokenizeSingleWithComments();
+  if (token.GetType() != kCommentToken) {
+    next_ = token;
+    has_look_ahead_ = true;
+    return false;
+  }
+
+  has_look_ahead_ = false;
+  offset_ = tokenizer_.Offset();
+  return true;
+}
+
+void CSSParserTokenStream::UncheckedConsumeComponentValue() {
   DCHECK(HasLookAhead());
 
   // Have to use internal consume/peek in here because they can read past
   // start/end of blocks
+  unsigned nesting_level = 0;
+  do {
+    const CSSParserToken& token = UncheckedConsumeInternal();
+    if (token.GetBlockType() == CSSParserToken::kBlockStart)
+      nesting_level++;
+    else if (token.GetBlockType() == CSSParserToken::kBlockEnd)
+      nesting_level--;
+  } while (!PeekInternal().IsEOF() && nesting_level);
+}
+
+void CSSParserTokenStream::UncheckedConsumeComponentValue(
+    CSSParserScopedTokenBuffer& buffer) {
+  // Have to use internal consume/peek in here because they can read past
+  // start/end of blocks
+  unsigned nesting_level = 0;
+  do {
+    const CSSParserToken& token = UncheckedConsumeInternal();
+    buffer.Append(token);
+    if (token.GetBlockType() == CSSParserToken::kBlockStart)
+      nesting_level++;
+    else if (token.GetBlockType() == CSSParserToken::kBlockEnd)
+      nesting_level--;
+  } while (!PeekInternal().IsEOF() && nesting_level);
+}
+
+void CSSParserTokenStream::UncheckedConsumeComponentValueWithOffsets(
+    CSSParserObserverWrapper& wrapper,
+    CSSParserScopedTokenBuffer& buffer) {
+  DCHECK(HasLookAhead());
+
+  // Have to use internal consume/peek in here because they can read past
+  // start/end of blocks
+  unsigned nesting_level = 0;
+  do {
+    wrapper.AddToken(LookAheadOffset());
+    const CSSParserToken& token = UncheckedConsumeInternal();
+    buffer.Append(token);
+    if (token.GetBlockType() == CSSParserToken::kBlockStart)
+      nesting_level++;
+    else if (token.GetBlockType() == CSSParserToken::kBlockEnd)
+      nesting_level--;
+  } while (!PeekInternal().IsEOF() && nesting_level);
+}
+
+void CSSParserTokenStream::UncheckedSkipToEndOfBlock() {
+  DCHECK(HasLookAhead());
+  // Have to use internal consume/peek in here because they can read past
+  // start/end of blocks
+  unsigned nesting_level = 1;
   do {
     const CSSParserToken& token = UncheckedConsumeInternal();
     if (token.GetBlockType() == CSSParserToken::kBlockStart)
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.h b/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.h
index 48b77c9..df76d577 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.h
@@ -5,32 +5,29 @@
 #ifndef CSSParserTokenStream_h
 #define CSSParserTokenStream_h
 
+#include "core/css/parser/CSSParserTokenBuffer.h"
 #include "core/css/parser/CSSParserTokenRange.h"
 #include "core/css/parser/CSSTokenizer.h"
 #include "platform/wtf/Noncopyable.h"
 
 namespace blink {
 
+class CSSParserScopedTokenBuffer;
+class CSSParserObserverWrapper;
+
 // A streaming interface to CSSTokenizer that tokenizes on demand.
 // Abstractly, the stream ends at either EOF or the beginning/end of a block.
 // To consume a block, a BlockGuard must be created first to ensure that
 // we finish consuming a block even if there was an error.
 //
-// Methods prefixed with "Unchecked" can only be called after Peek()
-// returns a non-EOF token or after AtEnd() returns false, with no
-// subsequent modifications to the stream such as a consume.
+// Methods prefixed with "Unchecked" can only be called after calls to Peek(),
+// EnsureLookAhead(), or AtEnd() with no subsequent modifications to the stream
+// such as a consume.
 class CORE_EXPORT CSSParserTokenStream {
   DISALLOW_NEW();
   WTF_MAKE_NONCOPYABLE(CSSParserTokenStream);
 
  public:
-  class Iterator {
-    explicit Iterator(size_t index) : index_(index) {}
-
-    size_t index_;
-    friend class CSSParserTokenStream;
-  };
-
   // Instantiate this to start reading from a block. When the guard is out of
   // scope, the rest of the block is consumed.
   class BlockGuard {
@@ -41,9 +38,7 @@
     }
 
     ~BlockGuard() {
-      if (stream_.EnsureLookAhead() == LookAhead::kIsEOF)
-        return;
-
+      stream_.EnsureLookAhead();
       stream_.UncheckedSkipToEndOfBlock();
     }
 
@@ -52,123 +47,110 @@
   };
 
   explicit CSSParserTokenStream(CSSTokenizer& tokenizer)
-      : tokenizer_(tokenizer), next_index_(0) {
-    // TODO(shend): Uncomment the code below once observers work properly with
-    // streams. DCHECK_EQ(tokenizer.CurrentSize(), 0U);
-  }
+      : buffer_(512), tokenizer_(tokenizer), next_(kEOFToken) {}
 
   CSSParserTokenStream(CSSParserTokenStream&&) = default;
 
-  // LookAhead::kIsEOF means the next token is EOF. Since we don't store EOF
-  // tokens, tokenizer_.tokens_[next_index_] is valid iff LookAhead::kIsValid.
-  enum class LookAhead { kIsValid, kIsEOF };
-  LookAhead EnsureLookAhead() const {
-    if (next_index_ == tokenizer_.CurrentSize()) {
-      // Reached end of token buffer, but might not be end of input.
-      if (tokenizer_.TokenizeSingle().IsEOF())
-        return LookAhead::kIsEOF;
+  inline void EnsureLookAhead() {
+    if (!HasLookAhead()) {
+      has_look_ahead_ = true;
+      next_ = tokenizer_.TokenizeSingle();
     }
+  }
+
+  // Forcibly read a lookahead token.
+  inline void LookAhead() {
+    DCHECK(!HasLookAhead());
+    next_ = tokenizer_.TokenizeSingle();
+    has_look_ahead_ = true;
+  }
+
+  inline bool HasLookAhead() const { return has_look_ahead_; }
+
+  inline const CSSParserToken& Peek() {
+    EnsureLookAhead();
+    return next_;
+  }
+
+  inline const CSSParserToken& UncheckedPeek() const {
     DCHECK(HasLookAhead());
-    return LookAhead::kIsValid;
+    return next_;
   }
 
-  bool HasLookAhead() const { return next_index_ < tokenizer_.CurrentSize(); }
-
-  const CSSParserToken& Peek() const {
-    const CSSParserToken& token = PeekInternal();
-    if (token.GetBlockType() == CSSParserToken::kBlockEnd)
-      return g_static_eof_token;
-    return token;
-  }
-
-  const CSSParserToken& UncheckedPeek() const {
-    const CSSParserToken& token = UncheckedPeekInternal();
-    if (token.GetBlockType() == CSSParserToken::kBlockEnd)
-      return g_static_eof_token;
-    return token;
-  }
-
-  const CSSParserToken& Consume() {
-    const CSSParserToken& token = ConsumeInternal();
-    DCHECK_NE(token.GetBlockType(), CSSParserToken::kBlockStart);
-    return token;
+  inline const CSSParserToken& Consume() {
+    EnsureLookAhead();
+    return UncheckedConsume();
   }
 
   const CSSParserToken& UncheckedConsume() {
-    const CSSParserToken& token = UncheckedConsumeInternal();
-    DCHECK_NE(token.GetBlockType(), CSSParserToken::kBlockStart);
-    return token;
+    DCHECK(HasLookAhead());
+    DCHECK_NE(next_.GetBlockType(), CSSParserToken::kBlockStart);
+    has_look_ahead_ = false;
+    offset_ = tokenizer_.Offset();
+    return next_;
   }
 
-  bool AtEnd() const { return Peek().IsEOF(); }
-
-  // Range represents all tokens from current position to EOF.
-  // Eagerly consumes all the remaining input.
-  // TODO(shend): Remove this method once we switch over to using streams
-  // completely.
-  CSSParserTokenRange MakeRangeToEOF() {
-    const auto range = tokenizer_.TokenRange();
-    return range.MakeSubRange(tokenizer_.tokens_.begin() + next_index_,
-                              tokenizer_.tokens_.end());
+  inline bool AtEnd() {
+    EnsureLookAhead();
+    return UncheckedAtEnd();
   }
 
-  // Range represents all tokens that were consumed between begin and end.
-  CSSParserTokenRange MakeSubRange(Iterator begin, Iterator end) {
-    DCHECK_LE(begin.index_, tokenizer_.CurrentSize());
-    DCHECK_LE(end.index_, tokenizer_.CurrentSize());
-    DCHECK_LE(begin.index_, end.index_);
-    const auto tokens_begin = tokenizer_.tokens_.begin();
-    return CSSParserTokenRange(tokenizer_.tokens_)
-        .MakeSubRange(tokens_begin + begin.index_, tokens_begin + end.index_);
-  }
-
-  // TODO(shend): Only used by CSSParserObserverWrapper. Delete this when we get
-  // streaming to work with observers
-  CSSParserTokenRange MakeSubRangeAtCurrentPosition() {
-    return MakeSubRange(Position(), Position());
-  }
-
-  Iterator Position() const {
-    DCHECK_LE(next_index_, tokenizer_.CurrentSize());
-    return Iterator(next_index_);
+  inline bool UncheckedAtEnd() const {
+    DCHECK(HasLookAhead());
+    return next_.IsEOF() || next_.GetBlockType() == CSSParserToken::kBlockEnd;
   }
 
   // Get the index of the character in the original string to be consumed next.
   size_t Offset() const { return offset_; }
 
+  // Get the index of the starting character of the look-ahead token.
+  size_t LookAheadOffset() const {
+    DCHECK(HasLookAhead());
+    return tokenizer_.PreviousOffset();
+  }
+
   void ConsumeWhitespace();
   CSSParserToken ConsumeIncludingWhitespace();
-  void UncheckedConsumeComponentValue(unsigned nesting_level = 0);
+  void UncheckedConsumeComponentValue();
+  void UncheckedConsumeComponentValue(CSSParserScopedTokenBuffer&);
+  void UncheckedConsumeComponentValueWithOffsets(CSSParserObserverWrapper&,
+                                                 CSSParserScopedTokenBuffer&);
+  // Either consumes a comment token and returns true, or peeks at the next
+  // token and return false.
+  bool ConsumeCommentOrNothing();
 
  private:
-  const CSSParserToken& PeekInternal() const {
-    if (EnsureLookAhead() == LookAhead::kIsEOF)
-      return g_static_eof_token;
+  friend class CSSParserScopedTokenBuffer;
+
+  const CSSParserToken& PeekInternal() {
+    EnsureLookAhead();
     return UncheckedPeekInternal();
   }
 
   const CSSParserToken& UncheckedPeekInternal() const {
     DCHECK(HasLookAhead());
-    return tokenizer_.tokens_[next_index_];
+    return next_;
   }
 
   const CSSParserToken& ConsumeInternal() {
-    if (EnsureLookAhead() == LookAhead::kIsEOF)
-      return g_static_eof_token;
+    EnsureLookAhead();
     return UncheckedConsumeInternal();
   }
 
   const CSSParserToken& UncheckedConsumeInternal() {
     DCHECK(HasLookAhead());
-    offset_ = tokenizer_.input_.Offset();
-    return tokenizer_.tokens_[next_index_++];
+    has_look_ahead_ = false;
+    offset_ = tokenizer_.Offset();
+    return next_;
   }
 
-  void UncheckedSkipToEndOfBlock() { UncheckedConsumeComponentValue(1); }
+  void UncheckedSkipToEndOfBlock();
 
+  CSSParserTokenBuffer buffer_;
   CSSTokenizer& tokenizer_;
-  size_t next_index_;  // Index of next token to be consumed.
+  CSSParserToken next_;
   size_t offset_ = 0;
+  bool has_look_ahead_ = false;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserTokenStreamTest.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserTokenStreamTest.cpp
index 2d4361ed..4b15b56 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserTokenStreamTest.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserTokenStreamTest.cpp
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "core/css/parser/CSSParserScopedTokenBuffer.h"
 #include "core/css/parser/CSSParserTokenStream.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
@@ -10,189 +11,105 @@
 
 namespace {
 
-// Parameterized tests for whether we are constructing a stream from
-// an empty or exhausted tokenizer.
-// TODO(shend): Remove this once we no longer need to construct streams
-// from exhausted tokenizers.
-class CSSParserTokenStreamTest : public ::testing::TestWithParam<bool> {};
-
-CSSParserTokenStream GetStream(CSSTokenizer& tokenizer,
-                               bool should_tokenize_to_end) {
-  if (should_tokenize_to_end)
-    tokenizer.TokenRange();
-  return CSSParserTokenStream(tokenizer);
-}
-
-TEST_P(CSSParserTokenStreamTest, EmptyStream) {
+TEST(CSSParserTokenStreamTest, EmptyStream) {
   CSSTokenizer tokenizer("");
-  auto stream = GetStream(tokenizer, GetParam());
+  CSSParserTokenStream stream(tokenizer);
   EXPECT_TRUE(stream.Consume().IsEOF());
   EXPECT_TRUE(stream.Peek().IsEOF());
   EXPECT_TRUE(stream.AtEnd());
-  EXPECT_TRUE(stream.MakeRangeToEOF().AtEnd());
 }
 
-TEST_P(CSSParserTokenStreamTest, PeekThenConsume) {
+TEST(CSSParserTokenStreamTest, PeekThenConsume) {
   CSSTokenizer tokenizer("A");  // kIdent
-  auto stream = GetStream(tokenizer, GetParam());
+  CSSParserTokenStream stream(tokenizer);
   EXPECT_EQ(kIdentToken, stream.Peek().GetType());
   EXPECT_EQ(kIdentToken, stream.Consume().GetType());
   EXPECT_TRUE(stream.AtEnd());
 }
 
-TEST_P(CSSParserTokenStreamTest, ConsumeThenPeek) {
+TEST(CSSParserTokenStreamTest, ConsumeThenPeek) {
   CSSTokenizer tokenizer("A");  // kIdent
-  auto stream = GetStream(tokenizer, GetParam());
+  CSSParserTokenStream stream(tokenizer);
   EXPECT_EQ(kIdentToken, stream.Consume().GetType());
   EXPECT_TRUE(stream.AtEnd());
 }
 
-TEST_P(CSSParserTokenStreamTest, ConsumeMultipleTokens) {
+TEST(CSSParserTokenStreamTest, ConsumeMultipleTokens) {
   CSSTokenizer tokenizer("A 1");  // kIdent kWhitespace kNumber
-  auto stream = GetStream(tokenizer, GetParam());
+  CSSParserTokenStream stream(tokenizer);
   EXPECT_EQ(kIdentToken, stream.Consume().GetType());
   EXPECT_EQ(kWhitespaceToken, stream.Consume().GetType());
   EXPECT_EQ(kNumberToken, stream.Consume().GetType());
   EXPECT_TRUE(stream.AtEnd());
 }
 
-TEST_P(CSSParserTokenStreamTest, UncheckedPeekAndConsumeAfterPeek) {
+TEST(CSSParserTokenStreamTest, UncheckedPeekAndConsumeAfterPeek) {
   CSSTokenizer tokenizer("A");  // kIdent
-  auto stream = GetStream(tokenizer, GetParam());
+  CSSParserTokenStream stream(tokenizer);
   EXPECT_EQ(kIdentToken, stream.Peek().GetType());
   EXPECT_EQ(kIdentToken, stream.UncheckedPeek().GetType());
   EXPECT_EQ(kIdentToken, stream.UncheckedConsume().GetType());
   EXPECT_TRUE(stream.AtEnd());
 }
 
-TEST_P(CSSParserTokenStreamTest, UncheckedPeekAndConsumeAfterAtEnd) {
+TEST(CSSParserTokenStreamTest, UncheckedPeekAndConsumeAfterAtEnd) {
   CSSTokenizer tokenizer("A");  // kIdent
-  auto stream = GetStream(tokenizer, GetParam());
+  CSSParserTokenStream stream(tokenizer);
   EXPECT_FALSE(stream.AtEnd());
   EXPECT_EQ(kIdentToken, stream.UncheckedPeek().GetType());
   EXPECT_EQ(kIdentToken, stream.UncheckedConsume().GetType());
   EXPECT_TRUE(stream.AtEnd());
 }
 
-TEST_P(CSSParserTokenStreamTest, MakeRangeToEOF) {
-  CSSTokenizer tokenizer("A 1");  // kIdent kWhitespace kNumber
-  auto stream = GetStream(tokenizer, GetParam());
-  EXPECT_EQ(kIdentToken, stream.Consume().GetType());
+TEST(CSSParserTokenStreamTest, UncheckedConsumeComponentValue) {
+  CSSTokenizer tokenizer("A{1}{2{3}}B");
+  CSSParserTokenStream stream(tokenizer);
 
-  auto range = stream.MakeRangeToEOF();
-  EXPECT_FALSE(stream.AtEnd());
-  EXPECT_EQ(kWhitespaceToken, range.Consume().GetType());
-  EXPECT_FALSE(stream.AtEnd());
-  EXPECT_EQ(kNumberToken, range.Consume().GetType());
-  EXPECT_TRUE(range.AtEnd());
+  EXPECT_EQ(kIdentToken, stream.Peek().GetType());
+  stream.UncheckedConsumeComponentValue();
+  EXPECT_EQ(kLeftBraceToken, stream.Peek().GetType());
+  stream.UncheckedConsumeComponentValue();
+  EXPECT_EQ(kLeftBraceToken, stream.Peek().GetType());
+  stream.UncheckedConsumeComponentValue();
+  EXPECT_EQ(kIdentToken, stream.Peek().GetType());
+  stream.UncheckedConsumeComponentValue();
 
-  EXPECT_FALSE(stream.AtEnd());
+  EXPECT_TRUE(stream.AtEnd());
 }
 
-TEST_P(CSSParserTokenStreamTest, MakeLargeRangeToEOF) {
-  String s = "";
+TEST(CSSParserTokenStreamTest, ConsumeWhitespace) {
+  CSSTokenizer tokenizer(" \t\n");  // kWhitespace
+  CSSParserTokenStream stream(tokenizer);
+
+  EXPECT_EQ(kWhitespaceToken, stream.Consume().GetType());
+  EXPECT_TRUE(stream.AtEnd());
+}
+
+TEST(CSSParserTokenStreamTest, ConsumeIncludingWhitespace) {
+  CSSTokenizer tokenizer("A \t\n");  // kIdent kWhitespace
+  CSSParserTokenStream stream(tokenizer);
+
+  EXPECT_EQ(kIdentToken, stream.ConsumeIncludingWhitespace().GetType());
+  EXPECT_TRUE(stream.AtEnd());
+}
+
+TEST(CSSParserTokenStreamTest, RangesDoNotGetInvalidatedWhenConsuming) {
+  String s = "1 ";
   for (int i = 0; i < 100; i++)
     s.append("A ");
 
   CSSTokenizer tokenizer(s);
   CSSParserTokenStream stream(tokenizer);
 
-  auto range = stream.MakeRangeToEOF();
-  while (!range.AtEnd()) {
-    EXPECT_EQ(kIdentToken, range.Consume().GetType());
-    EXPECT_EQ(kWhitespaceToken, range.Consume().GetType());
-  }
+  // Consume a single token range.
+  CSSParserScopedTokenBuffer buffer(stream);
+  stream.EnsureLookAhead();
+  stream.UncheckedConsumeComponentValue(buffer);
 
-  EXPECT_FALSE(stream.AtEnd());
-}
+  auto range = buffer.Range();
+  EXPECT_EQ(kNumberToken, range.Peek().GetType());
 
-TEST_P(CSSParserTokenStreamTest, UncheckedConsumeComponentValue) {
-  CSSTokenizer tokenizer("A{1}{2{3}}B");
-  auto stream = GetStream(tokenizer, GetParam());
-
-  EXPECT_EQ(kIdentToken, stream.Peek().GetType());
-  stream.UncheckedConsumeComponentValue();
-  EXPECT_EQ(kLeftBraceToken, stream.Peek().GetType());
-  stream.UncheckedConsumeComponentValue();
-  EXPECT_EQ(kLeftBraceToken, stream.Peek().GetType());
-  stream.UncheckedConsumeComponentValue();
-  EXPECT_EQ(kIdentToken, stream.Peek().GetType());
-  stream.UncheckedConsumeComponentValue();
-
-  EXPECT_TRUE(stream.AtEnd());
-}
-
-TEST_P(CSSParserTokenStreamTest, MakeSubRangeFromEmptyIterators) {
-  CSSTokenizer tokenizer("");  // kIdent kWhitespace kNumber
-  auto stream = GetStream(tokenizer, GetParam());
-
-  const auto a = stream.Position();
-  const auto b = stream.Position();
-  const auto range = stream.MakeSubRange(a, b);
-
-  EXPECT_TRUE(range.AtEnd());
-}
-
-TEST_P(CSSParserTokenStreamTest, MakeSubRangeFromMultipleIterators) {
-  CSSTokenizer tokenizer("A 1");  // kIdent kWhitespace kNumber
-  auto stream = GetStream(tokenizer, GetParam());
-
-  const auto a = stream.Position();
-  EXPECT_EQ(kIdentToken, stream.Consume().GetType());
-  const auto b = stream.Position();
-  EXPECT_EQ(kWhitespaceToken, stream.Consume().GetType());
-  const auto c = stream.Position();
-  EXPECT_EQ(kNumberToken, stream.Consume().GetType());
-  const auto d = stream.Position();
-
-  const auto range1 = stream.MakeSubRange(a, a);
-  EXPECT_TRUE(range1.AtEnd());
-
-  auto range2 = stream.MakeSubRange(a, d);
-  EXPECT_EQ(kIdentToken, range2.Consume().GetType());
-  EXPECT_EQ(kWhitespaceToken, range2.Consume().GetType());
-  EXPECT_EQ(kNumberToken, range2.Consume().GetType());
-  EXPECT_TRUE(range2.AtEnd());
-
-  auto range3 = stream.MakeSubRange(b, c);
-  EXPECT_EQ(kWhitespaceToken, range3.Consume().GetType());
-  EXPECT_TRUE(range3.AtEnd());
-
-  auto range4 = stream.MakeSubRange(b, d);
-  EXPECT_EQ(kWhitespaceToken, range4.Consume().GetType());
-  EXPECT_EQ(kNumberToken, range4.Consume().GetType());
-  EXPECT_TRUE(range4.AtEnd());
-}
-
-TEST_P(CSSParserTokenStreamTest, ConsumeWhitespace) {
-  CSSTokenizer tokenizer(" \t\n");  // kWhitespace
-  auto stream = GetStream(tokenizer, GetParam());
-
-  EXPECT_EQ(kWhitespaceToken, stream.Consume().GetType());
-  EXPECT_TRUE(stream.AtEnd());
-}
-
-TEST_P(CSSParserTokenStreamTest, ConsumeIncludingWhitespace) {
-  CSSTokenizer tokenizer("A \t\n");  // kIdent kWhitespace
-  auto stream = GetStream(tokenizer, GetParam());
-
-  EXPECT_EQ(kIdentToken, stream.ConsumeIncludingWhitespace().GetType());
-  EXPECT_TRUE(stream.AtEnd());
-}
-
-TEST_P(CSSParserTokenStreamTest, RangesDoNotGetInvalidatedWhenConsuming) {
-  String s = "1 ";
-  for (int i = 0; i < 100; i++)
-    s.append("A ");
-
-  CSSTokenizer tokenizer(s);
-  auto stream = GetStream(tokenizer, GetParam());
-
-  const auto start = stream.Position();
-  EXPECT_EQ(kNumberToken, stream.ConsumeIncludingWhitespace().GetType());
-  auto range = stream.MakeSubRange(start, stream.Position());
-
-  // Consume remaining tokens to cause buffer resize
+  // Consume remaining tokens to try to invalidate the range.
   while (!stream.AtEnd())
     stream.ConsumeIncludingWhitespace();
 
@@ -200,9 +117,9 @@
   EXPECT_TRUE(range.AtEnd());
 }
 
-TEST_P(CSSParserTokenStreamTest, BlockErrorRecoveryConsumesRestOfBlock) {
+TEST(CSSParserTokenStreamTest, BlockErrorRecoveryConsumesRestOfBlock) {
   CSSTokenizer tokenizer("{B }1");
-  auto stream = GetStream(tokenizer, GetParam());
+  CSSParserTokenStream stream(tokenizer);
 
   {
     CSSParserTokenStream::BlockGuard guard(stream);
@@ -213,9 +130,9 @@
   EXPECT_EQ(kNumberToken, stream.Consume().GetType());
 }
 
-TEST_P(CSSParserTokenStreamTest, BlockErrorRecoveryOnSuccess) {
+TEST(CSSParserTokenStreamTest, BlockErrorRecoveryOnSuccess) {
   CSSTokenizer tokenizer("{B }1");
-  auto stream = GetStream(tokenizer, GetParam());
+  CSSParserTokenStream stream(tokenizer);
 
   {
     CSSParserTokenStream::BlockGuard guard(stream);
@@ -227,21 +144,20 @@
   EXPECT_EQ(kNumberToken, stream.Consume().GetType());
 }
 
-TEST_P(CSSParserTokenStreamTest, BlockErrorRecoveryConsumeComponentValue) {
+TEST(CSSParserTokenStreamTest, BlockErrorRecoveryConsumeComponentValue) {
   CSSTokenizer tokenizer("{{B} C}1");
-  auto stream = GetStream(tokenizer, GetParam());
+  CSSParserTokenStream stream(tokenizer);
 
   {
     CSSParserTokenStream::BlockGuard guard(stream);
-    EXPECT_EQ(CSSParserTokenStream::LookAhead::kIsValid,
-              stream.EnsureLookAhead());
+    stream.EnsureLookAhead();
     stream.UncheckedConsumeComponentValue();
   }  // calls destructor
 
   EXPECT_EQ(kNumberToken, stream.Consume().GetType());
 }
 
-TEST_F(CSSParserTokenStreamTest, OffsetAfterPeek) {
+TEST(CSSParserTokenStreamTest, OffsetAfterPeek) {
   CSSTokenizer tokenizer("ABC");
   CSSParserTokenStream stream(tokenizer);
 
@@ -250,7 +166,7 @@
   EXPECT_EQ(0U, stream.Offset());
 }
 
-TEST_F(CSSParserTokenStreamTest, OffsetAfterConsumes) {
+TEST(CSSParserTokenStreamTest, OffsetAfterConsumes) {
   CSSTokenizer tokenizer("ABC 1 {23 }");
   CSSParserTokenStream stream(tokenizer);
 
@@ -266,9 +182,36 @@
   EXPECT_EQ(11U, stream.Offset());
 }
 
-INSTANTIATE_TEST_CASE_P(ShouldTokenizeToEnd,
-                        CSSParserTokenStreamTest,
-                        ::testing::Bool());
+TEST(CSSParserTokenStreamTest, LookAheadOffset) {
+  CSSTokenizer tokenizer("ABC/* *//* */1");
+  CSSParserTokenStream stream(tokenizer);
+
+  stream.EnsureLookAhead();
+  EXPECT_EQ(0U, stream.Offset());
+  EXPECT_EQ(0U, stream.LookAheadOffset());
+  EXPECT_EQ(kIdentToken, stream.Consume().GetType());
+
+  stream.EnsureLookAhead();
+  EXPECT_EQ(3U, stream.Offset());
+  EXPECT_EQ(13U, stream.LookAheadOffset());
+}
+
+TEST(CSSParserTokenStreamTest, ConsumeComponentValueWithBuffer) {
+  CSSTokenizer tokenizer("{23 }");
+  CSSParserTokenStream stream(tokenizer);
+
+  CSSParserScopedTokenBuffer buffer(stream);
+  stream.EnsureLookAhead();
+  stream.UncheckedConsumeComponentValue(buffer);
+  EXPECT_TRUE(stream.AtEnd());
+
+  auto range = buffer.Range();
+  EXPECT_EQ(kLeftBraceToken, range.Consume().GetType());
+  EXPECT_EQ(kNumberToken, range.Consume().GetType());
+  EXPECT_EQ(kWhitespaceToken, range.Consume().GetType());
+  EXPECT_EQ(kRightBraceToken, range.Consume().GetType());
+  EXPECT_TRUE(range.AtEnd());
+}
 
 }  // namespace
 
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp
index cf956fa..5c38411 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp
@@ -43,7 +43,7 @@
   if (!token_range.AtEnd()) {
     RefPtr<CSSVariableData> unparsed_css_variable_data =
         CSSVariableData::Create(token_range, false, false);
-    if (unparsed_css_variable_data.Get()) {
+    if (unparsed_css_variable_data.get()) {
       variable_data->push_back(std::move(unparsed_css_variable_data));
       return true;
     }
diff --git a/third_party/WebKit/Source/core/css/parser/CSSSelectorParserTest.cpp b/third_party/WebKit/Source/core/css/parser/CSSSelectorParserTest.cpp
index 5859814..33afb9b 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSSelectorParserTest.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSSelectorParserTest.cpp
@@ -82,7 +82,8 @@
 
     std::pair<int, int> ab;
     CSSTokenizer tokenizer(test_case.input);
-    CSSParserTokenRange range = tokenizer.TokenRange();
+    const auto tokens = tokenizer.TokenizeToEOF();
+    CSSParserTokenRange range(tokens);
     bool passed = CSSSelectorParser::ConsumeANPlusB(range, ab);
     EXPECT_TRUE(passed);
     EXPECT_EQ(test_case.a, ab.first);
@@ -104,7 +105,8 @@
 
     std::pair<int, int> ab;
     CSSTokenizer tokenizer(test_case);
-    CSSParserTokenRange range = tokenizer.TokenRange();
+    const auto tokens = tokenizer.TokenizeToEOF();
+    CSSParserTokenRange range(tokens);
     bool passed = CSSSelectorParser::ConsumeANPlusB(range, ab);
     EXPECT_FALSE(passed);
   }
@@ -121,7 +123,8 @@
   for (auto test_case : test_cases) {
     SCOPED_TRACE(test_case[0]);
     CSSTokenizer tokenizer(test_case[0]);
-    CSSParserTokenRange range = tokenizer.TokenRange();
+    const auto tokens = tokenizer.TokenizeToEOF();
+    CSSParserTokenRange range(tokens);
     CSSSelectorList list = CSSSelectorParser::ParseSelector(
         range, CSSParserContext::Create(kHTMLStandardMode), nullptr);
     EXPECT_STREQ(test_case[1], list.SelectorsText().Ascii().data());
@@ -140,7 +143,8 @@
 
   for (auto test_case : test_cases) {
     CSSTokenizer tokenizer(test_case);
-    CSSParserTokenRange range = tokenizer.TokenRange();
+    const auto tokens = tokenizer.TokenizeToEOF();
+    CSSParserTokenRange range(tokens);
     CSSSelectorList list = CSSSelectorParser::ParseSelector(
         range, CSSParserContext::Create(kHTMLStandardMode), nullptr);
     EXPECT_FALSE(list.IsValid());
@@ -158,7 +162,8 @@
 
   for (auto test_case : test_cases) {
     CSSTokenizer tokenizer(test_case);
-    CSSParserTokenRange range = tokenizer.TokenRange();
+    const auto tokens = tokenizer.TokenizeToEOF();
+    CSSParserTokenRange range(tokens);
     CSSSelectorList list = CSSSelectorParser::ParseSelector(
         range, CSSParserContext::Create(kHTMLStandardMode), nullptr);
     EXPECT_TRUE(list.IsValid());
@@ -188,7 +193,8 @@
 
   for (auto test_case : test_cases) {
     CSSTokenizer tokenizer(test_case);
-    CSSParserTokenRange range = tokenizer.TokenRange();
+    const auto tokens = tokenizer.TokenizeToEOF();
+    CSSParserTokenRange range(tokens);
     CSSSelectorList list = CSSSelectorParser::ParseSelector(
         range, CSSParserContext::Create(kHTMLStandardMode), nullptr);
     EXPECT_FALSE(list.IsValid());
@@ -203,7 +209,8 @@
 
   for (auto test_case : test_cases) {
     CSSTokenizer tokenizer(test_case);
-    CSSParserTokenRange range = tokenizer.TokenRange();
+    const auto tokens = tokenizer.TokenizeToEOF();
+    CSSParserTokenRange range(tokens);
     CSSSelectorList list = CSSSelectorParser::ParseSelector(
         range, CSSParserContext::Create(kUASheetMode), nullptr);
     EXPECT_TRUE(list.IsValid());
@@ -215,7 +222,8 @@
 
   for (auto test_case : test_cases) {
     CSSTokenizer tokenizer(test_case);
-    CSSParserTokenRange range = tokenizer.TokenRange();
+    const auto tokens = tokenizer.TokenizeToEOF();
+    CSSParserTokenRange range(tokens);
     CSSSelectorList list = CSSSelectorParser::ParseSelector(
         range, CSSParserContext::Create(kHTMLStandardMode), nullptr);
     EXPECT_TRUE(list.IsValid());
@@ -229,7 +237,8 @@
 
   for (auto test_case : test_cases) {
     CSSTokenizer tokenizer(test_case);
-    CSSParserTokenRange range = tokenizer.TokenRange();
+    const auto tokens = tokenizer.TokenizeToEOF();
+    CSSParserTokenRange range(tokens);
     CSSSelectorList list = CSSSelectorParser::ParseSelector(
         range, CSSParserContext::Create(kHTMLStandardMode), nullptr);
     EXPECT_FALSE(list.IsValid());
@@ -244,7 +253,8 @@
 
   for (auto test_case : test_cases) {
     CSSTokenizer tokenizer(test_case);
-    CSSParserTokenRange range = tokenizer.TokenRange();
+    const auto tokens = tokenizer.TokenizeToEOF();
+    CSSParserTokenRange range(tokens);
     CSSSelectorList list =
         CSSSelectorParser::ParseSelector(range, context, sheet);
     EXPECT_FALSE(list.IsValid());
@@ -271,7 +281,8 @@
   for (auto test_case : test_cases) {
     SCOPED_TRACE(test_case[0]);
     CSSTokenizer tokenizer(test_case[0]);
-    CSSParserTokenRange range = tokenizer.TokenRange();
+    const auto tokens = tokenizer.TokenizeToEOF();
+    CSSParserTokenRange range(tokens);
     CSSSelectorList list =
         CSSSelectorParser::ParseSelector(range, context, sheet);
     EXPECT_TRUE(list.IsValid());
@@ -289,7 +300,8 @@
   for (auto test_case : test_cases) {
     SCOPED_TRACE(test_case);
     CSSTokenizer tokenizer(test_case);
-    CSSParserTokenRange range = tokenizer.TokenRange();
+    const auto tokens = tokenizer.TokenizeToEOF();
+    CSSParserTokenRange range(tokens);
     CSSSelectorList list =
         CSSSelectorParser::ParseSelector(range, context, sheet);
     EXPECT_FALSE(list.IsValid());
@@ -307,7 +319,8 @@
   for (auto test_case : test_cases) {
     SCOPED_TRACE(test_case);
     CSSTokenizer tokenizer(test_case);
-    CSSParserTokenRange range = tokenizer.TokenRange();
+    const auto tokens = tokenizer.TokenizeToEOF();
+    CSSParserTokenRange range(tokens);
     CSSSelectorList list =
         CSSSelectorParser::ParseSelector(range, context, sheet);
     EXPECT_FALSE(list.IsValid());
@@ -327,7 +340,8 @@
   for (auto test_case : test_cases) {
     SCOPED_TRACE(test_case[0]);
     CSSTokenizer tokenizer(test_case[0]);
-    CSSParserTokenRange range = tokenizer.TokenRange();
+    const auto tokens = tokenizer.TokenizeToEOF();
+    CSSParserTokenRange range(tokens);
     CSSSelectorList list =
         CSSSelectorParser::ParseSelector(range, context, sheet);
     EXPECT_TRUE(list.IsValid());
@@ -344,7 +358,8 @@
   for (auto test_case : test_cases) {
     SCOPED_TRACE(test_case);
     CSSTokenizer tokenizer(test_case);
-    CSSParserTokenRange range = tokenizer.TokenRange();
+    const auto tokens = tokenizer.TokenizeToEOF();
+    CSSParserTokenRange range(tokens);
     CSSSelectorList list =
         CSSSelectorParser::ParseSelector(range, context, sheet);
     EXPECT_FALSE(list.IsValid());
@@ -362,7 +377,8 @@
   for (auto test_case : test_cases) {
     SCOPED_TRACE(test_case);
     CSSTokenizer tokenizer(test_case);
-    CSSParserTokenRange range = tokenizer.TokenRange();
+    const auto tokens = tokenizer.TokenizeToEOF();
+    CSSParserTokenRange range(tokens);
 
     CSSSelectorList author_list = CSSSelectorParser::ParseSelector(
         range, CSSParserContext::Create(kHTMLStandardMode), nullptr);
@@ -409,7 +425,8 @@
   for (auto test_case : test_cases) {
     SCOPED_TRACE(test_case.input);
     CSSTokenizer tokenizer(test_case.input);
-    CSSParserTokenRange range = tokenizer.TokenRange();
+    const auto tokens = tokenizer.TokenizeToEOF();
+    CSSParserTokenRange range(tokens);
     CSSSelectorList list =
         CSSSelectorParser::ParseSelector(range, context, sheet);
     EXPECT_TRUE(list.IsValid());
@@ -432,7 +449,8 @@
   for (auto test_case : test_cases) {
     SCOPED_TRACE(test_case.input);
     CSSTokenizer tokenizer(test_case.input);
-    CSSParserTokenRange range = tokenizer.TokenRange();
+    const auto tokens = tokenizer.TokenizeToEOF();
+    CSSParserTokenRange range(tokens);
     CSSSelectorList list =
         CSSSelectorParser::ParseSelector(range, context, sheet);
     EXPECT_TRUE(list.IsValid());
diff --git a/third_party/WebKit/Source/core/css/parser/CSSTokenizer.cpp b/third_party/WebKit/Source/core/css/parser/CSSTokenizer.cpp
index 2475d33..f5a56a6 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSTokenizer.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSTokenizer.cpp
@@ -16,7 +16,8 @@
 
 namespace blink {
 
-CSSTokenizer::CSSTokenizer(const String& string) : input_(string) {
+CSSTokenizer::CSSTokenizer(const String& string, size_t offset)
+    : input_(string) {
   // According to the spec, we should perform preprocessing here.
   // See: http://dev.w3.org/csswg/css-syntax/#input-preprocessing
   //
@@ -29,65 +30,40 @@
   if (string.IsEmpty())
     return;
 
-  // To avoid resizing we err on the side of reserving too much space.
-  // Most strings we tokenize have about 3.5 to 5 characters per token.
-  tokens_.ReserveInitialCapacity(string.length() / 3);
+  input_.Advance(offset);
 }
 
-CSSTokenizer::CSSTokenizer(const String& string,
-                           CSSParserObserverWrapper& wrapper)
-    : input_(string) {
-  if (string.IsEmpty())
-    return;
-
-  // TODO(shend): Do not tokenize all in one go. We should be tokenizing on the
-  // fly.
-  unsigned offset = 0;
+Vector<CSSParserToken, 32> CSSTokenizer::TokenizeToEOF() {
+  // To avoid resizing we err on the side of reserving too much space.
+  // Most strings we tokenize have about 3.5 to 5 characters per token.
+  Vector<CSSParserToken, 32> tokens;
+  tokens.ReserveInitialCapacity((input_.length() - Offset()) / 3);
   while (true) {
-    CSSParserToken token = NextToken();
-    if (token.GetType() == kEOFToken)
+    const CSSParserToken token = TokenizeSingle();
+    if (token.IsEOF())
       break;
-    if (token.GetType() == kCommentToken) {
-      wrapper.AddComment(offset, input_.Offset(), tokens_.size());
-    } else {
-      tokens_.push_back(token);
-      wrapper.AddToken(offset);
-    }
-    offset = input_.Offset();
+    tokens.push_back(token);
   }
-
-  wrapper.AddToken(offset);
-  wrapper.FinalizeConstruction(tokens_.begin());
+  return tokens;
 }
 
 CSSParserToken CSSTokenizer::TokenizeSingle() {
   while (true) {
+    prev_offset_ = input_.Offset();
     const CSSParserToken token = NextToken();
     if (token.GetType() == kCommentToken)
       continue;
-    if (!token.IsEOF())
-      tokens_.push_back(token);
     return token;
   }
 }
 
-void CSSTokenizer::EnsureTokenizedToEOF() {
-  while (!TokenizeSingle().IsEOF()) {
-  }
-}
-
-CSSParserTokenRange CSSTokenizer::TokenRange() {
-  EnsureTokenizedToEOF();
-  return tokens_;
-}
-
-unsigned CSSTokenizer::CurrentSize() const {
-  return tokens_.size();
+CSSParserToken CSSTokenizer::TokenizeSingleWithComments() {
+  prev_offset_ = input_.Offset();
+  return NextToken();
 }
 
 unsigned CSSTokenizer::TokenCount() {
-  EnsureTokenizedToEOF();
-  return tokens_.size();
+  return token_count_;
 }
 
 static bool IsNewLine(UChar cc) {
@@ -329,6 +305,7 @@
     code_point_func = &CSSTokenizer::NameStart;
   }
 
+  ++token_count_;
   if (code_point_func)
     return ((this)->*(code_point_func))(cc);
   return CSSParserToken(kDelimiterToken, cc);
diff --git a/third_party/WebKit/Source/core/css/parser/CSSTokenizer.h b/third_party/WebKit/Source/core/css/parser/CSSTokenizer.h
index f2ccc11..d8bc576 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSTokenizer.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSTokenizer.h
@@ -18,26 +18,23 @@
 namespace blink {
 
 class CSSTokenizerInputStream;
-class CSSParserObserverWrapper;
-class CSSParserTokenRange;
 
 class CORE_EXPORT CSSTokenizer {
   WTF_MAKE_NONCOPYABLE(CSSTokenizer);
   DISALLOW_NEW();
 
  public:
-  CSSTokenizer(const String&);
-  CSSTokenizer(const String&, CSSParserObserverWrapper&);  // For the inspector
+  CSSTokenizer(const String&, size_t offset = 0);
 
-  CSSParserTokenRange TokenRange();
+  Vector<CSSParserToken, 32> TokenizeToEOF();
   unsigned TokenCount();
 
-  Vector<String> TakeEscapedStrings() { return std::move(string_pool_); }
+  size_t Offset() const { return input_.Offset(); }
+  size_t PreviousOffset() const { return prev_offset_; }
 
  private:
   CSSParserToken TokenizeSingle();
-  void EnsureTokenizedToEOF();
-  unsigned CurrentSize() const;
+  CSSParserToken TokenizeSingleWithComments();
 
   CSSParserToken NextToken();
 
@@ -107,11 +104,13 @@
   CSSTokenizerInputStream input_;
   Vector<CSSParserTokenType, 8> block_stack_;
 
-  Vector<CSSParserToken> tokens_;
   // We only allocate strings when escapes are used.
   Vector<String> string_pool_;
 
   friend class CSSParserTokenStream;
+
+  size_t prev_offset_ = 0;
+  size_t token_count_ = 0;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/parser/CSSTokenizerTest.cpp b/third_party/WebKit/Source/core/css/parser/CSSTokenizerTest.cpp
index 54c49ac..284a70dd 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSTokenizerTest.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSTokenizerTest.cpp
@@ -72,7 +72,8 @@
   CSSParserTokenRange expected(expected_tokens);
 
   CSSTokenizer tokenizer(string);
-  CSSParserTokenRange actual = tokenizer.TokenRange();
+  const auto tokens = tokenizer.TokenizeToEOF();
+  CSSParserTokenRange actual(tokens);
 
   // Just check that serialization doesn't hit any asserts
   actual.Serialize();
@@ -496,7 +497,8 @@
   };
   for (int i = 0; test_cases[i].input; ++i) {
     CSSTokenizer tokenizer(test_cases[i].input);
-    CSSParserTokenRange range = tokenizer.TokenRange();
+    const auto tokens = tokenizer.TokenizeToEOF();
+    CSSParserTokenRange range(tokens);
     MediaQueryBlockWatcher block_watcher;
 
     unsigned max_level = 0;
diff --git a/third_party/WebKit/Source/core/css/parser/MediaConditionTest.cpp b/third_party/WebKit/Source/core/css/parser/MediaConditionTest.cpp
index 45f8d5fb..bdd3713 100644
--- a/third_party/WebKit/Source/core/css/parser/MediaConditionTest.cpp
+++ b/third_party/WebKit/Source/core/css/parser/MediaConditionTest.cpp
@@ -38,8 +38,9 @@
   // FIXME: We should test comma-seperated media conditions
   for (unsigned i = 0; test_cases[i].input; ++i) {
     CSSTokenizer tokenizer(test_cases[i].input);
+    const auto tokens = tokenizer.TokenizeToEOF();
     RefPtr<MediaQuerySet> media_condition_query_set =
-        MediaQueryParser::ParseMediaCondition(tokenizer.TokenRange());
+        MediaQueryParser::ParseMediaCondition(CSSParserTokenRange(tokens));
     ASSERT_EQ(media_condition_query_set->QueryVector().size(), (unsigned)1);
     String query_text = media_condition_query_set->QueryVector()[0]->CssText();
     ASSERT_STREQ(test_cases[i].output, query_text.Ascii().data());
diff --git a/third_party/WebKit/Source/core/css/parser/MediaQueryParser.cpp b/third_party/WebKit/Source/core/css/parser/MediaQueryParser.cpp
index 60039b1..5086162 100644
--- a/third_party/WebKit/Source/core/css/parser/MediaQueryParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/MediaQueryParser.cpp
@@ -12,7 +12,8 @@
 
 RefPtr<MediaQuerySet> MediaQueryParser::ParseMediaQuerySet(
     const String& query_string) {
-  return ParseMediaQuerySet(CSSTokenizer(query_string).TokenRange());
+  return ParseMediaQuerySet(
+      CSSParserTokenRange(CSSTokenizer(query_string).TokenizeToEOF()));
 }
 
 RefPtr<MediaQuerySet> MediaQueryParser::ParseMediaQuerySet(
diff --git a/third_party/WebKit/Source/core/css/parser/SizesAttributeParser.cpp b/third_party/WebKit/Source/core/css/parser/SizesAttributeParser.cpp
index adba378..8bccf201 100644
--- a/third_party/WebKit/Source/core/css/parser/SizesAttributeParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/SizesAttributeParser.cpp
@@ -15,7 +15,8 @@
                                            const String& attribute)
     : media_values_(media_values), length_(0), length_was_set_(false) {
   DCHECK(media_values_.Get());
-  is_valid_ = Parse(CSSTokenizer(attribute).TokenRange());
+  is_valid_ =
+      Parse(CSSParserTokenRange(CSSTokenizer(attribute).TokenizeToEOF()));
 }
 
 float SizesAttributeParser::length() {
diff --git a/third_party/WebKit/Source/core/css/parser/SizesCalcParserTest.cpp b/third_party/WebKit/Source/core/css/parser/SizesCalcParserTest.cpp
index 1af67f8..cd1fec1 100644
--- a/third_party/WebKit/Source/core/css/parser/SizesCalcParserTest.cpp
+++ b/third_party/WebKit/Source/core/css/parser/SizesCalcParserTest.cpp
@@ -116,8 +116,9 @@
   MediaValues* media_values = MediaValuesCached::Create(data);
 
   for (unsigned i = 0; test_cases[i].input; ++i) {
-    SizesCalcParser calc_parser(CSSTokenizer(test_cases[i].input).TokenRange(),
-                                media_values);
+    SizesCalcParser calc_parser(
+        CSSParserTokenRange(CSSTokenizer(test_cases[i].input).TokenizeToEOF()),
+        media_values);
     ASSERT_EQ(test_cases[i].valid, calc_parser.IsValid());
     if (calc_parser.IsValid())
       ASSERT_EQ(test_cases[i].output, calc_parser.Result());
diff --git a/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp b/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp
index 8122d63..27fa067 100644
--- a/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp
@@ -72,7 +72,7 @@
       ResolveCustomProperty(name, *variable_data, unused_cycle_detected);
   if (!registration) {
     inherited_variables_->SetVariable(name, new_variable_data);
-    return new_variable_data.Get();
+    return new_variable_data.get();
   }
 
   const CSSValue* parsed_value = nullptr;
@@ -90,7 +90,7 @@
   }
   if (!new_variable_data)
     return registration->InitialVariableData();
-  return new_variable_data.Get();
+  return new_variable_data.get();
 }
 
 RefPtr<CSSVariableData> CSSVariableResolver::ResolveCustomProperty(
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp b/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp
index e816e9f..500e767 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp
@@ -131,7 +131,7 @@
          style.Display() == EDisplay::kWebkitInlineBox ||
          IsAtShadowBoundary(element) || style.IsFloating() ||
          style.HasOutOfFlowPosition() || IsOutermostSVGElement(element) ||
-         isHTMLRTElement(element);
+         IsHTMLRTElement(element);
 }
 
 // Certain elements (<a>, <font>) override text decoration colors.  "The font
@@ -141,7 +141,7 @@
 // The <a> behavior is non-standard.
 static bool OverridesTextDecorationColors(const Element* element) {
   return element &&
-         (isHTMLFontElement(element) || isHTMLAnchorElement(element));
+         (IsHTMLFontElement(element) || IsHTMLAnchorElement(element));
 }
 
 // FIXME: This helper is only needed because pseudoStyleForElement passes a null
@@ -183,7 +183,7 @@
                                       HTMLElement& element) {
   // <div> and <span> are the most common elements on the web, we skip all the
   // work for them.
-  if (isHTMLDivElement(element) || isHTMLSpanElement(element))
+  if (IsHTMLDivElement(element) || IsHTMLSpanElement(element))
     return;
 
   if (IsHTMLTableCellElement(element)) {
@@ -199,13 +199,13 @@
     return;
   }
 
-  if (isHTMLImageElement(element)) {
-    if (toHTMLImageElement(element).IsCollapsed())
+  if (auto* image = ToHTMLImageElementOrNull(element)) {
+    if (image->IsCollapsed())
       style.SetDisplay(EDisplay::kNone);
     return;
   }
 
-  if (isHTMLTableElement(element)) {
+  if (IsHTMLTableElement(element)) {
     // Tables never support the -webkit-* values for text-align and will reset
     // back to the default.
     if (style.GetTextAlign() == ETextAlign::kWebkitLeft ||
@@ -215,7 +215,7 @@
     return;
   }
 
-  if (isHTMLFrameElement(element) || isHTMLFrameSetElement(element)) {
+  if (IsHTMLFrameElement(element) || IsHTMLFrameSetElement(element)) {
     // Frames and framesets never honor position:relative or position:absolute.
     // This is necessary to fix a crash where a site tries to position these
     // objects. They also never honor display.
@@ -232,7 +232,7 @@
     return;
   }
 
-  if (isHTMLRTElement(element)) {
+  if (IsHTMLRTElement(element)) {
     // Ruby text does not support float or position. This might change with
     // evolution of the specification.
     style.SetPosition(EPosition::kStatic);
@@ -240,19 +240,19 @@
     return;
   }
 
-  if (isHTMLLegendElement(element)) {
+  if (IsHTMLLegendElement(element)) {
     style.SetDisplay(EDisplay::kBlock);
     return;
   }
 
-  if (isHTMLMarqueeElement(element)) {
+  if (IsHTMLMarqueeElement(element)) {
     // For now, <marquee> requires an overflow clip to work properly.
     style.SetOverflowX(EOverflow::kHidden);
     style.SetOverflowY(EOverflow::kHidden);
     return;
   }
 
-  if (isHTMLTextAreaElement(element)) {
+  if (IsHTMLTextAreaElement(element)) {
     // Textarea considers overflow visible as auto.
     style.SetOverflowX(style.OverflowX() == EOverflow::kVisible
                            ? EOverflow::kAuto
@@ -394,16 +394,16 @@
   TouchAction inherited_action = parent_style.GetEffectiveTouchAction();
 
   bool is_svg_root = element && element->IsSVGElement() &&
-                     isSVGSVGElement(*element) && element->parentNode() &&
+                     IsSVGSVGElement(*element) && element->parentNode() &&
                      !element->parentNode()->IsSVGElement();
   bool is_replaced_canvas =
-      element && isHTMLCanvasElement(element) &&
+      element && IsHTMLCanvasElement(element) &&
       element->GetDocument().GetFrame() &&
       element->GetDocument().CanExecuteScripts(kNotAboutToExecuteScript);
   bool is_non_replaced_inline_elements =
       style.IsDisplayInlineType() &&
       !(style.IsDisplayReplacedType() || is_svg_root ||
-        isHTMLImageElement(element) || is_replaced_canvas);
+        IsHTMLImageElement(element) || is_replaced_canvas);
   bool is_table_row_or_column = style.IsDisplayTableRowOrColumnType();
   bool is_layout_object_needed =
       element && element->LayoutObjectIsNeeded(style);
@@ -481,10 +481,11 @@
   const ComputedStyle& parent_style = *state.ParentStyle();
   const ComputedStyle& layout_parent_style = *state.LayoutParentStyle();
 
+  if (style.Display() != EDisplay::kNone && element &&
+      element->IsHTMLElement()) {
+    AdjustStyleForHTMLElement(style, ToHTMLElement(*element));
+  }
   if (style.Display() != EDisplay::kNone) {
-    if (element && element->IsHTMLElement())
-      AdjustStyleForHTMLElement(style, ToHTMLElement(*element));
-
     // Per the spec, position 'static' and 'relative' in the top layer compute
     // to 'absolute'.
     if (IsInTopLayer(element, style) &&
@@ -573,17 +574,17 @@
 
     // Only the root <svg> element in an SVG document fragment tree honors css
     // position.
-    if (!(isSVGSVGElement(*element) && element->parentNode() &&
+    if (!(IsSVGSVGElement(*element) && element->parentNode() &&
           !element->parentNode()->IsSVGElement()))
       style.SetPosition(ComputedStyle::InitialPosition());
 
     // SVG text layout code expects us to be a block-level style element.
-    if ((isSVGForeignObjectElement(*element) || isSVGTextElement(*element)) &&
+    if ((IsSVGForeignObjectElement(*element) || IsSVGTextElement(*element)) &&
         style.IsDisplayInlineType())
       style.SetDisplay(EDisplay::kBlock);
 
     // Columns don't apply to svg text elements.
-    if (isSVGTextElement(*element))
+    if (IsSVGTextElement(*element))
       style.ClearMultiCol();
   }
 
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
index 8c3f9744..dd5a83ae 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
@@ -225,7 +225,7 @@
     } else {
       RefPtr<SharedFontFamily> new_family = SharedFontFamily::Create();
       curr_family->AppendFamily(new_family);
-      curr_family = new_family.Get();
+      curr_family = new_family.get();
     }
 
     curr_family->SetFamily(family_name);
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
index e0ad976..aec8f94 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
@@ -733,7 +733,7 @@
     StyleAdjuster::AdjustComputedStyle(state, element);
   }
 
-  if (isHTMLBodyElement(*element))
+  if (IsHTMLBodyElement(*element))
     GetDocument().GetTextLinkColors().SetTextColor(state.Style()->GetColor());
 
   SetAnimationUpdateIfNeeded(state, *element);
@@ -828,7 +828,7 @@
   DCHECK(style);
   parent_style->AddCachedPseudoStyle(style);
 
-  if (!PseudoElementLayoutObjectIsNeeded(style.Get()))
+  if (!PseudoElementLayoutObjectIsNeeded(style.get()))
     return nullptr;
 
   PseudoElement* pseudo = CreatePseudoElement(&parent, pseudo_id);
@@ -949,7 +949,7 @@
 RefPtr<ComputedStyle> StyleResolver::StyleForPage(int page_index) {
   RefPtr<ComputedStyle> initial_style = InitialStyleForElement(GetDocument());
   StyleResolverState state(GetDocument(), GetDocument().documentElement(),
-                           initial_style.Get(), initial_style.Get());
+                           initial_style.get(), initial_style.get());
 
   RefPtr<ComputedStyle> style = ComputedStyle::Create();
   const ComputedStyle* root_element_style =
@@ -1855,7 +1855,7 @@
       state, match_result.UaRules(), true, apply_inherited_only,
       needs_apply_pass);
 
-  if (UNLIKELY(isSVGForeignObjectElement(state.GetElement()))) {
+  if (UNLIKELY(IsSVGForeignObjectElement(state.GetElement()))) {
     // LayoutSVGRoot handles zooming for the whole SVG subtree, so foreignObject
     // content should not be scaled again.
     //
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolverState.cpp b/third_party/WebKit/Source/core/css/resolver/StyleResolverState.cpp
index f52f8ce..06fcc55 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleResolverState.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleResolverState.cpp
@@ -83,7 +83,7 @@
   // FIXME: Improve RAII of StyleResolverState to remove this function.
   style_ = std::move(style);
   css_to_length_conversion_data_ = CSSToLengthConversionData(
-      style_.Get(), RootElementStyle(), GetDocument().GetLayoutViewItem(),
+      style_.get(), RootElementStyle(), GetDocument().GetLayoutViewItem(),
       style_->EffectiveZoom());
 }
 
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolverState.h b/third_party/WebKit/Source/core/css/resolver/StyleResolverState.h
index fc00abbdc..30c54da7 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleResolverState.h
+++ b/third_party/WebKit/Source/core/css/resolver/StyleResolverState.h
@@ -81,8 +81,8 @@
   }
 
   void SetStyle(RefPtr<ComputedStyle>);
-  const ComputedStyle* Style() const { return style_.Get(); }
-  ComputedStyle* Style() { return style_.Get(); }
+  const ComputedStyle* Style() const { return style_.get(); }
+  ComputedStyle* Style() { return style_.get(); }
   RefPtr<ComputedStyle> TakeStyle();
 
   ComputedStyle& MutableStyleRef() const { return *style_; }
@@ -129,11 +129,11 @@
   }
 
   void SetParentStyle(RefPtr<const ComputedStyle>);
-  const ComputedStyle* ParentStyle() const { return parent_style_.Get(); }
+  const ComputedStyle* ParentStyle() const { return parent_style_.get(); }
 
   void SetLayoutParentStyle(RefPtr<const ComputedStyle>);
   const ComputedStyle* LayoutParentStyle() const {
-    return layout_parent_style_.Get();
+    return layout_parent_style_.get();
   }
 
   // FIXME: These are effectively side-channel "out parameters" for the various
diff --git a/third_party/WebKit/Source/core/dom/AXObjectCache.cpp b/third_party/WebKit/Source/core/dom/AXObjectCache.cpp
index d7ad4864..fe760f12 100644
--- a/third_party/WebKit/Source/core/dom/AXObjectCache.cpp
+++ b/third_party/WebKit/Source/core/dom/AXObjectCache.cpp
@@ -162,7 +162,7 @@
         return true;
     }
     cur_node = cur_node->parentNode();
-  } while (cur_node && !isHTMLBodyElement(node));
+  } while (cur_node && !IsHTMLBodyElement(node));
   return false;
 }
 
diff --git a/third_party/WebKit/Source/core/dom/ContainerNode.cpp b/third_party/WebKit/Source/core/dom/ContainerNode.cpp
index 7fd2504..afb9bc0 100644
--- a/third_party/WebKit/Source/core/dom/ContainerNode.cpp
+++ b/third_party/WebKit/Source/core/dom/ContainerNode.cpp
@@ -184,10 +184,17 @@
     return false;
 
   bool child_contains_parent = false;
-  if (IsInShadowTree() || GetDocument().IsTemplateDocument())
+  if (IsInShadowTree() || GetDocument().IsTemplateDocument()) {
     child_contains_parent = new_child.ContainsIncludingHostElements(*this);
-  else
-    child_contains_parent = new_child.contains(this);
+  } else {
+    const Node& root = TreeRoot();
+    if (root.IsDocumentFragment() &&
+        ToDocumentFragment(root).IsTemplateContent()) {
+      child_contains_parent = new_child.ContainsIncludingHostElements(*this);
+    } else {
+      child_contains_parent = new_child.contains(this);
+    }
+  }
   if (child_contains_parent) {
     exception_state.ThrowDOMException(
         kHierarchyRequestError, "The new child element contains the parent.");
@@ -465,7 +472,7 @@
   DCHECK(new_child);
   DCHECK_EQ(next_child.parentNode(), this);
   DCHECK(!new_child->IsDocumentFragment());
-  DCHECK(!isHTMLTemplateElement(this));
+  DCHECK(!IsHTMLTemplateElement(this));
 
   if (next_child.previousSibling() == new_child ||
       &next_child == new_child)  // nothing to do
@@ -837,7 +844,7 @@
 void ContainerNode::ParserAppendChild(Node* new_child) {
   DCHECK(new_child);
   DCHECK(!new_child->IsDocumentFragment());
-  DCHECK(!isHTMLTemplateElement(this));
+  DCHECK(!IsHTMLTemplateElement(this));
 
   RUNTIME_CALL_TIMER_SCOPE(V8PerIsolateData::MainThreadIsolate(),
                            RuntimeCallStats::CounterId::kParserAppendChild);
@@ -1522,9 +1529,8 @@
   DCHECK(!NeedsReattachLayoutTree());
 
   if (IsActiveSlotOrActiveV0InsertionPoint()) {
-    if (isHTMLSlotElement(this)) {
-      toHTMLSlotElement(this)->RebuildDistributedChildrenLayoutTrees(
-          whitespace_attacher);
+    if (auto* slot = ToHTMLSlotElementOrNull(this)) {
+      slot->RebuildDistributedChildrenLayoutTrees(whitespace_attacher);
     } else {
       ToV0InsertionPoint(this)->RebuildDistributedChildrenLayoutTrees(
           whitespace_attacher);
@@ -1680,7 +1686,7 @@
 
 RadioNodeList* ContainerNode::GetRadioNodeList(const AtomicString& name,
                                                bool only_match_img_elements) {
-  DCHECK(isHTMLFormElement(this) || isHTMLFieldSetElement(this));
+  DCHECK(IsHTMLFormElement(this) || IsHTMLFieldSetElement(this));
   CollectionType type =
       only_match_img_elements ? kRadioImgNodeListType : kRadioNodeListType;
   return EnsureCachedCollection<RadioNodeList>(type, name);
@@ -1718,7 +1724,7 @@
   if (node->IsV0InsertionPoint())
     return true;
 
-  if (isHTMLSlotElement(node))
+  if (IsHTMLSlotElement(node))
     return true;
 
   if (node->IsElementNode() && ToElement(node)->Shadow())
diff --git a/third_party/WebKit/Source/core/dom/DOMImplementation.cpp b/third_party/WebKit/Source/core/dom/DOMImplementation.cpp
index 21d3d40..9ddecc7 100644
--- a/third_party/WebKit/Source/core/dom/DOMImplementation.cpp
+++ b/third_party/WebKit/Source/core/dom/DOMImplementation.cpp
@@ -242,7 +242,7 @@
     // For that reason, the origin must be retrieved directly from init.url().
     if (init.GetFrame()->IsMainFrame()) {
       RefPtr<SecurityOrigin> origin = SecurityOrigin::Create(init.Url());
-      plugin_data = init.GetFrame()->GetPage()->GetPluginData(origin.Get());
+      plugin_data = init.GetFrame()->GetPage()->GetPluginData(origin.get());
     } else {
       plugin_data =
           init.GetFrame()->GetPage()->GetPluginData(init.GetFrame()
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index bf1e165b..a7f642e 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -783,7 +783,7 @@
 }
 
 bool Document::HasAppCacheManifest() const {
-  return isHTMLHtmlElement(documentElement()) &&
+  return IsHTMLHtmlElement(documentElement()) &&
          documentElement()->hasAttribute(manifestAttr);
 }
 
@@ -851,17 +851,17 @@
 String GetTypeExtension(Document* document,
                         const StringOrDictionary& string_or_options,
                         ExceptionState& exception_state) {
-  if (string_or_options.isNull())
+  if (string_or_options.IsNull())
     return g_empty_string;
 
-  if (string_or_options.isString()) {
+  if (string_or_options.IsString()) {
     UseCounter::Count(document,
                       WebFeature::kDocumentCreateElement2ndArgStringHandling);
-    return string_or_options.getAsString();
+    return string_or_options.GetAsString();
   }
 
-  if (string_or_options.isDictionary()) {
-    Dictionary dict = string_or_options.getAsDictionary();
+  if (string_or_options.IsDictionary()) {
+    Dictionary dict = string_or_options.GetAsDictionary();
     ElementCreationOptions impl;
     V8ElementCreationOptions::ToImpl(dict.GetIsolate(), dict.V8Value(), impl,
                                      exception_state);
@@ -890,12 +890,12 @@
   // 2. localName converted to ASCII lowercase
   const AtomicString& converted_local_name = ConvertLocalName(local_name);
 
-  bool is_v1 = string_or_options.isDictionary() || !RegistrationContext();
+  bool is_v1 = string_or_options.IsDictionary() || !RegistrationContext();
   bool create_v1_builtin =
-      string_or_options.isDictionary() &&
+      string_or_options.IsDictionary() &&
       RuntimeEnabledFeatures::CustomElementsBuiltinEnabled();
   bool should_create_builtin =
-      create_v1_builtin || string_or_options.isString();
+      create_v1_builtin || string_or_options.IsString();
 
   // 3.
   const AtomicString& is =
@@ -943,10 +943,10 @@
 
   // 8. If 'is' is non-null, set 'is' attribute
   if (!is.IsEmpty()) {
-    if (string_or_options.isString()) {
+    if (string_or_options.IsString()) {
       V0CustomElementRegistrationContext::SetIsAttributeAndTypeExtension(
           element, is);
-    } else if (string_or_options.isDictionary()) {
+    } else if (string_or_options.IsDictionary()) {
       element->setAttribute(HTMLNames::isAttr, is);
     }
   }
@@ -1000,12 +1000,12 @@
   if (q_name == QualifiedName::Null())
     return nullptr;
 
-  bool is_v1 = string_or_options.isDictionary() || !RegistrationContext();
+  bool is_v1 = string_or_options.IsDictionary() || !RegistrationContext();
   bool create_v1_builtin =
-      string_or_options.isDictionary() &&
+      string_or_options.IsDictionary() &&
       RuntimeEnabledFeatures::CustomElementsBuiltinEnabled();
   bool should_create_builtin =
-      create_v1_builtin || string_or_options.isString();
+      create_v1_builtin || string_or_options.IsString();
 
   // 2.
   const AtomicString& is =
@@ -1054,7 +1054,7 @@
     if (element->GetCustomElementState() != CustomElementState::kCustom) {
       V0CustomElementRegistrationContext::SetIsAttributeAndTypeExtension(
           element, is);
-    } else if (string_or_options.isDictionary()) {
+    } else if (string_or_options.IsDictionary()) {
       element->setAttribute(HTMLNames::isAttr, is);
     }
   }
@@ -1254,7 +1254,7 @@
         if (!ImportContainerNodeChildren(old_element, new_element,
                                          exception_state))
           return nullptr;
-        if (isHTMLTemplateElement(*old_element) &&
+        if (IsHTMLTemplateElement(*old_element) &&
             !EnsureTemplateDocument().ImportContainerNodeChildren(
                 toHTMLTemplateElement(old_element)->content(),
                 toHTMLTemplateElement(new_element)->content(), exception_state))
@@ -1647,7 +1647,7 @@
       head_element->AppendChild(title_element_.Get());
     } else if (IsSVGDocument()) {
       Element* element = documentElement();
-      if (!isSVGSVGElement(element))
+      if (!IsSVGSVGElement(element))
         return;
       title_element_ = SVGTitleElement::Create(*this);
       element->InsertBefore(title_element_.Get(), element->firstChild());
@@ -1657,10 +1657,10 @@
       title_element_ = nullptr;
   }
 
-  if (isHTMLTitleElement(title_element_))
-    toHTMLTitleElement(title_element_)->setText(title);
-  else if (isSVGTitleElement(title_element_))
-    toSVGTitleElement(title_element_)->SetText(title);
+  if (auto* html_title = ToHTMLTitleElementOrNull(title_element_))
+    html_title->setText(title);
+  else if (auto* svg_title = ToSVGTitleElementOrNull(title_element_))
+    svg_title->SetText(title);
   else
     UpdateTitle(title);
 }
@@ -1669,7 +1669,7 @@
   // If the root element is an svg element in the SVG namespace, then let value
   // be the child text content of the first title element in the SVG namespace
   // that is a child of the root element.
-  if (isSVGSVGElement(documentElement())) {
+  if (IsSVGSVGElement(documentElement())) {
     title_element_ = Traversal<SVGTitleElement>::FirstChild(*documentElement());
   } else {
     if (title_element_ && title_element_ != title_element)
@@ -1679,16 +1679,16 @@
 
     // If the root element isn't an svg element in the SVG namespace and the
     // title element is in the SVG namespace, it is ignored.
-    if (isSVGTitleElement(title_element_)) {
+    if (IsSVGTitleElement(title_element_)) {
       title_element_ = nullptr;
       return;
     }
   }
 
-  if (isHTMLTitleElement(title_element_))
-    UpdateTitle(toHTMLTitleElement(title_element_)->text());
-  else if (isSVGTitleElement(title_element_))
-    UpdateTitle(toSVGTitleElement(title_element_)->textContent());
+  if (auto* html_title = ToHTMLTitleElementOrNull(title_element_))
+    UpdateTitle(html_title->text());
+  else if (auto* svg_title = ToSVGTitleElementOrNull(title_element_))
+    UpdateTitle(svg_title->textContent());
 }
 
 void Document::RemoveTitle(Element* title_element) {
@@ -1713,15 +1713,15 @@
 
 const AtomicString& Document::dir() {
   Element* root_element = documentElement();
-  if (isHTMLHtmlElement(root_element))
-    return toHTMLHtmlElement(root_element)->dir();
+  if (auto* html = ToHTMLHtmlElementOrNull(root_element))
+    return html->dir();
   return g_null_atom;
 }
 
 void Document::setDir(const AtomicString& value) {
   Element* root_element = documentElement();
-  if (isHTMLHtmlElement(root_element))
-    toHTMLHtmlElement(root_element)->setDir(value);
+  if (auto* html = ToHTMLHtmlElementOrNull(root_element))
+    html->setDir(value);
 }
 
 PageVisibilityState Document::GetPageVisibilityState() const {
@@ -1946,7 +1946,7 @@
   // <html> root element with no background steals background from its first
   // <body> child.
   // Also see LayoutBoxModelObject::backgroundStolenForBeingBody()
-  if (isHTMLHtmlElement(documentElement()) && isHTMLBodyElement(body) &&
+  if (IsHTMLHtmlElement(documentElement()) && IsHTMLBodyElement(body) &&
       !background_style->HasBackground())
     background_style = body_style;
 
@@ -2869,7 +2869,7 @@
 bool Document::IsFrameSet() const {
   if (!IsHTMLDocument())
     return false;
-  return isHTMLFrameSetElement(body());
+  return IsHTMLFrameSetElement(body());
 }
 
 ScriptableDocumentParser* Document::GetScriptableDocumentParser() const {
@@ -3013,13 +3013,13 @@
 }
 
 HTMLElement* Document::body() const {
-  if (!documentElement() || !isHTMLHtmlElement(documentElement()))
+  if (!documentElement() || !IsHTMLHtmlElement(documentElement()))
     return 0;
 
   for (HTMLElement* child =
            Traversal<HTMLElement>::FirstChild(*documentElement());
        child; child = Traversal<HTMLElement>::NextSibling(*child)) {
-    if (isHTMLFrameSetElement(*child) || isHTMLBodyElement(*child))
+    if (IsHTMLFrameSetElement(*child) || IsHTMLBodyElement(*child))
       return child;
   }
 
@@ -3027,14 +3027,14 @@
 }
 
 HTMLBodyElement* Document::FirstBodyElement() const {
-  if (!documentElement() || !isHTMLHtmlElement(documentElement()))
+  if (!documentElement() || !IsHTMLHtmlElement(documentElement()))
     return 0;
 
   for (HTMLElement* child =
            Traversal<HTMLElement>::FirstChild(*documentElement());
        child; child = Traversal<HTMLElement>::NextSibling(*child)) {
-    if (isHTMLBodyElement(*child))
-      return toHTMLBodyElement(child);
+    if (auto* body = ToHTMLBodyElementOrNull(*child))
+      return body;
   }
 
   return 0;
@@ -3056,7 +3056,7 @@
     return;
   }
 
-  if (!isHTMLBodyElement(*new_body) && !isHTMLFrameSetElement(*new_body)) {
+  if (!IsHTMLBodyElement(*new_body) && !IsHTMLFrameSetElement(*new_body)) {
     exception_state.ThrowDOMException(
         kHierarchyRequestError,
         "The new body element is of type '" + new_body->tagName() +
@@ -3112,7 +3112,7 @@
       return nullptr;
   }
   if (body_element && root_style->IsOverflowVisible() &&
-      isHTMLHtmlElement(*root_element))
+      IsHTMLHtmlElement(*root_element))
     return body_element;
   return root_element;
 }
@@ -3380,8 +3380,8 @@
 
   if (load_event_progress_ <= kUnloadEventInProgress) {
     Element* current_focused_element = FocusedElement();
-    if (isHTMLInputElement(current_focused_element))
-      toHTMLInputElement(*current_focused_element).EndEditing();
+    if (auto* input = ToHTMLInputElementOrNull(current_focused_element))
+      input->EndEditing();
     if (load_event_progress_ < kPageHideInProgress) {
       load_event_progress_ = kPageHideInProgress;
       if (LocalDOMWindow* window = domWindow()) {
@@ -3500,7 +3500,7 @@
   if (IsRenderingReady() && body())
     return true;
 
-  if (documentElement() && !isHTMLHtmlElement(*documentElement()))
+  if (documentElement() && !IsHTMLHtmlElement(*documentElement()))
     return true;
 
   return false;
@@ -4052,10 +4052,10 @@
   if (!request.ReadOnly())
     UpdateHoverActiveState(request, result.InnerElement());
 
-  if (isHTMLCanvasElement(result.InnerNode())) {
+  if (auto* canvas = ToHTMLCanvasElementOrNull(result.InnerNode())) {
     HitTestCanvasResult* hit_test_canvas_result =
-        toHTMLCanvasElement(result.InnerNode())
-            ->GetControlAndIdIfHitRegionExists(result.PointInInnerNodeFrame());
+        canvas->GetControlAndIdIfHitRegionExists(
+            result.PointInInnerNodeFrame());
     if (hit_test_canvas_result->GetControl()) {
       result.SetInnerNode(hit_test_canvas_result->GetControl());
     }
@@ -5003,7 +5003,7 @@
     AddListenerType(kScrollListener);
   } else if (event_type == EventTypeNames::load) {
     if (Node* node = event_target.ToNode()) {
-      if (isHTMLStyleElement(*node)) {
+      if (IsHTMLStyleElement(*node)) {
         AddListenerType(kLoadListenerAtCapturePhaseOrAtStyleElement);
         return;
       }
@@ -5700,7 +5700,7 @@
 }
 
 bool Document::HasSVGRootNode() const {
-  return isSVGSVGElement(documentElement());
+  return IsSVGSVGElement(documentElement());
 }
 
 HTMLCollection* Document::images() {
@@ -5848,7 +5848,7 @@
   HTMLLinkElement* first_element = nullptr;
   if (head()) {
     first_element = Traversal<HTMLLinkElement>::FirstChild(*head());
-  } else if (IsSVGDocument() && isSVGSVGElement(documentElement())) {
+  } else if (IsSVGDocument() && IsSVGSVGElement(documentElement())) {
     first_element = Traversal<HTMLLinkElement>::FirstWithin(*documentElement());
     find_next_candidate = &Traversal<HTMLLinkElement>::Next;
   }
@@ -6135,7 +6135,7 @@
 
 bool Document::IsSecureTransitionTo(const KURL& url) const {
   RefPtr<SecurityOrigin> other = SecurityOrigin::Create(url);
-  return GetSecurityOrigin()->CanAccess(other.Get());
+  return GetSecurityOrigin()->CanAccess(other.get());
 }
 
 bool Document::CanExecuteScripts(ReasonForCallingCanExecuteScripts reason) {
@@ -6319,18 +6319,23 @@
 static void RunAddConsoleMessageTask(MessageSource source,
                                      MessageLevel level,
                                      const String& message,
+                                     Vector<DOMNodeId> nodes,
                                      ExecutionContext* context) {
-  context->AddConsoleMessage(ConsoleMessage::Create(source, level, message));
+  ConsoleMessage* console_message =
+      ConsoleMessage::Create(source, level, message);
+  console_message->SetNodes(std::move(nodes));
+  context->AddConsoleMessage(console_message);
 }
 
 void Document::AddConsoleMessage(ConsoleMessage* console_message) {
   if (!IsContextThread()) {
     TaskRunnerHelper::Get(TaskType::kUnthrottled, this)
-        ->PostTask(BLINK_FROM_HERE,
-                   CrossThreadBind(
-                       &RunAddConsoleMessageTask, console_message->Source(),
-                       console_message->Level(), console_message->Message(),
-                       WrapCrossThreadPersistent(this)));
+        ->PostTask(
+            BLINK_FROM_HERE,
+            CrossThreadBind(
+                &RunAddConsoleMessageTask, console_message->Source(),
+                console_message->Level(), console_message->Message(),
+                console_message->Nodes(), WrapCrossThreadPersistent(this)));
     return;
   }
 
@@ -6345,10 +6350,12 @@
       if (parser->IsParsingAtLineNumber())
         line_number = parser->LineNumber().OneBasedInt();
     }
+    Vector<DOMNodeId> nodes(console_message->Nodes());
     console_message = ConsoleMessage::Create(
         console_message->Source(), console_message->Level(),
         console_message->Message(),
         SourceLocation::Create(Url().GetString(), line_number, 0, nullptr));
+    console_message->SetNodes(std::move(nodes));
   }
   frame_->Console().AddMessage(console_message);
 }
@@ -6407,8 +6414,8 @@
 HTMLDialogElement* Document::ActiveModalDialog() const {
   for (auto it = top_layer_elements_.rbegin(); it != top_layer_elements_.rend();
        ++it) {
-    if (isHTMLDialogElement(*it))
-      return toHTMLDialogElement((*it).Get());
+    if (auto* dialog = ToHTMLDialogElementOrNull(*it))
+      return dialog;
   }
 
   return nullptr;
diff --git a/third_party/WebKit/Source/core/dom/DocumentStatisticsCollector.cpp b/third_party/WebKit/Source/core/dom/DocumentStatisticsCollector.cpp
index 7b32882..fd2bb71c 100644
--- a/third_party/WebKit/Source/core/dom/DocumentStatisticsCollector.cpp
+++ b/third_party/WebKit/Source/core/dom/DocumentStatisticsCollector.cpp
@@ -168,7 +168,7 @@
   DEFINE_STATIC_LOCAL(AtomicString, property_attr, ("property"));
   for (const Element* child = ElementTraversal::FirstChild(head); child;
        child = ElementTraversal::NextSibling(*child)) {
-    if (!isHTMLMetaElement(*child))
+    if (!IsHTMLMetaElement(*child))
       continue;
     const HTMLMetaElement& meta = toHTMLMetaElement(*child);
 
diff --git a/third_party/WebKit/Source/core/dom/DynamicModuleResolverTest.cpp b/third_party/WebKit/Source/core/dom/DynamicModuleResolverTest.cpp
index c22b432a..f60a51fbf 100644
--- a/third_party/WebKit/Source/core/dom/DynamicModuleResolverTest.cpp
+++ b/third_party/WebKit/Source/core/dom/DynamicModuleResolverTest.cpp
@@ -39,7 +39,7 @@
 
  private:
   // Implements Modulator:
-  ScriptState* GetScriptState() final { return script_state_.Get(); }
+  ScriptState* GetScriptState() final { return script_state_.get(); }
 
   ModuleScript* GetFetchedModuleScript(const KURL& url) final {
     EXPECT_EQ(kTestReferrerURL, url.GetString());
@@ -60,22 +60,22 @@
                             CaptureEvalErrorFlag capture_error) final {
     EXPECT_EQ(CaptureEvalErrorFlag::kCapture, capture_error);
 
-    ScriptState::Scope scope(script_state_.Get());
-    return module_script->Record().Evaluate(script_state_.Get(),
+    ScriptState::Scope scope(script_state_.get());
+    return module_script->Record().Evaluate(script_state_.get(),
                                             CaptureEvalErrorFlag::kCapture);
   }
 
   ScriptModuleState GetRecordStatus(ScriptModule script_module) final {
-    ScriptState::Scope scope(script_state_.Get());
-    return script_module.Status(script_state_.Get());
+    ScriptState::Scope scope(script_state_.get());
+    return script_module.Status(script_state_.get());
   }
 
   ScriptValue GetError(const ModuleScript* module_script) final {
-    ScriptState::Scope scope(script_state_.Get());
+    ScriptState::Scope scope(script_state_.get());
     ScriptModule record = module_script->Record();
     DCHECK(!record.IsNull());
-    return ScriptValue(script_state_.Get(),
-                       record.ErrorCompletion(script_state_.Get()));
+    return ScriptValue(script_state_.get(),
+                       record.ErrorCompletion(script_state_.get()));
   }
 
   RefPtr<ScriptState> script_state_;
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp
index b6464b5..12782e1 100644
--- a/third_party/WebKit/Source/core/dom/Element.cpp
+++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -127,7 +127,6 @@
 #include "core/layout/LayoutTextFragment.h"
 #include "core/layout/api/LayoutBoxItem.h"
 #include "core/layout/api/LayoutViewItem.h"
-#include "core/loader/DocumentLoader.h"
 #include "core/page/ChromeClient.h"
 #include "core/page/FocusController.h"
 #include "core/page/Page.h"
@@ -461,14 +460,14 @@
 
 void Element::scrollIntoView(ScrollIntoViewOptionsOrBoolean arg) {
   ScrollIntoViewOptions options;
-  if (arg.isBoolean()) {
-    if (arg.getAsBoolean())
+  if (arg.IsBoolean()) {
+    if (arg.GetAsBoolean())
       options.setBlock("start");
     else
       options.setBlock("end");
     options.setInlinePosition("nearest");
-  } else if (arg.isScrollIntoViewOptions()) {
-    options = arg.getAsScrollIntoViewOptions();
+  } else if (arg.IsScrollIntoViewOptions()) {
+    options = arg.GetAsScrollIntoViewOptions();
     if (!RuntimeEnabledFeatures::CSSOMSmoothScrollEnabled() &&
         options.behavior() == "smooth") {
       options.setBehavior("instant");
@@ -479,7 +478,7 @@
 
 void Element::scrollIntoView(bool align_to_top) {
   ScrollIntoViewOptionsOrBoolean arg;
-  arg.setBoolean(align_to_top);
+  arg.SetBoolean(align_to_top);
   scrollIntoView(arg);
 }
 
@@ -682,10 +681,6 @@
   // that if JS overrides one of these methods, but not the
   // other, this bookkeeping remains accurate.
   scroll_state.SetCurrentNativeScrollingElement(this);
-  if (scroll_state.fromUserInput()) {
-    if (DocumentLoader* document_loader = GetDocument().Loader())
-      document_loader->GetInitialScrollState().was_scrolled_by_user = true;
-  }
 };
 
 void Element::CallApplyScroll(ScrollState& scroll_state) {
@@ -1371,17 +1366,17 @@
 void Element::setAttribute(const QualifiedName& name,
                            const StringOrTrustedScriptURL& stringOrURL,
                            ExceptionState& exception_state) {
-  DCHECK(stringOrURL.isString() ||
+  DCHECK(stringOrURL.IsString() ||
          RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
-  if (stringOrURL.isString() && GetDocument().RequireTrustedTypes()) {
+  if (stringOrURL.IsString() && GetDocument().RequireTrustedTypes()) {
     exception_state.ThrowTypeError(
         "This document requires `TrustedScriptURL` assignment.");
     return;
   }
 
-  String valueString = stringOrURL.isString()
-                           ? stringOrURL.getAsString()
-                           : stringOrURL.getAsTrustedScriptURL()->toString();
+  String valueString = stringOrURL.IsString()
+                           ? stringOrURL.GetAsString()
+                           : stringOrURL.GetAsTrustedScriptURL()->toString();
 
   setAttribute(name, AtomicString(valueString));
 }
@@ -2137,7 +2132,7 @@
     return kReattach;
 
   StyleRecalcChange local_change =
-      ComputedStyle::StylePropagationDiff(old_style.Get(), new_style.Get());
+      ComputedStyle::StylePropagationDiff(old_style.get(), new_style.get());
   if (local_change == kNoChange) {
     INCREMENT_STYLE_STATS_COUNTER(GetDocument().GetStyleEngine(),
                                   styles_unchanged, 1);
@@ -2145,8 +2140,8 @@
     INCREMENT_STYLE_STATS_COUNTER(GetDocument().GetStyleEngine(),
                                   styles_changed, 1);
     if (this == GetDocument().documentElement()) {
-      if (GetDocument().GetStyleEngine().UpdateRemUnits(old_style.Get(),
-                                                        new_style.Get())) {
+      if (GetDocument().GetStyleEngine().UpdateRemUnits(old_style.get(),
+                                                        new_style.get())) {
         // Trigger a full document recalc on rem unit changes. We could keep
         // track of which elements depend on rem units like we do for viewport
         // styles, but we assume root font size changes are rare and just
@@ -2166,7 +2161,7 @@
   DCHECK(old_style);
 
   if (local_change != kNoChange)
-    UpdateCallbackSelectors(old_style.Get(), new_style.Get());
+    UpdateCallbackSelectors(old_style.get(), new_style.get());
 
   if (LayoutObject* layout_object = this->GetLayoutObject()) {
     // kNoChange may means that the computed style didn't change, but there are
@@ -2175,9 +2170,9 @@
     // invalidation diffing in that case, but we replace the old ComputedStyle
     // object with the new one to ensure the mentioned flags are up to date.
     if (local_change == kNoChange)
-      layout_object->SetStyleInternal(new_style.Get());
+      layout_object->SetStyleInternal(new_style.get());
     else
-      layout_object->SetStyle(new_style.Get());
+      layout_object->SetStyle(new_style.get());
   } else {
     if (ShouldStoreNonLayoutObjectComputedStyle(*new_style))
       StoreNonLayoutObjectComputedStyle(new_style);
@@ -3072,11 +3067,11 @@
 }
 
 void Element::innerHTML(StringOrTrustedHTML& result) const {
-  result.setString(InnerHTMLAsString());
+  result.SetString(InnerHTMLAsString());
 }
 
 void Element::outerHTML(StringOrTrustedHTML& result) const {
-  result.setString(OuterHTMLAsString());
+  result.SetString(OuterHTMLAsString());
 }
 
 void Element::SetInnerHTMLFromString(const String& html,
@@ -3085,8 +3080,8 @@
   if (DocumentFragment* fragment = CreateFragmentForInnerOuterHTML(
           html, this, kAllowScriptingContent, "innerHTML", exception_state)) {
     ContainerNode* container = this;
-    if (isHTMLTemplateElement(*this))
-      container = toHTMLTemplateElement(this)->content();
+    if (auto* template_element = ToHTMLTemplateElementOrNull(*this))
+      container = template_element->content();
     ReplaceChildrenWithFragment(container, fragment, exception_state);
   }
 }
@@ -3095,20 +3090,20 @@
   SetInnerHTMLFromString(html, ASSERT_NO_EXCEPTION);
 }
 
-void Element::setInnerHTML(const StringOrTrustedHTML& stringOrHtml,
+void Element::setInnerHTML(const StringOrTrustedHTML& string_or_html,
                            ExceptionState& exception_state) {
-  DCHECK(stringOrHtml.isString() ||
+  DCHECK(string_or_html.IsString() ||
          RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
 
-  if (stringOrHtml.isString() && GetDocument().RequireTrustedTypes()) {
+  if (string_or_html.IsString() && GetDocument().RequireTrustedTypes()) {
     exception_state.ThrowTypeError(
         "This document requires `TrustedHTML` assignment.");
     return;
   }
 
-  String html = stringOrHtml.isString()
-                    ? stringOrHtml.getAsString()
-                    : stringOrHtml.getAsTrustedHTML()->toString();
+  String html = string_or_html.IsString()
+                    ? string_or_html.GetAsString()
+                    : string_or_html.GetAsTrustedHTML()->toString();
 
   // TODO(mkwst): This is an ugly hack that will be resolved once `TreatNullAs`
   // is treated as an extended attribute on the `DOMString` type rather than
@@ -3119,8 +3114,8 @@
   SetInnerHTMLFromString(html, exception_state);
 }
 
-void Element::setInnerHTML(const StringOrTrustedHTML& stringOrHtml) {
-  setInnerHTML(stringOrHtml, ASSERT_NO_EXCEPTION);
+void Element::setInnerHTML(const StringOrTrustedHTML& string_or_html) {
+  setInnerHTML(string_or_html, ASSERT_NO_EXCEPTION);
 }
 
 void Element::SetOuterHTMLFromString(const String& html,
@@ -3157,20 +3152,20 @@
     MergeWithNextTextNode(ToText(prev), exception_state);
 }
 
-void Element::setOuterHTML(const StringOrTrustedHTML& stringOrHtml,
+void Element::setOuterHTML(const StringOrTrustedHTML& string_or_html,
                            ExceptionState& exception_state) {
-  DCHECK(stringOrHtml.isString() ||
+  DCHECK(string_or_html.IsString() ||
          RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
 
-  if (stringOrHtml.isString() && GetDocument().RequireTrustedTypes()) {
+  if (string_or_html.IsString() && GetDocument().RequireTrustedTypes()) {
     exception_state.ThrowTypeError(
         "This document requires `TrustedHTML` assignment.");
     return;
   }
 
-  String html = stringOrHtml.isString()
-                    ? stringOrHtml.getAsString()
-                    : stringOrHtml.getAsTrustedHTML()->toString();
+  String html = string_or_html.IsString()
+                    ? string_or_html.GetAsString()
+                    : string_or_html.GetAsTrustedHTML()->toString();
 
   // TODO(mkwst): This is an ugly hack that will be resolved once `TreatNullAs`
   // is treated as an extended attribute on the `DOMString` type rather than
@@ -3302,20 +3297,20 @@
 }
 
 void Element::insertAdjacentHTML(const String& where,
-                                 const StringOrTrustedHTML& stringOrHtml,
+                                 const StringOrTrustedHTML& string_or_html,
                                  ExceptionState& exception_state) {
-  DCHECK(stringOrHtml.isString() ||
+  DCHECK(string_or_html.IsString() ||
          RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
 
-  if (stringOrHtml.isString() && GetDocument().RequireTrustedTypes()) {
+  if (string_or_html.IsString() && GetDocument().RequireTrustedTypes()) {
     exception_state.ThrowTypeError(
         "This document requires `TrustedHTML` assignment.");
     return;
   }
 
-  String markup = stringOrHtml.isString()
-                      ? stringOrHtml.getAsString()
-                      : stringOrHtml.getAsTrustedHTML()->toString();
+  String markup = string_or_html.IsString()
+                      ? string_or_html.GetAsString()
+                      : string_or_html.GetAsTrustedHTML()->toString();
 
   insertAdjacentHTML(where, markup, exception_state);
 }
@@ -3525,7 +3520,7 @@
 #endif
 
   return style.Display() == EDisplay::kContents ||
-         isHTMLOptGroupElement(*this) || isHTMLOptionElement(*this);
+         IsHTMLOptGroupElement(*this) || IsHTMLOptionElement(*this);
 }
 
 void Element::StoreNonLayoutObjectComputedStyle(RefPtr<ComputedStyle> style) {
@@ -3786,11 +3781,11 @@
 KURL Element::HrefURL() const {
   // FIXME: These all have href() or url(), but no common super class. Why
   // doesn't <link> implement URLUtils?
-  if (isHTMLAnchorElement(*this) || isHTMLAreaElement(*this) ||
-      isHTMLLinkElement(*this))
+  if (IsHTMLAnchorElement(*this) || IsHTMLAreaElement(*this) ||
+      IsHTMLLinkElement(*this))
     return GetURLAttribute(hrefAttr);
-  if (isSVGAElement(*this))
-    return toSVGAElement(*this).LegacyHrefURL(GetDocument());
+  if (auto* svg_a = ToSVGAElementOrNull(*this))
+    return svg_a->LegacyHrefURL(GetDocument());
   return KURL();
 }
 
@@ -3808,7 +3803,7 @@
 void Element::GetURLAttribute(const QualifiedName& name,
                               StringOrTrustedScriptURL& result) const {
   KURL url = GetURLAttribute(name);
-  result.setString(url.GetString());
+  result.SetString(url.GetString());
 }
 
 KURL Element::GetNonEmptyURLAttribute(const QualifiedName& name) const {
diff --git a/third_party/WebKit/Source/core/dom/ElementRareData.h b/third_party/WebKit/Source/core/dom/ElementRareData.h
index cf2335b..ea5490b 100644
--- a/third_party/WebKit/Source/core/dom/ElementRareData.h
+++ b/third_party/WebKit/Source/core/dom/ElementRareData.h
@@ -87,7 +87,7 @@
     attribute_map_ = attribute_map;
   }
 
-  ComputedStyle* GetComputedStyle() const { return computed_style_.Get(); }
+  ComputedStyle* GetComputedStyle() const { return computed_style_.get(); }
   void SetComputedStyle(RefPtr<ComputedStyle>);
   void ClearComputedStyle();
 
diff --git a/third_party/WebKit/Source/core/dom/ElementShadowV0.cpp b/third_party/WebKit/Source/core/dom/ElementShadowV0.cpp
index 8194216..ec4ce373 100644
--- a/third_party/WebKit/Source/core/dom/ElementShadowV0.cpp
+++ b/third_party/WebKit/Source/core/dom/ElementShadowV0.cpp
@@ -64,7 +64,7 @@
 inline void DistributionPool::PopulateChildren(const ContainerNode& parent) {
   Clear();
   for (Node* child = parent.firstChild(); child; child = child->nextSibling()) {
-    if (isHTMLSlotElement(child)) {
+    if (IsHTMLSlotElement(child)) {
       // TODO(hayato): Support re-distribution across v0 and v1 shadow trees
       continue;
     }
@@ -88,7 +88,7 @@
     if (distributed_[i])
       continue;
 
-    if (isHTMLContentElement(*insertion_point) &&
+    if (IsHTMLContentElement(*insertion_point) &&
         !toHTMLContentElement(insertion_point)->CanSelectNode(nodes_, i))
       continue;
 
@@ -168,9 +168,9 @@
     for (const auto& point : root->DescendantInsertionPoints()) {
       if (!point->IsActive())
         continue;
-      if (isHTMLShadowElement(*point)) {
+      if (auto* shadow = ToHTMLShadowElementOrNull(*point)) {
         DCHECK(!shadow_insertion_point);
-        shadow_insertion_point = toHTMLShadowElement(point);
+        shadow_insertion_point = shadow;
         shadow_insertion_points.push_back(shadow_insertion_point);
       } else {
         pool.DistributeTo(point, this);
@@ -232,10 +232,8 @@
       if (!shadow->IsV1())
         select_features_.Add(shadow->V0().EnsureSelectFeatureSet());
     }
-    if (!isHTMLContentElement(element))
-      continue;
-    const CSSSelectorList& list = toHTMLContentElement(element).SelectorList();
-    select_features_.CollectFeaturesFromSelectorList(list);
+    if (auto* content = ToHTMLContentElementOrNull(element))
+      select_features_.CollectFeaturesFromSelectorList(content->SelectorList());
   }
 }
 
diff --git a/third_party/WebKit/Source/core/dom/ElementTest.cpp b/third_party/WebKit/Source/core/dom/ElementTest.cpp
index 06cdc89..cf25fb60 100644
--- a/third_party/WebKit/Source/core/dom/ElementTest.cpp
+++ b/third_party/WebKit/Source/core/dom/ElementTest.cpp
@@ -21,7 +21,7 @@
 
 TEST_F(ElementTest, SupportsFocus) {
   Document& document = GetDocument();
-  DCHECK(isHTMLHtmlElement(document.documentElement()));
+  DCHECK(IsHTMLHtmlElement(document.documentElement()));
   document.setDesignMode("on");
   document.View()->UpdateAllLifecyclePhases();
   EXPECT_TRUE(document.documentElement()->SupportsFocus())
diff --git a/third_party/WebKit/Source/core/dom/FirstLetterPseudoElement.cpp b/third_party/WebKit/Source/core/dom/FirstLetterPseudoElement.cpp
index 356cf4e..00cbd7f 100644
--- a/third_party/WebKit/Source/core/dom/FirstLetterPseudoElement.cpp
+++ b/third_party/WebKit/Source/core/dom/FirstLetterPseudoElement.cpp
@@ -143,7 +143,7 @@
               ? ToLayoutTextFragment(first_letter_text_layout_object)
                     ->CompleteText()
               : ToLayoutText(first_letter_text_layout_object)->OriginalText();
-      if (FirstLetterLength(str.Get()) ||
+      if (FirstLetterLength(str.get()) ||
           IsInvalidFirstLetterLayoutObject(first_letter_text_layout_object))
         break;
       first_letter_text_layout_object =
diff --git a/third_party/WebKit/Source/core/dom/FlatTreeTraversal.cpp b/third_party/WebKit/Source/core/dom/FlatTreeTraversal.cpp
index 1babc5a..10beffb 100644
--- a/third_party/WebKit/Source/core/dom/FlatTreeTraversal.cpp
+++ b/third_party/WebKit/Source/core/dom/FlatTreeTraversal.cpp
@@ -66,12 +66,11 @@
        sibling = (direction == kTraversalDirectionForward
                       ? sibling->nextSibling()
                       : sibling->previousSibling())) {
-    if (isHTMLSlotElement(*sibling)) {
-      const HTMLSlotElement& slot = toHTMLSlotElement(*sibling);
-      if (slot.SupportsDistribution()) {
+    if (auto* slot = ToHTMLSlotElementOrNull(*sibling)) {
+      if (slot->SupportsDistribution()) {
         if (Node* found = (direction == kTraversalDirectionForward
-                               ? slot.FirstDistributedNode()
-                               : slot.LastDistributedNode()))
+                               ? slot->FirstDistributedNode()
+                               : slot->LastDistributedNode()))
           return found;
         continue;
       }
@@ -86,7 +85,7 @@
 Node* FlatTreeTraversal::V0ResolveDistributionStartingAt(
     const Node& node,
     TraversalDirection direction) {
-  DCHECK(!isHTMLSlotElement(node) ||
+  DCHECK(!IsHTMLSlotElement(node) ||
          !toHTMLSlotElement(node).SupportsDistribution());
   for (const Node* sibling = &node; sibling;
        sibling = (direction == kTraversalDirectionForward
@@ -99,8 +98,8 @@
                            ? insertion_point.FirstDistributedNode()
                            : insertion_point.LastDistributedNode()))
       return found;
-    DCHECK(isHTMLShadowElement(insertion_point) ||
-           (isHTMLContentElement(insertion_point) &&
+    DCHECK(IsHTMLShadowElement(insertion_point) ||
+           (IsHTMLContentElement(insertion_point) &&
             !insertion_point.HasChildren()));
   }
   return nullptr;
@@ -125,11 +124,9 @@
 
   // Slotted nodes are already handled in traverseSiblingsForV1HostChild()
   // above, here is for fallback contents.
-  Element* parent = node.parentElement();
-  if (parent && isHTMLSlotElement(parent)) {
-    HTMLSlotElement& slot = toHTMLSlotElement(*parent);
-    if (slot.SupportsDistribution() && slot.AssignedNodes().IsEmpty())
-      return TraverseSiblings(slot, direction);
+  if (auto* slot = ToHTMLSlotElementOrNull(node.parentElement())) {
+    if (slot->SupportsDistribution() && slot->AssignedNodes().IsEmpty())
+      return TraverseSiblings(*slot, direction);
   }
 
   if (!node.IsInV0ShadowTree())
@@ -190,13 +187,11 @@
     return TraverseParent(*slot);
   }
 
-  Element* parent = node.parentElement();
-  if (parent && isHTMLSlotElement(parent)) {
-    HTMLSlotElement& slot = toHTMLSlotElement(*parent);
-    if (slot.SupportsDistribution()) {
-      if (!slot.AssignedNodes().IsEmpty())
+  if (auto* slot = ToHTMLSlotElementOrNull(node.parentElement())) {
+    if (slot->SupportsDistribution()) {
+      if (!slot->AssignedNodes().IsEmpty())
         return nullptr;
-      return TraverseParent(slot, details);
+      return TraverseParent(*slot, details);
     }
   }
 
diff --git a/third_party/WebKit/Source/core/dom/FlatTreeTraversal.h b/third_party/WebKit/Source/core/dom/FlatTreeTraversal.h
index 2e9e958d..23e89d3 100644
--- a/third_party/WebKit/Source/core/dom/FlatTreeTraversal.h
+++ b/third_party/WebKit/Source/core/dom/FlatTreeTraversal.h
@@ -64,7 +64,7 @@
   static Node* LastChild(const Node&);
   static bool HasChildren(const Node&);
 
-  static ContainerNode* Parent(const Node&, ParentTraversalDetails* = 0);
+  static ContainerNode* Parent(const Node&, ParentTraversalDetails* = nullptr);
   static Element* ParentElement(const Node&);
 
   static Node* NextSibling(const Node&);
@@ -150,10 +150,10 @@
   static Node* TraverseChild(const Node&, TraversalDirection);
 
   static ContainerNode* TraverseParent(const Node&,
-                                       ParentTraversalDetails* = 0);
+                                       ParentTraversalDetails* = nullptr);
   // TODO(hayato): Make ParentTraversalDetails be aware of slot elements too.
   static ContainerNode* TraverseParentForV0(const Node&,
-                                            ParentTraversalDetails* = 0);
+                                            ParentTraversalDetails* = nullptr);
   static ContainerNode* TraverseParentOrHost(const Node&);
 
   static Node* TraverseNextSibling(const Node&);
diff --git a/third_party/WebKit/Source/core/dom/LayoutTreeBuilder.h b/third_party/WebKit/Source/core/dom/LayoutTreeBuilder.h
index 52cf3d0..bfd6e29 100644
--- a/third_party/WebKit/Source/core/dom/LayoutTreeBuilder.h
+++ b/third_party/WebKit/Source/core/dom/LayoutTreeBuilder.h
@@ -91,7 +91,7 @@
       CreateLayoutObject();
   }
 
-  ComputedStyle* ResolvedStyle() const { return style_.Get(); }
+  ComputedStyle* ResolvedStyle() const { return style_.get(); }
 
  private:
   LayoutObject* ParentLayoutObject() const;
diff --git a/third_party/WebKit/Source/core/dom/ModulatorImplBase.cpp b/third_party/WebKit/Source/core/dom/ModulatorImplBase.cpp
index 6fbe2121..24d8fcdf 100644
--- a/third_party/WebKit/Source/core/dom/ModulatorImplBase.cpp
+++ b/third_party/WebKit/Source/core/dom/ModulatorImplBase.cpp
@@ -18,19 +18,19 @@
 namespace blink {
 
 ExecutionContext* ModulatorImplBase::GetExecutionContext() const {
-  return ExecutionContext::From(script_state_.Get());
+  return ExecutionContext::From(script_state_.get());
 }
 
 ModulatorImplBase::ModulatorImplBase(RefPtr<ScriptState> script_state)
     : script_state_(std::move(script_state)),
       task_runner_(
-          TaskRunnerHelper::Get(TaskType::kNetworking, script_state_.Get())),
+          TaskRunnerHelper::Get(TaskType::kNetworking, script_state_.get())),
       map_(ModuleMap::Create(this)),
       loader_registry_(ModuleScriptLoaderRegistry::Create()),
       tree_linker_registry_(ModuleTreeLinkerRegistry::Create()),
       script_module_resolver_(ScriptModuleResolverImpl::Create(
           this,
-          ExecutionContext::From(script_state_.Get()))),
+          ExecutionContext::From(script_state_.get()))),
       dynamic_module_resolver_(DynamicModuleResolver::Create(this)) {
   DCHECK(script_state_);
   DCHECK(task_runner_);
@@ -138,26 +138,26 @@
     script_source = provided_source;
 
   // Step 5. Let result be ParseModule(script source, realm, script).
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   return ScriptModule::Compile(script_state_->GetIsolate(), script_source,
                                url_str, access_control_status, credentials_mode,
                                nonce, parser_state, position, exception_state);
 }
 
 ScriptValue ModulatorImplBase::InstantiateModule(ScriptModule script_module) {
-  ScriptState::Scope scope(script_state_.Get());
-  return script_module.Instantiate(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
+  return script_module.Instantiate(script_state_.get());
 }
 
 ScriptModuleState ModulatorImplBase::GetRecordStatus(
     ScriptModule script_module) {
-  ScriptState::Scope scope(script_state_.Get());
-  return script_module.Status(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
+  return script_module.Status(script_state_.get());
 }
 
 ScriptValue ModulatorImplBase::GetError(const ModuleScript* module_script) {
   DCHECK(module_script);
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   // https://html.spec.whatwg.org/multipage/webappapis.html#concept-module-script-error
   // "When a module script is errored, ..." [spec text]
 
@@ -165,22 +165,22 @@
   // module record is null, ..." [spec text]
   ScriptModule record = module_script->Record();
   if (record.IsNull()) {
-    return ScriptValue(script_state_.Get(), module_script->CreateErrorInternal(
+    return ScriptValue(script_state_.get(), module_script->CreateErrorInternal(
                                                 script_state_->GetIsolate()));
   }
 
   // "or its module record's [[ErrorCompletion]] field's [[Value]] field,
   // otherwise." [spec text]
-  return ScriptValue(script_state_.Get(),
-                     record.ErrorCompletion(script_state_.Get()));
+  return ScriptValue(script_state_.get(),
+                     record.ErrorCompletion(script_state_.get()));
 }
 
 Vector<Modulator::ModuleRequest>
 ModulatorImplBase::ModuleRequestsFromScriptModule(ScriptModule script_module) {
-  ScriptState::Scope scope(script_state_.Get());
-  Vector<String> specifiers = script_module.ModuleRequests(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
+  Vector<String> specifiers = script_module.ModuleRequests(script_state_.get());
   Vector<TextPosition> positions =
-      script_module.ModuleRequestPositions(script_state_.Get());
+      script_module.ModuleRequestPositions(script_state_.get());
   DCHECK_EQ(specifiers.size(), positions.size());
   Vector<ModuleRequest> requests;
   requests.ReserveInitialCapacity(specifiers.size());
@@ -209,13 +209,13 @@
 
   // Step 4. "Prepare to run script given settings." [spec text]
   // This is placed here to also cover ScriptModule::ReportException().
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
 
   // Step 3. "If s is errored, then report the exception given by s's error for
   // s and abort these steps." [spec text]
   if (module_script->IsErrored()) {
     ScriptValue error = GetError(module_script);
-    ScriptModule::ReportException(script_state_.Get(), error.V8Value());
+    ScriptModule::ReportException(script_state_.get(), error.V8Value());
     return ScriptValue();
   }
 
@@ -224,7 +224,7 @@
   CHECK(!record.IsNull());
 
   // Step 6. "Let evaluationStatus be record.ModuleEvaluation()." [spec text]
-  ScriptValue eval_error = record.Evaluate(script_state_.Get(), capture_error);
+  ScriptValue eval_error = record.Evaluate(script_state_.get(), capture_error);
   // Step 7. "If evaluationStatus is an abrupt completion, then:" [spec text]
   if (capture_error == CaptureEvalErrorFlag::kCapture) {
     // Step 7.1. "If rethrow errors is true, rethrow the exception given by
diff --git a/third_party/WebKit/Source/core/dom/ModulatorImplBase.h b/third_party/WebKit/Source/core/dom/ModulatorImplBase.h
index 1b873445..3c6c9fe 100644
--- a/third_party/WebKit/Source/core/dom/ModulatorImplBase.h
+++ b/third_party/WebKit/Source/core/dom/ModulatorImplBase.h
@@ -43,10 +43,10 @@
   ScriptModuleResolver* GetScriptModuleResolver() override {
     return script_module_resolver_.Get();
   }
-  WebTaskRunner* TaskRunner() override { return task_runner_.Get(); }
+  WebTaskRunner* TaskRunner() override { return task_runner_.get(); }
   ReferrerPolicy GetReferrerPolicy() override;
   SecurityOrigin* GetSecurityOrigin() override;
-  ScriptState* GetScriptState() override { return script_state_.Get(); }
+  ScriptState* GetScriptState() override { return script_state_.get(); }
 
   void FetchTree(const ModuleScriptFetchRequest&, ModuleTreeClient*) override;
   void FetchDescendantsForInlineScript(ModuleScript*,
diff --git a/third_party/WebKit/Source/core/dom/Node.cpp b/third_party/WebKit/Source/core/dom/Node.cpp
index 1ee324e..b3350a1 100644
--- a/third_party/WebKit/Source/core/dom/Node.cpp
+++ b/third_party/WebKit/Source/core/dom/Node.cpp
@@ -493,7 +493,7 @@
 static bool IsNodeInNodes(const Node* const node,
                           const HeapVector<NodeOrString>& nodes) {
   for (const NodeOrString& node_or_string : nodes) {
-    if (node_or_string.isNode() && node_or_string.getAsNode() == node)
+    if (node_or_string.IsNode() && node_or_string.GetAsNode() == node)
       return true;
   }
   return false;
@@ -521,9 +521,9 @@
 
 static Node* NodeOrStringToNode(const NodeOrString& node_or_string,
                                 Document& document) {
-  if (node_or_string.isNode())
-    return node_or_string.getAsNode();
-  return Text::Create(document, node_or_string.getAsString());
+  if (node_or_string.IsNode())
+    return node_or_string.GetAsNode();
+  return Text::Create(document, node_or_string.GetAsString());
 }
 
 // Returns nullptr if an exception was thrown.
@@ -1123,7 +1123,7 @@
 }
 
 bool Node::IsActiveSlotOrActiveV0InsertionPoint() const {
-  return (isHTMLSlotElement(*this) &&
+  return (IsHTMLSlotElement(*this) &&
           toHTMLSlotElement(*this).SupportsDistribution()) ||
          IsActiveV0InsertionPoint(*this);
 }
@@ -1422,7 +1422,7 @@
 
   StringBuilder content;
   for (const Node& node : NodeTraversal::InclusiveDescendantsOf(*this)) {
-    if (isHTMLBRElement(node) && convert_brs_to_newlines) {
+    if (IsHTMLBRElement(node) && convert_brs_to_newlines) {
       content.Append('\n');
     } else if (node.IsTextNode()) {
       content.Append(ToText(node).data());
@@ -1843,7 +1843,7 @@
                                 const char* marked_label2) const {
   const Node* root_node;
   const Node* node = this;
-  while (node->ParentOrShadowHostNode() && !isHTMLBodyElement(*node))
+  while (node->ParentOrShadowHostNode() && !IsHTMLBodyElement(*node))
     node = node->ParentOrShadowHostNode();
   root_node = node;
 
@@ -1860,7 +1860,7 @@
                                     const char* marked_label2) const {
   const Node* root_node;
   const Node* node = this;
-  while (node->ParentOrShadowHostNode() && !isHTMLBodyElement(*node))
+  while (node->ParentOrShadowHostNode() && !IsHTMLBodyElement(*node))
     node = node->ParentOrShadowHostNode();
   root_node = node;
 
@@ -1922,7 +1922,7 @@
     // For imagemaps, the enclosing link node is the associated area element not
     // the image itself.  So we don't let images be the enclosingLinkNode, even
     // though isLink sometimes returns true for them.
-    if (node->IsLink() && !isHTMLImageElement(*node)) {
+    if (node->IsLink() && !IsHTMLImageElement(*node)) {
       // Casting to Element is safe because only HTMLAnchorElement,
       // HTMLImageElement and SVGAElement can return true for isLink().
       result = node;
@@ -2623,7 +2623,7 @@
   } else if (IsInV1ShadowTree()) {
     // Checking for fallback content if the node is in a v1 shadow tree.
     Element* parent = parentElement();
-    if (parent && isHTMLSlotElement(parent)) {
+    if (parent && IsHTMLSlotElement(parent)) {
       HTMLSlotElement& parent_slot = toHTMLSlotElement(*parent);
       DCHECK(parent_slot.SupportsDistribution());
       // The parent_slot's assigned nodes might not be calculated because they
@@ -2636,7 +2636,7 @@
 }
 
 WebPluginContainerImpl* Node::GetWebPluginContainer() const {
-  if (!isHTMLObjectElement(this) && !isHTMLEmbedElement(this)) {
+  if (!IsHTMLObjectElement(this) && !IsHTMLEmbedElement(this)) {
     return nullptr;
   }
 
diff --git a/third_party/WebKit/Source/core/dom/Node.h b/third_party/WebKit/Source/core/dom/Node.h
index d9573b0..8fb7436 100644
--- a/third_party/WebKit/Source/core/dom/Node.h
+++ b/third_party/WebKit/Source/core/dom/Node.h
@@ -112,7 +112,7 @@
   }
 
   ComputedStyle* GetNonAttachedStyle() const {
-    return non_attached_style_.Get();
+    return non_attached_style_.get();
   }
   void SetNonAttachedStyle(RefPtr<ComputedStyle> non_attached_style);
 
diff --git a/third_party/WebKit/Source/core/dom/PresentationAttributeStyle.cpp b/third_party/WebKit/Source/core/dom/PresentationAttributeStyle.cpp
index 237fcaf0..70f5b3c 100644
--- a/third_party/WebKit/Source/core/dom/PresentationAttributeStyle.cpp
+++ b/third_party/WebKit/Source/core/dom/PresentationAttributeStyle.cpp
@@ -140,7 +140,7 @@
     return;
   // Interpretation of the size attributes on <input> depends on the type
   // attribute.
-  if (isHTMLInputElement(element))
+  if (IsHTMLInputElement(element))
     return;
   AttributeCollection attributes = element.AttributesWithoutUpdate();
   for (const Attribute& attr : attributes) {
diff --git a/third_party/WebKit/Source/core/dom/QualifiedName.h b/third_party/WebKit/Source/core/dom/QualifiedName.h
index f875180..7b845c79 100644
--- a/third_party/WebKit/Source/core/dom/QualifiedName.h
+++ b/third_party/WebKit/Source/core/dom/QualifiedName.h
@@ -140,7 +140,7 @@
 
   String ToString() const;
 
-  QualifiedNameImpl* Impl() const { return impl_.Get(); }
+  QualifiedNameImpl* Impl() const { return impl_.get(); }
 
   // Init routine for globals
   static void InitAndReserveCapacityForSize(unsigned size);
diff --git a/third_party/WebKit/Source/core/dom/Range.cpp b/third_party/WebKit/Source/core/dom/Range.cpp
index 3afa3f32..ffec840 100644
--- a/third_party/WebKit/Source/core/dom/Range.cpp
+++ b/third_party/WebKit/Source/core/dom/Range.cpp
@@ -1015,7 +1015,7 @@
     element = node->parentElement();
 
   // Step 2.
-  if (!element || isHTMLHtmlElement(element)) {
+  if (!element || IsHTMLHtmlElement(element)) {
     Document& document = node->GetDocument();
 
     if (document.IsSVGDocument()) {
diff --git a/third_party/WebKit/Source/core/dom/ScriptElementBase.cpp b/third_party/WebKit/Source/core/dom/ScriptElementBase.cpp
index 136db70d..0e896d3e 100644
--- a/third_party/WebKit/Source/core/dom/ScriptElementBase.cpp
+++ b/third_party/WebKit/Source/core/dom/ScriptElementBase.cpp
@@ -10,10 +10,10 @@
 namespace blink {
 
 ScriptElementBase* ScriptElementBase::FromElementIfPossible(Element* element) {
-  if (isHTMLScriptElement(*element))
-    return toHTMLScriptElement(element);
-  if (isSVGScriptElement(*element))
-    return toSVGScriptElement(element);
+  if (auto* html_script = ToHTMLScriptElementOrNull(*element))
+    return html_script;
+  if (auto* svg_script = ToSVGScriptElementOrNull(*element))
+    return svg_script;
   return nullptr;
 }
 
diff --git a/third_party/WebKit/Source/core/dom/ScriptModuleResolverImplTest.cpp b/third_party/WebKit/Source/core/dom/ScriptModuleResolverImplTest.cpp
index 626bf6a..617b0a0 100644
--- a/third_party/WebKit/Source/core/dom/ScriptModuleResolverImplTest.cpp
+++ b/third_party/WebKit/Source/core/dom/ScriptModuleResolverImplTest.cpp
@@ -42,7 +42,7 @@
 
  private:
   // Implements Modulator:
-  ScriptState* GetScriptState() override { return script_state_.Get(); }
+  ScriptState* GetScriptState() override { return script_state_.get(); }
 
   ModuleScript* GetFetchedModuleScript(const KURL&) override;
 
@@ -50,8 +50,8 @@
     return ScriptModuleState::kInstantiated;
   }
   ScriptValue GetError(const ModuleScript* module_script) override {
-    ScriptState::Scope scope(script_state_.Get());
-    return ScriptValue(script_state_.Get(),
+    ScriptState::Scope scope(script_state_.get());
+    return ScriptValue(script_state_.get(),
                        module_script->CreateError(script_state_->GetIsolate()));
   }
 
diff --git a/third_party/WebKit/Source/core/dom/SecurityContext.cpp b/third_party/WebKit/Source/core/dom/SecurityContext.cpp
index 911e217a..20d695d 100644
--- a/third_party/WebKit/Source/core/dom/SecurityContext.cpp
+++ b/third_party/WebKit/Source/core/dom/SecurityContext.cpp
@@ -95,7 +95,7 @@
 
   DCHECK(!suborigin.GetName().IsEmpty());
   DCHECK(RuntimeEnabledFeatures::SuboriginsEnabled());
-  DCHECK(security_origin_.Get());
+  DCHECK(security_origin_.get());
   DCHECK(!security_origin_->HasSuborigin() ||
          security_origin_->GetSuborigin()->GetName() == suborigin.GetName());
   security_origin_->AddSuborigin(suborigin);
diff --git a/third_party/WebKit/Source/core/dom/SecurityContext.h b/third_party/WebKit/Source/core/dom/SecurityContext.h
index f52136f..4aa1aec5 100644
--- a/third_party/WebKit/Source/core/dom/SecurityContext.h
+++ b/third_party/WebKit/Source/core/dom/SecurityContext.h
@@ -56,7 +56,7 @@
 
   using InsecureNavigationsSet = HashSet<unsigned, WTF::AlreadyHashed>;
 
-  SecurityOrigin* GetSecurityOrigin() const { return security_origin_.Get(); }
+  SecurityOrigin* GetSecurityOrigin() const { return security_origin_.get(); }
   ContentSecurityPolicy* GetContentSecurityPolicy() const {
     return content_security_policy_.Get();
   }
diff --git a/third_party/WebKit/Source/core/dom/ShadowRoot.cpp b/third_party/WebKit/Source/core/dom/ShadowRoot.cpp
index e2b5f60..e2a1201 100644
--- a/third_party/WebKit/Source/core/dom/ShadowRoot.cpp
+++ b/third_party/WebKit/Source/core/dom/ShadowRoot.cpp
@@ -133,7 +133,7 @@
 }
 
 void ShadowRoot::innerHTML(StringOrTrustedHTML& result) const {
-  result.setString(InnerHTMLAsString());
+  result.SetString(InnerHTMLAsString());
 }
 
 void ShadowRoot::SetInnerHTMLFromString(const String& markup,
@@ -146,18 +146,18 @@
 
 void ShadowRoot::setInnerHTML(const StringOrTrustedHTML& stringOrHtml,
                               ExceptionState& exception_state) {
-  DCHECK(stringOrHtml.isString() ||
+  DCHECK(stringOrHtml.IsString() ||
          RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
 
-  if (stringOrHtml.isString() && GetDocument().RequireTrustedTypes()) {
+  if (stringOrHtml.IsString() && GetDocument().RequireTrustedTypes()) {
     exception_state.ThrowTypeError(
         "This document requires `TrustedHTML` assignment.");
     return;
   }
 
-  String html = stringOrHtml.isString()
-                    ? stringOrHtml.getAsString()
-                    : stringOrHtml.getAsTrustedHTML()->toString();
+  String html = stringOrHtml.IsString()
+                    ? stringOrHtml.GetAsString()
+                    : stringOrHtml.GetAsTrustedHTML()->toString();
 
   // TODO(mkwst): This is an ugly hack that will be resolved once `TreatNullAs`
   // is treated as an extended attribute on the `DOMString` type rather than
diff --git a/third_party/WebKit/Source/core/dom/ShadowRootRareDataV0.h b/third_party/WebKit/Source/core/dom/ShadowRootRareDataV0.h
index 9fb50546..483d0c4 100644
--- a/third_party/WebKit/Source/core/dom/ShadowRootRareDataV0.h
+++ b/third_party/WebKit/Source/core/dom/ShadowRootRareDataV0.h
@@ -104,9 +104,9 @@
 inline void ShadowRootRareDataV0::DidAddInsertionPoint(
     V0InsertionPoint* point) {
   DCHECK(point);
-  if (isHTMLShadowElement(*point))
+  if (IsHTMLShadowElement(*point))
     ++descendant_shadow_element_count_;
-  else if (isHTMLContentElement(*point))
+  else if (IsHTMLContentElement(*point))
     ++descendant_content_element_count_;
   else
     NOTREACHED();
@@ -115,10 +115,10 @@
 inline void ShadowRootRareDataV0::DidRemoveInsertionPoint(
     V0InsertionPoint* point) {
   DCHECK(point);
-  if (isHTMLShadowElement(*point)) {
+  if (IsHTMLShadowElement(*point)) {
     DCHECK_GT(descendant_shadow_element_count_, 0u);
     --descendant_shadow_element_count_;
-  } else if (isHTMLContentElement(*point)) {
+  } else if (IsHTMLContentElement(*point)) {
     DCHECK_GT(descendant_content_element_count_, 0u);
     --descendant_content_element_count_;
   } else {
diff --git a/third_party/WebKit/Source/core/dom/Text.cpp b/third_party/WebKit/Source/core/dom/Text.cpp
index 09b7afd..dcdc36ed 100644
--- a/third_party/WebKit/Source/core/dom/Text.cpp
+++ b/third_party/WebKit/Source/core/dom/Text.cpp
@@ -321,7 +321,7 @@
   Node* parent_or_shadow_host_node = text->ParentOrShadowHostNode();
   DCHECK(parent_or_shadow_host_node);
   return parent_or_shadow_host_node->IsSVGElement() &&
-         !isSVGForeignObjectElement(*parent_or_shadow_host_node);
+         !IsSVGForeignObjectElement(*parent_or_shadow_host_node);
 }
 
 LayoutText* Text::CreateTextLayoutObject(const ComputedStyle& style) {
diff --git a/third_party/WebKit/Source/core/dom/TreeOrderedMap.cpp b/third_party/WebKit/Source/core/dom/TreeOrderedMap.cpp
index 7cfe9f6..2920abb8f 100644
--- a/third_party/WebKit/Source/core/dom/TreeOrderedMap.cpp
+++ b/third_party/WebKit/Source/core/dom/TreeOrderedMap.cpp
@@ -66,13 +66,13 @@
 }
 
 inline bool KeyMatchesMapName(const AtomicString& key, const Element& element) {
-  return isHTMLMapElement(element) &&
+  return IsHTMLMapElement(element) &&
          toHTMLMapElement(element).GetName() == key;
 }
 
 inline bool KeyMatchesSlotName(const AtomicString& key,
                                const Element& element) {
-  return isHTMLSlotElement(element) &&
+  return IsHTMLSlotElement(element) &&
          toHTMLSlotElement(element).GetName() == key;
 }
 
diff --git a/third_party/WebKit/Source/core/dom/UserGestureIndicator.cpp b/third_party/WebKit/Source/core/dom/UserGestureIndicator.cpp
index 69d5940..a4d7b53 100644
--- a/third_party/WebKit/Source/core/dom/UserGestureIndicator.cpp
+++ b/third_party/WebKit/Source/core/dom/UserGestureIndicator.cpp
@@ -88,7 +88,7 @@
 
 void UserGestureIndicator::UpdateRootToken() {
   if (!root_token_) {
-    root_token_ = token_.Get();
+    root_token_ = token_.get();
   } else {
     RecordUserGestureMerge(*root_token_, *token_);
     token_->TransferGestureTo(root_token_);
diff --git a/third_party/WebKit/Source/core/dom/UserGestureIndicatorTest.cpp b/third_party/WebKit/Source/core/dom/UserGestureIndicatorTest.cpp
index 5e71bf8..471b2efa 100644
--- a/third_party/WebKit/Source/core/dom/UserGestureIndicatorTest.cpp
+++ b/third_party/WebKit/Source/core/dom/UserGestureIndicatorTest.cpp
@@ -148,7 +148,7 @@
     }
 
     {
-      UserGestureIndicator user_gesture_scope(token.Get());
+      UserGestureIndicator user_gesture_scope(token.get());
       AdvanceClock(0.75);
       EXPECT_TRUE(token->HasGestures());
       AdvanceClock(0.75);
diff --git a/third_party/WebKit/Source/core/dom/V0InsertionPoint.cpp b/third_party/WebKit/Source/core/dom/V0InsertionPoint.cpp
index e21c32e..f7b2c2e 100644
--- a/third_party/WebKit/Source/core/dom/V0InsertionPoint.cpp
+++ b/third_party/WebKit/Source/core/dom/V0InsertionPoint.cpp
@@ -171,25 +171,25 @@
     return false;
   ShadowRoot* shadow_root = ContainingShadowRoot();
   DCHECK(shadow_root);
-  if (!isHTMLShadowElement(*this) ||
+  if (!IsHTMLShadowElement(*this) ||
       shadow_root->DescendantShadowElementCount() <= 1)
     return true;
 
   // Slow path only when there are more than one shadow elements in a shadow
   // tree. That should be a rare case.
   for (const auto& point : shadow_root->DescendantInsertionPoints()) {
-    if (isHTMLShadowElement(*point))
+    if (IsHTMLShadowElement(*point))
       return point == this;
   }
   return true;
 }
 
 bool V0InsertionPoint::IsShadowInsertionPoint() const {
-  return isHTMLShadowElement(*this) && IsActive();
+  return IsHTMLShadowElement(*this) && IsActive();
 }
 
 bool V0InsertionPoint::IsContentInsertionPoint() const {
-  return isHTMLContentElement(*this) && IsActive();
+  return IsHTMLContentElement(*this) && IsActive();
 }
 
 StaticNodeList* V0InsertionPoint::getDistributedNodes() {
diff --git a/third_party/WebKit/Source/core/dom/VisitedLinkState.cpp b/third_party/WebKit/Source/core/dom/VisitedLinkState.cpp
index 6f1cd74..7aebc92 100644
--- a/third_party/WebKit/Source/core/dom/VisitedLinkState.cpp
+++ b/third_party/WebKit/Source/core/dom/VisitedLinkState.cpp
@@ -52,8 +52,8 @@
     const Element& element,
     const AtomicString& attribute = AtomicString()) {
   DCHECK(attribute.IsNull() || LinkAttribute(element) == attribute);
-  if (isHTMLAnchorElement(element))
-    return toHTMLAnchorElement(element).VisitedLinkHash();
+  if (auto* anchor = ToHTMLAnchorElementOrNull(element))
+    return anchor->VisitedLinkHash();
   return VisitedLinkHash(
       element.GetDocument().BaseURL(),
       attribute.IsNull() ? LinkAttribute(element) : attribute);
@@ -67,7 +67,7 @@
     bool invalidate_visited_link_hashes) {
   for (Node& node : NodeTraversal::StartsAt(root_node)) {
     if (node.IsLink()) {
-      if (invalidate_visited_link_hashes && isHTMLAnchorElement(node))
+      if (invalidate_visited_link_hashes && IsHTMLAnchorElement(node))
         toHTMLAnchorElement(node).InvalidateCachedVisitedLinkHash();
       ToElement(node).PseudoStateChanged(CSSSelector::kPseudoLink);
       ToElement(node).PseudoStateChanged(CSSSelector::kPseudoVisited);
diff --git a/third_party/WebKit/Source/core/dom/events/EventDispatcher.cpp b/third_party/WebKit/Source/core/dom/events/EventDispatcher.cpp
index 4e8e65d..2820cf1 100644
--- a/third_party/WebKit/Source/core/dom/events/EventDispatcher.cpp
+++ b/third_party/WebKit/Source/core/dom/events/EventDispatcher.cpp
@@ -306,7 +306,7 @@
   // TODO(dtapuska): Change this to a target SDK quirk crbug.com/643705
   if (!is_trusted_or_click && event_->IsMouseEvent() &&
       event_->type() == EventTypeNames::mousedown &&
-      isHTMLSelectElement(*node_)) {
+      IsHTMLSelectElement(*node_)) {
     if (Settings* settings = node_->GetDocument().GetSettings()) {
       is_trusted_or_click = settings->GetWideViewportQuirkEnabled();
     }
@@ -342,7 +342,7 @@
   // events to open select boxes.
   if (!event_->isTrusted() && event_->IsMouseEvent() &&
       event_->type() == EventTypeNames::mousedown &&
-      isHTMLSelectElement(*node_)) {
+      IsHTMLSelectElement(*node_)) {
     UseCounter::Count(node_->GetDocument(),
                       WebFeature::kUntrustedMouseDownEventDispatchedToSelect);
   }
diff --git a/third_party/WebKit/Source/core/dom/events/EventTarget.cpp b/third_party/WebKit/Source/core/dom/events/EventTarget.cpp
index 06c298e..392955a 100644
--- a/third_party/WebKit/Source/core/dom/events/EventTarget.cpp
+++ b/third_party/WebKit/Source/core/dom/events/EventTarget.cpp
@@ -313,11 +313,11 @@
     const AtomicString& event_type,
     EventListener* listener,
     const AddEventListenerOptionsOrBoolean& options_union) {
-  if (options_union.isBoolean())
-    return addEventListener(event_type, listener, options_union.getAsBoolean());
-  if (options_union.isAddEventListenerOptions()) {
+  if (options_union.IsBoolean())
+    return addEventListener(event_type, listener, options_union.GetAsBoolean());
+  if (options_union.IsAddEventListenerOptions()) {
     AddEventListenerOptionsResolved options =
-        options_union.getAsAddEventListenerOptions();
+        options_union.GetAsAddEventListenerOptions();
     return addEventListener(event_type, listener, options);
   }
   return addEventListener(event_type, listener);
@@ -396,11 +396,12 @@
     const AtomicString& event_type,
     const EventListener* listener,
     const EventListenerOptionsOrBoolean& options_union) {
-  if (options_union.isBoolean())
+  if (options_union.IsBoolean()) {
     return removeEventListener(event_type, listener,
-                               options_union.getAsBoolean());
-  if (options_union.isEventListenerOptions()) {
-    EventListenerOptions options = options_union.getAsEventListenerOptions();
+                               options_union.GetAsBoolean());
+  }
+  if (options_union.IsEventListenerOptions()) {
+    EventListenerOptions options = options_union.GetAsEventListenerOptions();
     return removeEventListener(event_type, listener, options);
   }
   return removeEventListener(event_type, listener);
diff --git a/third_party/WebKit/Source/core/editing/EditingStyle.cpp b/third_party/WebKit/Source/core/editing/EditingStyle.cpp
index a640d095..42cdcd12 100644
--- a/third_party/WebKit/Source/core/editing/EditingStyle.cpp
+++ b/third_party/WebKit/Source/core/editing/EditingStyle.cpp
@@ -1059,7 +1059,7 @@
     const HTMLElement* element) {
   DCHECK(element);
   bool element_is_span_or_element_equivalent = false;
-  if (isHTMLSpanElement(*element)) {
+  if (IsHTMLSpanElement(*element)) {
     element_is_span_or_element_equivalent = true;
   } else {
     const HeapVector<Member<HTMLElementEquivalent>>& html_element_equivalents =
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
index 32c7041..15c28e8 100644
--- a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
+++ b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
@@ -343,8 +343,8 @@
 // TODO(editing-dev): We should make |SelectionAdjuster| to use this funciton
 // instead of |isSelectionBondary()|.
 bool IsUserSelectContain(const Node& node) {
-  return isHTMLTextAreaElement(node) || isHTMLInputElement(node) ||
-         isHTMLSelectElement(node);
+  return IsHTMLTextAreaElement(node) || IsHTMLInputElement(node) ||
+         IsHTMLSelectElement(node);
 }
 
 enum EditableLevel { kEditable, kRichlyEditable };
@@ -430,14 +430,14 @@
   if (!highest_root)
     return 0;
 
-  if (isHTMLBodyElement(*highest_root))
+  if (IsHTMLBodyElement(*highest_root))
     return highest_root;
 
   ContainerNode* node = highest_root->parentNode();
   while (node) {
     if (has_editable_style(*node))
       highest_root = node;
-    if (isHTMLBodyElement(*node))
+    if (IsHTMLBodyElement(*node))
       break;
     node = node->parentNode();
   }
@@ -998,7 +998,7 @@
     return const_cast<Element*>(&ToElement(node));
 
   for (Node& runner : NodeTraversal::AncestorsOf(node)) {
-    if (IsBlockFlowElement(runner) || isHTMLBodyElement(runner))
+    if (IsBlockFlowElement(runner) || IsHTMLBodyElement(runner))
       return ToElement(&runner);
   }
   return nullptr;
@@ -1238,8 +1238,8 @@
 }
 
 bool IsHTMLListElement(Node* n) {
-  return (n && (isHTMLUListElement(*n) || isHTMLOListElement(*n) ||
-                isHTMLDListElement(*n)));
+  return (n && (IsHTMLUListElement(*n) || IsHTMLOListElement(*n) ||
+                IsHTMLDListElement(*n)));
 }
 
 bool IsListItem(const Node* n) {
@@ -1400,7 +1400,7 @@
   ContainerNode* root = HighestEditableRoot(FirstPositionInOrBeforeNode(node));
 
   for (Node& runner : NodeTraversal::AncestorsOf(*node)) {
-    if (isHTMLUListElement(runner) || isHTMLOListElement(runner))
+    if (IsHTMLUListElement(runner) || IsHTMLOListElement(runner))
       return ToHTMLElement(&runner);
     if (runner == root)
       return 0;
@@ -1420,7 +1420,7 @@
   // FIXME: This function is inappropriately named if it starts with node
   // instead of node->parentNode()
   for (Node* n = node; n && n->parentNode(); n = n->parentNode()) {
-    if (isHTMLLIElement(*n) ||
+    if (IsHTMLLIElement(*n) ||
         (IsHTMLListElement(n->parentNode()) && n != root))
       return n;
     if (n == root || IsTableCell(n))
@@ -1496,7 +1496,7 @@
 }
 
 bool IsDisplayInsideTable(const Node* node) {
-  return node && node->GetLayoutObject() && isHTMLTableElement(node);
+  return node && node->GetLayoutObject() && IsHTMLTableElement(node);
 }
 
 bool IsTableCell(const Node* node) {
@@ -1557,7 +1557,7 @@
 }
 
 bool IsTabHTMLSpanElement(const Node* node) {
-  if (!isHTMLSpanElement(node) || !node->firstChild())
+  if (!IsHTMLSpanElement(node) || !node->firstChild())
     return false;
   if (node->firstChild()->IsCharacterDataNode() &&
       ToCharacterData(node->firstChild())->data().Contains('\t'))
@@ -1654,7 +1654,7 @@
   if (position.IsNull())
     return Position();
 
-  if (isHTMLBRElement(*MostBackwardCaretPosition(position).AnchorNode()))
+  if (IsHTMLBRElement(*MostBackwardCaretPosition(position).AnchorNode()))
     return Position();
 
   const Position& prev = PreviousCharacterPosition(position, affinity);
@@ -1796,7 +1796,7 @@
   if (position.IsNull())
     return false;
 
-  if (isHTMLBRElement(*position.AnchorNode()) &&
+  if (IsHTMLBRElement(*position.AnchorNode()) &&
       position.AtFirstEditingPositionForNode())
     return true;
 
@@ -2038,7 +2038,7 @@
 
 bool IsInPasswordField(const Position& position) {
   TextControlElement* text_control = EnclosingTextControl(position);
-  return isHTMLInputElement(text_control) &&
+  return IsHTMLInputElement(text_control) &&
          toHTMLInputElement(text_control)->type() == InputTypeNames::password;
 }
 
diff --git a/third_party/WebKit/Source/core/editing/Editor.cpp b/third_party/WebKit/Source/core/editing/Editor.cpp
index 5829198a..e398947 100644
--- a/third_party/WebKit/Source/core/editing/Editor.cpp
+++ b/third_party/WebKit/Source/core/editing/Editor.cpp
@@ -144,12 +144,11 @@
 }
 
 bool IsInPasswordFieldWithUnrevealedPassword(const Position& position) {
-  TextControlElement* text_control = EnclosingTextControl(position);
-  if (!isHTMLInputElement(text_control))
-    return false;
-  HTMLInputElement* input = toHTMLInputElement(text_control);
-  return (input->type() == InputTypeNames::password) &&
-         !input->ShouldRevealPassword();
+  if (auto* input = ToHTMLInputElementOrNull(EnclosingTextControl(position))) {
+    return (input->type() == InputTypeNames::password) &&
+           !input->ShouldRevealPassword();
+  }
+  return false;
 }
 
 EphemeralRange ComputeRangeForTranspose(LocalFrame& frame) {
@@ -348,10 +347,7 @@
   if (!body)
     return 0;
 
-  Node* node = body->firstChild();
-  if (!isHTMLImageElement(node))
-    return 0;
-  return toHTMLImageElement(node);
+  return ToHTMLImageElementOrNull(body->firstChild());
 }
 
 bool Editor::CanCopy() const {
@@ -603,25 +599,25 @@
   DCHECK(node);
 
   RefPtr<Image> image = ImageFromNode(*node);
-  if (!image.Get())
+  if (!image.get())
     return;
 
   // FIXME: This should probably be reconciled with
   // HitTestResult::absoluteImageURL.
   AtomicString url_string;
-  if (isHTMLImageElement(*node) || isHTMLInputElement(*node))
+  if (IsHTMLImageElement(*node) || IsHTMLInputElement(*node))
     url_string = ToHTMLElement(node)->getAttribute(srcAttr);
-  else if (isSVGImageElement(*node))
+  else if (IsSVGImageElement(*node))
     url_string = ToSVGElement(node)->ImageSourceURL();
-  else if (isHTMLEmbedElement(*node) || isHTMLObjectElement(*node) ||
-           isHTMLCanvasElement(*node))
+  else if (IsHTMLEmbedElement(*node) || IsHTMLObjectElement(*node) ||
+           IsHTMLCanvasElement(*node))
     url_string = ToHTMLElement(node)->ImageSourceURL();
   KURL url = url_string.IsEmpty()
                  ? KURL()
                  : node->GetDocument().CompleteURL(
                        StripLeadingAndTrailingHTMLSpaces(url_string));
 
-  pasteboard->WriteImage(image.Get(), url, title);
+  pasteboard->WriteImage(image.get(), url, title);
 }
 
 // Returns whether caller should continue with "the default processing", which
@@ -1294,23 +1290,23 @@
     return;
   }
 
-  if (isHTMLInputElement(node)) {
+  if (IsHTMLInputElement(node)) {
     UseCounter::Count(execution_context, feature_on_input);
     return;
   }
 
-  if (isHTMLTextAreaElement(node)) {
+  if (IsHTMLTextAreaElement(node)) {
     UseCounter::Count(execution_context, feature_on_text_area);
     return;
   }
 
   TextControlElement* control = EnclosingTextControl(node);
-  if (isHTMLInputElement(control)) {
+  if (IsHTMLInputElement(control)) {
     UseCounter::Count(execution_context, feature_on_input);
     return;
   }
 
-  if (isHTMLTextAreaElement(control)) {
+  if (IsHTMLTextAreaElement(control)) {
     UseCounter::Count(execution_context, feature_on_text_area);
     return;
   }
@@ -1785,13 +1781,13 @@
   Element* existing_body = nullptr;
   Element* current_root = document.documentElement();
   if (current_root) {
-    if (isHTMLHtmlElement(current_root))
+    if (IsHTMLHtmlElement(current_root))
       return;
-    if (isHTMLHeadElement(current_root))
+    if (IsHTMLHeadElement(current_root))
       existing_head = current_root;
-    else if (isHTMLBodyElement(current_root))
+    else if (IsHTMLBodyElement(current_root))
       existing_body = current_root;
-    else if (isHTMLFrameSetElement(current_root))
+    else if (IsHTMLFrameSetElement(current_root))
       existing_body = current_root;
   }
   // We ensure only "the root is <html>."
diff --git a/third_party/WebKit/Source/core/editing/EditorTest.cpp b/third_party/WebKit/Source/core/editing/EditorTest.cpp
index 4406471..3475d11745 100644
--- a/third_party/WebKit/Source/core/editing/EditorTest.cpp
+++ b/third_party/WebKit/Source/core/editing/EditorTest.cpp
@@ -31,7 +31,7 @@
   GetDocument().AppendChild(body);
   Editor::TidyUpHTMLStructure(GetDocument());
 
-  EXPECT_TRUE(isHTMLHtmlElement(GetDocument().documentElement()));
+  EXPECT_TRUE(IsHTMLHtmlElement(GetDocument().documentElement()));
   EXPECT_EQ(body, GetDocument().body());
   EXPECT_EQ(GetDocument().documentElement(), body->parentNode());
 }
@@ -43,8 +43,8 @@
   GetDocument().AppendChild(div);
   Editor::TidyUpHTMLStructure(GetDocument());
 
-  EXPECT_TRUE(isHTMLHtmlElement(GetDocument().documentElement()));
-  EXPECT_TRUE(isHTMLBodyElement(GetDocument().body()));
+  EXPECT_TRUE(IsHTMLHtmlElement(GetDocument().documentElement()));
+  EXPECT_TRUE(IsHTMLBodyElement(GetDocument().body()));
   EXPECT_EQ(GetDocument().body(), div->parentNode());
 }
 
@@ -55,8 +55,8 @@
   GetDocument().AppendChild(head);
   Editor::TidyUpHTMLStructure(GetDocument());
 
-  EXPECT_TRUE(isHTMLHtmlElement(GetDocument().documentElement()));
-  EXPECT_TRUE(isHTMLBodyElement(GetDocument().body()));
+  EXPECT_TRUE(IsHTMLHtmlElement(GetDocument().documentElement()));
+  EXPECT_TRUE(IsHTMLBodyElement(GetDocument().body()));
   EXPECT_EQ(GetDocument().documentElement(), head->parentNode());
 }
 
diff --git a/third_party/WebKit/Source/core/editing/FrameCaretTest.cpp b/third_party/WebKit/Source/core/editing/FrameCaretTest.cpp
index 08ef38aa..ba1945f 100644
--- a/third_party/WebKit/Source/core/editing/FrameCaretTest.cpp
+++ b/third_party/WebKit/Source/core/editing/FrameCaretTest.cpp
@@ -41,7 +41,7 @@
   RefPtr<scheduler::FakeWebTaskRunner> task_runner =
       WTF::AdoptRef(new scheduler::FakeWebTaskRunner);
   task_runner->SetTime(0);
-  caret.RecreateCaretBlinkTimerForTesting(task_runner.Get());
+  caret.RecreateCaretBlinkTimerForTesting(task_runner.get());
   const double kInterval = 10;
   LayoutTheme::GetTheme().SetCaretBlinkInterval(kInterval);
   GetDocument().GetPage()->GetFocusController().SetActive(true);
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.cpp b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
index 5d2cd63..02153cc 100644
--- a/third_party/WebKit/Source/core/editing/FrameSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
@@ -637,9 +637,8 @@
 }
 
 void FrameSelection::SelectAll(SetSelectionBy set_selection_by) {
-  if (isHTMLSelectElement(GetDocument().FocusedElement())) {
-    HTMLSelectElement* select_element =
-        toHTMLSelectElement(GetDocument().FocusedElement());
+  if (auto* select_element =
+          ToHTMLSelectElementOrNull(GetDocument().FocusedElement())) {
     if (select_element->CanSelectAll()) {
       select_element->SelectAll();
       return;
diff --git a/third_party/WebKit/Source/core/editing/InputMethodController.cpp b/third_party/WebKit/Source/core/editing/InputMethodController.cpp
index 2a73167c..c19e90d5 100644
--- a/third_party/WebKit/Source/core/editing/InputMethodController.cpp
+++ b/third_party/WebKit/Source/core/editing/InputMethodController.cpp
@@ -184,9 +184,9 @@
     return AtomicString();
 
   bool query_attribute = false;
-  if (isHTMLInputElement(*element)) {
-    query_attribute = toHTMLInputElement(*element).SupportsInputModeAttribute();
-  } else if (isHTMLTextAreaElement(*element)) {
+  if (auto* input = ToHTMLInputElementOrNull(*element)) {
+    query_attribute = input->SupportsInputModeAttribute();
+  } else if (IsHTMLTextAreaElement(*element)) {
     query_attribute = true;
   } else {
     element->GetDocument().UpdateStyleAndLayoutTree();
@@ -372,10 +372,10 @@
   const Element* element = EnclosingTextControl(position);
   if (!element)
     return false;
-  if (isHTMLInputElement(element))
-    return toHTMLInputElement(element)->TooLong();
-  if (isHTMLTextAreaElement(element))
-    return toHTMLTextAreaElement(element)->TooLong();
+  if (auto* input = ToHTMLInputElementOrNull(element))
+    return input->TooLong();
+  if (auto* textarea = ToHTMLTextAreaElementOrNull(element))
+    return textarea->TooLong();
   return false;
 }
 
@@ -1298,11 +1298,10 @@
   if (!element)
     return kWebTextInputTypeNone;
 
-  if (isHTMLInputElement(*element)) {
-    HTMLInputElement& input = toHTMLInputElement(*element);
-    const AtomicString& type = input.type();
+  if (auto* input = ToHTMLInputElementOrNull(*element)) {
+    const AtomicString& type = input->type();
 
-    if (input.IsDisabledOrReadOnly())
+    if (input->IsDisabledOrReadOnly())
       return kWebTextInputTypeNone;
 
     if (type == InputTypeNames::password)
@@ -1323,8 +1322,8 @@
     return kWebTextInputTypeNone;
   }
 
-  if (isHTMLTextAreaElement(*element)) {
-    if (toHTMLTextAreaElement(*element).IsDisabledOrReadOnly())
+  if (auto* textarea = ToHTMLTextAreaElementOrNull(*element)) {
+    if (textarea->IsDisabledOrReadOnly())
       return kWebTextInputTypeNone;
     return kWebTextInputTypeTextArea;
   }
diff --git a/third_party/WebKit/Source/core/editing/RenderedPosition.cpp b/third_party/WebKit/Source/core/editing/RenderedPosition.cpp
index fc4dc4f0..d479b0f 100644
--- a/third_party/WebKit/Source/core/editing/RenderedPosition.cpp
+++ b/third_party/WebKit/Source/core/editing/RenderedPosition.cpp
@@ -362,7 +362,7 @@
   TextControlElement* text_control = EnclosingTextControl(node);
   if (!text_control)
     return true;
-  if (!isHTMLInputElement(text_control))
+  if (!IsHTMLInputElement(text_control))
     return true;
 
   LayoutObject* layout_object = text_control->GetLayoutObject();
diff --git a/third_party/WebKit/Source/core/editing/SelectionAdjuster.cpp b/third_party/WebKit/Source/core/editing/SelectionAdjuster.cpp
index fcd5b0267..2155590 100644
--- a/third_party/WebKit/Source/core/editing/SelectionAdjuster.cpp
+++ b/third_party/WebKit/Source/core/editing/SelectionAdjuster.cpp
@@ -53,8 +53,8 @@
 }
 
 bool IsSelectionBoundary(const Node& node) {
-  return isHTMLTextAreaElement(node) || isHTMLInputElement(node) ||
-         isHTMLSelectElement(node);
+  return IsHTMLTextAreaElement(node) || IsHTMLInputElement(node) ||
+         IsHTMLSelectElement(node);
 }
 
 Node* EnclosingShadowHostForStart(const PositionInFlatTree& position) {
diff --git a/third_party/WebKit/Source/core/editing/SelectionController.cpp b/third_party/WebKit/Source/core/editing/SelectionController.cpp
index fe4dc0b..44ee5bf 100644
--- a/third_party/WebKit/Source/core/editing/SelectionController.cpp
+++ b/third_party/WebKit/Source/core/editing/SelectionController.cpp
@@ -561,6 +561,12 @@
                             TextGranularity::kWord)
                       : VisibleSelectionInFlatTree();
 
+  // TODO(editing-dev): Fix CreateVisibleSelectionWithGranularity() to not
+  // return invalid ranges. Until we do that, we need this check here to avoid a
+  // renderer crash when we call PlainText() below (see crbug.com/735774).
+  if (new_selection.IsNone() || new_selection.Start() > new_selection.End())
+    return false;
+
   HandleVisibility visibility = HandleVisibility::kNotVisible;
   if (select_input_event_type == SelectInputEventType::kTouch) {
     // If node doesn't have text except space, tab or line break, do not
diff --git a/third_party/WebKit/Source/core/editing/SelectionTemplate.h b/third_party/WebKit/Source/core/editing/SelectionTemplate.h
index 7a18a77..ee138bc 100644
--- a/third_party/WebKit/Source/core/editing/SelectionTemplate.h
+++ b/third_party/WebKit/Source/core/editing/SelectionTemplate.h
@@ -160,8 +160,10 @@
 using SelectionInDOMTree = SelectionTemplate<EditingStrategy>;
 using SelectionInFlatTree = SelectionTemplate<EditingInFlatTreeStrategy>;
 
-SelectionInDOMTree ConvertToSelectionInDOMTree(const SelectionInFlatTree&);
-SelectionInFlatTree ConvertToSelectionInFlatTree(const SelectionInDOMTree&);
+CORE_EXPORT SelectionInDOMTree
+ConvertToSelectionInDOMTree(const SelectionInFlatTree&);
+CORE_EXPORT SelectionInFlatTree
+ConvertToSelectionInFlatTree(const SelectionInDOMTree&);
 
 CORE_EXPORT std::ostream& operator<<(std::ostream&, const SelectionInDOMTree&);
 CORE_EXPORT std::ostream& operator<<(std::ostream&, const SelectionInFlatTree&);
diff --git a/third_party/WebKit/Source/core/editing/TextFinder.cpp b/third_party/WebKit/Source/core/editing/TextFinder.cpp
index 029c6a6..f5873ee9 100644
--- a/third_party/WebKit/Source/core/editing/TextFinder.cpp
+++ b/third_party/WebKit/Source/core/editing/TextFinder.cpp
@@ -256,7 +256,7 @@
   Node* node = active_match->FirstNode();
   if (node && node->IsInShadowTree()) {
     if (Node* host = node->OwnerShadowHost()) {
-      if (isHTMLInputElement(*host) || isHTMLTextAreaElement(*host))
+      if (IsHTMLInputElement(*host) || IsHTMLTextAreaElement(*host))
         node = host;
     }
   }
diff --git a/third_party/WebKit/Source/core/editing/VisibleSelection.cpp b/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
index 2f753de..16d2b14 100644
--- a/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
@@ -625,7 +625,7 @@
   while (node) {
     if (HasEditableStyle(*node))
       return RootEditableElement(*node);
-    if (isHTMLBodyElement(*node))
+    if (IsHTMLBodyElement(*node))
       break;
     node = node->parentNode();
   }
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
index da4d27e..ef62ae7 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
@@ -1205,12 +1205,12 @@
     return true;
 
   // Don't include inline tables.
-  if (isHTMLTableElement(*node))
+  if (IsHTMLTableElement(*node))
     return false;
 
   // A Marquee elements are moving so we should assume their ends are always
   // visibily distinct.
-  if (isHTMLMarqueeElement(*node))
+  if (IsHTMLMarqueeElement(*node))
     return true;
 
   // There is a VisiblePosition inside an empty inline-block container.
@@ -1490,7 +1490,7 @@
 
     // stop before going above the body, up into the head
     // return the last visible streamer position
-    if (isHTMLBodyElement(*current_node) && current_pos.AtEndOfNode())
+    if (IsHTMLBodyElement(*current_node) && current_pos.AtEndOfNode())
       break;
 
     // Do not move to a visually distinct position.
@@ -1671,7 +1671,7 @@
   if (layout_object->IsLayoutBlockFlow() || layout_object->IsFlexibleBox() ||
       layout_object->IsLayoutGrid()) {
     if (ToLayoutBlock(layout_object)->LogicalHeight() ||
-        isHTMLBodyElement(*anchor_node)) {
+        IsHTMLBodyElement(*anchor_node)) {
       if (!HasRenderedNonAnonymousDescendantsWithHeight(layout_object))
         return position.AtFirstEditingPositionForNode();
       return HasEditableStyle(*anchor_node) && AtEditingBoundary(position);
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnitsLine.cpp b/third_party/WebKit/Source/core/editing/VisibleUnitsLine.cpp
index 7d33c33..9facc534 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnitsLine.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleUnitsLine.cpp
@@ -301,7 +301,7 @@
       break;
 
     const Position& candidate =
-        isHTMLBRElement(*runner)
+        IsHTMLBRElement(*runner)
             ? Position::BeforeNode(*runner)
             : Position::EditingPositionOf(runner, CaretMaxOffset(runner));
     if (IsVisuallyEquivalentCandidate(candidate))
@@ -428,7 +428,7 @@
     end_node = end_box->GetLineLayoutItem().NonPseudoNode();
   }
 
-  if (isHTMLBRElement(*end_node)) {
+  if (IsHTMLBRElement(*end_node)) {
     return CreateVisiblePosition(
         PositionTemplate<Strategy>::BeforeNode(*end_node),
         VP_UPSTREAM_IF_POSSIBLE);
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnitsWord.cpp b/third_party/WebKit/Source/core/editing/VisibleUnitsWord.cpp
index 15ccf9a..d3759ea 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnitsWord.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleUnitsWord.cpp
@@ -32,14 +32,8 @@
 
 #include "core/editing/EditingUtilities.h"
 #include "core/editing/VisiblePosition.h"
-#include "core/editing/iterators/BackwardsCharacterIterator.h"
-#include "core/editing/iterators/BackwardsTextBuffer.h"
-#include "core/editing/iterators/CharacterIterator.h"
-#include "core/editing/iterators/ForwardsTextBuffer.h"
-#include "core/editing/iterators/SimplifiedBackwardsTextIterator.h"
 #include "platform/instrumentation/tracing/TraceEvent.h"
 #include "platform/text/TextBoundaries.h"
-#include "platform/text/TextBreakIterator.h"
 
 namespace blink {
 
diff --git a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
index 2e07d7fb..a39389441 100644
--- a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
@@ -78,28 +78,30 @@
 }
 
 bool IsStyleSpanOrSpanWithOnlyStyleAttribute(const Element* element) {
-  if (!isHTMLSpanElement(element))
-    return false;
-  return HasNoAttributeOrOnlyStyleAttribute(toHTMLSpanElement(element),
-                                            kAllowNonEmptyStyleAttribute);
+  if (auto* span = ToHTMLSpanElementOrNull(element)) {
+    return HasNoAttributeOrOnlyStyleAttribute(span,
+                                              kAllowNonEmptyStyleAttribute);
+  }
+  return false;
 }
 
 static inline bool IsSpanWithoutAttributesOrUnstyledStyleSpan(
     const Node* node) {
-  if (!isHTMLSpanElement(node))
-    return false;
-  return HasNoAttributeOrOnlyStyleAttribute(toHTMLSpanElement(node),
-                                            kStyleAttributeShouldBeEmpty);
+  if (auto* span = ToHTMLSpanElementOrNull(node)) {
+    return HasNoAttributeOrOnlyStyleAttribute(span,
+                                              kStyleAttributeShouldBeEmpty);
+  }
+  return false;
 }
 
 bool IsEmptyFontTag(
     const Element* element,
     ShouldStyleAttributeBeEmpty should_style_attribute_be_empty) {
-  if (!isHTMLFontElement(element))
-    return false;
-
-  return HasNoAttributeOrOnlyStyleAttribute(toHTMLFontElement(element),
-                                            should_style_attribute_be_empty);
+  if (auto* font = ToHTMLFontElementOrNull(element)) {
+    return HasNoAttributeOrOnlyStyleAttribute(font,
+                                              should_style_attribute_be_empty);
+  }
+  return false;
 }
 
 static bool OffsetIsBeforeLastNodeOffset(int offset, Node* anchor_node) {
@@ -880,7 +882,7 @@
 
   // FIXME: Callers should perform this operation on a Range that includes the
   // br if they want style applied to the empty line.
-  if (start == end && isHTMLBRElement(*start.AnchorNode()))
+  if (start == end && IsHTMLBRElement(*start.AnchorNode()))
     past_end_node = NodeTraversal::Next(*start.AnchorNode());
 
   // Start from the highest fully selected ancestor so that we can modify the
@@ -1004,7 +1006,7 @@
     Node* sibling = node->nextSibling();
     while (sibling && sibling != past_end_node &&
            !sibling->contains(past_end_node) &&
-           (!IsEnclosingBlock(sibling) || isHTMLBRElement(*sibling)) &&
+           (!IsEnclosingBlock(sibling) || IsHTMLBRElement(*sibling)) &&
            !ContainsNonEditableRegion(*sibling)) {
       run_end = sibling;
       sibling = run_end->nextSibling();
@@ -1295,7 +1297,7 @@
   node->GetDocument().UpdateStyleAndLayoutTree();
 
   if (!style || style->IsEmpty() || !node->GetLayoutObject() ||
-      isHTMLIFrameElement(*node))
+      IsHTMLIFrameElement(*node))
     return;
 
   EditingStyle* new_inline_style = style;
@@ -1376,7 +1378,7 @@
           // Delete id attribute from the second element because the same id
           // cannot be used for more than one element
           element->removeAttribute(HTMLNames::idAttr);
-          if (isHTMLAnchorElement(element))
+          if (IsHTMLAnchorElement(element))
             element->removeAttribute(HTMLNames::nameAttr);
           SurroundNodeRangeWithElement(child, child, wrapper, editing_state);
           if (editing_state->IsAborted())
@@ -1706,7 +1708,7 @@
     end_node = end.AnchorNode()->parentNode();
   }
 
-  if (!end_node->IsElementNode() || isHTMLBRElement(*end_node))
+  if (!end_node->IsElementNode() || IsHTMLBRElement(*end_node))
     return false;
 
   Node* next_sibling = end_node->nextSibling();
@@ -1868,12 +1870,12 @@
   HTMLElement* style_container = nullptr;
   for (Node* container = start_node; container && start_node == end_node;
        container = container->firstChild()) {
-    if (isHTMLFontElement(*container))
-      font_container = toHTMLFontElement(container);
-    bool style_container_is_not_span = !isHTMLSpanElement(style_container);
+    if (auto* font = ToHTMLFontElementOrNull(container))
+      font_container = font;
+    bool style_container_is_not_span = !IsHTMLSpanElement(style_container);
     if (container->IsHTMLElement()) {
       HTMLElement* container_element = ToHTMLElement(container);
-      if (isHTMLSpanElement(*container_element) ||
+      if (IsHTMLSpanElement(*container_element) ||
           (style_container_is_not_span && container_element->HasChildren()))
         style_container = ToHTMLElement(container);
     }
diff --git a/third_party/WebKit/Source/core/editing/commands/BreakBlockquoteCommand.cpp b/third_party/WebKit/Source/core/editing/commands/BreakBlockquoteCommand.cpp
index a03a1ec..c8b0a770 100644
--- a/third_party/WebKit/Source/core/editing/commands/BreakBlockquoteCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/BreakBlockquoteCommand.cpp
@@ -230,11 +230,11 @@
   for (size_t i = ancestors.size(); i != 0; --i) {
     Element* cloned_child = ancestors[i - 1]->CloneElementWithoutChildren();
     // Preserve list item numbering in cloned lists.
-    if (isHTMLOListElement(*cloned_child)) {
+    if (IsHTMLOListElement(*cloned_child)) {
       Node* list_child_node = i > 1 ? ancestors[i - 2].Get() : start_node;
       // The first child of the cloned list might not be a list item element,
       // find the first one so that we know where to start numbering.
-      while (list_child_node && !isHTMLLIElement(*list_child_node))
+      while (list_child_node && !IsHTMLLIElement(*list_child_node))
         list_child_node = list_child_node->nextSibling();
       if (IsListItem(list_child_node))
         SetNodeAttribute(
diff --git a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
index 4113417..e7d99275 100644
--- a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
@@ -274,7 +274,7 @@
 
 bool CompositeEditCommand::IsRemovableBlock(const Node* node) {
   DCHECK(node);
-  if (!isHTMLDivElement(*node))
+  if (!IsHTMLDivElement(*node))
     return false;
 
   const HTMLDivElement& element = toHTMLDivElement(*node);
@@ -983,7 +983,7 @@
 
   // We are certain that the position is at a line break, but it may be a br or
   // a preserved newline.
-  if (isHTMLBRElement(*p.AnchorNode())) {
+  if (IsHTMLBRElement(*p.AnchorNode())) {
     // Removing a BR element won't dispatch synchronous events.
     RemoveNode(p.AnchorNode(), ASSERT_NO_EDITING_ABORT);
     return;
@@ -1071,7 +1071,7 @@
   DCHECK(new_block);
 
   bool end_was_br =
-      isHTMLBRElement(*visible_paragraph_end.DeepEquivalent().AnchorNode());
+      IsHTMLBRElement(*visible_paragraph_end.DeepEquivalent().AnchorNode());
 
   // Inserting default paragraph element can change visible position. We
   // should update visible positions before use them.
@@ -1093,7 +1093,7 @@
   if (editing_state->IsAborted())
     return nullptr;
 
-  if (new_block->lastChild() && isHTMLBRElement(*new_block->lastChild()) &&
+  if (new_block->lastChild() && IsHTMLBRElement(*new_block->lastChild()) &&
       !end_was_br) {
     RemoveNode(new_block->lastChild(), editing_state);
     if (editing_state->IsAborted())
@@ -1246,7 +1246,7 @@
       return;
 
     // Normally deletion will leave a br as a placeholder.
-    if (isHTMLBRElement(*node)) {
+    if (IsHTMLBRElement(*node)) {
       RemoveNodeAndPruneAncestors(node, editing_state, destination_node);
 
       // If the selection to move was empty and in an empty block that
@@ -1620,14 +1620,14 @@
   // FIXME: Can't we do something better when the immediate parent wasn't a list
   // node?
   if (!list_node ||
-      (!isHTMLUListElement(*list_node) && !isHTMLOListElement(*list_node)) ||
+      (!IsHTMLUListElement(*list_node) && !IsHTMLOListElement(*list_node)) ||
       !HasEditableStyle(*list_node) ||
       list_node == RootEditableElement(*empty_list_item))
     return false;
 
   HTMLElement* new_block = nullptr;
   if (ContainerNode* block_enclosing_list = list_node->parentNode()) {
-    if (isHTMLLIElement(
+    if (IsHTMLLIElement(
             *block_enclosing_list)) {  // listNode is inside another list item
       if (VisiblePositionAfterNode(*block_enclosing_list).DeepEquivalent() ==
           VisiblePositionAfterNode(*list_node).DeepEquivalent()) {
@@ -1652,8 +1652,8 @@
       }
       // If listNode does NOT appear at the end of the outer list item, then
       // behave as if in a regular paragraph.
-    } else if (isHTMLOListElement(*block_enclosing_list) ||
-               isHTMLUListElement(*block_enclosing_list)) {
+    } else if (IsHTMLOListElement(*block_enclosing_list) ||
+               IsHTMLUListElement(*block_enclosing_list)) {
       new_block = HTMLLIElement::Create(GetDocument());
     }
   }
@@ -1777,12 +1777,12 @@
   Position caret_pos(MostForwardCaretPosition(caret.DeepEquivalent()));
   // A line break is either a br or a preserved newline.
   DCHECK(
-      isHTMLBRElement(caret_pos.AnchorNode()) ||
+      IsHTMLBRElement(caret_pos.AnchorNode()) ||
       (caret_pos.AnchorNode()->IsTextNode() &&
        caret_pos.AnchorNode()->GetLayoutObject()->Style()->PreserveNewline()))
       << caret_pos;
 
-  if (isHTMLBRElement(*caret_pos.AnchorNode())) {
+  if (IsHTMLBRElement(*caret_pos.AnchorNode())) {
     RemoveNodeAndPruneAncestors(caret_pos.AnchorNode(), editing_state);
     if (editing_state->IsAborted())
       return false;
diff --git a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
index 7c9265a..b359b8ef 100644
--- a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
@@ -57,7 +57,7 @@
 }
 
 static bool IsTableRowEmpty(Node* row) {
-  if (!isHTMLTableRowElement(row))
+  if (!IsHTMLTableRowElement(row))
     return false;
 
   row->GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();
@@ -137,9 +137,9 @@
   // For HRs, we'll get a position at (HR,1) when hitting delete from the
   // beginning of the previous line, or (HR,0) when forward deleting, but in
   // these cases, we want to delete it, so manually expand the selection
-  if (isHTMLHRElement(*start.AnchorNode()))
+  if (IsHTMLHRElement(*start.AnchorNode()))
     start = Position::BeforeNode(*start.AnchorNode());
-  else if (isHTMLHRElement(*end.AnchorNode()))
+  else if (IsHTMLHRElement(*end.AnchorNode()))
     end = Position::AfterNode(*end.AnchorNode());
 
   // FIXME: This is only used so that moveParagraphs can avoid the bugs in
@@ -254,9 +254,9 @@
   end_root_ = RootEditableElementOf(end);
 
   start_table_row_ =
-      toHTMLTableRowElement(EnclosingNodeOfType(start, &isHTMLTableRowElement));
+      toHTMLTableRowElement(EnclosingNodeOfType(start, &IsHTMLTableRowElement));
   end_table_row_ =
-      toHTMLTableRowElement(EnclosingNodeOfType(end, &isHTMLTableRowElement));
+      toHTMLTableRowElement(EnclosingNodeOfType(end, &IsHTMLTableRowElement));
 
   // Don't move content out of a table cell.
   // If the cell is non-editable, enclosingNodeOfType won't return it by
@@ -429,8 +429,8 @@
 
   // Check for special-case where the selection contains only a BR on a line by
   // itself after another BR.
-  bool upstream_start_is_br = isHTMLBRElement(*node_after_upstream_start);
-  bool downstream_start_is_br = isHTMLBRElement(*node_after_downstream_start);
+  bool upstream_start_is_br = IsHTMLBRElement(*node_after_upstream_start);
+  bool downstream_start_is_br = IsHTMLBRElement(*node_after_downstream_start);
   bool is_br_on_line_by_itself =
       upstream_start_is_br && downstream_start_is_br &&
       node_after_downstream_start == node_after_upstream_end;
@@ -582,7 +582,7 @@
   Node* node = range->FirstNode();
   while (node && node != range->PastLastNode()) {
     Node* next_node = NodeTraversal::Next(*node);
-    if (isHTMLStyleElement(*node) || isHTMLLinkElement(*node)) {
+    if (IsHTMLStyleElement(*node) || IsHTMLLinkElement(*node)) {
       next_node = NodeTraversal::NextSkippingChildren(*node);
       Element* element = RootEditableElement(*node);
       if (element) {
@@ -615,7 +615,7 @@
   // merge content in.
   if (start_node == start_block_.Get() && !start_offset &&
       CanHaveChildrenForEditing(start_node) &&
-      !isHTMLTableElement(*start_node)) {
+      !IsHTMLTableElement(*start_node)) {
     start_offset = 0;
     start_node = NodeTraversal::Next(*start_node);
     if (!start_node)
@@ -901,7 +901,7 @@
   if (!starts_at_empty_line_ && IsStartOfParagraph(merge_destination) &&
       AbsoluteCaretBoundsOf(start_of_paragraph_to_move).X() >
           AbsoluteCaretBoundsOf(merge_destination).X()) {
-    if (isHTMLBRElement(
+    if (IsHTMLBRElement(
             *MostForwardCaretPosition(merge_destination.DeepEquivalent())
                  .AnchorNode())) {
       RemoveNodeAndPruneAncestors(
diff --git a/third_party/WebKit/Source/core/editing/commands/FormatBlockCommand.cpp b/third_party/WebKit/Source/core/editing/commands/FormatBlockCommand.cpp
index 623e319d..92e626c 100644
--- a/third_party/WebKit/Source/core/editing/commands/FormatBlockCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/FormatBlockCommand.cpp
@@ -180,7 +180,7 @@
   for (Node& runner : NodeTraversal::InclusiveAncestorsOf(*start_node)) {
     if (!HasEditableStyle(runner))
       return last_block;
-    if (IsTableCell(&runner) || isHTMLBodyElement(&runner) ||
+    if (IsTableCell(&runner) || IsHTMLBodyElement(&runner) ||
         !runner.parentNode() || !HasEditableStyle(*runner.parentNode()) ||
         IsElementForFormatBlock(&runner))
       return &runner;
diff --git a/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp b/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp
index 656997f4..276c762f 100644
--- a/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp
@@ -53,7 +53,7 @@
   const HTMLElement& element = ToHTMLElement(*node);
   // TODO(yosin): We should check OL/UL element has "list-style-type" CSS
   // property to make sure they layout contents as list.
-  return isHTMLUListElement(element) || isHTMLOListElement(element) ||
+  return IsHTMLUListElement(element) || IsHTMLOListElement(element) ||
          element.HasTagName(blockquoteTag);
 }
 
@@ -79,7 +79,7 @@
   Element* selected_list_item = EnclosingBlock(last_node_in_selected_paragraph);
 
   // FIXME: we need to deal with the case where there is no li (malformed HTML)
-  if (!isHTMLLIElement(selected_list_item))
+  if (!IsHTMLLIElement(selected_list_item))
     return false;
 
   // FIXME: previousElementSibling does not ignore non-rendered content like
@@ -215,13 +215,13 @@
     return;
 
   // Use InsertListCommand to remove the selection from the list
-  if (isHTMLOListElement(*enclosing_element)) {
+  if (IsHTMLOListElement(*enclosing_element)) {
     ApplyCommandToComposite(InsertListCommand::Create(
                                 GetDocument(), InsertListCommand::kOrderedList),
                             editing_state);
     return;
   }
-  if (isHTMLUListElement(*enclosing_element)) {
+  if (IsHTMLUListElement(*enclosing_element)) {
     ApplyCommandToComposite(
         InsertListCommand::Create(GetDocument(),
                                   InsertListCommand::kUnorderedList),
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertLineBreakCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertLineBreakCommand.cpp
index f90a183..02ae8602 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertLineBreakCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/InsertLineBreakCommand.cpp
@@ -104,8 +104,8 @@
 
   if (IsEndOfParagraph(CreateVisiblePosition(caret.ToPositionWithAffinity())) &&
       !LineBreakExistsAtVisiblePosition(caret)) {
-    bool need_extra_line_break = !isHTMLHRElement(*pos.AnchorNode()) &&
-                                 !isHTMLTableElement(*pos.AnchorNode());
+    bool need_extra_line_break = !IsHTMLHRElement(*pos.AnchorNode()) &&
+                                 !IsHTMLTableElement(*pos.AnchorNode());
 
     InsertNodeAt(node_to_insert, pos, editing_state);
     if (editing_state->IsAborted())
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
index e5b5da8..560199a 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
@@ -471,7 +471,7 @@
   VisiblePosition start;
   VisiblePosition end;
   DCHECK(list_child_node);
-  if (isHTMLLIElement(*list_child_node)) {
+  if (IsHTMLLIElement(*list_child_node)) {
     start = VisiblePosition::FirstPositionInNode(*list_child_node);
     end = VisiblePosition::LastPositionInNode(*list_child_node);
     next_list_child = list_child_node->nextSibling();
@@ -636,13 +636,13 @@
   // | |-B
   // | +-C (insertion point)
   // |   |-D (*)
-  if (isHTMLSpanElement(insertion_pos.AnchorNode())) {
+  if (IsHTMLSpanElement(insertion_pos.AnchorNode())) {
     insertion_pos =
         Position::InParentBeforeNode(*insertion_pos.ComputeContainerNode());
   }
   // Also avoid the containing list item.
   Node* const list_child = EnclosingListChild(insertion_pos.AnchorNode());
-  if (isHTMLLIElement(list_child))
+  if (IsHTMLLIElement(list_child))
     insertion_pos = Position::InParentBeforeNode(*list_child);
 
   HTMLElement* list_element = CreateHTMLElement(GetDocument(), list_tag);
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
index 06c99fd..c201f59 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
@@ -55,7 +55,7 @@
   // We don't want to return a root node (if it happens to be a div, e.g., in a
   // document fragment) because there are no siblings for us to append to.
   while (!cur_block->nextSibling() &&
-         isHTMLDivElement(*cur_block->parentElement()) &&
+         IsHTMLDivElement(*cur_block->parentElement()) &&
          cur_block->parentElement()->parentElement()) {
     if (cur_block->parentElement()->hasAttributes())
       break;
@@ -215,14 +215,14 @@
       CreateVisiblePosition(insertion_position).DeepEquivalent();
   if (!start_block || !start_block->NonShadowBoundaryParentNode() ||
       IsTableCell(start_block) ||
-      isHTMLFormElement(*start_block)
+      IsHTMLFormElement(*start_block)
       // FIXME: If the node is hidden, we don't have a canonical position so we
       // will do the wrong thing for tables and <hr>.
       // https://bugs.webkit.org/show_bug.cgi?id=40342
       || (!canonical_pos.IsNull() &&
           IsDisplayInsideTable(canonical_pos.AnchorNode())) ||
       (!canonical_pos.IsNull() &&
-       isHTMLHRElement(*canonical_pos.AnchorNode()))) {
+       IsHTMLHRElement(*canonical_pos.AnchorNode()))) {
     ApplyCommandToComposite(InsertLineBreakCommand::Create(GetDocument()),
                             editing_state);
     return;
@@ -319,7 +319,7 @@
         // startBlock (e.g., when nesting within lists). However, for div nodes,
         // this can result in nested div tags that are hard to break out of.
         Element* sibling_element = start_block;
-        if (isHTMLDivElement(*block_to_insert))
+        if (IsHTMLDivElement(*block_to_insert))
           sibling_element = HighestVisuallyEquivalentDivBelowRoot(start_block);
         InsertNodeAfter(block_to_insert, sibling_element, editing_state);
       }
diff --git a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
index 0f75b96..20fd812 100644
--- a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
@@ -113,7 +113,7 @@
 static bool IsInterchangeHTMLBRElement(const Node* node) {
   DEFINE_STATIC_LOCAL(String, interchange_newline_class_string,
                       (AppleInterchangeNewline));
-  if (!isHTMLBRElement(node) ||
+  if (!IsHTMLBRElement(node) ||
       toHTMLBRElement(node)->getAttribute(classAttr) !=
           interchange_newline_class_string)
     return false;
@@ -479,7 +479,7 @@
   return !selection_start_was_start_of_paragraph &&
          !fragment_has_interchange_newline_at_start &&
          IsStartOfParagraph(start_of_inserted_content) &&
-         !isHTMLBRElement(
+         !IsHTMLBRElement(
              *start_of_inserted_content.DeepEquivalent().AnchorNode()) &&
          ShouldMerge(start_of_inserted_content, prev);
 }
@@ -494,7 +494,7 @@
 
   return !selection_end_was_end_of_paragraph &&
          IsEndOfParagraph(end_of_inserted_content) &&
-         !isHTMLBRElement(
+         !IsHTMLBRElement(
              *end_of_inserted_content.DeepEquivalent().AnchorNode()) &&
          ShouldMerge(end_of_inserted_content, next);
 }
@@ -823,8 +823,8 @@
 static void RemoveHeadContents(ReplacementFragment& fragment) {
   Node* next = nullptr;
   for (Node* node = fragment.FirstChild(); node; node = next) {
-    if (isHTMLBaseElement(*node) || isHTMLLinkElement(*node) ||
-        isHTMLMetaElement(*node) || isHTMLTitleElement(*node)) {
+    if (IsHTMLBaseElement(*node) || IsHTMLLinkElement(*node) ||
+        IsHTMLMetaElement(*node) || IsHTMLTitleElement(*node)) {
       next = NodeTraversal::NextSkippingChildren(*node);
       fragment.RemoveNode(node);
     } else {
@@ -849,7 +849,7 @@
 static void HandleStyleSpansBeforeInsertion(ReplacementFragment& fragment,
                                             const Position& insertion_pos) {
   Node* top_node = fragment.FirstChild();
-  if (!isHTMLSpanElement(top_node))
+  if (!IsHTMLSpanElement(top_node))
     return;
 
   // Handling the case where we are doing Paste as Quotation or pasting into
@@ -967,7 +967,7 @@
 
 static Node* EnclosingInline(Node* node) {
   while (ContainerNode* parent = node->parentNode()) {
-    if (IsBlockFlowElement(*parent) || isHTMLBodyElement(*parent))
+    if (IsBlockFlowElement(*parent) || IsHTMLBodyElement(*parent))
       return node;
     // Stop if any previous sibling is a block.
     for (Node* sibling = node->previousSibling(); sibling;
@@ -1186,7 +1186,7 @@
       return;
     // This will leave a br between the split.
     Node* br = EndingVisibleSelection().Start().AnchorNode();
-    DCHECK(isHTMLBRElement(br)) << br;
+    DCHECK(IsHTMLBRElement(br)) << br;
     // Insert content between the two blockquotes, but remove the br (since it
     // was just a placeholder).
     insertion_pos = Position::InParentBeforeNode(*br);
@@ -1210,11 +1210,8 @@
   // position as p (since in the case where a br is at the end of a block and
   // collapsed away, there are positions after the br which map to the same
   // visible position as [br, 0]).
-  HTMLBRElement* end_br =
-      isHTMLBRElement(*MostForwardCaretPosition(insertion_pos).AnchorNode())
-          ? toHTMLBRElement(
-                MostForwardCaretPosition(insertion_pos).AnchorNode())
-          : 0;
+  HTMLBRElement* end_br = ToHTMLBRElementOrNull(
+      *MostForwardCaretPosition(insertion_pos).AnchorNode());
   VisiblePosition original_vis_pos_before_end_br;
   if (end_br) {
     original_vis_pos_before_end_br =
@@ -1658,7 +1655,7 @@
 
   TextControlElement* text_control =
       EnclosingTextControl(PositionAtStartOfInsertedContent().DeepEquivalent());
-  if (isHTMLInputElement(text_control) &&
+  if (IsHTMLInputElement(text_control) &&
       toHTMLInputElement(text_control)->type() == InputTypeNames::password)
     return false;  // Disable smart replace for password fields.
 
@@ -2015,7 +2012,7 @@
   GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();
 
   if (node_after_insertion_pos && node_after_insertion_pos->parentNode() &&
-      isHTMLBRElement(*node_after_insertion_pos) &&
+      IsHTMLBRElement(*node_after_insertion_pos) &&
       ShouldRemoveEndBR(
           toHTMLBRElement(node_after_insertion_pos),
           VisiblePosition::BeforeNode(*node_after_insertion_pos))) {
diff --git a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
index 7e92403..37d36fe5 100644
--- a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
@@ -708,7 +708,7 @@
     return false;
 
   if (root->firstChild() == root->lastChild()) {
-    if (isHTMLBRElement(root->firstChild())) {
+    if (IsHTMLBRElement(root->firstChild())) {
       // If there is a single child and it could be a placeholder, leave it
       // alone.
       if (root->GetLayoutObject() &&
diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
index e38774c..3950ec2 100644
--- a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
+++ b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
@@ -350,10 +350,10 @@
                     layout_object->IsLayoutEmbeddedContent() ||
                     (node_ && node_->IsHTMLElement() &&
                      (IsHTMLFormControlElement(ToHTMLElement(*node_)) ||
-                      isHTMLLegendElement(ToHTMLElement(*node_)) ||
-                      isHTMLImageElement(ToHTMLElement(*node_)) ||
-                      isHTMLMeterElement(ToHTMLElement(*node_)) ||
-                      isHTMLProgressElement(ToHTMLElement(*node_)))))) {
+                      IsHTMLLegendElement(ToHTMLElement(*node_)) ||
+                      IsHTMLImageElement(ToHTMLElement(*node_)) ||
+                      IsHTMLMeterElement(ToHTMLElement(*node_)) ||
+                      IsHTMLProgressElement(ToHTMLElement(*node_)))))) {
           HandleReplacedElement();
         } else {
           HandleNonTextNode();
@@ -371,7 +371,7 @@
     // To support |TextIteratorEmitsImageAltText|, we don't traversal child
     // nodes, in flat tree.
     Node* next =
-        iteration_progress_ < kHandledChildren && !isHTMLImageElement(*node_)
+        iteration_progress_ < kHandledChildren && !IsHTMLImageElement(*node_)
             ? Strategy::FirstChild(*node_)
             : nullptr;
     if (!next) {
@@ -496,9 +496,9 @@
   HTMLElement& element = ToHTMLElement(*node);
 
   // FIXME: Add isSVGImageElement.
-  if (isHTMLImageElement(element))
+  if (IsHTMLImageElement(element))
     return true;
-  if (isHTMLInputElement(ToHTMLElement(*node)) &&
+  if (IsHTMLInputElement(ToHTMLElement(*node)) &&
       toHTMLInputElement(*node).type() == InputTypeNames::image)
     return true;
   return false;
@@ -574,10 +574,10 @@
     bool emits_original_text) {
   LayoutObject* layout_object = node->GetLayoutObject();
 
-  if (layout_object ? !layout_object->IsBR() : !isHTMLBRElement(node))
+  if (layout_object ? !layout_object->IsBR() : !IsHTMLBRElement(node))
     return false;
   return emits_original_text || !(node->IsInShadowTree() &&
-                                  isHTMLInputElement(*node->OwnerShadowHost()));
+                                  IsHTMLInputElement(*node->OwnerShadowHost()));
 }
 
 static bool ShouldEmitNewlinesBeforeAndAfterNode(Node& node) {
@@ -599,7 +599,7 @@
 
   // Need to make an exception for option and optgroup, because we want to
   // keep the legacy behavior before we added layoutObjects to them.
-  if (isHTMLOptionElement(node) || isHTMLOptGroupElement(node))
+  if (IsHTMLOptionElement(node) || IsHTMLOptGroupElement(node))
     return false;
 
   // Need to make an exception for table cells, because they are blocks, but we
@@ -706,7 +706,7 @@
           EVisibility::kVisible ||
       (node_->GetLayoutObject()->IsLayoutBlockFlow() &&
        !ToLayoutBlock(node_->GetLayoutObject())->Size().Height() &&
-       !isHTMLBodyElement(*node_)))
+       !IsHTMLBodyElement(*node_)))
     return false;
 
   // The startPos.isNotNull() check is needed because the start could be before
diff --git a/third_party/WebKit/Source/core/editing/serializers/MarkupAccumulator.cpp b/third_party/WebKit/Source/core/editing/serializers/MarkupAccumulator.cpp
index d942727..b28aeb6 100644
--- a/third_party/WebKit/Source/core/editing/serializers/MarkupAccumulator.cpp
+++ b/third_party/WebKit/Source/core/editing/serializers/MarkupAccumulator.cpp
@@ -175,7 +175,7 @@
 
   if (!(accumulator.SerializeAsHTMLDocument(target_node) &&
         ElementCannotHaveEndTag(target_node))) {
-    Node* current = isHTMLTemplateElement(target_node)
+    Node* current = IsHTMLTemplateElement(target_node)
                         ? Strategy::FirstChild(
                               *toHTMLTemplateElement(target_node).content())
                         : Strategy::FirstChild(target_node);
diff --git a/third_party/WebKit/Source/core/editing/serializers/Serialization.cpp b/third_party/WebKit/Source/core/editing/serializers/Serialization.cpp
index 4e9e7165..40c0f5f 100644
--- a/third_party/WebKit/Source/core/editing/serializers/Serialization.cpp
+++ b/third_party/WebKit/Source/core/editing/serializers/Serialization.cpp
@@ -131,7 +131,7 @@
     return 0;
 
   if (common_ancestor_block->HasTagName(tbodyTag) ||
-      isHTMLTableRowElement(*common_ancestor_block))
+      IsHTMLTableRowElement(*common_ancestor_block))
     return Traversal<HTMLTableElement>::FirstAncestor(*common_ancestor_block);
 
   if (IsNonTableCellHTMLBlockElement(common_ancestor_block))
@@ -491,7 +491,7 @@
 
 bool IsPlainTextMarkup(Node* node) {
   DCHECK(node);
-  if (!isHTMLDivElement(*node))
+  if (!IsHTMLDivElement(*node))
     return false;
 
   HTMLDivElement& element = toHTMLDivElement(*node);
@@ -558,7 +558,7 @@
   Element* block =
       EnclosingBlock(context.StartPosition().NodeAsRangeFirstNode());
   bool use_clones_of_enclosing_block =
-      block && !isHTMLBodyElement(*block) && !isHTMLHtmlElement(*block) &&
+      block && !IsHTMLBodyElement(*block) && !IsHTMLHtmlElement(*block) &&
       block != RootEditableElementOf(context.StartPosition());
 
   Vector<String> list;
@@ -592,7 +592,7 @@
     ExceptionState& exception_state) {
   DCHECK(context_element);
   Document& document =
-      isHTMLTemplateElement(*context_element)
+      IsHTMLTemplateElement(*context_element)
           ? context_element->GetDocument().EnsureTemplateDocument()
           : context_element->GetDocument();
   DocumentFragment* fragment = DocumentFragment::Create(document);
@@ -674,8 +674,8 @@
   Node* next_node = nullptr;
   for (Node* node = fragment->firstChild(); node; node = next_node) {
     next_node = node->nextSibling();
-    if (isHTMLHtmlElement(*node) || isHTMLHeadElement(*node) ||
-        isHTMLBodyElement(*node)) {
+    if (IsHTMLHtmlElement(*node) || IsHTMLHeadElement(*node) ||
+        IsHTMLBodyElement(*node)) {
       HTMLElement* element = ToHTMLElement(node);
       if (Node* first_child = element->firstChild())
         next_node = first_child;
diff --git a/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.cpp b/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.cpp
index d7a63079..944c115 100644
--- a/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.cpp
+++ b/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.cpp
@@ -149,7 +149,7 @@
   // Add an interchange newline if a paragraph break is selected and a br won't
   // already be added to the markup to represent it.
   return IsEndOfParagraph(v) && IsStartOfParagraph(next) &&
-         !(isHTMLBRElement(*upstream_node) && upstream_node == downstream_node);
+         !(IsHTMLBRElement(*upstream_node) && upstream_node == downstream_node);
 }
 
 template <typename Strategy>
@@ -481,7 +481,7 @@
   switch (node.getNodeType()) {
     case Node::kTextNode: {
       Text& text = ToText(node);
-      if (text.parentElement() && isHTMLTextAreaElement(text.parentElement())) {
+      if (text.parentElement() && IsHTMLTextAreaElement(text.parentElement())) {
         accumulator_->AppendText(text);
         break;
       }
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.h b/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.h
index 604dff4..5babc8e 100644
--- a/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.h
+++ b/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.h
@@ -75,7 +75,7 @@
   int request_number_;
 };
 
-class SpellCheckRequester final
+class CORE_EXPORT SpellCheckRequester final
     : public GarbageCollectedFinalized<SpellCheckRequester> {
   WTF_MAKE_NONCOPYABLE(SpellCheckRequester);
 
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp b/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp
index c0c9434c..9031247 100644
--- a/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp
+++ b/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp
@@ -791,13 +791,12 @@
   if (position.IsNull())
     return false;
   if (TextControlElement* text_control = EnclosingTextControl(position)) {
-    if (isHTMLInputElement(text_control)) {
-      HTMLInputElement& input = toHTMLInputElement(*text_control);
+    if (auto* input = ToHTMLInputElementOrNull(text_control)) {
       // TODO(tkent): The following password type check should be done in
       // HTMLElement::spellcheck(). crbug.com/371567
-      if (input.type() == InputTypeNames::password)
+      if (input->type() == InputTypeNames::password)
         return false;
-      if (!input.IsFocusedElementInDocument())
+      if (!input->IsFocusedElementInDocument())
         return false;
     }
   }
diff --git a/third_party/WebKit/Source/core/events/ErrorEvent.h b/third_party/WebKit/Source/core/events/ErrorEvent.h
index a5a785c9..1e0e5f5 100644
--- a/third_party/WebKit/Source/core/events/ErrorEvent.h
+++ b/third_party/WebKit/Source/core/events/ErrorEvent.h
@@ -89,7 +89,7 @@
 
   const AtomicString& InterfaceName() const override;
 
-  DOMWrapperWorld* World() const { return world_.Get(); }
+  DOMWrapperWorld* World() const { return world_.get(); }
 
   void SetUnsanitizedMessage(const String&);
 
diff --git a/third_party/WebKit/Source/core/events/EventTypeNames.json5 b/third_party/WebKit/Source/core/events/EventTypeNames.json5
index 39fd306..56a52211d 100644
--- a/third_party/WebKit/Source/core/events/EventTypeNames.json5
+++ b/third_party/WebKit/Source/core/events/EventTypeNames.json5
@@ -212,6 +212,7 @@
     "removetrack",
     "repeatEvent",
     "reset",
+    "resetpose",
     "resize",
     "resourcetimingbufferfull",
     "result",
diff --git a/third_party/WebKit/Source/core/events/PopStateEvent.h b/third_party/WebKit/Source/core/events/PopStateEvent.h
index 35776b4..a40775f 100644
--- a/third_party/WebKit/Source/core/events/PopStateEvent.h
+++ b/third_party/WebKit/Source/core/events/PopStateEvent.h
@@ -51,7 +51,7 @@
 
   ScriptValue state(ScriptState*) const;
   SerializedScriptValue* SerializedState() const {
-    return serialized_state_.Get();
+    return serialized_state_.get();
   }
   void SetSerializedState(RefPtr<SerializedScriptValue> state) {
     DCHECK(!serialized_state_);
diff --git a/third_party/WebKit/Source/core/exported/PrerenderingTest.cpp b/third_party/WebKit/Source/core/exported/PrerenderingTest.cpp
index 666321d..3608d2b 100644
--- a/third_party/WebKit/Source/core/exported/PrerenderingTest.cpp
+++ b/third_party/WebKit/Source/core/exported/PrerenderingTest.cpp
@@ -193,7 +193,7 @@
     Document* document =
         web_view_helper_.LocalMainFrame()->GetFrame()->GetDocument();
     Element* console = document->getElementById("console");
-    DCHECK(isHTMLUListElement(console));
+    DCHECK(IsHTMLUListElement(console));
     return *console;
   }
 
@@ -205,7 +205,7 @@
     Node* item = NodeTraversal::ChildAt(Console(), 1 + i);
 
     DCHECK(item);
-    DCHECK(isHTMLLIElement(item));
+    DCHECK(IsHTMLLIElement(item));
     DCHECK(item->hasChildren());
 
     return item->textContent();
diff --git a/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.cpp b/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.cpp
index 3b3d2ae..ca82c63 100644
--- a/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.cpp
+++ b/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.cpp
@@ -360,7 +360,8 @@
 
   session->Append(new InspectorLogAgent(
       &inspected_frames_->Root()->GetPage()->GetConsoleMessageStorage(),
-      inspected_frames_->Root()->GetPerformanceMonitor()));
+      inspected_frames_->Root()->GetPerformanceMonitor(),
+      session->V8Session()));
 
   InspectorOverlayAgent* overlay_agent =
       new InspectorOverlayAgent(web_local_frame_impl_, inspected_frames_.Get(),
diff --git a/third_party/WebKit/Source/core/exported/WebDocumentSubresourceFilterTest.cpp b/third_party/WebKit/Source/core/exported/WebDocumentSubresourceFilterTest.cpp
index cfaf76c..e6665c5 100644
--- a/third_party/WebKit/Source/core/exported/WebDocumentSubresourceFilterTest.cpp
+++ b/third_party/WebKit/Source/core/exported/WebDocumentSubresourceFilterTest.cpp
@@ -101,7 +101,6 @@
 
   void ExpectSubresourceWasLoaded(bool loaded) {
     WebElement web_element = MainFrame()->GetDocument().QuerySelector("img");
-    ASSERT_TRUE(isHTMLImageElement(web_element));
     HTMLImageElement* image_element = toHTMLImageElement(web_element);
     EXPECT_EQ(loaded, !!image_element->naturalWidth());
   }
diff --git a/third_party/WebKit/Source/core/exported/WebElementTest.cpp b/third_party/WebKit/Source/core/exported/WebElementTest.cpp
index c0fe7c6..4886472 100644
--- a/third_party/WebKit/Source/core/exported/WebElementTest.cpp
+++ b/third_party/WebKit/Source/core/exported/WebElementTest.cpp
@@ -50,6 +50,11 @@
     "  <div>Hello</div> "
     "</div>";
 
+static const char kBlockWithEmptyZeroSizedSVG[] =
+    "<div id='testElement'>"
+    "  <svg height='0'><g><rect width='100' height='100'/></g></svg> "
+    "</div>";
+
 static const char kBlockWithInlines[] =
     "<div id='testElement'>"
     "  <span>Hello</span> "
@@ -60,6 +65,12 @@
     "  <span></span> "
     "</div>";
 
+static const char kBlockWithEmptyFirstChild[] =
+    "<div id='testElement'>"
+    "  <div style='position: absolute'></div> "
+    "  <div style='position: absolute'>Hello</div> "
+    "</div>";
+
 class WebElementTest : public ::testing::Test {
  protected:
   Document& GetDocument() { return page_holder_->GetDocument(); }
@@ -99,6 +110,9 @@
   InsertHTML(kBlockWithEmptyInlines);
   EXPECT_FALSE(TestElement().HasNonEmptyLayoutSize());
 
+  InsertHTML(kBlockWithEmptyZeroSizedSVG);
+  EXPECT_FALSE(TestElement().HasNonEmptyLayoutSize());
+
   InsertHTML(kBlockWithContinuations);
   EXPECT_TRUE(TestElement().HasNonEmptyLayoutSize());
 
@@ -116,6 +130,9 @@
       GetDocument().getElementById("testElement")->CreateShadowRootInternal();
   root.SetInnerHTMLFromString("<div>Hello World</div>");
   EXPECT_TRUE(TestElement().HasNonEmptyLayoutSize());
+
+  InsertHTML(kBlockWithEmptyFirstChild);
+  EXPECT_TRUE(TestElement().HasNonEmptyLayoutSize());
 }
 
 TEST_F(WebElementTest, IsEditable) {
diff --git a/third_party/WebKit/Source/core/exported/WebFormControlElement.cpp b/third_party/WebKit/Source/core/exported/WebFormControlElement.cpp
index 2a242aa8..317030b 100644
--- a/third_party/WebKit/Source/core/exported/WebFormControlElement.cpp
+++ b/third_party/WebKit/Source/core/exported/WebFormControlElement.cpp
@@ -71,30 +71,30 @@
 }
 
 bool WebFormControlElement::AutoComplete() const {
-  if (isHTMLInputElement(*private_))
-    return ConstUnwrap<HTMLInputElement>()->ShouldAutocomplete();
-  if (isHTMLTextAreaElement(*private_))
-    return ConstUnwrap<HTMLTextAreaElement>()->ShouldAutocomplete();
-  if (isHTMLSelectElement(*private_))
-    return ConstUnwrap<HTMLSelectElement>()->ShouldAutocomplete();
+  if (auto* input = ToHTMLInputElementOrNull(*private_))
+    return input->ShouldAutocomplete();
+  if (auto* textarea = ToHTMLTextAreaElementOrNull(*private_))
+    return textarea->ShouldAutocomplete();
+  if (auto* select = ToHTMLSelectElementOrNull(*private_))
+    return select->ShouldAutocomplete();
   return false;
 }
 
 void WebFormControlElement::SetValue(const WebString& value, bool send_events) {
-  if (isHTMLInputElement(*private_)) {
-    Unwrap<HTMLInputElement>()->setValue(
+  if (auto* input = ToHTMLInputElementOrNull(*private_)) {
+    input->setValue(
         value, send_events ? kDispatchInputAndChangeEvent : kDispatchNoEvent);
-  } else if (isHTMLTextAreaElement(*private_)) {
-    Unwrap<HTMLTextAreaElement>()->setValue(
+  } else if (auto* textarea = ToHTMLTextAreaElementOrNull(*private_)) {
+    textarea->setValue(
         value, send_events ? kDispatchInputAndChangeEvent : kDispatchNoEvent);
-  } else if (isHTMLSelectElement(*private_)) {
-    Unwrap<HTMLSelectElement>()->setValue(value, send_events);
+  } else if (auto* select = ToHTMLSelectElementOrNull(*private_)) {
+    select->setValue(value, send_events);
   }
 }
 
 void WebFormControlElement::SetAutofillValue(const WebString& value) {
   // The input and change events will be sent in setValue.
-  if (isHTMLInputElement(*private_) || isHTMLTextAreaElement(*private_)) {
+  if (IsHTMLInputElement(*private_) || IsHTMLTextAreaElement(*private_)) {
     if (!Focused()) {
       Unwrap<Element>()->DispatchFocusEvent(nullptr, kWebFocusTypeForward,
                                             nullptr);
@@ -108,12 +108,12 @@
       Unwrap<Element>()->DispatchBlurEvent(nullptr, kWebFocusTypeForward,
                                            nullptr);
     }
-  } else if (isHTMLSelectElement(*private_)) {
+  } else if (auto* select = ToHTMLSelectElementOrNull(*private_)) {
     if (!Focused()) {
       Unwrap<Element>()->DispatchFocusEvent(nullptr, kWebFocusTypeForward,
                                             nullptr);
     }
-    Unwrap<HTMLSelectElement>()->setValue(value, true);
+    select->setValue(value, true);
     if (!Focused()) {
       Unwrap<Element>()->DispatchBlurEvent(nullptr, kWebFocusTypeForward,
                                            nullptr);
@@ -122,62 +122,62 @@
 }
 
 WebString WebFormControlElement::Value() const {
-  if (isHTMLInputElement(*private_))
-    return ConstUnwrap<HTMLInputElement>()->value();
-  if (isHTMLTextAreaElement(*private_))
-    return ConstUnwrap<HTMLTextAreaElement>()->value();
-  if (isHTMLSelectElement(*private_))
-    return ConstUnwrap<HTMLSelectElement>()->value();
+  if (auto* input = ToHTMLInputElementOrNull(*private_))
+    return input->value();
+  if (auto* textarea = ToHTMLTextAreaElementOrNull(*private_))
+    return textarea->value();
+  if (auto* select = ToHTMLSelectElementOrNull(*private_))
+    return select->value();
   return WebString();
 }
 
 void WebFormControlElement::SetSuggestedValue(const WebString& value) {
-  if (isHTMLInputElement(*private_))
-    Unwrap<HTMLInputElement>()->SetSuggestedValue(value);
-  else if (isHTMLTextAreaElement(*private_))
-    Unwrap<HTMLTextAreaElement>()->SetSuggestedValue(value);
-  else if (isHTMLSelectElement(*private_))
-    Unwrap<HTMLSelectElement>()->SetSuggestedValue(value);
+  if (auto* input = ToHTMLInputElementOrNull(*private_))
+    input->SetSuggestedValue(value);
+  else if (auto* textarea = ToHTMLTextAreaElementOrNull(*private_))
+    textarea->SetSuggestedValue(value);
+  else if (auto* select = ToHTMLSelectElementOrNull(*private_))
+    select->SetSuggestedValue(value);
 }
 
 WebString WebFormControlElement::SuggestedValue() const {
-  if (isHTMLInputElement(*private_))
-    return ConstUnwrap<HTMLInputElement>()->SuggestedValue();
-  if (isHTMLTextAreaElement(*private_))
-    return ConstUnwrap<HTMLTextAreaElement>()->SuggestedValue();
-  if (isHTMLSelectElement(*private_))
-    return ConstUnwrap<HTMLSelectElement>()->SuggestedValue();
+  if (auto* input = ToHTMLInputElementOrNull(*private_))
+    return input->SuggestedValue();
+  if (auto* textarea = ToHTMLTextAreaElementOrNull(*private_))
+    return textarea->SuggestedValue();
+  if (auto* select = ToHTMLSelectElementOrNull(*private_))
+    return select->SuggestedValue();
   return WebString();
 }
 
 WebString WebFormControlElement::EditingValue() const {
-  if (isHTMLInputElement(*private_))
-    return ConstUnwrap<HTMLInputElement>()->InnerEditorValue();
-  if (isHTMLTextAreaElement(*private_))
-    return ConstUnwrap<HTMLTextAreaElement>()->InnerEditorValue();
+  if (auto* input = ToHTMLInputElementOrNull(*private_))
+    return input->InnerEditorValue();
+  if (auto* textarea = ToHTMLTextAreaElementOrNull(*private_))
+    return textarea->InnerEditorValue();
   return WebString();
 }
 
 void WebFormControlElement::SetSelectionRange(int start, int end) {
-  if (isHTMLInputElement(*private_))
-    Unwrap<HTMLInputElement>()->SetSelectionRange(start, end);
-  else if (isHTMLTextAreaElement(*private_))
-    Unwrap<HTMLTextAreaElement>()->SetSelectionRange(start, end);
+  if (auto* input = ToHTMLInputElementOrNull(*private_))
+    input->SetSelectionRange(start, end);
+  if (auto* textarea = ToHTMLTextAreaElementOrNull(*private_))
+    textarea->SetSelectionRange(start, end);
 }
 
 int WebFormControlElement::SelectionStart() const {
-  if (isHTMLInputElement(*private_))
-    return ConstUnwrap<HTMLInputElement>()->selectionStart();
-  if (isHTMLTextAreaElement(*private_))
-    return ConstUnwrap<HTMLTextAreaElement>()->selectionStart();
+  if (auto* input = ToHTMLInputElementOrNull(*private_))
+    return input->selectionStart();
+  if (auto* textarea = ToHTMLTextAreaElementOrNull(*private_))
+    return textarea->selectionStart();
   return 0;
 }
 
 int WebFormControlElement::SelectionEnd() const {
-  if (isHTMLInputElement(*private_))
-    return ConstUnwrap<HTMLInputElement>()->selectionEnd();
-  if (isHTMLTextAreaElement(*private_))
-    return ConstUnwrap<HTMLTextAreaElement>()->selectionEnd();
+  if (auto* input = ToHTMLInputElementOrNull(*private_))
+    return input->selectionEnd();
+  if (auto* textarea = ToHTMLTextAreaElementOrNull(*private_))
+    return textarea->selectionEnd();
   return 0;
 }
 
diff --git a/third_party/WebKit/Source/core/exported/WebFormElement.cpp b/third_party/WebKit/Source/core/exported/WebFormElement.cpp
index 352889d..1d3ec92 100644
--- a/third_party/WebKit/Source/core/exported/WebFormElement.cpp
+++ b/third_party/WebKit/Source/core/exported/WebFormElement.cpp
@@ -75,7 +75,7 @@
 WebFormElement::WebFormElement(HTMLFormElement* e) : WebElement(e) {}
 
 DEFINE_WEB_NODE_TYPE_CASTS(WebFormElement,
-                           isHTMLFormElement(ConstUnwrap<Node>()));
+                           IsHTMLFormElement(ConstUnwrap<Node>()));
 
 WebFormElement& WebFormElement::operator=(HTMLFormElement* e) {
   private_ = e;
diff --git a/third_party/WebKit/Source/core/exported/WebFrameSerializer.cpp b/third_party/WebKit/Source/core/exported/WebFrameSerializer.cpp
index 5f40020..f863ad7c 100644
--- a/third_party/WebKit/Source/core/exported/WebFrameSerializer.cpp
+++ b/third_party/WebKit/Source/core/exported/WebFrameSerializer.cpp
@@ -152,7 +152,7 @@
   // being loaded. But if an iframe is injected into the head later, it will
   // stay there and not been displayed. To prevent it from being brought to the
   // saved page and cause it being displayed, we should not include it.
-  if (isHTMLIFrameElement(element) &&
+  if (IsHTMLIFrameElement(element) &&
       Traversal<HTMLHeadElement>::FirstAncestor(element)) {
     return true;
   }
@@ -162,7 +162,7 @@
     return true;
 
   // Do not include the hidden form element.
-  return isHTMLInputElement(element) &&
+  return IsHTMLInputElement(element) &&
          toHTMLInputElement(&element)->type() == InputTypeNames::hidden;
 }
 
@@ -174,7 +174,7 @@
   // the saved MHTML page, there is no need to carry the directives. If they
   // are still kept in the MHTML, child frames that are referred to using cid:
   // scheme could be prevented from loading.
-  if (!isHTMLMetaElement(element))
+  if (!IsHTMLMetaElement(element))
     return false;
   if (!element.FastHasAttribute(HTMLNames::contentAttr))
     return false;
@@ -219,7 +219,7 @@
 
   // Do not save ping attribute since anyway the ping will be blocked from
   // MHTML.
-  if (isHTMLAnchorElement(element) &&
+  if (IsHTMLAnchorElement(element) &&
       attribute.LocalName() == HTMLNames::pingAttr) {
     return true;
   }
@@ -227,7 +227,7 @@
   // The special attribute in a template element to denote the shadow DOM
   // should only be generated from MHTML serialization. If it is found in the
   // original page, it should be ignored.
-  if (isHTMLTemplateElement(element) &&
+  if (IsHTMLTemplateElement(element) &&
       (attribute.LocalName() == kShadowModeAttributeName ||
        attribute.LocalName() == kShadowDelegatesFocusAttributeName) &&
       !shadow_template_elements_.Contains(&element)) {
@@ -270,7 +270,7 @@
     return true;
   }
 
-  if (isHTMLObjectElement(&element)) {
+  if (IsHTMLObjectElement(&element)) {
     Document* doc = frame_owner_element->contentDocument();
     bool is_handled_by_serializer = doc->IsHTMLDocument() ||
                                     doc->IsXHTMLDocument() ||
@@ -302,9 +302,8 @@
     const Element& element) {
   Vector<Attribute> attributes;
 
-  if (isHTMLImageElement(element)) {
-    GetCustomAttributesForImageElement(toHTMLImageElement(element),
-                                       &attributes);
+  if (auto* image = ToHTMLImageElementOrNull(element)) {
+    GetCustomAttributesForImageElement(*image, &attributes);
   } else if (element.IsFormControlElement()) {
     GetCustomAttributesForFormControlElement(element, &attributes);
   }
diff --git a/third_party/WebKit/Source/core/exported/WebFrameTest.cpp b/third_party/WebKit/Source/core/exported/WebFrameTest.cpp
index d708c92..c7878a1 100644
--- a/third_party/WebKit/Source/core/exported/WebFrameTest.cpp
+++ b/third_party/WebKit/Source/core/exported/WebFrameTest.cpp
@@ -164,6 +164,7 @@
 #include "v8/include/v8.h"
 
 using blink::URLTestHelpers::ToKURL;
+using blink::mojom::SelectionMenuBehavior;
 using blink::testing::RunPendingTasks;
 using ::testing::ElementsAre;
 using ::testing::Mock;
@@ -5387,7 +5388,8 @@
                                  &web_view_helper);
 
   WebLocalFrameImpl* frame = web_view_helper.LocalMainFrame();
-  frame->SelectRange(WebRange(0, 5));
+  frame->SelectRange(WebRange(0, 5), WebLocalFrame::kHideSelectionHandle,
+                     SelectionMenuBehavior::kHide);
   EXPECT_FALSE(frame->SelectionRange().IsNull());
 
   EXPECT_FALSE(frame->GetFrame()->Selection().IsHandleVisible())
@@ -5402,7 +5404,8 @@
                                  &web_view_helper);
 
   WebLocalFrameImpl* frame = web_view_helper.LocalMainFrame();
-  frame->SelectRange(WebRange(0, 5), WebLocalFrame::kHideSelectionHandle);
+  frame->SelectRange(WebRange(0, 5), WebLocalFrame::kHideSelectionHandle,
+                     SelectionMenuBehavior::kHide);
 
   EXPECT_FALSE(frame->GetFrame()->Selection().IsHandleVisible())
       << "Selection handle should not be visible with kHideSelectionHandle";
@@ -5416,7 +5419,8 @@
                                  &web_view_helper);
 
   WebLocalFrameImpl* frame = web_view_helper.LocalMainFrame();
-  frame->SelectRange(WebRange(0, 5), WebLocalFrame::kShowSelectionHandle);
+  frame->SelectRange(WebRange(0, 5), WebLocalFrame::kShowSelectionHandle,
+                     SelectionMenuBehavior::kHide);
 
   EXPECT_TRUE(frame->GetFrame()->Selection().IsHandleVisible())
       << "Selection handle should be visible with kShowSelectionHandle";
@@ -5430,14 +5434,18 @@
                                  &web_view_helper);
 
   WebLocalFrameImpl* frame = web_view_helper.LocalMainFrame();
-  frame->SelectRange(WebRange(0, 5), WebLocalFrame::kHideSelectionHandle);
-  frame->SelectRange(WebRange(0, 6), WebLocalFrame::kPreserveHandleVisibility);
+  frame->SelectRange(WebRange(0, 5), WebLocalFrame::kHideSelectionHandle,
+                     SelectionMenuBehavior::kHide);
+  frame->SelectRange(WebRange(0, 6), WebLocalFrame::kPreserveHandleVisibility,
+                     SelectionMenuBehavior::kHide);
 
   EXPECT_FALSE(frame->GetFrame()->Selection().IsHandleVisible())
       << "kPreserveHandleVisibility should keep handles invisible";
 
-  frame->SelectRange(WebRange(0, 5), WebLocalFrame::kShowSelectionHandle);
-  frame->SelectRange(WebRange(0, 6), WebLocalFrame::kPreserveHandleVisibility);
+  frame->SelectRange(WebRange(0, 5), WebLocalFrame::kShowSelectionHandle,
+                     SelectionMenuBehavior::kHide);
+  frame->SelectRange(WebRange(0, 6), WebLocalFrame::kPreserveHandleVisibility,
+                     SelectionMenuBehavior::kHide);
 
   EXPECT_TRUE(frame->GetFrame()->Selection().IsHandleVisible())
       << "kPreserveHandleVisibility should keep handles visible";
@@ -6658,7 +6666,9 @@
 
   const int kAllTextBeginOffset = 0;
   const int kAllTextLength = 11;
-  frame->SelectRange(WebRange(kAllTextBeginOffset, kAllTextLength));
+  frame->SelectRange(WebRange(kAllTextBeginOffset, kAllTextLength),
+                     WebLocalFrame::kHideSelectionHandle,
+                     SelectionMenuBehavior::kHide);
   EphemeralRange selection_range = frame->GetFrame()
                                        ->Selection()
                                        .ComputeVisibleSelectionInDOMTree()
@@ -6704,7 +6714,9 @@
 
   const int kAllTextBeginOffset = 0;
   const int kAllTextLength = 11;
-  frame->SelectRange(WebRange(kAllTextBeginOffset, kAllTextLength));
+  frame->SelectRange(WebRange(kAllTextBeginOffset, kAllTextLength),
+                     WebLocalFrame::kHideSelectionHandle,
+                     SelectionMenuBehavior::kHide);
   EphemeralRange selection_range = frame->GetFrame()
                                        ->Selection()
                                        .ComputeVisibleSelectionInDOMTree()
diff --git a/third_party/WebKit/Source/core/exported/WebInputElement.cpp b/third_party/WebKit/Source/core/exported/WebInputElement.cpp
index ba3bd1f..2395f0f 100644
--- a/third_party/WebKit/Source/core/exported/WebInputElement.cpp
+++ b/third_party/WebKit/Source/core/exported/WebInputElement.cpp
@@ -136,7 +136,7 @@
     : WebFormControlElement(elem) {}
 
 DEFINE_WEB_NODE_TYPE_CASTS(WebInputElement,
-                           isHTMLInputElement(ConstUnwrap<Node>()));
+                           IsHTMLInputElement(ConstUnwrap<Node>()));
 
 WebInputElement& WebInputElement::operator=(HTMLInputElement* elem) {
   private_ = elem;
@@ -148,7 +148,7 @@
 }
 
 WebInputElement* ToWebInputElement(WebElement* web_element) {
-  if (!isHTMLInputElement(*web_element->Unwrap<Element>()))
+  if (!IsHTMLInputElement(*web_element->Unwrap<Element>()))
     return 0;
 
   return static_cast<WebInputElement*>(web_element);
diff --git a/third_party/WebKit/Source/core/exported/WebInputMethodControllerImpl.cpp b/third_party/WebKit/Source/core/exported/WebInputMethodControllerImpl.cpp
index d66234e..bd8b4820 100644
--- a/third_party/WebKit/Source/core/exported/WebInputMethodControllerImpl.cpp
+++ b/third_party/WebKit/Source/core/exported/WebInputMethodControllerImpl.cpp
@@ -53,8 +53,11 @@
     return false;
 
   // Select the range to be replaced with the composition later.
-  if (!replacement_range.IsNull())
-    web_frame_->SelectRange(replacement_range);
+  if (!replacement_range.IsNull()) {
+    web_frame_->SelectRange(replacement_range,
+                            WebLocalFrame::kHideSelectionHandle,
+                            blink::mojom::SelectionMenuBehavior::kHide);
+  }
 
   // We should verify the parent node of this IME composition node are
   // editable because JavaScript may delete a parent node of the composition
@@ -115,8 +118,11 @@
   }
 
   // Select the range to be replaced with the composition later.
-  if (!replacement_range.IsNull())
-    web_frame_->SelectRange(replacement_range);
+  if (!replacement_range.IsNull()) {
+    web_frame_->SelectRange(replacement_range,
+                            WebLocalFrame::kHideSelectionHandle,
+                            blink::mojom::SelectionMenuBehavior::kHide);
+  }
 
   // TODO(editing-dev): The use of updateStyleAndLayoutIgnorePendingStylesheets
   // needs to be audited.  See http://crbug.com/590369 for more details.
diff --git a/third_party/WebKit/Source/core/exported/WebLabelElement.cpp b/third_party/WebKit/Source/core/exported/WebLabelElement.cpp
index 5800c40..c1b19fb 100644
--- a/third_party/WebKit/Source/core/exported/WebLabelElement.cpp
+++ b/third_party/WebKit/Source/core/exported/WebLabelElement.cpp
@@ -45,7 +45,7 @@
 WebLabelElement::WebLabelElement(HTMLLabelElement* elem) : WebElement(elem) {}
 
 DEFINE_WEB_NODE_TYPE_CASTS(WebLabelElement,
-                           isHTMLLabelElement(ConstUnwrap<Node>()));
+                           IsHTMLLabelElement(ConstUnwrap<Node>()));
 
 WebLabelElement& WebLabelElement::operator=(HTMLLabelElement* elem) {
   private_ = elem;
diff --git a/third_party/WebKit/Source/core/exported/WebMetaElement.cpp b/third_party/WebKit/Source/core/exported/WebMetaElement.cpp
index cbc6cf7..8d003fdc 100644
--- a/third_party/WebKit/Source/core/exported/WebMetaElement.cpp
+++ b/third_party/WebKit/Source/core/exported/WebMetaElement.cpp
@@ -19,7 +19,7 @@
     : WebElement(element) {}
 
 DEFINE_WEB_NODE_TYPE_CASTS(WebMetaElement,
-                           isHTMLMetaElement(ConstUnwrap<Node>()));
+                           IsHTMLMetaElement(ConstUnwrap<Node>()));
 
 WebMetaElement& WebMetaElement::operator=(HTMLMetaElement* element) {
   private_ = element;
diff --git a/third_party/WebKit/Source/core/exported/WebOptionElement.cpp b/third_party/WebKit/Source/core/exported/WebOptionElement.cpp
index 98c8b4f..8d4be970 100644
--- a/third_party/WebKit/Source/core/exported/WebOptionElement.cpp
+++ b/third_party/WebKit/Source/core/exported/WebOptionElement.cpp
@@ -53,7 +53,7 @@
     : WebElement(elem) {}
 
 DEFINE_WEB_NODE_TYPE_CASTS(WebOptionElement,
-                           isHTMLOptionElement(ConstUnwrap<Node>()));
+                           IsHTMLOptionElement(ConstUnwrap<Node>()));
 
 WebOptionElement& WebOptionElement::operator=(HTMLOptionElement* elem) {
   private_ = elem;
diff --git a/third_party/WebKit/Source/core/exported/WebPagePopupImpl.cpp b/third_party/WebKit/Source/core/exported/WebPagePopupImpl.cpp
index 23694e0..443126b 100644
--- a/third_party/WebKit/Source/core/exported/WebPagePopupImpl.cpp
+++ b/third_party/WebKit/Source/core/exported/WebPagePopupImpl.cpp
@@ -319,7 +319,7 @@
   InitializeLayerTreeView();
 
   RefPtr<SharedBuffer> data = SharedBuffer::Create();
-  popup_client_->WriteDocument(data.Get());
+  popup_client_->WriteDocument(data.get());
   frame->SetPageZoomFactor(popup_client_->ZoomFactor());
   frame->ForceSynchronousDocumentInstall("text/html", data);
   return true;
diff --git a/third_party/WebKit/Source/core/exported/WebSearchableFormData.cpp b/third_party/WebKit/Source/core/exported/WebSearchableFormData.cpp
index 037c6f1..b0933db1 100644
--- a/third_party/WebKit/Source/core/exported/WebSearchableFormData.cpp
+++ b/third_party/WebKit/Source/core/exported/WebSearchableFormData.cpp
@@ -118,15 +118,12 @@
 // in its default state if the checked state matches the state of the checked
 // attribute.
 bool IsInDefaultState(const HTMLFormControlElement& form_element) {
-  if (isHTMLInputElement(form_element)) {
-    const HTMLInputElement& input_element = toHTMLInputElement(form_element);
-    if (input_element.type() == InputTypeNames::checkbox ||
-        input_element.type() == InputTypeNames::radio) {
-      return input_element.checked() ==
-             input_element.FastHasAttribute(checkedAttr);
-    }
-  } else if (isHTMLSelectElement(form_element)) {
-    return IsSelectInDefaultState(toHTMLSelectElement(form_element));
+  if (auto* input = ToHTMLInputElementOrNull(form_element)) {
+    if (input->type() == InputTypeNames::checkbox ||
+        input->type() == InputTypeNames::radio)
+      return input->checked() == input->FastHasAttribute(checkedAttr);
+  } else if (auto* select = ToHTMLSelectElementOrNull(form_element)) {
+    return IsSelectInDefaultState(*select);
   }
   return true;
 }
@@ -148,10 +145,10 @@
     if (control.IsDisabledFormControl() || control.GetName().IsNull())
       continue;
 
-    if (!IsInDefaultState(control) || isHTMLTextAreaElement(control))
+    if (!IsInDefaultState(control) || IsHTMLTextAreaElement(control))
       return nullptr;
 
-    if (isHTMLInputElement(control) && control.willValidate()) {
+    if (IsHTMLInputElement(control) && control.willValidate()) {
       const HTMLInputElement& input = toHTMLInputElement(control);
 
       // Return nothing if a file upload field or a password field are
diff --git a/third_party/WebKit/Source/core/exported/WebSelectElement.cpp b/third_party/WebKit/Source/core/exported/WebSelectElement.cpp
index 858f64365..b7426fc5 100644
--- a/third_party/WebKit/Source/core/exported/WebSelectElement.cpp
+++ b/third_party/WebKit/Source/core/exported/WebSelectElement.cpp
@@ -52,7 +52,7 @@
     : WebFormControlElement(element) {}
 
 DEFINE_WEB_NODE_TYPE_CASTS(WebSelectElement,
-                           isHTMLSelectElement(ConstUnwrap<Node>()));
+                           IsHTMLSelectElement(ConstUnwrap<Node>()));
 
 WebSelectElement& WebSelectElement::operator=(HTMLSelectElement* element) {
   private_ = element;
diff --git a/third_party/WebKit/Source/core/exported/WebViewImpl.cpp b/third_party/WebKit/Source/core/exported/WebViewImpl.cpp
index 3ed8a5a..e36d8ab 100644
--- a/third_party/WebKit/Source/core/exported/WebViewImpl.cpp
+++ b/third_party/WebKit/Source/core/exported/WebViewImpl.cpp
@@ -475,7 +475,7 @@
   }
 
   if (page_popup_ && page_popup &&
-      page_popup_->HasSamePopupClient(page_popup.Get())) {
+      page_popup_->HasSamePopupClient(page_popup.get())) {
     // That click triggered a page popup that is the same as the one we just
     // closed.  It needs to be closed.
     CancelPagePopup();
@@ -706,7 +706,7 @@
       }
 
       if (page_popup_ && last_hidden_page_popup_ &&
-          page_popup_->HasSamePopupClient(last_hidden_page_popup_.Get())) {
+          page_popup_->HasSamePopupClient(last_hidden_page_popup_.get())) {
         // The tap triggered a page popup that is the same as the one we just
         // closed. It needs to be closed.
         CancelPagePopup();
@@ -1535,14 +1535,14 @@
   }
   EnablePopupMouseWheelEventListener(WebLocalFrameImpl::FromFrame(
       client->OwnerElement().GetDocument().GetFrame()->LocalFrameRoot()));
-  return page_popup_.Get();
+  return page_popup_.get();
 }
 
 void WebViewImpl::ClosePagePopup(PagePopup* popup) {
   DCHECK(popup);
   WebPagePopupImpl* popup_impl = ToWebPagePopupImpl(popup);
-  DCHECK_EQ(page_popup_.Get(), popup_impl);
-  if (page_popup_.Get() != popup_impl)
+  DCHECK_EQ(page_popup_.get(), popup_impl);
+  if (page_popup_.get() != popup_impl)
     return;
   page_popup_->ClosePopup();
 }
@@ -2289,7 +2289,7 @@
 }
 
 WebPagePopupImpl* WebViewImpl::GetPagePopup() const {
-  return page_popup_.Get();
+  return page_popup_.get();
 }
 
 // TODO(ekaramad):This method is almost duplicated in WebFrameWidgetImpl as
@@ -3129,7 +3129,7 @@
                                            const WebPoint& location) {
   HitTestResult result = HitTestResultForViewportPos(location);
   Node* node = result.InnerNode();
-  if (!isHTMLVideoElement(*node) && !isHTMLAudioElement(*node))
+  if (!IsHTMLVideoElement(*node) && !IsHTMLAudioElement(*node))
     return;
 
   HTMLMediaElement* media_element = ToHTMLMediaElement(node);
@@ -3160,7 +3160,7 @@
   // FIXME: Location is probably in viewport coordinates
   HitTestResult result = HitTestResultForRootFramePos(location);
   Node* node = result.InnerNode();
-  if (!isHTMLObjectElement(*node) && !isHTMLEmbedElement(*node))
+  if (!IsHTMLObjectElement(*node) && !IsHTMLEmbedElement(*node))
     return;
 
   LayoutObject* object = node->GetLayoutObject();
diff --git a/third_party/WebKit/Source/core/exported/WebViewImpl.h b/third_party/WebKit/Source/core/exported/WebViewImpl.h
index 563cd28..820c1d2a 100644
--- a/third_party/WebKit/Source/core/exported/WebViewImpl.h
+++ b/third_party/WebKit/Source/core/exported/WebViewImpl.h
@@ -361,7 +361,7 @@
   WebViewScheduler* Scheduler() const override;
   void SetVisibilityState(WebPageVisibilityState, bool) override;
 
-  bool HasOpenedPopup() const { return page_popup_.Get(); }
+  bool HasOpenedPopup() const { return page_popup_.get(); }
 
   // Called by a full frame plugin inside this view to inform it that its
   // zoom level has been updated.  The plugin should only call this function
diff --git a/third_party/WebKit/Source/core/fileapi/Blob.cpp b/third_party/WebKit/Source/core/fileapi/Blob.cpp
index ee0cdc12..37fb842 100644
--- a/third_party/WebKit/Source/core/fileapi/Blob.cpp
+++ b/third_party/WebKit/Source/core/fileapi/Blob.cpp
@@ -127,18 +127,18 @@
     const HeapVector<ArrayBufferOrArrayBufferViewOrBlobOrUSVString>& parts,
     bool normalize_line_endings_to_native) {
   for (const auto& item : parts) {
-    if (item.isArrayBuffer()) {
-      DOMArrayBuffer* array_buffer = item.getAsArrayBuffer();
+    if (item.IsArrayBuffer()) {
+      DOMArrayBuffer* array_buffer = item.GetAsArrayBuffer();
       blob_data->AppendBytes(array_buffer->Data(), array_buffer->ByteLength());
-    } else if (item.isArrayBufferView()) {
+    } else if (item.IsArrayBufferView()) {
       DOMArrayBufferView* array_buffer_view =
-          item.getAsArrayBufferView().View();
+          item.GetAsArrayBufferView().View();
       blob_data->AppendBytes(array_buffer_view->BaseAddress(),
                              array_buffer_view->byteLength());
-    } else if (item.isBlob()) {
-      item.getAsBlob()->AppendTo(*blob_data);
-    } else if (item.isUSVString()) {
-      blob_data->AppendText(item.getAsUSVString(),
+    } else if (item.IsBlob()) {
+      item.GetAsBlob()->AppendTo(*blob_data);
+    } else if (item.IsUSVString()) {
+      blob_data->AppendText(item.GetAsUSVString(),
                             normalize_line_endings_to_native);
     } else {
       NOTREACHED();
diff --git a/third_party/WebKit/Source/core/fileapi/FileReader.cpp b/third_party/WebKit/Source/core/fileapi/FileReader.cpp
index d8c8b6eb..6165673 100644
--- a/third_party/WebKit/Source/core/fileapi/FileReader.cpp
+++ b/third_party/WebKit/Source/core/fileapi/FileReader.cpp
@@ -362,9 +362,9 @@
   }
 
   if (read_type_ == FileReaderLoader::kReadAsArrayBuffer)
-    result_attribute.setArrayBuffer(loader_->ArrayBufferResult());
+    result_attribute.SetArrayBuffer(loader_->ArrayBufferResult());
   else
-    result_attribute.setString(loader_->StringResult());
+    result_attribute.SetString(loader_->StringResult());
 }
 
 void FileReader::Terminate() {
diff --git a/third_party/WebKit/Source/core/frame/Deprecation.cpp b/third_party/WebKit/Source/core/frame/Deprecation.cpp
index 6d0298d..696b504 100644
--- a/third_party/WebKit/Source/core/frame/Deprecation.cpp
+++ b/third_party/WebKit/Source/core/frame/Deprecation.cpp
@@ -288,8 +288,8 @@
   // Send the deprecation report to the Reporting API.
   mojom::blink::ReportingServiceProxyPtr service;
   frame->Client()->GetInterfaceProvider()->GetInterface(&service);
-  service->QueueDeprecationReport(document->Url(), body->message(),
-                                  body->sourceFile(), body->lineNumber());
+  service->QueueDeprecationReport(document->Url(), message, body->sourceFile(),
+                                  body->lineNumber());
 }
 
 String Deprecation::DeprecationMessage(WebFeature feature) {
diff --git a/third_party/WebKit/Source/core/frame/FrameConsole.cpp b/third_party/WebKit/Source/core/frame/FrameConsole.cpp
index 535d4f78..f4b27dd 100644
--- a/third_party/WebKit/Source/core/frame/FrameConsole.cpp
+++ b/third_party/WebKit/Source/core/frame/FrameConsole.cpp
@@ -55,9 +55,11 @@
     std::unique_ptr<SourceLocation> source_location =
         provisional_loader->CopySourceLocation();
     if (source_location) {
+      Vector<DOMNodeId> nodes(console_message->Nodes());
       console_message = ConsoleMessage::Create(
           console_message->Source(), console_message->Level(),
           console_message->Message(), std::move(source_location));
+      console_message->SetNodes(std::move(nodes));
     }
   }
 
diff --git a/third_party/WebKit/Source/core/frame/FrameSerializer.cpp b/third_party/WebKit/Source/core/frame/FrameSerializer.cpp
index 1fec2c2..aa8abe6 100644
--- a/third_party/WebKit/Source/core/frame/FrameSerializer.cpp
+++ b/third_party/WebKit/Source/core/frame/FrameSerializer.cpp
@@ -157,11 +157,11 @@
 
 bool SerializerMarkupAccumulator::ShouldIgnoreElement(
     const Element& element) const {
-  if (isHTMLScriptElement(element))
+  if (IsHTMLScriptElement(element))
     return true;
-  if (isHTMLNoScriptElement(element))
+  if (IsHTMLNoScriptElement(element))
     return true;
-  if (isHTMLMetaElement(element) &&
+  if (IsHTMLMetaElement(element) &&
       toHTMLMetaElement(element).ComputeEncoding().IsValid()) {
     return true;
   }
@@ -175,7 +175,7 @@
 
   // TODO(tiger): Refactor MarkupAccumulator so it is easier to append an
   // element like this, without special cases for XHTML
-  if (isHTMLHeadElement(element)) {
+  if (IsHTMLHeadElement(element)) {
     result.Append("<meta http-equiv=\"Content-Type\" content=\"");
     AppendAttributeValue(result, document_->SuggestedMIMEType());
     result.Append("; charset=");
@@ -328,31 +328,24 @@
                                      document);
     }
 
-    if (isHTMLImageElement(element)) {
-      HTMLImageElement& image_element = toHTMLImageElement(element);
-      KURL url =
-          document.CompleteURL(image_element.getAttribute(HTMLNames::srcAttr));
-      ImageResourceContent* cached_image = image_element.CachedImage();
+    if (auto* image = ToHTMLImageElementOrNull(element)) {
+      KURL url = document.CompleteURL(image->getAttribute(HTMLNames::srcAttr));
+      ImageResourceContent* cached_image = image->CachedImage();
       AddImageToResources(cached_image, url);
-    } else if (isHTMLInputElement(element)) {
-      HTMLInputElement& input_element = toHTMLInputElement(element);
-      if (input_element.type() == InputTypeNames::image &&
-          input_element.ImageLoader()) {
-        KURL url = input_element.Src();
-        ImageResourceContent* cached_image =
-            input_element.ImageLoader()->GetImage();
+    } else if (auto* input = ToHTMLInputElementOrNull(element)) {
+      if (input->type() == InputTypeNames::image && input->ImageLoader()) {
+        KURL url = input->Src();
+        ImageResourceContent* cached_image = input->ImageLoader()->GetImage();
         AddImageToResources(cached_image, url);
       }
-    } else if (isHTMLLinkElement(element)) {
-      HTMLLinkElement& link_element = toHTMLLinkElement(element);
-      if (CSSStyleSheet* sheet = link_element.sheet()) {
-        KURL url = document.CompleteURL(
-            link_element.getAttribute(HTMLNames::hrefAttr));
+    } else if (auto* link = ToHTMLLinkElementOrNull(element)) {
+      if (CSSStyleSheet* sheet = link->sheet()) {
+        KURL url =
+            document.CompleteURL(link->getAttribute(HTMLNames::hrefAttr));
         SerializeCSSStyleSheet(*sheet, url);
       }
-    } else if (isHTMLStyleElement(element)) {
-      HTMLStyleElement& style_element = toHTMLStyleElement(element);
-      if (CSSStyleSheet* sheet = style_element.sheet())
+    } else if (auto* style = ToHTMLStyleElementOrNull(element)) {
+      if (CSSStyleSheet* sheet = style->sheet())
         SerializeCSSStyleSheet(*sheet, NullURL());
     }
   }
diff --git a/third_party/WebKit/Source/core/frame/FullscreenController.cpp b/third_party/WebKit/Source/core/frame/FullscreenController.cpp
index 54ee8fc..66c0809 100644
--- a/third_party/WebKit/Source/core/frame/FullscreenController.cpp
+++ b/third_party/WebKit/Source/core/frame/FullscreenController.cpp
@@ -197,13 +197,12 @@
   if (new_element) {
     DCHECK(Fullscreen::IsFullscreenElement(*new_element));
 
-    if (isHTMLVideoElement(*new_element)) {
-      HTMLVideoElement& video_element = toHTMLVideoElement(*new_element);
-      video_element.DidEnterFullscreen();
+    if (auto* video_element = ToHTMLVideoElementOrNull(*new_element)) {
+      video_element->DidEnterFullscreen();
 
       // If the video uses overlay fullscreen mode, make the background
       // transparent.
-      if (video_element.UsesOverlayFullscreenVideo())
+      if (video_element->UsesOverlayFullscreenVideo())
         web_view_base_->SetBackgroundColorOverride(Color::kTransparent);
     }
   }
@@ -211,10 +210,8 @@
   if (old_element) {
     DCHECK(!Fullscreen::IsFullscreenElement(*old_element));
 
-    if (isHTMLVideoElement(*old_element)) {
-      HTMLVideoElement& video_element = toHTMLVideoElement(*old_element);
-      video_element.DidExitFullscreen();
-    }
+    if (auto* video_element = ToHTMLVideoElementOrNull(*old_element))
+      video_element->DidExitFullscreen();
   }
 }
 
diff --git a/third_party/WebKit/Source/core/frame/History.cpp b/third_party/WebKit/Source/core/frame/History.cpp
index a3edf95..ae171b64 100644
--- a/third_party/WebKit/Source/core/frame/History.cpp
+++ b/third_party/WebKit/Source/core/frame/History.cpp
@@ -81,7 +81,7 @@
     return 0;
   }
   last_state_object_requested_ = StateInternal();
-  return last_state_object_requested_.Get();
+  return last_state_object_requested_.get();
 }
 
 SerializedScriptValue* History::StateInternal() const {
diff --git a/third_party/WebKit/Source/core/frame/HistoryTest.cpp b/third_party/WebKit/Source/core/frame/HistoryTest.cpp
index 192ca7f6..1dd08e33 100644
--- a/third_party/WebKit/Source/core/frame/HistoryTest.cpp
+++ b/third_party/WebKit/Source/core/frame/HistoryTest.cpp
@@ -50,7 +50,7 @@
     KURL document_url(kParsedURLString, test.document_url);
     RefPtr<SecurityOrigin> document_origin =
         SecurityOrigin::Create(document_url);
-    EXPECT_EQ(test.expected, History::CanChangeToUrl(url, document_origin.Get(),
+    EXPECT_EQ(test.expected, History::CanChangeToUrl(url, document_origin.get(),
                                                      document_url));
   }
 }
@@ -74,7 +74,7 @@
     KURL document_url(kParsedURLString, test.document_url);
     RefPtr<SecurityOrigin> document_origin =
         SecurityOrigin::Create(document_url);
-    EXPECT_EQ(test.expected, History::CanChangeToUrl(url, document_origin.Get(),
+    EXPECT_EQ(test.expected, History::CanChangeToUrl(url, document_origin.get(),
                                                      document_url));
   }
 }
@@ -109,7 +109,7 @@
     KURL url(kParsedURLString, test.url);
     KURL document_url(kParsedURLString, test.document_url);
     RefPtr<SecurityOrigin> document_origin = SecurityOrigin::CreateUnique();
-    EXPECT_EQ(test.expected, History::CanChangeToUrl(url, document_origin.Get(),
+    EXPECT_EQ(test.expected, History::CanChangeToUrl(url, document_origin.get(),
                                                      document_url));
   }
 }
diff --git a/third_party/WebKit/Source/core/frame/Intervention.cpp b/third_party/WebKit/Source/core/frame/Intervention.cpp
index 8569bc2..4253392 100644
--- a/third_party/WebKit/Source/core/frame/Intervention.cpp
+++ b/third_party/WebKit/Source/core/frame/Intervention.cpp
@@ -7,9 +7,12 @@
 #include "core/frame/FrameConsole.h"
 #include "core/frame/InterventionReport.h"
 #include "core/frame/LocalFrame.h"
+#include "core/frame/LocalFrameClient.h"
 #include "core/frame/Report.h"
 #include "core/frame/ReportingContext.h"
 #include "core/inspector/ConsoleMessage.h"
+#include "public/platform/reporting.mojom-blink.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
 
 namespace blink {
 
@@ -26,16 +29,24 @@
   if (!frame->Client())
     return;
 
-  // Send the intervention report to any ReportingObservers.
   Document* document = frame->GetDocument();
-  ReportingContext* reporting_context = ReportingContext::From(document);
-  if (!reporting_context->ObserverExists())
-    return;
 
-  ReportBody* body = new InterventionReport(message, SourceLocation::Capture());
+  // Construct the intervention report.
+  InterventionReport* body =
+      new InterventionReport(message, SourceLocation::Capture());
   Report* report =
       new Report("intervention", document->Url().GetString(), body);
-  reporting_context->QueueReport(report);
+
+  // Send the intervention report to any ReportingObservers.
+  ReportingContext* reporting_context = ReportingContext::From(document);
+  if (reporting_context->ObserverExists())
+    reporting_context->QueueReport(report);
+
+  // Send the intervention report to the Reporting API.
+  mojom::blink::ReportingServiceProxyPtr service;
+  frame->Client()->GetInterfaceProvider()->GetInterface(&service);
+  service->QueueInterventionReport(document->Url(), message, body->sourceFile(),
+                                   body->lineNumber());
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/InterventionReport.h b/third_party/WebKit/Source/core/frame/InterventionReport.h
index 87ebcd9..f80005d 100644
--- a/third_party/WebKit/Source/core/frame/InterventionReport.h
+++ b/third_party/WebKit/Source/core/frame/InterventionReport.h
@@ -22,8 +22,10 @@
   ~InterventionReport() override {}
 
   String message() const { return message_; }
-  String sourceFile() const { return location_->Url(); }
   long lineNumber() const { return location_->LineNumber(); }
+  String sourceFile() const {
+    return location_->Url().IsNull() ? "" : location_->Url();
+  }
 
   DEFINE_INLINE_VIRTUAL_TRACE() { ReportBody::Trace(visitor); }
 
diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
index d20bf8dd..a45d02c8 100644
--- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
@@ -125,12 +125,12 @@
   }
 
   MessageEvent* Event() const { return event_; }
-  SecurityOrigin* TargetOrigin() const { return target_origin_.Get(); }
+  SecurityOrigin* TargetOrigin() const { return target_origin_.get(); }
   std::unique_ptr<SourceLocation> TakeLocation() {
     return std::move(location_);
   }
   UserGestureToken* GetUserGestureToken() const {
-    return user_gesture_token_.Get();
+    return user_gesture_token_.get();
   }
   void ContextDestroyed(ExecutionContext* destroyed_context) override {
     SuspendableTimer::ContextDestroyed(destroyed_context);
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
index 7d72605..2f71770 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
@@ -1199,9 +1199,9 @@
       ClearLayoutSubtreeRootsAndMarkContainingBlocks();
       Node* body = document->body();
       if (body && body->GetLayoutObject()) {
-        if (isHTMLFrameSetElement(*body)) {
+        if (IsHTMLFrameSetElement(*body)) {
           body->GetLayoutObject()->SetChildNeedsLayout();
-        } else if (isHTMLBodyElement(*body)) {
+        } else if (IsHTMLBodyElement(*body)) {
           if (!first_layout_ && size_.Height() != GetLayoutSize().Height() &&
               body->GetLayoutObject()->EnclosingBox()->StretchesToViewport())
             body->GetLayoutObject()->SetChildNeedsLayout();
@@ -1502,7 +1502,7 @@
   // Tell the DOM element that it needs a Plugin update.
   Node* node = object.GetNode();
   DCHECK(node);
-  if (isHTMLObjectElement(*node) || isHTMLEmbedElement(*node))
+  if (IsHTMLObjectElement(*node) || IsHTMLEmbedElement(*node))
     ToHTMLPlugInElement(node)->SetNeedsPluginUpdate(true);
 
   part_update_set_.insert(&object);
@@ -4175,7 +4175,7 @@
   GetFrame().Loader().SaveScrollState();
   DidChangeScrollOffset();
 
-  if (scroll_type == kCompositorScroll && frame_->IsMainFrame()) {
+  if (scroll_type == kCompositorScroll || scroll_type == kUserScroll) {
     if (DocumentLoader* document_loader = frame_->Loader().GetDocumentLoader())
       document_loader->GetInitialScrollState().was_scrolled_by_user = true;
   }
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.h b/third_party/WebKit/Source/core/frame/LocalFrameView.h
index fe610df2..4e3c5ab 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameView.h
+++ b/third_party/WebKit/Source/core/frame/LocalFrameView.h
@@ -725,23 +725,23 @@
     pre_translation_ = std::move(pre_translation);
   }
   TransformPaintPropertyNode* PreTranslation() const {
-    return pre_translation_.Get();
+    return pre_translation_.get();
   }
   void SetScrollNode(RefPtr<ScrollPaintPropertyNode> scroll_node) {
     scroll_node_ = std::move(scroll_node);
   }
-  ScrollPaintPropertyNode* ScrollNode() const { return scroll_node_.Get(); }
+  ScrollPaintPropertyNode* ScrollNode() const { return scroll_node_.get(); }
   void SetScrollTranslation(
       RefPtr<TransformPaintPropertyNode> scroll_translation) {
     scroll_translation_ = std::move(scroll_translation);
   }
   TransformPaintPropertyNode* ScrollTranslation() const {
-    return scroll_translation_.Get();
+    return scroll_translation_.get();
   }
   void SetContentClip(RefPtr<ClipPaintPropertyNode> content_clip) {
     content_clip_ = std::move(content_clip);
   }
-  ClipPaintPropertyNode* ContentClip() const { return content_clip_.Get(); }
+  ClipPaintPropertyNode* ContentClip() const { return content_clip_.get(); }
 
   // The property tree state that should be used for painting contents. These
   // properties are either created by this LocalFrameView or are inherited from
diff --git a/third_party/WebKit/Source/core/frame/Location.cpp b/third_party/WebKit/Source/core/frame/Location.cpp
index 9719fcf..c15d0d2 100644
--- a/third_party/WebKit/Source/core/frame/Location.cpp
+++ b/third_party/WebKit/Source/core/frame/Location.cpp
@@ -63,7 +63,7 @@
 }
 
 void Location::href(StringOrTrustedURL& result) const {
-  result.setString(Url().StrippedForUseAsHref());
+  result.SetString(Url().StrippedForUseAsHref());
 }
 
 String Location::protocol() const {
@@ -109,8 +109,8 @@
 String Location::toString() const {
   StringOrTrustedURL result;
   href(result);
-  DCHECK(result.isString());
-  return result.getAsString();
+  DCHECK(result.IsString());
+  return result.GetAsString();
 }
 
 String Location::hash() const {
@@ -121,19 +121,19 @@
                        LocalDOMWindow* entered_window,
                        const StringOrTrustedURL& stringOrUrl,
                        ExceptionState& exception_state) {
-  DCHECK(stringOrUrl.isString() ||
+  DCHECK(stringOrUrl.IsString() ||
          RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
 
-  if (stringOrUrl.isString() &&
+  if (stringOrUrl.IsString() &&
       current_window->document()->RequireTrustedTypes()) {
     exception_state.ThrowTypeError(
         "This document requires `TrustedURL` assignment.");
     return;
   }
 
-  String url = stringOrUrl.isString()
-                   ? stringOrUrl.getAsString()
-                   : stringOrUrl.getAsTrustedURL()->toString();
+  String url = stringOrUrl.IsString()
+                   ? stringOrUrl.GetAsString()
+                   : stringOrUrl.GetAsTrustedURL()->toString();
   SetLocation(url, current_window, entered_window, &exception_state);
 }
 
diff --git a/third_party/WebKit/Source/core/frame/MHTMLTest.cpp b/third_party/WebKit/Source/core/frame/MHTMLTest.cpp
index 638ee8b..9e3278c 100644
--- a/third_party/WebKit/Source/core/frame/MHTMLTest.cpp
+++ b/third_party/WebKit/Source/core/frame/MHTMLTest.cpp
@@ -304,16 +304,16 @@
 
   // MHTMLArchives can only be initialized from local schemes, http/https
   // schemes, and content scheme(Android specific).
-  EXPECT_NE(nullptr, MHTMLArchive::Create(http_url, data.Get()));
+  EXPECT_NE(nullptr, MHTMLArchive::Create(http_url, data.get()));
 #if defined(OS_ANDROID)
-  EXPECT_NE(nullptr, MHTMLArchive::Create(content_url, data.Get()));
+  EXPECT_NE(nullptr, MHTMLArchive::Create(content_url, data.get()));
 #else
-  EXPECT_EQ(nullptr, MHTMLArchive::Create(content_url, data.Get()));
+  EXPECT_EQ(nullptr, MHTMLArchive::Create(content_url, data.get()));
 #endif
-  EXPECT_NE(nullptr, MHTMLArchive::Create(file_url, data.Get()));
-  EXPECT_EQ(nullptr, MHTMLArchive::Create(special_scheme_url, data.Get()));
+  EXPECT_NE(nullptr, MHTMLArchive::Create(file_url, data.get()));
+  EXPECT_EQ(nullptr, MHTMLArchive::Create(special_scheme_url, data.get()));
   SchemeRegistry::RegisterURLSchemeAsLocal("fooscheme");
-  EXPECT_NE(nullptr, MHTMLArchive::Create(special_scheme_url, data.Get()));
+  EXPECT_NE(nullptr, MHTMLArchive::Create(special_scheme_url, data.get()));
 }
 
 // Checks that full sandboxing protection has been turned on.
diff --git a/third_party/WebKit/Source/core/frame/SmartClip.cpp b/third_party/WebKit/Source/core/frame/SmartClip.cpp
index 6e0e9a1..4a0970c 100644
--- a/third_party/WebKit/Source/core/frame/SmartClip.cpp
+++ b/third_party/WebKit/Source/core/frame/SmartClip.cpp
@@ -204,7 +204,7 @@
 bool SmartClip::ShouldSkipBackgroundImage(Node* node) {
   DCHECK(node);
   // Apparently we're only interested in background images on spans and divs.
-  if (!isHTMLSpanElement(*node) && !isHTMLDivElement(*node))
+  if (!IsHTMLSpanElement(*node) && !IsHTMLDivElement(*node))
     return true;
 
   // This check actually makes a bit of sense. If you're going to sprite an
diff --git a/third_party/WebKit/Source/core/frame/SuspendableScriptExecutor.cpp b/third_party/WebKit/Source/core/frame/SuspendableScriptExecutor.cpp
index 176f968..ac7ba88 100644
--- a/third_party/WebKit/Source/core/frame/SuspendableScriptExecutor.cpp
+++ b/third_party/WebKit/Source/core/frame/SuspendableScriptExecutor.cpp
@@ -217,7 +217,7 @@
   if (callback_)
     callback_->WillExecute();
 
-  ScriptState::Scope script_scope(script_state_.Get());
+  ScriptState::Scope script_scope(script_state_.get());
   Vector<v8::Local<v8::Value>> results =
       executor_->Execute(ToDocument(GetExecutionContext())->GetFrame());
 
diff --git a/third_party/WebKit/Source/core/frame/WebFrameSerializerImpl.cpp b/third_party/WebKit/Source/core/frame/WebFrameSerializerImpl.cpp
index 1ddc652..761f454 100644
--- a/third_party/WebKit/Source/core/frame/WebFrameSerializerImpl.cpp
+++ b/third_party/WebKit/Source/core/frame/WebFrameSerializerImpl.cpp
@@ -129,13 +129,13 @@
     // have overrided the META which have correct charset declaration after
     // serializing open tag of HEAD element.
     DCHECK(element);
-    if (isHTMLMetaElement(element) &&
+    if (IsHTMLMetaElement(element) &&
         toHTMLMetaElement(element)->ComputeEncoding().IsValid()) {
       // Found META tag declared charset, we need to skip it when
       // serializing DOM.
       param->skip_meta_element = element;
       *need_skip = true;
-    } else if (isHTMLHtmlElement(*element)) {
+    } else if (IsHTMLHtmlElement(*element)) {
       // Check something before processing the open tag of HEAD element.
       // First we add doc type declaration if original document has it.
       if (!param->have_seen_doc_type) {
@@ -147,7 +147,7 @@
       // See http://msdn2.microsoft.com/en-us/library/ms537628(VS.85).aspx.
       result.Append(
           WebFrameSerializer::GenerateMarkOfTheWebDeclaration(param->url));
-    } else if (isHTMLBaseElement(*element)) {
+    } else if (IsHTMLBaseElement(*element)) {
       // Comment the BASE tag when serializing dom.
       result.Append("<!--");
     }
@@ -187,7 +187,7 @@
   if (!param->is_html_document)
     return result.ToString();
   // Check after processing the open tag of HEAD element
-  if (!param->have_added_charset_declaration && isHTMLHeadElement(*element)) {
+  if (!param->have_added_charset_declaration && IsHTMLHeadElement(*element)) {
     param->have_added_charset_declaration = true;
     // Check meta element. WebKit only pre-parse the first 512 bytes of the
     // document. If the whole <HEAD> is larger and meta is the end of head
@@ -236,7 +236,7 @@
   if (!param->is_html_document)
     return result.ToString();
   // Comment the BASE tag when serializing DOM.
-  if (isHTMLBaseElement(*element)) {
+  if (IsHTMLBaseElement(*element)) {
     result.Append("-->");
     // Append a new base tag declaration.
     result.Append(WebFrameSerializer::GenerateBaseTagDeclaration(
@@ -351,7 +351,7 @@
   // is written even if the original document didn't have that attribute
   // (mainly needed for iframes with srcdoc, but with no src attribute).
   if (should_rewrite_frame_src && !did_rewrite_frame_src &&
-      isHTMLIFrameElement(element)) {
+      IsHTMLIFrameElement(element)) {
     AppendAttribute(result, param->is_html_document,
                     HTMLNames::srcAttr.ToString(), rewritten_frame_link);
   }
diff --git a/third_party/WebKit/Source/core/frame/WebFrameWidgetImpl.cpp b/third_party/WebKit/Source/core/frame/WebFrameWidgetImpl.cpp
index 889eea2..21cd870 100644
--- a/third_party/WebKit/Source/core/frame/WebFrameWidgetImpl.cpp
+++ b/third_party/WebKit/Source/core/frame/WebFrameWidgetImpl.cpp
@@ -819,7 +819,7 @@
   }
 
   if (view_impl->GetPagePopup() && page_popup &&
-      view_impl->GetPagePopup()->HasSamePopupClient(page_popup.Get())) {
+      view_impl->GetPagePopup()->HasSamePopupClient(page_popup.get())) {
     // That click triggered a page popup that is the same as the one we just
     // closed.  It needs to be closed.
     view_impl->HidePopups();
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
index eedcf27..8d88a12 100644
--- a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
+++ b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
@@ -136,6 +136,7 @@
 #include "core/exported/WebPluginContainerImpl.h"
 #include "core/exported/WebRemoteFrameImpl.h"
 #include "core/exported/WebViewImpl.h"
+#include "core/frame/FrameConsole.h"
 #include "core/frame/LocalDOMWindow.h"
 #include "core/frame/LocalFrameView.h"
 #include "core/frame/PageScaleConstraintsSet.h"
@@ -158,6 +159,7 @@
 #include "core/html/HTMLInputElement.h"
 #include "core/html/HTMLLinkElement.h"
 #include "core/html/PluginDocument.h"
+#include "core/input/ContextMenuAllowedScope.h"
 #include "core/input/EventHandler.h"
 #include "core/inspector/ConsoleMessage.h"
 #include "core/layout/HitTestResult.h"
@@ -711,10 +713,18 @@
       break;
   }
 
-  GetFrame()->GetDocument()->AddConsoleMessage(ConsoleMessage::Create(
-      kOtherMessageSource, web_core_message_level, message.text,
+  MessageSource message_source = message.nodes.empty()
+                                     ? kOtherMessageSource
+                                     : kRecommendationMessageSource;
+  Vector<DOMNodeId> nodes;
+  for (const blink::WebNode& web_node : message.nodes)
+    nodes.push_back(DOMNodeIds::IdForNode(&(*web_node)));
+  ConsoleMessage* console_message = ConsoleMessage::Create(
+      message_source, web_core_message_level, message.text,
       SourceLocation::Create(message.url, message.line_number,
-                             message.column_number, nullptr)));
+                             message.column_number, nullptr));
+  console_message->SetNodes(std::move(nodes));
+  GetFrame()->GetDocument()->AddConsoleMessage(console_message);
 }
 
 void WebLocalFrameImpl::CollectGarbage() {
@@ -871,10 +881,8 @@
 
 void WebLocalFrameImpl::ReloadImage(const WebNode& web_node) {
   const Node* node = web_node.ConstUnwrap<Node>();
-  if (isHTMLImageElement(*node)) {
-    const HTMLImageElement& image_element = toHTMLImageElement(*node);
-    image_element.ForceReload();
-  }
+  if (auto* image_element = ToHTMLImageElementOrNull(*node))
+    image_element->ForceReload();
 }
 
 void WebLocalFrameImpl::ReloadLoFiImages() {
@@ -1198,7 +1206,8 @@
 
 void WebLocalFrameImpl::SelectRange(
     const WebRange& web_range,
-    HandleVisibilityBehavior handle_visibility_behavior) {
+    HandleVisibilityBehavior handle_visibility_behavior,
+    blink::mojom::SelectionMenuBehavior selection_menu_behavior) {
   TRACE_EVENT0("blink", "WebLocalFrameImpl::selectRange");
 
   // TODO(editing-dev): The use of updateStyleAndLayoutIgnorePendingStylesheets
@@ -1221,6 +1230,12 @@
           .SetIsDirectional(false)
           .Build(),
       SetSelectionOptions::Builder().SetShouldShowHandle(show_handles).Build());
+
+  if (selection_menu_behavior == blink::mojom::SelectionMenuBehavior::kShow) {
+    ContextMenuAllowedScope scope;
+    GetFrame()->GetEventHandler().ShowNonLocatedContextMenu(
+        nullptr, kMenuSourceAdjustSelection);
+  }
 }
 
 WebString WebLocalFrameImpl::RangeAsText(const WebRange& web_range) {
@@ -1961,8 +1976,8 @@
   DCHECK(GetFrame());
   DCHECK(context_menu_node_.Get());
   Element* anchor = context_menu_node_->EnclosingLinkEventParentOrSelf();
-  if (isHTMLAnchorElement(anchor))
-    toHTMLAnchorElement(anchor)->SendPings(destination_url);
+  if (auto* html_anchor = ToHTMLAnchorElementOrNull(anchor))
+    html_anchor->SendPings(destination_url);
 }
 
 bool WebLocalFrameImpl::DispatchBeforeUnloadEvent(bool is_reload) {
@@ -2391,7 +2406,7 @@
 
 void WebLocalFrameImpl::CopyImageAt(const WebPoint& pos_in_viewport) {
   HitTestResult result = HitTestResultForVisualViewportPos(pos_in_viewport);
-  if (!isHTMLCanvasElement(result.InnerNodeOrImageMapImage()) &&
+  if (!IsHTMLCanvasElement(result.InnerNodeOrImageMapImage()) &&
       result.AbsoluteImageURL().IsEmpty()) {
     // There isn't actually an image at these coordinates.  Might be because
     // the window scrolled while the context menu was open or because the page
@@ -2413,7 +2428,7 @@
 void WebLocalFrameImpl::SaveImageAt(const WebPoint& pos_in_viewport) {
   Node* node = HitTestResultForVisualViewportPos(pos_in_viewport)
                    .InnerNodeOrImageMapImage();
-  if (!node || !(isHTMLCanvasElement(*node) || isHTMLImageElement(*node)))
+  if (!node || !(IsHTMLCanvasElement(*node) || IsHTMLImageElement(*node)))
     return;
 
   String url = ToElement(*node).ImageSourceURL();
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h
index 9c84273..93c7b5c 100644
--- a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h
+++ b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h
@@ -190,7 +190,8 @@
   bool SelectWordAroundCaret() override;
   void SelectRange(const WebPoint& base, const WebPoint& extent) override;
   void SelectRange(const WebRange&,
-                   HandleVisibilityBehavior = kHideSelectionHandle) override;
+                   HandleVisibilityBehavior,
+                   blink::mojom::SelectionMenuBehavior) override;
   WebString RangeAsText(const WebRange&) override;
   void MoveRangeSelectionExtent(const WebPoint&) override;
   void MoveRangeSelection(
diff --git a/third_party/WebKit/Source/core/frame/WebViewFrameWidget.cpp b/third_party/WebKit/Source/core/frame/WebViewFrameWidget.cpp
index 7e15b777..3e2abb1 100644
--- a/third_party/WebKit/Source/core/frame/WebViewFrameWidget.cpp
+++ b/third_party/WebKit/Source/core/frame/WebViewFrameWidget.cpp
@@ -252,7 +252,7 @@
 }
 
 PageWidgetEventHandler* WebViewFrameWidget::GetPageWidgetEventHandler() {
-  return web_view_.Get();
+  return web_view_.get();
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/csp/CSPDirectiveList.cpp b/third_party/WebKit/Source/core/frame/csp/CSPDirectiveList.cpp
index eb89c29..d4c1a10 100644
--- a/third_party/WebKit/Source/core/frame/csp/CSPDirectiveList.cpp
+++ b/third_party/WebKit/Source/core/frame/csp/CSPDirectiveList.cpp
@@ -611,7 +611,7 @@
   SourceListDirective* directive = OperativeDirective(script_src_.Get());
   if (IsMatchingNoncePresent(directive, nonce))
     return true;
-  if (element && isHTMLScriptElement(element) &&
+  if (element && IsHTMLScriptElement(element) &&
       !toHTMLScriptElement(element)->Loader()->IsParserInserted() &&
       AllowDynamic()) {
     return true;
diff --git a/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp b/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp
index 8f01b049..78cee2c 100644
--- a/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp
+++ b/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp
@@ -294,7 +294,7 @@
     return true;
   }
 
-  if (parent_origin->CanAccess(SecurityOrigin::Create(response.Url()).Get()))
+  if (parent_origin->CanAccess(SecurityOrigin::Create(response.Url()).get()))
     return true;
 
   String header = response.HttpHeaderField(HTTPNames::Allow_CSP_From);
@@ -303,7 +303,7 @@
     return true;
   if (RefPtr<SecurityOrigin> child_origin =
           SecurityOrigin::CreateFromString(header)) {
-    return parent_origin->CanAccess(child_origin.Get());
+    return parent_origin->CanAccess(child_origin.get());
   }
 
   return false;
diff --git a/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicyTest.cpp b/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicyTest.cpp
index f6911b0..fa41fd4 100644
--- a/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicyTest.cpp
+++ b/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicyTest.cpp
@@ -942,29 +942,29 @@
     ResourceResponse response;
     response.SetURL(KURL(kParsedURLString, test.resource_url));
     EXPECT_EQ(ContentSecurityPolicy::ShouldEnforceEmbeddersPolicy(
-                  response, secure_origin.Get()),
+                  response, secure_origin.get()),
               test.inherits);
 
     response.SetHTTPHeaderField(HTTPNames::Allow_CSP_From, AtomicString("*"));
     EXPECT_TRUE(ContentSecurityPolicy::ShouldEnforceEmbeddersPolicy(
-        response, secure_origin.Get()));
+        response, secure_origin.get()));
 
     response.SetHTTPHeaderField(HTTPNames::Allow_CSP_From,
                                 AtomicString("* not a valid header"));
     EXPECT_EQ(ContentSecurityPolicy::ShouldEnforceEmbeddersPolicy(
-                  response, secure_origin.Get()),
+                  response, secure_origin.get()),
               test.inherits);
 
     response.SetHTTPHeaderField(HTTPNames::Allow_CSP_From,
                                 AtomicString("http://example.test"));
     EXPECT_EQ(ContentSecurityPolicy::ShouldEnforceEmbeddersPolicy(
-                  response, secure_origin.Get()),
+                  response, secure_origin.get()),
               test.inherits);
 
     response.SetHTTPHeaderField(HTTPNames::Allow_CSP_From,
                                 AtomicString("https://example.test"));
     EXPECT_TRUE(ContentSecurityPolicy::ShouldEnforceEmbeddersPolicy(
-        response, secure_origin.Get()));
+        response, secure_origin.get()));
   }
 }
 
diff --git a/third_party/WebKit/Source/core/fullscreen/Fullscreen.cpp b/third_party/WebKit/Source/core/fullscreen/Fullscreen.cpp
index 4e67a3a9..71f7146 100644
--- a/third_party/WebKit/Source/core/fullscreen/Fullscreen.cpp
+++ b/third_party/WebKit/Source/core/fullscreen/Fullscreen.cpp
@@ -167,7 +167,11 @@
 bool RequestFullscreenConditionsMet(Element& pending, Document& document) {
   // |pending|'s namespace is the HTML namespace or |pending| is an SVG svg or
   // MathML math element. Note: MathML is not supported.
-  if (!pending.IsHTMLElement() && !isSVGSVGElement(pending))
+  if (!pending.IsHTMLElement() && !IsSVGSVGElement(pending))
+    return false;
+
+  // |pending| is not a dialog element.
+  if (IsHTMLDialogElement(pending))
     return false;
 
   // The fullscreen element ready check for |pending| returns false.
@@ -482,20 +486,6 @@
                         WebFeature::kFullscreenRequestWithPendingElement);
     }
 
-    // TODO(foolip): In order to reinstate the hierarchy restrictions in the
-    // spec, something has to prevent dialog elements from moving within top
-    // layer. Either disallowing fullscreen for dialog elements entirely or just
-    // preventing dialog elements from simultaneously being fullscreen and modal
-    // are good candidates. See https://github.com/whatwg/fullscreen/pull/91
-    if (isHTMLDialogElement(pending)) {
-      UseCounter::Count(document,
-                        WebFeature::kRequestFullscreenForDialogElement);
-      if (pending.IsInTopLayer()) {
-        UseCounter::Count(
-            document, WebFeature::kRequestFullscreenForDialogElementInTopLayer);
-      }
-    }
-
     From(document).pending_requests_.push_back(
         std::make_pair(&pending, request_type));
     LocalFrame& frame = *document.GetFrame();
@@ -872,7 +862,7 @@
     // the iframe element for the out-of-process frame that contains the
     // fullscreen element. Hence, it must match :-webkit-full-screen-ancestor.
     if (new_request_type == RequestType::kPrefixedForCrossProcessDescendant) {
-      DCHECK(isHTMLIFrameElement(new_element));
+      DCHECK(IsHTMLIFrameElement(new_element));
       new_element->SetContainsFullScreenElement(true);
     }
     new_element->SetContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(
diff --git a/third_party/WebKit/Source/core/geometry/DOMMatrix.cpp b/third_party/WebKit/Source/core/geometry/DOMMatrix.cpp
index 39611e3..451753d 100644
--- a/third_party/WebKit/Source/core/geometry/DOMMatrix.cpp
+++ b/third_party/WebKit/Source/core/geometry/DOMMatrix.cpp
@@ -20,7 +20,7 @@
 DOMMatrix* DOMMatrix::Create(ExecutionContext* execution_context,
                              StringOrUnrestrictedDoubleSequence& init,
                              ExceptionState& exception_state) {
-  if (init.isString()) {
+  if (init.IsString()) {
     if (!execution_context->IsDocument()) {
       exception_state.ThrowTypeError(
           "DOMMatrix can't be constructed with strings on workers.");
@@ -28,12 +28,12 @@
     }
 
     DOMMatrix* matrix = new DOMMatrix(TransformationMatrix());
-    matrix->SetMatrixValueFromString(init.getAsString(), exception_state);
+    matrix->SetMatrixValueFromString(init.GetAsString(), exception_state);
     return matrix;
   }
 
-  if (init.isUnrestrictedDoubleSequence()) {
-    const Vector<double>& sequence = init.getAsUnrestrictedDoubleSequence();
+  if (init.IsUnrestrictedDoubleSequence()) {
+    const Vector<double>& sequence = init.GetAsUnrestrictedDoubleSequence();
     if (sequence.size() != 6 && sequence.size() != 16) {
       exception_state.ThrowTypeError(
           "The sequence must contain 6 elements for a 2D matrix or 16 elements "
diff --git a/third_party/WebKit/Source/core/geometry/DOMMatrixReadOnly.cpp b/third_party/WebKit/Source/core/geometry/DOMMatrixReadOnly.cpp
index 97ffd3a..1ac5c6d 100644
--- a/third_party/WebKit/Source/core/geometry/DOMMatrixReadOnly.cpp
+++ b/third_party/WebKit/Source/core/geometry/DOMMatrixReadOnly.cpp
@@ -117,7 +117,7 @@
     ExecutionContext* execution_context,
     StringOrUnrestrictedDoubleSequence& init,
     ExceptionState& exception_state) {
-  if (init.isString()) {
+  if (init.IsString()) {
     if (!execution_context->IsDocument()) {
       exception_state.ThrowTypeError(
           "DOMMatrix can't be constructed with strings on workers.");
@@ -125,12 +125,12 @@
     }
 
     DOMMatrixReadOnly* matrix = new DOMMatrixReadOnly(TransformationMatrix());
-    matrix->SetMatrixValueFromString(init.getAsString(), exception_state);
+    matrix->SetMatrixValueFromString(init.GetAsString(), exception_state);
     return matrix;
   }
 
-  if (init.isUnrestrictedDoubleSequence()) {
-    const Vector<double>& sequence = init.getAsUnrestrictedDoubleSequence();
+  if (init.IsUnrestrictedDoubleSequence()) {
+    const Vector<double>& sequence = init.GetAsUnrestrictedDoubleSequence();
     if (sequence.size() != 6 && sequence.size() != 16) {
       exception_state.ThrowTypeError(
           "The sequence must contain 6 elements for a 2D matrix or 16 elements "
diff --git a/third_party/WebKit/Source/core/html/DocumentNameCollection.cpp b/third_party/WebKit/Source/core/html/DocumentNameCollection.cpp
index 0d8615bf..e8158e8e 100644
--- a/third_party/WebKit/Source/core/html/DocumentNameCollection.cpp
+++ b/third_party/WebKit/Source/core/html/DocumentNameCollection.cpp
@@ -18,13 +18,13 @@
   // Match images, forms, embeds, objects and iframes by name,
   // object by id, and images by id but only if they have
   // a name attribute (this very strange rule matches IE)
-  if (isHTMLFormElement(element) || isHTMLIFrameElement(element) ||
-      (isHTMLEmbedElement(element) && toHTMLEmbedElement(element).IsExposed()))
+  if (IsHTMLFormElement(element) || IsHTMLIFrameElement(element) ||
+      (IsHTMLEmbedElement(element) && toHTMLEmbedElement(element).IsExposed()))
     return element.GetNameAttribute() == name_;
-  if (isHTMLObjectElement(element) && toHTMLObjectElement(element).IsExposed())
+  if (IsHTMLObjectElement(element) && toHTMLObjectElement(element).IsExposed())
     return element.GetNameAttribute() == name_ ||
            element.GetIdAttribute() == name_;
-  if (isHTMLImageElement(element)) {
+  if (IsHTMLImageElement(element)) {
     const AtomicString& name_value = element.GetNameAttribute();
     return name_value == name_ ||
            (element.GetIdAttribute() == name_ && !name_value.IsEmpty());
diff --git a/third_party/WebKit/Source/core/html/FormData.cpp b/third_party/WebKit/Source/core/html/FormData.cpp
index f1c9c51..d410567c 100644
--- a/third_party/WebKit/Source/core/html/FormData.cpp
+++ b/third_party/WebKit/Source/core/html/FormData.cpp
@@ -60,10 +60,10 @@
     const FormData::Entry& entry = *form_data_->Entries()[current_++];
     name = form_data_->Decode(entry.name());
     if (entry.IsString()) {
-      value.setUSVString(form_data_->Decode(entry.Value()));
+      value.SetUSVString(form_data_->Decode(entry.Value()));
     } else {
       DCHECK(entry.isFile());
-      value.setFile(entry.GetFile());
+      value.SetFile(entry.GetFile());
     }
     return true;
   }
@@ -130,10 +130,10 @@
   for (const auto& entry : Entries()) {
     if (entry->name() == encoded_name) {
       if (entry->IsString()) {
-        result.setUSVString(Decode(entry->Value()));
+        result.SetUSVString(Decode(entry->Value()));
       } else {
         DCHECK(entry->isFile());
-        result.setFile(entry->GetFile());
+        result.SetFile(entry->GetFile());
       }
       return;
     }
@@ -149,10 +149,10 @@
       continue;
     FormDataEntryValue value;
     if (entry->IsString()) {
-      value.setUSVString(Decode(entry->Value()));
+      value.SetUSVString(Decode(entry->Value()));
     } else {
       DCHECK(entry->isFile());
-      value.setFile(entry->GetFile());
+      value.SetFile(entry->GetFile());
     }
     results.push_back(value);
   }
diff --git a/third_party/WebKit/Source/core/html/FormData.h b/third_party/WebKit/Source/core/html/FormData.h
index 3118748..03b3775 100644
--- a/third_party/WebKit/Source/core/html/FormData.h
+++ b/third_party/WebKit/Source/core/html/FormData.h
@@ -55,7 +55,7 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static FormData* Create(HTMLFormElement* form = 0) {
+  static FormData* Create(HTMLFormElement* form = nullptr) {
     return new FormData(form);
   }
 
diff --git a/third_party/WebKit/Source/core/html/FormDataTest.cpp b/third_party/WebKit/Source/core/html/FormDataTest.cpp
index 9f74c20a..1dfeebd 100644
--- a/third_party/WebKit/Source/core/html/FormDataTest.cpp
+++ b/third_party/WebKit/Source/core/html/FormDataTest.cpp
@@ -14,8 +14,8 @@
 
   FileOrUSVString result;
   fd->get("name1", result);
-  EXPECT_TRUE(result.isUSVString());
-  EXPECT_EQ("value1", result.getAsUSVString());
+  EXPECT_TRUE(result.IsUSVString());
+  EXPECT_EQ("value1", result.GetAsUSVString());
 
   const FormData::Entry& entry = *fd->Entries()[0];
   EXPECT_STREQ("name1", entry.name().data());
@@ -28,8 +28,8 @@
 
   HeapVector<FormDataEntryValue> results = fd->getAll("name1");
   EXPECT_EQ(1u, results.size());
-  EXPECT_TRUE(results[0].isUSVString());
-  EXPECT_EQ("value1", results[0].getAsUSVString());
+  EXPECT_TRUE(results[0].IsUSVString());
+  EXPECT_EQ("value1", results[0].GetAsUSVString());
 
   EXPECT_EQ(1u, fd->size());
 }
diff --git a/third_party/WebKit/Source/core/html/HTMLAllCollection.cpp b/third_party/WebKit/Source/core/html/HTMLAllCollection.cpp
index 49f8075..2165bd0b 100644
--- a/third_party/WebKit/Source/core/html/HTMLAllCollection.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLAllCollection.cpp
@@ -70,13 +70,13 @@
     return;
 
   if (named_items.size() == 1) {
-    return_value.setElement(named_items.at(0));
+    return_value.SetElement(named_items.at(0));
     return;
   }
 
   // FIXME: HTML5 specification says this should be a HTMLCollection.
   // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#htmlallcollection
-  return_value.setNodeList(StaticElementList::Adopt(named_items));
+  return_value.SetNodeList(StaticElementList::Adopt(named_items));
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/HTMLAnchorElement.cpp b/third_party/WebKit/Source/core/html/HTMLAnchorElement.cpp
index aa810e91..42ebf61 100644
--- a/third_party/WebKit/Source/core/html/HTMLAnchorElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLAnchorElement.cpp
@@ -120,7 +120,7 @@
   DCHECK(event->target());
   Node* target = event->target()->ToNode();
   DCHECK(target);
-  if (!isHTMLImageElement(*target))
+  if (!IsHTMLImageElement(*target))
     return;
 
   HTMLImageElement& image_element = toHTMLImageElement(*target);
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
index 5e6a215..cad6afda6 100644
--- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
@@ -613,7 +613,7 @@
 
   if (PlaceholderFrame()) {
     DCHECK(GetDocument().Printing());
-    context.DrawImage(PlaceholderFrame().Get(), PixelSnappedIntRect(r));
+    context.DrawImage(PlaceholderFrame().get(), PixelSnappedIntRect(r));
     return;
   }
 
@@ -1415,36 +1415,34 @@
 
   // An a element that represents a hyperlink and that does not have any img
   // descendants.
-  if (isHTMLAnchorElement(element))
+  if (IsHTMLAnchorElement(element))
     return !Traversal<HTMLImageElement>::FirstWithin(element);
 
   // A button element
-  if (isHTMLButtonElement(element))
+  if (IsHTMLButtonElement(element))
     return true;
 
   // An input element whose type attribute is in one of the Checkbox or Radio
   // Button states.  An input element that is a button but its type attribute is
   // not in the Image Button state.
-  if (isHTMLInputElement(element)) {
-    const HTMLInputElement& input_element = toHTMLInputElement(element);
-    if (input_element.type() == InputTypeNames::checkbox ||
-        input_element.type() == InputTypeNames::radio ||
-        input_element.IsTextButton())
+  if (auto* input_element = ToHTMLInputElementOrNull(element)) {
+    if (input_element->type() == InputTypeNames::checkbox ||
+        input_element->type() == InputTypeNames::radio ||
+        input_element->IsTextButton())
       return true;
   }
 
   // A select element with a "multiple" attribute or with a display size greater
   // than 1.
-  if (isHTMLSelectElement(element)) {
-    const HTMLSelectElement& select_element = toHTMLSelectElement(element);
-    if (select_element.IsMultiple() || select_element.size() > 1)
+  if (auto* select_element = ToHTMLSelectElementOrNull(element)) {
+    if (select_element->IsMultiple() || select_element->size() > 1)
       return true;
   }
 
   // An option element that is in a list of options of a select element with a
   // "multiple" attribute or with a display size greater than 1.
-  if (isHTMLOptionElement(element) && element.parentNode() &&
-      isHTMLSelectElement(*element.parentNode())) {
+  if (IsHTMLOptionElement(element) && element.parentNode() &&
+      IsHTMLSelectElement(*element.parentNode())) {
     const HTMLSelectElement& select_element =
         toHTMLSelectElement(*element.parentNode());
     if (select_element.IsMultiple() || select_element.size() > 1)
@@ -1458,7 +1456,7 @@
 
   // A non-interactive table, caption, thead, tbody, tfoot, tr, td, or th
   // element.
-  if (isHTMLTableElement(element) ||
+  if (IsHTMLTableElement(element) ||
       element.HasTagName(HTMLNames::captionTag) ||
       element.HasTagName(HTMLNames::theadTag) ||
       element.HasTagName(HTMLNames::tbodyTag) ||
diff --git a/third_party/WebKit/Source/core/html/HTMLCollection.cpp b/third_party/WebKit/Source/core/html/HTMLCollection.cpp
index 4f509ba..60b067d 100644
--- a/third_party/WebKit/Source/core/html/HTMLCollection.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLCollection.cpp
@@ -109,9 +109,9 @@
     case kMapAreas:
       return NodeListRootType::kNode;
     case kFormControls:
-      if (isHTMLFieldSetElement(owner))
+      if (IsHTMLFieldSetElement(owner))
         return NodeListRootType::kNode;
-      DCHECK(isHTMLFormElement(owner));
+      DCHECK(IsHTMLFormElement(owner));
       return NodeListRootType::kTreeScope;
     case kNameNodeListType:
     case kRadioNodeListType:
@@ -225,7 +225,7 @@
     case kSelectOptions:
       return ToHTMLOptionsCollection(html_collection).ElementMatches(element);
     case kSelectedOptions:
-      return isHTMLOptionElement(element) &&
+      return IsHTMLOptionElement(element) &&
              toHTMLOptionElement(element).Selected();
     case kDataListOptions:
       return ToHTMLDataListOptionsCollection(html_collection)
@@ -233,7 +233,7 @@
     case kMapAreas:
       return element.HasTagName(areaTag);
     case kDocApplets:
-      return isHTMLObjectElement(element) &&
+      return IsHTMLObjectElement(element) &&
              toHTMLObjectElement(element).ContainsJavaApplet();
     case kDocEmbeds:
       return element.HasTagName(embedTag);
@@ -243,8 +243,8 @@
     case kDocAnchors:
       return element.HasTagName(aTag) && element.FastHasAttribute(nameAttr);
     case kFormControls:
-      DCHECK(isHTMLFieldSetElement(html_collection.ownerNode()));
-      return isHTMLObjectElement(element) || IsHTMLFormControlElement(element);
+      DCHECK(IsHTMLFieldSetElement(html_collection.ownerNode()));
+      return IsHTMLObjectElement(element) || IsHTMLFormControlElement(element);
     case kClassCollectionType:
     case kTagCollectionType:
     case kTagCollectionNSType:
diff --git a/third_party/WebKit/Source/core/html/HTMLDataListOptionsCollection.h b/third_party/WebKit/Source/core/html/HTMLDataListOptionsCollection.h
index 23d8829..65534470 100644
--- a/third_party/WebKit/Source/core/html/HTMLDataListOptionsCollection.h
+++ b/third_party/WebKit/Source/core/html/HTMLDataListOptionsCollection.h
@@ -39,7 +39,7 @@
 
 inline bool HTMLDataListOptionsCollection::ElementMatches(
     const HTMLElement& element) const {
-  return isHTMLOptionElement(element);
+  return IsHTMLOptionElement(element);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/HTMLDetailsElement.cpp b/third_party/WebKit/Source/core/html/HTMLDetailsElement.cpp
index a1f15fa..6a11b10 100644
--- a/third_party/WebKit/Source/core/html/HTMLDetailsElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLDetailsElement.cpp
@@ -116,7 +116,7 @@
   HTMLContentElement* content =
       toHTMLContentElementOrDie(UserAgentShadowRoot()->firstChild());
   DCHECK(content->firstChild());
-  CHECK(isHTMLSummaryElement(*content->firstChild()));
+  CHECK(IsHTMLSummaryElement(*content->firstChild()));
   return ToElement(content->firstChild());
 }
 
diff --git a/third_party/WebKit/Source/core/html/HTMLDialogElement.cpp b/third_party/WebKit/Source/core/html/HTMLDialogElement.cpp
index 4441ade..54097f34 100644
--- a/third_party/WebKit/Source/core/html/HTMLDialogElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLDialogElement.cpp
@@ -50,7 +50,7 @@
   // currently specified.  This may change at any time.
   // See crbug/383230 and https://github.com/whatwg/html/issues/2393 .
   for (Node* node = FlatTreeTraversal::FirstChild(*dialog); node; node = next) {
-    next = isHTMLDialogElement(*node)
+    next = IsHTMLDialogElement(*node)
                ? FlatTreeTraversal::NextSkippingChildren(*node, dialog)
                : FlatTreeTraversal::Next(*node, dialog);
 
diff --git a/third_party/WebKit/Source/core/html/HTMLDocument.cpp b/third_party/WebKit/Source/core/html/HTMLDocument.cpp
index f71db5c3c..6e1b135 100644
--- a/third_party/WebKit/Source/core/html/HTMLDocument.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLDocument.cpp
@@ -76,8 +76,7 @@
 HTMLDocument::~HTMLDocument() {}
 
 HTMLBodyElement* HTMLDocument::HtmlBodyElement() const {
-  HTMLElement* body = this->body();
-  return isHTMLBodyElement(body) ? toHTMLBodyElement(body) : 0;
+  return ToHTMLBodyElementOrNull(body());
 }
 
 const AtomicString& HTMLDocument::BodyAttributeValue(
diff --git a/third_party/WebKit/Source/core/html/HTMLElement.cpp b/third_party/WebKit/Source/core/html/HTMLElement.cpp
index 0f583de6..0217f1c 100644
--- a/third_party/WebKit/Source/core/html/HTMLElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLElement.cpp
@@ -114,7 +114,7 @@
     return false;
   if (node.IsHTMLElement())
     return true;
-  if (isSVGSVGElement(node))
+  if (IsSVGSVGElement(node))
     return true;
   if (node.IsElementNode() && ToElement(node).HasTagName(MathMLNames::mathTag))
     return true;
@@ -202,9 +202,9 @@
     // FIXME: Remove the following UseCounter code when we collect enough
     // data.
     UseCounter::Count(GetDocument(), WebFeature::kLangAttribute);
-    if (isHTMLHtmlElement(*this))
+    if (IsHTMLHtmlElement(*this))
       UseCounter::Count(GetDocument(), WebFeature::kLangAttributeOnHTML);
-    else if (isHTMLBodyElement(*this))
+    else if (IsHTMLBodyElement(*this))
       UseCounter::Count(GetDocument(), WebFeature::kLangAttributeOnBody);
     String html_language = value.GetString();
     size_t first_separator = html_language.find('-');
@@ -301,7 +301,7 @@
       if (IsValidDirAttribute(value))
         AddPropertyToPresentationAttributeStyle(style, CSSPropertyDirection,
                                                 value);
-      else if (isHTMLBodyElement(*this))
+      else if (IsHTMLBodyElement(*this))
         AddPropertyToPresentationAttributeStyle(style, CSSPropertyDirection,
                                                 "ltr");
       if (!HasTagName(bdiTag) && !HasTagName(bdoTag) && !HasTagName(outputTag))
@@ -896,7 +896,7 @@
 }
 
 static inline bool ElementAffectsDirectionality(const Node* node) {
-  return node->IsHTMLElement() && (isHTMLBDIElement(ToHTMLElement(*node)) ||
+  return node->IsHTMLElement() && (IsHTMLBDIElement(ToHTMLElement(*node)) ||
                                    ToHTMLElement(*node).hasAttribute(dirAttr));
 }
 
@@ -909,7 +909,7 @@
   // <bdi> defaults to dir="auto"
   // https://html.spec.whatwg.org/multipage/semantics.html#the-bdi-element
   const AtomicString& direction = FastGetAttribute(dirAttr);
-  return (isHTMLBDIElement(*this) && direction == g_null_atom) ||
+  return (IsHTMLBDIElement(*this) && direction == g_null_atom) ||
          DeprecatedEqualIgnoringCase(direction, "auto");
 }
 
@@ -923,15 +923,16 @@
 
 TextDirection HTMLElement::Directionality(
     Node** strong_directionality_text_node) const {
-  if (isHTMLInputElement(*this)) {
-    HTMLInputElement* input_element =
-        toHTMLInputElement(const_cast<HTMLElement*>(this));
+  if (auto* input_element = ToHTMLInputElementOrNull(*this)) {
     bool has_strong_directionality;
     TextDirection text_direction = DetermineDirectionality(
         input_element->value(), &has_strong_directionality);
-    if (strong_directionality_text_node)
+    if (strong_directionality_text_node) {
       *strong_directionality_text_node =
-          has_strong_directionality ? input_element : 0;
+          has_strong_directionality
+              ? const_cast<HTMLInputElement*>(input_element)
+              : 0;
+    }
     return text_direction;
   }
 
@@ -939,7 +940,7 @@
   while (node) {
     // Skip bdi, script, style and text form controls.
     if (DeprecatedEqualIgnoringCase(node->nodeName(), "bdi") ||
-        isHTMLScriptElement(*node) || isHTMLStyleElement(*node) ||
+        IsHTMLScriptElement(*node) || IsHTMLStyleElement(*node) ||
         (node->IsElementNode() && ToElement(node)->IsTextControl()) ||
         (node->IsElementNode() &&
          ToElement(node)->ShadowPseudoId() == "-webkit-input-placeholder")) {
diff --git a/third_party/WebKit/Source/core/html/HTMLEmbedElement.cpp b/third_party/WebKit/Source/core/html/HTMLEmbedElement.cpp
index 16aef7b..76bb27d 100644
--- a/third_party/WebKit/Source/core/html/HTMLEmbedElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLEmbedElement.cpp
@@ -197,10 +197,10 @@
   // * The element has an ancestor object element that is not showing its
   //   fallback content.
   ContainerNode* p = parentNode();
-  if (isHTMLObjectElement(p)) {
+  if (auto* object = ToHTMLObjectElementOrNull(p)) {
     DCHECK(p->GetLayoutObject());
-    if (!toHTMLObjectElement(p)->WillUseFallbackContentAtLayout() &&
-        !toHTMLObjectElement(p)->UseFallbackContent()) {
+    if (!object->WillUseFallbackContentAtLayout() &&
+        !object->UseFallbackContent()) {
       DCHECK(!p->GetLayoutObject()->IsEmbeddedObject());
       return false;
     }
diff --git a/third_party/WebKit/Source/core/html/HTMLEmbedElementTest.cpp b/third_party/WebKit/Source/core/html/HTMLEmbedElementTest.cpp
index 19eb9ef..4432bc5 100644
--- a/third_party/WebKit/Source/core/html/HTMLEmbedElementTest.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLEmbedElementTest.cpp
@@ -56,7 +56,6 @@
 
   auto* object_element = GetDocument().getElementById("fco");
   ASSERT_TRUE(object_element);
-  ASSERT_TRUE(isHTMLObjectElement(object_element));
   HTMLObjectElement* object = toHTMLObjectElement(object_element);
 
   // At this moment updatePlugin() function is not called, so
@@ -68,7 +67,6 @@
 
   auto* embed_element = GetDocument().getElementById("fce");
   ASSERT_TRUE(embed_element);
-  ASSERT_TRUE(isHTMLEmbedElement(embed_element));
   HTMLEmbedElement* embed = toHTMLEmbedElement(embed_element);
 
   GetDocument().View()->UpdateAllLifecyclePhases();
diff --git a/third_party/WebKit/Source/core/html/HTMLFormControlElement.cpp b/third_party/WebKit/Source/core/html/HTMLFormControlElement.cpp
index a8714ee7..6fab1ac 100644
--- a/third_party/WebKit/Source/core/html/HTMLFormControlElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLFormControlElement.cpp
@@ -115,9 +115,9 @@
   ContainerNode* highest_legend_ancestor = nullptr;
   for (HTMLElement* ancestor = Traversal<HTMLElement>::FirstAncestor(*this);
        ancestor; ancestor = Traversal<HTMLElement>::FirstAncestor(*ancestor)) {
-    if (isHTMLLegendElement(*ancestor))
+    if (IsHTMLLegendElement(*ancestor))
       highest_legend_ancestor = ancestor;
-    if (isHTMLFieldSetElement(*ancestor) && ancestor->IsDisabledFormControl())
+    if (IsHTMLFieldSetElement(*ancestor) && ancestor->IsDisabledFormControl())
       highest_disabled_field_set_ancestor = toHTMLFieldSetElement(ancestor);
   }
   ancestor_disabled_state_ =
diff --git a/third_party/WebKit/Source/core/html/HTMLFormControlsCollection.cpp b/third_party/WebKit/Source/core/html/HTMLFormControlsCollection.cpp
index 5297ee3..70ed389 100644
--- a/third_party/WebKit/Source/core/html/HTMLFormControlsCollection.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLFormControlsCollection.cpp
@@ -43,7 +43,7 @@
     : HTMLCollection(owner_node, kFormControls, kOverridesItemAfter),
       cached_element_(nullptr),
       cached_element_offset_in_array_(0) {
-  DCHECK(isHTMLFormElement(owner_node));
+  DCHECK(IsHTMLFormElement(owner_node));
 }
 
 HTMLFormControlsCollection* HTMLFormControlsCollection::Create(
@@ -182,14 +182,14 @@
     return;
 
   if (named_items.size() == 1) {
-    if (!isHTMLImageElement(*named_items[0]))
-      return_value.setElement(named_items.at(0));
+    if (!IsHTMLImageElement(*named_items[0]))
+      return_value.SetElement(named_items.at(0));
     return;
   }
 
   // This path never returns a RadioNodeList for <img> because
   // onlyMatchingImgElements flag is false by default.
-  return_value.setRadioNodeList(ownerNode().GetRadioNodeList(name));
+  return_value.SetRadioNodeList(ownerNode().GetRadioNodeList(name));
 }
 
 void HTMLFormControlsCollection::SupportedPropertyNames(Vector<String>& names) {
diff --git a/third_party/WebKit/Source/core/html/HTMLFormElement.cpp b/third_party/WebKit/Source/core/html/HTMLFormElement.cpp
index 8a10a78..da80411 100644
--- a/third_party/WebKit/Source/core/html/HTMLFormElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLFormElement.cpp
@@ -111,11 +111,11 @@
   // below).
   // FIXME: This check is not correct for Shadow DOM.
   bool parent_is_table_element_part =
-      (parent_layout_object->IsTable() && isHTMLTableElement(*node)) ||
-      (parent_layout_object->IsTableRow() && isHTMLTableRowElement(*node)) ||
+      (parent_layout_object->IsTable() && IsHTMLTableElement(*node)) ||
+      (parent_layout_object->IsTableRow() && IsHTMLTableRowElement(*node)) ||
       (parent_layout_object->IsTableSection() && node->HasTagName(tbodyTag)) ||
       (parent_layout_object->IsLayoutTableCol() && node->HasTagName(colTag)) ||
-      (parent_layout_object->IsTableCell() && isHTMLTableRowElement(*node));
+      (parent_layout_object->IsTableCell() && IsHTMLTableRowElement(*node));
 
   if (!parent_is_table_element_part)
     return true;
@@ -597,8 +597,8 @@
     ListedElement* listed_element = 0;
     if (element.IsFormControlElement())
       listed_element = ToHTMLFormControlElement(&element);
-    else if (isHTMLObjectElement(element))
-      listed_element = toHTMLObjectElement(&element);
+    else if (auto* object = ToHTMLObjectElementOrNull(element))
+      listed_element = object;
     else
       continue;
     if (listed_element->Form() == this)
@@ -729,9 +729,9 @@
   if (!element)
     return 0;
   SECURITY_DCHECK(ToHTMLElement(element)->formOwner() == this);
-  if (isHTMLImageElement(*element)) {
+  if (IsHTMLImageElement(*element)) {
     SECURITY_DCHECK(ImageElements().Find(element) != kNotFound);
-  } else if (isHTMLObjectElement(*element)) {
+  } else if (IsHTMLObjectElement(*element)) {
     SECURITY_DCHECK(ListedElements().Find(toHTMLObjectElement(element)) !=
                     kNotFound);
   } else {
@@ -815,14 +815,14 @@
   DCHECK(!elements.IsEmpty());
 
   bool only_match_img =
-      !elements.IsEmpty() && isHTMLImageElement(*elements.front());
+      !elements.IsEmpty() && IsHTMLImageElement(*elements.front());
   if (only_match_img) {
     UseCounter::Count(GetDocument(),
                       WebFeature::kFormNameAccessForImageElement);
     // The following code has performance impact, but it should be small
     // because <img> access via <form> name getter is rarely used.
     for (auto& element : elements) {
-      if (isHTMLImageElement(*element) && !element->IsDescendantOf(this)) {
+      if (IsHTMLImageElement(*element) && !element->IsDescendantOf(this)) {
         UseCounter::Count(
             GetDocument(),
             WebFeature::kFormNameAccessForNonDescendantImageElement);
@@ -831,11 +831,11 @@
     }
   }
   if (elements.size() == 1) {
-    return_value.setElement(elements.at(0));
+    return_value.SetElement(elements.at(0));
     return;
   }
 
-  return_value.setRadioNodeList(GetRadioNodeList(name, only_match_img));
+  return_value.SetRadioNodeList(GetRadioNodeList(name, only_match_img));
 }
 
 void HTMLFormElement::SetDemoted(bool demoted) {
diff --git a/third_party/WebKit/Source/core/html/HTMLFrameElementBase.h b/third_party/WebKit/Source/core/html/HTMLFrameElementBase.h
index 537ec6a..5ff5a62 100644
--- a/third_party/WebKit/Source/core/html/HTMLFrameElementBase.h
+++ b/third_party/WebKit/Source/core/html/HTMLFrameElementBase.h
@@ -87,7 +87,7 @@
 };
 
 inline bool IsHTMLFrameElementBase(const HTMLElement& element) {
-  return isHTMLFrameElement(element) || isHTMLIFrameElement(element);
+  return IsHTMLFrameElement(element) || IsHTMLIFrameElement(element);
 }
 
 DEFINE_HTMLELEMENT_TYPE_CASTS_WITH_FUNCTION(HTMLFrameElementBase);
diff --git a/third_party/WebKit/Source/core/html/HTMLFrameSetElement.cpp b/third_party/WebKit/Source/core/html/HTMLFrameSetElement.cpp
index 2ef9ffd..eb20353 100644
--- a/third_party/WebKit/Source/core/html/HTMLFrameSetElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLFrameSetElement.cpp
@@ -292,7 +292,7 @@
 LocalDOMWindow* HTMLFrameSetElement::AnonymousNamedGetter(
     const AtomicString& name) {
   Element* frame_element = Children()->namedItem(name);
-  if (!isHTMLFrameElement(frame_element))
+  if (!IsHTMLFrameElement(frame_element))
     return nullptr;
   Document* document = toHTMLFrameElement(frame_element)->contentDocument();
   if (!document || !document->GetFrame())
diff --git a/third_party/WebKit/Source/core/html/HTMLHRElement.cpp b/third_party/WebKit/Source/core/html/HTMLHRElement.cpp
index 7f2452e..732427e 100644
--- a/third_party/WebKit/Source/core/html/HTMLHRElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLHRElement.cpp
@@ -111,20 +111,18 @@
 HTMLSelectElement* HTMLHRElement::OwnerSelectElement() const {
   if (!parentNode())
     return nullptr;
-  if (isHTMLSelectElement(*parentNode()))
-    return toHTMLSelectElement(parentNode());
-  if (!isHTMLOptGroupElement(*parentNode()))
+  if (auto* select = ToHTMLSelectElementOrNull(*parentNode()))
+    return select;
+  if (!IsHTMLOptGroupElement(*parentNode()))
     return nullptr;
-  Node* grand_parent = parentNode()->parentNode();
-  return isHTMLSelectElement(grand_parent) ? toHTMLSelectElement(grand_parent)
-                                           : nullptr;
+  return ToHTMLSelectElementOrNull(parentNode()->parentNode());
 }
 
 Node::InsertionNotificationRequest HTMLHRElement::InsertedInto(
     ContainerNode* insertion_point) {
   HTMLElement::InsertedInto(insertion_point);
   if (HTMLSelectElement* select = OwnerSelectElement()) {
-    if (insertion_point == select || (isHTMLOptGroupElement(*insertion_point) &&
+    if (insertion_point == select || (IsHTMLOptGroupElement(*insertion_point) &&
                                       insertion_point->parentNode() == select))
       select->HrInsertedOrRemoved(*this);
   }
@@ -132,13 +130,13 @@
 }
 
 void HTMLHRElement::RemovedFrom(ContainerNode* insertion_point) {
-  if (isHTMLSelectElement(*insertion_point)) {
-    if (!parentNode() || isHTMLOptGroupElement(*parentNode()))
-      toHTMLSelectElement(insertion_point)->HrInsertedOrRemoved(*this);
-  } else if (isHTMLOptGroupElement(*insertion_point)) {
+  if (auto* select = ToHTMLSelectElementOrNull(*insertion_point)) {
+    if (!parentNode() || IsHTMLOptGroupElement(*parentNode()))
+      select->HrInsertedOrRemoved(*this);
+  } else if (IsHTMLOptGroupElement(*insertion_point)) {
     Node* parent = insertion_point->parentNode();
-    if (isHTMLSelectElement(parent))
-      toHTMLSelectElement(parent)->HrInsertedOrRemoved(*this);
+    if (auto* select = ToHTMLSelectElementOrNull(parent))
+      select->HrInsertedOrRemoved(*this);
   }
   HTMLElement::RemovedFrom(insertion_point);
 }
diff --git a/third_party/WebKit/Source/core/html/HTMLImageElement.cpp b/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
index 219709f..f62fd743 100644
--- a/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
@@ -303,14 +303,14 @@
   DCHECK(IsMainThread());
   Node* parent = parentNode();
   source_ = nullptr;
-  if (!parent || !isHTMLPictureElement(*parent))
+  if (!parent || !IsHTMLPictureElement(*parent))
     return ImageCandidate();
   for (Node* child = parent->firstChild(); child;
        child = child->nextSibling()) {
     if (child == this)
       return ImageCandidate();
 
-    if (!isHTMLSourceElement(*child))
+    if (!IsHTMLSourceElement(*child))
       continue;
 
     HTMLSourceElement* source = toHTMLSourceElement(child);
@@ -400,7 +400,7 @@
   if (listener_)
     GetDocument().GetMediaQueryMatcher().AddViewportListener(listener_);
   Node* parent = parentNode();
-  if (parent && isHTMLPictureElement(*parent))
+  if (parent && IsHTMLPictureElement(*parent))
     toHTMLPictureElement(parent)->AddListenerToSourceChildren();
 
   bool image_was_modified = false;
@@ -429,7 +429,7 @@
   if (listener_) {
     GetDocument().GetMediaQueryMatcher().RemoveViewportListener(listener_);
     Node* parent = parentNode();
-    if (parent && isHTMLPictureElement(*parent))
+    if (parent && IsHTMLPictureElement(*parent))
       toHTMLPictureElement(parent)->RemoveListenerFromSourceChildren();
   }
   HTMLElement::RemovedFrom(insertion_point);
diff --git a/third_party/WebKit/Source/core/html/HTMLImageLoader.cpp b/third_party/WebKit/Source/core/html/HTMLImageLoader.cpp
index 0b824a8..2ff8ebb 100644
--- a/third_party/WebKit/Source/core/html/HTMLImageLoader.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLImageLoader.cpp
@@ -44,11 +44,11 @@
 
   // HTMLVideoElement uses this class to load the poster image, but it should
   // not fire events for loading or failure.
-  if (isHTMLVideoElement(*GetElement()))
+  if (IsHTMLVideoElement(*GetElement()))
     return;
 
   bool error_occurred = GetImage()->ErrorOccurred();
-  if (isHTMLObjectElement(*GetElement()) && !error_occurred) {
+  if (IsHTMLObjectElement(*GetElement()) && !error_occurred) {
     // An <object> considers a 404 to be an error and should fire onerror.
     error_occurred = (GetImage()->GetResponse().HttpStatusCode() >= 400);
   }
@@ -62,10 +62,10 @@
   if (ToHTMLElement(GetElement())->AltText().IsEmpty())
     return;
 
-  if (isHTMLImageElement(GetElement()))
-    toHTMLImageElement(GetElement())->EnsureCollapsedOrFallbackContent();
-  else if (isHTMLInputElement(GetElement()))
-    toHTMLInputElement(GetElement())->EnsureFallbackContent();
+  if (auto* image = ToHTMLImageElementOrNull(GetElement()))
+    image->EnsureCollapsedOrFallbackContent();
+  else if (auto* input = ToHTMLInputElementOrNull(GetElement()))
+    input->EnsureFallbackContent();
 }
 
 void HTMLImageLoader::ImageNotifyFinished(ImageResourceContent*) {
@@ -74,22 +74,22 @@
   ImageLoader::ImageNotifyFinished(cached_image);
 
   bool load_error = cached_image->ErrorOccurred();
-  if (isHTMLImageElement(*element)) {
+  if (auto* image = ToHTMLImageElementOrNull(*element)) {
     if (load_error)
-      toHTMLImageElement(element)->EnsureCollapsedOrFallbackContent();
+      image->EnsureCollapsedOrFallbackContent();
     else
-      toHTMLImageElement(element)->EnsurePrimaryContent();
+      image->EnsurePrimaryContent();
   }
 
-  if (isHTMLInputElement(*element)) {
+  if (auto* input = ToHTMLInputElementOrNull(*element)) {
     if (load_error)
-      toHTMLInputElement(element)->EnsureFallbackContent();
+      input->EnsureFallbackContent();
     else
-      toHTMLInputElement(element)->EnsurePrimaryContent();
+      input->EnsurePrimaryContent();
   }
 
   if ((load_error || cached_image->GetResponse().HttpStatusCode() >= 400) &&
-      isHTMLObjectElement(*element))
+      IsHTMLObjectElement(*element))
     toHTMLObjectElement(element)->RenderFallbackContent();
 }
 
diff --git a/third_party/WebKit/Source/core/html/HTMLLIElement.cpp b/third_party/WebKit/Source/core/html/HTMLLIElement.cpp
index 14f6e72..b3feb3a8 100644
--- a/third_party/WebKit/Source/core/html/HTMLLIElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLLIElement.cpp
@@ -103,7 +103,7 @@
       current = LayoutTreeBuilderTraversal::ParentElement(*current);
       if (!current)
         break;
-      if (isHTMLUListElement(*current) || isHTMLOListElement(*current))
+      if (IsHTMLUListElement(*current) || IsHTMLOListElement(*current))
         list_node = current;
     }
 
diff --git a/third_party/WebKit/Source/core/html/HTMLLegendElement.cpp b/third_party/WebKit/Source/core/html/HTMLLegendElement.cpp
index afad4fd..2d033a2 100644
--- a/third_party/WebKit/Source/core/html/HTMLLegendElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLLegendElement.cpp
@@ -73,11 +73,9 @@
   // According to the specification, If the legend has a fieldset element as
   // its parent, then the form attribute must return the same value as the
   // form attribute on that fieldset element. Otherwise, it must return null.
-  ContainerNode* fieldset = parentNode();
-  if (!isHTMLFieldSetElement(fieldset))
-    return nullptr;
-
-  return toHTMLFieldSetElement(fieldset)->formOwner();
+  if (auto* fieldset = ToHTMLFieldSetElementOrNull(parentNode()))
+    return fieldset->formOwner();
+  return nullptr;
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp b/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp
index d7bdee40..470ad3c 100644
--- a/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp
@@ -289,7 +289,7 @@
   Timing timing;
   timing.fill_mode = Timing::FillMode::FORWARDS;
   TimingInput::SetIterationDuration(
-      timing, UnrestrictedDoubleOrString::fromUnrestrictedDouble(duration),
+      timing, UnrestrictedDoubleOrString::FromUnrestrictedDouble(duration),
       ASSERT_NO_EXCEPTION);
 
   KeyframeEffect* keyframe_effect =
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
index 84bd98db..e925f50c 100644
--- a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
@@ -2905,7 +2905,7 @@
       continue;
     looking_for_start_node = false;
 
-    if (!isHTMLSourceElement(*node))
+    if (!IsHTMLSourceElement(*node))
       continue;
     if (node->parentNode() != this)
       continue;
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.h b/third_party/WebKit/Source/core/html/HTMLMediaElement.h
index 7e41277..bd1a8bd 100644
--- a/third_party/WebKit/Source/core/html/HTMLMediaElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.h
@@ -738,7 +738,7 @@
 };
 
 inline bool IsHTMLMediaElement(const HTMLElement& element) {
-  return isHTMLAudioElement(element) || isHTMLVideoElement(element);
+  return IsHTMLAudioElement(element) || IsHTMLVideoElement(element);
 }
 
 DEFINE_HTMLELEMENT_TYPE_CASTS_WITH_FUNCTION(HTMLMediaElement);
diff --git a/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp b/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp
index e721716..f14d982 100644
--- a/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp
@@ -206,7 +206,7 @@
     if (child->IsTextNode()) {
       if (!ToText(child)->ContainsOnlyWhitespace())
         return true;
-    } else if (!isHTMLParamElement(*child)) {
+    } else if (!IsHTMLParamElement(*child)) {
       return true;
     }
   }
@@ -396,7 +396,7 @@
       return false;
   }
   for (HTMLElement& element : Traversal<HTMLElement>::DescendantsOf(*this)) {
-    if (isHTMLObjectElement(element) || isHTMLEmbedElement(element))
+    if (IsHTMLObjectElement(element) || IsHTMLEmbedElement(element))
       return false;
   }
   return true;
@@ -407,12 +407,12 @@
     return true;
 
   for (HTMLElement& child : Traversal<HTMLElement>::ChildrenOf(*this)) {
-    if (isHTMLParamElement(child) &&
+    if (IsHTMLParamElement(child) &&
         DeprecatedEqualIgnoringCase(child.GetNameAttribute(), "type") &&
         MIMETypeRegistry::IsJavaAppletMIMEType(
             child.getAttribute(valueAttr).GetString()))
       return true;
-    if (isHTMLObjectElement(child) &&
+    if (IsHTMLObjectElement(child) &&
         toHTMLObjectElement(child).ContainsJavaApplet())
       return true;
   }
diff --git a/third_party/WebKit/Source/core/html/HTMLOptGroupElement.cpp b/third_party/WebKit/Source/core/html/HTMLOptGroupElement.cpp
index 3a4be52..19fdbae 100644
--- a/third_party/WebKit/Source/core/html/HTMLOptGroupElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLOptGroupElement.cpp
@@ -94,9 +94,9 @@
 }
 
 void HTMLOptGroupElement::RemovedFrom(ContainerNode* insertion_point) {
-  if (isHTMLSelectElement(*insertion_point)) {
+  if (auto* select = ToHTMLSelectElementOrNull(*insertion_point)) {
     if (!parentNode())
-      toHTMLSelectElement(insertion_point)->OptGroupInsertedOrRemoved(*this);
+      select->OptGroupInsertedOrRemoved(*this);
   }
   HTMLElement::RemovedFrom(insertion_point);
 }
diff --git a/third_party/WebKit/Source/core/html/HTMLOptionElement.cpp b/third_party/WebKit/Source/core/html/HTMLOptionElement.cpp
index af82f5c..2777d0aab 100644
--- a/third_party/WebKit/Source/core/html/HTMLOptionElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLOptionElement.cpp
@@ -94,7 +94,7 @@
     if (HTMLSelectElement* select = OwnerSelectElement())
       select->UpdateListOnLayoutObject();
     resolved_style = OriginalStyleForLayoutObject();
-    option_context.resolved_style = resolved_style.Get();
+    option_context.resolved_style = resolved_style.get();
   }
   HTMLElement::AttachLayoutTree(option_context);
 }
@@ -303,13 +303,11 @@
 HTMLSelectElement* HTMLOptionElement::OwnerSelectElement() const {
   if (!parentNode())
     return nullptr;
-  if (isHTMLSelectElement(*parentNode()))
-    return toHTMLSelectElement(parentNode());
-  if (!isHTMLOptGroupElement(*parentNode()))
-    return nullptr;
-  Node* grand_parent = parentNode()->parentNode();
-  return isHTMLSelectElement(grand_parent) ? toHTMLSelectElement(grand_parent)
-                                           : nullptr;
+  if (auto* select = ToHTMLSelectElementOrNull(*parentNode()))
+    return select;
+  if (IsHTMLOptGroupElement(*parentNode()))
+    return ToHTMLSelectElementOrNull(parentNode()->parentNode());
+  return nullptr;
 }
 
 String HTMLOptionElement::label() const {
@@ -327,7 +325,7 @@
 
 String HTMLOptionElement::TextIndentedToRespectGroupLabel() const {
   ContainerNode* parent = parentNode();
-  if (parent && isHTMLOptGroupElement(*parent))
+  if (parent && IsHTMLOptGroupElement(*parent))
     return "    " + DisplayLabel();
   return DisplayLabel();
 }
@@ -340,7 +338,7 @@
   if (OwnElementDisabled())
     return true;
   if (Element* parent = parentElement())
-    return isHTMLOptGroupElement(*parent) && parent->IsDisabledFormControl();
+    return IsHTMLOptGroupElement(*parent) && parent->IsDisabledFormControl();
   return false;
 }
 
@@ -354,7 +352,7 @@
     ContainerNode* insertion_point) {
   HTMLElement::InsertedInto(insertion_point);
   if (HTMLSelectElement* select = OwnerSelectElement()) {
-    if (insertion_point == select || (isHTMLOptGroupElement(*insertion_point) &&
+    if (insertion_point == select || (IsHTMLOptGroupElement(*insertion_point) &&
                                       insertion_point->parentNode() == select))
       select->OptionInserted(*this, is_selected_);
   }
@@ -362,13 +360,12 @@
 }
 
 void HTMLOptionElement::RemovedFrom(ContainerNode* insertion_point) {
-  if (isHTMLSelectElement(*insertion_point)) {
-    if (!parentNode() || isHTMLOptGroupElement(*parentNode()))
-      toHTMLSelectElement(insertion_point)->OptionRemoved(*this);
-  } else if (isHTMLOptGroupElement(*insertion_point)) {
-    Node* parent = insertion_point->parentNode();
-    if (isHTMLSelectElement(parent))
-      toHTMLSelectElement(parent)->OptionRemoved(*this);
+  if (auto* select = ToHTMLSelectElementOrNull(*insertion_point)) {
+    if (!parentNode() || IsHTMLOptGroupElement(*parentNode()))
+      select->OptionRemoved(*this);
+  } else if (IsHTMLOptGroupElement(*insertion_point)) {
+    if (auto* select = ToHTMLSelectElementOrNull(insertion_point->parentNode()))
+      select->OptionRemoved(*this);
   }
   HTMLElement::RemovedFrom(insertion_point);
 }
@@ -423,7 +420,7 @@
     // ComputedStyle.
     Element* parent = parentElement();
     DCHECK(parent);
-    if (isHTMLOptGroupElement(*parent)) {
+    if (IsHTMLOptGroupElement(*parent)) {
       const ComputedStyle* parent_style = parent->GetComputedStyle()
                                               ? parent->GetComputedStyle()
                                               : parent->EnsureComputedStyle();
diff --git a/third_party/WebKit/Source/core/html/HTMLOptionsCollection.cpp b/third_party/WebKit/Source/core/html/HTMLOptionsCollection.cpp
index 1a91b23e..147da66 100644
--- a/third_party/WebKit/Source/core/html/HTMLOptionsCollection.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLOptionsCollection.cpp
@@ -35,7 +35,7 @@
 
 HTMLOptionsCollection::HTMLOptionsCollection(ContainerNode& select)
     : HTMLCollection(select, kSelectOptions, kDoesNotOverrideItemAfter) {
-  DCHECK(isHTMLSelectElement(select));
+  DCHECK(IsHTMLSelectElement(select));
 }
 
 void HTMLOptionsCollection::SupportedPropertyNames(Vector<String>& names) {
@@ -106,7 +106,7 @@
     return;
 
   if (named_items.size() == 1) {
-    return_value.setElement(named_items.at(0));
+    return_value.SetElement(named_items.at(0));
     return;
   }
 
@@ -115,7 +115,7 @@
   UseCounter::Count(
       GetDocument(),
       WebFeature::kHTMLOptionsCollectionNamedGetterReturnsNodeList);
-  return_value.setNodeList(StaticElementList::Adopt(named_items));
+  return_value.SetNodeList(StaticElementList::Adopt(named_items));
 }
 
 bool HTMLOptionsCollection::AnonymousIndexedSetter(
diff --git a/third_party/WebKit/Source/core/html/HTMLOptionsCollection.h b/third_party/WebKit/Source/core/html/HTMLOptionsCollection.h
index f454cb7..7fcc70b 100644
--- a/third_party/WebKit/Source/core/html/HTMLOptionsCollection.h
+++ b/third_party/WebKit/Source/core/html/HTMLOptionsCollection.h
@@ -72,14 +72,14 @@
 
 inline bool HTMLOptionsCollection::ElementMatches(
     const HTMLElement& element) const {
-  if (!isHTMLOptionElement(element))
+  if (!IsHTMLOptionElement(element))
     return false;
   Node* parent = element.parentNode();
   if (!parent)
     return false;
   if (parent == &RootNode())
     return true;
-  return isHTMLOptGroupElement(*parent) && parent->parentNode() == &RootNode();
+  return IsHTMLOptGroupElement(*parent) && parent->parentNode() == &RootNode();
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/HTMLScriptElement.cpp b/third_party/WebKit/Source/core/html/HTMLScriptElement.cpp
index 2d0d8f554..7df0f1214 100644
--- a/third_party/WebKit/Source/core/html/HTMLScriptElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLScriptElement.cpp
@@ -225,7 +225,7 @@
 void HTMLScriptElement::SetScriptElementForBinding(
     HTMLScriptElementOrSVGScriptElement& element) {
   if (!IsInV1ShadowTree())
-    element.setHTMLScriptElement(this);
+    element.SetHTMLScriptElement(this);
 }
 
 Element* HTMLScriptElement::CloneElementWithoutAttributesAndChildren() {
diff --git a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
index dee364c..544fe1c 100644
--- a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
@@ -132,7 +132,7 @@
 
   // TODO(tkent): This function is called in CSS selector matching. Using
   // listItems() might have performance impact.
-  if (GetListItems().size() == 0 || !isHTMLOptionElement(GetListItems()[0]))
+  if (GetListItems().size() == 0 || !IsHTMLOptionElement(GetListItems()[0]))
     return false;
   return toHTMLOptionElement(GetListItems()[0])->value().IsEmpty();
 }
@@ -206,17 +206,17 @@
     const HTMLElementOrLong& before,
     ExceptionState& exception_state) {
   HTMLElement* element_to_insert;
-  DCHECK(!element.isNull());
-  if (element.isHTMLOptionElement())
-    element_to_insert = element.getAsHTMLOptionElement();
+  DCHECK(!element.IsNull());
+  if (element.IsHTMLOptionElement())
+    element_to_insert = element.GetAsHTMLOptionElement();
   else
-    element_to_insert = element.getAsHTMLOptGroupElement();
+    element_to_insert = element.GetAsHTMLOptGroupElement();
 
   HTMLElement* before_element;
-  if (before.isHTMLElement())
-    before_element = before.getAsHTMLElement();
-  else if (before.isLong())
-    before_element = options()->item(before.getAsLong());
+  if (before.IsHTMLElement())
+    before_element = before.GetAsHTMLElement();
+  else if (before.IsLong())
+    before_element = options()->item(before.GetAsLong());
   else
     before_element = nullptr;
 
@@ -379,14 +379,14 @@
     return;
   }
   HTMLOptionElementOrHTMLOptGroupElement element;
-  element.setHTMLOptionElement(option);
+  element.SetHTMLOptionElement(option);
   HTMLElementOrLong before;
   // Out of array bounds? First insert empty dummies.
   if (diff > 0) {
     setLength(index, exception_state);
     // Replace an existing entry?
   } else if (diff < 0) {
-    before.setHTMLElement(options()->item(index + 1));
+    before.SetHTMLElement(options()->item(index + 1));
     remove(index);
   }
   if (exception_state.HadException())
@@ -471,7 +471,7 @@
        list_index += direction) {
     --skip;
     HTMLElement* element = list_items[list_index];
-    if (!isHTMLOptionElement(*element))
+    if (!IsHTMLOptionElement(*element))
       continue;
     if (toHTMLOptionElement(*element).IsDisplayNone())
       continue;
@@ -562,7 +562,7 @@
   last_on_change_selection_.clear();
   for (auto& element : GetListItems())
     last_on_change_selection_.push_back(
-        isHTMLOptionElement(*element) &&
+        IsHTMLOptionElement(*element) &&
         toHTMLOptionElement(element)->Selected());
 }
 
@@ -650,7 +650,7 @@
   bool fire_on_change = false;
   for (unsigned i = 0; i < items.size(); ++i) {
     HTMLElement* element = items[i];
-    bool selected = isHTMLOptionElement(*element) &&
+    bool selected = IsHTMLOptionElement(*element) &&
                     toHTMLOptionElement(element)->Selected();
     if (selected != last_on_change_selection_[i])
       fire_on_change = true;
@@ -752,7 +752,7 @@
     // We should ignore nested optgroup elements. The HTML parser flatten
     // them.  However we need to ignore nested optgroups built by DOM APIs.
     // This behavior matches to IE and Firefox.
-    if (isHTMLOptGroupElement(current)) {
+    if (IsHTMLOptGroupElement(current)) {
       if (current.parentNode() != this) {
         current_element = ElementTraversal::NextSkippingChildren(current, this);
         continue;
@@ -764,10 +764,10 @@
       }
     }
 
-    if (isHTMLOptionElement(current))
+    if (IsHTMLOptionElement(current))
       list_items_.push_back(&current);
 
-    if (isHTMLHRElement(current))
+    if (IsHTMLHRElement(current))
       list_items_.push_back(&current);
 
     // In conforming HTML code, only <optgroup> and <option> will be found
@@ -852,7 +852,7 @@
 int HTMLSelectElement::SelectedListIndex() const {
   int index = 0;
   for (const auto& item : GetListItems()) {
-    if (isHTMLOptionElement(item) && toHTMLOptionElement(item)->Selected())
+    if (IsHTMLOptionElement(item) && toHTMLOptionElement(item)->Selected())
       return index;
     ++index;
   }
@@ -1102,7 +1102,7 @@
   size_t length = items.size();
   FormControlState state;
   for (unsigned i = 0; i < length; ++i) {
-    if (!isHTMLOptionElement(*items[i]))
+    if (!IsHTMLOptionElement(*items[i]))
       continue;
     HTMLOptionElement* option = toHTMLOptionElement(items[i]);
     if (!option->Selected())
@@ -1121,7 +1121,7 @@
   const ListItems& items = GetListItems();
   size_t loop_end_index = std::min(items.size(), list_index_end);
   for (size_t i = list_index_start; i < loop_end_index; ++i) {
-    if (!isHTMLOptionElement(items[i]))
+    if (!IsHTMLOptionElement(items[i]))
       continue;
     if (toHTMLOptionElement(items[i])->value() == value)
       return i;
@@ -1143,7 +1143,7 @@
   DCHECK_GE(state.ValueSize(), 2u);
   if (!IsMultiple()) {
     size_t index = state[1].ToUInt();
-    if (index < items_size && isHTMLOptionElement(items[index]) &&
+    if (index < items_size && IsHTMLOptionElement(items[index]) &&
         toHTMLOptionElement(items[index])->value() == state[0]) {
       toHTMLOptionElement(items[index])->SetSelectedState(true);
       toHTMLOptionElement(items[index])->SetDirty(true);
@@ -1161,7 +1161,7 @@
     for (size_t i = 0; i < state.ValueSize(); i += 2) {
       const String& value = state[i];
       const size_t index = state[i + 1].ToUInt();
-      if (index < items_size && isHTMLOptionElement(items[index]) &&
+      if (index < items_size && IsHTMLOptionElement(items[index]) &&
           toHTMLOptionElement(items[index])->value() == value) {
         toHTMLOptionElement(items[index])->SetSelectedState(true);
         toHTMLOptionElement(items[index])->SetDirty(true);
@@ -1434,7 +1434,7 @@
 
 HTMLOptionElement* HTMLSelectElement::EventTargetOption(const Event& event) {
   Node* target_node = event.target()->ToNode();
-  if (!target_node || !isHTMLOptionElement(*target_node))
+  if (!target_node || !IsHTMLOptionElement(*target_node))
     return nullptr;
   return toHTMLOptionElement(target_node);
 }
diff --git a/third_party/WebKit/Source/core/html/HTMLSlotElement.cpp b/third_party/WebKit/Source/core/html/HTMLSlotElement.cpp
index 2aad8f2..6d186ea 100644
--- a/third_party/WebKit/Source/core/html/HTMLSlotElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLSlotElement.cpp
@@ -94,7 +94,7 @@
 void HTMLSlotElement::ResolveDistributedNodes() {
   for (auto& node : assigned_nodes_) {
     DCHECK(node->IsSlotable());
-    if (isHTMLSlotElement(*node) &&
+    if (IsHTMLSlotElement(*node) &&
         toHTMLSlotElement(*node).SupportsDistribution())
       AppendDistributedNodesFrom(toHTMLSlotElement(*node));
     else
@@ -278,8 +278,8 @@
   for (auto& child : NodeTraversal::ChildrenOf(*this)) {
     if (!child.IsSlotable())
       continue;
-    if (isHTMLSlotElement(child))
-      AppendDistributedNodesFrom(toHTMLSlotElement(child));
+    if (auto* slot = ToHTMLSlotElementOrNull(child))
+      AppendDistributedNodesFrom(*slot);
     else
       AppendDistributedNode(child);
   }
diff --git a/third_party/WebKit/Source/core/html/HTMLSourceElement.cpp b/third_party/WebKit/Source/core/html/HTMLSourceElement.cpp
index 6079e93..df0166e 100644
--- a/third_party/WebKit/Source/core/html/HTMLSourceElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLSourceElement.cpp
@@ -90,10 +90,10 @@
     ContainerNode* insertion_point) {
   HTMLElement::InsertedInto(insertion_point);
   Element* parent = parentElement();
-  if (IsHTMLMediaElement(parent))
-    ToHTMLMediaElement(parent)->SourceWasAdded(this);
-  if (isHTMLPictureElement(parent))
-    toHTMLPictureElement(parent)->SourceOrMediaChanged();
+  if (auto* media = ToHTMLMediaElementOrNull(parent))
+    media->SourceWasAdded(this);
+  if (auto* picture = ToHTMLPictureElementOrNull(parent))
+    picture->SourceOrMediaChanged();
   return kInsertionDone;
 }
 
@@ -101,11 +101,11 @@
   Element* parent = parentElement();
   if (!parent && removal_root->IsElementNode())
     parent = ToElement(removal_root);
-  if (IsHTMLMediaElement(parent))
-    ToHTMLMediaElement(parent)->SourceWasRemoved(this);
-  if (isHTMLPictureElement(parent)) {
+  if (auto* media = ToHTMLMediaElementOrNull(parent))
+    media->SourceWasRemoved(this);
+  if (auto* picture = ToHTMLPictureElementOrNull(parent)) {
     RemoveMediaQueryListListener();
-    toHTMLPictureElement(parent)->SourceOrMediaChanged();
+    picture->SourceOrMediaChanged();
   }
   HTMLElement::RemovedFrom(removal_root);
 }
@@ -173,16 +173,14 @@
     CreateMediaQueryList(params.new_value);
   if (name == srcsetAttr || name == sizesAttr || name == mediaAttr ||
       name == typeAttr) {
-    Element* parent = parentElement();
-    if (isHTMLPictureElement(parent))
-      toHTMLPictureElement(parent)->SourceOrMediaChanged();
+    if (auto* picture = ToHTMLPictureElementOrNull(parentElement()))
+      picture->SourceOrMediaChanged();
   }
 }
 
 void HTMLSourceElement::NotifyMediaQueryChanged() {
-  Element* parent = parentElement();
-  if (isHTMLPictureElement(parent))
-    toHTMLPictureElement(parent)->SourceOrMediaChanged();
+  if (auto* picture = ToHTMLPictureElementOrNull(parentElement()))
+    picture->SourceOrMediaChanged();
 }
 
 DEFINE_TRACE(HTMLSourceElement) {
diff --git a/third_party/WebKit/Source/core/html/HTMLSummaryElement.cpp b/third_party/WebKit/Source/core/html/HTMLSummaryElement.cpp
index 6366acc..201ebe5 100644
--- a/third_party/WebKit/Source/core/html/HTMLSummaryElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLSummaryElement.cpp
@@ -62,12 +62,10 @@
 }
 
 HTMLDetailsElement* HTMLSummaryElement::DetailsElement() const {
-  Node* parent = parentNode();
-  if (isHTMLDetailsElement(parent))
-    return toHTMLDetailsElement(parent);
-  Element* host = OwnerShadowHost();
-  if (isHTMLDetailsElement(host))
-    return toHTMLDetailsElement(host);
+  if (auto* details = ToHTMLDetailsElementOrNull(parentNode()))
+    return details;
+  if (auto* details = ToHTMLDetailsElementOrNull(OwnerShadowHost()))
+    return details;
   return nullptr;
 }
 
diff --git a/third_party/WebKit/Source/core/html/HTMLTableCellElement.cpp b/third_party/WebKit/Source/core/html/HTMLTableCellElement.cpp
index c20dd0d..0e34c40 100644
--- a/third_party/WebKit/Source/core/html/HTMLTableCellElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLTableCellElement.cpp
@@ -73,7 +73,7 @@
 }
 
 int HTMLTableCellElement::cellIndex() const {
-  if (!isHTMLTableRowElement(parentElement()))
+  if (!IsHTMLTableRowElement(parentElement()))
     return -1;
 
   int index = 0;
diff --git a/third_party/WebKit/Source/core/html/HTMLTablePartElement.cpp b/third_party/WebKit/Source/core/html/HTMLTablePartElement.cpp
index 3579731b..8b687b90 100644
--- a/third_party/WebKit/Source/core/html/HTMLTablePartElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLTablePartElement.cpp
@@ -109,7 +109,7 @@
 
 HTMLTableElement* HTMLTablePartElement::FindParentTable() const {
   ContainerNode* parent = FlatTreeTraversal::Parent(*this);
-  while (parent && !isHTMLTableElement(*parent))
+  while (parent && !IsHTMLTableElement(*parent))
     parent = FlatTreeTraversal::Parent(*parent);
   return toHTMLTableElement(parent);
 }
diff --git a/third_party/WebKit/Source/core/html/HTMLTableRowElement.cpp b/third_party/WebKit/Source/core/html/HTMLTableRowElement.cpp
index f9e466c..b3f49ec2 100644
--- a/third_party/WebKit/Source/core/html/HTMLTableRowElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLTableRowElement.cpp
@@ -71,7 +71,7 @@
     // Skip THEAD, TBODY and TFOOT.
     maybe_table = maybe_table->parentNode();
   }
-  if (!(maybe_table && isHTMLTableElement(maybe_table)))
+  if (!(maybe_table && IsHTMLTableElement(maybe_table)))
     return -1;
   return FindIndexInRowCollection(*toHTMLTableElement(maybe_table)->rows(),
                                   *this);
@@ -82,10 +82,10 @@
   if (!maybe_table)
     return -1;
   HTMLCollection* rows = nullptr;
-  if (IsHTMLTableSectionElement(maybe_table))
-    rows = ToHTMLTableSectionElement(maybe_table)->rows();
-  else if (isHTMLTableElement(maybe_table))
-    rows = toHTMLTableElement(maybe_table)->rows();
+  if (auto* section = ToHTMLTableSectionElementOrNull(maybe_table))
+    rows = section->rows();
+  else if (auto* table = ToHTMLTableElementOrNull(maybe_table))
+    rows = table->rows();
   if (!rows)
     return -1;
   return FindIndexInRowCollection(*rows, *this);
diff --git a/third_party/WebKit/Source/core/html/HTMLTableRowsCollection.cpp b/third_party/WebKit/Source/core/html/HTMLTableRowsCollection.cpp
index 7f956dc8..7e6e49c 100644
--- a/third_party/WebKit/Source/core/html/HTMLTableRowsCollection.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLTableRowsCollection.cpp
@@ -80,8 +80,8 @@
   else if (IsInSection(*previous, tbodyTag))
     child = Traversal<HTMLElement>::NextSibling(*previous->parentNode());
   for (; child; child = Traversal<HTMLElement>::NextSibling(*child)) {
-    if (isHTMLTableRowElement(child))
-      return toHTMLTableRowElement(child);
+    if (auto* row = ToHTMLTableRowElementOrNull(child))
+      return row;
     if (child->HasTagName(tbodyTag)) {
       if (HTMLTableRowElement* row =
               Traversal<HTMLTableRowElement>::FirstChild(*child))
@@ -117,8 +117,8 @@
 
   for (HTMLElement* child = Traversal<HTMLElement>::LastChild(table); child;
        child = Traversal<HTMLElement>::PreviousSibling(*child)) {
-    if (isHTMLTableRowElement(child))
-      return toHTMLTableRowElement(child);
+    if (auto* row = ToHTMLTableRowElementOrNull(child))
+      return row;
     if (child->HasTagName(tbodyTag)) {
       if (HTMLTableRowElement* last_row =
               Traversal<HTMLTableRowElement>::LastChild(*child))
@@ -143,7 +143,7 @@
 // evaluation is undefined and can differ between compilers.
 HTMLTableRowsCollection::HTMLTableRowsCollection(ContainerNode& table)
     : HTMLCollection(table, kTableRows, kOverridesItemAfter) {
-  DCHECK(isHTMLTableElement(table));
+  DCHECK(IsHTMLTableElement(table));
 }
 
 HTMLTableRowsCollection* HTMLTableRowsCollection::Create(ContainerNode& table,
diff --git a/third_party/WebKit/Source/core/html/HTMLTextAreaElement.cpp b/third_party/WebKit/Source/core/html/HTMLTextAreaElement.cpp
index 37f9ca4..0f330b4 100644
--- a/third_party/WebKit/Source/core/html/HTMLTextAreaElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLTextAreaElement.cpp
@@ -277,7 +277,7 @@
   for (Node& node : NodeTraversal::DescendantsOf(*inner_editor)) {
     if (node.IsTextNode())
       continue;
-    DCHECK(isHTMLBRElement(node));
+    DCHECK(IsHTMLBRElement(node));
     DCHECK_EQ(&node, inner_editor->lastChild());
   }
 #endif
diff --git a/third_party/WebKit/Source/core/html/ImageData.cpp b/third_party/WebKit/Source/core/html/ImageData.cpp
index 52f0c2b9..1d8eff6 100644
--- a/third_party/WebKit/Source/core/html/ImageData.cpp
+++ b/third_party/WebKit/Source/core/html/ImageData.cpp
@@ -365,14 +365,14 @@
   // pixels.
   String storage_format_name;
 
-  if (data.isUint8ClampedArray()) {
-    buffer_view = data.getAsUint8ClampedArray().View();
+  if (data.IsUint8ClampedArray()) {
+    buffer_view = data.GetAsUint8ClampedArray().View();
     storage_format_name = kUint8ClampedArrayStorageFormatName;
-  } else if (data.isUint16Array()) {
-    buffer_view = data.getAsUint16Array().View();
+  } else if (data.IsUint16Array()) {
+    buffer_view = data.GetAsUint16Array().View();
     storage_format_name = kUint16ArrayStorageFormatName;
-  } else if (data.isFloat32Array()) {
-    buffer_view = data.getAsFloat32Array().View();
+  } else if (data.IsFloat32Array()) {
+    buffer_view = data.GetAsFloat32Array().View();
     storage_format_name = kFloat32ArrayStorageFormatName;
   } else {
     NOTREACHED();
@@ -814,7 +814,7 @@
       data_ = const_cast<DOMUint8ClampedArray*>(
           static_cast<const DOMUint8ClampedArray*>(data));
       DCHECK(data_);
-      data_union_.setUint8ClampedArray(data_);
+      data_union_.SetUint8ClampedArray(data_);
       SECURITY_CHECK(static_cast<unsigned>(size.Width() * size.Height() * 4) <=
                      data_->length());
       break;
@@ -824,7 +824,7 @@
       data_u16_ =
           const_cast<DOMUint16Array*>(static_cast<const DOMUint16Array*>(data));
       DCHECK(data_u16_);
-      data_union_.setUint16Array(data_u16_);
+      data_union_.SetUint16Array(data_u16_);
       SECURITY_CHECK(static_cast<unsigned>(size.Width() * size.Height() * 4) <=
                      data_u16_->length());
       break;
@@ -834,7 +834,7 @@
       data_f32_ = const_cast<DOMFloat32Array*>(
           static_cast<const DOMFloat32Array*>(data));
       DCHECK(data_f32_);
-      data_union_.setFloat32Array(data_f32_);
+      data_union_.SetFloat32Array(data_f32_);
       SECURITY_CHECK(static_cast<unsigned>(size.Width() * size.Height() * 4) <=
                      data_f32_->length());
       break;
diff --git a/third_party/WebKit/Source/core/html/ImageDataTest.cpp b/third_party/WebKit/Source/core/html/ImageDataTest.cpp
index 36a0639..75ac7e3 100644
--- a/third_party/WebKit/Source/core/html/ImageDataTest.cpp
+++ b/third_party/WebKit/Source/core/html/ImageDataTest.cpp
@@ -476,7 +476,7 @@
             } else if (image_data_storage_formats[i] ==
                        kUint16ArrayStorageFormat) {
               if (cropped_image_data->dataUnion()
-                      .getAsUint16Array()
+                      .GetAsUint16Array()
                       .View()
                       ->Data()[index] != expected_value) {
                 test_passed = false;
@@ -484,7 +484,7 @@
               }
             } else {
               if (cropped_image_data->dataUnion()
-                      .getAsFloat32Array()
+                      .GetAsFloat32Array()
                       .View()
                       ->Data()[index] != fexpected_value) {
                 test_passed = false;
diff --git a/third_party/WebKit/Source/core/html/LabelsNodeList.cpp b/third_party/WebKit/Source/core/html/LabelsNodeList.cpp
index 0b3177a5..e06c17f 100644
--- a/third_party/WebKit/Source/core/html/LabelsNodeList.cpp
+++ b/third_party/WebKit/Source/core/html/LabelsNodeList.cpp
@@ -42,7 +42,7 @@
 LabelsNodeList::~LabelsNodeList() {}
 
 bool LabelsNodeList::ElementMatches(const Element& element) const {
-  return isHTMLLabelElement(element) &&
+  return IsHTMLLabelElement(element) &&
          toHTMLLabelElement(element).control() == ownerNode();
 }
 
diff --git a/third_party/WebKit/Source/core/html/ListItemOrdinal.cpp b/third_party/WebKit/Source/core/html/ListItemOrdinal.cpp
index c3c2ac7..a2daaea 100644
--- a/third_party/WebKit/Source/core/html/ListItemOrdinal.cpp
+++ b/third_party/WebKit/Source/core/html/ListItemOrdinal.cpp
@@ -31,17 +31,19 @@
 #include "core/html/HTMLOListElement.h"
 #include "core/layout/LayoutListItem.h"
 #include "core/layout/api/LayoutLIItem.h"
+#include "core/layout/ng/layout_ng_list_item.h"
 
 namespace blink {
 
 ListItemOrdinal::ListItemOrdinal() : type_(kNeedsUpdate), not_in_list_(false) {}
 
 bool ListItemOrdinal::IsList(const Node& node) {
-  return isHTMLUListElement(node) || isHTMLOListElement(node);
+  return IsHTMLUListElement(node) || IsHTMLOListElement(node);
 }
 
 bool ListItemOrdinal::IsListItem(const LayoutObject* layout_object) {
-  return layout_object && layout_object->IsListItem();
+  return layout_object &&
+         (layout_object->IsListItem() || layout_object->IsLayoutNGListItem());
 }
 
 bool ListItemOrdinal::IsListItem(const Node& node) {
@@ -50,8 +52,12 @@
 
 ListItemOrdinal* ListItemOrdinal::Get(const Node& item_node) {
   LayoutObject* layout_object = item_node.GetLayoutObject();
-  if (layout_object && layout_object->IsListItem())
-    return &ToLayoutListItem(layout_object)->Ordinal();
+  if (layout_object) {
+    if (layout_object->IsListItem())
+      return &ToLayoutListItem(layout_object)->Ordinal();
+    if (layout_object->IsLayoutNGListItem())
+      return &ToLayoutNGListItem(layout_object)->Ordinal();
+  }
   return nullptr;
 }
 
@@ -155,8 +161,7 @@
     return value_;
 
   Node* list = EnclosingList(&item_node);
-  HTMLOListElement* o_list_element =
-      isHTMLOListElement(list) ? toHTMLOListElement(list) : nullptr;
+  HTMLOListElement* o_list_element = ToHTMLOListElementOrNull(list);
   int value_step = 1;
   if (o_list_element && o_list_element->IsReversed())
     value_step = -1;
@@ -186,8 +191,10 @@
   SetType(type);
 
   LayoutObject* layout_object = item_node.GetLayoutObject();
-  if (IsListItem(layout_object))
+  if (layout_object->IsListItem())
     ToLayoutListItem(layout_object)->OrdinalValueChanged();
+  else if (layout_object->IsLayoutNGListItem())
+    ToLayoutNGListItem(layout_object)->OrdinalValueChanged();
 }
 
 // Invalidate items after |item_node| in the DOM order.
@@ -261,7 +268,7 @@
 }
 
 void ListItemOrdinal::ItemInsertedOrRemoved(
-    const LayoutListItem* layout_list_item) {
+    const LayoutObject* layout_list_item) {
   // If distribution recalc is needed, updateListMarkerNumber will be re-invoked
   // after distribution is calculated.
   const Node* item_node = layout_list_item->GetNode();
@@ -272,9 +279,7 @@
   CHECK(list_node);
 
   bool is_list_reversed = false;
-  HTMLOListElement* o_list_element =
-      isHTMLOListElement(list_node) ? toHTMLOListElement(list_node) : 0;
-  if (o_list_element) {
+  if (auto* o_list_element = ToHTMLOListElementOrNull(list_node)) {
     o_list_element->ItemCountChanged();
     is_list_reversed = o_list_element->IsReversed();
   }
diff --git a/third_party/WebKit/Source/core/html/ListItemOrdinal.h b/third_party/WebKit/Source/core/html/ListItemOrdinal.h
index b3580fe6..744e613 100644
--- a/third_party/WebKit/Source/core/html/ListItemOrdinal.h
+++ b/third_party/WebKit/Source/core/html/ListItemOrdinal.h
@@ -34,7 +34,6 @@
 namespace blink {
 
 class HTMLOListElement;
-class LayoutListItem;
 class LayoutObject;
 class Node;
 
@@ -76,7 +75,7 @@
   static void InvalidateAllItemsForOrderedList(const HTMLOListElement*);
 
   // Invalidate items that are affected by an insertion or a removal.
-  static void ItemInsertedOrRemoved(const LayoutListItem*);
+  static void ItemInsertedOrRemoved(const LayoutObject*);
 
  private:
   enum ValueType { kNeedsUpdate, kUpdated, kExplicit };
diff --git a/third_party/WebKit/Source/core/html/ListedElement.cpp b/third_party/WebKit/Source/core/html/ListedElement.cpp
index a4a746a8..3412539 100644
--- a/third_party/WebKit/Source/core/html/ListedElement.cpp
+++ b/third_party/WebKit/Source/core/html/ListedElement.cpp
@@ -115,9 +115,7 @@
     // 3.2. Abort the "reset the form owner" steps.
     Element* new_form_candidate =
         element->GetTreeScope().getElementById(form_id);
-    return isHTMLFormElement(new_form_candidate)
-               ? toHTMLFormElement(new_form_candidate)
-               : 0;
+    return ToHTMLFormElementOrNull(new_form_candidate);
   }
   // 4. Otherwise, if the form-associated element in question has an ancestor
   // form element, then associate the form-associated element with the nearest
diff --git a/third_party/WebKit/Source/core/html/RadioNodeList.cpp b/third_party/WebKit/Source/core/html/RadioNodeList.cpp
index 3e82cad..c7620534 100644
--- a/third_party/WebKit/Source/core/html/RadioNodeList.cpp
+++ b/third_party/WebKit/Source/core/html/RadioNodeList.cpp
@@ -44,14 +44,14 @@
     : LiveNodeList(root_node,
                    type,
                    kInvalidateForFormControls,
-                   isHTMLFormElement(root_node) ? NodeListRootType::kTreeScope
+                   IsHTMLFormElement(root_node) ? NodeListRootType::kTreeScope
                                                 : NodeListRootType::kNode),
       name_(name) {}
 
 RadioNodeList::~RadioNodeList() {}
 
 static inline HTMLInputElement* ToRadioButtonInputElement(Element& element) {
-  if (!isHTMLInputElement(element))
+  if (!IsHTMLInputElement(element))
     return nullptr;
   HTMLInputElement& input_element = toHTMLInputElement(element);
   if (input_element.type() != InputTypeNames::radio ||
@@ -94,9 +94,9 @@
 bool RadioNodeList::CheckElementMatchesRadioNodeListFilter(
     const Element& test_element) const {
   DCHECK(!ShouldOnlyMatchImgElements());
-  DCHECK(isHTMLObjectElement(test_element) ||
+  DCHECK(IsHTMLObjectElement(test_element) ||
          test_element.IsFormControlElement());
-  if (isHTMLFormElement(ownerNode())) {
+  if (IsHTMLFormElement(ownerNode())) {
     HTMLFormElement* form_element = ToHTMLElement(test_element).formOwner();
     if (!form_element || form_element != ownerNode())
       return false;
@@ -107,7 +107,7 @@
 
 bool RadioNodeList::ElementMatches(const Element& element) const {
   if (ShouldOnlyMatchImgElements()) {
-    if (!isHTMLImageElement(element))
+    if (!IsHTMLImageElement(element))
       return false;
 
     if (toHTMLImageElement(element).formOwner() != ownerNode())
@@ -116,10 +116,10 @@
     return MatchesByIdOrName(element);
   }
 
-  if (!isHTMLObjectElement(element) && !element.IsFormControlElement())
+  if (!IsHTMLObjectElement(element) && !element.IsFormControlElement())
     return false;
 
-  if (isHTMLInputElement(element) &&
+  if (IsHTMLInputElement(element) &&
       toHTMLInputElement(element).type() == InputTypeNames::image)
     return false;
 
diff --git a/third_party/WebKit/Source/core/html/TextControlElement.cpp b/third_party/WebKit/Source/core/html/TextControlElement.cpp
index 1eb27c7..524d681 100644
--- a/third_party/WebKit/Source/core/html/TextControlElement.cpp
+++ b/third_party/WebKit/Source/core/html/TextControlElement.cpp
@@ -636,7 +636,7 @@
   Node* end_node = 0;
   for (Node& node : NodeTraversal::DescendantsOf(*inner_text)) {
     DCHECK(!node.hasChildren());
-    DCHECK(node.IsTextNode() || isHTMLBRElement(node));
+    DCHECK(node.IsTextNode() || IsHTMLBRElement(node));
     int length = node.IsTextNode() ? Position::LastOffsetInNode(node) : 1;
 
     if (offset <= start && start <= offset + length)
@@ -811,7 +811,7 @@
 
   // If the last child is a trailing <br> that's appended below, remove it
   // first so as to enable setInnerText() fast path of updating a text node.
-  if (isHTMLBRElement(inner_editor->lastChild()))
+  if (IsHTMLBRElement(inner_editor->lastChild()))
     inner_editor->RemoveChild(inner_editor->lastChild(), ASSERT_NO_EXCEPTION);
 
   // We don't use setTextContent.  It triggers unnecessary paint.
@@ -844,15 +844,15 @@
     Node* second_child = first_child.nextSibling();
     if (!second_child)
       return ToText(first_child).data();
-    if (!second_child->nextSibling() && isHTMLBRElement(*second_child))
+    if (!second_child->nextSibling() && IsHTMLBRElement(*second_child))
       return ToText(first_child).data();
-  } else if (!first_child.nextSibling() && isHTMLBRElement(first_child)) {
+  } else if (!first_child.nextSibling() && IsHTMLBRElement(first_child)) {
     return g_empty_string;
   }
 
   StringBuilder result;
   for (Node& node : NodeTraversal::InclusiveDescendantsOf(*inner_editor)) {
-    if (isHTMLBRElement(node)) {
+    if (IsHTMLBRElement(node)) {
       DCHECK_EQ(&node, inner_editor->lastChild());
       if (&node != inner_editor->lastChild())
         result.Append(kNewlineCharacter);
@@ -904,7 +904,7 @@
 
   StringBuilder result;
   for (Node& node : NodeTraversal::DescendantsOf(*inner_text)) {
-    if (isHTMLBRElement(node)) {
+    if (IsHTMLBRElement(node)) {
       DCHECK_EQ(&node, inner_text->lastChild());
       if (&node != inner_text->lastChild())
         result.Append(kNewlineCharacter);
diff --git a/third_party/WebKit/Source/core/html/WindowNameCollection.cpp b/third_party/WebKit/Source/core/html/WindowNameCollection.cpp
index aa644944..2b87fb4f 100644
--- a/third_party/WebKit/Source/core/html/WindowNameCollection.cpp
+++ b/third_party/WebKit/Source/core/html/WindowNameCollection.cpp
@@ -15,8 +15,8 @@
 bool WindowNameCollection::ElementMatches(const Element& element) const {
   // Match only images, forms, embeds and objects by name,
   // but anything by id
-  if (isHTMLImageElement(element) || isHTMLFormElement(element) ||
-      isHTMLEmbedElement(element) || isHTMLObjectElement(element)) {
+  if (IsHTMLImageElement(element) || IsHTMLFormElement(element) ||
+      IsHTMLEmbedElement(element) || IsHTMLObjectElement(element)) {
     if (element.GetNameAttribute() == name_)
       return true;
   }
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasFontCache.cpp b/third_party/WebKit/Source/core/html/canvas/CanvasFontCache.cpp
index a578b5d8..c6165d1 100644
--- a/third_party/WebKit/Source/core/html/canvas/CanvasFontCache.cpp
+++ b/third_party/WebKit/Source/core/html/canvas/CanvasFontCache.cpp
@@ -76,8 +76,8 @@
     return false;
 
   RefPtr<ComputedStyle> font_style =
-      ComputedStyle::Clone(*default_font_style_.Get());
-  document_->EnsureStyleResolver().ComputeFont(font_style.Get(), *parsed_style);
+      ComputedStyle::Clone(*default_font_style_.get());
+  document_->EnsureStyleResolver().ComputeFont(font_style.get(), *parsed_style);
   fonts_resolved_using_default_style_.insert(font_string,
                                              font_style->GetFont());
   resolved_font = fonts_resolved_using_default_style_.find(font_string)->value;
diff --git a/third_party/WebKit/Source/core/html/forms/ExternalPopupMenu.cpp b/third_party/WebKit/Source/core/html/forms/ExternalPopupMenu.cpp
index e1887b9..9ef064b 100644
--- a/third_party/WebKit/Source/core/html/forms/ExternalPopupMenu.cpp
+++ b/third_party/WebKit/Source/core/html/forms/ExternalPopupMenu.cpp
@@ -251,9 +251,9 @@
     popup_item.label = owner_element.ItemText(item_element);
     popup_item.tool_tip = item_element.title();
     popup_item.checked = false;
-    if (isHTMLHRElement(item_element)) {
+    if (IsHTMLHRElement(item_element)) {
       popup_item.type = WebMenuItemInfo::kSeparator;
-    } else if (isHTMLOptGroupElement(item_element)) {
+    } else if (IsHTMLOptGroupElement(item_element)) {
       popup_item.type = WebMenuItemInfo::kGroup;
     } else {
       popup_item.type = WebMenuItemInfo::kOption;
diff --git a/third_party/WebKit/Source/core/html/forms/FileChooser.cpp b/third_party/WebKit/Source/core/html/forms/FileChooser.cpp
index d97509d..b87a17c 100644
--- a/third_party/WebKit/Source/core/html/forms/FileChooser.cpp
+++ b/third_party/WebKit/Source/core/html/forms/FileChooser.cpp
@@ -38,7 +38,7 @@
     chooser_->DisconnectClient();
 
   chooser_ = FileChooser::Create(this, params);
-  return chooser_.Get();
+  return chooser_.get();
 }
 
 inline FileChooser::FileChooser(FileChooserClient* client,
diff --git a/third_party/WebKit/Source/core/html/forms/InternalPopupMenu.cpp b/third_party/WebKit/Source/core/html/forms/InternalPopupMenu.cpp
index 25654c0..058044c 100644
--- a/third_party/WebKit/Source/core/html/forms/InternalPopupMenu.cpp
+++ b/third_party/WebKit/Source/core/html/forms/InternalPopupMenu.cpp
@@ -272,14 +272,14 @@
   const HeapVector<Member<HTMLElement>>& items = owner_element.GetListItems();
   for (; context.list_index_ < items.size(); ++context.list_index_) {
     Element& child = *items[context.list_index_];
-    if (!isHTMLOptGroupElement(child.parentNode()))
+    if (!IsHTMLOptGroupElement(child.parentNode()))
       context.FinishGroupIfNecessary();
-    if (isHTMLOptionElement(child))
-      AddOption(context, toHTMLOptionElement(child));
-    else if (isHTMLOptGroupElement(child))
-      AddOptGroup(context, toHTMLOptGroupElement(child));
-    else if (isHTMLHRElement(child))
-      AddSeparator(context, toHTMLHRElement(child));
+    if (auto* option = ToHTMLOptionElementOrNull(child))
+      AddOption(context, *option);
+    else if (auto* optgroup = ToHTMLOptGroupElementOrNull(child))
+      AddOptGroup(context, *optgroup);
+    else if (auto* hr = ToHTMLHRElementOrNull(child))
+      AddSeparator(context, *hr);
   }
   context.FinishGroupIfNecessary();
   PagePopupClient::AddString("],\n", data);
@@ -524,30 +524,30 @@
   }
 
   RefPtr<SharedBuffer> data = SharedBuffer::Create();
-  PagePopupClient::AddString("window.updateData = {\n", data.Get());
-  PagePopupClient::AddString("type: \"update\",\n", data.Get());
-  ItemIterationContext context(*owner_element_->GetComputedStyle(), data.Get());
+  PagePopupClient::AddString("window.updateData = {\n", data.get());
+  PagePopupClient::AddString("type: \"update\",\n", data.get());
+  ItemIterationContext context(*owner_element_->GetComputedStyle(), data.get());
   context.SerializeBaseStyle();
-  PagePopupClient::AddString("children: [", data.Get());
+  PagePopupClient::AddString("children: [", data.get());
   const HeapVector<Member<HTMLElement>>& items = owner_element_->GetListItems();
   for (; context.list_index_ < items.size(); ++context.list_index_) {
     Element& child = *items[context.list_index_];
-    if (!isHTMLOptGroupElement(child.parentNode()))
+    if (!IsHTMLOptGroupElement(child.parentNode()))
       context.FinishGroupIfNecessary();
-    if (isHTMLOptionElement(child))
-      AddOption(context, toHTMLOptionElement(child));
-    else if (isHTMLOptGroupElement(child))
-      AddOptGroup(context, toHTMLOptGroupElement(child));
-    else if (isHTMLHRElement(child))
-      AddSeparator(context, toHTMLHRElement(child));
+    if (auto* option = ToHTMLOptionElementOrNull(child))
+      AddOption(context, *option);
+    else if (auto* optgroup = ToHTMLOptGroupElementOrNull(child))
+      AddOptGroup(context, *optgroup);
+    else if (auto* hr = ToHTMLHRElementOrNull(child))
+      AddSeparator(context, *hr);
   }
   context.FinishGroupIfNecessary();
-  PagePopupClient::AddString("],\n", data.Get());
+  PagePopupClient::AddString("],\n", data.get());
   IntRect anchor_rect_in_screen = chrome_client_->ViewportToScreen(
       owner_element_->VisibleBoundsInVisualViewport(),
       OwnerElement().GetDocument().View());
-  AddProperty("anchorRectInScreen", anchor_rect_in_screen, data.Get());
-  PagePopupClient::AddString("}\n", data.Get());
+  AddProperty("anchorRectInScreen", anchor_rect_in_screen, data.get());
+  PagePopupClient::AddString("}\n", data.get());
   popup_->PostMessage(String::FromUTF8(data->Data(), data->size()));
 }
 
diff --git a/third_party/WebKit/Source/core/html/forms/OptionList.cpp b/third_party/WebKit/Source/core/html/forms/OptionList.cpp
index 2a8bd1b..87cda3e 100644
--- a/third_party/WebKit/Source/core/html/forms/OptionList.cpp
+++ b/third_party/WebKit/Source/core/html/forms/OptionList.cpp
@@ -23,11 +23,11 @@
     current = ElementTraversal::FirstChild(*select_);
   }
   while (current) {
-    if (isHTMLOptionElement(current)) {
-      current_ = toHTMLOptionElement(current);
+    if (auto* option = ToHTMLOptionElementOrNull(current)) {
+      current_ = option;
       return;
     }
-    if (isHTMLOptGroupElement(current) &&
+    if (IsHTMLOptGroupElement(current) &&
         current->parentNode() == select_.Get()) {
       if ((current_ = Traversal<HTMLOptionElement>::FirstChild(*current)))
         return;
diff --git a/third_party/WebKit/Source/core/html/forms/RadioInputType.cpp b/third_party/WebKit/Source/core/html/forms/RadioInputType.cpp
index 1e78751..ca2d13c 100644
--- a/third_party/WebKit/Source/core/html/forms/RadioInputType.cpp
+++ b/third_party/WebKit/Source/core/html/forms/RadioInputType.cpp
@@ -162,12 +162,10 @@
   // skip any other elements in the group.
   Element* current_focused_element =
       GetElement().GetDocument().FocusedElement();
-  if (isHTMLInputElement(current_focused_element)) {
-    HTMLInputElement& focused_input =
-        toHTMLInputElement(*current_focused_element);
-    if (focused_input.type() == InputTypeNames::radio &&
-        focused_input.Form() == GetElement().Form() &&
-        focused_input.GetName() == GetElement().GetName())
+  if (auto* focused_input = ToHTMLInputElementOrNull(current_focused_element)) {
+    if (focused_input->type() == InputTypeNames::radio &&
+        focused_input->Form() == GetElement().Form() &&
+        focused_input->GetName() == GetElement().GetName())
       return false;
   }
 
diff --git a/third_party/WebKit/Source/core/html/media/MediaDocument.cpp b/third_party/WebKit/Source/core/html/media/MediaDocument.cpp
index 85a70fe..ef7a53b 100644
--- a/third_party/WebKit/Source/core/html/media/MediaDocument.cpp
+++ b/third_party/WebKit/Source/core/html/media/MediaDocument.cpp
@@ -134,7 +134,7 @@
     AddEventListenerOptions options;
     options.setOnce(true);
     AddEventListenerOptionsOrBoolean options_or_boolean;
-    options_or_boolean.setAddEventListenerOptions(options);
+    options_or_boolean.SetAddEventListenerOptions(options);
     media->addEventListener(EventTypeNames::loadedmetadata, listener,
                             options_or_boolean);
   }
diff --git a/third_party/WebKit/Source/core/html/parser/AtomicHTMLToken.h b/third_party/WebKit/Source/core/html/parser/AtomicHTMLToken.h
index 0a793264..f8e3934 100644
--- a/third_party/WebKit/Source/core/html/parser/AtomicHTMLToken.h
+++ b/third_party/WebKit/Source/core/html/parser/AtomicHTMLToken.h
@@ -114,9 +114,9 @@
       case HTMLToken::kStartTag:
       case HTMLToken::kEndTag: {
         self_closing_ = token.SelfClosing();
-        if (StringImpl* tag_name =
+        if (const AtomicString& tag_name =
                 lookupHTMLTag(token.GetName().data(), token.GetName().size()))
-          name_ = AtomicString(tag_name);
+          name_ = tag_name;
         else
           name_ = AtomicString(token.GetName());
         InitializeAttributes(token.Attributes());
@@ -229,7 +229,13 @@
     attribute.NameRange().CheckValid();
     attribute.ValueRange().CheckValid();
 
-    AtomicString value(attribute.Value8BitIfNecessary());
+    AtomicString value(attribute.ValueAsVector());
+    // attribute.ValueAsVector.data() is null for attributes with no values, but
+    // the null atom is used to represent absence of attributes; attributes with
+    // no values have the value set to an empty atom instead.
+    if (value == g_null_atom) {
+      value = g_empty_atom;
+    }
     const QualifiedName& name = NameForAttribute(attribute);
     // FIXME: This is N^2 for the number of attributes.
     if (!FindAttributeInVector(attributes_, name))
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp b/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp
index 4353f661..59134a4 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp
@@ -85,8 +85,8 @@
 }
 
 static bool ShouldUseLengthLimit(const ContainerNode& node) {
-  return !isHTMLScriptElement(node) && !isHTMLStyleElement(node) &&
-         !isSVGScriptElement(node);
+  return !IsHTMLScriptElement(node) && !IsHTMLStyleElement(node) &&
+         !IsSVGScriptElement(node);
 }
 
 static unsigned TextLengthLimitForContainer(const ContainerNode& node) {
@@ -99,8 +99,8 @@
 }
 
 static inline void Insert(HTMLConstructionSiteTask& task) {
-  if (isHTMLTemplateElement(*task.parent))
-    task.parent = toHTMLTemplateElement(task.parent.Get())->content();
+  if (auto* template_element = ToHTMLTemplateElementOrNull(*task.parent))
+    task.parent = template_element->content();
 
   // https://html.spec.whatwg.org/#insert-a-foreign-element
   // 3.1, (3) Push (pop) an element queue
@@ -752,9 +752,8 @@
     FindFosterSite(dummy_task);
 
   // FIXME: This probably doesn't need to be done both here and in insert(Task).
-  if (isHTMLTemplateElement(*dummy_task.parent))
-    dummy_task.parent =
-        toHTMLTemplateElement(dummy_task.parent.Get())->content();
+  if (auto* template_element = ToHTMLTemplateElementOrNull(*dummy_task.parent))
+    dummy_task.parent = template_element->content();
 
   // Unclear when parent != case occurs. Somehow we insert text into two
   // separate nodes while processing the same Token. The nextChild !=
@@ -814,8 +813,8 @@
 }
 
 inline Document& HTMLConstructionSite::OwnerDocumentForCurrentNode() {
-  if (isHTMLTemplateElement(*CurrentNode()))
-    return toHTMLTemplateElement(CurrentElement())->content()->GetDocument();
+  if (auto* template_element = ToHTMLTemplateElementOrNull(*CurrentNode()))
+    return template_element->content()->GetDocument();
   return CurrentNode()->GetDocument();
 }
 
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
index 03da8be..8ce609f4 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
@@ -137,7 +137,7 @@
           TaskRunnerHelper::Get(TaskType::kNetworking, &document)),
       parser_scheduler_(
           sync_policy == kAllowAsynchronousParsing
-              ? HTMLParserScheduler::Create(this, loading_task_runner_.Get())
+              ? HTMLParserScheduler::Create(this, loading_task_runner_.get())
               : nullptr),
       xss_auditor_delegate_(&document),
       weak_factory_(this),
@@ -816,7 +816,7 @@
   config->xss_auditor->Init(GetDocument(), &xss_auditor_delegate_);
 
   config->decoder = TakeDecoder();
-  config->tokenized_chunk_queue = tokenized_chunk_queue_.Get();
+  config->tokenized_chunk_queue = tokenized_chunk_queue_.get();
   if (GetDocument()->GetSettings()) {
     if (GetDocument()
             ->GetSettings()
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h
index 4c86051..75f55fe 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h
+++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h
@@ -109,7 +109,7 @@
   void SuspendScheduledTasks() final;
   void ResumeScheduledTasks() final;
 
-  HTMLParserReentryPermit* ReentryPermit() { return reentry_permit_.Get(); }
+  HTMLParserReentryPermit* ReentryPermit() { return reentry_permit_.get(); }
 
   struct TokenizedChunk {
     USING_FAST_MALLOC(TokenizedChunk);
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLElementStack.cpp b/third_party/WebKit/Source/core/html/parser/HTMLElementStack.cpp
index 22a78725..902194f4 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLElementStack.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLElementStack.cpp
@@ -167,8 +167,8 @@
     Node& node = *TopNode();
     if (node.IsElementNode()) {
       ToElement(node).FinishParsingChildren();
-      if (isHTMLSelectElement(node))
-        ToHTMLFormControlElement(node).SetBlocksFormSubmission(true);
+      if (auto* select = ToHTMLSelectElementOrNull(node))
+        select->SetBlocksFormSubmission(true);
     }
     top_ = top_->ReleaseNext();
   }
@@ -351,7 +351,7 @@
 }
 
 void HTMLElementStack::Remove(Element* element) {
-  DCHECK(!isHTMLHeadElement(element));
+  DCHECK(!IsHTMLHeadElement(element));
   if (top_->GetElement() == element) {
     Pop();
     return;
@@ -505,8 +505,8 @@
 }
 
 void HTMLElementStack::RemoveNonTopCommon(Element* element) {
-  DCHECK(!isHTMLHtmlElement(element));
-  DCHECK(!isHTMLBodyElement(element));
+  DCHECK(!IsHTMLHtmlElement(element));
+  DCHECK(!IsHTMLBodyElement(element));
   DCHECK_NE(Top(), element);
   for (ElementRecord* pos = top_.Get(); pos; pos = pos->Next()) {
     if (pos->Next()->GetElement() == element) {
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLToken.h b/third_party/WebKit/Source/core/html/parser/HTMLToken.h
index e41c73b..761f497 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLToken.h
+++ b/third_party/WebKit/Source/core/html/parser/HTMLToken.h
@@ -115,6 +115,7 @@
       return AttemptStaticStringCreation(name_, kLikely8Bit);
     }
     const Vector<UChar, 32>& NameAsVector() const { return name_; }
+    const Vector<UChar, 32>& ValueAsVector() const { return value_; }
 
     void AppendToName(UChar c) { name_.push_back(c); }
 
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp b/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp
index 443a537..24b9e36 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp
@@ -152,7 +152,7 @@
     DCHECK(!IsEmpty());
     unsigned start = current_;
     current_ = end_;
-    return StringView(characters_.Get(), start, end_ - start);
+    return StringView(characters_.get(), start, end_ - start);
   }
 
   void GiveRemainingTo(StringBuilder& recipient) {
@@ -207,7 +207,7 @@
     DCHECK(!IsEmpty());
     const unsigned start = current_;
     SkipLeading<characterPredicate>();
-    return StringView(characters_.Get(), start, current_ - start);
+    return StringView(characters_.get(), start, current_ - start);
   }
 
   RefPtr<StringImpl> characters_;
@@ -249,7 +249,7 @@
   tree_.OpenElements()->PushRootNode(HTMLStackItem::Create(
       fragment, HTMLStackItem::kItemForDocumentFragmentNode));
 
-  if (isHTMLTemplateElement(*context_element))
+  if (IsHTMLTemplateElement(*context_element))
     template_insertion_modes_.push_back(kTemplateContentsMode);
 
   ResetInsertionModeAppropriately();
@@ -866,7 +866,7 @@
   if (!tree_.OpenElements()->HasTemplateInHTMLScope()) {
     DCHECK(template_insertion_modes_.IsEmpty() ||
            (template_insertion_modes_.size() == 1 &&
-            isHTMLTemplateElement(fragment_context_.ContextElement())));
+            IsHTMLTemplateElement(fragment_context_.ContextElement())));
     ParseError(token);
     return false;
   }
@@ -892,7 +892,7 @@
 
 bool HTMLTreeBuilder::ProcessColgroupEndTagForInColumnGroup() {
   if (tree_.CurrentIsRootNode() ||
-      isHTMLTemplateElement(*tree_.CurrentNode())) {
+      IsHTMLTemplateElement(*tree_.CurrentNode())) {
     DCHECK(IsParsingFragmentOrTemplateContents());
     // FIXME: parse error
     return false;
@@ -2420,7 +2420,7 @@
         return;  // FIXME: Should we break here instead of returning?
       }
       DCHECK(tree_.CurrentNode()->HasTagName(colgroupTag) ||
-             isHTMLTemplateElement(tree_.CurrentNode()));
+             IsHTMLTemplateElement(tree_.CurrentNode()));
       ProcessColgroupEndTagForInColumnGroup();
     // Fall through
     case kInFramesetMode:
@@ -2451,7 +2451,7 @@
         DVLOG(1) << "Not implemented.";
       }
       Element* el = tree_.OpenElements()->Top();
-      if (isHTMLTextAreaElement(el))
+      if (IsHTMLTextAreaElement(el))
         ToHTMLFormControlElement(el)->SetBlocksFormSubmission(true);
       tree_.OpenElements()->Pop();
       DCHECK_NE(original_insertion_mode_, kTextMode);
diff --git a/third_party/WebKit/Source/core/html/track/TextTrackContainer.cpp b/third_party/WebKit/Source/core/html/track/TextTrackContainer.cpp
index 4cfb1b9..076a15f 100644
--- a/third_party/WebKit/Source/core/html/track/TextTrackContainer.cpp
+++ b/third_party/WebKit/Source/core/html/track/TextTrackContainer.cpp
@@ -49,7 +49,7 @@
   void OnResize(
       const HeapVector<Member<ResizeObserverEntry>>& entries) override {
     DCHECK_EQ(entries.size(), 1u);
-    DCHECK(isHTMLVideoElement(entries[0]->target()));
+    DCHECK(IsHTMLVideoElement(entries[0]->target()));
     text_track_container_->UpdateDefaultFontSize(
         entries[0]->target()->GetLayoutObject());
   }
@@ -79,7 +79,7 @@
       new TextTrackContainer(media_element.GetDocument());
   element->SetShadowPseudoId(
       AtomicString("-webkit-media-text-track-container"));
-  if (isHTMLVideoElement(media_element))
+  if (IsHTMLVideoElement(media_element))
     element->ObserveSizeChanges(media_element);
   return element;
 }
@@ -134,7 +134,7 @@
   // 1. If the media element is an audio element, or is another playback
   // mechanism with no rendering area, abort these steps. There is nothing to
   // render.
-  if (isHTMLAudioElement(media_element))
+  if (IsHTMLAudioElement(media_element))
     return;
 
   // 2. Let video be the media element or other playback mechanism.
diff --git a/third_party/WebKit/Source/core/html/track/TrackEvent.cpp b/third_party/WebKit/Source/core/html/track/TrackEvent.cpp
index 5f97647..82f1ff1 100644
--- a/third_party/WebKit/Source/core/html/track/TrackEvent.cpp
+++ b/third_party/WebKit/Source/core/html/track/TrackEvent.cpp
@@ -42,12 +42,12 @@
     return;
 
   const VideoTrackOrAudioTrackOrTextTrack& track = initializer.track();
-  if (track.isVideoTrack())
-    track_ = track.getAsVideoTrack();
-  else if (track.isAudioTrack())
-    track_ = track.getAsAudioTrack();
-  else if (track.isTextTrack())
-    track_ = track.getAsTextTrack();
+  if (track.IsVideoTrack())
+    track_ = track.GetAsVideoTrack();
+  else if (track.IsAudioTrack())
+    track_ = track.GetAsAudioTrack();
+  else if (track.IsTextTrack())
+    track_ = track.GetAsTextTrack();
   else
     NOTREACHED();
 }
@@ -64,13 +64,13 @@
 
   switch (track_->GetType()) {
     case WebMediaPlayer::kTextTrack:
-      return_value.setTextTrack(ToTextTrack(track_.Get()));
+      return_value.SetTextTrack(ToTextTrack(track_.Get()));
       break;
     case WebMediaPlayer::kAudioTrack:
-      return_value.setAudioTrack(ToAudioTrack(track_.Get()));
+      return_value.SetAudioTrack(ToAudioTrack(track_.Get()));
       break;
     case WebMediaPlayer::kVideoTrack:
-      return_value.setVideoTrack(ToVideoTrack(track_.Get()));
+      return_value.SetVideoTrack(ToVideoTrack(track_.Get()));
       break;
     default:
       NOTREACHED();
diff --git a/third_party/WebKit/Source/core/html/track/vtt/VTTCue.cpp b/third_party/WebKit/Source/core/html/track/vtt/VTTCue.cpp
index 56301d3..b2cbfdc 100644
--- a/third_party/WebKit/Source/core/html/track/vtt/VTTCue.cpp
+++ b/third_party/WebKit/Source/core/html/track/vtt/VTTCue.cpp
@@ -311,9 +311,9 @@
 
 void VTTCue::line(DoubleOrAutoKeyword& result) const {
   if (LineIsAuto())
-    result.setAutoKeyword(AutoKeyword());
+    result.SetAutoKeyword(AutoKeyword());
   else
-    result.setDouble(line_position_);
+    result.SetDouble(line_position_);
 }
 
 void VTTCue::setLine(const DoubleOrAutoKeyword& position) {
@@ -322,13 +322,13 @@
   // value is the string "auto", then it must be interpreted as the special
   // value auto.  ("auto" is translated to NaN.)
   float float_position;
-  if (position.isAutoKeyword()) {
+  if (position.IsAutoKeyword()) {
     if (LineIsAuto())
       return;
     float_position = std::numeric_limits<float>::quiet_NaN();
   } else {
-    DCHECK(position.isDouble());
-    float_position = clampTo<float>(position.getAsDouble());
+    DCHECK(position.IsDouble());
+    float_position = clampTo<float>(position.GetAsDouble());
     if (line_position_ == float_position)
       return;
   }
@@ -344,9 +344,9 @@
 
 void VTTCue::position(DoubleOrAutoKeyword& result) const {
   if (TextPositionIsAuto())
-    result.setAutoKeyword(AutoKeyword());
+    result.SetAutoKeyword(AutoKeyword());
   else
-    result.setDouble(text_position_);
+    result.SetDouble(text_position_);
 }
 
 void VTTCue::setPosition(const DoubleOrAutoKeyword& position,
@@ -357,15 +357,15 @@
   // position must be set to the new value; if the new value is the string
   // "auto", then it must be interpreted as the special value auto.
   float float_position;
-  if (position.isAutoKeyword()) {
+  if (position.IsAutoKeyword()) {
     if (TextPositionIsAuto())
       return;
     float_position = std::numeric_limits<float>::quiet_NaN();
   } else {
-    DCHECK(position.isDouble());
-    if (IsInvalidPercentage(position.getAsDouble(), exception_state))
+    DCHECK(position.IsDouble());
+    if (IsInvalidPercentage(position.GetAsDouble(), exception_state))
       return;
-    float_position = clampTo<float>(position.getAsDouble());
+    float_position = clampTo<float>(position.GetAsDouble());
     if (text_position_ == float_position)
       return;
   }
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.cpp b/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.cpp
index b151b2c..24c24db 100644
--- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.cpp
+++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.cpp
@@ -210,7 +210,7 @@
   RefPtr<Uint8Array> image_pixels = CopyImageData(input);
   if (!image_pixels)
     return nullptr;
-  SkImageInfo info = GetSkImageInfo(input.Get());
+  SkImageInfo info = GetSkImageInfo(input.get());
   unsigned image_row_bytes = info.width() * info.bytesPerPixel();
   for (int i = 0; i < info.height() / 2; i++) {
     unsigned top_first_element = i * image_row_bytes;
@@ -233,7 +233,7 @@
   if (skia_image->alphaType() == alpha_type)
     return image;
 
-  SkImageInfo info = GetSkImageInfo(image.Get());
+  SkImageInfo info = GetSkImageInfo(image.get());
   info = info.makeAlphaType(alpha_type);
   RefPtr<Uint8Array> dst_pixels = CopyImageData(image, info);
   if (!dst_pixels)
@@ -482,7 +482,7 @@
     return;
   DCHECK(image_input->IsStaticBitmapImage());
   RefPtr<StaticBitmapImage> input =
-      static_cast<StaticBitmapImage*>(image_input.Get());
+      static_cast<StaticBitmapImage*>(image_input.get());
 
   ParsedOptions parsed_options = ParseOptions(
       options, crop_rect, IntSize(input->width(), input->height()));
@@ -506,7 +506,7 @@
       FloatSize(offscreen_canvas->Size()));
   DCHECK(raw_input->IsStaticBitmapImage());
   RefPtr<StaticBitmapImage> input =
-      static_cast<StaticBitmapImage*>(raw_input.Get());
+      static_cast<StaticBitmapImage*>(raw_input.get());
   raw_input = nullptr;
 
   if (status != kNormalSourceImageStatus)
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp
index b5cb13f..6e49e65 100644
--- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp
+++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp
@@ -80,42 +80,42 @@
   DEFINE_THREAD_SAFE_STATIC_LOCAL(
       EnumerationHistogram, image_bitmap_source_histogram,
       ("Canvas.CreateImageBitmapSource", kCreateImageBitmapSourceCount));
-  if (value.isHTMLVideoElement()) {
+  if (value.IsHTMLVideoElement()) {
     image_bitmap_source_histogram.Count(
         kCreateImageBitmapSourceHTMLVideoElement);
-    return value.getAsHTMLVideoElement();
+    return value.GetAsHTMLVideoElement();
   }
-  if (value.isHTMLImageElement()) {
+  if (value.IsHTMLImageElement()) {
     image_bitmap_source_histogram.Count(
         kCreateImageBitmapSourceHTMLImageElement);
-    return value.getAsHTMLImageElement();
+    return value.GetAsHTMLImageElement();
   }
-  if (value.isSVGImageElement()) {
+  if (value.IsSVGImageElement()) {
     image_bitmap_source_histogram.Count(
         kCreateImageBitmapSourceSVGImageElement);
-    return value.getAsSVGImageElement();
+    return value.GetAsSVGImageElement();
   }
-  if (value.isHTMLCanvasElement()) {
+  if (value.IsHTMLCanvasElement()) {
     image_bitmap_source_histogram.Count(
         kCreateImageBitmapSourceHTMLCanvasElement);
-    return value.getAsHTMLCanvasElement();
+    return value.GetAsHTMLCanvasElement();
   }
-  if (value.isBlob()) {
+  if (value.IsBlob()) {
     image_bitmap_source_histogram.Count(kCreateImageBitmapSourceBlob);
-    return value.getAsBlob();
+    return value.GetAsBlob();
   }
-  if (value.isImageData()) {
+  if (value.IsImageData()) {
     image_bitmap_source_histogram.Count(kCreateImageBitmapSourceImageData);
-    return value.getAsImageData();
+    return value.GetAsImageData();
   }
-  if (value.isImageBitmap()) {
+  if (value.IsImageBitmap()) {
     image_bitmap_source_histogram.Count(kCreateImageBitmapSourceImageBitmap);
-    return value.getAsImageBitmap();
+    return value.GetAsImageBitmap();
   }
-  if (value.isOffscreenCanvas()) {
+  if (value.IsOffscreenCanvas()) {
     image_bitmap_source_histogram.Count(
         kCreateImageBitmapSourceOffscreenCanvas);
-    return value.getAsOffscreenCanvas();
+    return value.GetAsOffscreenCanvas();
   }
   NOTREACHED();
   return nullptr;
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapTest.cpp b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapTest.cpp
index 19391b0b..641d5ff 100644
--- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapTest.cpp
+++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapTest.cpp
@@ -112,7 +112,7 @@
   sk_sp<SkImage> image = surface->makeImageSnapshot();
   ImageResourceContent* original_image_resource =
       ImageResourceContent::CreateLoaded(
-          StaticBitmapImage::Create(image).Get());
+          StaticBitmapImage::Create(image).get());
   image_element->SetImageForTest(original_image_resource);
 
   Optional<IntRect> crop_rect =
@@ -180,7 +180,7 @@
   sk_sp<SkImage> raster_image = raster_surface->makeImageSnapshot();
   ImageResourceContent* original_image_resource =
       ImageResourceContent::CreateLoaded(
-          StaticBitmapImage::Create(raster_image).Get());
+          StaticBitmapImage::Create(raster_image).get());
   image->SetImageForTest(original_image_resource);
 
   const ImageBitmapOptions default_options;
@@ -195,7 +195,7 @@
           .GetSkImage());
 
   ImageResourceContent* new_image_resource = ImageResourceContent::CreateLoaded(
-      StaticBitmapImage::Create(image2_).Get());
+      StaticBitmapImage::Create(image2_).get());
   image->SetImageForTest(new_image_resource);
 
   {
@@ -297,7 +297,7 @@
 
   ImageResourceContent* original_image_resource =
       ImageResourceContent::CreateLoaded(
-          StaticBitmapImage::Create(image).Get());
+          StaticBitmapImage::Create(image).get());
   image_element->SetImageForTest(original_image_resource);
 
   Optional<IntRect> crop_rect = IntRect(0, 0, image->width(), image->height());
@@ -417,7 +417,7 @@
 
   ImageResourceContent* source_image_resource =
       ImageResourceContent::CreateLoaded(
-          StaticBitmapImage::Create(image).Get());
+          StaticBitmapImage::Create(image).get());
   image_element->SetImageForTest(source_image_resource);
 
   Optional<IntRect> crop_rect = IntRect(0, 0, image->width(), image->height());
diff --git a/third_party/WebKit/Source/core/input/EventHandler.cpp b/third_party/WebKit/Source/core/input/EventHandler.cpp
index 452b02d4..172d5d9 100644
--- a/third_party/WebKit/Source/core/input/EventHandler.cpp
+++ b/third_party/WebKit/Source/core/input/EventHandler.cpp
@@ -117,7 +117,7 @@
   if (!target_node || !target_node->parentNode())
     return true;
   return target_node->IsShadowRoot() &&
-         isHTMLInputElement(ToShadowRoot(target_node)->host());
+         IsHTMLInputElement(ToShadowRoot(target_node)->host());
 }
 
 }  // namespace
@@ -173,8 +173,7 @@
       should_only_fire_drag_over_event_(false),
       scroll_manager_(new ScrollManager(frame)),
       mouse_event_manager_(new MouseEventManager(frame, *scroll_manager_)),
-      mouse_wheel_event_manager_(
-          new MouseWheelEventManager(frame, *scroll_manager_)),
+      mouse_wheel_event_manager_(new MouseWheelEventManager(frame)),
       keyboard_event_manager_(
           new KeyboardEventManager(frame, *scroll_manager_)),
       pointer_event_manager_(
@@ -321,7 +320,7 @@
 }
 
 static bool IsSubmitImage(Node* node) {
-  return isHTMLInputElement(node) &&
+  return IsHTMLInputElement(node) &&
          toHTMLInputElement(node)->type() == InputTypeNames::image;
 }
 
@@ -2050,7 +2049,6 @@
 
   if (!scrollbar || !scrollbar->Enabled())
     return false;
-  scroll_manager_->SetFrameWasScrolledByUser();
   scrollbar->MouseDown(mev.Event());
   return true;
 }
diff --git a/third_party/WebKit/Source/core/input/MouseWheelEventManager.cpp b/third_party/WebKit/Source/core/input/MouseWheelEventManager.cpp
index 643f6da..00fb937 100644
--- a/third_party/WebKit/Source/core/input/MouseWheelEventManager.cpp
+++ b/third_party/WebKit/Source/core/input/MouseWheelEventManager.cpp
@@ -10,21 +10,18 @@
 #include "core/frame/LocalFrameView.h"
 #include "core/input/EventHandler.h"
 #include "core/input/EventHandlingUtil.h"
-#include "core/input/ScrollManager.h"
 #include "core/layout/HitTestRequest.h"
 #include "core/layout/HitTestResult.h"
 #include "core/layout/api/LayoutViewItem.h"
 #include "public/platform/WebMouseWheelEvent.h"
 
 namespace blink {
-MouseWheelEventManager::MouseWheelEventManager(LocalFrame& frame,
-                                               ScrollManager& scroll_manager)
-    : frame_(frame), wheel_target_(nullptr), scroll_manager_(scroll_manager) {}
+MouseWheelEventManager::MouseWheelEventManager(LocalFrame& frame)
+    : frame_(frame), wheel_target_(nullptr) {}
 
 DEFINE_TRACE(MouseWheelEventManager) {
   visitor->Trace(frame_);
   visitor->Trace(wheel_target_);
-  visitor->Trace(scroll_manager_);
 }
 
 void MouseWheelEventManager::Clear() {
@@ -98,8 +95,6 @@
   if (subframe) {
     WebInputEventResult result =
         subframe->GetEventHandler().HandleWheelEvent(event);
-    if (result != WebInputEventResult::kNotHandled)
-      scroll_manager_->SetFrameWasScrolledByUser();
     return result;
   }
 
diff --git a/third_party/WebKit/Source/core/input/MouseWheelEventManager.h b/third_party/WebKit/Source/core/input/MouseWheelEventManager.h
index 809ed02..f942b9a 100644
--- a/third_party/WebKit/Source/core/input/MouseWheelEventManager.h
+++ b/third_party/WebKit/Source/core/input/MouseWheelEventManager.h
@@ -15,7 +15,6 @@
 class LocalFrame;
 class LocalFrameView;
 class Node;
-class ScrollManager;
 class WebMouseWheelEvent;
 
 class MouseWheelEventManager final
@@ -23,7 +22,7 @@
   WTF_MAKE_NONCOPYABLE(MouseWheelEventManager);
 
  public:
-  explicit MouseWheelEventManager(LocalFrame&, ScrollManager&);
+  explicit MouseWheelEventManager(LocalFrame&);
   DECLARE_TRACE();
 
   void Clear();
@@ -37,7 +36,6 @@
 
   const Member<LocalFrame> frame_;
   Member<Node> wheel_target_;
-  Member<ScrollManager> scroll_manager_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/input/PointerEventManager.cpp b/third_party/WebKit/Source/core/input/PointerEventManager.cpp
index 8249a1f9..c16112f 100644
--- a/third_party/WebKit/Source/core/input/PointerEventManager.cpp
+++ b/third_party/WebKit/Source/core/input/PointerEventManager.cpp
@@ -392,9 +392,9 @@
     Node* node = hit_test_tesult.InnerNode();
     if (node) {
       pointer_event_target.target_frame = node->GetDocument().GetFrame();
-      if (isHTMLCanvasElement(node)) {
+      if (auto* canvas = ToHTMLCanvasElementOrNull(node)) {
         HitTestCanvasResult* hit_test_canvas_result =
-            toHTMLCanvasElement(node)->GetControlAndIdIfHitRegionExists(
+            canvas->GetControlAndIdIfHitRegionExists(
                 hit_test_tesult.PointInInnerNodeFrame());
         if (hit_test_canvas_result->GetControl())
           node = hit_test_canvas_result->GetControl();
diff --git a/third_party/WebKit/Source/core/input/ScrollManager.cpp b/third_party/WebKit/Source/core/input/ScrollManager.cpp
index 1e89292..791cd8b5 100644
--- a/third_party/WebKit/Source/core/input/ScrollManager.cpp
+++ b/third_party/WebKit/Source/core/input/ScrollManager.cpp
@@ -16,7 +16,6 @@
 #include "core/layout/LayoutBlock.h"
 #include "core/layout/LayoutEmbeddedContent.h"
 #include "core/layout/api/LayoutViewItem.h"
-#include "core/loader/DocumentLoader.h"
 #include "core/page/AutoscrollController.h"
 #include "core/page/Page.h"
 #include "core/page/scrolling/OverscrollController.h"
@@ -205,10 +204,8 @@
     ScrollResult result =
         cur_box->Scroll(granularity, ToScrollDelta(physical_direction, 1));
 
-    if (result.DidScroll()) {
-      SetFrameWasScrolledByUser();
+    if (result.DidScroll())
       return true;
-    }
 
     cur_box = cur_box->ContainingBlock();
   }
@@ -239,11 +236,6 @@
       .BubblingScroll(direction, granularity, frame_->DeprecatedLocalOwner());
 }
 
-void ScrollManager::SetFrameWasScrolledByUser() {
-  if (DocumentLoader* document_loader = frame_->Loader().GetDocumentLoader())
-    document_loader->GetInitialScrollState().was_scrolled_by_user = true;
-}
-
 void ScrollManager::CustomizedScroll(ScrollState& scroll_state) {
   if (scroll_state.FullyConsumed())
     return;
@@ -477,10 +469,8 @@
     GetPage()->GetOverscrollController().ResetAccumulated(did_scroll_x,
                                                           did_scroll_y);
 
-  if (did_scroll_x || did_scroll_y) {
-    SetFrameWasScrolledByUser();
+  if (did_scroll_x || did_scroll_y)
     return WebInputEventResult::kHandledSystem;
-  }
 
   return WebInputEventResult::kNotHandled;
 }
diff --git a/third_party/WebKit/Source/core/input/ScrollManager.h b/third_party/WebKit/Source/core/input/ScrollManager.h
index ff23ed62..bbe281c 100644
--- a/third_party/WebKit/Source/core/input/ScrollManager.h
+++ b/third_party/WebKit/Source/core/input/ScrollManager.h
@@ -68,8 +68,6 @@
                       Node* starting_node,
                       Node* mouse_press_node);
 
-  void SetFrameWasScrolledByUser();
-
   // TODO(crbug.com/616491): Consider moving all gesture related functions to
   // another class.
 
diff --git a/third_party/WebKit/Source/core/input/TouchEventManager.cpp b/third_party/WebKit/Source/core/input/TouchEventManager.cpp
index 70d24f5..d93e816 100644
--- a/third_party/WebKit/Source/core/input/TouchEventManager.cpp
+++ b/third_party/WebKit/Source/core/input/TouchEventManager.cpp
@@ -518,9 +518,9 @@
       Node* node = result.InnerNode();
       if (!node)
         return;
-      if (isHTMLCanvasElement(node)) {
+      if (auto* canvas = ToHTMLCanvasElementOrNull(node)) {
         HitTestCanvasResult* hit_test_canvas_result =
-            toHTMLCanvasElement(node)->GetControlAndIdIfHitRegionExists(
+            canvas->GetControlAndIdIfHitRegionExists(
                 result.PointInInnerNodeFrame());
         if (hit_test_canvas_result->GetControl())
           node = hit_test_canvas_result->GetControl();
diff --git a/third_party/WebKit/Source/core/inspector/BUILD.gn b/third_party/WebKit/Source/core/inspector/BUILD.gn
index 1379668..63babe0 100644
--- a/third_party/WebKit/Source/core/inspector/BUILD.gn
+++ b/third_party/WebKit/Source/core/inspector/BUILD.gn
@@ -90,6 +90,8 @@
     "MainThreadDebugger.h",
     "NetworkResourcesData.cpp",
     "NetworkResourcesData.h",
+    "ResolveNode.cpp",
+    "ResolveNode.h",
     "ThreadDebugger.cpp",
     "ThreadDebugger.h",
     "V8InspectorString.cpp",
diff --git a/third_party/WebKit/Source/core/inspector/ConsoleMessage.cpp b/third_party/WebKit/Source/core/inspector/ConsoleMessage.cpp
index 3a6ac9fa5..38c1b3a 100644
--- a/third_party/WebKit/Source/core/inspector/ConsoleMessage.cpp
+++ b/third_party/WebKit/Source/core/inspector/ConsoleMessage.cpp
@@ -5,6 +5,7 @@
 #include "core/inspector/ConsoleMessage.h"
 
 #include "bindings/core/v8/SourceLocation.h"
+#include "core/dom/Node.h"
 #include "platform/wtf/Assertions.h"
 #include "platform/wtf/CurrentTime.h"
 #include "public/web/WebConsoleMessage.h"
@@ -94,6 +95,14 @@
   return worker_id_;
 }
 
+Vector<DOMNodeId>& ConsoleMessage::Nodes() {
+  return nodes_;
+}
+
+void ConsoleMessage::SetNodes(Vector<DOMNodeId> nodes) {
+  nodes_ = std::move(nodes);
+}
+
 DEFINE_TRACE(ConsoleMessage) {}
 
 STATIC_ASSERT_ENUM(WebConsoleMessage::kLevelVerbose, kVerboseMessageLevel);
diff --git a/third_party/WebKit/Source/core/inspector/ConsoleMessage.h b/third_party/WebKit/Source/core/inspector/ConsoleMessage.h
index 8912ff0789..f2451374 100644
--- a/third_party/WebKit/Source/core/inspector/ConsoleMessage.h
+++ b/third_party/WebKit/Source/core/inspector/ConsoleMessage.h
@@ -6,6 +6,7 @@
 #define ConsoleMessage_h
 
 #include "core/CoreExport.h"
+#include "core/dom/DOMNodeIds.h"
 #include "core/inspector/ConsoleTypes.h"
 #include "platform/heap/Handle.h"
 #include "platform/wtf/Forward.h"
@@ -51,6 +52,8 @@
   MessageLevel Level() const;
   const String& Message() const;
   const String& WorkerId() const;
+  Vector<DOMNodeId>& Nodes();
+  void SetNodes(Vector<DOMNodeId> nodes);
 
   DECLARE_TRACE();
 
@@ -67,6 +70,7 @@
   unsigned long request_identifier_;
   double timestamp_;
   String worker_id_;
+  Vector<DOMNodeId> nodes_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/ConsoleTypes.h b/third_party/WebKit/Source/core/inspector/ConsoleTypes.h
index ca7835f..7536dca7 100644
--- a/third_party/WebKit/Source/core/inspector/ConsoleTypes.h
+++ b/third_party/WebKit/Source/core/inspector/ConsoleTypes.h
@@ -20,7 +20,8 @@
   kDeprecationMessageSource,
   kWorkerMessageSource,
   kViolationMessageSource,
-  kInterventionMessageSource
+  kInterventionMessageSource,
+  kRecommendationMessageSource
 };
 
 enum MessageLevel {
diff --git a/third_party/WebKit/Source/core/inspector/DOMPatchSupport.cpp b/third_party/WebKit/Source/core/inspector/DOMPatchSupport.cpp
index c89f95b..8a4d587e 100644
--- a/third_party/WebKit/Source/core/inspector/DOMPatchSupport.cpp
+++ b/third_party/WebKit/Source/core/inspector/DOMPatchSupport.cpp
@@ -139,12 +139,12 @@
     new_list.push_back(CreateDigest(child, 0));
   for (Node* child = fragment->firstChild(); child;
        child = child->nextSibling()) {
-    if (isHTMLHeadElement(*child) && !child->hasChildren() &&
+    if (IsHTMLHeadElement(*child) && !child->hasChildren() &&
         markup_copy.Find("</head>") == kNotFound) {
       // HTML5 parser inserts empty <head> tag whenever it parses <body>
       continue;
     }
-    if (isHTMLBodyElement(*child) && !child->hasChildren() &&
+    if (IsHTMLBodyElement(*child) && !child->hasChildren() &&
         markup_copy.Find("</body>") == kNotFound) {
       // HTML5 parser inserts empty <body> tag whenever it parses </head>
       continue;
@@ -335,11 +335,11 @@
 
     // Always match <head> and <body> tags with each other - we can't remove
     // them from the DOM upon patching.
-    if (isHTMLHeadElement(*old_list[i]->node_)) {
+    if (IsHTMLHeadElement(*old_list[i]->node_)) {
       old_head = old_list[i].Get();
       continue;
     }
-    if (isHTMLBodyElement(*old_list[i]->node_)) {
+    if (IsHTMLBodyElement(*old_list[i]->node_)) {
       old_body = old_list[i].Get();
       continue;
     }
@@ -386,9 +386,9 @@
   // Mark <head> and <body> nodes for merge.
   if (old_head || old_body) {
     for (size_t i = 0; i < new_list.size(); ++i) {
-      if (old_head && isHTMLHeadElement(*new_list[i]->node_))
+      if (old_head && IsHTMLHeadElement(*new_list[i]->node_))
         merges.Set(new_list[i].Get(), old_head);
-      if (old_body && isHTMLBodyElement(*new_list[i]->node_))
+      if (old_body && IsHTMLBodyElement(*new_list[i]->node_))
         merges.Set(new_list[i].Get(), old_body);
     }
   }
@@ -417,7 +417,7 @@
     Node* anchor_node = NodeTraversal::ChildAt(*parent_node, old_map[i].second);
     if (node == anchor_node)
       continue;
-    if (isHTMLBodyElement(*node) || isHTMLHeadElement(*node)) {
+    if (IsHTMLBodyElement(*node) || IsHTMLHeadElement(*node)) {
       // Never move head or body, move the rest of the nodes around them.
       continue;
     }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp
index a4e464a..49c5e13 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp
@@ -97,7 +97,7 @@
                               bool is_transition) {
   ComputedTimingProperties computed_timing = effect->getComputedTiming();
   double delay = computed_timing.delay();
-  double duration = computed_timing.duration().getAsUnrestrictedDouble();
+  double duration = computed_timing.duration().GetAsUnrestrictedDouble();
   String easing = effect->SpecifiedTiming().timing_function->ToString();
 
   if (is_transition) {
@@ -160,9 +160,9 @@
 
   for (const auto& keyframe : normalized_keyframes) {
     // Ignore CSS Transitions
-    if (!keyframe.Get()->IsStringKeyframe())
+    if (!keyframe.get()->IsStringKeyframe())
       continue;
-    const StringKeyframe* string_keyframe = ToStringKeyframe(keyframe.Get());
+    const StringKeyframe* string_keyframe = ToStringKeyframe(keyframe.get());
     keyframes->addItem(BuildObjectForStringKeyframe(string_keyframe));
   }
   return protocol::Animation::KeyframesRule::create()
@@ -293,7 +293,7 @@
       KeyframeVector old_keyframes = old_string_keyframe_model->GetFrames();
       StringKeyframeVector new_keyframes;
       for (auto& old_keyframe : old_keyframes)
-        new_keyframes.push_back(ToStringKeyframe(old_keyframe.Get()));
+        new_keyframes.push_back(ToStringKeyframe(old_keyframe.get()));
       new_model = StringKeyframeEffectModel::Create(new_keyframes);
     } else if (old_model->IsAnimatableValueKeyframeEffectModel()) {
       AnimatableValueKeyframeEffectModel* old_animatable_value_keyframe_model =
@@ -302,7 +302,7 @@
           old_animatable_value_keyframe_model->GetFrames();
       AnimatableValueKeyframeVector new_keyframes;
       for (auto& old_keyframe : old_keyframes)
-        new_keyframes.push_back(ToAnimatableValueKeyframe(old_keyframe.Get()));
+        new_keyframes.push_back(ToAnimatableValueKeyframe(old_keyframe.get()));
       new_model = AnimatableValueKeyframeEffectModel::Create(new_keyframes);
     } else if (old_model->IsTransitionKeyframeEffectModel()) {
       TransitionKeyframeEffectModel* old_transition_keyframe_model =
@@ -310,7 +310,7 @@
       KeyframeVector old_keyframes = old_transition_keyframe_model->GetFrames();
       TransitionKeyframeVector new_keyframes;
       for (auto& old_keyframe : old_keyframes)
-        new_keyframes.push_back(ToTransitionKeyframe(old_keyframe.Get()));
+        new_keyframes.push_back(ToTransitionKeyframe(old_keyframe.get()));
       new_model = TransitionKeyframeEffectModel::Create(new_keyframes);
     }
 
@@ -390,7 +390,7 @@
     DCHECK(frames.size() == 3);
     KeyframeVector new_frames;
     for (int i = 0; i < 3; i++)
-      new_frames.push_back(ToTransitionKeyframe(frames[i]->Clone().Get()));
+      new_frames.push_back(ToTransitionKeyframe(frames[i]->Clone().get()));
     // Update delay, represented by the distance between the first two
     // keyframes.
     new_frames[1]->SetOffset(delay / (delay + duration));
@@ -398,13 +398,13 @@
 
     AnimationEffectTiming* timing = effect->timing();
     UnrestrictedDoubleOrString unrestricted_duration;
-    unrestricted_duration.setUnrestrictedDouble(duration + delay);
+    unrestricted_duration.SetUnrestrictedDouble(duration + delay);
     timing->setDuration(unrestricted_duration, exception_state);
   } else {
     AnimationEffectTiming* timing =
         ToAnimationEffectTiming(animation->effect()->timing());
     UnrestrictedDoubleOrString unrestricted_duration;
-    unrestricted_duration.setUnrestrictedDouble(duration);
+    unrestricted_duration.SetUnrestrictedDouble(duration);
     timing->setDuration(unrestricted_duration, exception_state);
     timing->setDelay(delay);
   }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
index c55c1cd..3954f54 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
@@ -257,10 +257,10 @@
     if (!layout_object)
       continue;
 
-    if (isHTMLCanvasElement(element) || isHTMLEmbedElement(element) ||
-        isHTMLImageElement(element) || isHTMLObjectElement(element) ||
-        isHTMLPictureElement(element) || element->IsSVGElement() ||
-        isHTMLVideoElement(element)) {
+    if (IsHTMLCanvasElement(element) || IsHTMLEmbedElement(element) ||
+        IsHTMLImageElement(element) || IsHTMLObjectElement(element) ||
+        IsHTMLPictureElement(element) || element->IsSVGElement() ||
+        IsHTMLVideoElement(element)) {
       colors.clear();
       found_opaque_color = false;
       continue;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
index 0d33754a..d2a38b6 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
@@ -67,6 +67,7 @@
 #include "core/inspector/InspectedFrames.h"
 #include "core/inspector/InspectorHighlight.h"
 #include "core/inspector/InspectorHistory.h"
+#include "core/inspector/ResolveNode.h"
 #include "core/inspector/V8InspectorString.h"
 #include "core/layout/HitTestResult.h"
 #include "core/layout/LayoutInline.h"
@@ -319,10 +320,9 @@
     if (element->GetPseudoElement(kPseudoIdAfter))
       Unbind(element->GetPseudoElement(kPseudoIdAfter), nodes_map);
 
-    if (isHTMLLinkElement(*element)) {
-      HTMLLinkElement& link_element = toHTMLLinkElement(*element);
-      if (link_element.IsImport() && link_element.import())
-        Unbind(link_element.import(), nodes_map);
+    if (auto* link_element = ToHTMLLinkElementOrNull(*element)) {
+      if (link_element->IsImport() && link_element->import())
+        Unbind(link_element->import(), nodes_map);
     }
   }
 
@@ -1271,7 +1271,7 @@
   Response response = AssertNode(node_id, backend_node_id, object_id, node);
   if (!response.isSuccess())
     return response;
-  if (!isHTMLInputElement(*node) ||
+  if (!IsHTMLInputElement(*node) ||
       toHTMLInputElement(*node).type() != InputTypeNames::file)
     return Response::Error("Node is not a file input element");
 
@@ -1344,7 +1344,7 @@
 
   if (!node)
     return Response::Error("No node with given id found");
-  *result = ResolveNode(node, object_group_name);
+  *result = ResolveNode(v8_session_, node, object_group_name);
   if (!*result) {
     return Response::Error(
         "Node with given id does not belong to the document");
@@ -1479,20 +1479,18 @@
       force_push_children = true;
     }
 
-    if (isHTMLLinkElement(*element)) {
-      HTMLLinkElement& link_element = toHTMLLinkElement(*element);
-      if (link_element.IsImport() && link_element.import() &&
-          InnerParentNode(link_element.import()) == link_element) {
+    if (auto* link_element = ToHTMLLinkElementOrNull(*element)) {
+      if (link_element->IsImport() && link_element->import() &&
+          InnerParentNode(link_element->import()) == link_element) {
         value->setImportedDocument(BuildObjectForNode(
-            link_element.import(), 0, pierce, nodes_map, flatten_result));
+            link_element->import(), 0, pierce, nodes_map, flatten_result));
       }
       force_push_children = true;
     }
 
-    if (isHTMLTemplateElement(*element)) {
-      value->setTemplateContent(
-          BuildObjectForNode(toHTMLTemplateElement(*element).content(), 0,
-                             pierce, nodes_map, flatten_result));
+    if (auto* template_element = ToHTMLTemplateElementOrNull(*element)) {
+      value->setTemplateContent(BuildObjectForNode(
+          template_element->content(), 0, pierce, nodes_map, flatten_result));
       force_push_children = true;
     }
 
@@ -1517,9 +1515,8 @@
           BuildArrayForDistributedNodes(ToV0InsertionPoint(element)));
       force_push_children = true;
     }
-    if (isHTMLSlotElement(*element)) {
-      value->setDistributedNodes(
-          BuildDistributedNodesForSlot(toHTMLSlotElement(element)));
+    if (auto* slot = ToHTMLSlotElementOrNull(*element)) {
+      value->setDistributedNodes(BuildDistributedNodesForSlot(slot));
       force_push_children = true;
     }
   } else if (node->IsDocumentNode()) {
@@ -1737,18 +1734,6 @@
 }
 
 // static
-v8::Local<v8::Value> InspectorDOMAgent::NodeV8Value(
-    v8::Local<v8::Context> context,
-    Node* node) {
-  v8::Isolate* isolate = context->GetIsolate();
-  if (!node || !BindingSecurity::ShouldAllowAccessTo(
-                   CurrentDOMWindow(isolate), node,
-                   BindingSecurity::ErrorReportOption::kDoNotReport))
-    return v8::Null(isolate);
-  return ToV8(node, context->Global(), isolate);
-}
-
-// static
 void InspectorDOMAgent::CollectNodes(Node* node,
                                      int depth,
                                      bool pierce,
@@ -1778,11 +1763,10 @@
       }
     }
 
-    if (isHTMLLinkElement(*element)) {
-      HTMLLinkElement& link_element = toHTMLLinkElement(*element);
-      if (link_element.IsImport() && link_element.import() &&
-          InnerParentNode(link_element.import()) == link_element) {
-        CollectNodes(link_element.import(), depth, pierce, filter, result);
+    if (auto* link_element = ToHTMLLinkElementOrNull(*element)) {
+      if (link_element->IsImport() && link_element->import() &&
+          InnerParentNode(link_element->import()) == link_element) {
+        CollectNodes(link_element->import(), depth, pierce, filter, result);
       }
     }
   }
@@ -2151,8 +2135,7 @@
       : node_id_(DOMNodeIds::IdForNode(node)) {}
 
   v8::Local<v8::Value> get(v8::Local<v8::Context> context) override {
-    return InspectorDOMAgent::NodeV8Value(context,
-                                          DOMNodeIds::NodeForId(node_id_));
+    return NodeV8Value(context, DOMNodeIds::NodeForId(node_id_));
   }
 
  private:
@@ -2207,24 +2190,6 @@
   return Response::OK();
 }
 
-std::unique_ptr<v8_inspector::protocol::Runtime::API::RemoteObject>
-InspectorDOMAgent::ResolveNode(Node* node, const String& object_group) {
-  Document* document =
-      node->IsDocumentNode() ? &node->GetDocument() : node->ownerDocument();
-  LocalFrame* frame = document ? document->GetFrame() : nullptr;
-  if (!frame)
-    return nullptr;
-
-  ScriptState* script_state = ToScriptStateForMainWorld(frame);
-  if (!script_state)
-    return nullptr;
-
-  ScriptState::Scope scope(script_state);
-  return v8_session_->wrapObject(script_state->GetContext(),
-                                 NodeV8Value(script_state->GetContext(), node),
-                                 ToV8InspectorStringView(object_group));
-}
-
 Response InspectorDOMAgent::PushDocumentUponHandlelessOperation() {
   if (!document_node_to_id_map_->Contains(document_)) {
     std::unique_ptr<protocol::DOM::Node> root;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h
index 2979b60..207d9fb 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h
@@ -240,9 +240,6 @@
   static String DocumentURLString(Document*);
   static String DocumentBaseURLString(Document*);
 
-  std::unique_ptr<v8_inspector::protocol::Runtime::API::RemoteObject>
-  ResolveNode(Node*, const String& object_group);
-
   InspectorHistory* History() { return history_.Get(); }
 
   // We represent embedded doms as a part of the same hierarchy. Hence we treat
@@ -254,7 +251,6 @@
   static unsigned InnerChildNodeCount(Node*);
   static Node* InnerParentNode(Node*);
   static bool IsWhitespace(Node*);
-  static v8::Local<v8::Value> NodeV8Value(v8::Local<v8::Context>, Node*);
   static void CollectNodes(Node* root,
                            int depth,
                            bool pierce,
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp
index 18f9cbd..a9592260 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp
@@ -40,6 +40,7 @@
 #include "core/dom/events/EventTarget.h"
 #include "core/frame/LocalDOMWindow.h"
 #include "core/inspector/InspectorDOMAgent.h"
+#include "core/inspector/ResolveNode.h"
 #include "core/inspector/V8InspectorString.h"
 #include "core/probe/CoreProbes.h"
 
@@ -120,7 +121,7 @@
       int backend_node_id = 0;
       if (target_node) {
         backend_node_id = DOMNodeIds::IdForNode(target_node);
-        target_wrapper = InspectorDOMAgent::NodeV8Value(
+        target_wrapper = NodeV8Value(
             report_for_all_contexts ? context : isolate->GetCurrentContext(),
             target_node);
       }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.cpp
index 32d0973..930cd24 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.cpp
@@ -196,39 +196,30 @@
         value->setFrameId(IdentifiersFactory::FrameId(frame));
     }
 
-    if (isHTMLLinkElement(*element)) {
-      const HTMLLinkElement& link_element = toHTMLLinkElement(*element);
-      if (link_element.IsImport() && link_element.import() &&
-          InspectorDOMAgent::InnerParentNode(link_element.import()) ==
+    if (auto* link_element = ToHTMLLinkElementOrNull(*element)) {
+      if (link_element->IsImport() && link_element->import() &&
+          InspectorDOMAgent::InnerParentNode(link_element->import()) ==
               link_element) {
-        value->setImportedDocumentIndex(VisitNode(link_element.import()));
+        value->setImportedDocumentIndex(VisitNode(link_element->import()));
       }
     }
 
-    if (isHTMLTemplateElement(*element)) {
-      value->setTemplateContentIndex(
-          VisitNode(toHTMLTemplateElement(*element).content()));
-    }
+    if (auto* template_element = ToHTMLTemplateElementOrNull(*element))
+      value->setTemplateContentIndex(VisitNode(template_element->content()));
 
-    if (isHTMLTextAreaElement(*element)) {
-      const HTMLTextAreaElement& text_area_element =
-          toHTMLTextAreaElement(*element);
-      value->setTextValue(text_area_element.value());
-    }
+    if (auto* textarea_element = ToHTMLTextAreaElementOrNull(*element))
+      value->setTextValue(textarea_element->value());
 
-    if (isHTMLInputElement(*element)) {
-      const HTMLInputElement& input_element = toHTMLInputElement(*element);
-      value->setInputValue(input_element.value());
-      if ((input_element.type() == InputTypeNames::radio) ||
-          (input_element.type() == InputTypeNames::checkbox)) {
-        value->setInputChecked(input_element.checked());
+    if (auto* input_element = ToHTMLInputElementOrNull(*element)) {
+      value->setInputValue(input_element->value());
+      if ((input_element->type() == InputTypeNames::radio) ||
+          (input_element->type() == InputTypeNames::checkbox)) {
+        value->setInputChecked(input_element->checked());
       }
     }
 
-    if (isHTMLOptionElement(*element)) {
-      const HTMLOptionElement& option_element = toHTMLOptionElement(*element);
-      value->setOptionSelected(option_element.Selected());
-    }
+    if (auto* option_element = ToHTMLOptionElementOrNull(*element))
+      value->setOptionSelected(option_element->Selected());
 
     if (element->GetPseudoId()) {
       protocol::DOM::PseudoType pseudo_type;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp
index 6b0b88c..9cfe17a2 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp
@@ -502,7 +502,7 @@
   SnapshotById::iterator it = snapshot_by_id_.find(snapshot_id);
   if (it == snapshot_by_id_.end())
     return Response::Error("Snapshot not found");
-  result = it->value.Get();
+  result = it->value.get();
   return Response::OK();
 }
 
diff --git a/third_party/WebKit/Source/core/inspector/InspectorLogAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorLogAgent.cpp
index 74b12e13..7bfeeefb 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorLogAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorLogAgent.cpp
@@ -9,6 +9,9 @@
 #include "core/inspector/ConsoleMessage.h"
 #include "core/inspector/ConsoleMessageStorage.h"
 #include "core/inspector/IdentifiersFactory.h"
+#include "core/inspector/InspectorDOMAgent.h"
+#include "core/inspector/ResolveNode.h"
+#include "third_party/WebKit/Source/platform/ScriptForbiddenScope.h"
 
 namespace blink {
 
@@ -48,6 +51,8 @@
       return protocol::Log::LogEntry::SourceEnum::Violation;
     case kInterventionMessageSource:
       return protocol::Log::LogEntry::SourceEnum::Intervention;
+    case kRecommendationMessageSource:
+      return protocol::Log::LogEntry::SourceEnum::Recommendation;
     default:
       return protocol::Log::LogEntry::SourceEnum::Other;
   }
@@ -71,11 +76,14 @@
 
 using protocol::Log::ViolationSetting;
 
-InspectorLogAgent::InspectorLogAgent(ConsoleMessageStorage* storage,
-                                     PerformanceMonitor* performance_monitor)
+InspectorLogAgent::InspectorLogAgent(
+    ConsoleMessageStorage* storage,
+    PerformanceMonitor* performance_monitor,
+    v8_inspector::V8InspectorSession* v8_session)
     : enabled_(false),
       storage_(storage),
-      performance_monitor_(performance_monitor) {}
+      performance_monitor_(performance_monitor),
+      v8_session_(v8_session) {}
 
 InspectorLogAgent::~InspectorLogAgent() {}
 
@@ -124,6 +132,23 @@
     entry->setNetworkRequestId(
         IdentifiersFactory::RequestId(message->RequestIdentifier()));
 
+  if (v8_session_ && !message->Nodes().IsEmpty()) {
+    ScriptForbiddenScope::AllowUserAgentScript allow_script;
+    std::unique_ptr<
+        protocol::Array<v8_inspector::protocol::Runtime::API::RemoteObject>>
+        remote_objects = protocol::Array<
+            v8_inspector::protocol::Runtime::API::RemoteObject>::create();
+    for (DOMNodeId node_id : message->Nodes()) {
+      Node* node = DOMNodeIds::NodeForId(node_id);
+      if (node) {
+        auto remote_object = ResolveNode(v8_session_, node, "console");
+        if (remote_object)
+          remote_objects->addItem(std::move(remote_object));
+      }
+    }
+    entry->setArgs(std::move(remote_objects));
+  }
+
   GetFrontend()->entryAdded(std::move(entry));
   GetFrontend()->flush();
 }
@@ -141,7 +166,7 @@
             .setSource(protocol::Log::LogEntry::SourceEnum::Other)
             .setLevel(protocol::Log::LogEntry::LevelEnum::Warning)
             .setText(String::Number(storage_->ExpiredCount()) +
-                     String(" log entires are not shown."))
+                     String(" log entries are not shown."))
             .setTimestamp(0)
             .build();
     GetFrontend()->entryAdded(std::move(expired));
diff --git a/third_party/WebKit/Source/core/inspector/InspectorLogAgent.h b/third_party/WebKit/Source/core/inspector/InspectorLogAgent.h
index 5575f34..7b32f99b 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorLogAgent.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorLogAgent.h
@@ -10,6 +10,10 @@
 #include "core/inspector/InspectorBaseAgent.h"
 #include "core/inspector/protocol/Log.h"
 
+namespace v8_inspector {
+class V8InspectorSession;
+}
+
 namespace blink {
 
 class ConsoleMessage;
@@ -22,7 +26,9 @@
   WTF_MAKE_NONCOPYABLE(InspectorLogAgent);
 
  public:
-  InspectorLogAgent(ConsoleMessageStorage*, PerformanceMonitor*);
+  InspectorLogAgent(ConsoleMessageStorage*,
+                    PerformanceMonitor*,
+                    v8_inspector::V8InspectorSession*);
   ~InspectorLogAgent() override;
   DECLARE_VIRTUAL_TRACE();
 
@@ -51,6 +57,7 @@
   bool enabled_;
   Member<ConsoleMessageStorage> storage_;
   Member<PerformanceMonitor> performance_monitor_;
+  v8_inspector::V8InspectorSession* v8_session_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp
index 49a68a9..872d64fa 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp
@@ -947,7 +947,7 @@
   pending_request_type_ = InspectorPageAgent::kXHRResource;
   pending_xhr_replay_data_ = XHRReplayData::Create(
       xhr->GetExecutionContext(), method, UrlWithoutFragment(url), async,
-      form_data.Get(), include_credentials);
+      form_data.get(), include_credentials);
   for (const auto& header : headers)
     pending_xhr_replay_data_->AddHeader(header.key, header.value);
 }
@@ -1432,7 +1432,7 @@
   for (auto& resource : resources_data_->Resources()) {
     RefPtr<SecurityOrigin> resource_origin =
         SecurityOrigin::Create(resource->RequestedURL());
-    if (resource_origin->IsSameSchemeHostPort(security_origin.Get()) &&
+    if (resource_origin->IsSameSchemeHostPort(security_origin.get()) &&
         resource->Certificate().size()) {
       for (auto& cert : resource->Certificate())
         certificate->get()->addItem(Base64Encode(cert.Latin1()));
diff --git a/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp b/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp
index ed851813..a7a8789 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp
@@ -383,14 +383,19 @@
   CSSParser::ParseSheetForInspector(ParserContextForDocument(document),
                                     style_sheet, text, handler);
 
-  // Exactly two should be parsed.
+  // Exactly one should be parsed.
   unsigned rule_count = source_data->size();
-  if (rule_count != 2 || source_data->at(0)->type != StyleRule::kKeyframes ||
-      source_data->at(1)->type != StyleRule::kKeyframe)
+  if (rule_count != 1 || source_data->at(0)->type != StyleRule::kKeyframes)
+    return false;
+
+  const CSSRuleSourceData& keyframe_data = *source_data->at(0);
+  if (keyframe_data.child_rules.size() != 1 ||
+      keyframe_data.child_rules.at(0)->type != StyleRule::kKeyframe)
     return false;
 
   // Exactly one property should be in keyframe rule.
-  unsigned property_count = source_data->at(1)->property_data.size();
+  const unsigned property_count =
+      keyframe_data.child_rules.at(0)->property_data.size();
   if (property_count != 1)
     return false;
 
@@ -1831,7 +1836,7 @@
     return nullptr;
   Element* owner_element = ToElement(owner_node);
 
-  if (!isHTMLStyleElement(owner_element) && !isSVGStyleElement(owner_element))
+  if (!IsHTMLStyleElement(owner_element) && !IsSVGStyleElement(owner_element))
     return nullptr;
   return owner_element;
 }
diff --git a/third_party/WebKit/Source/core/inspector/NetworkResourcesData.h b/third_party/WebKit/Source/core/inspector/NetworkResourcesData.h
index a117cf2..86c7371 100644
--- a/third_party/WebKit/Source/core/inspector/NetworkResourcesData.h
+++ b/third_party/WebKit/Source/core/inspector/NetworkResourcesData.h
@@ -144,7 +144,7 @@
     }
 
     BlobDataHandle* DownloadedFileBlob() const {
-      return downloaded_file_blob_.Get();
+      return downloaded_file_blob_.get();
     }
     void SetDownloadedFileBlob(RefPtr<BlobDataHandle> blob) {
       downloaded_file_blob_ = std::move(blob);
@@ -168,7 +168,7 @@
     DECLARE_TRACE();
 
    private:
-    bool HasData() const { return data_buffer_.Get(); }
+    bool HasData() const { return data_buffer_.get(); }
     size_t DataLength() const;
     void AppendData(const char* data, size_t data_length);
     size_t DecodeDataToContent();
diff --git a/third_party/WebKit/Source/core/inspector/ResolveNode.cpp b/third_party/WebKit/Source/core/inspector/ResolveNode.cpp
new file mode 100644
index 0000000..1daf1ce
--- /dev/null
+++ b/third_party/WebKit/Source/core/inspector/ResolveNode.cpp
@@ -0,0 +1,44 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/inspector/ResolveNode.h"
+
+#include "bindings/core/v8/BindingSecurity.h"
+#include "bindings/core/v8/V8BindingForCore.h"
+#include "core/dom/Document.h"
+#include "core/dom/Node.h"
+#include "core/inspector/V8InspectorString.h"
+
+namespace blink {
+
+v8::Local<v8::Value> NodeV8Value(v8::Local<v8::Context> context, Node* node) {
+  v8::Isolate* isolate = context->GetIsolate();
+  if (!node || !BindingSecurity::ShouldAllowAccessTo(
+                   CurrentDOMWindow(isolate), node,
+                   BindingSecurity::ErrorReportOption::kDoNotReport))
+    return v8::Null(isolate);
+  return ToV8(node, context->Global(), isolate);
+}
+
+std::unique_ptr<v8_inspector::protocol::Runtime::API::RemoteObject> ResolveNode(
+    v8_inspector::V8InspectorSession* v8_session,
+    Node* node,
+    const String& object_group) {
+  Document* document =
+      node->IsDocumentNode() ? &node->GetDocument() : node->ownerDocument();
+  LocalFrame* frame = document ? document->GetFrame() : nullptr;
+  if (!frame)
+    return nullptr;
+
+  ScriptState* script_state = ToScriptStateForMainWorld(frame);
+  if (!script_state)
+    return nullptr;
+
+  ScriptState::Scope scope(script_state);
+  return v8_session->wrapObject(script_state->GetContext(),
+                                NodeV8Value(script_state->GetContext(), node),
+                                ToV8InspectorStringView(object_group));
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/ResolveNode.h b/third_party/WebKit/Source/core/inspector/ResolveNode.h
new file mode 100644
index 0000000..a1c21f4c
--- /dev/null
+++ b/third_party/WebKit/Source/core/inspector/ResolveNode.h
@@ -0,0 +1,27 @@
+// 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 ResolveNode_h
+#define ResolveNode_h
+
+#include <memory>
+
+#include "core/inspector/protocol/Runtime.h"
+#include "platform/wtf/text/WTFString.h"
+#include "v8/include/v8-inspector.h"
+
+namespace blink {
+
+class Node;
+
+v8::Local<v8::Value> NodeV8Value(v8::Local<v8::Context>, Node*);
+
+std::unique_ptr<v8_inspector::protocol::Runtime::API::RemoteObject> ResolveNode(
+    v8_inspector::V8InspectorSession*,
+    Node*,
+    const String& object_group);
+
+}  // namespace blink
+
+#endif  // ResolveNode_h
diff --git a/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp b/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp
index c0614d1..15648bf 100644
--- a/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp
+++ b/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp
@@ -73,8 +73,8 @@
   InspectorSession* session = new InspectorSession(
       this, probe_sink_.Get(), session_id, debugger_->GetV8Inspector(),
       debugger_->ContextGroupId(thread_), nullptr);
-  session->Append(
-      new InspectorLogAgent(thread_->GetConsoleMessageStorage(), nullptr));
+  session->Append(new InspectorLogAgent(thread_->GetConsoleMessageStorage(),
+                                        nullptr, session->V8Session()));
   if (thread_->GlobalScope()->IsWorkerGlobalScope() &&
       RuntimeEnabledFeatures::OffMainThreadFetchEnabled()) {
     DCHECK(ToWorkerGlobalScope(thread_->GlobalScope())->GetResourceFetcher());
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json
index 8aa0b05..5896080 100644
--- a/third_party/WebKit/Source/core/inspector/browser_protocol.json
+++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -4927,6 +4927,20 @@
                     { "name": "origin", "type": "string", "description": "Security origin." }
                 ],
                 "description": "Unregisters origin from receiving notifications for cache storage."
+            },
+            {
+                "name": "trackIndexedDBForOrigin",
+                "parameters": [
+                    { "name": "origin", "type": "string", "description": "Security origin." }
+                ],
+                "description": "Registers origin to be notified when an update occurs to its IndexedDB."
+            },
+            {
+                "name": "untrackIndexedDBForOrigin",
+                "parameters": [
+                    { "name": "origin", "type": "string", "description": "Security origin." }
+                ],
+                "description": "Unregisters origin from receiving notifications for IndexedDB."
             }
         ],
         "events": [
@@ -4944,6 +4958,22 @@
                     { "name": "cacheName", "type": "string", "description": "Name of cache in origin." }
                 ],
                 "description": "A cache's contents have been modified."
+            },
+            {
+                "name": "indexedDBListUpdated",
+                "parameters": [
+                    { "name": "origin", "type": "string", "description": "Origin to update." }
+                ],
+                "description": "The origin's IndexedDB database list has been modified."
+            },
+            {
+                "name": "indexedDBContentUpdated",
+                "parameters": [
+                    { "name": "origin", "type": "string", "description": "Origin to update." },
+                    { "name": "databaseName", "type": "string", "description": "Database to update." },
+                    { "name": "objectStoreName", "type": "string", "description": "ObjectStore to update." }
+                ],
+                "description": "The origin's IndexedDB object store has been modified."
             }
         ]
     },
@@ -4958,7 +4988,7 @@
                 "type": "object",
                 "description": "Log entry.",
                 "properties": [
-                    { "name": "source", "type": "string", "enum": ["xml", "javascript", "network", "storage", "appcache", "rendering", "security", "deprecation", "worker", "violation", "intervention", "other"], "description": "Log entry source." },
+                    { "name": "source", "type": "string", "enum": ["xml", "javascript", "network", "storage", "appcache", "rendering", "security", "deprecation", "worker", "violation", "intervention", "recommendation", "other"], "description": "Log entry source." },
                     { "name": "level", "type": "string", "enum": ["verbose", "info", "warning", "error"], "description": "Log entry severity." },
                     { "name": "text", "type": "string", "description": "Logged text." },
                     { "name": "timestamp", "$ref": "Runtime.Timestamp", "description": "Timestamp when this entry was added." },
@@ -4966,7 +4996,8 @@
                     { "name": "lineNumber", "type": "integer", "optional": true, "description": "Line number in the resource." },
                     { "name": "stackTrace", "$ref": "Runtime.StackTrace", "optional": true, "description": "JavaScript stack trace." },
                     { "name": "networkRequestId", "$ref": "Network.RequestId", "optional": true, "description": "Identifier of the network request associated with this entry." },
-                    { "name": "workerId", "type": "string", "optional": true, "description": "Identifier of the worker associated with this entry." }
+                    { "name": "workerId", "type": "string", "optional": true, "description": "Identifier of the worker associated with this entry." },
+                    { "name": "args", "type": "array", "items": { "$ref": "Runtime.RemoteObject" }, "optional": true, "description": "Call arguments." }
                 ]
             },
             {
diff --git a/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.cpp b/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.cpp
index d033b44..2e46f40c 100644
--- a/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.cpp
+++ b/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.cpp
@@ -72,7 +72,8 @@
   // "1px 2px 3px" = top left/right bottom
   // "1px 2px 3px 4px" = top left right bottom
   CSSTokenizer tokenizer(root_margin_parameter);
-  CSSParserTokenRange token_range = tokenizer.TokenRange();
+  const auto tokens = tokenizer.TokenizeToEOF();
+  CSSParserTokenRange token_range(tokens);
   while (token_range.Peek().GetType() != kEOFToken &&
          !exception_state.HadException()) {
     if (root_margin.size() == 4) {
@@ -110,10 +111,10 @@
 void ParseThresholds(const DoubleOrDoubleSequence& threshold_parameter,
                      Vector<float>& thresholds,
                      ExceptionState& exception_state) {
-  if (threshold_parameter.isDouble()) {
-    thresholds.push_back(static_cast<float>(threshold_parameter.getAsDouble()));
+  if (threshold_parameter.IsDouble()) {
+    thresholds.push_back(static_cast<float>(threshold_parameter.GetAsDouble()));
   } else {
-    for (auto threshold_value : threshold_parameter.getAsDoubleSequence())
+    for (auto threshold_value : threshold_parameter.GetAsDoubleSequence())
       thresholds.push_back(static_cast<float>(threshold_value));
   }
 
diff --git a/third_party/WebKit/Source/core/layout/BUILD.gn b/third_party/WebKit/Source/core/layout/BUILD.gn
index 2ef2b47..30445de6 100644
--- a/third_party/WebKit/Source/core/layout/BUILD.gn
+++ b/third_party/WebKit/Source/core/layout/BUILD.gn
@@ -377,6 +377,8 @@
     "ng/inline/ng_text_fragment_builder.h",
     "ng/layout_ng_block_flow.cc",
     "ng/layout_ng_block_flow.h",
+    "ng/layout_ng_list_item.cc",
+    "ng/layout_ng_list_item.h",
     "ng/legacy_layout_tree_walking.cc",
     "ng/legacy_layout_tree_walking.h",
     "ng/ng_absolute_utils.cc",
@@ -439,6 +441,8 @@
     "ng/ng_relative_utils.h",
     "ng/ng_space_utils.cc",
     "ng/ng_space_utils.h",
+    "ng/ng_text_decoration_offset.cc",
+    "ng/ng_text_decoration_offset.h",
     "ng/ng_unpositioned_float.cc",
     "ng/ng_unpositioned_float.h",
     "ng/ng_writing_mode.cc",
diff --git a/third_party/WebKit/Source/core/layout/GeneratedChildren.h b/third_party/WebKit/Source/core/layout/GeneratedChildren.h
index 11097a33..f6d0535f 100644
--- a/third_party/WebKit/Source/core/layout/GeneratedChildren.h
+++ b/third_party/WebKit/Source/core/layout/GeneratedChildren.h
@@ -25,7 +25,7 @@
   // We'll write the code assuming any other button types that might emerge in
   // the future can also have children.
   if (layout_object.IsLayoutButton())
-    return !isHTMLInputElement(*layout_object.GetNode());
+    return !IsHTMLInputElement(*layout_object.GetNode());
 
   return layout_object.CanHaveChildren();
 }
diff --git a/third_party/WebKit/Source/core/layout/HitTestResult.cpp b/third_party/WebKit/Source/core/layout/HitTestResult.cpp
index a11abbc..51f08961 100644
--- a/third_party/WebKit/Source/core/layout/HitTestResult.cpp
+++ b/third_party/WebKit/Source/core/layout/HitTestResult.cpp
@@ -183,7 +183,7 @@
   // case so that a toolip title in the shadow tree works.
   while (containing_shadow_root &&
          (containing_shadow_root->GetType() == ShadowRootType::kUserAgent ||
-          isSVGUseElement(containing_shadow_root->host()))) {
+          IsSVGUseElement(containing_shadow_root->host()))) {
     shadow_host = &containing_shadow_root->host();
     containing_shadow_root = shadow_host->ContainingShadowRoot();
     SetInnerNode(node->OwnerShadowHost());
@@ -195,14 +195,11 @@
 
 HTMLAreaElement* HitTestResult::ImageAreaForImage() const {
   DCHECK(inner_node_);
-  HTMLImageElement* image_element = nullptr;
-  if (isHTMLImageElement(inner_node_)) {
-    image_element = toHTMLImageElement(inner_node_);
-  } else if (inner_node_->IsInShadowTree()) {
+  HTMLImageElement* image_element = ToHTMLImageElementOrNull(inner_node_);
+  if (!image_element && inner_node_->IsInShadowTree()) {
     if (inner_node_->ContainingShadowRoot()->GetType() ==
         ShadowRootType::kUserAgent) {
-      if (isHTMLImageElement(inner_node_->OwnerShadowHost()))
-        image_element = toHTMLImageElement(inner_node_->OwnerShadowHost());
+      image_element = ToHTMLImageElementOrNull(inner_node_->OwnerShadowHost());
     }
   }
 
@@ -282,17 +279,11 @@
   if (!inner_node_or_image_map_image)
     return g_null_atom;
 
-  if (isHTMLImageElement(*inner_node_or_image_map_image)) {
-    HTMLImageElement& image =
-        toHTMLImageElement(*inner_node_or_image_map_image);
-    return image.getAttribute(altAttr);
-  }
+  if (auto* image = ToHTMLImageElementOrNull(*inner_node_or_image_map_image))
+    return image->getAttribute(altAttr);
 
-  if (isHTMLInputElement(*inner_node_or_image_map_image)) {
-    HTMLInputElement& input =
-        toHTMLInputElement(*inner_node_or_image_map_image);
-    return input.Alt();
-  }
+  if (auto* input = ToHTMLInputElementOrNull(*inner_node_or_image_map_image))
+    return input->Alt();
 
   return g_null_atom;
 }
@@ -332,16 +323,16 @@
   // even if they don't have a LayoutImage (e.g. because the image didn't load
   // and we are using an alt container). For other elements we don't create alt
   // containers so ensure they contain a loaded image.
-  if (isHTMLImageElement(*inner_node_or_image_map_image) ||
-      (isHTMLInputElement(*inner_node_or_image_map_image) &&
+  if (IsHTMLImageElement(*inner_node_or_image_map_image) ||
+      (IsHTMLInputElement(*inner_node_or_image_map_image) &&
        toHTMLInputElement(inner_node_or_image_map_image)->type() ==
            InputTypeNames::image))
     url_string = ToElement(*inner_node_or_image_map_image).ImageSourceURL();
   else if ((inner_node_or_image_map_image->GetLayoutObject() &&
             inner_node_or_image_map_image->GetLayoutObject()->IsImage()) &&
-           (isHTMLEmbedElement(*inner_node_or_image_map_image) ||
-            isHTMLObjectElement(*inner_node_or_image_map_image) ||
-            isSVGImageElement(*inner_node_or_image_map_image)))
+           (IsHTMLEmbedElement(*inner_node_or_image_map_image) ||
+            IsHTMLObjectElement(*inner_node_or_image_map_image) ||
+            IsSVGImageElement(*inner_node_or_image_map_image)))
     url_string = ToElement(*inner_node_or_image_map_image).ImageSourceURL();
   if (url_string.IsEmpty())
     return KURL();
@@ -398,13 +389,11 @@
   if (!inner_node_)
     return false;
 
-  if (isHTMLTextAreaElement(*inner_node_))
-    return !toHTMLTextAreaElement(*inner_node_).IsDisabledOrReadOnly();
+  if (auto* textarea = ToHTMLTextAreaElementOrNull(*inner_node_))
+    return !textarea->IsDisabledOrReadOnly();
 
-  if (isHTMLInputElement(*inner_node_)) {
-    HTMLInputElement& input_element = toHTMLInputElement(*inner_node_);
-    return !input_element.IsDisabledOrReadOnly() && input_element.IsTextField();
-  }
+  if (auto* input = ToHTMLInputElementOrNull(*inner_node_))
+    return !input->IsDisabledOrReadOnly() && input->IsTextField();
 
   return HasEditableStyle(*inner_node_);
 }
@@ -522,10 +511,10 @@
     return nullptr;
 
   HTMLImageElement* image_map_image_element = nullptr;
-  if (isHTMLAreaElement(inner_node_))
-    image_map_image_element = toHTMLAreaElement(inner_node_)->ImageElement();
-  else if (isHTMLMapElement(inner_node_))
-    image_map_image_element = toHTMLMapElement(inner_node_)->ImageElement();
+  if (auto* area = ToHTMLAreaElementOrNull(inner_node_))
+    image_map_image_element = area->ImageElement();
+  else if (auto* map = ToHTMLMapElementOrNull(inner_node_))
+    image_map_image_element = map->ImageElement();
 
   if (!image_map_image_element)
     return inner_node_.Get();
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp
index 6f9eec5..454635a 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp
@@ -1352,7 +1352,7 @@
 
   max_logical_width = std::max(min_logical_width, max_logical_width);
 
-  if (isHTMLMarqueeElement(GetNode()) &&
+  if (IsHTMLMarqueeElement(GetNode()) &&
       toHTMLMarqueeElement(GetNode())->IsHorizontal())
     min_logical_width = LayoutUnit();
 
@@ -1591,7 +1591,7 @@
     return true;
 
   if (GetNode()->IsShadowRoot() &&
-      isHTMLInputElement(ToShadowRoot(GetNode())->host()))
+      IsHTMLInputElement(ToShadowRoot(GetNode())->host()))
     return true;
 
   return false;
@@ -1810,15 +1810,6 @@
   return nullptr;
 }
 
-void LayoutBlock::UpdateHitTestResult(HitTestResult& result,
-                                      const LayoutPoint& point) {
-  if (result.InnerNode())
-    return;
-
-  if (Node* n = NodeForHitTest())
-    result.SetNodeAndPosition(n, point);
-}
-
 // An inline-block uses its inlineBox as the inlineBoxWrapper,
 // so the firstChild() is nullptr if the only child is an empty inline-block.
 inline bool LayoutBlock::IsInlineBoxWrapperActuallyChild() const {
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlock.h b/third_party/WebKit/Source/core/layout/LayoutBlock.h
index a34cc3e..12c71b0 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlock.h
+++ b/third_party/WebKit/Source/core/layout/LayoutBlock.h
@@ -409,7 +409,6 @@
                        const HitTestLocation& location_in_container,
                        const LayoutPoint& accumulated_offset,
                        HitTestAction) override;
-  void UpdateHitTestResult(HitTestResult&, const LayoutPoint&) override;
 
   void UpdateAfterLayout() override;
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
index 68daa1b..7c7bd9f 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
@@ -78,6 +78,12 @@
 static_assert(sizeof(LayoutBlockFlow::MarginValues) == sizeof(LayoutUnit[4]),
               "MarginValues should stay small");
 
+typedef HashMap<LayoutBlockFlow*, int> LayoutPassCountMap;
+static LayoutPassCountMap& GetLayoutPassCountMap() {
+  DEFINE_STATIC_LOCAL(LayoutPassCountMap, map, ());
+  return map;
+}
+
 // Caches all our current margin collapsing state.
 class MarginInfo {
   // Collapsing flags for whether we can collapse our margins with our
@@ -406,6 +412,9 @@
   DCHECK(NeedsLayout());
   DCHECK(IsInlineBlockOrInlineTable() || !IsInline());
 
+  if (RuntimeEnabledFeatures::TrackLayoutPassesPerBlockEnabled())
+    IncrementLayoutPassCount();
+
   if (!relayout_children && SimplifiedLayout())
     return;
 
@@ -491,7 +500,7 @@
 
   UpdateAfterLayout();
 
-  if (isHTMLDialogElement(GetNode()) && IsOutOfFlowPositioned())
+  if (IsHTMLDialogElement(GetNode()) && IsOutOfFlowPositioned())
     PositionDialog();
 
   ClearNeedsLayout();
@@ -4038,7 +4047,8 @@
   // If we are in the margins of block elements that are part of a
   // continuation we're actually still inside the enclosing element
   // that was split. Use the appropriate inner node.
-  return IsAnonymousBlockContinuation() ? Continuation()->GetNode() : GetNode();
+  return IsAnonymousBlockContinuation() ? Continuation()->NodeForHitTest()
+                                        : LayoutBlock::NodeForHitTest();
 }
 
 bool LayoutBlockFlow::HitTestChildren(
@@ -4752,4 +4762,17 @@
       invalidation_reason);
 }
 
+void LayoutBlockFlow::IncrementLayoutPassCount() {
+  int layout_pass_count = 0;
+  HashMap<LayoutBlockFlow*, int>::iterator layout_count_iterator =
+      GetLayoutPassCountMap().find(this);
+  if (layout_count_iterator != GetLayoutPassCountMap().end())
+    layout_pass_count = layout_count_iterator->value;
+  GetLayoutPassCountMap().Set(this, ++layout_pass_count);
+}
+
+int LayoutBlockFlow::GetLayoutPassCountForTesting() {
+  return GetLayoutPassCountMap().find(this)->value;
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h
index 4fd60a7..90d54f9 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h
+++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h
@@ -742,6 +742,8 @@
   static void UpdateAncestorShouldPaintFloatingObject(
       const LayoutBox& float_box);
 
+  int GetLayoutPassCountForTesting();
+
  protected:
   LayoutUnit MaxPositiveMarginBefore() const {
     return rare_data_
@@ -977,6 +979,7 @@
   // Positions new floats and also adjust all floats encountered on the line if
   // any of them have to move to the next page/column.
   void PositionDialog();
+  void IncrementLayoutPassCount();
 
   // END METHODS DEFINED IN LayoutBlockFlowLine
 };
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index fcfee138..85264901 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -2624,7 +2624,7 @@
   DCHECK(layout_object);
   Node* parent_node = layout_object->GeneratingNode();
   DCHECK(parent_node);
-  DCHECK(isHTMLOListElement(parent_node) || isHTMLUListElement(parent_node));
+  DCHECK(IsHTMLOListElement(parent_node) || IsHTMLUListElement(parent_node));
   DCHECK_NE(layout_object->Style()->TextAutosizingMultiplier(), 1);
 #endif
   float max_width = 0;
@@ -2755,8 +2755,8 @@
   if (style_to_use.TextAutosizingMultiplier() != 1 &&
       style_to_use.MarginStart().GetType() == kFixed) {
     Node* parent_node = GeneratingNode();
-    if (parent_node && (isHTMLOListElement(*parent_node) ||
-                        isHTMLUListElement(*parent_node))) {
+    if (parent_node && (IsHTMLOListElement(*parent_node) ||
+                        IsHTMLUListElement(*parent_node))) {
       // Make sure the markers in a list are properly positioned (i.e. not
       // chopped off) when autosized.
       const float adjusted_margin =
@@ -2975,9 +2975,9 @@
 
 bool LayoutBox::AutoWidthShouldFitContent() const {
   return GetNode() &&
-         (isHTMLInputElement(*GetNode()) || isHTMLSelectElement(*GetNode()) ||
-          isHTMLButtonElement(*GetNode()) ||
-          isHTMLTextAreaElement(*GetNode()) || IsRenderedLegend());
+         (IsHTMLInputElement(*GetNode()) || IsHTMLSelectElement(*GetNode()) ||
+          IsHTMLButtonElement(*GetNode()) ||
+          IsHTMLTextAreaElement(*GetNode()) || IsRenderedLegend());
 }
 
 void LayoutBox::ComputeMarginsForDirection(MarginDirection flow_direction,
@@ -4935,7 +4935,7 @@
   Node* node = this->GetNode();
   return node && node->IsElementNode() &&
          (ToElement(node)->IsFormControlElement() ||
-          isHTMLImageElement(ToElement(node)));
+          IsHTMLImageElement(ToElement(node)));
 }
 
 bool LayoutBox::AvoidsFloats() const {
@@ -5031,7 +5031,7 @@
 }
 
 bool LayoutBox::IsRenderedLegend() const {
-  if (!isHTMLLegendElement(GetNode()))
+  if (!IsHTMLLegendElement(GetNode()))
     return false;
   if (IsFloatingOrOutOfFlowPositioned())
     return false;
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.h b/third_party/WebKit/Source/core/layout/LayoutBox.h
index 9943badb..4efa12a 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.h
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.h
@@ -1089,8 +1089,6 @@
   }  // Returns -1 if we should skip this box when computing the baseline of an
      // inline-block.
 
-  virtual Node* NodeForHitTest() const { return GetNode(); }
-
   bool ShrinkToAvoidFloats() const;
   virtual bool AvoidsFloats() const;
   bool ShouldBeConsideredAsReplaced() const;
diff --git a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
index 8b68691..220828d 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
@@ -593,7 +593,7 @@
   for (const LayoutBoxModelObject* root = this; root;
        root = root->Continuation()) {
     for (const LayoutObject* object = root; object;
-         object = object->NextInPreOrder(object)) {
+         object = object->NextInPreOrder(root)) {
       if (object->IsBox()) {
         const LayoutBox& box = ToLayoutBox(*object);
         if (box.LogicalHeight() && box.LogicalWidth())
@@ -603,7 +603,7 @@
         if (!layout_inline.LinesBoundingBox().IsEmpty())
           return true;
       } else {
-        DCHECK(object->IsText());
+        DCHECK(object->IsText() || object->IsSVG());
       }
     }
   }
@@ -1427,7 +1427,7 @@
     return false;
 
   Element* root_element = GetDocument().documentElement();
-  if (!isHTMLHtmlElement(root_element))
+  if (!IsHTMLHtmlElement(root_element))
     return false;
 
   if (!root_element_style)
diff --git a/third_party/WebKit/Source/core/layout/LayoutBoxModelObjectTest.cpp b/third_party/WebKit/Source/core/layout/LayoutBoxModelObjectTest.cpp
index f69d946..ca31319 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBoxModelObjectTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBoxModelObjectTest.cpp
@@ -989,4 +989,52 @@
             target->Layer()->CompositingContainer());
 }
 
+// Tests that when a sticky object is removed from the root scroller it
+// correctly clears its viewport constrained position: https://crbug.com/755307.
+TEST_F(LayoutBoxModelObjectTest, StickyRemovedFromRootScrollableArea) {
+  SetBodyInnerHTML(
+      "<style>"
+      "body { height: 5000px; }"
+      "#scroller { height: 100px; }"
+      "#sticky { position: sticky; top: 0; height: 50px; width: 50px; }"
+      "</style>"
+      "<div id='scroller'>"
+      "  <div id='sticky'></div>"
+      "  </div>");
+
+  LayoutBoxModelObject* sticky =
+      ToLayoutBoxModelObject(GetLayoutObjectByElementId("sticky"));
+  LayoutBoxModelObject* scroller =
+      ToLayoutBoxModelObject(GetLayoutObjectByElementId("scroller"));
+
+  // The 'scroller' starts as non-overflow, so the sticky element's ancestor
+  // overflow layer should be the outer scroller.
+  EXPECT_TRUE(sticky->Layer()->AncestorOverflowLayer()->IsRootLayer());
+
+  // We need the sticky element to not be a PaintLayer child of the scroller,
+  // so that it is later reparented under the scroller's PaintLayer
+  EXPECT_FALSE(scroller->Layer());
+
+  // Now make the scroller into an actual scroller. This will reparent the
+  // sticky element to be a child of the scroller, and will set its previous
+  // overflow layer to nullptr.
+  ToElement(scroller->GetNode())
+      ->SetInlineStyleProperty(CSSPropertyOverflow, "scroll");
+  GetDocument().View()->UpdateAllLifecyclePhases();
+
+  // The sticky element should no longer be viewport constrained.
+  EXPECT_FALSE(GetDocument().View()->HasViewportConstrainedObjects());
+
+  // Making the scroller have visible overflow but still have a PaintLayer
+  // (in this case by making it position: relative) will cause us to need to
+  // recompute the sticky element's ancestor overflow layer.
+  ToElement(scroller->GetNode())
+      ->SetInlineStyleProperty(CSSPropertyPosition, "relative");
+  ToElement(scroller->GetNode())
+      ->SetInlineStyleProperty(CSSPropertyOverflow, "visible");
+
+  // Now try to scroll to the sticky element, this used to crash.
+  GetDocument().GetFrame()->DomWindow()->scrollTo(0, 500);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/LayoutButton.cpp b/third_party/WebKit/Source/core/layout/LayoutButton.cpp
index 4c17f13..c36d170 100644
--- a/third_party/WebKit/Source/core/layout/LayoutButton.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutButton.cpp
@@ -110,6 +110,6 @@
 
 // For compatibility with IE/FF we only clip overflow on input elements.
 bool LayoutButton::HasControlClip() const {
-  return !isHTMLButtonElement(GetNode());
+  return !IsHTMLButtonElement(GetNode());
 }
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/LayoutButton.h b/third_party/WebKit/Source/core/layout/LayoutButton.h
index 7ddfabea..a911aaa 100644
--- a/third_party/WebKit/Source/core/layout/LayoutButton.h
+++ b/third_party/WebKit/Source/core/layout/LayoutButton.h
@@ -64,7 +64,7 @@
   void UpdateAnonymousChildStyle(const LayoutObject& child,
                                  ComputedStyle& child_style) const override;
 
-  bool HasLineIfEmpty() const override { return isHTMLInputElement(GetNode()); }
+  bool HasLineIfEmpty() const override { return IsHTMLInputElement(GetNode()); }
 
   LayoutBlock* inner_;
 };
diff --git a/third_party/WebKit/Source/core/layout/LayoutCountTest.cpp b/third_party/WebKit/Source/core/layout/LayoutCountTest.cpp
new file mode 100644
index 0000000..36b29ae28
--- /dev/null
+++ b/third_party/WebKit/Source/core/layout/LayoutCountTest.cpp
@@ -0,0 +1,25 @@
+// 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 "core/layout/LayoutBlockFlow.h"
+#include "core/layout/LayoutTestHelper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+class LayoutCountTest : public RenderingTest {};
+
+TEST_F(LayoutCountTest, SimpleBlockLayoutIsOnePass) {
+  RuntimeEnabledFeatures::SetTrackLayoutPassesPerBlockEnabled(true);
+  RuntimeEnabledFeatures::SetRootLayerScrollingEnabled(true);
+  SetBodyInnerHTML(
+      "<!DOCTYPE html>"
+      " <div id='block' style='height:1000px'>Item</div>");
+
+  LayoutBlockFlow* block = ToLayoutBlockFlow(
+      GetDocument().getElementById("block")->GetLayoutObject());
+  ASSERT_EQ(block->GetLayoutPassCountForTesting(), 1);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/LayoutCounter.cpp b/third_party/WebKit/Source/core/layout/LayoutCounter.cpp
index 01e3903..c1b2355e 100644
--- a/third_party/WebKit/Source/core/layout/LayoutCounter.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutCounter.cpp
@@ -190,13 +190,13 @@
         is_reset = false;
         return true;
       }
-      if (isHTMLOListElement(*e)) {
-        value = toHTMLOListElement(e)->StartConsideringItemCount();
+      if (auto* olist = ToHTMLOListElementOrNull(*e)) {
+        value = olist->StartConsideringItemCount();
         is_reset = true;
         return true;
       }
-      if (isHTMLUListElement(*e) || isHTMLMenuElement(*e) ||
-          isHTMLDirectoryElement(*e)) {
+      if (IsHTMLUListElement(*e) || IsHTMLMenuElement(*e) ||
+          IsHTMLDirectoryElement(*e)) {
         value = 0;
         is_reset = true;
         return true;
@@ -261,7 +261,7 @@
               // that reset is a root.
               parent = current_counter->Parent();
               previous_sibling = parent ? current_counter : nullptr;
-              return parent.Get();
+              return parent.get();
             }
             // We are not a reset node or the previous reset must be on an
             // ancestor of our owner layoutObject hence we must be a child of
@@ -274,7 +274,7 @@
             if (previous_sibling_protector->Parent() != current_counter)
               previous_sibling_protector = nullptr;
 
-            previous_sibling = previous_sibling_protector.Get();
+            previous_sibling = previous_sibling_protector.get();
             return true;
           }
           // CurrentCounter, the counter at the EndSearchLayoutObject, is not
@@ -289,7 +289,7 @@
               return false;
 
             parent = current_counter->Parent();
-            previous_sibling = previous_sibling_protector.Get();
+            previous_sibling = previous_sibling_protector.get();
             return true;
           }
         } else {
@@ -303,10 +303,10 @@
                                 *current_layout_object, counter_owner)) {
               parent = current_counter->Parent();
               previous_sibling = current_counter;
-              return parent.Get();
+              return parent.get();
             }
             parent = current_counter;
-            previous_sibling = previous_sibling_protector.Get();
+            previous_sibling = previous_sibling_protector.get();
             return true;
           }
           if (!is_reset || !AreLayoutObjectsElementsSiblings(
@@ -390,7 +390,7 @@
   RefPtr<CounterNode> new_node = CounterNode::Create(object, is_reset, value);
   if (FindPlaceForCounter(object, identifier, is_reset, new_parent,
                           new_previous_sibling))
-    new_parent->InsertAfter(new_node.Get(), new_previous_sibling.Get(),
+    new_parent->InsertAfter(new_node.get(), new_previous_sibling.get(),
                             identifier);
   CounterMap* node_map;
   if (object.HasCounterNodeMap()) {
@@ -402,7 +402,7 @@
   }
   node_map->Set(identifier, new_node);
   if (new_node->Parent())
-    return new_node.Get();
+    return new_node.get();
   // Checking if some nodes that were previously counter tree root nodes
   // should become children of this node now.
   CounterMaps& maps = GetCounterMaps();
@@ -428,7 +428,7 @@
       break;
     new_node->InsertAfter(current_counter, new_node->LastChild(), identifier);
   }
-  return new_node.Get();
+  return new_node.get();
 }
 
 LayoutCounter::LayoutCounter(PseudoElement& pseudo,
@@ -512,7 +512,7 @@
   for (RefPtr<CounterNode> child = node->LastDescendant();
        child && child != node; child = previous) {
     previous = child->PreviousInPreOrder();
-    child->Parent()->RemoveChild(child.Get());
+    child->Parent()->RemoveChild(child.get());
     DCHECK(GetCounterMaps().at(&child->Owner())->at(identifier) == child);
     GetCounterMaps().at(&child->Owner())->erase(identifier);
   }
@@ -528,7 +528,7 @@
   CounterMap* map = maps_iterator->value.get();
   CounterMap::const_iterator end = map->end();
   for (CounterMap::const_iterator it = map->begin(); it != end; ++it) {
-    DestroyCounterNodeWithoutMapRemoval(it->key, it->value.Get());
+    DestroyCounterNodeWithoutMapRemoval(it->key, it->value.get());
   }
   maps.erase(maps_iterator);
   owner.SetHasCounterNodeMap(false);
@@ -544,7 +544,7 @@
   CounterMap::iterator map_iterator = map->find(identifier);
   if (map_iterator == map->end())
     return;
-  DestroyCounterNodeWithoutMapRemoval(identifier, map_iterator->value.Get());
+  DestroyCounterNodeWithoutMapRemoval(identifier, map_iterator->value.get());
   map->erase(map_iterator);
   // We do not delete "map" here even if empty because we expect to reuse
   // it soon. In order for a layoutObject to lose all its counters permanently,
@@ -610,9 +610,9 @@
     if (new_parent == parent && new_previous_sibling == node->PreviousSibling())
       continue;
     if (parent)
-      parent->RemoveChild(node.Get());
+      parent->RemoveChild(node.get());
     if (new_parent)
-      new_parent->InsertAfter(node.Get(), new_previous_sibling.Get(), it->key);
+      new_parent->InsertAfter(node.get(), new_previous_sibling.get(), it->key);
   }
 }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutDetailsMarker.cpp b/third_party/WebKit/Source/core/layout/LayoutDetailsMarker.cpp
index 53b435b..4aeca58 100644
--- a/third_party/WebKit/Source/core/layout/LayoutDetailsMarker.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutDetailsMarker.cpp
@@ -61,11 +61,11 @@
        layout_object = layout_object->Parent()) {
     if (!layout_object->GetNode())
       continue;
-    if (isHTMLDetailsElement(*layout_object->GetNode()))
+    if (IsHTMLDetailsElement(*layout_object->GetNode()))
       return !ToElement(layout_object->GetNode())
                   ->getAttribute(openAttr)
                   .IsNull();
-    if (isHTMLInputElement(*layout_object->GetNode()))
+    if (IsHTMLInputElement(*layout_object->GetNode()))
       return true;
   }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutFieldset.cpp b/third_party/WebKit/Source/core/layout/LayoutFieldset.cpp
index 1778dfc..54c525d 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFieldset.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutFieldset.cpp
@@ -142,7 +142,7 @@
     if (legend->IsFloatingOrOutOfFlowPositioned())
       continue;
 
-    if (isHTMLLegendElement(legend->GetNode()))
+    if (IsHTMLLegendElement(legend->GetNode()))
       return ToLayoutBox(legend);
   }
   return nullptr;
diff --git a/third_party/WebKit/Source/core/layout/LayoutFileUploadControl.cpp b/third_party/WebKit/Source/core/layout/LayoutFileUploadControl.cpp
index eb0bf42..9f62c74 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFileUploadControl.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutFileUploadControl.cpp
@@ -163,8 +163,7 @@
   // FIXME: This should be on HTMLInputElement as an API like
   // innerButtonElement().
   HTMLInputElement* input = toHTMLInputElement(GetNode());
-  Node* button_node = input->UserAgentShadowRoot()->firstChild();
-  return isHTMLInputElement(button_node) ? toHTMLInputElement(button_node) : 0;
+  return ToHTMLInputElementOrNull(input->UserAgentShadowRoot()->firstChild());
 }
 
 String LayoutFileUploadControl::ButtonValue() {
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
index 07f6009..9c934784 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
@@ -1178,17 +1178,23 @@
 DISABLE_CFI_PERF
 FlexItem LayoutFlexibleBox::ConstructFlexItem(LayoutBox& child,
                                               ChildLayoutType layout_type) {
-  // If this condition is true, then computeMainAxisExtentForChild will call
-  // child.intrinsicContentLogicalHeight() and
-  // child.scrollbarLogicalHeight(), so if the child has intrinsic
-  // min/max/preferred size, run layout on it now to make sure its logical
-  // height and scroll bars are up to date.
-  if (layout_type != kNeverLayout && ChildHasIntrinsicMainAxisSize(child) &&
-      (child.NeedsLayout() || IsColumnFlow())) {
-    child.ClearOverrideSize();
-    child.ForceChildLayout();
-    CacheChildMainSize(child);
-    layout_type = kLayoutIfNeeded;
+  if (layout_type != kNeverLayout && ChildHasIntrinsicMainAxisSize(child)) {
+    // If this condition is true, then ComputeMainAxisExtentForChild will call
+    // child.IntrinsicContentLogicalHeight() and
+    // child.ScrollbarLogicalHeight(), so if the child has intrinsic
+    // min/max/preferred size, run layout on it now to make sure its logical
+    // height and scroll bars are up to date.
+    // For column flow flex containers, we even need to do this for children
+    // that don't need layout, if there's a chance that the logical width of
+    // the flex container has changed (because that may affect the intrinsic
+    // height of the child).
+    if (child.NeedsLayout() ||
+        (IsColumnFlow() && layout_type == kForceLayout)) {
+      child.ClearOverrideSize();
+      child.ForceChildLayout();
+      CacheChildMainSize(child);
+      layout_type = kLayoutIfNeeded;
+    }
   }
 
   MinMaxSize sizes = ComputeMinAndMaxSizesForChild(child);
diff --git a/third_party/WebKit/Source/core/layout/LayoutImage.cpp b/third_party/WebKit/Source/core/layout/LayoutImage.cpp
index 0c204c2c..e37a7b99 100644
--- a/third_party/WebKit/Source/core/layout/LayoutImage.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutImage.cpp
@@ -98,7 +98,7 @@
   if (new_image != image_resource_->ImagePtr())
     return;
 
-  if (IsGeneratedContent() && isHTMLImageElement(GetNode()) &&
+  if (IsGeneratedContent() && IsHTMLImageElement(GetNode()) &&
       image_resource_->ErrorOccurred()) {
     toHTMLImageElement(GetNode())->EnsureFallbackForGeneratedContent();
     return;
@@ -267,8 +267,7 @@
 }
 
 HTMLMapElement* LayoutImage::ImageMap() const {
-  HTMLImageElement* i =
-      isHTMLImageElement(GetNode()) ? toHTMLImageElement(GetNode()) : 0;
+  HTMLImageElement* i = ToHTMLImageElementOrNull(GetNode());
   return i ? i->GetTreeScope().GetImageMap(i->FastGetAttribute(usemapAttr)) : 0;
 }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutImageResourceStyleImage.cpp b/third_party/WebKit/Source/core/layout/LayoutImageResourceStyleImage.cpp
index 91a00eb8..36e27a6 100644
--- a/third_party/WebKit/Source/core/layout/LayoutImageResourceStyleImage.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutImageResourceStyleImage.cpp
@@ -64,8 +64,10 @@
   // don't assert but gracefully exit.
   if (style_image_->IsPendingImage())
     return nullptr;
+  LayoutSize logical_size(size);
   return style_image_->GetImage(*layout_object_, layout_object_->GetDocument(),
-                                layout_object_->StyleRef(), size);
+                                layout_object_->StyleRef(), size,
+                                &logical_size);
 }
 
 LayoutSize LayoutImageResourceStyleImage::ImageSize(float multiplier) const {
diff --git a/third_party/WebKit/Source/core/layout/LayoutListBox.cpp b/third_party/WebKit/Source/core/layout/LayoutListBox.cpp
index fb7cbd9..fc06475 100644
--- a/third_party/WebKit/Source/core/layout/LayoutListBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutListBox.cpp
@@ -48,7 +48,7 @@
 LayoutListBox::LayoutListBox(Element* element) : LayoutBlockFlow(element) {
   DCHECK(element);
   DCHECK(element->IsHTMLElement());
-  DCHECK(isHTMLSelectElement(element));
+  DCHECK(IsHTMLSelectElement(element));
 }
 
 LayoutListBox::~LayoutListBox() {}
@@ -84,8 +84,8 @@
 
   LayoutUnit max_height;
   for (Element* element : items) {
-    if (isHTMLOptGroupElement(element))
-      element = &toHTMLOptGroupElement(element)->OptGroupLabelElement();
+    if (auto* optgroup = ToHTMLOptGroupElementOrNull(element))
+      element = &optgroup->OptGroupLabelElement();
     LayoutObject* layout_object = element->GetLayoutObject();
     LayoutUnit item_height;
     if (layout_object && layout_object->IsBox())
diff --git a/third_party/WebKit/Source/core/layout/LayoutListItem.cpp b/third_party/WebKit/Source/core/layout/LayoutListItem.cpp
index 0313d23..ac624a1 100644
--- a/third_party/WebKit/Source/core/layout/LayoutListItem.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutListItem.cpp
@@ -146,8 +146,8 @@
       break;
 
     if (curr->IsListItem() && in_quirks_mode && curr_child->GetNode() &&
-        (isHTMLUListElement(*curr_child->GetNode()) ||
-         isHTMLOListElement(*curr_child->GetNode())))
+        (IsHTMLUListElement(*curr_child->GetNode()) ||
+         IsHTMLOListElement(*curr_child->GetNode())))
       break;
 
     LayoutObject* line_box =
diff --git a/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp b/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp
index 53f6c2a2a..ea76bfa 100644
--- a/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp
@@ -47,7 +47,7 @@
       inner_block_height_(LayoutUnit()),
       options_width_(0),
       last_active_index_(-1) {
-  DCHECK(isHTMLSelectElement(element));
+  DCHECK(IsHTMLSelectElement(element));
 }
 
 LayoutMenuList::~LayoutMenuList() {}
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
index e0cbb67..751cdcbd94 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -78,6 +78,7 @@
 #include "core/layout/api/LayoutAPIShim.h"
 #include "core/layout/api/LayoutEmbeddedContentItem.h"
 #include "core/layout/ng/layout_ng_block_flow.h"
+#include "core/layout/ng/layout_ng_list_item.h"
 #include "core/layout/ng/ng_layout_result.h"
 #include "core/layout/ng/ng_unpositioned_float.h"
 #include "core/layout/svg/SVGResources.h"
@@ -196,6 +197,8 @@
         return new LayoutNGBlockFlow(element);
       return new LayoutBlockFlow(element);
     case EDisplay::kListItem:
+      if (RuntimeEnabledFeatures::LayoutNGEnabled())
+        return new LayoutNGListItem(element);
       return new LayoutListItem(element);
     case EDisplay::kTable:
     case EDisplay::kInlineTable:
@@ -260,7 +263,7 @@
 }
 
 bool LayoutObject::IsHR() const {
-  return isHTMLHRElement(GetNode());
+  return IsHTMLHRElement(GetNode());
 }
 
 void LayoutObject::SetIsInsideFlowThreadIncludingDescendants(
@@ -1137,17 +1140,12 @@
   if (dirty_rect.IsEmpty())
     return;
 
-  auto& rare_paint_data = EnsureRarePaintData();
-  rare_paint_data.SetPartialInvalidationRect(
-      UnionRect(dirty_rect, rare_paint_data.PartialInvalidationRect()));
+  SetPartialInvalidationRect(UnionRect(dirty_rect, PartialInvalidationRect()));
 
-  if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
-    SetMayNeedPaintInvalidationWithoutGeometryChange();
-  } else {
-    // Not using the WithoutGeometryChange version because we need to map
-    // the partial invalidated rect to visual rect in backing.
-    SetMayNeedPaintInvalidation();
-  }
+  // Not using the WithoutGeometryChange version because we need to map the
+  // partial invalidated rect to visual rect in backing or the containing
+  // transform node.
+  SetMayNeedPaintInvalidation();
 }
 
 LayoutRect LayoutObject::SelectionRectInViewCoordinates() const {
@@ -1182,8 +1180,10 @@
 
 void LayoutObject::ClearPreviousVisualRects() {
   SetVisualRect(LayoutRect());
-  if (rare_paint_data_)
+  if (rare_paint_data_) {
     rare_paint_data_->SetLocationInBacking(LayoutPoint());
+    rare_paint_data_->SetSelectionVisualRect(LayoutRect());
+  }
   // Ensure check paint invalidation of subtree that would be triggered by
   // location change if we had valid previous location.
   SetMayNeedPaintInvalidationSubtree();
@@ -1575,11 +1575,11 @@
   UpdateCursorImages(old_style ? old_style->Cursors() : nullptr,
                      style_->Cursors());
 
-  CheckCounterChanges(old_style.Get(), style_.Get());
+  CheckCounterChanges(old_style.get(), style_.get());
 
   bool does_not_need_layout_or_paint_invalidation = !parent_;
 
-  StyleDidChange(diff, old_style.Get());
+  StyleDidChange(diff, old_style.get());
 
   // FIXME: |this| might be destroyed here. This can currently happen for a
   // LayoutTextFragment when its first-letter block gets an update in
@@ -2462,7 +2462,7 @@
   if (layout_object->GetDocument().IsImageDocument())
     return kRespectImageOrientation;
 
-  if (!isHTMLImageElement(layout_object->GetNode()))
+  if (!IsHTMLImageElement(layout_object->GetNode()))
     return kDoNotRespectImageOrientation;
 
   if (layout_object->GetDocument().GetSettings() &&
@@ -2893,11 +2893,7 @@
   return inside;
 }
 
-void LayoutObject::UpdateHitTestResult(HitTestResult& result,
-                                       const LayoutPoint& point) {
-  if (result.InnerNode())
-    return;
-
+Node* LayoutObject::NodeForHitTest() const {
   Node* node = this->GetNode();
 
   // If we hit the anonymous layoutObjects inside generated content we should
@@ -2908,8 +2904,16 @@
       node = layout_object->GetNode();
   }
 
-  if (node)
-    result.SetNodeAndPosition(node, point);
+  return node;
+}
+
+void LayoutObject::UpdateHitTestResult(HitTestResult& result,
+                                       const LayoutPoint& point) {
+  if (result.InnerNode())
+    return;
+
+  if (Node* n = NodeForHitTest())
+    result.SetNodeAndPosition(n, point);
 }
 
 bool LayoutObject::NodeAtPoint(HitTestResult&,
@@ -2996,17 +3000,17 @@
 
   DCHECK(!IsText());
 
-  return FirstLineStyleForCachedUncachedType(kUncached, this, style_.Get());
+  return FirstLineStyleForCachedUncachedType(kUncached, this, style_.get());
 }
 
 ComputedStyle* LayoutObject::CachedFirstLineStyle() const {
   DCHECK(GetDocument().GetStyleEngine().UsesFirstLineRules());
 
   if (RefPtr<ComputedStyle> style = FirstLineStyleForCachedUncachedType(
-          kCached, IsText() ? Parent() : this, style_.Get()))
-    return style.Get();
+          kCached, IsText() ? Parent() : this, style_.get()))
+    return style.get();
 
-  return style_.Get();
+  return style_.get();
 }
 
 ComputedStyle* LayoutObject::GetCachedPseudoStyle(
@@ -3161,11 +3165,11 @@
     if (ancestor->CanContainAbsolutePositionObjects())
       break;
 
-    if (isHTMLBodyElement(*node))
+    if (IsHTMLBodyElement(*node))
       break;
 
     if (!IsPositioned() &&
-        (isHTMLTableElement(*node) || IsHTMLTableCellElement(*node)))
+        (IsHTMLTableElement(*node) || IsHTMLTableCellElement(*node)))
       break;
 
     // Webkit specific extension where offsetParent stops at zoom level changes.
@@ -3417,12 +3421,12 @@
 }
 
 void LayoutObject::ClearPaintInvalidationFlags() {
-// paintInvalidationStateIsDirty should be kept in sync with the
+// PaintInvalidationStateIsDirty should be kept in sync with the
 // booleans that are cleared below.
 #if DCHECK_IS_ON()
   DCHECK(!ShouldCheckForPaintInvalidation() || PaintInvalidationStateIsDirty());
 #endif
-  if (rare_paint_data_)
+  if (rare_paint_data_ && !RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
     rare_paint_data_->SetPartialInvalidationRect(LayoutRect());
   ClearShouldDoFullPaintInvalidation();
   bitfields_.SetMayNeedPaintInvalidation(false);
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.h b/third_party/WebKit/Source/core/layout/LayoutObject.h
index c7d38b3..9c5be09d 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.h
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.h
@@ -202,6 +202,8 @@
                                  public DisplayItemClient {
   friend class LayoutObjectChildList;
   FRIEND_TEST_ALL_PREFIXES(LayoutObjectTest, MutableForPaintingClearPaintFlags);
+  FRIEND_TEST_ALL_PREFIXES(LayoutObjectTest,
+                           LocationInBackingAndSelectionVisualRect);
   friend class VisualRectMappingTest;
   WTF_MAKE_NONCOPYABLE(LayoutObject);
 
@@ -221,6 +223,14 @@
 
   // DisplayItemClient methods.
   LayoutRect VisualRect() const final { return visual_rect_; }
+  LayoutRect PartialInvalidationRect() const final {
+    return rare_paint_data_ ? rare_paint_data_->PartialInvalidationRect()
+                            : LayoutRect();
+  }
+  void ClearPartialInvalidationRect() const final {
+    DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
+    return GetMutableForPainting().SetPartialInvalidationRect(LayoutRect());
+  }
   String DebugName() const final;
 
   LayoutObject* Parent() const { return parent_; }
@@ -492,6 +502,7 @@
   bool IsLayoutNGBlockFlow() const {
     return IsOfType(kLayoutObjectNGBlockFlow);
   }
+  bool IsLayoutNGListItem() const { return IsOfType(kLayoutObjectNGListItem); }
   bool IsLayoutTableCol() const {
     return IsOfType(kLayoutObjectLayoutTableCol);
   }
@@ -1124,6 +1135,11 @@
                const HitTestLocation& location_in_container,
                const LayoutPoint& accumulated_offset,
                HitTestFilter = kHitTestAll);
+  // Returns the node that is ultimately added to the hit test result. Some
+  // objects report a hit testing node that is not their own (such as
+  // continuations and some psuedo elements) and it is important that the
+  // node be consistent between point- and list-based hit test results.
+  virtual Node* NodeForHitTest() const;
   virtual void UpdateHitTestResult(HitTestResult&, const LayoutPoint&);
   virtual bool NodeAtPoint(HitTestResult&,
                            const HitTestLocation& location_in_container,
@@ -1325,8 +1341,8 @@
   // TODO(jchaffraix): We will probably want to rename it to match CSS 3.
   virtual LayoutUnit MaxPreferredLogicalWidth() const { return LayoutUnit(); }
 
-  const ComputedStyle* Style() const { return style_.Get(); }
-  ComputedStyle* MutableStyle() const { return style_.Get(); }
+  const ComputedStyle* Style() const { return style_.get(); }
+  ComputedStyle* MutableStyle() const { return style_.get(); }
 
   // style_ can only be nullptr before the first style is set, thus most
   // callers will never see a nullptr style and should use StyleRef().
@@ -1753,7 +1769,8 @@
         layout_object_.EnsureRarePaintData().SetLocationInBacking(p);
     }
     void SetSelectionVisualRect(const LayoutRect& r) {
-      layout_object_.EnsureRarePaintData().SetSelectionVisualRect(r);
+      if (layout_object_.GetRarePaintData() || !r.IsEmpty())
+        layout_object_.EnsureRarePaintData().SetSelectionVisualRect(r);
     }
 
     void SetPreviousBackgroundObscured(bool b) {
@@ -1771,6 +1788,10 @@
       layout_object_.SetNeedsPaintPropertyUpdate();
     }
 
+    void SetPartialInvalidationRect(const LayoutRect& r) {
+      layout_object_.SetPartialInvalidationRect(r);
+    }
+
 #if DCHECK_IS_ON()
     // Same as setNeedsPaintPropertyUpdate() but does not mark ancestors as
     // having a descendant needing a paint property update.
@@ -1888,10 +1909,6 @@
     return rare_paint_data_ ? rare_paint_data_->SelectionVisualRect()
                             : LayoutRect();
   }
-  LayoutRect PartialInvalidationRect() const {
-    return rare_paint_data_ ? rare_paint_data_->PartialInvalidationRect()
-                            : LayoutRect();
-  }
 
  protected:
   enum LayoutObjectType {
@@ -1911,6 +1928,7 @@
     kLayoutObjectMedia,
     kLayoutObjectMenuList,
     kLayoutObjectNGBlockFlow,
+    kLayoutObjectNGListItem,
     kLayoutObjectProgress,
     kLayoutObjectQuote,
     kLayoutObjectLayoutButton,
@@ -2025,12 +2043,19 @@
                                        const LayoutPoint& layer_offset) const {}
 
   void SetVisualRect(const LayoutRect& rect) { visual_rect_ = rect; }
+  void SetPartialInvalidationRect(const LayoutRect& rect) {
+    if (GetRarePaintData() || !rect.IsEmpty())
+      EnsureRarePaintData().SetPartialInvalidationRect(rect);
+  }
 
 #if DCHECK_IS_ON()
   virtual bool PaintInvalidationStateIsDirty() const {
     return BackgroundChangedSinceLastPaintInvalidation() ||
            ShouldCheckForPaintInvalidation() || ShouldInvalidateSelection() ||
-           NeedsPaintOffsetAndVisualRectUpdate();
+           NeedsPaintOffsetAndVisualRectUpdate() ||
+           (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled() &&
+            rare_paint_data_ &&
+            !rare_paint_data_->PartialInvalidationRect().IsEmpty());
   }
 #endif
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp b/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp
index b128589b..ad6d4ac 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp
@@ -384,7 +384,7 @@
 
   MockLayoutObject mock_object;
   auto style = ComputedStyle::Create();
-  mock_object.SetStyle(style.Get());
+  mock_object.SetStyle(style.get());
   EXPECT_EQ(LayoutRect(10, 10, 20, 20), mock_object.LocalVisualRect());
   EXPECT_EQ(LayoutRect(10, 10, 20, 20), mock_object.LocalVisualRect());
 
@@ -397,4 +397,39 @@
   EXPECT_EQ(LayoutRect(10, 10, 20, 20), mock_object.LocalVisualRect());
 }
 
+TEST_F(LayoutObjectTest, LocationInBackingAndSelectionVisualRect) {
+  auto* object = GetDocument().body()->GetLayoutObject();
+  EXPECT_EQ(nullptr, object->GetRarePaintData());
+
+  // Default LocationInBacking and SelectionVisualRect should not create
+  // RarePaintData.
+  object->SetVisualRect(LayoutRect(10, 20, 30, 400));
+  object->GetMutableForPainting().SetLocationInBacking(LayoutPoint(10, 20));
+  object->GetMutableForPainting().SetSelectionVisualRect(LayoutRect());
+  EXPECT_EQ(nullptr, object->GetRarePaintData());
+  EXPECT_EQ(LayoutPoint(10, 20), object->LocationInBacking());
+  EXPECT_EQ(LayoutRect(), object->SelectionVisualRect());
+
+  // Non-Default LocationInBacking and SelectionVisualRect create RarePaintData.
+  object->GetMutableForPainting().SetLocationInBacking(LayoutPoint(20, 30));
+  object->GetMutableForPainting().SetSelectionVisualRect(
+      LayoutRect(1, 2, 3, 4));
+  EXPECT_NE(nullptr, object->GetRarePaintData());
+  EXPECT_EQ(LayoutPoint(20, 30), object->LocationInBacking());
+  EXPECT_EQ(LayoutRect(1, 2, 3, 4), object->SelectionVisualRect());
+
+  // RarePaintData should store default LocationInBacking and
+  // SelectionVisualRect once it's created.
+  object->GetMutableForPainting().SetLocationInBacking(LayoutPoint(10, 20));
+  object->GetMutableForPainting().SetSelectionVisualRect(LayoutRect());
+  EXPECT_NE(nullptr, object->GetRarePaintData());
+  EXPECT_EQ(LayoutPoint(10, 20), object->LocationInBacking());
+  EXPECT_EQ(LayoutRect(), object->SelectionVisualRect());
+
+  object->ClearPreviousVisualRects();
+  EXPECT_EQ(LayoutRect(), object->VisualRect());
+  EXPECT_EQ(LayoutPoint(), object->LocationInBacking());
+  EXPECT_EQ(LayoutRect(), object->SelectionVisualRect());
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/LayoutTable.cpp b/third_party/WebKit/Source/core/layout/LayoutTable.cpp
index bb168a0..2a21e9e 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTable.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTable.cpp
@@ -398,7 +398,7 @@
   // HTML tables' width styles already include borders and paddings, but CSS
   // tables' width styles do not.
   LayoutUnit borders;
-  bool is_css_table = !isHTMLTableElement(GetNode());
+  bool is_css_table = !IsHTMLTableElement(GetNode());
   if (is_css_table && style_logical_width.IsSpecified() &&
       style_logical_width.IsPositive() &&
       Style()->BoxSizing() == EBoxSizing::kContentBox) {
@@ -426,7 +426,7 @@
     LayoutUnit borders = LayoutUnit();
     // FIXME: We cannot apply box-sizing: content-box on <table> which other
     // browsers allow.
-    if (isHTMLTableElement(GetNode()) ||
+    if (IsHTMLTableElement(GetNode()) ||
         Style()->BoxSizing() == EBoxSizing::kBorderBox) {
       borders = border_and_padding;
     }
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
index 8a16143d..97c2d4bc 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
@@ -1726,7 +1726,7 @@
     c_col_++;
   for (unsigned row = 0; row < grid_.size(); ++row) {
     auto& grid_cells = grid_[row].grid_cells;
-    EnsureCols(row, pos + 2);
+    EnsureCols(row, pos + 1);
     grid_cells.insert(pos + 1, TableGridCell());
     if (grid_cells[pos].HasCells()) {
       grid_cells[pos + 1].Cells().AppendVector(grid_cells[pos].Cells());
diff --git a/third_party/WebKit/Source/core/layout/LayoutTestHelper.cpp b/third_party/WebKit/Source/core/layout/LayoutTestHelper.cpp
index 6b85596c..943e168a 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTestHelper.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTestHelper.cpp
@@ -89,7 +89,7 @@
   RefPtr<SharedBuffer> shared_buffer =
       testing::ReadFromFile(testing::CoreTestDataPath("Ahem.ttf"));
   StringOrArrayBufferOrArrayBufferView buffer =
-      StringOrArrayBufferOrArrayBufferView::fromArrayBuffer(
+      StringOrArrayBufferOrArrayBufferView::FromArrayBuffer(
           DOMArrayBuffer::Create(shared_buffer));
   FontFace* ahem =
       FontFace::Create(&document, "Ahem", buffer, FontFaceDescriptors());
diff --git a/third_party/WebKit/Source/core/layout/LayoutText.cpp b/third_party/WebKit/Source/core/layout/LayoutText.cpp
index ea42ad0..1f592d2 100644
--- a/third_party/WebKit/Source/core/layout/LayoutText.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutText.cpp
@@ -1449,7 +1449,7 @@
                                    unsigned offset,
                                    unsigned len,
                                    bool force) {
-  if (!force && Equal(text_.Impl(), text.Get()))
+  if (!force && Equal(text_.Impl(), text.get()))
     return;
 
   unsigned old_len = TextLength();
@@ -1643,7 +1643,7 @@
 void LayoutText::SetText(RefPtr<StringImpl> text, bool force) {
   DCHECK(text);
 
-  if (!force && Equal(text_.Impl(), text.Get()))
+  if (!force && Equal(text_.Impl(), text.get()))
     return;
 
   SetTextInternal(std::move(text));
diff --git a/third_party/WebKit/Source/core/layout/LayoutTextFragment.cpp b/third_party/WebKit/Source/core/layout/LayoutTextFragment.cpp
index 92f5823..17e07402 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTextFragment.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTextFragment.cpp
@@ -125,7 +125,7 @@
 
 UChar LayoutTextFragment::PreviousCharacter() const {
   if (Start()) {
-    StringImpl* original = CompleteText().Get();
+    StringImpl* original = CompleteText().get();
     if (original && Start() <= original->length())
       return (*original)[Start() - 1];
   }
diff --git a/third_party/WebKit/Source/core/layout/LayoutTextFragment.h b/third_party/WebKit/Source/core/layout/LayoutTextFragment.h
index 01827a9..1bb2c94 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTextFragment.h
+++ b/third_party/WebKit/Source/core/layout/LayoutTextFragment.h
@@ -59,7 +59,7 @@
   unsigned TextStartOffset() const override { return Start(); }
 
   void SetContentString(StringImpl*);
-  StringImpl* ContentString() const { return content_string_.Get(); }
+  StringImpl* ContentString() const { return content_string_.get(); }
   // The complete text is all of the text in the associated DOM text node.
   RefPtr<StringImpl> CompleteText() const;
   // The fragment text is the text which will be used by this
diff --git a/third_party/WebKit/Source/core/layout/LayoutTheme.cpp b/third_party/WebKit/Source/core/layout/LayoutTheme.cpp
index fadda3a..09d5e2a 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTheme.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTheme.cpp
@@ -483,15 +483,15 @@
 }
 
 bool LayoutTheme::IsChecked(const LayoutObject& o) {
-  if (!isHTMLInputElement(o.GetNode()))
-    return false;
-  return toHTMLInputElement(o.GetNode())->ShouldAppearChecked();
+  if (auto* input = ToHTMLInputElementOrNull(o.GetNode()))
+    return input->ShouldAppearChecked();
+  return false;
 }
 
 bool LayoutTheme::IsIndeterminate(const LayoutObject& o) {
-  if (!isHTMLInputElement(o.GetNode()))
-    return false;
-  return toHTMLInputElement(o.GetNode())->ShouldAppearIndeterminate();
+  if (auto* input = ToHTMLInputElementOrNull(o.GetNode()))
+    return input->ShouldAppearIndeterminate();
+  return false;
 }
 
 bool LayoutTheme::IsEnabled(const LayoutObject& o) {
diff --git a/third_party/WebKit/Source/core/layout/LayoutThemeMobile.cpp b/third_party/WebKit/Source/core/layout/LayoutThemeMobile.cpp
index b3e1819..03980c5b 100644
--- a/third_party/WebKit/Source/core/layout/LayoutThemeMobile.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutThemeMobile.cpp
@@ -29,6 +29,7 @@
 #include "core/style/ComputedStyle.h"
 #include "platform/DataResourceHelper.h"
 #include "platform/LayoutTestSupport.h"
+#include "platform/runtime_enabled_features.h"
 #include "public/platform/Platform.h"
 #include "public/platform/WebThemeEngine.h"
 
@@ -47,7 +48,9 @@
 }
 
 String LayoutThemeMobile::ExtraMediaControlsStyleSheet() {
-  return GetDataResourceAsASCIIString("mediaControlsAndroid.css");
+  if (RuntimeEnabledFeatures::ModernMediaControlsEnabled())
+    return String();
+  return GetDataResourceAsASCIIString("legacyMediaControlsAndroid.css");
 }
 
 String LayoutThemeMobile::ExtraFullscreenStyleSheet() {
diff --git a/third_party/WebKit/Source/core/layout/LayoutTreeAsText.cpp b/third_party/WebKit/Source/core/layout/LayoutTreeAsText.cpp
index 31d6a647..d149869 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTreeAsText.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTreeAsText.cpp
@@ -515,10 +515,11 @@
       LayoutViewItem root_item = frame_view->GetLayoutViewItem();
       if (!root_item.IsNull()) {
         root_item.UpdateStyleAndLayout();
-        PaintLayer* layer = root_item.Layer();
-        if (layer)
-          LayoutTreeAsText::WriteLayers(ts, layer, layer, layer->Rect(),
-                                        indent + 1, behavior);
+        if (auto* layer = root_item.Layer()) {
+          LayoutTreeAsText::WriteLayers(
+              ts, layer, layer, layer->RectIgnoringNeedsPositionUpdate(),
+              indent + 1, behavior);
+        }
       }
     }
   }
@@ -678,6 +679,13 @@
       ToLayoutEmbeddedContent(layer->GetLayoutObject()).IsThrottledFrameView())
     should_paint = false;
 
+#if DCHECK_IS_ON()
+  if (layer->NeedsPositionUpdate()) {
+    WriteIndent(ts, indent);
+    ts << " NEEDS POSITION UPDATE\n";
+  }
+#endif
+
   Vector<PaintLayerStackingNode*>* neg_list =
       layer->StackingNode()->NegZOrderList();
   bool paints_background_separately = neg_list && neg_list->size() > 0;
@@ -802,8 +810,9 @@
     return ts.Release();
 
   PaintLayer* layer = layout_object->Layer();
-  LayoutTreeAsText::WriteLayers(ts, layer, layer, layer->Rect(), 0, behavior,
-                                marked_layer);
+  LayoutTreeAsText::WriteLayers(ts, layer, layer,
+                                layer->RectIgnoringNeedsPositionUpdate(), 0,
+                                behavior, marked_layer);
   WriteSelection(ts, layout_object);
   return ts.Release();
 }
diff --git a/third_party/WebKit/Source/core/layout/LayoutView.cpp b/third_party/WebKit/Source/core/layout/LayoutView.cpp
index 6673ace..f6c7f5d 100644
--- a/third_party/WebKit/Source/core/layout/LayoutView.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutView.cpp
@@ -602,13 +602,13 @@
 void LayoutView::AbsoluteRects(Vector<IntRect>& rects,
                                const LayoutPoint& accumulated_offset) const {
   rects.push_back(
-      PixelSnappedIntRect(accumulated_offset, LayoutSize(Layer()->size())));
+      PixelSnappedIntRect(accumulated_offset, LayoutSize(Layer()->Size())));
 }
 
 void LayoutView::AbsoluteQuads(Vector<FloatQuad>& quads,
                                MapCoordinatesFlags mode) const {
   quads.push_back(LocalToAbsoluteQuad(
-      FloatRect(FloatPoint(), FloatSize(Layer()->size())), mode));
+      FloatRect(FloatPoint(), FloatSize(Layer()->Size())), mode));
 }
 
 void LayoutView::ClearSelection() {
@@ -671,7 +671,7 @@
   Document& document = GetDocument();
   if (Node* body = document.body()) {
     // Framesets can't scroll.
-    if (isHTMLFrameSetElement(body) && body->GetLayoutObject())
+    if (IsHTMLFrameSetElement(body) && body->GetLayoutObject())
       RETURN_SCROLLBAR_MODE(kScrollbarAlwaysOff);
   }
 
@@ -848,7 +848,7 @@
 IntervalArena* LayoutView::GetIntervalArena() {
   if (!interval_arena_)
     interval_arena_ = IntervalArena::Create();
-  return interval_arena_.Get();
+  return interval_arena_.get();
 }
 
 bool LayoutView::BackgroundIsKnownToBeOpaqueInRect(const LayoutRect&) const {
diff --git a/third_party/WebKit/Source/core/layout/MultiColumnFragmentainerGroupTest.cpp b/third_party/WebKit/Source/core/layout/MultiColumnFragmentainerGroupTest.cpp
index 64ed5e8a..4e7e9349 100644
--- a/third_party/WebKit/Source/core/layout/MultiColumnFragmentainerGroupTest.cpp
+++ b/third_party/WebKit/Source/core/layout/MultiColumnFragmentainerGroupTest.cpp
@@ -35,7 +35,7 @@
   RenderingTest::SetUp();
   RefPtr<ComputedStyle> style = ComputedStyle::Create();
   flow_thread_ =
-      LayoutMultiColumnFlowThread::CreateAnonymous(GetDocument(), *style.Get());
+      LayoutMultiColumnFlowThread::CreateAnonymous(GetDocument(), *style.get());
   column_set_ = LayoutMultiColumnSet::CreateAnonymous(*flow_thread_,
                                                       *flow_thread_->Style());
 }
diff --git a/third_party/WebKit/Source/core/layout/TextAutosizer.cpp b/third_party/WebKit/Source/core/layout/TextAutosizer.cpp
index 4a18aea2..566bb25 100644
--- a/third_party/WebKit/Source/core/layout/TextAutosizer.cpp
+++ b/third_party/WebKit/Source/core/layout/TextAutosizer.cpp
@@ -74,7 +74,7 @@
     return false;
   const Element* element = ToElement(node);
 
-  return (element->IsFormControlElement() && !isHTMLTextAreaElement(element));
+  return (element->IsFormControlElement() && !IsHTMLTextAreaElement(element));
 }
 
 static bool IsPotentialClusterRoot(const LayoutObject* layout_object) {
diff --git a/third_party/WebKit/Source/core/layout/TextDecorationOffset.cpp b/third_party/WebKit/Source/core/layout/TextDecorationOffset.cpp
index f2801baa6..0ea1fdd 100644
--- a/third_party/WebKit/Source/core/layout/TextDecorationOffset.cpp
+++ b/third_party/WebKit/Source/core/layout/TextDecorationOffset.cpp
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "core/layout/TextDecorationOffset.h"
+
 #include "core/layout/line/InlineTextBox.h"
 #include "core/layout/line/RootInlineBox.h"
 #include "platform/fonts/FontMetrics.h"
diff --git a/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp b/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp
index b08c8ef0..d4c3f40 100644
--- a/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp
+++ b/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp
@@ -371,7 +371,7 @@
   CheckPaintInvalidationVisualRect(*target);
   // (2, 3, 140, 100) is first clipped by container's overflow clip, to
   // (10, 10, 50, 80), then is by added container's offset in LayoutView
-  // (111, 222).
+  // (222, 111).
   EXPECT_EQ(LayoutRect(232, 121, 50, 80), target->VisualRect());
 
   LayoutRect container_local_visual_rect = container->LocalVisualRect();
@@ -408,8 +408,8 @@
   // 150 = total_layout_overflow(100 + 100) - width(50)
   EXPECT_EQ(LayoutUnit(150), container->ScrollLeft());
   container->SetScrollTop(LayoutUnit(7));
-  container->SetScrollLeft(
-      LayoutUnit(142));  // Scroll to the right by 8 pixels.
+  // Scroll to the right by 8 pixels.
+  container->SetScrollLeft(LayoutUnit(142));
   GetDocument().View()->UpdateAllLifecyclePhases();
 
   LayoutBlock* target = ToLayoutBlock(GetLayoutObjectByElementId("target"));
@@ -438,10 +438,9 @@
   CheckPaintInvalidationVisualRect(*target);
   // (-2, 3, 140, 100) is first clipped by container's overflow clip, to
   // (40, 10, 50, 80), then is added by container's offset in LayoutView
-  // (111, 222).
-  // TODO(crbug.com/600039): rect.x() should be 262 (left + border-left), but is
-  // offset
-  // by extra horizontal border-widths because of layout error.
+  // (222, 111).
+  // TODO(crbug.com/600039): rect.X() should be 262 (left + border-left), but is
+  // offset by extra horizontal border-widths because of layout error.
   EXPECT_EQ(LayoutRect(322, 121, 50, 80), target->VisualRect());
 
   LayoutRect container_local_visual_rect = container->LocalVisualRect();
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_baseline.h b/third_party/WebKit/Source/core/layout/ng/inline/ng_baseline.h
index d8561567..f8e9319 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_baseline.h
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_baseline.h
@@ -16,8 +16,6 @@
 enum class NGBaselineAlgorithmType {
   // Compute baselines for atomic inlines.
   kAtomicInline,
-  // Compute baselines for atomic inlines using the first line style.
-  kAtomicInlineForFirstLine,
   // Compute baseline of first line box.
   kFirstLine
 };
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_item.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_item.cc
index 89f29b6..78807ec6 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_item.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_item.cc
@@ -31,9 +31,7 @@
       layout_object_(layout_object),
       type_(type),
       bidi_level_(UBIDI_LTR),
-      shape_options_(kPreContext | kPostContext),
-      rotate_sideways_(false),
-      fallback_priority_(FontFallbackPriority::kInvalid) {
+      shape_options_(kPreContext | kPostContext) {
   DCHECK_GE(end, start);
 }
 
@@ -142,7 +140,8 @@
 bool NGInlineItem::HasEndEdge() const {
   DCHECK(Type() == kOpenTag || Type() == kCloseTag);
   // TODO(kojii): Should use break token when NG has its own tree building.
-  return !ToLayoutInline(GetLayoutObject())->Continuation();
+  return !GetLayoutObject()->IsLayoutInline() ||
+         !ToLayoutInline(GetLayoutObject())->Continuation();
 }
 
 NGInlineItemRange::NGInlineItemRange(Vector<NGInlineItem>* items,
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_item.h b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_item.h
index fa60d4cc..b024b6b 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_item.h
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_item.h
@@ -59,7 +59,7 @@
   NGInlineItemType Type() const { return static_cast<NGInlineItemType>(type_); }
   const char* NGInlineItemTypeToString(int val) const;
 
-  const ShapeResult* TextShapeResult() const { return shape_result_.Get(); }
+  const ShapeResult* TextShapeResult() const { return shape_result_.get(); }
   NGLayoutInlineShapeOptions ShapeOptions() const {
     return static_cast<NGLayoutInlineShapeOptions>(shape_options_);
   }
@@ -70,7 +70,7 @@
   TextDirection Direction() const { return DirectionFromLevel(BidiLevel()); }
   UBiDiLevel BidiLevel() const { return static_cast<UBiDiLevel>(bidi_level_); }
   UScriptCode GetScript() const { return script_; }
-  const ComputedStyle* Style() const { return style_.Get(); }
+  const ComputedStyle* Style() const { return style_.get(); }
   LayoutObject* GetLayoutObject() const { return layout_object_; }
 
   void SetOffset(unsigned start, unsigned end);
@@ -104,11 +104,6 @@
   unsigned type_ : 3;
   unsigned bidi_level_ : 8;  // UBiDiLevel is defined as uint8_t.
   unsigned shape_options_ : 2;
-  unsigned rotate_sideways_ : 1;
-
-  // TODO(layout-ng): Do we need fallback_priority_ here? If so we should pack
-  // it with the bit field above.
-  FontFallbackPriority fallback_priority_;
 
   friend class NGInlineNode;
 };
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_items_builder_test.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_items_builder_test.cc
index 3a451f14..7acfc663 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_items_builder_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_items_builder_test.cc
@@ -53,7 +53,7 @@
     items_.clear();
     NGInlineItemsBuilderForOffsetMapping builder(&items_);
     for (int i = 0; i < size; i++)
-      builder.Append(inputs[i], style_.Get());
+      builder.Append(inputs[i], style_.get());
     text_ = builder.ToString();
     collapsed_ = GetCollapsed(builder.GetOffsetMappingBuilder());
     ValidateItems();
@@ -248,8 +248,8 @@
        CollapsibleSpaceAfterNonCollapsibleSpaceAcrossElements) {
   NGInlineItemsBuilderForOffsetMapping builder(&items_);
   RefPtr<ComputedStyle> pre_wrap(CreateWhitespaceStyle(EWhiteSpace::kPreWrap));
-  builder.Append("text ", pre_wrap.Get());
-  builder.Append(" text", style_.Get());
+  builder.Append("text ", pre_wrap.get());
+  builder.Append(" text", style_.get());
   EXPECT_EQ("text  text", builder.ToString())
       << "The whitespace in constructions like '<span style=\"white-space: "
          "pre-wrap\">text <span><span> text</span>' does not collapse.";
@@ -309,22 +309,22 @@
 
 TEST_F(NGInlineItemsBuilderTest, OpaqueToSpaceCollapsing) {
   NGInlineItemsBuilderForOffsetMapping builder(&items_);
-  builder.Append("Hello ", style_.Get());
+  builder.Append("Hello ", style_.get());
   builder.AppendOpaque(NGInlineItem::kBidiControl,
                        kFirstStrongIsolateCharacter);
-  builder.Append(" ", style_.Get());
+  builder.Append(" ", style_.get());
   builder.AppendOpaque(NGInlineItem::kBidiControl,
                        kFirstStrongIsolateCharacter);
-  builder.Append(" World", style_.Get());
+  builder.Append(" World", style_.get());
   EXPECT_EQ(String(u"Hello \u2068\u2068World"), builder.ToString());
   EXPECT_EQ("{7, 9}", GetCollapsed(builder.GetOffsetMappingBuilder()));
 }
 
 TEST_F(NGInlineItemsBuilderTest, CollapseAroundReplacedElement) {
   NGInlineItemsBuilderForOffsetMapping builder(&items_);
-  builder.Append("Hello ", style_.Get());
+  builder.Append("Hello ", style_.get());
   builder.Append(NGInlineItem::kAtomicInline, kObjectReplacementCharacter);
-  builder.Append(" World", style_.Get());
+  builder.Append(" World", style_.get());
   EXPECT_EQ(String(u"Hello \uFFFC World"), builder.ToString());
   EXPECT_EQ("{}", GetCollapsed(builder.GetOffsetMappingBuilder()));
 }
@@ -332,12 +332,12 @@
 TEST_F(NGInlineItemsBuilderTest, CollapseNewlineAfterObject) {
   NGInlineItemsBuilderForOffsetMapping builder(&items_);
   builder.Append(NGInlineItem::kAtomicInline, kObjectReplacementCharacter);
-  builder.Append("\n", style_.Get());
+  builder.Append("\n", style_.get());
   builder.Append(NGInlineItem::kAtomicInline, kObjectReplacementCharacter);
   EXPECT_EQ(String(u"\uFFFC \uFFFC"), builder.ToString());
   EXPECT_EQ(3u, items_.size());
   EXPECT_EQ(nullptr, items_[0].Style());
-  EXPECT_EQ(style_.Get(), items_[1].Style());
+  EXPECT_EQ(style_.get(), items_[1].Style());
   EXPECT_EQ(nullptr, items_[2].Style());
   EXPECT_EQ("{}", GetCollapsed(builder.GetOffsetMappingBuilder()));
 }
@@ -365,7 +365,7 @@
   Vector<NGInlineItem> items;
   NGInlineItemsBuilderForOffsetMapping builder(&items);
   RefPtr<ComputedStyle> block_style(ComputedStyle::Create());
-  builder.EnterBlock(block_style.Get());
+  builder.EnterBlock(block_style.get());
   builder.ExitBlock();
 
   EXPECT_EQ("", builder.ToString());
@@ -378,8 +378,8 @@
   RefPtr<ComputedStyle> block_style(ComputedStyle::Create());
   block_style->SetUnicodeBidi(UnicodeBidi::kBidiOverride);
   block_style->SetDirection(TextDirection::kRtl);
-  builder.EnterBlock(block_style.Get());
-  builder.Append("Hello", style_.Get());
+  builder.EnterBlock(block_style.get());
+  builder.Append("Hello", style_.get());
   builder.ExitBlock();
 
   // Expected control characters as defined in:
@@ -394,7 +394,7 @@
 static std::unique_ptr<LayoutInline> CreateLayoutInline(
     void (*initialize_style)(ComputedStyle*)) {
   RefPtr<ComputedStyle> style(ComputedStyle::Create());
-  initialize_style(style.Get());
+  initialize_style(style.get());
   std::unique_ptr<LayoutInline> node = WTF::MakeUnique<LayoutInline>(nullptr);
   node->SetStyleInternal(std::move(style));
   return node;
@@ -403,16 +403,16 @@
 TEST_F(NGInlineItemsBuilderTest, BidiIsolate) {
   Vector<NGInlineItem> items;
   NGInlineItemsBuilderForOffsetMapping builder(&items);
-  builder.Append("Hello ", style_.Get());
+  builder.Append("Hello ", style_.get());
   std::unique_ptr<LayoutInline> isolate_rtl(
       CreateLayoutInline([](ComputedStyle* style) {
         style->SetUnicodeBidi(UnicodeBidi::kIsolate);
         style->SetDirection(TextDirection::kRtl);
       }));
   builder.EnterInline(isolate_rtl.get());
-  builder.Append(u"\u05E2\u05D1\u05E8\u05D9\u05EA", style_.Get());
+  builder.Append(u"\u05E2\u05D1\u05E8\u05D9\u05EA", style_.get());
   builder.ExitInline(isolate_rtl.get());
-  builder.Append(" World", style_.Get());
+  builder.Append(" World", style_.get());
 
   // Expected control characters as defined in:
   // https://drafts.csswg.org/css-writing-modes-3/#bidi-control-codes-injection-table
@@ -428,16 +428,16 @@
 TEST_F(NGInlineItemsBuilderTest, BidiIsolateOverride) {
   Vector<NGInlineItem> items;
   NGInlineItemsBuilderForOffsetMapping builder(&items);
-  builder.Append("Hello ", style_.Get());
+  builder.Append("Hello ", style_.get());
   std::unique_ptr<LayoutInline> isolate_override_rtl(
       CreateLayoutInline([](ComputedStyle* style) {
         style->SetUnicodeBidi(UnicodeBidi::kIsolateOverride);
         style->SetDirection(TextDirection::kRtl);
       }));
   builder.EnterInline(isolate_override_rtl.get());
-  builder.Append(u"\u05E2\u05D1\u05E8\u05D9\u05EA", style_.Get());
+  builder.Append(u"\u05E2\u05D1\u05E8\u05D9\u05EA", style_.get());
   builder.ExitInline(isolate_override_rtl.get());
-  builder.Append(" World", style_.Get());
+  builder.Append(" World", style_.get());
 
   // Expected control characters as defined in:
   // https://drafts.csswg.org/css-writing-modes-3/#bidi-control-codes-injection-table
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc
index 47b4bdb..61da44f7 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc
@@ -170,7 +170,8 @@
     const NGInlineItem& item = *item_result.item;
     if (item.Type() == NGInlineItem::kText ||
         item.Type() == NGInlineItem::kControl) {
-      DCHECK(item.GetLayoutObject()->IsText());
+      DCHECK(item.GetLayoutObject()->IsText() ||
+             item.GetLayoutObject()->IsLayoutNGListItem());
       DCHECK(!box->text_metrics.IsEmpty());
       DCHECK(item.Style());
       text_builder.SetStyle(item.Style());
@@ -181,7 +182,7 @@
           box->ActivateTextMetrics();
         // Take all used fonts into account if 'line-height: normal'.
         if (box->include_used_fonts && item.Type() == NGInlineItem::kText) {
-          box->AccumulateUsedFonts(item_result.shape_result.Get(),
+          box->AccumulateUsedFonts(item_result.shape_result.get(),
                                    baseline_type_);
         }
         text_builder.SetEndEffect(item_result.text_end_effect);
@@ -311,10 +312,7 @@
       ConstraintSpace().WritingMode(),
       ToNGPhysicalBoxFragment(*item_result->layout_result->PhysicalFragment()));
   NGLineHeightMetrics metrics = fragment.BaselineMetrics(
-      {line_info.UseFirstLineStyle()
-           ? NGBaselineAlgorithmType::kAtomicInlineForFirstLine
-           : NGBaselineAlgorithmType::kAtomicInline,
-       baseline_type_});
+      {NGBaselineAlgorithmType::kAtomicInline, baseline_type_});
   box->metrics.Unite(metrics);
 
   LayoutUnit line_top = item_result->margins.block_start - metrics.ascent;
@@ -498,16 +496,17 @@
   for (const auto& request : requests) {
     switch (request.algorithm_type) {
       case NGBaselineAlgorithmType::kAtomicInline:
-      case NGBaselineAlgorithmType::kAtomicInlineForFirstLine:
+        // Propagate from the last line box.
         for (unsigned i = container_builder_.Children().size(); i--;) {
-          if (AddBaseline(request, container_builder_.Children()[i].Get(),
+          if (AddBaseline(request, container_builder_.Children()[i].get(),
                           container_builder_.Offsets()[i].block_offset))
             break;
         }
         break;
       case NGBaselineAlgorithmType::kFirstLine:
+        // Propagate from the first line box.
         for (unsigned i = 0; i < container_builder_.Children().size(); i++) {
-          if (AddBaseline(request, container_builder_.Children()[i].Get(),
+          if (AddBaseline(request, container_builder_.Children()[i].get(),
                           container_builder_.Offsets()[i].block_offset))
             break;
         }
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm_test.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm_test.cc
index 5e8a67ea..22849b1 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm_test.cc
@@ -48,26 +48,26 @@
   RefPtr<NGLayoutResult> layout_result =
       inline_node.Layout(*constraint_space, nullptr);
   auto* wrapper =
-      ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().Get());
+      ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().get());
 
   // Test that the anonymous wrapper has 2 line boxes, and both have unfinished
   // break tokens.
   EXPECT_EQ(2u, wrapper->Children().size());
-  auto* line1 = ToNGPhysicalLineBoxFragment(wrapper->Children()[0].Get());
+  auto* line1 = ToNGPhysicalLineBoxFragment(wrapper->Children()[0].get());
   EXPECT_FALSE(line1->BreakToken()->IsFinished());
-  auto* line2 = ToNGPhysicalLineBoxFragment(wrapper->Children()[1].Get());
+  auto* line2 = ToNGPhysicalLineBoxFragment(wrapper->Children()[1].get());
   EXPECT_FALSE(line2->BreakToken()->IsFinished());
 
   // Perform 2nd layout with the break token from the 2nd line.
   RefPtr<NGLayoutResult> layout_result2 =
       inline_node.Layout(*constraint_space, line2->BreakToken());
   auto* wrapper2 =
-      ToNGPhysicalBoxFragment(layout_result2->PhysicalFragment().Get());
+      ToNGPhysicalBoxFragment(layout_result2->PhysicalFragment().get());
 
   // Test that the anonymous wrapper has 1 line boxes, and has a finished break
   // token.
   EXPECT_EQ(1u, wrapper2->Children().size());
-  auto* line3 = ToNGPhysicalLineBoxFragment(wrapper2->Children()[0].Get());
+  auto* line3 = ToNGPhysicalLineBoxFragment(wrapper2->Children()[0].get());
   EXPECT_TRUE(line3->BreakToken()->IsFinished());
 
   // Test that the wrapper has the break token without children.
@@ -100,16 +100,16 @@
   RefPtr<NGLayoutResult> layout_result = block_node.Layout(*space);
 
   auto* block_box =
-      ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().Get());
+      ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().get());
   EXPECT_TRUE(layout_result->BfcOffset().has_value());
   EXPECT_EQ(0, layout_result->BfcOffset().value().line_offset);
   EXPECT_EQ(0, layout_result->BfcOffset().value().block_offset);
 
-  auto* wrapper = ToNGPhysicalBoxFragment(block_box->Children()[0].Get());
+  auto* wrapper = ToNGPhysicalBoxFragment(block_box->Children()[0].get());
   EXPECT_EQ(5, wrapper->Offset().left);
   EXPECT_EQ(10, wrapper->Offset().top);
 
-  auto* line = ToNGPhysicalLineBoxFragment(wrapper->Children()[0].Get());
+  auto* line = ToNGPhysicalLineBoxFragment(wrapper->Children()[0].get());
   EXPECT_EQ(0, line->Offset().left);
   EXPECT_EQ(0, line->Offset().top);
 }
@@ -136,11 +136,11 @@
       NGConstraintSpace::CreateFromLayoutObject(*block_flow);
   RefPtr<NGLayoutResult> layout_result = inline_node.Layout(*space);
   auto* wrapper =
-      ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().Get());
+      ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().get());
   EXPECT_EQ(1u, wrapper->Children().size());
-  auto* line = ToNGPhysicalLineBoxFragment(wrapper->Children()[0].Get());
+  auto* line = ToNGPhysicalLineBoxFragment(wrapper->Children()[0].get());
   EXPECT_EQ(LayoutUnit(96), line->Size().height);
-  auto* img = line->Children()[0].Get();
+  auto* img = line->Children()[0].get();
   EXPECT_EQ(LayoutUnit(0), img->Offset().top);
 }
 
@@ -181,16 +181,16 @@
   std::tie(html_fragment, space) = RunBlockLayoutAlgorithmForElement(
       GetDocument().getElementsByTagName("html")->item(0));
   auto* body_fragment =
-      ToNGPhysicalBoxFragment(html_fragment->Children()[0].Get());
+      ToNGPhysicalBoxFragment(html_fragment->Children()[0].get());
   auto* container_fragment =
-      ToNGPhysicalBoxFragment(body_fragment->Children()[0].Get());
+      ToNGPhysicalBoxFragment(body_fragment->Children()[0].get());
   auto* span_box_fragments_wrapper =
-      ToNGPhysicalBoxFragment(container_fragment->Children()[3].Get());
+      ToNGPhysicalBoxFragment(container_fragment->Children()[3].get());
   auto* line_box_fragments_wrapper =
-      ToNGPhysicalBoxFragment(span_box_fragments_wrapper->Children()[0].Get());
+      ToNGPhysicalBoxFragment(span_box_fragments_wrapper->Children()[0].get());
   Vector<NGPhysicalLineBoxFragment*> line_boxes;
   for (const auto& child : line_box_fragments_wrapper->Children()) {
-    line_boxes.push_back(ToNGPhysicalLineBoxFragment(child.Get()));
+    line_boxes.push_back(ToNGPhysicalLineBoxFragment(child.get()));
   }
 
   LayoutText* layout_text =
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc
index bf5b9dc3..18e2112 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc
@@ -72,7 +72,10 @@
       if (item.Type() == NGInlineItem::kText ||
           item.Type() == NGInlineItem::kControl) {
         LayoutObject* layout_object = item.GetLayoutObject();
-        DCHECK(layout_object->IsText());
+        if (!layout_object->IsText()) {
+          DCHECK(layout_object->IsLayoutNGListItem());
+          continue;
+        }
         unsigned text_offset =
             text_offsets[physical_fragment.ItemIndexDeprecated()];
         run = new BidiRun(physical_fragment.StartOffset() - text_offset,
@@ -551,7 +554,7 @@
   if (result->Status() == NGLayoutResult::kSuccess &&
       result->UnpositionedFloats().IsEmpty() &&
       !RuntimeEnabledFeatures::LayoutNGPaintFragmentsEnabled()) {
-    CopyFragmentDataToLayoutBox(constraint_space, result.Get());
+    CopyFragmentDataToLayoutBox(constraint_space, result.get());
   }
 
   return result;
@@ -649,11 +652,11 @@
   BidiRunList<BidiRun> bidi_runs;
   LineInfo line_info;
   NGPhysicalBoxFragment* box_fragment =
-      ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().Get());
+      ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().get());
   for (const auto& container_child : box_fragment->Children()) {
     // Skip any float children we might have, these are handled by the wrapping
     // parent NGBlockNode.
-    if (!container_child.Get()->IsLineBox())
+    if (!container_child.get()->IsLineBox())
       continue;
 
     const auto& physical_line_box =
@@ -664,6 +667,10 @@
     CreateBidiRuns(&bidi_runs, physical_line_box.Children(), constraint_space,
                    line_box.Offset(), items, text_offsets,
                    &positions_for_bidi_runs, &positions);
+    // TODO(kojii): When a line contains a list marker but nothing else, there
+    // are fragments but there is no BidiRun. How to handle this is TBD.
+    if (!bidi_runs.FirstRun())
+      continue;
     // TODO(kojii): bidi needs to find the logical last run.
     bidi_runs.SetLogicallyLastRun(bidi_runs.LastRun());
 
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 c8c4026d..35b48a2 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
@@ -106,12 +106,12 @@
         NGInlineLayoutAlgorithm(node, *constraint_space).Layout();
 
     const NGPhysicalBoxFragment* container =
-        ToNGPhysicalBoxFragment(result->PhysicalFragment().Get());
+        ToNGPhysicalBoxFragment(result->PhysicalFragment().get());
     EXPECT_EQ(container->Children().size(), 1u);
     const NGPhysicalLineBoxFragment* line =
-        ToNGPhysicalLineBoxFragment(container->Children()[0].Get());
+        ToNGPhysicalLineBoxFragment(container->Children()[0].get());
     for (const auto& child : line->Children()) {
-      fragments_out->push_back(ToNGPhysicalTextFragment(child.Get()));
+      fragments_out->push_back(ToNGPhysicalTextFragment(child.get()));
     }
   }
 
@@ -288,7 +288,7 @@
 
 TEST_F(NGInlineNodeTest, SegmentBidiIsolate) {
   NGInlineNodeForTest node = CreateInlineNode();
-  node = CreateBidiIsolateNode(node, style_.Get(), layout_object_);
+  node = CreateBidiIsolateNode(node, style_.get(), layout_object_);
   Vector<NGInlineItem>& items = node.Items();
   ASSERT_EQ(9u, items.size());
   TEST_ITEM_OFFSET_DIR(items[0], 0u, 6u, TextDirection::kLtr);
@@ -314,7 +314,7 @@
   style->SetLineHeight(Length(1, kFixed));
   style->GetFont().Update(nullptr);
   NGInlineNodeForTest node = CreateInlineNode();
-  node = CreateBidiIsolateNode(node, style.Get(), layout_object_);
+  node = CreateBidiIsolateNode(node, style.get(), layout_object_);
   node.ShapeText();
   Vector<RefPtr<const NGPhysicalTextFragment>> fragments;
   CreateLine(node, &fragments);
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_box_fragment_builder.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_box_fragment_builder.cc
index e825f131..540c6785 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_box_fragment_builder.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_box_fragment_builder.cc
@@ -83,7 +83,7 @@
           .ConvertToPhysical(writing_mode);
 
   for (size_t i = 0; i < children_.size(); ++i) {
-    NGPhysicalFragment* child = children_[i].Get();
+    NGPhysicalFragment* child = children_[i].get();
     child->SetOffset(offsets_[i].ConvertToPhysical(
         writing_mode, Direction(), physical_size, child->Size()));
   }
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc
index 4247951..74a5af0b 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc
@@ -392,7 +392,7 @@
     }
 
     if (result.is_hyphenated) {
-      AppendHyphen(*item.Style(), shape_result.Get());
+      AppendHyphen(*item.Style(), shape_result.get());
       item_result->inline_size = shape_result->SnappedWidth();
       // TODO(kojii): Implement when adding a hyphen caused overflow.
       item_result->text_end_effect = NGTextEndEffect::kHyphen;
@@ -482,10 +482,9 @@
   // Request to compute baseline during the layout, except when we know the box
   // would synthesize box-baseline.
   if (NGBaseline::ShouldPropagateBaselines(layout_box)) {
+    space_builder.SetUseFirstLineStyle(line_info.UseFirstLineStyle());
     space_builder.AddBaselineRequest(
-        {line_info.UseFirstLineStyle()
-             ? NGBaselineAlgorithmType::kAtomicInlineForFirstLine
-             : NGBaselineAlgorithmType::kAtomicInline,
+        {NGBaselineAlgorithmType::kAtomicInline,
          IsHorizontalWritingMode(constraint_space_.WritingMode())
              ? FontBaseline::kAlphabeticBaseline
              : FontBaseline::kIdeographicBaseline});
@@ -565,7 +564,7 @@
       /* break_token */ nullptr);
 
   LayoutUnit inline_size = ComputeInlineSizeForUnpositionedFloat(
-      constraint_space_, unpositioned_float.Get());
+      constraint_space_, unpositioned_float.get());
 
   // We can only determine if our float will fit if we have an available_width
   // I.e. we may not have come across any text yet, in order to be able to
@@ -589,7 +588,7 @@
 
     NGPositionedFloat positioned_float = PositionFloat(
         origin_block_offset, container_bfc_offset.block_offset,
-        unpositioned_float.Get(), constraint_space_,
+        unpositioned_float.get(), constraint_space_,
         container_builder_->Size().inline_size, line_.exclusion_space.get());
     container_builder_->AddChild(positioned_float.layout_result,
                                  positioned_float.logical_offset);
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_physical_text_fragment.h b/third_party/WebKit/Source/core/layout/ng/inline/ng_physical_text_fragment.h
index 2e1633d7..fdb5e1b 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_physical_text_fragment.h
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_physical_text_fragment.h
@@ -62,7 +62,7 @@
   unsigned Length() const { return end_offset_ - start_offset_; }
   StringView Text() const { return StringView(text_, start_offset_, Length()); }
 
-  const ShapeResult* TextShapeResult() const { return shape_result_.Get(); }
+  const ShapeResult* TextShapeResult() const { return shape_result_.get(); }
 
   // Deprecating ItemIndex in favor of storing and accessing each component;
   // e.g., text, style, ShapeResult, etc. Currently used for CreateBidiRuns and
diff --git a/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.cc b/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.cc
index 5fe9b2a..0f8908a 100644
--- a/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.cc
+++ b/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.cc
@@ -91,7 +91,7 @@
     descendant.node.UseOldOutOfFlowPositioning();
 
   NGPhysicalBoxFragment* fragment =
-      ToNGPhysicalBoxFragment(result->PhysicalFragment().Get());
+      ToNGPhysicalBoxFragment(result->PhysicalFragment().get());
 
   // This object has already been positioned in legacy layout by our containing
   // block. Copy the position and place the fragment.
@@ -137,7 +137,7 @@
 // cache evolves.
 const NGPhysicalFragment* LayoutNGBlockFlow::CurrentFragment() const {
   if (cached_result_)
-    return cached_result_->PhysicalFragment().Get();
+    return cached_result_->PhysicalFragment().get();
   return nullptr;
 }
 
diff --git a/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.h b/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.h
index 1ca5e39..5a211fb0 100644
--- a/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.h
+++ b/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.h
@@ -18,7 +18,7 @@
 class NGLayoutResult;
 
 // This overrides the default layout block algorithm to use Layout NG.
-class CORE_EXPORT LayoutNGBlockFlow final : public LayoutBlockFlow {
+class CORE_EXPORT LayoutNGBlockFlow : public LayoutBlockFlow {
  public:
   explicit LayoutNGBlockFlow(Element*);
   ~LayoutNGBlockFlow() override;
@@ -49,11 +49,11 @@
   const NGPaintFragment* PaintFragment() const { return paint_fragment_.get(); }
 
  protected:
+  bool IsOfType(LayoutObjectType) const override;
+
   void AddOverflowFromChildren() override;
 
  private:
-  bool IsOfType(LayoutObjectType) const override;
-
   const NGPhysicalFragment* CurrentFragment() const;
 
   void UpdateMargins(const NGConstraintSpace&);
diff --git a/third_party/WebKit/Source/core/layout/ng/layout_ng_list_item.cc b/third_party/WebKit/Source/core/layout/ng/layout_ng_list_item.cc
new file mode 100644
index 0000000..bb94be6
--- /dev/null
+++ b/third_party/WebKit/Source/core/layout/ng/layout_ng_list_item.cc
@@ -0,0 +1,176 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/layout/ng/layout_ng_list_item.h"
+
+#include "core/layout/ListMarkerText.h"
+#include "platform/wtf/text/StringBuilder.h"
+
+namespace blink {
+
+LayoutNGListItem::LayoutNGListItem(Element* element)
+    : LayoutNGBlockFlow(element) {
+  SetInline(false);
+}
+
+bool LayoutNGListItem::IsOfType(LayoutObjectType type) const {
+  return type == kLayoutObjectNGListItem || LayoutNGBlockFlow::IsOfType(type);
+}
+
+void LayoutNGListItem::WillBeDestroyed() {
+  if (marker_) {
+    marker_->Destroy();
+    marker_ = nullptr;
+  }
+
+  LayoutNGBlockFlow::WillBeDestroyed();
+}
+
+void LayoutNGListItem::InsertedIntoTree() {
+  LayoutNGBlockFlow::InsertedIntoTree();
+
+  ListItemOrdinal::ItemInsertedOrRemoved(this);
+}
+
+void LayoutNGListItem::WillBeRemovedFromTree() {
+  LayoutNGBlockFlow::WillBeRemovedFromTree();
+
+  ListItemOrdinal::ItemInsertedOrRemoved(this);
+}
+
+void LayoutNGListItem::StyleDidChange(StyleDifference diff,
+                                      const ComputedStyle* old_style) {
+  LayoutNGBlockFlow::StyleDidChange(diff, old_style);
+
+  UpdateMarker();
+}
+
+void LayoutNGListItem::OrdinalValueChanged() {
+  if (marker_)
+    UpdateMarkerText(ToLayoutText(marker_->FirstChild()));
+}
+
+void LayoutNGListItem::UpdateMarkerText(LayoutText* text) {
+  DCHECK(text);
+  StringBuilder marker_text_builder;
+  MarkerText(&marker_text_builder);
+  text->SetText(marker_text_builder.ToString().ReleaseImpl());
+}
+
+void LayoutNGListItem::UpdateMarker() {
+  const ComputedStyle& style = StyleRef();
+  if (style.ListStyleType() == EListStyleType::kNone) {
+    if (marker_) {
+      marker_->Destroy();
+      marker_ = nullptr;
+    }
+    return;
+  }
+
+  if (!marker_)
+    marker_ = LayoutBlockFlow::CreateAnonymous(&GetDocument());
+
+  RefPtr<ComputedStyle> marker_style =
+      ComputedStyle::CreateAnonymousStyleWithDisplay(style,
+                                                     EDisplay::kInlineBlock);
+  marker_->SetStyle(std::move(marker_style));
+
+  LayoutText* text = nullptr;
+  if (LayoutObject* child = marker_->FirstChild()) {
+    text = ToLayoutText(child);
+    text->SetStyle(marker_->MutableStyle());
+  } else {
+    text = LayoutText::CreateEmptyAnonymous(GetDocument());
+    text->SetStyle(marker_->MutableStyle());
+    marker_->AddChild(text);
+  }
+
+  UpdateMarkerText(text);
+
+  LayoutObject* first_child = FirstChild();
+  if (first_child != marker_) {
+    marker_->Remove();
+    AddChild(marker_, FirstChild());
+  }
+}
+
+int LayoutNGListItem::Value() const {
+  DCHECK(GetNode());
+  return ordinal_.Value(*GetNode());
+}
+
+void LayoutNGListItem::MarkerText(StringBuilder* text) const {
+  const ComputedStyle& style = StyleRef();
+  switch (style.ListStyleType()) {
+    case EListStyleType::kNone:
+      break;
+    case EListStyleType::kDisc:
+    case EListStyleType::kCircle:
+    case EListStyleType::kSquare:
+      // value is ignored for these types
+      text->Append(ListMarkerText::GetText(Style()->ListStyleType(), 0));
+      text->Append(' ');
+      break;
+    case EListStyleType::kArabicIndic:
+    case EListStyleType::kArmenian:
+    case EListStyleType::kBengali:
+    case EListStyleType::kCambodian:
+    case EListStyleType::kCjkIdeographic:
+    case EListStyleType::kCjkEarthlyBranch:
+    case EListStyleType::kCjkHeavenlyStem:
+    case EListStyleType::kDecimalLeadingZero:
+    case EListStyleType::kDecimal:
+    case EListStyleType::kDevanagari:
+    case EListStyleType::kEthiopicHalehame:
+    case EListStyleType::kEthiopicHalehameAm:
+    case EListStyleType::kEthiopicHalehameTiEr:
+    case EListStyleType::kEthiopicHalehameTiEt:
+    case EListStyleType::kGeorgian:
+    case EListStyleType::kGujarati:
+    case EListStyleType::kGurmukhi:
+    case EListStyleType::kHangul:
+    case EListStyleType::kHangulConsonant:
+    case EListStyleType::kHebrew:
+    case EListStyleType::kHiragana:
+    case EListStyleType::kHiraganaIroha:
+    case EListStyleType::kKannada:
+    case EListStyleType::kKatakana:
+    case EListStyleType::kKatakanaIroha:
+    case EListStyleType::kKhmer:
+    case EListStyleType::kKoreanHangulFormal:
+    case EListStyleType::kKoreanHanjaFormal:
+    case EListStyleType::kKoreanHanjaInformal:
+    case EListStyleType::kLao:
+    case EListStyleType::kLowerAlpha:
+    case EListStyleType::kLowerArmenian:
+    case EListStyleType::kLowerGreek:
+    case EListStyleType::kLowerLatin:
+    case EListStyleType::kLowerRoman:
+    case EListStyleType::kMalayalam:
+    case EListStyleType::kMongolian:
+    case EListStyleType::kMyanmar:
+    case EListStyleType::kOriya:
+    case EListStyleType::kPersian:
+    case EListStyleType::kSimpChineseFormal:
+    case EListStyleType::kSimpChineseInformal:
+    case EListStyleType::kTelugu:
+    case EListStyleType::kThai:
+    case EListStyleType::kTibetan:
+    case EListStyleType::kTradChineseFormal:
+    case EListStyleType::kTradChineseInformal:
+    case EListStyleType::kUpperAlpha:
+    case EListStyleType::kUpperArmenian:
+    case EListStyleType::kUpperLatin:
+    case EListStyleType::kUpperRoman:
+    case EListStyleType::kUrdu: {
+      int value = Value();
+      text->Append(ListMarkerText::GetText(Style()->ListStyleType(), value));
+      text->Append(ListMarkerText::Suffix(Style()->ListStyleType(), value));
+      text->Append(' ');
+      break;
+    }
+  }
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/layout_ng_list_item.h b/third_party/WebKit/Source/core/layout/ng/layout_ng_list_item.h
new file mode 100644
index 0000000..8aebad125
--- /dev/null
+++ b/third_party/WebKit/Source/core/layout/ng/layout_ng_list_item.h
@@ -0,0 +1,47 @@
+// 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 layout_ng_list_item_h
+#define layout_ng_list_item_h
+
+#include "core/CoreExport.h"
+#include "core/html/ListItemOrdinal.h"
+#include "core/layout/ng/layout_ng_block_flow.h"
+
+namespace blink {
+
+// A LayoutObject subclass for 'display: list-item' in LayoutNG.
+class CORE_EXPORT LayoutNGListItem final : public LayoutNGBlockFlow {
+ public:
+  explicit LayoutNGListItem(Element*);
+
+  ListItemOrdinal& Ordinal() { return ordinal_; }
+
+  int Value() const;
+
+  void OrdinalValueChanged();
+
+  const char* GetName() const override { return "LayoutNGListItem"; }
+
+ private:
+  bool IsOfType(LayoutObjectType) const override;
+
+  void WillBeDestroyed() override;
+  void InsertedIntoTree() override;
+  void WillBeRemovedFromTree() override;
+  void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
+
+  void MarkerText(StringBuilder*) const;
+  void UpdateMarkerText(LayoutText*);
+  void UpdateMarker();
+
+  ListItemOrdinal ordinal_;
+  LayoutBlockFlow* marker_ = nullptr;
+};
+
+DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutNGListItem, IsLayoutNGListItem());
+
+}  // namespace blink
+
+#endif  // layout_ng_list_item_h
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_base_layout_algorithm_test.cc b/third_party/WebKit/Source/core/layout/ng/ng_base_layout_algorithm_test.cc
index 5e461646..ce6d0ac 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_base_layout_algorithm_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_base_layout_algorithm_test.cc
@@ -37,7 +37,7 @@
 
   RefPtr<NGLayoutResult> result = NGBlockLayoutAlgorithm(node, *space).Layout();
   return std::make_pair(
-      ToNGPhysicalBoxFragment(result->PhysicalFragment().Get()),
+      ToNGPhysicalBoxFragment(result->PhysicalFragment().get()),
       std::move(space));
 }
 
@@ -52,7 +52,7 @@
     if (index_ >= parent_->Children().size())
       return nullptr;
   }
-  return ToNGPhysicalBoxFragment(parent_->Children()[index_++].Get());
+  return ToNGPhysicalBoxFragment(parent_->Children()[index_++].get());
 }
 
 RefPtr<NGConstraintSpace> ConstructBlockLayoutTestConstraintSpace(
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_child_iterator.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_child_iterator.cc
index 1de4bda5..6734379 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_child_iterator.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_child_iterator.cc
@@ -42,7 +42,7 @@
       // This child break token candidate doesn't match the current node, this
       // node must be unfinished.
       NGBreakToken* child_break_token_candidate =
-          child_break_tokens[child_token_idx_].Get();
+          child_break_tokens[child_token_idx_].get();
       if (child_break_token_candidate->InputNode() != child_)
         break;
 
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_child_iterator_test.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_child_iterator_test.cc
index 18334fb..ee8940f92 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_child_iterator_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_child_iterator_test.cc
@@ -69,7 +69,7 @@
       NGBlockBreakToken::Create(container, LayoutUnit(50), child_break_tokens);
 
   // The iterator should loop through two children.
-  NGBlockChildIterator iterator(node1, parent_token.Get());
+  NGBlockChildIterator iterator(node1, parent_token.get());
   ASSERT_EQ(NGBlockChildIterator::Entry(node2, nullptr), iterator.NextChild());
   ASSERT_EQ(NGBlockChildIterator::Entry(node3, nullptr), iterator.NextChild());
   ASSERT_EQ(NGBlockChildIterator::Entry(nullptr, nullptr),
@@ -82,7 +82,7 @@
   // The first break token is for the #child2. That means that everything
   // preceding it (i.e. #child1) has already been finished. The break token for
   // #child2 is marked as finished, so all we need to visit is #child3.
-  NGBlockChildIterator iterator2(node1, parent_token.Get());
+  NGBlockChildIterator iterator2(node1, parent_token.get());
   ASSERT_EQ(NGBlockChildIterator::Entry(node3, nullptr), iterator2.NextChild());
   ASSERT_EQ(NGBlockChildIterator::Entry(nullptr, nullptr),
             iterator2.NextChild());
@@ -110,8 +110,8 @@
       NGBlockBreakToken::Create(container, LayoutUnit(50), child_break_tokens);
 
   // The iterator should loop through three children, one with a break token.
-  NGBlockChildIterator iterator(node1, parent_token.Get());
-  ASSERT_EQ(NGBlockChildIterator::Entry(node1, child_token.Get()),
+  NGBlockChildIterator iterator(node1, parent_token.get());
+  ASSERT_EQ(NGBlockChildIterator::Entry(node1, child_token.get()),
             iterator.NextChild());
   ASSERT_EQ(NGBlockChildIterator::Entry(node2, nullptr), iterator.NextChild());
   ASSERT_EQ(NGBlockChildIterator::Entry(node3, nullptr), iterator.NextChild());
@@ -128,8 +128,8 @@
   // preceding it (i.e. #child1) has already been finished. The break token for
   // #child2 is not marked as finished, so we need to visit that child, and
   // #child3.
-  NGBlockChildIterator iterator2(node1, parent_token.Get());
-  ASSERT_EQ(NGBlockChildIterator::Entry(node2, child_token.Get()),
+  NGBlockChildIterator iterator2(node1, parent_token.get());
+  ASSERT_EQ(NGBlockChildIterator::Entry(node2, child_token.get()),
             iterator2.NextChild());
   ASSERT_EQ(NGBlockChildIterator::Entry(node3, nullptr), iterator2.NextChild());
   ASSERT_EQ(NGBlockChildIterator::Entry(nullptr, nullptr),
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
index 2abf2d8..9f35fb5 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
@@ -1209,16 +1209,15 @@
   for (const auto& request : requests) {
     switch (request.algorithm_type) {
       case NGBaselineAlgorithmType::kAtomicInline:
-      case NGBaselineAlgorithmType::kAtomicInlineForFirstLine:
         for (unsigned i = container_builder_.Children().size(); i--;) {
-          if (AddBaseline(request, container_builder_.Children()[i].Get(),
+          if (AddBaseline(request, container_builder_.Children()[i].get(),
                           container_builder_.Offsets()[i].block_offset))
             break;
         }
         break;
       case NGBaselineAlgorithmType::kFirstLine:
         for (unsigned i = 0; i < container_builder_.Children().size(); i++) {
-          if (AddBaseline(request, container_builder_.Children()[i].Get(),
+          if (AddBaseline(request, container_builder_.Children()[i].get(),
                           container_builder_.Offsets()[i].block_offset))
             break;
         }
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc
index 8296f43..0a8fbd19 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc
@@ -43,7 +43,7 @@
     RefPtr<NGLayoutResult> result =
         NGBlockLayoutAlgorithm(node, space).Layout();
 
-    return ToNGPhysicalBoxFragment(result->PhysicalFragment().Get());
+    return ToNGPhysicalBoxFragment(result->PhysicalFragment().get());
   }
 
   MinMaxSize RunComputeMinAndMax(NGBlockNode node) {
@@ -107,26 +107,26 @@
 
   // Test pointer-equal constraint space
   result = block_flow->CachedLayoutResult(*space, nullptr);
-  EXPECT_NE(result.Get(), nullptr);
+  EXPECT_NE(result.get(), nullptr);
 
   // Test identical, but not pointer-equal, constraint space
   space = ConstructBlockLayoutTestConstraintSpace(
       kHorizontalTopBottom, TextDirection::kLtr,
       NGLogicalSize(LayoutUnit(100), NGSizeIndefinite));
   result = block_flow->CachedLayoutResult(*space, nullptr);
-  EXPECT_NE(result.Get(), nullptr);
+  EXPECT_NE(result.get(), nullptr);
 
   // Test different constraint space
   space = ConstructBlockLayoutTestConstraintSpace(
       kHorizontalTopBottom, TextDirection::kLtr,
       NGLogicalSize(LayoutUnit(200), NGSizeIndefinite));
   result = block_flow->CachedLayoutResult(*space, nullptr);
-  EXPECT_EQ(result.Get(), nullptr);
+  EXPECT_EQ(result.get(), nullptr);
 
   // Test layout invalidation
   block_flow->SetNeedsLayout("");
   result = block_flow->CachedLayoutResult(*space, nullptr);
-  EXPECT_EQ(result.Get(), nullptr);
+  EXPECT_EQ(result.get(), nullptr);
 }
 
 // Verifies that two children are laid out with the correct size and position.
@@ -157,11 +157,11 @@
   EXPECT_EQ(NGPhysicalFragment::kFragmentBox, frag->Type());
   ASSERT_EQ(frag->Children().size(), 2UL);
 
-  const NGPhysicalFragment* first_child_fragment = frag->Children()[0].Get();
+  const NGPhysicalFragment* first_child_fragment = frag->Children()[0].get();
   EXPECT_EQ(kHeight1, first_child_fragment->Size().height);
   EXPECT_EQ(0, first_child_fragment->Offset().top);
 
-  const NGPhysicalFragment* second_child_fragment = frag->Children()[1].Get();
+  const NGPhysicalFragment* second_child_fragment = frag->Children()[1].get();
   EXPECT_EQ(kHeight2, second_child_fragment->Size().height);
   EXPECT_EQ(kHeight1 + kMarginTop, second_child_fragment->Offset().top);
 }
@@ -195,9 +195,9 @@
   RefPtr<NGPhysicalBoxFragment> frag =
       RunBlockLayoutAlgorithm(*space, container);
 
-  const NGPhysicalFragment* child = frag->Children()[0].Get();
+  const NGPhysicalFragment* child = frag->Children()[0].get();
   // DIV2
-  child = static_cast<const NGPhysicalBoxFragment*>(child)->Children()[0].Get();
+  child = static_cast<const NGPhysicalBoxFragment*>(child)->Children()[0].get();
 
   EXPECT_EQ(kHeight, child->Size().height);
   EXPECT_EQ(0, child->Offset().top);
@@ -249,7 +249,7 @@
   std::tie(fragment, space) = RunBlockLayoutAlgorithmForElement(
       GetDocument().getElementsByTagName("html")->item(0));
   ASSERT_EQ(fragment->Children().size(), 1UL);
-  auto* body_fragment = ToNGPhysicalBoxFragment(fragment->Children()[0].Get());
+  auto* body_fragment = ToNGPhysicalBoxFragment(fragment->Children()[0].get());
   // 20 = max(first child's margin top, containers's margin top)
   int body_top_offset = 20;
   EXPECT_THAT(LayoutUnit(body_top_offset), body_fragment->Offset().top);
@@ -258,12 +258,12 @@
   EXPECT_THAT(LayoutUnit(body_left_offset), body_fragment->Offset().left);
   ASSERT_EQ(1UL, body_fragment->Children().size());
   auto* container_fragment =
-      ToNGPhysicalBoxFragment(body_fragment->Children()[0].Get());
+      ToNGPhysicalBoxFragment(body_fragment->Children()[0].get());
   // 0 = collapsed with body's margin
   EXPECT_THAT(LayoutUnit(0), container_fragment->Offset().top);
   ASSERT_EQ(3UL, container_fragment->Children().size());
   auto* first_child_fragment =
-      ToNGPhysicalBoxFragment(container_fragment->Children()[2].Get());
+      ToNGPhysicalBoxFragment(container_fragment->Children()[2].get());
   // 0 = collapsed with container's margin
   EXPECT_THAT(LayoutUnit(0), first_child_fragment->Offset().top);
 }
@@ -325,7 +325,7 @@
   std::tie(fragment, space) = RunBlockLayoutAlgorithmForElement(
       GetDocument().getElementsByTagName("html")->item(0));
 
-  auto* body_fragment = ToNGPhysicalBoxFragment(fragment->Children()[0].Get());
+  auto* body_fragment = ToNGPhysicalBoxFragment(fragment->Children()[0].get());
   // -7 = empty1's margin(-15) + body's margin(8)
   EXPECT_THAT(LayoutUnit(-7), body_fragment->Offset().top);
   ASSERT_EQ(4UL, body_fragment->Children().size());
@@ -384,12 +384,12 @@
     std::tie(fragment, std::ignore) = RunBlockLayoutAlgorithmForElement(
         GetDocument().getElementsByTagName("html")->item(0));
     ASSERT_EQ(1UL, fragment->Children().size());
-    body_fragment = ToNGPhysicalBoxFragment(fragment->Children()[0].Get());
+    body_fragment = ToNGPhysicalBoxFragment(fragment->Children()[0].get());
     container_fragment =
-        ToNGPhysicalBoxFragment(body_fragment->Children()[0].Get());
+        ToNGPhysicalBoxFragment(body_fragment->Children()[0].get());
     ASSERT_EQ(1UL, container_fragment->Children().size());
     child_fragment =
-        ToNGPhysicalBoxFragment(container_fragment->Children()[0].Get());
+        ToNGPhysicalBoxFragment(container_fragment->Children()[0].get());
   };
 
   // height == auto
@@ -436,12 +436,12 @@
     std::tie(fragment, std::ignore) = RunBlockLayoutAlgorithmForElement(
         GetDocument().getElementsByTagName("html")->item(0));
     ASSERT_EQ(1UL, fragment->Children().size());
-    body_fragment = ToNGPhysicalBoxFragment(fragment->Children()[0].Get());
+    body_fragment = ToNGPhysicalBoxFragment(fragment->Children()[0].get());
     container_fragment =
-        ToNGPhysicalBoxFragment(body_fragment->Children()[0].Get());
+        ToNGPhysicalBoxFragment(body_fragment->Children()[0].get());
     ASSERT_EQ(1UL, container_fragment->Children().size());
     child_fragment =
-        ToNGPhysicalBoxFragment(container_fragment->Children()[0].Get());
+        ToNGPhysicalBoxFragment(container_fragment->Children()[0].get());
   };
 
   // with padding
@@ -498,7 +498,7 @@
       GetDocument().getElementsByTagName("html")->item(0));
 
   // body
-  auto* body_fragment = ToNGPhysicalBoxFragment(fragment->Children()[0].Get());
+  auto* body_fragment = ToNGPhysicalBoxFragment(fragment->Children()[0].get());
   // 10 = std::max(body's margin 8, container's margin top)
   int body_top_offset = 10;
   EXPECT_THAT(body_fragment->Offset().top, LayoutUnit(body_top_offset));
@@ -515,7 +515,7 @@
 
   // container
   auto* container_fragment =
-      ToNGPhysicalBoxFragment(body_fragment->Children()[0].Get());
+      ToNGPhysicalBoxFragment(body_fragment->Children()[0].get());
   // Container's margins are collapsed with body's fragment.
   EXPECT_THAT(container_fragment->Offset().top, LayoutUnit());
   EXPECT_THAT(container_fragment->Offset().left, LayoutUnit());
@@ -523,13 +523,13 @@
 
   // vertical
   auto* vertical_fragment =
-      ToNGPhysicalBoxFragment(container_fragment->Children()[0].Get());
+      ToNGPhysicalBoxFragment(container_fragment->Children()[0].get());
   EXPECT_THAT(vertical_fragment->Offset().top, LayoutUnit());
   EXPECT_THAT(vertical_fragment->Offset().left, LayoutUnit());
 
   // horizontal
   auto* horizontal_fragment =
-      ToNGPhysicalBoxFragment(container_fragment->Children()[1].Get());
+      ToNGPhysicalBoxFragment(container_fragment->Children()[1].get());
   EXPECT_THAT(horizontal_fragment->Offset().top, LayoutUnit());
   // 130 = vertical's width 30 +
   //       std::max(vertical's margin right 90, horizontal's margin-left 100)
@@ -555,13 +555,13 @@
       GetDocument().getElementsByTagName("html")->item(0));
 
   auto* body_fragment =
-      ToNGPhysicalBoxFragment(html_fragment->Children()[0].Get());
+      ToNGPhysicalBoxFragment(html_fragment->Children()[0].get());
   // 20 = std::max(body's margin, p's margin)
   EXPECT_THAT(body_fragment->Offset(),
               NGPhysicalOffset(LayoutUnit(10), LayoutUnit(20)));
 
   auto* p_fragment =
-      ToNGPhysicalBoxFragment(body_fragment->Children()[0].Get());
+      ToNGPhysicalBoxFragment(body_fragment->Children()[0].get());
   // Collapsed margins with result = 0.
   EXPECT_THAT(p_fragment->Offset(),
               NGPhysicalOffset(LayoutUnit(20), LayoutUnit(0)));
@@ -601,11 +601,11 @@
 
   ASSERT_EQ(frag->Children().size(), 2UL);
 
-  const NGPhysicalFragment* child1 = frag->Children()[0].Get();
+  const NGPhysicalFragment* child1 = frag->Children()[0].get();
   EXPECT_EQ(0, child1->Offset().top);
   EXPECT_EQ(kHeight, child1->Size().height);
 
-  const NGPhysicalFragment* child2 = frag->Children()[1].Get();
+  const NGPhysicalFragment* child2 = frag->Children()[1].get();
   EXPECT_EQ(kHeight + std::max(kMarginBottom, kMarginTop),
             child2->Offset().top);
 }
@@ -647,7 +647,7 @@
   std::tie(fragment, std::ignore) = RunBlockLayoutAlgorithmForElement(
       GetDocument().getElementsByTagName("html")->item(0));
 
-  FragmentChildIterator iterator(fragment.Get());
+  FragmentChildIterator iterator(fragment.get());
 
   // body
   const NGPhysicalBoxFragment* child = iterator.NextChild();
@@ -735,7 +735,7 @@
 
     std::tie(fragment, std::ignore) = RunBlockLayoutAlgorithmForElement(
         GetDocument().getElementsByTagName("html")->item(0));
-    FragmentChildIterator iterator(fragment.Get());
+    FragmentChildIterator iterator(fragment.get());
 
     // body
     const NGPhysicalBoxFragment* child = iterator.NextChild();
@@ -858,7 +858,7 @@
     offset:125,20 size:50x20
     offset:150,40 size:50x20
 )DUMP";
-  EXPECT_EQ(expectation, DumpFragmentTree(fragment.Get()));
+  EXPECT_EQ(expectation, DumpFragmentTree(fragment.get()));
 }
 
 // Verifies that a box's size includes its borders and padding, and that
@@ -903,7 +903,7 @@
   ASSERT_EQ(frag->Children().size(), 1UL);
 
   // div1
-  const NGPhysicalFragment* child = frag->Children()[0].Get();
+  const NGPhysicalFragment* child = frag->Children()[0].get();
   EXPECT_EQ(kBorderLeft + kPaddingLeft + kWidth + kPaddingRight + kBorderRight,
             child->Size().width);
   EXPECT_EQ(kBorderTop + kPaddingTop + kHeight + kPaddingBottom + kBorderBottom,
@@ -914,7 +914,7 @@
             1UL);
 
   // div2
-  child = static_cast<const NGPhysicalBoxFragment*>(child)->Children()[0].Get();
+  child = static_cast<const NGPhysicalBoxFragment*>(child)->Children()[0].get();
   EXPECT_EQ(kBorderTop + kPaddingTop, child->Offset().top);
   EXPECT_EQ(kBorderLeft + kPaddingLeft, child->Offset().left);
 }
@@ -940,7 +940,7 @@
   EXPECT_EQ(NGPhysicalFragment::kFragmentBox, frag->Type());
   ASSERT_EQ(frag->Children().size(), 1UL);
 
-  const NGPhysicalFragment* child = frag->Children()[0].Get();
+  const NGPhysicalFragment* child = frag->Children()[0].get();
   EXPECT_EQ(LayoutUnit(12), child->Size().width);
 }
 
@@ -973,7 +973,7 @@
   EXPECT_EQ(LayoutUnit(kWidth + kPaddingLeft), frag->OverflowSize().width);
   ASSERT_EQ(1UL, frag->Children().size());
 
-  const NGPhysicalFragment* child = frag->Children()[0].Get();
+  const NGPhysicalFragment* child = frag->Children()[0].get();
   EXPECT_EQ(LayoutUnit(kChildWidth), child->Size().width);
   EXPECT_EQ(LayoutUnit(kPaddingLeft + 10), child->Offset().left);
   EXPECT_EQ(LayoutUnit(0), child->Offset().top);
@@ -1030,7 +1030,7 @@
       GetDocument().getElementsByTagName("html")->item(0));
 
   const auto* body_fragment =
-      ToNGPhysicalBoxFragment(fragment->Children()[0].Get());
+      ToNGPhysicalBoxFragment(fragment->Children()[0].get());
   FragmentChildIterator iterator(body_fragment);
   // 20 = std::max(empty1's margin, empty2's margin, body's margin)
   int body_top_offset = 20;
@@ -1161,7 +1161,7 @@
   // ** Verify LayoutNG fragments and the list of positioned floats **
   ASSERT_EQ(1UL, fragment->Children().size());
   const auto* body_fragment =
-      ToNGPhysicalBoxFragment(fragment->Children()[0].Get());
+      ToNGPhysicalBoxFragment(fragment->Children()[0].get());
   EXPECT_THAT(LayoutUnit(8), body_fragment->Offset().top);
 
   FragmentChildIterator iterator(body_fragment);
@@ -1284,16 +1284,16 @@
     std::tie(fragment, std::ignore) = RunBlockLayoutAlgorithmForElement(
         GetDocument().getElementsByTagName("html")->item(0));
     ASSERT_EQ(1UL, fragment->Children().size());
-    body_fragment = ToNGPhysicalBoxFragment(fragment->Children()[0].Get());
+    body_fragment = ToNGPhysicalBoxFragment(fragment->Children()[0].get());
     container_fragment =
-        ToNGPhysicalBoxFragment(body_fragment->Children()[0].Get());
+        ToNGPhysicalBoxFragment(body_fragment->Children()[0].get());
     ASSERT_EQ(5UL, container_fragment->Children().size());
     clerance_fragment =
-        ToNGPhysicalBoxFragment(container_fragment->Children()[2].Get());
+        ToNGPhysicalBoxFragment(container_fragment->Children()[2].get());
     block_fragment =
-        ToNGPhysicalBoxFragment(container_fragment->Children()[3].Get());
+        ToNGPhysicalBoxFragment(container_fragment->Children()[3].get());
     adjoining_clearance_fragment =
-        ToNGPhysicalBoxFragment(container_fragment->Children()[4].Get());
+        ToNGPhysicalBoxFragment(container_fragment->Children()[4].get());
   };
 
   // clear: none
@@ -1432,17 +1432,17 @@
   std::tie(html_fragment, std::ignore) = RunBlockLayoutAlgorithmForElement(
       GetDocument().getElementsByTagName("html")->item(0));
   auto* body_fragment =
-      ToNGPhysicalBoxFragment(html_fragment->Children()[0].Get());
+      ToNGPhysicalBoxFragment(html_fragment->Children()[0].get());
   auto* container_fragment =
-      ToNGPhysicalBoxFragment(body_fragment->Children()[0].Get());
+      ToNGPhysicalBoxFragment(body_fragment->Children()[0].get());
   auto* empty_block1 =
-      ToNGPhysicalBoxFragment(container_fragment->Children()[1].Get());
+      ToNGPhysicalBoxFragment(container_fragment->Children()[1].get());
   // empty-block1's margin == 8
   EXPECT_THAT(empty_block1->Offset(),
               NGPhysicalOffset(LayoutUnit(8), LayoutUnit(8)));
 
   auto* empty_block2 =
-      ToNGPhysicalBoxFragment(container_fragment->Children()[2].Get());
+      ToNGPhysicalBoxFragment(container_fragment->Children()[2].get());
   // empty-block2's margin == 50
   EXPECT_THAT(empty_block2->Offset(),
               NGPhysicalOffset(LayoutUnit(0), LayoutUnit(50)));
@@ -1502,12 +1502,12 @@
   std::tie(html_fragment, std::ignore) = RunBlockLayoutAlgorithmForElement(
       GetDocument().getElementsByTagName("html")->item(0));
   auto* body_fragment =
-      ToNGPhysicalBoxFragment(html_fragment->Children()[0].Get());
+      ToNGPhysicalBoxFragment(html_fragment->Children()[0].get());
   ASSERT_EQ(4UL, body_fragment->Children().size());
 
   // Verify #container-clear block
   auto* container_clear_fragment =
-      ToNGPhysicalBoxFragment(body_fragment->Children()[3].Get());
+      ToNGPhysicalBoxFragment(body_fragment->Children()[3].get());
   // 60 = block1's height 30 + std::max(block1's margin 20, zero's margin 30)
   EXPECT_THAT(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(60)),
               container_clear_fragment->Offset());
@@ -1519,7 +1519,7 @@
   // Verify #clears-right block
   ASSERT_EQ(2UL, container_clear_fragment->Children().size());
   auto* clears_right_fragment =
-      ToNGPhysicalBoxFragment(container_clear_fragment->Children()[1].Get());
+      ToNGPhysicalBoxFragment(container_clear_fragment->Children()[1].get());
   // 20 = right-float's block end offset (130 + 80) -
   //      container_clear->offsetTop() 190
   EXPECT_THAT(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(20)),
@@ -1626,7 +1626,7 @@
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(200)), fragment->Size());
   ASSERT_FALSE(fragment->BreakToken()->IsFinished());
 
-  FragmentChildIterator iterator(ToNGPhysicalBoxFragment(fragment.Get()));
+  FragmentChildIterator iterator(ToNGPhysicalBoxFragment(fragment.get()));
   const NGPhysicalBoxFragment* child = iterator.NextChild();
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(180)), child->Size());
   EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(20)), child->Offset());
@@ -1640,7 +1640,7 @@
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(140)), fragment->Size());
   ASSERT_TRUE(fragment->BreakToken()->IsFinished());
 
-  iterator.SetParent(ToNGPhysicalBoxFragment(fragment.Get()));
+  iterator.SetParent(ToNGPhysicalBoxFragment(fragment.get()));
   child = iterator.NextChild();
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(20)), child->Size());
   EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(0)), child->Offset());
@@ -1693,7 +1693,7 @@
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(200)), fragment->Size());
   ASSERT_FALSE(fragment->BreakToken()->IsFinished());
 
-  FragmentChildIterator iterator(ToNGPhysicalBoxFragment(fragment.Get()));
+  FragmentChildIterator iterator(ToNGPhysicalBoxFragment(fragment.get()));
   const NGPhysicalBoxFragment* child = iterator.NextChild();
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(180)), child->Size());
   EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(20)), child->Offset());
@@ -1707,7 +1707,7 @@
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(140)), fragment->Size());
   ASSERT_TRUE(fragment->BreakToken()->IsFinished());
 
-  iterator.SetParent(ToNGPhysicalBoxFragment(fragment.Get()));
+  iterator.SetParent(ToNGPhysicalBoxFragment(fragment.get()));
   child = iterator.NextChild();
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(20)), child->Size());
   EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(0)), child->Offset());
@@ -1758,7 +1758,7 @@
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(70)), fragment->Size());
   ASSERT_FALSE(fragment->BreakToken()->IsFinished());
 
-  FragmentChildIterator iterator(ToNGPhysicalBoxFragment(fragment.Get()));
+  FragmentChildIterator iterator(ToNGPhysicalBoxFragment(fragment.get()));
   const NGPhysicalBoxFragment* child = iterator.NextChild();
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(180)), child->Size());
   EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(20)), child->Offset());
@@ -1772,7 +1772,7 @@
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(0)), fragment->Size());
   ASSERT_TRUE(fragment->BreakToken()->IsFinished());
 
-  iterator.SetParent(ToNGPhysicalBoxFragment(fragment.Get()));
+  iterator.SetParent(ToNGPhysicalBoxFragment(fragment.get()));
   child = iterator.NextChild();
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(20)), child->Size());
   EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(0)), child->Offset());
@@ -1824,7 +1824,7 @@
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(50)), fragment->Size());
   ASSERT_FALSE(fragment->BreakToken()->IsFinished());
 
-  FragmentChildIterator iterator(ToNGPhysicalBoxFragment(fragment.Get()));
+  FragmentChildIterator iterator(ToNGPhysicalBoxFragment(fragment.get()));
 
   // First fragment of float1.
   const auto* child = iterator.NextChild();
@@ -1847,7 +1847,7 @@
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(0)), fragment->Size());
   ASSERT_TRUE(fragment->BreakToken()->IsFinished());
 
-  iterator.SetParent(ToNGPhysicalBoxFragment(fragment.Get()));
+  iterator.SetParent(ToNGPhysicalBoxFragment(fragment.get()));
 
   // Second fragment of float1.
   child = iterator.NextChild();
@@ -1903,7 +1903,7 @@
   ASSERT_TRUE(fragment->BreakToken()->IsFinished());
 
   // float2 should only have one fragment.
-  FragmentChildIterator iterator(ToNGPhysicalBoxFragment(fragment.Get()));
+  FragmentChildIterator iterator(ToNGPhysicalBoxFragment(fragment.get()));
   const auto* child = iterator.NextChild();
   child = iterator.NextChild();
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(60), LayoutUnit(200)), child->Size());
@@ -1947,7 +1947,7 @@
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(50)), fragment->Size());
   ASSERT_FALSE(fragment->BreakToken()->IsFinished());
 
-  FragmentChildIterator iterator(ToNGPhysicalBoxFragment(fragment.Get()));
+  FragmentChildIterator iterator(ToNGPhysicalBoxFragment(fragment.get()));
   const auto* child = iterator.NextChild();
 
   // First fragment of float.
@@ -1967,7 +1967,7 @@
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(0)), fragment->Size());
   ASSERT_TRUE(fragment->BreakToken()->IsFinished());
 
-  iterator.SetParent(ToNGPhysicalBoxFragment(fragment.Get()));
+  iterator.SetParent(ToNGPhysicalBoxFragment(fragment.get()));
   child = iterator.NextChild();
 
   // Second fragment of float.
@@ -2015,12 +2015,12 @@
     std::tie(fragment, std::ignore) = RunBlockLayoutAlgorithmForElement(
         GetDocument().getElementsByTagName("html")->item(0));
     ASSERT_EQ(1UL, fragment->Children().size());
-    body_fragment = ToNGPhysicalBoxFragment(fragment->Children()[0].Get());
+    body_fragment = ToNGPhysicalBoxFragment(fragment->Children()[0].get());
     container_fragment =
-        ToNGPhysicalBoxFragment(body_fragment->Children()[0].Get());
+        ToNGPhysicalBoxFragment(body_fragment->Children()[0].get());
     ASSERT_EQ(2UL, container_fragment->Children().size());
     new_fc_fragment =
-        ToNGPhysicalBoxFragment(container_fragment->Children()[1].Get());
+        ToNGPhysicalBoxFragment(container_fragment->Children()[1].get());
   };
 
   // #new-fc is small enough to fit on the same line with #float.
@@ -2072,7 +2072,7 @@
       NGBlockLayoutAlgorithm(node, *space).Layout()->PhysicalFragment();
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(200), LayoutUnit(150)), fragment->Size());
 
-  FragmentChildIterator iterator(ToNGPhysicalBoxFragment(fragment.Get()));
+  FragmentChildIterator iterator(ToNGPhysicalBoxFragment(fragment.get()));
 
   const NGPhysicalBoxFragment* child = iterator.NextChild();
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(100), LayoutUnit(30)), child->Size());
@@ -2106,7 +2106,7 @@
       NGBlockLayoutAlgorithm(node, *space).Layout()->PhysicalFragment();
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(200), LayoutUnit(10)), fragment->Size());
 
-  FragmentChildIterator iterator(ToNGPhysicalBoxFragment(fragment.Get()));
+  FragmentChildIterator iterator(ToNGPhysicalBoxFragment(fragment.get()));
 
   const NGPhysicalBoxFragment* child = iterator.NextChild();
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(50), LayoutUnit(50)), child->Size());
@@ -2142,7 +2142,7 @@
       NGBlockLayoutAlgorithm(node, *space).Layout()->PhysicalFragment();
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(200), LayoutUnit(10)), fragment->Size());
 
-  FragmentChildIterator iterator(ToNGPhysicalBoxFragment(fragment.Get()));
+  FragmentChildIterator iterator(ToNGPhysicalBoxFragment(fragment.get()));
 
   const NGPhysicalBoxFragment* child = iterator.NextChild();
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(50), LayoutUnit(0)), child->Size());
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
index 2b7eb5b..2faa93d 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
@@ -353,7 +353,7 @@
     // layout object as ourselves, we need to copy its floats across.
     if (child_object == box_) {
       for (const auto& maybe_float_fragment :
-           ToNGPhysicalBoxFragment(child_fragment.Get())->Children()) {
+           ToNGPhysicalBoxFragment(child_fragment.get())->Children()) {
         // The child of the anonymous fragment might be just a line-box
         // fragment - ignore.
         if (IsFloatFragment(*maybe_float_fragment)) {
@@ -366,7 +366,7 @@
       }
       continue;
     }
-    const auto& box_fragment = *ToNGPhysicalBoxFragment(child_fragment.Get());
+    const auto& box_fragment = *ToNGPhysicalBoxFragment(child_fragment.get());
     if (IsFirstFragment(constraint_space, box_fragment))
       CopyChildFragmentPosition(box_fragment, offset_from_start);
 
@@ -383,11 +383,11 @@
     // Each anonymous child of a multicol container constitutes one column.
     DCHECK(child->IsPlaced());
     DCHECK(child->GetLayoutObject() == box_);
-    const auto* column = ToNGPhysicalBoxFragment(child.Get());
+    const auto* column = ToNGPhysicalBoxFragment(child.get());
     for (const auto& actual_child : column->Children()) {
       // Position each child node in the first column that they occur,
       // relatively to the block-start of the flow thread.
-      const auto& box_fragment = *ToNGPhysicalBoxFragment(actual_child.Get());
+      const auto& box_fragment = *ToNGPhysicalBoxFragment(actual_child.get());
       if (!IsFirstFragment(constraint_space, box_fragment))
         continue;
       // TODO(mstensho): writing modes
@@ -515,10 +515,8 @@
   for (const auto& request : requests) {
     switch (request.algorithm_type) {
       case NGBaselineAlgorithmType::kAtomicInline:
-        AddAtomicInlineBaselineFromOldLayout(request, false, builder);
-        break;
-      case NGBaselineAlgorithmType::kAtomicInlineForFirstLine:
-        AddAtomicInlineBaselineFromOldLayout(request, true, builder);
+        AddAtomicInlineBaselineFromOldLayout(
+            request, constraint_space.UseFirstLineStyle(), builder);
         break;
       case NGBaselineAlgorithmType::kFirstLine: {
         LayoutUnit position = box_->FirstLineBoxBaseline();
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_column_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/ng_column_layout_algorithm.cc
index fff573e..0db10625 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_column_layout_algorithm.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_column_layout_algorithm.cc
@@ -48,11 +48,11 @@
 
   do {
     // Lay out one column. Each column will become a fragment.
-    NGBlockLayoutAlgorithm child_algorithm(Node(), *child_space.Get(),
-                                           break_token.Get());
+    NGBlockLayoutAlgorithm child_algorithm(Node(), *child_space.get(),
+                                           break_token.get());
     RefPtr<NGLayoutResult> result = child_algorithm.Layout();
     RefPtr<NGPhysicalBoxFragment> column(
-        ToNGPhysicalBoxFragment(result->PhysicalFragment().Get()));
+        ToNGPhysicalBoxFragment(result->PhysicalFragment().get()));
 
     NGLogicalOffset logical_offset(column_inline_offset, column_block_offset);
     container_builder_.AddChild(column, logical_offset);
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 dd4314a..e3f2ca3 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
@@ -26,7 +26,7 @@
     RefPtr<NGLayoutResult> result =
         NGBlockLayoutAlgorithm(node, space).Layout();
 
-    return ToNGPhysicalBoxFragment(result->PhysicalFragment().Get());
+    return ToNGPhysicalBoxFragment(result->PhysicalFragment().get());
   }
 
   RefPtr<NGPhysicalBoxFragment> RunBlockLayoutAlgorithm(Element* element) {
@@ -48,7 +48,7 @@
 
   String DumpFragmentTree(Element* element) {
     auto fragment = RunBlockLayoutAlgorithm(element);
-    return DumpFragmentTree(fragment.Get());
+    return DumpFragmentTree(fragment.get());
   }
 
   RefPtr<ComputedStyle> style_;
@@ -76,7 +76,7 @@
       NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite));
   RefPtr<const NGPhysicalBoxFragment> parent_fragment =
       RunBlockLayoutAlgorithm(*space, container);
-  FragmentChildIterator iterator(parent_fragment.Get());
+  FragmentChildIterator iterator(parent_fragment.get());
   const auto* fragment = iterator.NextChild();
   ASSERT_TRUE(fragment);
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(210), LayoutUnit(100)), fragment->Size());
@@ -117,7 +117,7 @@
       NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite));
   RefPtr<const NGPhysicalBoxFragment> parent_fragment =
       RunBlockLayoutAlgorithm(*space, container);
-  FragmentChildIterator iterator(parent_fragment.Get());
+  FragmentChildIterator iterator(parent_fragment.get());
   const auto* fragment = iterator.NextChild();
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(210), LayoutUnit(100)), fragment->Size());
   ASSERT_TRUE(fragment);
@@ -166,7 +166,7 @@
   RefPtr<const NGPhysicalBoxFragment> parent_fragment =
       RunBlockLayoutAlgorithm(*space, container);
 
-  FragmentChildIterator iterator(parent_fragment.Get());
+  FragmentChildIterator iterator(parent_fragment.get());
   const auto* fragment = iterator.NextChild();
   ASSERT_TRUE(fragment);
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(310), LayoutUnit(100)), fragment->Size());
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.cc b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.cc
index d093864..5b12c28 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.cc
@@ -27,6 +27,7 @@
     NGFragmentationType block_direction_fragmentation_type,
     bool is_new_fc,
     bool is_anonymous,
+    bool use_first_line_style,
     const NGMarginStrut& margin_strut,
     const NGBfcOffset& bfc_offset,
     const WTF::Optional<NGBfcOffset>& floats_bfc_offset,
@@ -51,6 +52,7 @@
       block_direction_fragmentation_type_(block_direction_fragmentation_type),
       is_new_fc_(is_new_fc),
       is_anonymous_(is_anonymous),
+      use_first_line_style_(use_first_line_style),
       writing_mode_(writing_mode),
       direction_(static_cast<unsigned>(direction)),
       margin_strut_(margin_strut),
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.h b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.h
index e409952..2987d6c 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.h
@@ -95,6 +95,13 @@
   // any borders or padding.
   bool IsAnonymous() const { return is_anonymous_; }
 
+  // Whether to use the ':first-line' style or not.
+  // Note, this is not about the first line of the content to layout, but
+  // whether the constraint space itself is on the first line, such as when it's
+  // an inline block.
+  // Also note this is true only when the document has ':first-line' rules.
+  bool UseFirstLineStyle() const { return use_first_line_style_; }
+
   // Whether exceeding the AvailableSize() triggers the presence of a scrollbar
   // for the indicated direction.
   // If exceeded the current layout should be aborted and invoked again with a
@@ -201,6 +208,7 @@
       NGFragmentationType block_direction_fragmentation_type,
       bool is_new_fc,
       bool is_anonymous,
+      bool use_first_line_style,
       const NGMarginStrut& margin_strut,
       const NGBfcOffset& bfc_offset,
       const WTF::Optional<NGBfcOffset>& floats_bfc_offset,
@@ -232,6 +240,7 @@
   unsigned is_new_fc_ : 1;
 
   unsigned is_anonymous_ : 1;
+  unsigned use_first_line_style_ : 1;
 
   unsigned writing_mode_ : 3;
   unsigned direction_ : 1;
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_builder.cc b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_builder.cc
index 7c6c977..300522c 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_builder.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_builder.cc
@@ -27,6 +27,7 @@
       fragmentation_type_(kFragmentNone),
       is_new_fc_(false),
       is_anonymous_(false),
+      use_first_line_sytle_(false),
       text_direction_(static_cast<unsigned>(TextDirection::kLtr)),
       exclusion_space_(nullptr) {}
 
@@ -130,6 +131,12 @@
   return *this;
 }
 
+NGConstraintSpaceBuilder& NGConstraintSpaceBuilder::SetUseFirstLineStyle(
+    bool use_first_line_sytle) {
+  use_first_line_sytle_ = use_first_line_sytle;
+  return *this;
+}
+
 NGConstraintSpaceBuilder& NGConstraintSpaceBuilder::SetUnpositionedFloats(
     Vector<RefPtr<NGUnpositionedFloat>>& unpositioned_floats) {
   unpositioned_floats_ = unpositioned_floats;
@@ -229,9 +236,9 @@
         is_inline_direction_triggers_scrollbar_,
         is_block_direction_triggers_scrollbar_,
         static_cast<NGFragmentationType>(fragmentation_type_), is_new_fc_,
-        is_anonymous_, margin_strut, bfc_offset, floats_bfc_offset,
-        exclusion_space, unpositioned_floats_, clearance_offset,
-        baseline_requests_));
+        is_anonymous_, use_first_line_sytle_, margin_strut, bfc_offset,
+        floats_bfc_offset, exclusion_space, unpositioned_floats_,
+        clearance_offset, baseline_requests_));
   }
   return WTF::AdoptRef(new NGConstraintSpace(
       out_writing_mode, static_cast<TextDirection>(text_direction_),
@@ -242,9 +249,9 @@
       is_block_direction_triggers_scrollbar_,
       is_inline_direction_triggers_scrollbar_,
       static_cast<NGFragmentationType>(fragmentation_type_), is_new_fc_,
-      is_anonymous_, margin_strut, bfc_offset, floats_bfc_offset,
-      exclusion_space, unpositioned_floats_, clearance_offset,
-      baseline_requests_));
+      is_anonymous_, use_first_line_sytle_, margin_strut, bfc_offset,
+      floats_bfc_offset, exclusion_space, unpositioned_floats_,
+      clearance_offset, baseline_requests_));
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_builder.h b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_builder.h
index b33f622..a1191956 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_builder.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_builder.h
@@ -55,6 +55,7 @@
   NGConstraintSpaceBuilder& SetFragmentationType(NGFragmentationType);
   NGConstraintSpaceBuilder& SetIsNewFormattingContext(bool is_new_fc);
   NGConstraintSpaceBuilder& SetIsAnonymous(bool is_anonymous);
+  NGConstraintSpaceBuilder& SetUseFirstLineStyle(bool use_first_line_sytle);
 
   NGConstraintSpaceBuilder& SetUnpositionedFloats(
       Vector<RefPtr<NGUnpositionedFloat>>& unpositioned_floats);
@@ -103,6 +104,7 @@
   unsigned fragmentation_type_ : 2;
   unsigned is_new_fc_ : 1;
   unsigned is_anonymous_ : 1;
+  unsigned use_first_line_sytle_ : 1;
   unsigned text_direction_ : 1;
 
   NGMarginStrut margin_strut_;
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_floats_utils.cc b/third_party/WebKit/Source/core/layout/ng/ng_floats_utils.cc
index dbbd53da..f051fed 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_floats_utils.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_floats_utils.cc
@@ -168,9 +168,9 @@
   // we fragment.
   if (is_same_writing_mode) {
     WTF::Optional<MinMaxSize> min_max_size;
-    if (NeedMinMaxSize(*space.Get(), style))
+    if (NeedMinMaxSize(*space.get(), style))
       min_max_size = unpositioned_float->node.ComputeMinMaxSize();
-    return ComputeInlineSizeForFragment(*space.Get(), style, min_max_size);
+    return ComputeInlineSizeForFragment(*space.get(), style, min_max_size);
   }
 
   // If we are performing layout on a float to determine its inline size it
@@ -234,7 +234,7 @@
     RefPtr<NGConstraintSpace> space = CreateConstraintSpaceForFloat(
         *unpositioned_float, parent_space, fragmentation_offset);
     layout_result = unpositioned_float->node.Layout(
-        *space, unpositioned_float->token.Get());
+        *space, unpositioned_float->token.get());
   }
 
   DCHECK(layout_result->PhysicalFragment());
@@ -289,7 +289,7 @@
 
   for (auto& unpositioned_float : unpositioned_floats) {
     positioned_floats.push_back(PositionFloat(
-        origin_block_offset, parent_bfc_block_offset, unpositioned_float.Get(),
+        origin_block_offset, parent_bfc_block_offset, unpositioned_float.get(),
         space, parent_inline_size, exclusion_space));
   }
 
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc
index ad9a990..a1b6853 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc
@@ -205,7 +205,7 @@
   NGPhysicalSize physical_size = size_.ConvertToPhysical(WritingMode());
 
   for (size_t i = 0; i < children_.size(); ++i) {
-    NGPhysicalFragment* child = children_[i].Get();
+    NGPhysicalFragment* child = children_[i].get();
     child->SetOffset(offsets_[i].ConvertToPhysical(
         WritingMode(), Direction(), physical_size, child->Size()));
   }
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc b/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc
index 4964c39..3e8d403e 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc
@@ -132,7 +132,7 @@
   if (AbsoluteNeedsChildBlockSize(descendant.Style())) {
     layout_result = GenerateFragment(descendant, block_estimate, node_position);
 
-    DCHECK(layout_result->PhysicalFragment().Get());
+    DCHECK(layout_result->PhysicalFragment().get());
     NGFragment fragment(descendant_writing_mode,
                         *layout_result->PhysicalFragment());
 
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part_test.cc b/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part_test.cc
index 0f64539b..1404f5ad 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part_test.cc
@@ -113,7 +113,7 @@
       node.Layout(*space)->PhysicalFragment();
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(200), LayoutUnit(400)), fragment->Size());
 
-  fragment = ToNGPhysicalBoxFragment(fragment.Get())->Children()[0];
+  fragment = ToNGPhysicalBoxFragment(fragment.get())->Children()[0];
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(0), LayoutUnit(30)), fragment->Size());
   EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(10)),
             fragment->Offset());
@@ -152,7 +152,7 @@
       node.Layout(*space)->PhysicalFragment();
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(200), LayoutUnit(400)), fragment->Size());
 
-  fragment = ToNGPhysicalBoxFragment(fragment.Get())->Children()[0];
+  fragment = ToNGPhysicalBoxFragment(fragment.get())->Children()[0];
   EXPECT_EQ(NGPhysicalSize(LayoutUnit(40), LayoutUnit(30)), fragment->Size());
   EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(10)),
             fragment->Offset());
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.cc b/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.cc
index c053dfb..4c11032 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.cc
@@ -72,7 +72,7 @@
     if (flags & NGPhysicalFragment::DumpSubtree) {
       const auto& children = box->Children();
       for (unsigned i = 0; i < children.size(); i++)
-        AppendFragmentToString(children[i].Get(), builder, flags, indent + 2);
+        AppendFragmentToString(children[i].get(), builder, flags, indent + 2);
     }
     return;
   }
@@ -90,7 +90,7 @@
       const auto* line_box = ToNGPhysicalLineBoxFragment(fragment);
       const auto& children = line_box->Children();
       for (unsigned i = 0; i < children.size(); i++)
-        AppendFragmentToString(children[i].Get(), builder, flags, indent + 2);
+        AppendFragmentToString(children[i].get(), builder, flags, indent + 2);
       return;
     }
   }
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.h b/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.h
index 735e3d5f..5bc04e5 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.h
@@ -75,7 +75,7 @@
     return offset_;
   }
 
-  NGBreakToken* BreakToken() const { return break_token_.Get(); }
+  NGBreakToken* BreakToken() const { return break_token_.get(); }
   const ComputedStyle& Style() const;
   Node* GetNode() const;
 
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_text_decoration_offset.cc b/third_party/WebKit/Source/core/layout/ng/ng_text_decoration_offset.cc
new file mode 100644
index 0000000..74bd244c
--- /dev/null
+++ b/third_party/WebKit/Source/core/layout/ng/ng_text_decoration_offset.cc
@@ -0,0 +1,52 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/layout/ng/ng_text_decoration_offset.h"
+
+#include "core/layout/line/RootInlineBox.h"
+#include "core/layout/ng/inline/ng_baseline.h"
+#include "core/layout/ng/inline/ng_physical_text_fragment.h"
+#include "core/layout/ng/ng_physical_box_fragment.h"
+#include "platform/fonts/FontMetrics.h"
+
+namespace blink {
+
+int NGTextDecorationOffset::ComputeUnderlineOffsetForUnder(
+    float text_decoration_thickness,
+    LineVerticalPositionType position_type) const {
+  LayoutUnit offset = LayoutUnit::Max();
+
+  if (decorating_box_) {
+    // TODO(eae): Replace with actual baseline once available.
+    NGBaselineRequest baseline_request = {
+        NGBaselineAlgorithmType::kAtomicInline,
+        FontBaseline::kIdeographicBaseline};
+
+    const NGBaseline* baseline = decorating_box_->Baseline(baseline_request);
+    if (baseline)
+      offset = baseline->offset;
+  }
+
+  if (offset == LayoutUnit::Max()) {
+    // TODO(layout-dev): How do we compute the baseline offset with a
+    // decorating_box?
+    offset = text_fragment_.Size().height;
+  }
+
+  // Compute offset to the farthest position of the decorating box.
+  // TODO(layout-dev): This is quite incorrect.
+  LayoutUnit logical_top = text_fragment_.Offset().top;
+  LayoutUnit position = logical_top + offset;
+  int offset_int = position.Floor();
+
+  // Gaps are not needed for TextTop because it generally has internal
+  // leadings.
+  if (position_type == LineVerticalPositionType::TextTop)
+    return offset_int;
+
+  // TODO(layout-dev): Add or subtract one depending on side (IsLineOverSide).
+  return offset_int + 1;
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_text_decoration_offset.h b/third_party/WebKit/Source/core/layout/ng/ng_text_decoration_offset.h
new file mode 100644
index 0000000..f9d8bec
--- /dev/null
+++ b/third_party/WebKit/Source/core/layout/ng/ng_text_decoration_offset.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 ng_text_decoration_offset_h
+#define ng_text_decoration_offset_h
+
+#include "core/CoreExport.h"
+#include "core/layout/TextDecorationOffsetBase.h"
+#include "core/layout/api/LineLayoutItem.h"
+
+namespace blink {
+
+class ComputedStyle;
+class NGPhysicalBoxFragment;
+class NGPhysicalTextFragment;
+
+// Class for computing the decoration offset for text fragments in LayoutNG.
+class CORE_EXPORT NGTextDecorationOffset : public TextDecorationOffsetBase {
+  STACK_ALLOCATED();
+
+ public:
+  NGTextDecorationOffset(const ComputedStyle& style,
+                         const NGPhysicalTextFragment& text_fragment,
+                         const NGPhysicalBoxFragment* decorating_box)
+      : TextDecorationOffsetBase(style),
+        text_fragment_(text_fragment),
+        decorating_box_(decorating_box) {}
+  ~NGTextDecorationOffset() {}
+
+  int ComputeUnderlineOffsetForUnder(float text_decoration_thickness,
+                                     LineVerticalPositionType) const override;
+
+ private:
+  const NGPhysicalTextFragment& text_fragment_;
+  const NGPhysicalBoxFragment* decorating_box_;
+};
+
+}  // namespace blink
+
+#endif  // ng_text_decoration_offset_h
diff --git a/third_party/WebKit/Source/core/layout/shapes/ShapeOutsideInfo.cpp b/third_party/WebKit/Source/core/layout/shapes/ShapeOutsideInfo.cpp
index 914cc9cd..ee7e3e7e 100644
--- a/third_party/WebKit/Source/core/layout/shapes/ShapeOutsideInfo.cpp
+++ b/third_party/WebKit/Source/core/layout/shapes/ShapeOutsideInfo.cpp
@@ -168,11 +168,11 @@
   }
 
   DCHECK(!style_image->IsPendingImage());
-  RefPtr<Image> image =
-      style_image->GetImage(layout_box_, layout_box_.GetDocument(),
-                            layout_box_.StyleRef(), FlooredIntSize(image_size));
+  RefPtr<Image> image = style_image->GetImage(
+      layout_box_, layout_box_.GetDocument(), layout_box_.StyleRef(),
+      FlooredIntSize(image_size), nullptr);
 
-  return Shape::CreateRasterShape(image.Get(), shape_image_threshold,
+  return Shape::CreateRasterShape(image.get(), shape_image_threshold,
                                   image_rect, margin_rect, writing_mode,
                                   margin);
 }
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGEllipse.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGEllipse.cpp
index 18b617b..d463ba9e 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGEllipse.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGEllipse.cpp
@@ -84,7 +84,7 @@
       length_context.ValueForLength(Style()->SvgStyle().Cy(), StyleRef(),
                                     SVGLengthMode::kHeight));
 
-  if (isSVGCircleElement(*GetElement())) {
+  if (IsSVGCircleElement(*GetElement())) {
     float radius = length_context.ValueForLength(
         Style()->SvgStyle().R(), StyleRef(), SVGLengthMode::kOther);
     radii_ = FloatSize(radius, radius);
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGInline.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGInline.cpp
index ec5354cc..ca1bba93 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGInline.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGInline.cpp
@@ -35,9 +35,9 @@
   if (child->IsText())
     return SVGLayoutSupport::IsLayoutableTextNode(child);
 
-  if (isSVGAElement(*GetNode())) {
+  if (IsSVGAElement(*GetNode())) {
     // Disallow direct descendant 'a'.
-    if (isSVGAElement(*child->GetNode()))
+    if (IsSVGAElement(*child->GetNode()))
       return false;
   }
 
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceClipper.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceClipper.cpp
index 07963fa..37610ce 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceClipper.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceClipper.cpp
@@ -68,7 +68,7 @@
 ClipStrategy DetermineClipStrategy(const SVGElement& element) {
   // <use> within <clipPath> have a restricted content model.
   // (https://drafts.fxtf.org/css-masking-1/#ClipPathElement)
-  if (isSVGUseElement(element)) {
+  if (IsSVGUseElement(element)) {
     const LayoutObject* use_layout_object = element.GetLayoutObject();
     if (!use_layout_object ||
         use_layout_object->StyleRef().Display() == EDisplay::kNone)
@@ -91,10 +91,10 @@
 }
 
 void PathFromElement(const SVGElement& element, Path& clip_path) {
-  if (IsSVGGeometryElement(element))
-    ToSVGGeometryElement(element).ToClipPath(clip_path);
-  else if (isSVGUseElement(element))
-    toSVGUseElement(element).ToClipPath(clip_path);
+  if (auto* geometry = ToSVGGeometryElementOrNull(element))
+    geometry->ToClipPath(clip_path);
+  else if (auto* use = ToSVGUseElementOrNull(element))
+    use->ToClipPath(clip_path);
 }
 
 }  // namespace
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilterPrimitive.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilterPrimitive.cpp
index b75c8a4..49c1e29 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilterPrimitive.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilterPrimitive.cpp
@@ -42,16 +42,16 @@
     return;
   const SVGComputedStyle& new_style = this->StyleRef().SvgStyle();
   DCHECK(GetElement());
-  if (isSVGFEFloodElement(*GetElement()) ||
-      isSVGFEDropShadowElement(*GetElement())) {
+  if (IsSVGFEFloodElement(*GetElement()) ||
+      IsSVGFEDropShadowElement(*GetElement())) {
     if (new_style.FloodColor() != old_style->SvgStyle().FloodColor())
       ToLayoutSVGResourceFilter(filter)->PrimitiveAttributeChanged(
           this, SVGNames::flood_colorAttr);
     if (new_style.FloodOpacity() != old_style->SvgStyle().FloodOpacity())
       ToLayoutSVGResourceFilter(filter)->PrimitiveAttributeChanged(
           this, SVGNames::flood_opacityAttr);
-  } else if (isSVGFEDiffuseLightingElement(*GetElement()) ||
-             isSVGFESpecularLightingElement(*GetElement())) {
+  } else if (IsSVGFEDiffuseLightingElement(*GetElement()) ||
+             IsSVGFESpecularLightingElement(*GetElement())) {
     if (new_style.LightingColor() != old_style->SvgStyle().LightingColor())
       ToLayoutSVGResourceFilter(filter)->PrimitiveAttributeChanged(
           this, SVGNames::lighting_colorAttr);
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGTextPath.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGTextPath.cpp
index 235480fb..c65315f 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGTextPath.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGTextPath.cpp
@@ -62,7 +62,7 @@
       text_path_element.HrefString(),
       text_path_element.TreeScopeForIdResolution());
 
-  if (!isSVGPathElement(target_element))
+  if (!IsSVGPathElement(target_element))
     return nullptr;
 
   SVGPathElement& path_element = toSVGPathElement(*target_element);
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGTransformableContainer.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGTransformableContainer.cpp
index bbcbc4e..e8141c1b 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGTransformableContainer.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGTransformableContainer.cpp
@@ -45,7 +45,7 @@
     LayoutObject* child,
     const ComputedStyle& style) const {
   DCHECK(GetElement());
-  if (isSVGSwitchElement(*GetElement())) {
+  if (IsSVGSwitchElement(*GetElement())) {
     Node* node = child->GetNode();
     // Reject non-SVG/non-valid elements.
     if (!node->IsSVGElement() || !ToSVGElement(node)->IsValid())
@@ -53,11 +53,11 @@
     // Reject this child if it isn't the first valid node.
     if (HasValidPredecessor(node))
       return false;
-  } else if (isSVGAElement(*GetElement())) {
+  } else if (IsSVGAElement(*GetElement())) {
     // http://www.w3.org/2003/01/REC-SVG11-20030114-errata#linking-text-environment
     // The 'a' element may contain any element that its parent may contain,
     // except itself.
-    if (isSVGAElement(*child->GetNode()))
+    if (IsSVGAElement(*child->GetNode()))
       return false;
     if (Parent() && Parent()->IsSVG())
       return Parent()->IsChildAllowed(child, style);
@@ -81,15 +81,10 @@
   // element inside the shadow tree, that was created during the use/symbol/svg
   // expansion in SVGUseElement. These containers need to respect the
   // translations induced by their corresponding use elements x/y attributes.
-  SVGUseElement* use_element = nullptr;
-  if (isSVGUseElement(*element)) {
-    use_element = toSVGUseElement(element);
-  } else if (isSVGGElement(*element) &&
-             toSVGGElement(element)->InUseShadowTree()) {
-    SVGElement* corresponding_element = element->CorrespondingElement();
-    if (isSVGUseElement(corresponding_element))
-      use_element = toSVGUseElement(corresponding_element);
-  }
+  SVGUseElement* use_element = ToSVGUseElementOrNull(*element);
+  if (!use_element && IsSVGGElement(*element) &&
+      toSVGGElement(element)->InUseShadowTree())
+    use_element = ToSVGUseElementOrNull(element->CorrespondingElement());
 
   if (use_element) {
     SVGLengthContext length_context(element);
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp b/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp
index 42f6b6d6..546d109 100644
--- a/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp
@@ -349,7 +349,7 @@
   const ComputedStyle& style = shape.StyleRef();
   const SVGComputedStyle& svg_style = style.SvgStyle();
 
-  if (isSVGRectElement(*svg_element)) {
+  if (IsSVGRectElement(*svg_element)) {
     WriteNameValuePair(ts, "x",
                        length_context.ValueForLength(svg_style.X(), style,
                                                      SVGLengthMode::kWidth));
@@ -362,7 +362,7 @@
     WriteNameValuePair(ts, "height",
                        length_context.ValueForLength(style.Height(), style,
                                                      SVGLengthMode::kHeight));
-  } else if (isSVGLineElement(*svg_element)) {
+  } else if (IsSVGLineElement(*svg_element)) {
     SVGLineElement& element = toSVGLineElement(*svg_element);
     WriteNameValuePair(ts, "x1",
                        element.x1()->CurrentValue()->Value(length_context));
@@ -372,7 +372,7 @@
                        element.x2()->CurrentValue()->Value(length_context));
     WriteNameValuePair(ts, "y2",
                        element.y2()->CurrentValue()->Value(length_context));
-  } else if (isSVGEllipseElement(*svg_element)) {
+  } else if (IsSVGEllipseElement(*svg_element)) {
     WriteNameValuePair(ts, "cx",
                        length_context.ValueForLength(svg_style.Cx(), style,
                                                      SVGLengthMode::kWidth));
@@ -385,7 +385,7 @@
     WriteNameValuePair(ts, "ry",
                        length_context.ValueForLength(svg_style.Ry(), style,
                                                      SVGLengthMode::kHeight));
-  } else if (isSVGCircleElement(*svg_element)) {
+  } else if (IsSVGCircleElement(*svg_element)) {
     WriteNameValuePair(ts, "cx",
                        length_context.ValueForLength(svg_style.Cx(), style,
                                                      SVGLengthMode::kWidth));
@@ -401,7 +401,7 @@
                                 .Points()
                                 ->CurrentValue()
                                 ->ValueAsString());
-  } else if (isSVGPathElement(*svg_element)) {
+  } else if (IsSVGPathElement(*svg_element)) {
     const StylePath& path =
         svg_style.D() ? *svg_style.D() : *StylePath::EmptyPath();
     WriteNameAndQuotedValue(ts, "data",
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGResources.cpp b/third_party/WebKit/Source/core/layout/svg/SVGResources.cpp
index d2f4c08..2465af2 100644
--- a/third_party/WebKit/Source/core/layout/svg/SVGResources.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/SVGResources.cpp
@@ -110,10 +110,10 @@
 
 static inline AtomicString TargetReferenceFromResource(SVGElement& element) {
   String target;
-  if (isSVGPatternElement(element))
-    target = toSVGPatternElement(element).href()->CurrentValue()->Value();
-  else if (IsSVGGradientElement(element))
-    target = ToSVGGradientElement(element).href()->CurrentValue()->Value();
+  if (auto* pattern = ToSVGPatternElementOrNull(element))
+    target = pattern->href()->CurrentValue()->Value();
+  else if (auto* gradient = ToSVGGradientElementOrNull(element))
+    target = gradient->href()->CurrentValue()->Value();
   else
     NOTREACHED();
 
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngine.cpp b/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngine.cpp
index 9d749a3e..a1439b86 100644
--- a/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngine.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngine.cpp
@@ -274,7 +274,7 @@
         continue;
 
       SVGInlineFlowBox* flow_box = ToSVGInlineFlowBox(child);
-      bool is_text_path = isSVGTextPathElement(*node);
+      bool is_text_path = IsSVGTextPathElement(*node);
       if (is_text_path)
         BeginTextPathLayout(flow_box);
 
diff --git a/third_party/WebKit/Source/core/leak_detector/BlinkLeakDetector.cpp b/third_party/WebKit/Source/core/leak_detector/BlinkLeakDetector.cpp
index e578f84..f161939 100644
--- a/third_party/WebKit/Source/core/leak_detector/BlinkLeakDetector.cpp
+++ b/third_party/WebKit/Source/core/leak_detector/BlinkLeakDetector.cpp
@@ -11,7 +11,7 @@
 #include "core/frame/LocalFrame.h"
 #include "core/frame/WebLocalFrameImpl.h"
 #include "core/leak_detector/BlinkLeakDetectorClient.h"
-#include "core/workers/InProcessWorkerMessagingProxy.h"
+#include "core/workers/DedicatedWorkerMessagingProxy.h"
 #include "core/workers/WorkerThread.h"
 #include "platform/Timer.h"
 #include "platform/bindings/V8PerIsolateData.h"
@@ -87,7 +87,7 @@
   if (--number_of_gc_needed_ > 0) {
     delayed_gc_timer_.StartOneShot(0, BLINK_FROM_HERE);
   } else if (number_of_gc_needed_ > -1 &&
-             InProcessWorkerMessagingProxy::ProxyCount()) {
+             DedicatedWorkerMessagingProxy::ProxyCount()) {
     // It is possible that all posted tasks for finalizing in-process proxy
     // objects will not have run before the final round of GCs started. If so,
     // do yet another pass, letting these tasks run and then afterwards perform
diff --git a/third_party/WebKit/Source/core/loader/BaseFetchContext.cpp b/third_party/WebKit/Source/core/loader/BaseFetchContext.cpp
index 009cb895..681a4f1 100644
--- a/third_party/WebKit/Source/core/loader/BaseFetchContext.cpp
+++ b/third_party/WebKit/Source/core/loader/BaseFetchContext.cpp
@@ -162,7 +162,7 @@
   if (ShouldBlockRequestByInspector(resource_request.Url()))
     return ResourceRequestBlockedReason::kInspector;
 
-  SecurityOrigin* security_origin = options.security_origin.Get();
+  SecurityOrigin* security_origin = options.security_origin.get();
   if (!security_origin)
     security_origin = GetSecurityOrigin();
 
diff --git a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp
index 2213200..46e8cda9 100644
--- a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp
@@ -743,7 +743,7 @@
     RefPtr<SecurityOrigin> original_origin =
         SecurityOrigin::Create(original_url);
     RefPtr<SecurityOrigin> new_origin = SecurityOrigin::Create(new_url);
-    if (!original_origin->IsSameSchemeHostPort(new_origin.Get()))
+    if (!original_origin->IsSameSchemeHostPort(new_origin.get()))
       security_origin_ = SecurityOrigin::CreateUnique();
   }
 
@@ -1326,7 +1326,7 @@
 
 SecurityOrigin* DocumentThreadableLoader::GetSecurityOrigin() const {
   return security_origin_
-             ? security_origin_.Get()
+             ? security_origin_.get()
              : loading_context_->GetFetchContext()->GetSecurityOrigin();
 }
 
diff --git a/third_party/WebKit/Source/core/loader/FormSubmission.cpp b/third_party/WebKit/Source/core/loader/FormSubmission.cpp
index 318fcf1..43c2802 100644
--- a/third_party/WebKit/Source/core/loader/FormSubmission.cpp
+++ b/third_party/WebKit/Source/core/loader/FormSubmission.cpp
@@ -234,9 +234,9 @@
     HTMLElement& element = ToHTMLElement(*control);
     if (!element.IsDisabledFormControl())
       control->AppendToFormData(*dom_form_data);
-    if (isHTMLInputElement(element)) {
-      HTMLInputElement& input = toHTMLInputElement(element);
-      if (input.type() == InputTypeNames::password && !input.value().IsEmpty())
+    if (auto* input = ToHTMLInputElementOrNull(element)) {
+      if (input->type() == InputTypeNames::password &&
+          !input->value().IsEmpty())
         contains_password_data = true;
     }
   }
diff --git a/third_party/WebKit/Source/core/loader/FormSubmission.h b/third_party/WebKit/Source/core/loader/FormSubmission.h
index 83524521..0916f0a 100644
--- a/third_party/WebKit/Source/core/loader/FormSubmission.h
+++ b/third_party/WebKit/Source/core/loader/FormSubmission.h
@@ -105,7 +105,7 @@
   const AtomicString& Target() const { return target_; }
   void ClearTarget() { target_ = g_null_atom; }
   HTMLFormElement* Form() const { return form_.Get(); }
-  EncodedFormData* Data() const { return form_data_.Get(); }
+  EncodedFormData* Data() const { return form_data_.get(); }
 
   const String& Result() const { return result_; }
 
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
index d7a8d4e2..e8f2d64 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
@@ -766,7 +766,7 @@
 
 SecurityOrigin* FrameFetchContext::GetSecurityOrigin() const {
   if (IsDetached())
-    return frozen_state_->security_origin.Get();
+    return frozen_state_->security_origin.get();
   return document_ ? document_->GetSecurityOrigin() : nullptr;
 }
 
@@ -1018,7 +1018,7 @@
 
 const SecurityOrigin* FrameFetchContext::GetParentSecurityOrigin() const {
   if (IsDetached())
-    return frozen_state_->parent_security_origin.Get();
+    return frozen_state_->parent_security_origin.get();
   Frame* parent = GetFrame()->Tree().Parent();
   if (!parent)
     return nullptr;
@@ -1161,7 +1161,7 @@
       return loader;
   }
 
-  return GetFrame()->CreateURLLoader(request, task_runner.Get());
+  return GetFrame()->CreateURLLoader(request, task_runner.get());
 }
 
 FetchContext* FrameFetchContext::Detach() {
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp
index 8351094..9d4573e 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp
@@ -1190,7 +1190,7 @@
 
   dummy_page_holder = nullptr;
 
-  fetch_context->UpdateTimingInfoForIFrameNavigation(info.Get());
+  fetch_context->UpdateTimingInfoForIFrameNavigation(info.get());
   // Should not crash.
 }
 
@@ -1216,7 +1216,7 @@
   document->SetSecurityOrigin(origin);
 
   dummy_page_holder = nullptr;
-  EXPECT_EQ(origin.Get(), fetch_context->GetSecurityOrigin());
+  EXPECT_EQ(origin.get(), fetch_context->GetSecurityOrigin());
 }
 
 TEST_F(FrameFetchContextTest, PopulateResourceRequestWhenDetached) {
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
index fea12264..4cb0137 100644
--- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
@@ -1542,7 +1542,7 @@
   if (!url.IsAboutSrcdocURL())
     return false;
   HTMLFrameOwnerElement* owner_element = frame_->DeprecatedLocalOwner();
-  if (!isHTMLIFrameElement(owner_element))
+  if (!IsHTMLIFrameElement(owner_element))
     return false;
   return owner_element->FastHasAttribute(srcdocAttr);
 }
diff --git a/third_party/WebKit/Source/core/loader/HistoryItem.cpp b/third_party/WebKit/Source/core/loader/HistoryItem.cpp
index 5a4e1b7..c73cdef 100644
--- a/third_party/WebKit/Source/core/loader/HistoryItem.cpp
+++ b/third_party/WebKit/Source/core/loader/HistoryItem.cpp
@@ -147,7 +147,7 @@
 }
 
 EncodedFormData* HistoryItem::FormData() {
-  return form_data_.Get();
+  return form_data_.get();
 }
 
 ResourceRequest HistoryItem::GenerateResourceRequest(
diff --git a/third_party/WebKit/Source/core/loader/HistoryItem.h b/third_party/WebKit/Source/core/loader/HistoryItem.h
index 7c0a3dba..a147801 100644
--- a/third_party/WebKit/Source/core/loader/HistoryItem.h
+++ b/third_party/WebKit/Source/core/loader/HistoryItem.h
@@ -93,7 +93,7 @@
   void SetReferrer(const Referrer&);
 
   void SetStateObject(RefPtr<SerializedScriptValue>);
-  SerializedScriptValue* StateObject() const { return state_object_.Get(); }
+  SerializedScriptValue* StateObject() const { return state_object_.get(); }
 
   void SetItemSequenceNumber(long long number) {
     item_sequence_number_ = number;
diff --git a/third_party/WebKit/Source/core/loader/ImageLoader.cpp b/third_party/WebKit/Source/core/loader/ImageLoader.cpp
index f5707fcc..8581517e 100644
--- a/third_party/WebKit/Source/core/loader/ImageLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/ImageLoader.cpp
@@ -115,7 +115,7 @@
     ExecutionContext& context = loader_->GetElement()->GetDocument();
     probe::AsyncTask async_task(&context, this);
     if (script_state_->ContextIsValid()) {
-      ScriptState::Scope scope(script_state_.Get());
+      ScriptState::Scope scope(script_state_.get());
       loader_->DoUpdateFromElement(should_bypass_main_world_csp_,
                                    update_behavior_, request_url_,
                                    referrer_policy_);
@@ -304,7 +304,7 @@
 
   if (client_hints_preferences.ShouldSend(
           mojom::WebClientHintsType::kResourceWidth) &&
-      isHTMLImageElement(element))
+      IsHTMLImageElement(element))
     params.SetResourceWidth(toHTMLImageElement(element).GetResourceWidth());
 }
 
@@ -392,7 +392,7 @@
           referrer_policy, url, document.OutgoingReferrer()));
     }
 
-    if (isHTMLPictureElement(GetElement()->parentNode()) ||
+    if (IsHTMLPictureElement(GetElement()->parentNode()) ||
         !GetElement()->FastGetAttribute(HTMLNames::srcsetAttr).IsNull())
       resource_request.SetRequestContext(
           WebURLRequest::kRequestContextImageSet);
@@ -553,7 +553,7 @@
     if (resource && !resource->ErrorOccurred())
       return true;
   }
-  return (isHTMLObjectElement(element_) || isHTMLEmbedElement(element_));
+  return (IsHTMLObjectElement(element_) || IsHTMLEmbedElement(element_));
 }
 
 void ImageLoader::ImageChanged(ImageResourceContent* content, const IntRect*) {
diff --git a/third_party/WebKit/Source/core/loader/MixedContentCheckerTest.cpp b/third_party/WebKit/Source/core/loader/MixedContentCheckerTest.cpp
index c5e463b0..c9fe008 100644
--- a/third_party/WebKit/Source/core/loader/MixedContentCheckerTest.cpp
+++ b/third_party/WebKit/Source/core/loader/MixedContentCheckerTest.cpp
@@ -62,7 +62,7 @@
     RefPtr<SecurityOrigin> security_origin(SecurityOrigin::Create(origin_url));
     KURL target_url(NullURL(), test.target);
     EXPECT_EQ(test.expectation, MixedContentChecker::IsMixedContent(
-                                    security_origin.Get(), target_url));
+                                    security_origin.get(), target_url));
   }
 }
 
diff --git a/third_party/WebKit/Source/core/loader/PingLoader.cpp b/third_party/WebKit/Source/core/loader/PingLoader.cpp
index 50f90165..b52e39f 100644
--- a/third_party/WebKit/Source/core/loader/PingLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/PingLoader.cpp
@@ -159,7 +159,7 @@
   }
 
   void Serialize(ResourceRequest& request) const override {
-    request.SetHTTPBody(entity_body_.Get());
+    request.SetHTTPBody(entity_body_.get());
     request.SetHTTPContentType(content_type_);
   }
 
@@ -264,7 +264,7 @@
                              AtomicString(destination_url.GetString()));
   RefPtr<SecurityOrigin> ping_origin = SecurityOrigin::Create(ping_url);
   if (ProtocolIs(frame->GetDocument()->Url().GetString(), "http") ||
-      frame->GetDocument()->GetSecurityOrigin()->CanAccess(ping_origin.Get())) {
+      frame->GetDocument()->GetSecurityOrigin()->CanAccess(ping_origin.get())) {
     request.SetHTTPHeaderField(
         HTTPNames::Ping_From,
         AtomicString(frame->GetDocument()->Url().GetString()));
diff --git a/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp b/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp
index 59925835..3e214291 100644
--- a/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp
+++ b/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp
@@ -238,7 +238,7 @@
     worker_thread_ = WTF::MakeUnique<WorkerThreadForTest>(
         ThreadableLoadingContext::Create(GetDocument()), *reporting_proxy_);
 
-    worker_thread_->StartWithSourceCode(security_origin_.Get(),
+    worker_thread_->StartWithSourceCode(security_origin_.get(),
                                         "//fake source code",
                                         parent_frame_task_runners_.Get());
     worker_thread_->WaitForInit();
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp
index 2d324cd..f8b5a03 100644
--- a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp
+++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp
@@ -71,10 +71,10 @@
   ~ModuleScriptLoaderTestModulator() override {}
 
   SecurityOrigin* GetSecurityOrigin() override {
-    return security_origin_.Get();
+    return security_origin_.get();
   }
 
-  ScriptState* GetScriptState() override { return script_state_.Get(); }
+  ScriptState* GetScriptState() override { return script_state_.get(); }
 
   ScriptModule CompileModule(
       const String& script,
@@ -85,7 +85,7 @@
       ParserDisposition parser_state,
       const TextPosition& position,
       ExceptionState& exception_state) override {
-    ScriptState::Scope scope(script_state_.Get());
+    ScriptState::Scope scope(script_state_.get());
     return ScriptModule::Compile(script_state_->GetIsolate(), script, url_str,
                                  access_control_status, credentials_mode, nonce,
                                  parser_state, position, exception_state);
@@ -105,7 +105,7 @@
   }
 
   ModuleScriptFetcher* CreateModuleScriptFetcher() override {
-    auto* execution_context = ExecutionContext::From(script_state_.Get());
+    auto* execution_context = ExecutionContext::From(script_state_.get());
     if (execution_context->IsDocument())
       return new DocumentModuleScriptFetcher(Fetcher());
     auto* global_scope = ToWorkletGlobalScope(execution_context);
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerTest.cpp b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerTest.cpp
index 27714da..ae79a8d 100644
--- a/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerTest.cpp
+++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerTest.cpp
@@ -65,7 +65,7 @@
       const KURL& url,
       const Vector<String>& dependency_module_specifiers,
       ScriptModuleState state) {
-    ScriptState::Scope scope(script_state_.Get());
+    ScriptState::Scope scope(script_state_.get());
 
     StringBuilder source_text;
     Vector<ModuleRequest> dependency_module_requests;
@@ -97,7 +97,7 @@
       v8::Local<v8::Value> error = V8ThrowException::CreateError(
           script_state_->GetIsolate(), "Instantiation failure.");
       module_script->SetErrorAndClearRecord(
-          ScriptValue(script_state_.Get(), error));
+          ScriptValue(script_state_.get(), error));
     }
 
     if (state == ScriptModuleState::kErrored) {
@@ -125,7 +125,7 @@
  private:
   // Implements Modulator:
 
-  ScriptState* GetScriptState() override { return script_state_.Get(); }
+  ScriptState* GetScriptState() override { return script_state_.get(); }
 
   void FetchSingle(const ModuleScriptFetchRequest& request,
                    ModuleGraphLevel,
@@ -144,11 +144,11 @@
 
   ScriptValue InstantiateModule(ScriptModule record) override {
     if (instantiate_should_fail_) {
-      ScriptState::Scope scope(script_state_.Get());
+      ScriptState::Scope scope(script_state_.get());
       v8::Local<v8::Value> error = V8ThrowException::CreateError(
           script_state_->GetIsolate(), "Instantiation failure.");
       errored_records_.insert(record);
-      return ScriptValue(script_state_.Get(), error);
+      return ScriptValue(script_state_.get(), error);
     }
     instantiated_records_.insert(record);
     return ScriptValue();
@@ -163,8 +163,8 @@
   }
 
   ScriptValue GetError(const ModuleScript* module_script) override {
-    ScriptState::Scope scope(script_state_.Get());
-    return ScriptValue(script_state_.Get(), module_script->CreateErrorInternal(
+    ScriptState::Scope scope(script_state_.get());
+    return ScriptValue(script_state_.get(), module_script->CreateErrorInternal(
                                                 script_state_->GetIsolate()));
   }
 
diff --git a/third_party/WebKit/Source/core/loader/resource/ImageResourceContent.cpp b/third_party/WebKit/Source/core/loader/resource/ImageResourceContent.cpp
index 386d0712..0146eaad 100644
--- a/third_party/WebKit/Source/core/loader/resource/ImageResourceContent.cpp
+++ b/third_party/WebKit/Source/core/loader/resource/ImageResourceContent.cpp
@@ -223,7 +223,7 @@
   }
 
   if (image_)
-    return image_.Get();
+    return image_.get();
 
   return blink::Image::NullImage();
 }
@@ -253,7 +253,7 @@
 
   if (image_->IsBitmapImage() &&
       should_respect_image_orientation == kRespectImageOrientation) {
-    size = LayoutSize(ToBitmapImage(image_.Get())->SizeRespectingOrientation());
+    size = LayoutSize(ToBitmapImage(image_.get())->SizeRespectingOrientation());
   } else {
     size = LayoutSize(image_->Size());
   }
diff --git a/third_party/WebKit/Source/core/loader/resource/ImageResourceContent.h b/third_party/WebKit/Source/core/loader/resource/ImageResourceContent.h
index 489d046..d044c31 100644
--- a/third_party/WebKit/Source/core/loader/resource/ImageResourceContent.h
+++ b/third_party/WebKit/Source/core/loader/resource/ImageResourceContent.h
@@ -59,7 +59,7 @@
 
   // Returns the nullImage() if the image is not available yet.
   blink::Image* GetImage();
-  bool HasImage() const { return image_.Get(); }
+  bool HasImage() const { return image_.get(); }
 
   static std::pair<blink::Image*, float> BrokenImage(
       float
diff --git a/third_party/WebKit/Source/core/mojo/MojoHandle.cpp b/third_party/WebKit/Source/core/mojo/MojoHandle.cpp
index 1331f72..ad5ec65 100644
--- a/third_party/WebKit/Source/core/mojo/MojoHandle.cpp
+++ b/third_party/WebKit/Source/core/mojo/MojoHandle.cpp
@@ -62,12 +62,12 @@
 
   const void* bytes = nullptr;
   uint32_t num_bytes = 0;
-  if (buffer.isArrayBuffer()) {
-    DOMArrayBuffer* array = buffer.getAsArrayBuffer();
+  if (buffer.IsArrayBuffer()) {
+    DOMArrayBuffer* array = buffer.GetAsArrayBuffer();
     bytes = array->Data();
     num_bytes = array->ByteLength();
   } else {
-    DOMArrayBufferView* view = buffer.getAsArrayBufferView().View();
+    DOMArrayBufferView* view = buffer.GetAsArrayBufferView().View();
     bytes = view->BaseAddress();
     num_bytes = view->byteLength();
   }
@@ -138,12 +138,12 @@
 
   const void* elements = nullptr;
   uint32_t num_bytes = 0;
-  if (buffer.isArrayBuffer()) {
-    DOMArrayBuffer* array = buffer.getAsArrayBuffer();
+  if (buffer.IsArrayBuffer()) {
+    DOMArrayBuffer* array = buffer.GetAsArrayBuffer();
     elements = array->Data();
     num_bytes = array->ByteLength();
   } else {
-    DOMArrayBufferView* view = buffer.getAsArrayBufferView().View();
+    DOMArrayBufferView* view = buffer.GetAsArrayBufferView().View();
     elements = view->BaseAddress();
     num_bytes = view->byteLength();
   }
@@ -186,12 +186,12 @@
 
   void* elements = nullptr;
   unsigned num_bytes = 0;
-  if (buffer.isArrayBuffer()) {
-    DOMArrayBuffer* array = buffer.getAsArrayBuffer();
+  if (buffer.IsArrayBuffer()) {
+    DOMArrayBuffer* array = buffer.GetAsArrayBuffer();
     elements = array->Data();
     num_bytes = array->ByteLength();
   } else {
-    DOMArrayBufferView* view = buffer.getAsArrayBufferView().View();
+    DOMArrayBufferView* view = buffer.GetAsArrayBufferView().View();
     elements = view->BaseAddress();
     num_bytes = view->byteLength();
   }
diff --git a/third_party/WebKit/Source/core/page/ChromeClientImpl.cpp b/third_party/WebKit/Source/core/page/ChromeClientImpl.cpp
index 735a4b8..f6c1a24 100644
--- a/third_party/WebKit/Source/core/page/ChromeClientImpl.cpp
+++ b/third_party/WebKit/Source/core/page/ChromeClientImpl.cpp
@@ -497,8 +497,8 @@
         !result.AbsoluteLinkURL().GetString().IsEmpty()) {
       url = result.AbsoluteLinkURL();
     } else if (result.InnerNode() &&
-               (isHTMLObjectElement(*result.InnerNode()) ||
-                isHTMLEmbedElement(*result.InnerNode()))) {
+               (IsHTMLObjectElement(*result.InnerNode()) ||
+                IsHTMLEmbedElement(*result.InnerNode()))) {
       LayoutObject* object = result.InnerNode()->GetLayoutObject();
       if (object && object->IsLayoutEmbeddedContent()) {
         PluginView* plugin_view = ToLayoutEmbeddedContent(object)->Plugin();
diff --git a/third_party/WebKit/Source/core/page/ContextMenuClient.cpp b/third_party/WebKit/Source/core/page/ContextMenuClient.cpp
index 93a7ddac..26a6b7fe 100644
--- a/third_party/WebKit/Source/core/page/ContextMenuClient.cpp
+++ b/third_party/WebKit/Source/core/page/ContextMenuClient.cpp
@@ -147,8 +147,8 @@
 }
 
 static HTMLFormElement* AssociatedFormElement(HTMLElement& element) {
-  if (isHTMLFormElement(element))
-    return &toHTMLFormElement(element);
+  if (auto* form = ToHTMLFormElementOrNull(element))
+    return form;
   return element.formOwner();
 }
 
@@ -239,7 +239,7 @@
     }
   }
 
-  if (isHTMLCanvasElement(r.InnerNode())) {
+  if (IsHTMLCanvasElement(r.InnerNode())) {
     data.media_type = WebContextMenuData::kMediaTypeCanvas;
     data.has_image_contents = true;
   } else if (!r.AbsoluteImageURL().IsEmpty()) {
@@ -253,7 +253,7 @@
     data.is_placeholder_image =
         r.GetImage() && r.GetImage()->IsPlaceholderImage();
     if (data.has_image_contents &&
-        isHTMLImageElement(r.InnerNodeOrImageMapImage())) {
+        IsHTMLImageElement(r.InnerNodeOrImageMapImage())) {
       HTMLImageElement* image_element =
           toHTMLImageElement(r.InnerNodeOrImageMapImage());
       if (image_element && image_element->CachedImage()) {
@@ -267,9 +267,9 @@
     // We know that if absoluteMediaURL() is not empty, then this
     // is a media element.
     HTMLMediaElement* media_element = ToHTMLMediaElement(r.InnerNode());
-    if (isHTMLVideoElement(*media_element))
+    if (IsHTMLVideoElement(*media_element))
       data.media_type = WebContextMenuData::kMediaTypeVideo;
-    else if (isHTMLAudioElement(*media_element))
+    else if (IsHTMLAudioElement(*media_element))
       data.media_type = WebContextMenuData::kMediaTypeAudio;
 
     if (media_element->error())
@@ -293,8 +293,8 @@
       data.media_flags |= WebContextMenuData::kMediaCanToggleControls;
     if (media_element->ShouldShowControls())
       data.media_flags |= WebContextMenuData::kMediaControls;
-  } else if (isHTMLObjectElement(*r.InnerNode()) ||
-             isHTMLEmbedElement(*r.InnerNode())) {
+  } else if (IsHTMLObjectElement(*r.InnerNode()) ||
+             IsHTMLEmbedElement(*r.InnerNode())) {
     LayoutObject* object = r.InnerNode()->GetLayoutObject();
     if (object && object->IsLayoutEmbeddedContent()) {
       PluginView* plugin_view = ToLayoutEmbeddedContent(object)->Plugin();
@@ -396,7 +396,7 @@
     }
 
     HTMLFormElement* form = CurrentForm(selected_frame->Selection());
-    if (form && isHTMLInputElement(*r.InnerNode())) {
+    if (form && IsHTMLInputElement(*r.InnerNode())) {
       HTMLInputElement& selected_element = toHTMLInputElement(*r.InnerNode());
       WebSearchableFormData ws = WebSearchableFormData(
           WebFormElement(form), WebInputElement(&selected_element));
@@ -422,9 +422,7 @@
   // Filter out custom menu elements and add them into the data.
   PopulateCustomMenuItems(default_menu, &data);
 
-  if (isHTMLAnchorElement(r.URLElement())) {
-    HTMLAnchorElement* anchor = toHTMLAnchorElement(r.URLElement());
-
+  if (auto* anchor = ToHTMLAnchorElementOrNull(r.URLElement())) {
     // Extract suggested filename for saving file.
     data.suggested_filename = anchor->FastGetAttribute(HTMLNames::downloadAttr);
 
@@ -437,11 +435,10 @@
   }
 
   // Find the input field type.
-  if (isHTMLInputElement(r.InnerNode())) {
-    HTMLInputElement* element = toHTMLInputElement(r.InnerNode());
-    if (element->type() == InputTypeNames::password)
+  if (auto* input = ToHTMLInputElementOrNull(r.InnerNode())) {
+    if (input->type() == InputTypeNames::password)
       data.input_field_type = WebContextMenuData::kInputFieldTypePassword;
-    else if (element->IsTextField())
+    else if (input->IsTextField())
       data.input_field_type = WebContextMenuData::kInputFieldTypePlainText;
     else
       data.input_field_type = WebContextMenuData::kInputFieldTypeOther;
diff --git a/third_party/WebKit/Source/core/page/DragController.cpp b/third_party/WebKit/Source/core/page/DragController.cpp
index c33122b..8e8d1e91 100644
--- a/third_party/WebKit/Source/core/page/DragController.cpp
+++ b/third_party/WebKit/Source/core/page/DragController.cpp
@@ -343,7 +343,7 @@
 static HTMLInputElement* AsFileInput(Node* node) {
   DCHECK(node);
   for (; node; node = node->OwnerShadowHost()) {
-    if (isHTMLInputElement(*node) &&
+    if (IsHTMLInputElement(*node) &&
         toHTMLInputElement(node)->type() == InputTypeNames::file)
       return toHTMLInputElement(node);
   }
@@ -828,7 +828,7 @@
         candidate_drag_type = kDragSourceActionDHTML;
         break;
       }
-      if (isHTMLAnchorElement(*node) &&
+      if (IsHTMLAnchorElement(*node) &&
           toHTMLAnchorElement(node)->IsLiveLink()) {
         candidate_drag_type = kDragSourceActionLink;
         break;
@@ -927,7 +927,7 @@
   DataTransfer* data_transfer = state.drag_data_transfer_.Get();
   Node* node = state.drag_src_.Get();
 
-  if (isHTMLAnchorElement(*node) && toHTMLAnchorElement(node)->IsLiveLink() &&
+  if (IsHTMLAnchorElement(*node) && toHTMLAnchorElement(node)->IsLiveLink() &&
       !link_url.IsEmpty()) {
     // Simplify whitespace so the title put on the clipboard resembles what
     // the user sees on the web page. This includes replacing newlines with
@@ -1030,7 +1030,7 @@
     KURL url = element->GetDocument().CompleteURL(element->ImageSourceURL());
     svg_image = SVGImageForContainer::Create(
         ToSVGImage(image), image_element_size_in_pixels, 1, url);
-    image = svg_image.Get();
+    image = svg_image.get();
   }
 
   InterpolationQuality interpolation_quality =
diff --git a/third_party/WebKit/Source/core/page/FocusController.cpp b/third_party/WebKit/Source/core/page/FocusController.cpp
index 9d0b7e3..fa35a74 100644
--- a/third_party/WebKit/Source/core/page/FocusController.cpp
+++ b/third_party/WebKit/Source/core/page/FocusController.cpp
@@ -305,10 +305,8 @@
     const Element& element) {
   Element* parent = const_cast<Element*>(element.parentElement());
   while (parent) {
-    if (isHTMLSlotElement(parent))
-      return toHTMLSlotElement(parent)->AssignedNodes().IsEmpty()
-                 ? toHTMLSlotElement(parent)
-                 : nullptr;
+    if (auto* slot = ToHTMLSlotElementOrNull(parent))
+      return slot->AssignedNodes().IsEmpty() ? slot : nullptr;
     parent = parent->parentElement();
   }
   return nullptr;
@@ -323,7 +321,7 @@
     const Element& current) {
   Element* parent = current.parentElement();
   while (parent) {
-    if (isHTMLSlotElement(parent) &&
+    if (IsHTMLSlotElement(parent) &&
         toHTMLSlotElement(parent)->AssignedNodes().IsEmpty())
       return !SlotScopedTraversal::IsSlotScoped(current) &&
              toHTMLSlotElement(parent) == slot;
@@ -412,7 +410,7 @@
 inline bool IsNonFocusableFocusScopeOwner(Element& element) {
   return IsNonKeyboardFocusableShadowHost(element) ||
          IsShadowInsertionPointFocusScopeOwner(element) ||
-         isHTMLSlotElement(element);
+         IsHTMLSlotElement(element);
 }
 
 inline bool IsShadowHostDelegatesFocus(const Element& element) {
@@ -1423,12 +1421,11 @@
           type, focused_element);
       starting_rect = NodeRectInAbsoluteCoordinates(focused_element,
                                                     true /* ignore border */);
-    } else if (isHTMLAreaElement(*focused_element)) {
-      HTMLAreaElement& area = toHTMLAreaElement(*focused_element);
-      if (area.ImageElement()) {
+    } else if (auto* area = ToHTMLAreaElementOrNull(*focused_element)) {
+      if (area->ImageElement()) {
         container = ScrollableEnclosingBoxOrParentFrameForNodeInDirection(
-            type, area.ImageElement());
-        starting_rect = VirtualRectForAreaElementAndDirection(area, type);
+            type, area->ImageElement());
+        starting_rect = VirtualRectForAreaElementAndDirection(*area, type);
       }
     }
   }
diff --git a/third_party/WebKit/Source/core/page/PagePopupClientTest.cpp b/third_party/WebKit/Source/core/page/PagePopupClientTest.cpp
index f40346eb..ad1f230 100644
--- a/third_party/WebKit/Source/core/page/PagePopupClientTest.cpp
+++ b/third_party/WebKit/Source/core/page/PagePopupClientTest.cpp
@@ -13,7 +13,7 @@
   RefPtr<SharedBuffer> buffer = SharedBuffer::Create();
   PagePopupClient::AddJavaScriptString(
       String::FromUTF8("abc\r\n'\"</script>\t\f\v\xE2\x80\xA8\xE2\x80\xA9"),
-      buffer.Get());
+      buffer.get());
   const Vector<char> contiguous = buffer->Copy();
   EXPECT_EQ(
       "\"abc\\r\\n'\\\"\\x3C/script>\\u0009\\u000C\\u000B\\u2028\\u2029\"",
diff --git a/third_party/WebKit/Source/core/page/SpatialNavigation.cpp b/third_party/WebKit/Source/core/page/SpatialNavigation.cpp
index b62702a..8db47851 100644
--- a/third_party/WebKit/Source/core/page/SpatialNavigation.cpp
+++ b/third_party/WebKit/Source/core/page/SpatialNavigation.cpp
@@ -61,14 +61,13 @@
   DCHECK(node);
   DCHECK(node->IsElementNode());
 
-  if (isHTMLAreaElement(*node)) {
-    HTMLAreaElement& area = toHTMLAreaElement(*node);
-    HTMLImageElement* image = area.ImageElement();
+  if (auto* area = ToHTMLAreaElementOrNull(*node)) {
+    HTMLImageElement* image = area->ImageElement();
     if (!image || !image->GetLayoutObject())
       return;
 
     visible_node = image;
-    rect = VirtualRectForAreaElementAndDirection(area, type);
+    rect = VirtualRectForAreaElementAndDirection(*area, type);
   } else {
     if (!node->GetLayoutObject())
       return;
@@ -539,8 +538,8 @@
   if (!first_candidate.rect.Intersects(second_candidate.rect))
     return false;
 
-  if (isHTMLAreaElement(*first_candidate.focusable_node) ||
-      isHTMLAreaElement(*second_candidate.focusable_node))
+  if (IsHTMLAreaElement(*first_candidate.focusable_node) ||
+      IsHTMLAreaElement(*second_candidate.focusable_node))
     return false;
 
   if (!first_candidate.visible_node->GetLayoutObject()->IsLayoutInline() ||
diff --git a/third_party/WebKit/Source/core/page/TouchAdjustment.cpp b/third_party/WebKit/Source/core/page/TouchAdjustment.cpp
index 5fad437..209bc40d 100644
--- a/third_party/WebKit/Source/core/page/TouchAdjustment.cpp
+++ b/third_party/WebKit/Source/core/page/TouchAdjustment.cpp
@@ -92,7 +92,7 @@
     // Tapping on a text field or other focusable item should trigger
     // adjustment, except that iframe elements are hard-coded to support focus
     // but the effect is often invisible so they should be excluded.
-    if (element->IsMouseFocusable() && !isHTMLIFrameElement(element))
+    if (element->IsMouseFocusable() && !IsHTMLIFrameElement(element))
       return true;
     // Accept nodes that has a CSS effect when touched.
     if (element->ChildrenOrSiblingsAffectedByActive() ||
diff --git a/third_party/WebKit/Source/core/page/TouchDisambiguation.cpp b/third_party/WebKit/Source/core/page/TouchDisambiguation.cpp
index 557f059..baa103fb 100644
--- a/third_party/WebKit/Source/core/page/TouchDisambiguation.cpp
+++ b/third_party/WebKit/Source/core/page/TouchDisambiguation.cpp
@@ -137,8 +137,8 @@
     for (Node& node : NodeTraversal::InclusiveAncestorsOf(*hit_result)) {
       if (black_list.Contains(&node))
         continue;
-      if (node.IsDocumentNode() || isHTMLHtmlElement(node) ||
-          isHTMLBodyElement(node))
+      if (node.IsDocumentNode() || IsHTMLHtmlElement(node) ||
+          IsHTMLBodyElement(node))
         break;
       if (node.WillRespondToMouseClickEvents()) {
         TouchTargetData& target_data =
diff --git a/third_party/WebKit/Source/core/page/ValidationMessageOverlayDelegate.cpp b/third_party/WebKit/Source/core/page/ValidationMessageOverlayDelegate.cpp
index 07b37a73..a7391ab 100644
--- a/third_party/WebKit/Source/core/page/ValidationMessageOverlayDelegate.cpp
+++ b/third_party/WebKit/Source/core/page/ValidationMessageOverlayDelegate.cpp
@@ -148,7 +148,7 @@
   page_->GetVisualViewport().SetSize(view_size);
 
   RefPtr<SharedBuffer> data = SharedBuffer::Create();
-  WriteDocument(data.Get());
+  WriteDocument(data.get());
   float zoom_factor = anchor_->GetDocument().GetFrame()->PageZoomFactor();
   frame->SetPageZoomFactor(zoom_factor);
   // Propagate deprecated DSF for platforms without use-zoom-for-dsf.
diff --git a/third_party/WebKit/Source/core/page/scrolling/RootScrollerTest.cpp b/third_party/WebKit/Source/core/page/scrolling/RootScrollerTest.cpp
index 7640162..c6bc7b9 100644
--- a/third_party/WebKit/Source/core/page/scrolling/RootScrollerTest.cpp
+++ b/third_party/WebKit/Source/core/page/scrolling/RootScrollerTest.cpp
@@ -219,7 +219,7 @@
   // should remain the same.
   NonThrowableExceptionState non_throw;
   HeapVector<NodeOrString> nodes;
-  nodes.push_back(NodeOrString::fromNode(iframe));
+  nodes.push_back(NodeOrString::FromNode(iframe));
   document->documentElement()->ReplaceWith(nodes, non_throw);
 
   MainFrameView()->UpdateAllLifecyclePhases();
diff --git a/third_party/WebKit/Source/core/page/scrolling/SmoothScrollTest.cpp b/third_party/WebKit/Source/core/page/scrolling/SmoothScrollTest.cpp
index 35f563a..073601b2 100644
--- a/third_party/WebKit/Source/core/page/scrolling/SmoothScrollTest.cpp
+++ b/third_party/WebKit/Source/core/page/scrolling/SmoothScrollTest.cpp
@@ -36,7 +36,7 @@
   ScrollIntoViewOptionsOrBoolean arg;
   ScrollIntoViewOptions options;
   options.setBlock("start");
-  arg.setScrollIntoViewOptions(options);
+  arg.SetScrollIntoViewOptions(options);
   content->scrollIntoView(arg);
 
   ASSERT_EQ(Window().scrollY(), content->OffsetTop());
@@ -56,7 +56,7 @@
   ScrollIntoViewOptions options;
   options.setBlock("start");
   options.setBehavior("smooth");
-  arg.setScrollIntoViewOptions(options);
+  arg.SetScrollIntoViewOptions(options);
   Compositor().BeginFrame();
   ASSERT_EQ(Window().scrollY(), 0);
 
@@ -90,7 +90,7 @@
   ScrollIntoViewOptions options;
   options.setBlock("start");
   options.setBehavior("smooth");
-  arg.setScrollIntoViewOptions(options);
+  arg.SetScrollIntoViewOptions(options);
   Compositor().BeginFrame();
   ASSERT_EQ(Window().scrollY(), 0);
   ASSERT_EQ(container->scrollTop(), 0);
@@ -142,7 +142,7 @@
   ScrollIntoViewOptions options;
   options.setBlock("start");
   options.setBehavior("smooth");
-  arg.setScrollIntoViewOptions(options);
+  arg.SetScrollIntoViewOptions(options);
 
   Compositor().BeginFrame();
   ASSERT_EQ(Window().scrollY(), 0);
@@ -201,7 +201,7 @@
   ScrollIntoViewOptions options;
   options.setBlock("start");
   options.setBehavior("smooth");
-  arg.setScrollIntoViewOptions(options);
+  arg.SetScrollIntoViewOptions(options);
   Compositor().BeginFrame();
   ASSERT_EQ(Window().scrollY(), 0);
   ASSERT_EQ(container->scrollTop(), 0);
@@ -252,7 +252,7 @@
 
   options.setBlock("nearest");
   options.setInlinePosition("nearest");
-  arg1.setScrollIntoViewOptions(options);
+  arg1.SetScrollIntoViewOptions(options);
   content->scrollIntoView(arg1);
   ASSERT_EQ(Window().scrollX(),
             content->OffsetLeft() + content_width - window_width);
@@ -261,14 +261,14 @@
 
   options.setBlock("start");
   options.setInlinePosition("start");
-  arg2.setScrollIntoViewOptions(options);
+  arg2.SetScrollIntoViewOptions(options);
   content->scrollIntoView(arg2);
   ASSERT_EQ(Window().scrollX(), content->OffsetLeft());
   ASSERT_EQ(Window().scrollY(), content->OffsetTop());
 
   options.setBlock("center");
   options.setInlinePosition("center");
-  arg3.setScrollIntoViewOptions(options);
+  arg3.SetScrollIntoViewOptions(options);
   content->scrollIntoView(arg3);
   ASSERT_EQ(Window().scrollX(),
             content->OffsetLeft() + (content_width - window_width) / 2);
@@ -277,7 +277,7 @@
 
   options.setBlock("end");
   options.setInlinePosition("end");
-  arg4.setScrollIntoViewOptions(options);
+  arg4.SetScrollIntoViewOptions(options);
   content->scrollIntoView(arg4);
   ASSERT_EQ(Window().scrollX(),
             content->OffsetLeft() + content_width - window_width);
@@ -307,7 +307,7 @@
   ScrollIntoViewOptionsOrBoolean arg;
   ScrollIntoViewOptions options;
   options.setBlock("start");
-  arg.setScrollIntoViewOptions(options);
+  arg.SetScrollIntoViewOptions(options);
   Compositor().BeginFrame();
   ASSERT_EQ(Window().scrollY(), 0);
   ASSERT_EQ(container->scrollTop(), 0);
@@ -401,7 +401,7 @@
   ScrollIntoViewOptionsOrBoolean arg;
   ScrollIntoViewOptions options;
   options.setBlock("start");
-  arg.setScrollIntoViewOptions(options);
+  arg.SetScrollIntoViewOptions(options);
   Compositor().BeginFrame();
   ASSERT_EQ(Window().scrollY(), 0);
 
diff --git a/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp b/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp
index a2c3c742..bc46462a 100644
--- a/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp
+++ b/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp
@@ -530,6 +530,7 @@
   // present in the painted tile.
   SetTileSize(
       ApplySubPixelHeuristicToImageSize(fill_tile_size, positioning_area));
+  SetLogicalTileSize(fill_tile_size);
 
   EFillRepeat background_repeat_x = fill_layer.RepeatX();
   EFillRepeat background_repeat_y = fill_layer.RepeatY();
@@ -565,6 +566,7 @@
 
     SetTileSize(
         ApplySubPixelHeuristicToImageSize(fill_tile_size, positioning_area));
+    SetLogicalTileSize(fill_tile_size);
     SetPhaseX(
         TileSize().Width()
             ? LayoutUnit(roundf(TileSize().Width() -
@@ -593,6 +595,7 @@
 
     SetTileSize(
         ApplySubPixelHeuristicToImageSize(fill_tile_size, positioning_area));
+    SetLogicalTileSize(fill_tile_size);
     SetPhaseY(
         TileSize().Height()
             ? LayoutUnit(roundf(TileSize().Height() -
diff --git a/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.h b/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.h
index 967ec87..02456c8 100644
--- a/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.h
+++ b/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.h
@@ -55,6 +55,10 @@
   // that tile region. This may happen because of CSS background-size and
   // background-repeat requirements.
   const LayoutSize& TileSize() const { return tile_size_; }
+  // The tile_size_ is set in the Calculate() function after calling the
+  // ApplySubPixelHeuristicToImageSize(). The logical_tile_size_ is similar to
+  // the tile_size_, but without applying any subpixel heuristic.
+  const LayoutSize& LogicalTileSize() { return logical_tile_size_; }
   // phase() represents the point in the image that will appear at (0,0) in the
   // destination space. The point is defined in tileSize() coordinates.
   const LayoutPoint& Phase() const { return phase_; }
@@ -78,6 +82,9 @@
   void SetDestRect(const LayoutRect& dest_rect) { dest_rect_ = dest_rect; }
   void SetPhase(const LayoutPoint& phase) { phase_ = phase; }
   void SetTileSize(const LayoutSize& tile_size) { tile_size_ = tile_size; }
+  void SetLogicalTileSize(const LayoutSize& logical_tile_size) {
+    logical_tile_size_ = logical_tile_size;
+  }
   void SetSpaceSize(const LayoutSize& repeat_spacing) {
     repeat_spacing_ = repeat_spacing;
   }
@@ -116,6 +123,7 @@
   LayoutRect dest_rect_;
   LayoutPoint phase_;
   LayoutSize tile_size_;
+  LayoutSize logical_tile_size_;
   LayoutSize repeat_spacing_;
   bool has_non_local_geometry_;
   bool coordinate_offset_by_paint_rect_;
diff --git a/third_party/WebKit/Source/core/paint/BlockPainterTest.cpp b/third_party/WebKit/Source/core/paint/BlockPainterTest.cpp
index bff9893..d291f6d4 100644
--- a/third_party/WebKit/Source/core/paint/BlockPainterTest.cpp
+++ b/third_party/WebKit/Source/core/paint/BlockPainterTest.cpp
@@ -87,8 +87,8 @@
   auto* contents_transform =
       contents_chunk.properties.property_tree_state.Transform();
   auto* contents_scroll = contents_transform->ScrollNode();
-  EXPECT_EQ(IntSize(200, 300), contents_scroll->Bounds());
-  EXPECT_EQ(IntSize(200, 200), contents_scroll->ContainerBounds());
+  EXPECT_EQ(IntRect(0, 0, 200, 300), contents_scroll->ContentsRect());
+  EXPECT_EQ(IntRect(0, 0, 200, 200), contents_scroll->ContainerRect());
   auto* contents_clip = contents_chunk.properties.property_tree_state.Clip();
   EXPECT_EQ(FloatRect(0, 0, 200, 200), contents_clip->ClipRect().Rect());
 
@@ -145,8 +145,8 @@
   auto* contents_transform =
       contents_chunk.properties.property_tree_state.Transform();
   auto* contents_scroll = contents_transform->ScrollNode();
-  EXPECT_EQ(IntSize(800, 2000), contents_scroll->Bounds());
-  EXPECT_EQ(IntSize(800, 600), contents_scroll->ContainerBounds());
+  EXPECT_EQ(IntRect(0, 0, 800, 2000), contents_scroll->ContentsRect());
+  EXPECT_EQ(IntRect(0, 0, 800, 600), contents_scroll->ContainerRect());
   auto* contents_clip = contents_chunk.properties.property_tree_state.Clip();
   EXPECT_EQ(FloatRect(0, 0, 800, 600), contents_clip->ClipRect().Rect());
 
diff --git a/third_party/WebKit/Source/core/paint/BoxPainterBase.cpp b/third_party/WebKit/Source/core/paint/BoxPainterBase.cpp
index 3fca72e..2709f04 100644
--- a/third_party/WebKit/Source/core/paint/BoxPainterBase.cpp
+++ b/third_party/WebKit/Source/core/paint/BoxPainterBase.cpp
@@ -557,7 +557,7 @@
                        scrolled_paint_rect);
     image = info.image->GetImage(
         geometry.ImageClient(), geometry.ImageDocument(), geometry.ImageStyle(),
-        FlooredIntSize(geometry.TileSize()));
+        FlooredIntSize(geometry.TileSize()), &geometry.LogicalTileSize());
     interpolation_quality_context.emplace(geometry.ImageStyle(), context);
 
     if (bg_layer.MaskSourceType() == kMaskLuminance)
@@ -575,7 +575,7 @@
 
   // Fast path for drawing simple color backgrounds.
   if (PaintFastBottomLayer(display_item_, node_, paint_info, info, rect,
-                           border_rect, geometry, image.Get(), composite_op)) {
+                           border_rect, geometry, image.get(), composite_op)) {
     return;
   }
 
@@ -585,7 +585,7 @@
                            kApplyToContext);
   }
   if (bg_layer.Clip() == kTextFillBox) {
-    PaintFillLayerTextFillBox(context, info, image.Get(), composite_op,
+    PaintFillLayerTextFillBox(context, info, image.get(), composite_op,
                               geometry, rect, scrolled_paint_rect);
     return;
   }
@@ -615,7 +615,7 @@
       break;
   }
 
-  PaintFillLayerBackground(context, info, image.Get(), composite_op, geometry,
+  PaintFillLayerBackground(context, info, image.get(), composite_op, geometry,
                            scrolled_paint_rect);
 }
 
diff --git a/third_party/WebKit/Source/core/paint/ClipPathClipper.cpp b/third_party/WebKit/Source/core/paint/ClipPathClipper.cpp
index fbe1e16..e9ae850b 100644
--- a/third_party/WebKit/Source/core/paint/ClipPathClipper.cpp
+++ b/third_party/WebKit/Source/core/paint/ClipPathClipper.cpp
@@ -51,7 +51,7 @@
     return nullptr;
   SVGElement* element =
       reference_clip_path_operation.FindElement(target_node->GetTreeScope());
-  if (!isSVGClipPathElement(element) || !element->GetLayoutObject())
+  if (!IsSVGClipPathElement(element) || !element->GetLayoutObject())
     return nullptr;
   return ToLayoutSVGResourceClipper(
       ToLayoutSVGResourceContainer(element->GetLayoutObject()));
diff --git a/third_party/WebKit/Source/core/paint/FilterEffectBuilder.cpp b/third_party/WebKit/Source/core/paint/FilterEffectBuilder.cpp
index ad1653c..30c5138 100644
--- a/third_party/WebKit/Source/core/paint/FilterEffectBuilder.cpp
+++ b/third_party/WebKit/Source/core/paint/FilterEffectBuilder.cpp
@@ -417,10 +417,9 @@
   DCHECK(target_context_);
   Element* filter_element = reference_operation.ElementProxy().FindElement(
       target_context_->GetTreeScope());
-  if (!isSVGFilterElement(filter_element))
-    return nullptr;
-  return BuildReferenceFilter(toSVGFilterElement(*filter_element),
-                              previous_effect);
+  if (auto* filter = ToSVGFilterElementOrNull(filter_element))
+    return BuildReferenceFilter(*filter, previous_effect);
+  return nullptr;
 }
 
 Filter* FilterEffectBuilder::BuildReferenceFilter(
diff --git a/third_party/WebKit/Source/core/paint/FindPaintOffsetAndVisualRectNeedingUpdate.h b/third_party/WebKit/Source/core/paint/FindPaintOffsetAndVisualRectNeedingUpdate.h
index ef49b49..4963b13 100644
--- a/third_party/WebKit/Source/core/paint/FindPaintOffsetAndVisualRectNeedingUpdate.h
+++ b/third_party/WebKit/Source/core/paint/FindPaintOffsetAndVisualRectNeedingUpdate.h
@@ -50,7 +50,7 @@
                   ->PaintProperties()
                   ->PaintOffsetTranslation()
             : nullptr;
-    DCHECK_OBJECT_PROPERTY_EQ(object_, old_paint_offset_translation_.Get(),
+    DCHECK_OBJECT_PROPERTY_EQ(object_, old_paint_offset_translation_.get(),
                               paint_offset_translation);
   }
 
diff --git a/third_party/WebKit/Source/core/paint/FramePainter.cpp b/third_party/WebKit/Source/core/paint/FramePainter.cpp
index 7628b03..101e8604 100644
--- a/third_party/WebKit/Source/core/paint/FramePainter.cpp
+++ b/third_party/WebKit/Source/core/paint/FramePainter.cpp
@@ -7,6 +7,7 @@
 #include "core/editing/markers/DocumentMarkerController.h"
 #include "core/frame/LocalFrameView.h"
 #include "core/inspector/InspectorTraceEvents.h"
+#include "core/layout/LayoutScrollbarPart.h"
 #include "core/layout/LayoutView.h"
 #include "core/page/Page.h"
 #include "core/paint/FramePaintTiming.h"
@@ -233,11 +234,11 @@
     bool needs_background = GetFrameView().GetFrame().IsMainFrame();
     if (needs_background &&
         !LayoutObjectDrawingRecorder::UseCachedDrawingIfPossible(
-            context, *GetFrameView().GetLayoutView(),
-            DisplayItem::kScrollbarCorner)) {
+            context, *GetFrameView().ScrollCorner(),
+            DisplayItem::kScrollbarBackground)) {
       LayoutObjectDrawingRecorder drawing_recorder(
-          context, *GetFrameView().GetLayoutView(),
-          DisplayItem::kScrollbarCorner, FloatRect(corner_rect));
+          context, *GetFrameView().ScrollCorner(),
+          DisplayItem::kScrollbarBackground, corner_rect);
       context.FillRect(corner_rect, GetFrameView().BaseBackgroundColor());
     }
     ScrollbarPainter::PaintIntoRect(*GetFrameView().ScrollCorner(), context,
@@ -268,7 +269,13 @@
   if (needs_background) {
     IntRect to_fill = bar.FrameRect();
     to_fill.Intersect(rect);
-    context.FillRect(to_fill, GetFrameView().BaseBackgroundColor());
+    if (!to_fill.IsEmpty() &&
+        !DrawingRecorder::UseCachedDrawingIfPossible(
+            context, bar, DisplayItem::kScrollbarBackground)) {
+      DrawingRecorder recorder(context, bar, DisplayItem::kScrollbarBackground,
+                               to_fill);
+      context.FillRect(to_fill, GetFrameView().BaseBackgroundColor());
+    }
   }
 
   bar.Paint(context, CullRect(rect));
diff --git a/third_party/WebKit/Source/core/paint/ImagePainter.cpp b/third_party/WebKit/Source/core/paint/ImagePainter.cpp
index f1d1e2b..9157d8e 100644
--- a/third_party/WebKit/Source/core/paint/ImagePainter.cpp
+++ b/third_party/WebKit/Source/core/paint/ImagePainter.cpp
@@ -39,7 +39,7 @@
     return;
 
   Element* focused_element = document.FocusedElement();
-  if (!isHTMLAreaElement(focused_element))
+  if (!IsHTMLAreaElement(focused_element))
     return;
 
   HTMLAreaElement& area_element = toHTMLAreaElement(*focused_element);
@@ -173,7 +173,7 @@
       context.ImageInterpolationQuality();
   context.SetImageInterpolationQuality(interpolation_quality);
   context.DrawImage(
-      image.Get(), pixel_snapped_dest_rect, &src_rect, SkBlendMode::kSrcOver,
+      image.get(), pixel_snapped_dest_rect, &src_rect, SkBlendMode::kSrcOver,
       LayoutObject::ShouldRespectImageOrientation(&layout_image_));
   context.SetImageInterpolationQuality(previous_interpolation_quality);
 }
diff --git a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp
index aad725f..1dcc902c 100644
--- a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp
@@ -70,7 +70,7 @@
       return current;
 
     if (Node* node = current.GetNode()) {
-      if (isHTMLAnchorElement(node) || node->HasTagName(HTMLNames::fontTag))
+      if (IsHTMLAnchorElement(node) || node->HasTagName(HTMLNames::fontTag))
         return current;
     }
   }
diff --git a/third_party/WebKit/Source/core/paint/LayerClipRecorder.cpp b/third_party/WebKit/Source/core/paint/LayerClipRecorder.cpp
index 1d2132f..6356d30 100644
--- a/third_party/WebKit/Source/core/paint/LayerClipRecorder.cpp
+++ b/third_party/WebKit/Source/core/paint/LayerClipRecorder.cpp
@@ -95,7 +95,7 @@
       // getRoundedInnerBorderFor assumes it has not been snapped yet.
       LayoutSize size(layer->GetLayoutBox()
                           ? ToLayoutBox(layer->GetLayoutObject()).Size()
-                          : LayoutSize(layer->size()));
+                          : LayoutSize(layer->Size()));
       rounded_rect_clips.push_back(
           layer->GetLayoutObject().Style()->GetRoundedInnerBorderFor(
               LayoutRect(delta, size)));
diff --git a/third_party/WebKit/Source/core/paint/ListMarkerPainter.cpp b/third_party/WebKit/Source/core/paint/ListMarkerPainter.cpp
index 409dee6..4642af014 100644
--- a/third_party/WebKit/Source/core/paint/ListMarkerPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/ListMarkerPainter.cpp
@@ -76,8 +76,8 @@
     context.DrawImage(
         layout_list_marker_.GetImage()
             ->GetImage(layout_list_marker_, layout_list_marker_.GetDocument(),
-                       layout_list_marker_.StyleRef(), marker.Size())
-            .Get(),
+                       layout_list_marker_.StyleRef(), marker.Size(), nullptr)
+            .get(),
         marker);
     if (layout_list_marker_.GetSelectionState() != SelectionState::kNone) {
       LayoutRect sel_rect = layout_list_marker_.LocalSelectionRect();
diff --git a/third_party/WebKit/Source/core/paint/NinePieceImagePainter.cpp b/third_party/WebKit/Source/core/paint/NinePieceImagePainter.cpp
index 4322bf5..37e83e6c 100644
--- a/third_party/WebKit/Source/core/paint/NinePieceImagePainter.cpp
+++ b/third_party/WebKit/Source/core/paint/NinePieceImagePainter.cpp
@@ -89,8 +89,9 @@
   // scale of them again.
   IntSize image_size = RoundedIntSize(
       style_image->ImageSize(document, 1, border_image_rect.Size()));
-  RefPtr<Image> image =
-      style_image->GetImage(observer, document, style, image_size);
+  LayoutSize logical_image_size(image_size);
+  RefPtr<Image> image = style_image->GetImage(observer, document, style,
+                                              image_size, &logical_image_size);
 
   InterpolationQuality interpolation_quality = style.GetInterpolationQuality();
   InterpolationQuality previous_interpolation_quality =
@@ -103,7 +104,7 @@
                                               FloatRect(border_image_rect)));
 
   PaintPieces(graphics_context, border_image_rect, style, nine_piece_image,
-              image.Get(), image_size, op);
+              image.get(), image_size, op);
 
   graphics_context.SetImageInterpolationQuality(previous_interpolation_quality);
   return true;
diff --git a/third_party/WebKit/Source/core/paint/ObjectPaintInvalidator.cpp b/third_party/WebKit/Source/core/paint/ObjectPaintInvalidator.cpp
index 3f8ae83..4058e2bc 100644
--- a/third_party/WebKit/Source/core/paint/ObjectPaintInvalidator.cpp
+++ b/third_party/WebKit/Source/core/paint/ObjectPaintInvalidator.cpp
@@ -505,8 +505,10 @@
   // or shouldInvalidationSelection is set (in case that the selection itself
   // changed).
   bool full_invalidation = IsImmediateFullPaintInvalidationReason(reason);
-  if (!full_invalidation && !object_.ShouldInvalidateSelection())
+  if (!full_invalidation && !object_.ShouldInvalidateSelection()) {
+    object_.GetMutableForPainting().SetSelectionVisualRect(LayoutRect());
     return;
+  }
 
   LayoutRect old_selection_rect = object_.SelectionVisualRect();
   LayoutRect new_selection_rect;
@@ -550,15 +552,17 @@
     object_.InvalidateDisplayItemClients(PaintInvalidationReason::kRectangle);
   }
 
-  // TODO(crbug.com/732612): Implement rectangle raster invalidation for SPv2.
-  if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
-    return;
-
   context_.MapLocalRectToVisualRectInBacking(object_, rect);
   if (rect.IsEmpty())
     return;
-  InvalidatePaintRectangleWithContext(rect,
-                                      PaintInvalidationReason::kRectangle);
+
+  if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+    // PaintController will handle raster invalidation of the partial rect.
+    object_.GetMutableForPainting().SetPartialInvalidationRect(rect);
+  } else {
+    InvalidatePaintRectangleWithContext(rect,
+                                        PaintInvalidationReason::kRectangle);
+  }
 }
 
 DISABLE_CFI_PERF
diff --git a/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h b/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h
index e40f3bb..8a935dd 100644
--- a/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h
+++ b/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h
@@ -65,23 +65,23 @@
   //                                      redundant, but it is a pain to teach
   //                                      scrollbars to paint with an offset.
   const TransformPaintPropertyNode* PaintOffsetTranslation() const {
-    return paint_offset_translation_.Get();
+    return paint_offset_translation_.get();
   }
   const TransformPaintPropertyNode* Transform() const {
-    return transform_.Get();
+    return transform_.get();
   }
   const TransformPaintPropertyNode* Perspective() const {
-    return perspective_.Get();
+    return perspective_.get();
   }
   const TransformPaintPropertyNode* SvgLocalToBorderBoxTransform() const {
-    return svg_local_to_border_box_transform_.Get();
+    return svg_local_to_border_box_transform_.get();
   }
-  const ScrollPaintPropertyNode* Scroll() const { return scroll_.Get(); }
+  const ScrollPaintPropertyNode* Scroll() const { return scroll_.get(); }
   const TransformPaintPropertyNode* ScrollTranslation() const {
-    return scroll_translation_.Get();
+    return scroll_translation_.get();
   }
   const TransformPaintPropertyNode* ScrollbarPaintOffset() const {
-    return scrollbar_paint_offset_.Get();
+    return scrollbar_paint_offset_.get();
   }
 
   // The hierarchy of the effect subtree created by a LayoutObject is as
@@ -95,9 +95,9 @@
   // +-[ mask ]
   //       Isolated group for painting the CSS mask. This node will have
   //       SkBlendMode::kDstIn and shall paint last, i.e. after masked contents.
-  const EffectPaintPropertyNode* Effect() const { return effect_.Get(); }
-  const EffectPaintPropertyNode* Filter() const { return filter_.Get(); }
-  const EffectPaintPropertyNode* Mask() const { return mask_.Get(); }
+  const EffectPaintPropertyNode* Effect() const { return effect_.get(); }
+  const EffectPaintPropertyNode* Filter() const { return filter_.get(); }
+  const EffectPaintPropertyNode* Mask() const { return mask_.get(); }
 
   // The hierarchy of the clip subtree created by a LayoutObject is as follows:
   // [ fragment clip ]
@@ -125,18 +125,18 @@
   //       Clip created by CSS clip. Only exists if the current clip includes
   //       some clip that doesn't apply to our fixed position descendants.
   const ClipPaintPropertyNode* FragmentClip() const {
-    return fragment_clip_.Get();
+    return fragment_clip_.get();
   }
-  const ClipPaintPropertyNode* MaskClip() const { return mask_clip_.Get(); }
-  const ClipPaintPropertyNode* CssClip() const { return css_clip_.Get(); }
+  const ClipPaintPropertyNode* MaskClip() const { return mask_clip_.get(); }
+  const ClipPaintPropertyNode* CssClip() const { return css_clip_.get(); }
   const ClipPaintPropertyNode* CssClipFixedPosition() const {
-    return css_clip_fixed_position_.Get();
+    return css_clip_fixed_position_.get();
   }
   const ClipPaintPropertyNode* InnerBorderRadiusClip() const {
-    return inner_border_radius_clip_.Get();
+    return inner_border_radius_clip_.get();
   }
   const ClipPaintPropertyNode* OverflowClip() const {
-    return overflow_clip_.Get();
+    return overflow_clip_.get();
   }
 
   // This is the complete set of property nodes that can be used to paint the
diff --git a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp
index 2e0c4046..c5878b4 100644
--- a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp
@@ -76,7 +76,12 @@
           PaintInvalidationReason::kScrollControl);
     }
     should_invalidate_new_rect = true;
+  } else if (previous_visual_rect.IsEmpty()) {
+    DCHECK(new_visual_rect.IsEmpty());
+    // Do not issue an empty invalidation.
+    should_invalidate_new_rect = false;
   }
+
   if (should_invalidate_new_rect) {
     // TODO(crbug.com/732612): Implement partial raster invalidation for scroll
     // controls.
diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.cpp b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
index 343418b..6826a9a4 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayer.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
@@ -2139,8 +2139,8 @@
   // the lowest z-index.
   PaintLayer* hit_layer = HitTestChildren(
       kPositiveZOrderChildren, root_layer, result, hit_test_rect,
-      hit_test_location, local_transform_state.Get(),
-      z_offset_for_descendants_ptr, z_offset, unflattened_transform_state.Get(),
+      hit_test_location, local_transform_state.get(),
+      z_offset_for_descendants_ptr, z_offset, unflattened_transform_state.get(),
       depth_sort_descendants);
   if (hit_layer) {
     if (!depth_sort_descendants)
@@ -2151,8 +2151,8 @@
   // Now check our overflow objects.
   hit_layer = HitTestChildren(
       kNormalFlowChildren, root_layer, result, hit_test_rect, hit_test_location,
-      local_transform_state.Get(), z_offset_for_descendants_ptr, z_offset,
-      unflattened_transform_state.Get(), depth_sort_descendants);
+      local_transform_state.get(), z_offset_for_descendants_ptr, z_offset,
+      unflattened_transform_state.get(), depth_sort_descendants);
   if (hit_layer) {
     if (!depth_sort_descendants)
       return hit_layer;
@@ -2191,7 +2191,7 @@
                                     hit_test_location, kHitTestDescendants,
                                     inside_fragment_foreground_rect) &&
         IsHitCandidate(this, false, z_offset_for_contents_ptr,
-                       unflattened_transform_state.Get())) {
+                       unflattened_transform_state.get())) {
       if (result.GetHitTestRequest().ListBased())
         result.Append(temp_result);
       else
@@ -2210,8 +2210,8 @@
   // Now check our negative z-index children.
   hit_layer = HitTestChildren(
       kNegativeZOrderChildren, root_layer, result, hit_test_rect,
-      hit_test_location, local_transform_state.Get(),
-      z_offset_for_descendants_ptr, z_offset, unflattened_transform_state.Get(),
+      hit_test_location, local_transform_state.get(),
+      z_offset_for_descendants_ptr, z_offset, unflattened_transform_state.get(),
       depth_sort_descendants);
   if (hit_layer) {
     if (!depth_sort_descendants)
@@ -2232,7 +2232,7 @@
                                     hit_test_location, kHitTestSelf,
                                     inside_fragment_background_rect) &&
         IsHitCandidate(this, false, z_offset_for_contents_ptr,
-                       unflattened_transform_state.Get())) {
+                       unflattened_transform_state.get())) {
       if (result.IsRectBasedTest())
         result.Append(temp_result);
       else
@@ -2368,7 +2368,7 @@
 
   // Now do a hit test with the root layer shifted to be us.
   return HitTestLayer(this, container_layer, result, local_hit_test_rect,
-                      new_hit_test_location, true, new_transform_state.Get(),
+                      new_hit_test_location, true, new_transform_state.get(),
                       z_offset);
 }
 
@@ -2409,8 +2409,8 @@
     // to look for it manually like we do here, and give up on setting a local
     // point in the result, because that has bad implications for text selection
     // and caretRangeFromPoint(). See crbug.com/461791
-    if (!result.InnerNode())
-      result.SetInnerNode(e);
+    // This code path only ever hits in fullscreen tests.
+    result.SetInnerNode(e);
   }
   return true;
 }
@@ -2514,7 +2514,7 @@
       ToReferenceClipPathOperation(*clip_path_operation);
   SVGElement* element =
       reference_clip_path_operation.FindElement(target_node->GetTreeScope());
-  if (!isSVGClipPathElement(element) || !element->GetLayoutObject())
+  if (!IsSVGClipPathElement(element) || !element->GetLayoutObject())
     return false;
   LayoutSVGResourceClipper* clipper = ToLayoutSVGResourceClipper(
       ToLayoutSVGResourceContainer(element->GetLayoutObject()));
@@ -3229,6 +3229,15 @@
     return;
 
   if (AncestorOverflowLayer()) {
+    // If the previous AncestorOverflowLayer is the root and this object is a
+    // sticky viewport constrained object, it is no longer known to be
+    // constrained by the root.
+    if (AncestorOverflowLayer()->IsRootLayer() &&
+        GetLayoutObject().Style()->HasStickyConstrainedPosition()) {
+      GetLayoutObject().View()->GetFrameView()->RemoveViewportConstrainedObject(
+          GetLayoutObject());
+    }
+
     if (PaintLayerScrollableArea* ancestor_scrollable_area =
             AncestorOverflowLayer()->GetScrollableArea()) {
       // TODO(pdr): When slimming paint v2 is enabled, we will need to
@@ -3307,7 +3316,7 @@
 void PaintLayer::ComputeSelfHitTestRects(
     LayerHitTestRects& rects,
     TouchAction supported_fast_actions) const {
-  if (!size().IsEmpty()) {
+  if (!Size().IsEmpty()) {
     Vector<TouchActionRect> rect;
     TouchAction whitelisted_touch_action =
         GetLayoutObject().Style()->GetEffectiveTouchAction() &
diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.h b/third_party/WebKit/Source/core/paint/PaintLayer.h
index 0ca5c02..211c0a9f 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayer.h
+++ b/third_party/WebKit/Source/core/paint/PaintLayer.h
@@ -275,12 +275,22 @@
 #endif
     return location_;
   }
+
   // FIXME: size() should DCHECK(!needs_position_update_) as well, but that
   // fails in some tests, for example, fast/repaint/clipped-relative.html.
-  const IntSize& size() const { return size_; }
+  const IntSize& Size() const { return size_; }
+
   void SetSizeHackForLayoutTreeAsText(const IntSize& size) { size_ = size; }
 
-  LayoutRect Rect() const { return LayoutRect(Location(), LayoutSize(size())); }
+  LayoutRect Rect() const { return LayoutRect(Location(), LayoutSize(Size())); }
+
+  // For LayoutTreeAsText
+  LayoutRect RectIgnoringNeedsPositionUpdate() const {
+    return LayoutRect(location_, LayoutSize(size_));
+  }
+#if DCHECK_IS_ON()
+  bool NeedsPositionUpdate() const { return needs_position_update_; }
+#endif
 
   bool IsRootLayer() const { return is_root_layer_; }
 
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp b/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp
index d9536b8..8ace961 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp
@@ -149,7 +149,7 @@
   DCHECK(entry.overlay_scrollbar_clip_behavior ==
          context.overlay_scrollbar_clip_behavior);
 #endif
-  return entry.clip_rects.Get();
+  return entry.clip_rects.get();
 }
 
 ClipRects& PaintLayerClipper::StoreClipRectsInCache(
@@ -294,7 +294,7 @@
       layer_.ConvertToLayerCoords(context.root_layer, offset);
     }
   }
-  layer_bounds = LayoutRect(offset, LayoutSize(layer_.size()));
+  layer_bounds = LayoutRect(offset, LayoutSize(layer_.Size()));
 
   CalculateBackgroundClipRectWithGeometryMapper(context, fragment_data,
                                                 background_rect);
@@ -347,7 +347,7 @@
     offset = *offset_from_root;
   else
     layer_.ConvertToLayerCoords(context.root_layer, offset);
-  layer_bounds = LayoutRect(offset, LayoutSize(layer_.size()));
+  layer_bounds = LayoutRect(offset, LayoutSize(layer_.Size()));
 
   // Update the clip rects that will be passed to child layers.
   if (ShouldClipOverflow(context)) {
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
index cf5a5da..c4a4b33 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
@@ -508,7 +508,7 @@
       }
       PaintLayerFragment& fragment = layer_fragments.emplace_back();
       fragment.SetRects(
-          LayoutRect(offset_from_root, LayoutSize(paint_layer_.size())),
+          LayoutRect(offset_from_root, LayoutSize(paint_layer_.Size())),
           LayoutRect(LayoutRect::InfiniteIntRect()), foreground_clip);
     } else {
       paint_layer_for_fragments->CollectFragmentsForPaint(
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
index 23c9998..108c5cf 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
@@ -412,6 +412,7 @@
   if (GetScrollOffset() == new_offset)
     return;
 
+  bool offset_was_zero = scroll_offset_.IsZero();
   scroll_offset_ = new_offset;
 
   LocalFrame* frame = Box().GetFrame();
@@ -419,7 +420,6 @@
 
   LocalFrameView* frame_view = Box().GetFrameView();
   bool is_root_layer = Layer()->IsRootLayer();
-  bool is_main_frame = is_root_layer && frame->IsMainFrame();
 
   TRACE_EVENT1("devtools.timeline", "ScrollLayer", "data",
                InspectorScrollLayerEvent::Data(&Box()));
@@ -460,32 +460,7 @@
       page->GetChromeClient().ClearToolTip(*frame);
   }
 
-  bool requires_paint_invalidation = true;
-
-  if (Box().View()->Compositor()->InCompositingMode()) {
-    bool only_scrolled_composited_layers =
-        ScrollsOverflow() && Layer()->IsAllScrollingContentComposited() &&
-        Box().Style()->BackgroundLayers().Attachment() !=
-            kLocalBackgroundAttachment;
-
-    if (UsesCompositedScrolling() || only_scrolled_composited_layers)
-      requires_paint_invalidation = false;
-  }
-
-  if (!requires_paint_invalidation && is_root_layer) {
-    // Some special invalidations for the root layer.
-    frame_view->InvalidateBackgroundAttachmentFixedObjects();
-    if (frame_view->HasViewportConstrainedObjects()) {
-      if (!frame_view->InvalidateViewportConstrainedObjects())
-        requires_paint_invalidation = true;
-    }
-  }
-
-  // Just schedule a full paint invalidation of our object.
-  // FIXME: This invalidation will be unnecessary in slimming paint phase 2.
-  if (requires_paint_invalidation) {
-    Box().SetShouldDoFullPaintInvalidationIncludingNonCompositingDescendants();
-  }
+  InvalidatePaintForScrollOffsetChange(offset_was_zero);
 
   // The scrollOffsetTranslation paint property depends on the scroll offset.
   // (see: PaintPropertyTreeBuilder.updateProperties(LocalFrameView&,...) and
@@ -509,8 +484,7 @@
   if (is_root_layer) {
     frame_view->GetFrame().Loader().SaveScrollState();
     frame_view->DidChangeScrollOffset();
-    // TODO(szager): Clean up was_scrolled_by_user. (crbug.com/732955)
-    if (scroll_type == kCompositorScroll && is_main_frame) {
+    if (scroll_type == kCompositorScroll || scroll_type == kUserScroll) {
       if (DocumentLoader* document_loader = frame->Loader().GetDocumentLoader())
         document_loader->GetInitialScrollState().was_scrolled_by_user = true;
     }
@@ -525,6 +499,70 @@
   }
 }
 
+void PaintLayerScrollableArea::InvalidatePaintForScrollOffsetChange(
+    bool offset_was_zero) {
+  if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+    // "background-attachment: local" causes the background of this element to
+    // change position due to scroll so a paint invalidation is needed.
+    // TODO(pdr): This invalidation can be removed if the local background
+    // attachment is painted into the scrolling contents.
+    if (ScrollsOverflow() && Box().Style()->BackgroundLayers().Attachment() ==
+                                 kLocalBackgroundAttachment) {
+      Box().SetShouldDoFullPaintInvalidation();
+      return;
+    }
+
+    // TODO(pdr): If this is the root frame, descendants with fixed background
+    // attachments need to be invalidated.
+
+    // A scroll offset translation is still needed for overflow:hidden and there
+    // is an optimization to only create this translation node when scroll
+    // offset is non-zero (see: NeedsScrollOrScrollTranslation in
+    // PaintPropertyTreeBuilder.cpp). Because of this optimization, gaining or
+    // losing scroll offset can change whether a property exists and we have to
+    // invalidate paint to ensure this property gets picked up in BlockPainter.
+    bool needs_repaint_for_overflow_hidden =
+        !ScrollsOverflow() && (offset_was_zero || GetScrollOffset().IsZero());
+    // An invalidation is needed to ensure the interest rect is recalculated
+    // so newly-scrolled-to items are repainted. We may want to set a flag on
+    // PaintLayer to just check for interest rect changes instead of doing a
+    // full repaint.
+    bool needs_repaint_for_interest_rect = true;
+    if (needs_repaint_for_overflow_hidden || needs_repaint_for_interest_rect) {
+      Layer()->SetNeedsRepaint();
+      return;
+    }
+
+    return;
+  }
+
+  bool requires_paint_invalidation = true;
+
+  LocalFrameView* frame_view = Box().GetFrameView();
+  bool is_root_layer = Layer()->IsRootLayer();
+  if (Box().View()->Compositor()->InCompositingMode()) {
+    bool only_scrolled_composited_layers =
+        ScrollsOverflow() && Layer()->IsAllScrollingContentComposited() &&
+        Box().Style()->BackgroundLayers().Attachment() !=
+            kLocalBackgroundAttachment;
+
+    if (UsesCompositedScrolling() || only_scrolled_composited_layers)
+      requires_paint_invalidation = false;
+  }
+
+  if (!requires_paint_invalidation && is_root_layer) {
+    // Some special invalidations for the root layer.
+    frame_view->InvalidateBackgroundAttachmentFixedObjects();
+    if (frame_view->HasViewportConstrainedObjects()) {
+      if (!frame_view->InvalidateViewportConstrainedObjects())
+        requires_paint_invalidation = true;
+    }
+  }
+
+  if (requires_paint_invalidation)
+    Box().SetShouldDoFullPaintInvalidationIncludingNonCompositingDescendants();
+}
+
 IntSize PaintLayerScrollableArea::ScrollOffsetInt() const {
   return FlooredIntSize(scroll_offset_);
 }
@@ -574,7 +612,7 @@
 LayoutRect PaintLayerScrollableArea::LayoutContentRect(
     IncludeScrollbarsInRect scrollbar_inclusion) const {
   // LayoutContentRect is conceptually the same as the box's client rect.
-  LayoutSize layer_size = LayoutSize(Layer()->size());
+  LayoutSize layer_size = LayoutSize(Layer()->Size());
   LayoutUnit border_width = Box().BorderWidth();
   LayoutUnit border_height = Box().BorderHeight();
   LayoutUnit horizontal_scrollbar_height, vertical_scrollbar_width;
@@ -902,8 +940,8 @@
   PositionOverflowControls();
 
   Node* node = Box().GetNode();
-  if (isHTMLSelectElement(node))
-    toHTMLSelectElement(node)->ScrollToOptionAfterLayout(*this);
+  if (auto* select = ToHTMLSelectElementOrNull(node))
+    select->ScrollToOptionAfterLayout(*this);
 }
 
 void PaintLayerScrollableArea::ClampScrollOffsetAfterOverflowChange() {
@@ -1188,7 +1226,7 @@
 IntSize PaintLayerScrollableArea::ScrollbarOffset(
     const Scrollbar& scrollbar) const {
   if (&scrollbar == VerticalScrollbar()) {
-    return IntSize(VerticalScrollbarStart(0, Layer()->size().Width()),
+    return IntSize(VerticalScrollbarStart(0, Layer()->Size().Width()),
                    Box().BorderTop().ToInt());
   }
 
@@ -1494,7 +1532,7 @@
   int resize_control_size = max(resize_control_rect.Height(), 0);
   if (HasVerticalScrollbar() &&
       VerticalScrollbar()->ShouldParticipateInHitTesting()) {
-    LayoutRect v_bar_rect(VerticalScrollbarStart(0, Layer()->size().Width()),
+    LayoutRect v_bar_rect(VerticalScrollbarStart(0, Layer()->Size().Width()),
                           Box().BorderTop().ToInt(),
                           VerticalScrollbar()->ScrollbarThickness(),
                           VisibleContentRect(kIncludeScrollbars).Height() -
@@ -1571,7 +1609,7 @@
 
   IntPoint local_point =
       RoundedIntPoint(Box().AbsoluteToLocal(absolute_point, kUseTransforms));
-  IntRect local_bounds(IntPoint(), Layer()->size());
+  IntRect local_bounds(IntPoint(), Layer()->Size());
   return ResizerCornerRect(local_bounds, resizer_hit_test_type)
       .Contains(local_point);
 }
@@ -1661,7 +1699,7 @@
   // left corner.
   // FIXME: This assumes the location is 0, 0. Is this guaranteed to always be
   // the case?
-  IntSize element_size = Layer()->size();
+  IntSize element_size = Layer()->Size();
   if (Box().ShouldPlaceBlockDirectionScrollbarOnLogicalLeft())
     element_size.SetWidth(0);
   IntPoint resizer_point = IntPoint(element_size);
@@ -1906,10 +1944,10 @@
 static bool LayerNodeMayNeedCompositedScrolling(const PaintLayer* layer) {
   // Don't force composite scroll for select or text input elements.
   if (Node* node = layer->GetLayoutObject().GetNode()) {
-    if (isHTMLSelectElement(node))
+    if (IsHTMLSelectElement(node))
       return false;
     if (TextControlElement* text_control = EnclosingTextControl(node)) {
-      if (isHTMLInputElement(text_control)) {
+      if (IsHTMLInputElement(text_control)) {
         return false;
       }
     }
@@ -1933,7 +1971,7 @@
   if (!layer->ScrollsOverflow())
     return false;
 
-  if (layer->size().IsEmpty())
+  if (layer->Size().IsEmpty())
     return false;
 
   // This is for an experiment aiming at memory save by not compositing certain
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h
index 69afa22..80a087a 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h
@@ -512,6 +512,7 @@
   void UpdateScrollbarEnabledState();
 
   void UpdateScrollOffset(const ScrollOffset&, ScrollType) override;
+  void InvalidatePaintForScrollOffsetChange(bool offset_was_zero);
 
   int VerticalScrollbarStart(int min_x, int max_x) const;
   int HorizontalScrollbarStart(int min_x) const;
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp
index 15d4cb4..d44905b 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp
@@ -212,7 +212,7 @@
 }
 
 TEST_F(PaintLayerScrollableAreaTest, OpaqueContainedLayersPromoted) {
-  RuntimeEnabledFeatures::SetCompositeOpaqueScrollersEnabled(true);
+  ScopedCompositeOpaqueScrollersForTest composite_opaque_scrollers(true);
 
   SetBodyInnerHTML(
       "<style>"
@@ -238,7 +238,7 @@
 // Promoting the scroller would also require promoting the positioned div
 // which would lose subpixel anti-aliasing due to its transparent background.
 TEST_F(PaintLayerScrollableAreaTest, NonContainedLayersNotPromoted) {
-  RuntimeEnabledFeatures::SetCompositeOpaqueScrollersEnabled(true);
+  ScopedCompositeOpaqueScrollersForTest composite_opaque_scrollers(true);
 
   SetBodyInnerHTML(
       "<style>"
@@ -264,7 +264,7 @@
 }
 
 TEST_F(PaintLayerScrollableAreaTest, TransparentLayersNotPromoted) {
-  RuntimeEnabledFeatures::SetCompositeOpaqueScrollersEnabled(true);
+  ScopedCompositeOpaqueScrollersForTest composite_opaque_scrollers(true);
 
   SetBodyInnerHTML(
       "<style>"
@@ -286,7 +286,7 @@
 }
 
 TEST_F(PaintLayerScrollableAreaTest, OpaqueLayersDepromotedOnStyleChange) {
-  RuntimeEnabledFeatures::SetCompositeOpaqueScrollersEnabled(true);
+  ScopedCompositeOpaqueScrollersForTest composite_opaque_scrollers(true);
 
   SetBodyInnerHTML(
       "<style>"
@@ -316,7 +316,7 @@
 }
 
 TEST_F(PaintLayerScrollableAreaTest, OpaqueLayersPromotedOnStyleChange) {
-  RuntimeEnabledFeatures::SetCompositeOpaqueScrollersEnabled(true);
+  ScopedCompositeOpaqueScrollersForTest composite_opaque_scrollers(true);
 
   SetBodyInnerHTML(
       "<style>"
@@ -459,7 +459,8 @@
 TEST_F(PaintLayerScrollableAreaTest, SmallScrollerPromotionTest) {
   GetDocument().GetFrame()->GetSettings()->SetPreferCompositingToLCDTextEnabled(
       true);
-  RuntimeEnabledFeatures::SetSkipCompositingSmallScrollersEnabled(true);
+  ScopedSkipCompositingSmallScrollersForTest skip_compositing_small_scrollers(
+      true);
   SetBodyInnerHTML(
       "<!DOCTYPE html>"
       "<style>"
@@ -482,7 +483,8 @@
 TEST_F(PaintLayerScrollableAreaTest, LargeScrollerPromotionTest) {
   GetDocument().GetFrame()->GetSettings()->SetPreferCompositingToLCDTextEnabled(
       false);
-  RuntimeEnabledFeatures::SetSkipCompositingSmallScrollersEnabled(true);
+  ScopedSkipCompositingSmallScrollersForTest skip_compositing_small_scrollers(
+      true);
   SetBodyInnerHTML(
       "<!DOCTYPE html>"
       "<style>"
@@ -521,7 +523,8 @@
        SmallScrollerWithSeparateCompositingReasonPromotionTest) {
   GetDocument().GetFrame()->GetSettings()->SetPreferCompositingToLCDTextEnabled(
       true);
-  RuntimeEnabledFeatures::SetSkipCompositingSmallScrollersEnabled(true);
+  ScopedSkipCompositingSmallScrollersForTest skip_compositing_small_scrollers(
+      true);
   SetBodyInnerHTML(
       "<!DOCTYPE html>"
       "<style>"
@@ -715,7 +718,7 @@
 }
 
 TEST_F(PaintLayerScrollableAreaTest, IncludeOverlayScrollbarsInVisibleWidth) {
-  RuntimeEnabledFeatures::SetOverlayScrollbarsEnabled(false);
+  ScopedOverlayScrollbarsForTest overlay_scrollbars(false);
   SetBodyInnerHTML(
       "<style>"
       "#scroller { overflow: overlay; height: 100px; width: 100px; }"
@@ -733,7 +736,7 @@
 }
 
 TEST_F(PaintLayerScrollableAreaTest, ShowAutoScrollbarsForVisibleContent) {
-  RuntimeEnabledFeatures::SetOverlayScrollbarsEnabled(false);
+  ScopedOverlayScrollbarsForTest overlay_scrollbars(false);
   SetBodyInnerHTML(
       "<style>"
       "#outerDiv {"
@@ -762,7 +765,7 @@
 }
 
 TEST_F(PaintLayerScrollableAreaTest, FloatOverflowInRtlContainer) {
-  RuntimeEnabledFeatures::SetOverlayScrollbarsEnabled(false);
+  ScopedOverlayScrollbarsForTest overlay_scrollbars(false);
   SetBodyInnerHTML(
       "<!DOCTYPE html>"
       "<style>"
@@ -786,4 +789,129 @@
   ASSERT_TRUE(scrollable_area);
   EXPECT_FALSE(scrollable_area->HasHorizontalScrollbar());
 }
+
+TEST_F(PaintLayerScrollableAreaTest,
+       SlimmingPaintV2OverflowHiddenScrollOffsetInvalidation) {
+  ScopedSlimmingPaintV2ForTest enabler(true);
+
+  SetBodyInnerHTML(
+      "<style>"
+      "#scroller {"
+      "  overflow: hidden;"
+      "  height: 200px;"
+      "  width: 200px;"
+      "}"
+      "</style>"
+      "<div id='scroller'>"
+      "  <div id='forceScroll' style='height: 2000px;'></div>"
+      "</div>");
+  GetDocument().View()->UpdateAllLifecyclePhases();
+
+  auto* scroller = GetLayoutObjectByElementId("scroller");
+  auto* scrollable_area = ToLayoutBoxModelObject(scroller)->GetScrollableArea();
+
+  const auto* properties = scroller->FirstFragment()->PaintProperties();
+
+  // No scroll offset translation is needed when scroll offset is zero.
+  EXPECT_EQ(nullptr, properties->ScrollTranslation());
+  EXPECT_EQ(FloatSize(0, 0), scrollable_area->GetScrollOffset());
+
+  // Going from zero scroll offset to non-zero may require a new paint property
+  // and should invalidate paint and paint properties.
+  scrollable_area->SetScrollOffset(ScrollOffset(0, 1), kProgrammaticScroll);
+  EXPECT_TRUE(scroller->PaintingLayer()->NeedsRepaint());
+  EXPECT_TRUE(scroller->NeedsPaintPropertyUpdate());
+  GetDocument().View()->UpdateAllLifecyclePhases();
+
+  // A scroll offset translation is needed when scroll offset is non-zero.
+  EXPECT_EQ(FloatSize(0, 1), scrollable_area->GetScrollOffset());
+  EXPECT_NE(nullptr, properties->ScrollTranslation());
+
+  // A property update is needed when scroll offset changes.
+  scrollable_area->SetScrollOffset(ScrollOffset(0, 2), kProgrammaticScroll);
+  EXPECT_TRUE(scroller->NeedsPaintPropertyUpdate());
+  GetDocument().View()->UpdateAllLifecyclePhases();
+
+  // A scroll offset translation is still needed when scroll offset is non-zero.
+  EXPECT_EQ(FloatSize(0, 2), scrollable_area->GetScrollOffset());
+  EXPECT_NE(nullptr, properties->ScrollTranslation());
+
+  // Going from non-zero scroll offset to zero may require destroying a paint
+  // property and should invalidate paint and paint properties.
+  scrollable_area->SetScrollOffset(ScrollOffset(0, 0), kProgrammaticScroll);
+  EXPECT_TRUE(scroller->PaintingLayer()->NeedsRepaint());
+  EXPECT_TRUE(scroller->NeedsPaintPropertyUpdate());
+  GetDocument().View()->UpdateAllLifecyclePhases();
+
+  // No scroll offset translation is needed when scroll offset is zero.
+  EXPECT_EQ(nullptr, properties->ScrollTranslation());
+  EXPECT_EQ(FloatSize(0, 0), scrollable_area->GetScrollOffset());
+}
+
+TEST_F(PaintLayerScrollableAreaTest, SlimmingPaintV2ScrollDoesNotInvalidate) {
+  ScopedSlimmingPaintV2ForTest enabler(true);
+
+  SetBodyInnerHTML(
+      "<style>"
+      "  #scroller {"
+      "    overflow: scroll;"
+      "    height: 200px;"
+      "    width: 200px;"
+      "    background: linear-gradient(black, white);"
+      "  }"
+      "</style>"
+      "<div id='scroller'>"
+      "  <div id='forceScroll' style='height: 2000px;'></div>"
+      "</div>");
+  GetDocument().View()->UpdateAllLifecyclePhases();
+
+  auto* scroller = GetLayoutObjectByElementId("scroller");
+  auto* scrollable_area = ToLayoutBoxModelObject(scroller)->GetScrollableArea();
+
+  const auto* properties = scroller->FirstFragment()->PaintProperties();
+  // Scroll offset translation is needed even when scroll offset is zero.
+  EXPECT_NE(nullptr, properties->ScrollTranslation());
+  EXPECT_EQ(FloatSize(0, 0), scrollable_area->GetScrollOffset());
+
+  // Changing the scroll offset should not require paint invalidation.
+  scrollable_area->SetScrollOffset(ScrollOffset(0, 1), kProgrammaticScroll);
+  EXPECT_FALSE(scroller->ShouldDoFullPaintInvalidation());
+  EXPECT_TRUE(scroller->NeedsPaintPropertyUpdate());
+  GetDocument().View()->UpdateAllLifecyclePhases();
+  EXPECT_EQ(FloatSize(0, 1), scrollable_area->GetScrollOffset());
+  EXPECT_NE(nullptr, properties->ScrollTranslation());
+}
+
+TEST_F(PaintLayerScrollableAreaTest,
+       SlimmingPaintV2ScrollWithLocalBackgroundAttachment) {
+  ScopedSlimmingPaintV2ForTest enabler(true);
+
+  SetBodyInnerHTML(
+      "<style>"
+      "  #scroller {"
+      "    overflow: scroll;"
+      "    height: 200px;"
+      "    width: 200px;"
+      "    background: linear-gradient(black, white);"
+      "    background-attachment: local;"
+      "  }"
+      "</style>"
+      "<div id='scroller'>"
+      "  <div id='forceScroll' style='height: 2000px;'></div>"
+      "</div>");
+  GetDocument().View()->UpdateAllLifecyclePhases();
+
+  auto* scroller = GetLayoutObjectByElementId("scroller");
+  auto* scrollable_area = ToLayoutBoxModelObject(scroller)->GetScrollableArea();
+
+  // Programmatically changing the scroll offset should require paint
+  // invalidation due to background attachment.
+  scrollable_area->SetScrollOffset(ScrollOffset(0, 1), kProgrammaticScroll);
+  EXPECT_TRUE(scroller->ShouldDoFullPaintInvalidation());
+  EXPECT_TRUE(scroller->NeedsPaintPropertyUpdate());
+  GetDocument().View()->UpdateAllLifecyclePhases();
+  EXPECT_EQ(FloatSize(0, 1), scrollable_area->GetScrollOffset());
+  const auto* properties = scroller->FirstFragment()->PaintProperties();
+  EXPECT_NE(nullptr, properties->ScrollTranslation());
+}
 }
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp
index d788d3a..d2844c6 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp
@@ -100,7 +100,7 @@
 TEST_P(PaintLayerTest, RootLayerScrollBounds) {
   if (!RuntimeEnabledFeatures::RootLayerScrollingEnabled())
     return;
-  RuntimeEnabledFeatures::SetOverlayScrollbarsEnabled(false);
+  ScopedOverlayScrollbarsForTest overlay_scrollbars(false);
 
   SetBodyInnerHTML(
       "<style> body { width: 1000px; height: 1000px; margin: 0 } </style>");
@@ -263,6 +263,12 @@
 }
 
 TEST_P(PaintLayerTest, NonCompositedScrollingNeedsRepaint) {
+  // SPV2 scrolling raster invalidation decisions are made in
+  // ContentLayerClientImpl::GenerateRasterInvalidations through
+  // PaintArtifactCompositor.
+  if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
+    return;
+
   SetBodyInnerHTML(
       "<div id='scroll' style='width: 100px; height: 100px; overflow: scroll'>"
       "  <div id='content' style='position: relative; background: blue;"
@@ -1052,7 +1058,7 @@
       ComputedStyle::Clone(target_object->StyleRef());
   ComputedStyle* new_style = target_object->MutableStyle();
   new_style->SetHasCurrentTransformAnimation(true);
-  target_paint_layer->UpdateTransform(old_style.Get(), *new_style);
+  target_paint_layer->UpdateTransform(old_style.get(), *new_style);
 
   EXPECT_NE(nullptr, target_paint_layer->Transform());
 }
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
index 5ee880e..5b0f2ce 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -79,28 +79,46 @@
   return true;
 }
 
+static MainThreadScrollingReasons GetMainThreadScrollingReasons(
+    const LocalFrameView& frame_view,
+    MainThreadScrollingReasons ancestor_reasons) {
+  auto reasons = ancestor_reasons;
+  if (!frame_view.GetFrame().GetSettings()->GetThreadedScrollingEnabled())
+    reasons |= MainThreadScrollingReason::kThreadedScrollingDisabled;
+  if (frame_view.HasBackgroundAttachmentFixedObjects())
+    reasons |= MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects;
+  return reasons;
+}
+
 // True if a new property was created or a main thread scrolling reason changed
 // (which can affect descendants), false if an existing one was updated.
-static bool UpdateScroll(
-    LocalFrameView& frame_view,
-    RefPtr<const ScrollPaintPropertyNode> parent,
-    const IntSize& clip,
-    const IntSize& bounds,
-    bool user_scrollable_horizontal,
-    bool user_scrollable_vertical,
-    MainThreadScrollingReasons main_thread_scrolling_reasons) {
+static bool UpdateScroll(LocalFrameView& frame_view,
+                         PaintPropertyTreeBuilderFragmentContext& context) {
   DCHECK(!RuntimeEnabledFeatures::RootLayerScrollingEnabled());
+  IntRect container_rect(IntPoint(), frame_view.VisibleContentSize());
+  IntRect contents_rect(-frame_view.ScrollOrigin(), frame_view.ContentsSize());
+  bool user_scrollable_horizontal =
+      frame_view.UserInputScrollable(kHorizontalScrollbar);
+  bool user_scrollable_vertical =
+      frame_view.UserInputScrollable(kVerticalScrollbar);
+  auto ancestor_reasons =
+      context.current.scroll->GetMainThreadScrollingReasons();
+  auto main_thread_scrolling_reasons =
+      GetMainThreadScrollingReasons(frame_view, ancestor_reasons);
   auto element_id = frame_view.GetCompositorElementId();
+
   if (auto* existing_scroll = frame_view.ScrollNode()) {
     auto existing_reasons = existing_scroll->GetMainThreadScrollingReasons();
-    existing_scroll->Update(
-        std::move(parent), IntPoint(), clip, bounds, user_scrollable_horizontal,
-        user_scrollable_vertical, main_thread_scrolling_reasons, element_id);
+    existing_scroll->Update(context.current.scroll, container_rect,
+                            contents_rect, user_scrollable_horizontal,
+                            user_scrollable_vertical,
+                            main_thread_scrolling_reasons, element_id);
     return existing_reasons != main_thread_scrolling_reasons;
   }
   frame_view.SetScrollNode(ScrollPaintPropertyNode::Create(
-      std::move(parent), IntPoint(), clip, bounds, user_scrollable_horizontal,
-      user_scrollable_vertical, main_thread_scrolling_reasons, element_id));
+      context.current.scroll, container_rect, contents_rect,
+      user_scrollable_horizontal, user_scrollable_vertical,
+      main_thread_scrolling_reasons, element_id));
   return true;
 }
 
@@ -124,17 +142,6 @@
   return true;
 }
 
-static MainThreadScrollingReasons GetMainThreadScrollingReasons(
-    const LocalFrameView& frame_view,
-    MainThreadScrollingReasons ancestor_reasons) {
-  auto reasons = ancestor_reasons;
-  if (!frame_view.GetFrame().GetSettings()->GetThreadedScrollingEnabled())
-    reasons |= MainThreadScrollingReason::kThreadedScrollingDisabled;
-  if (frame_view.HasBackgroundAttachmentFixedObjects())
-    reasons |= MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects;
-  return reasons;
-}
-
 void PaintPropertyTreeBuilder::UpdateProperties(
     LocalFrameView& frame_view,
     PaintPropertyTreeBuilderContext& full_context) {
@@ -179,21 +186,7 @@
         content_clip, full_context.clip_changed);
 
     if (frame_view.IsScrollable()) {
-      IntSize scroll_clip = frame_view.VisibleContentSize();
-      IntSize scroll_bounds = frame_view.ContentsSize();
-      bool user_scrollable_horizontal =
-          frame_view.UserInputScrollable(kHorizontalScrollbar);
-      bool user_scrollable_vertical =
-          frame_view.UserInputScrollable(kVerticalScrollbar);
-
-      auto ancestor_reasons =
-          context.current.scroll->GetMainThreadScrollingReasons();
-      auto reasons =
-          GetMainThreadScrollingReasons(frame_view, ancestor_reasons);
-
-      full_context.force_subtree_update |= UpdateScroll(
-          frame_view, context.current.scroll, scroll_clip, scroll_bounds,
-          user_scrollable_horizontal, user_scrollable_vertical, reasons);
+      full_context.force_subtree_update |= UpdateScroll(frame_view, context);
     } else if (frame_view.ScrollNode()) {
       // Ensure pre-existing properties are cleared if there is no scrolling.
       frame_view.SetScrollNode(nullptr);
@@ -1098,11 +1091,19 @@
       // The container bounds are snapped to integers to match the equivalent
       // bounds on cc::ScrollNode. The offset is snapped to match the current
       // integer offsets used in CompositedLayerMapping.
-      auto clip_rect = PixelSnappedIntRect(
+      auto container_rect = PixelSnappedIntRect(
           box.OverflowClipRect(context.current.paint_offset));
-      IntPoint bounds_offset = clip_rect.Location();
-      IntSize container_bounds = clip_rect.Size();
-      IntSize scroll_bounds = scrollable_area->ContentsSize();
+
+      IntRect contents_rect(-scrollable_area->ScrollOrigin(),
+                            scrollable_area->ContentsSize());
+      contents_rect.MoveBy(container_rect.Location());
+      // In flipped blocks writing mode, if there is scrollbar on the right,
+      // we move the contents to the left with extra amount of ScrollTranslation
+      // (-VerticalScrollbarWidth, 0). As contents_rect is in the space of
+      // ScrollTranslation, we need to compensate the extra ScrollTranslation
+      // to get correct contents_rect origin.
+      if (box.HasFlippedBlocksWritingMode())
+        contents_rect.Move(box.VerticalScrollbarWidth(), 0);
 
       bool user_scrollable_horizontal =
           scrollable_area->UserInputScrollable(kHorizontalScrollbar);
@@ -1124,9 +1125,9 @@
 
       // TODO(pdr): Set the correct compositing reasons here.
       auto result = properties.UpdateScroll(
-          context.current.scroll, bounds_offset, container_bounds,
-          scroll_bounds, user_scrollable_horizontal, user_scrollable_vertical,
-          reasons, element_id);
+          context.current.scroll, container_rect, contents_rect,
+          user_scrollable_horizontal, user_scrollable_vertical, reasons,
+          element_id);
       force_subtree_update |= result.NewNodeCreated();
     } else {
       // Ensure pre-existing properties are cleared.
@@ -1608,8 +1609,11 @@
                     full_context.force_subtree_update);
     UpdateCssClip(object, *properties, fragment_context,
                   full_context.force_subtree_update, full_context.clip_changed);
-    UpdateEffect(object, *properties, fragment_context,
-                 full_context.force_subtree_update, full_context.clip_changed);
+    if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
+      UpdateEffect(object, *properties, fragment_context,
+                   full_context.force_subtree_update,
+                   full_context.clip_changed);
+    }
     UpdateFilter(object, *properties, fragment_context,
                  full_context.force_subtree_update);
   }
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
index 604cdb2..309d4b1 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
@@ -220,8 +220,8 @@
             scroller_properties->OverflowClip()->LocalTransformSpace());
   const auto* scroll = scroller_properties->ScrollTranslation()->ScrollNode();
   EXPECT_EQ(FrameScroll(), scroll->Parent());
-  EXPECT_EQ(FloatSize(413, 317), scroll->ContainerBounds());
-  EXPECT_EQ(FloatSize(660, 10200), scroll->Bounds());
+  EXPECT_EQ(IntRect(0, 0, 413, 317), scroll->ContainerRect());
+  EXPECT_EQ(IntRect(0, 0, 660, 10200), scroll->ContentsRect());
   EXPECT_FALSE(scroll->UserScrollableHorizontal());
   EXPECT_TRUE(scroll->UserScrollableVertical());
   EXPECT_EQ(FloatSize(120, 340), scroller_properties->PaintOffsetTranslation()
@@ -271,6 +271,63 @@
                           frame_view->GetLayoutView());
 }
 
+TEST_P(PaintPropertyTreeBuilderTest, OverflowScrollVerticalRL) {
+  SetBodyInnerHTML(
+      "<style>::-webkit-scrollbar {width: 15px; height: 15px}</style>"
+      "<div id='scroller'"
+      "     style='width: 100px; height: 100px; overflow: scroll; "
+      "            writing-mode: vertical-rl; border: 10px solid blue'>"
+      "  <div style='width: 400px; height: 400px'></div>"
+      "</div>");
+
+  const auto* properties = PaintPropertiesForElement("scroller");
+  const auto* overflow_clip = properties->OverflowClip();
+  const auto* scroll_translation = properties->ScrollTranslation();
+  const auto* scroll = properties->Scroll();
+
+  EXPECT_EQ(TransformationMatrix().Translate(-15, 0),
+            scroll_translation->Matrix());
+  EXPECT_EQ(scroll, scroll_translation->ScrollNode());
+  // 10: border width. 85: container client size (== 100 - scrollbar width).
+  EXPECT_EQ(IntRect(10, 10, 85, 85), scroll->ContainerRect());
+  // The content is placed at (-290, 10) so that its right edge aligns with the
+  // right edge of the container's client box, with the initial
+  // ScrollTranslation applied.
+  EXPECT_EQ(IntRect(-290, 10, 400, 400), scroll->ContentsRect());
+
+  EXPECT_EQ(FrameContentClip(), overflow_clip->Parent());
+  EXPECT_EQ(properties->PaintOffsetTranslation(),
+            overflow_clip->LocalTransformSpace());
+  EXPECT_EQ(FloatRoundedRect(10, 10, 85, 85), overflow_clip->ClipRect());
+}
+
+TEST_P(PaintPropertyTreeBuilderTest, OverflowScrollRTL) {
+  SetBodyInnerHTML(
+      "<style>::-webkit-scrollbar {width: 15px; height: 15px}</style>"
+      "<div id='scroller'"
+      "     style='width: 100px; height: 100px; overflow: scroll; "
+      "            direction: rtl; border: 10px solid blue'>"
+      "  <div style='width: 400px; height: 400px'></div>"
+      "</div>");
+
+  const auto* properties = PaintPropertiesForElement("scroller");
+  const auto* overflow_clip = properties->OverflowClip();
+  const auto* scroll_translation = properties->ScrollTranslation();
+  const auto* scroll = properties->Scroll();
+
+  EXPECT_EQ(TransformationMatrix(), scroll_translation->Matrix());
+  EXPECT_EQ(scroll, scroll_translation->ScrollNode());
+  // 25: border width (10) + scrollbar (on the left) width (15).
+  // 85: container client size (== 100 - scrollbar width).
+  EXPECT_EQ(IntRect(25, 10, 85, 85), scroll->ContainerRect());
+  EXPECT_EQ(IntRect(-290, 10, 400, 400), scroll->ContentsRect());
+
+  EXPECT_EQ(FrameContentClip(), overflow_clip->Parent());
+  EXPECT_EQ(properties->PaintOffsetTranslation(),
+            overflow_clip->LocalTransformSpace());
+  EXPECT_EQ(FloatRoundedRect(25, 10, 85, 85), overflow_clip->ClipRect());
+}
+
 TEST_P(PaintPropertyTreeBuilderTest, FrameScrollingTraditional) {
   SetBodyInnerHTML("<style> body { height: 10000px; } </style>");
 
@@ -2855,10 +2912,10 @@
   EXPECT_TRUE(overflow_a_scroll_node->Parent()->IsRoot());
   EXPECT_EQ(TransformationMatrix().Translate(0, -37),
             scroll_a_translation->Matrix());
-  EXPECT_EQ(IntSize(5, 3), overflow_a_scroll_node->ContainerBounds());
+  EXPECT_EQ(IntRect(0, 0, 5, 3), overflow_a_scroll_node->ContainerRect());
   // 107 is the forceScroll element plus the height of the overflow scroll child
   // (overflowB).
-  EXPECT_EQ(IntSize(9, 107), overflow_a_scroll_node->Bounds());
+  EXPECT_EQ(IntRect(0, 0, 9, 107), overflow_a_scroll_node->ContentsRect());
   EXPECT_TRUE(overflow_a_scroll_node->UserScrollableHorizontal());
   EXPECT_TRUE(overflow_a_scroll_node->UserScrollableVertical());
 
@@ -2872,8 +2929,8 @@
   EXPECT_EQ(overflow_a_scroll_node, overflow_b_scroll_node->Parent());
   EXPECT_EQ(TransformationMatrix().Translate(0, -41),
             scroll_b_translation->Matrix());
-  EXPECT_EQ(IntSize(9, 7), overflow_b_scroll_node->ContainerBounds());
-  EXPECT_EQ(IntSize(9, 100), overflow_b_scroll_node->Bounds());
+  EXPECT_EQ(IntRect(0, 0, 9, 7), overflow_b_scroll_node->ContainerRect());
+  EXPECT_EQ(IntRect(0, 0, 9, 100), overflow_b_scroll_node->ContentsRect());
   EXPECT_TRUE(overflow_b_scroll_node->UserScrollableHorizontal());
   EXPECT_TRUE(overflow_b_scroll_node->UserScrollableVertical());
 }
@@ -2941,11 +2998,11 @@
       overflow_scroll_properties->ScrollTranslation()->ScrollNode()->Parent());
   EXPECT_EQ(TransformationMatrix().Translate(0, -37),
             scroll_translation->Matrix());
-  EXPECT_EQ(IntSize(5, 3), overflow_scroll_node->ContainerBounds());
+  EXPECT_EQ(IntRect(0, 0, 5, 3), overflow_scroll_node->ContainerRect());
   // The height should be 4000px because the (dom-order) overflow children are
   // positioned and do not contribute to the height. Only the 4000px
   // "forceScroll" height is present.
-  EXPECT_EQ(IntSize(5, 4000), overflow_scroll_node->Bounds());
+  EXPECT_EQ(IntRect(0, 0, 5, 4000), overflow_scroll_node->ContentsRect());
 
   const ObjectPaintProperties* abspos_overflow_scroll_properties =
       abspos_overflow->GetLayoutObject()->FirstFragment()->PaintProperties();
@@ -2957,8 +3014,9 @@
   EXPECT_EQ(FrameScroll(), abspos_overflow_scroll_node->Parent());
   EXPECT_EQ(TransformationMatrix().Translate(0, -41),
             abspos_scroll_translation->Matrix());
-  EXPECT_EQ(IntSize(9, 7), abspos_overflow_scroll_node->ContainerBounds());
-  EXPECT_EQ(IntSize(9, 4000), abspos_overflow_scroll_node->Bounds());
+  EXPECT_EQ(IntRect(0, 0, 9, 7), abspos_overflow_scroll_node->ContainerRect());
+  EXPECT_EQ(IntRect(0, 0, 9, 4000),
+            abspos_overflow_scroll_node->ContentsRect());
 
   const ObjectPaintProperties* fixed_overflow_scroll_properties =
       fixed_overflow->GetLayoutObject()->FirstFragment()->PaintProperties();
@@ -2970,8 +3028,9 @@
   EXPECT_TRUE(fixed_overflow_scroll_node->Parent()->IsRoot());
   EXPECT_EQ(TransformationMatrix().Translate(0, -43),
             fixed_scroll_translation->Matrix());
-  EXPECT_EQ(IntSize(13, 11), fixed_overflow_scroll_node->ContainerBounds());
-  EXPECT_EQ(IntSize(13, 4000), fixed_overflow_scroll_node->Bounds());
+  EXPECT_EQ(IntRect(0, 0, 13, 11), fixed_overflow_scroll_node->ContainerRect());
+  EXPECT_EQ(IntRect(0, 0, 13, 4000),
+            fixed_overflow_scroll_node->ContentsRect());
 }
 
 TEST_P(PaintPropertyTreeBuilderTest, NestedPositionedScrollProperties) {
@@ -3024,10 +3083,10 @@
   EXPECT_TRUE(overflow_a_scroll_node->Parent()->IsRoot());
   EXPECT_EQ(TransformationMatrix().Translate(0, -37),
             scroll_a_translation->Matrix());
-  EXPECT_EQ(IntSize(20, 20), overflow_a_scroll_node->ContainerBounds());
+  EXPECT_EQ(IntRect(0, 0, 20, 20), overflow_a_scroll_node->ContainerRect());
   // 100 is the forceScroll element's height because the overflow child does not
   // contribute to the height.
-  EXPECT_EQ(IntSize(20, 100), overflow_a_scroll_node->Bounds());
+  EXPECT_EQ(IntRect(0, 0, 20, 100), overflow_a_scroll_node->ContentsRect());
   EXPECT_TRUE(overflow_a_scroll_node->UserScrollableHorizontal());
   EXPECT_TRUE(overflow_a_scroll_node->UserScrollableVertical());
 
@@ -3041,8 +3100,8 @@
   EXPECT_EQ(overflow_a_scroll_node, overflow_b_scroll_node->Parent());
   EXPECT_EQ(TransformationMatrix().Translate(0, -41),
             scroll_b_translation->Matrix());
-  EXPECT_EQ(IntSize(5, 3), overflow_b_scroll_node->ContainerBounds());
-  EXPECT_EQ(IntSize(5, 100), overflow_b_scroll_node->Bounds());
+  EXPECT_EQ(IntRect(0, 0, 5, 3), overflow_b_scroll_node->ContainerRect());
+  EXPECT_EQ(IntRect(0, 0, 5, 100), overflow_b_scroll_node->ContentsRect());
   EXPECT_TRUE(overflow_b_scroll_node->UserScrollableHorizontal());
   EXPECT_TRUE(overflow_b_scroll_node->UserScrollableVertical());
 }
@@ -3799,7 +3858,7 @@
   EXPECT_EQ(FloatSize(7, 11),
             paint_offset_translation->Matrix().To2DTranslation());
   // And the scroll node should not.
-  EXPECT_EQ(IntPoint(0, 0), scroll_node->Offset());
+  EXPECT_EQ(IntRect(0, 0, 100, 100), scroll_node->ContainerRect());
 
   scroller->setAttribute(HTMLNames::styleAttr, "border: 20px solid black;");
   GetDocument().View()->UpdateAllLifecyclePhases();
@@ -3807,7 +3866,7 @@
   EXPECT_EQ(FloatSize(7, 11),
             paint_offset_translation->Matrix().To2DTranslation());
   // The scroll node should be offset by the border.
-  EXPECT_EQ(IntPoint(20, 20), scroll_node->Offset());
+  EXPECT_EQ(IntRect(20, 20, 100, 100), scroll_node->ContainerRect());
 
   scroller->setAttribute(HTMLNames::styleAttr,
                          "border: 20px solid black;"
@@ -3815,7 +3874,7 @@
   GetDocument().View()->UpdateAllLifecyclePhases();
   // The scroll node's offset should not include margin if it has already been
   // included in a paint offset node.
-  EXPECT_EQ(IntPoint(20, 20), scroll_node->Offset());
+  EXPECT_EQ(IntRect(20, 20, 100, 100), scroll_node->ContainerRect());
   EXPECT_EQ(TransformationMatrix().Translate(7, 11),
             scroll_properties->PaintOffsetTranslation()->Matrix());
 }
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeUpdateTests.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeUpdateTests.cpp
index 4fa85d9..c83629a 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeUpdateTests.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeUpdateTests.cpp
@@ -753,8 +753,8 @@
                           ->PaintProperties()
                           ->ScrollTranslation()
                           ->ScrollNode();
-  EXPECT_EQ(IntSize(100, 100), scroll_node->ContainerBounds());
-  EXPECT_EQ(IntSize(200, 200), scroll_node->Bounds());
+  EXPECT_EQ(IntRect(0, 0, 100, 100), scroll_node->ContainerRect());
+  EXPECT_EQ(IntRect(0, 0, 200, 200), scroll_node->ContentsRect());
 
   GetDocument().getElementById("content")->setAttribute(
       HTMLNames::styleAttr, "width: 200px; height: 300px");
@@ -763,8 +763,8 @@
                              ->PaintProperties()
                              ->ScrollTranslation()
                              ->ScrollNode());
-  EXPECT_EQ(IntSize(100, 100), scroll_node->ContainerBounds());
-  EXPECT_EQ(IntSize(200, 300), scroll_node->Bounds());
+  EXPECT_EQ(IntRect(0, 0, 100, 100), scroll_node->ContainerRect());
+  EXPECT_EQ(IntRect(0, 0, 200, 300), scroll_node->ContentsRect());
 }
 
 TEST_P(PaintPropertyTreeUpdateTest, ScrollbarWidthChange) {
diff --git a/third_party/WebKit/Source/core/paint/SVGContainerPainter.cpp b/third_party/WebKit/Source/core/paint/SVGContainerPainter.cpp
index 43e05d7a..f3cb920 100644
--- a/third_party/WebKit/Source/core/paint/SVGContainerPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/SVGContainerPainter.cpp
@@ -33,7 +33,7 @@
 
   // Spec: An empty viewBox on the <svg> element disables rendering.
   DCHECK(layout_svg_container_.GetElement());
-  if (isSVGSVGElement(*layout_svg_container_.GetElement()) &&
+  if (IsSVGSVGElement(*layout_svg_container_.GetElement()) &&
       toSVGSVGElement(*layout_svg_container_.GetElement()).HasEmptyViewBox())
     return;
 
diff --git a/third_party/WebKit/Source/core/paint/SVGImagePainter.cpp b/third_party/WebKit/Source/core/paint/SVGImagePainter.cpp
index 7dcac0a..d1addea 100644
--- a/third_party/WebKit/Source/core/paint/SVGImagePainter.cpp
+++ b/third_party/WebKit/Source/core/paint/SVGImagePainter.cpp
@@ -78,7 +78,7 @@
   InterpolationQuality previous_interpolation_quality =
       paint_info.context.ImageInterpolationQuality();
   paint_info.context.SetImageInterpolationQuality(interpolation_quality);
-  paint_info.context.DrawImage(image.Get(), dest_rect, &src_rect);
+  paint_info.context.DrawImage(image.get(), dest_rect, &src_rect);
   paint_info.context.SetImageInterpolationQuality(
       previous_interpolation_quality);
 }
diff --git a/third_party/WebKit/Source/core/paint/ScrollableAreaPainter.cpp b/third_party/WebKit/Source/core/paint/ScrollableAreaPainter.cpp
index 2343c2ef..74331b841 100644
--- a/third_party/WebKit/Source/core/paint/ScrollableAreaPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/ScrollableAreaPainter.cpp
@@ -171,7 +171,7 @@
   if (painting_overlay_controls && !GetScrollableArea().HasOverlayScrollbars())
     return;
 
-  IntRect clip_rect(adjusted_paint_offset, GetScrollableArea().Layer()->size());
+  IntRect clip_rect(adjusted_paint_offset, GetScrollableArea().Layer()->Size());
   ClipRecorder clip_recorder(context, GetScrollableArea().Box(),
                              DisplayItem::kClipLayerOverflowControls,
                              clip_rect);
diff --git a/third_party/WebKit/Source/core/paint/ThemePainter.cpp b/third_party/WebKit/Source/core/paint/ThemePainter.cpp
index 84f8562..ca33511 100644
--- a/third_party/WebKit/Source/core/paint/ThemePainter.cpp
+++ b/third_party/WebKit/Source/core/paint/ThemePainter.cpp
@@ -71,13 +71,13 @@
   if (part == kButtonPart && o.GetNode()) {
     UseCounter::Count(o.GetDocument(),
                       WebFeature::kCSSValueAppearanceButtonRendered);
-    if (isHTMLAnchorElement(o.GetNode())) {
+    if (IsHTMLAnchorElement(o.GetNode())) {
       UseCounter::Count(o.GetDocument(),
                         WebFeature::kCSSValueAppearanceButtonForAnchor);
-    } else if (isHTMLButtonElement(o.GetNode())) {
+    } else if (IsHTMLButtonElement(o.GetNode())) {
       UseCounter::Count(o.GetDocument(),
                         WebFeature::kCSSValueAppearanceButtonForButton);
-    } else if (isHTMLInputElement(o.GetNode()) &&
+    } else if (IsHTMLInputElement(o.GetNode()) &&
                toHTMLInputElement(o.GetNode())->IsTextButton()) {
       // Text buttons (type=button, reset, submit) has
       // -webkit-appearance:push-button by default.
@@ -179,8 +179,7 @@
     case kTextFieldPart:
       UseCounter::Count(o.GetDocument(),
                         WebFeature::kCSSValueAppearanceTextFieldRendered);
-      if (isHTMLInputElement(o.GetNode())) {
-        HTMLInputElement* input = toHTMLInputElement(o.GetNode());
+      if (auto* input = ToHTMLInputElementOrNull(o.GetNode())) {
         if (input->type() == InputTypeNames::search) {
           UseCounter::Count(o.GetDocument(),
                             WebFeature::kCSSValueAppearanceTextFieldForSearch);
@@ -251,7 +250,7 @@
                                     const PaintInfo& paint_info,
                                     const IntRect& rect) {
   Node* node = o.GetNode();
-  if (!isHTMLInputElement(node))
+  if (!IsHTMLInputElement(node))
     return;
 
   HTMLInputElement* input = toHTMLInputElement(node);
diff --git a/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.cpp b/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.cpp
index 5ae665d..5bb1d78 100644
--- a/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.cpp
+++ b/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.cpp
@@ -2751,7 +2751,7 @@
     // Now look at the body's layoutObject.
     HTMLElement* body = layout_object.GetDocument().body();
     LayoutObject* body_object =
-        isHTMLBodyElement(body) ? body->GetLayoutObject() : 0;
+        IsHTMLBodyElement(body) ? body->GetLayoutObject() : 0;
     if (body_object &&
         HasBoxDecorationsOrBackgroundImage(body_object->StyleRef()))
       return true;
diff --git a/third_party/WebKit/Source/core/paint/compositing/GraphicsLayerTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/compositing/GraphicsLayerTreeBuilder.cpp
index 8326c83e..bf7e0ce 100644
--- a/third_party/WebKit/Source/core/paint/compositing/GraphicsLayerTreeBuilder.cpp
+++ b/third_party/WebKit/Source/core/paint/compositing/GraphicsLayerTreeBuilder.cpp
@@ -41,7 +41,7 @@
 
 static bool ShouldAppendLayer(const PaintLayer& layer) {
   Node* node = layer.GetLayoutObject().GetNode();
-  if (node && isHTMLVideoElement(*node)) {
+  if (node && IsHTMLVideoElement(*node)) {
     HTMLVideoElement* element = toHTMLVideoElement(node);
     if (element->IsFullscreen() && element->UsesOverlayFullscreenVideo())
       return false;
diff --git a/third_party/WebKit/Source/core/paint/compositing/PaintLayerCompositor.cpp b/third_party/WebKit/Source/core/paint/compositing/PaintLayerCompositor.cpp
index 83a46594..f26a7dc 100644
--- a/third_party/WebKit/Source/core/paint/compositing/PaintLayerCompositor.cpp
+++ b/third_party/WebKit/Source/core/paint/compositing/PaintLayerCompositor.cpp
@@ -171,7 +171,7 @@
       return nullptr;
     fullscreen_element = Fullscreen::FullscreenElementFrom(*content_document);
   }
-  if (!isHTMLVideoElement(fullscreen_element))
+  if (!IsHTMLVideoElement(fullscreen_element))
     return nullptr;
   LayoutObject* layout_object = fullscreen_element->GetLayoutObject();
   if (!layout_object)
@@ -1087,6 +1087,9 @@
 }
 
 void PaintLayerCompositor::UpdateOverflowControlsLayers() {
+  if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
+    return;
+
   GraphicsLayer* controls_parent = overflow_controls_host_layer_.get();
   // Main frame scrollbars should always be stuck to the sides of the screen (in
   // overscroll and in pinch-zoom), so make the parent for the scrollbars be the
diff --git a/third_party/WebKit/Source/core/paint/ng/ng_box_fragment_painter.cc b/third_party/WebKit/Source/core/paint/ng/ng_box_fragment_painter.cc
index 77e8d23..76df22dc 100644
--- a/third_party/WebKit/Source/core/paint/ng/ng_box_fragment_painter.cc
+++ b/third_party/WebKit/Source/core/paint/ng/ng_box_fragment_painter.cc
@@ -135,6 +135,11 @@
     paint_info.context.EndLayer();
 }
 
+static bool RequiresLegacyFallback(const NGPhysicalFragment& fragment) {
+  LayoutObject* layout_object = fragment.GetLayoutObject();
+  return layout_object->IsLayoutReplaced();
+}
+
 void NGBoxFragmentPainter::PaintChildren(
     const Vector<std::unique_ptr<const NGPaintFragment>>& children,
     const PaintInfo& paint_info,
@@ -149,7 +154,11 @@
       PaintChildren(child->Children(), child_info, child_offset);
     } else if (fragment.Type() == NGPhysicalBoxFragment::kFragmentBox) {
       PaintInfo child_paint_info(paint_info);
-      NGBoxFragmentPainter(*child).Paint(child_paint_info, child_offset);
+
+      if (RequiresLegacyFallback(fragment))
+        fragment.GetLayoutObject()->Paint(child_paint_info, child_offset);
+      else
+        NGBoxFragmentPainter(*child).Paint(child_paint_info, child_offset);
 
       // TODO(layout-dev): Implement support for this.
     } else if (fragment.Type() == NGPhysicalBoxFragment::kFragmentText) {
diff --git a/third_party/WebKit/Source/core/paint/ng/ng_text_fragment_painter.cc b/third_party/WebKit/Source/core/paint/ng/ng_text_fragment_painter.cc
index 345be86..990105f 100644
--- a/third_party/WebKit/Source/core/paint/ng/ng_text_fragment_painter.cc
+++ b/third_party/WebKit/Source/core/paint/ng/ng_text_fragment_painter.cc
@@ -5,6 +5,8 @@
 #include "core/paint/ng/ng_text_fragment_painter.h"
 
 #include "core/layout/ng/inline/ng_physical_text_fragment.h"
+#include "core/layout/ng/ng_physical_box_fragment.h"
+#include "core/layout/ng/ng_text_decoration_offset.h"
 #include "core/paint/PaintInfo.h"
 #include "core/paint/TextPainterBase.h"
 #include "core/paint/ng/ng_paint_fragment.h"
@@ -16,33 +18,6 @@
 
 namespace blink {
 
-namespace {
-
-static void PaintDecorationsExceptLineThrough(
-    NGTextPainter& text_painter,
-    bool& has_line_through_decoration,
-    const NGPhysicalTextFragment& fragment,
-    const DecorationInfo& decoration_info,
-    const PaintInfo& paint_info,
-    const Vector<AppliedTextDecoration>& decorations) {
-  GraphicsContext& context = paint_info.context;
-  GraphicsContextStateSaver state_saver(context);
-  context.SetStrokeThickness(decoration_info.thickness);
-
-  // text-underline-position may flip underline and overline.
-  ResolvedUnderlinePosition underline_position =
-      decoration_info.underline_position;
-  bool flip_underline_and_overline = false;
-  if (underline_position == ResolvedUnderlinePosition::kOver) {
-    flip_underline_and_overline = true;
-    underline_position = ResolvedUnderlinePosition::kUnder;
-  }
-
-  // TODO(layout-dev): Add support for text decorations.
-}
-
-}  // anonymous namespace
-
 NGTextFragmentPainter::NGTextFragmentPainter(
     const NGPaintFragment& text_fragment)
     : fragment_(text_fragment) {
@@ -52,7 +27,7 @@
 void NGTextFragmentPainter::Paint(const Document& document,
                                   const PaintInfo& paint_info,
                                   const LayoutPoint& paint_offset) {
-  const ComputedStyle& style_to_use = fragment_.Style();
+  const ComputedStyle& style = fragment_.Style();
 
   NGPhysicalSize size_;
   NGPhysicalOffset offset_;
@@ -81,16 +56,16 @@
 
   // Determine text colors.
   TextPaintStyle text_style =
-      TextPainterBase::TextPaintingStyle(document, style_to_use, paint_info);
+      TextPainterBase::TextPaintingStyle(document, style, paint_info);
   TextPaintStyle selection_style = TextPainterBase::SelectionPaintingStyle(
-      document, style_to_use, fragment_.GetNode(), have_selection, paint_info,
+      document, style, fragment_.GetNode(), have_selection, paint_info,
       text_style);
   bool paint_selected_text_only = (paint_info.phase == kPaintPhaseSelection);
   bool paint_selected_text_separately =
       !paint_selected_text_only && text_style != selection_style;
 
   // Set our font.
-  const Font& font = style_to_use.GetFont();
+  const Font& font = style.GetFont();
   const SimpleFontData* font_data = font.PrimaryFont();
   DCHECK(font_data);
 
@@ -108,10 +83,11 @@
   int selection_start = 0;
   int selection_end = 0;
 
-  // TODO(layout-dev): Add hyphen support.
-
   const NGPhysicalTextFragment& text_fragment =
       ToNGPhysicalTextFragment(fragment_.PhysicalFragment());
+
+  // TODO(layout-dev): Truncation and hyphens are computed during layout.
+  // Remove the concept of truncation?
   unsigned length = text_fragment.Text().length();
   unsigned truncation = kCNoTruncation;
 
@@ -131,13 +107,12 @@
 
   NGTextPainter text_painter(context, font, text_fragment, text_origin,
                              box_rect, text_fragment.IsHorizontal());
-  TextEmphasisPosition emphasis_mark_position;
-  bool has_text_emphasis = false;  // TODO(layout-dev): Implement.
-  emphasis_mark_position = TextEmphasisPosition::kOverRight;
-  if (has_text_emphasis) {
-    text_painter.SetEmphasisMark(style_to_use.TextEmphasisMarkString(),
-                                 emphasis_mark_position);
+
+  if (style.GetTextEmphasisMark() != TextEmphasisMark::kNone) {
+    text_painter.SetEmphasisMark(style.TextEmphasisMarkString(),
+                                 style.GetTextEmphasisPosition());
   }
+
   if (truncation != kCNoTruncation && ltr != flow_is_ltr)
     text_painter.SetEllipsisOffset(truncation);
 
@@ -145,24 +120,27 @@
     // Paint text decorations except line-through.
     DecorationInfo decoration_info;
     bool has_line_through_decoration = false;
-    if (style_to_use.TextDecorationsInEffect() != TextDecoration::kNone &&
+    if (style.TextDecorationsInEffect() != TextDecoration::kNone &&
         truncation != kCFullTruncation) {
       LayoutPoint local_origin = LayoutPoint(box_origin);
       LayoutUnit width = fragment_.Size().width;
-      const ComputedStyle* decorating_box_style = nullptr;
-      // TODO(layout-dev): Implement.
+      const NGPhysicalBoxFragment* decorating_box = nullptr;
+      const ComputedStyle* decorating_box_style =
+          decorating_box ? &decorating_box->Style() : nullptr;
+
+      // TODO(eae): Use correct baseline when available.
       FontBaseline baseline_type = kAlphabeticBaseline;
 
       text_painter.ComputeDecorationInfo(decoration_info, box_origin,
                                          local_origin, width, baseline_type,
-                                         style_to_use, decorating_box_style);
-      GraphicsContextStateSaver state_saver(context, false);
-      TextPainterBase::UpdateGraphicsContext(
-          context, text_style, text_fragment.IsHorizontal(), state_saver);
+                                         style, decorating_box_style);
 
-      PaintDecorationsExceptLineThrough(
-          text_painter, has_line_through_decoration, text_fragment,
-          decoration_info, paint_info, style_to_use.AppliedTextDecorations());
+      NGTextDecorationOffset decoration_offset(*decoration_info.style,
+                                               text_fragment, decorating_box);
+      text_painter.PaintDecorationsExceptLineThrough(
+          decoration_offset, decoration_info, paint_info,
+          style.AppliedTextDecorations(), text_style,
+          &has_line_through_decoration);
     }
 
     int start_offset = 0;
@@ -185,7 +163,7 @@
     // Paint line-through decoration if needed.
     if (has_line_through_decoration) {
       text_painter.PaintDecorationsOnlyLineThrough(
-          decoration_info, paint_info, style_to_use.AppliedTextDecorations(),
+          decoration_info, paint_info, style.AppliedTextDecorations(),
           text_style);
     }
   }
diff --git a/third_party/WebKit/Source/core/paint/ng/ng_text_painter.cc b/third_party/WebKit/Source/core/paint/ng/ng_text_painter.cc
index b786eba..de287e7 100644
--- a/third_party/WebKit/Source/core/paint/ng/ng_text_painter.cc
+++ b/third_party/WebKit/Source/core/paint/ng/ng_text_painter.cc
@@ -30,7 +30,11 @@
   // TODO(layout-dev): Handle combine text here or elsewhere.
   PaintInternal<kPaintText>(start_offset, end_offset, length);
 
-  // TODO(layout-dev): Handle emphasis marks.
+  if (!emphasis_mark_.IsEmpty()) {
+    if (text_style.emphasis_mark_color != text_style.fill_color)
+      graphics_context_.SetFillColor(text_style.emphasis_mark_color);
+    PaintInternal<kPaintEmphasisMark>(start_offset, end_offset, length);
+  }
 }
 
 template <NGTextPainter::PaintInternalStep step>
@@ -63,19 +67,15 @@
   if (!fragment_.TextShapeResult())
     return;
 
-  NGTextFragmentPaintInfo fragment_paint_info = fragment_.PaintInfo();
+  NGTextFragmentPaintInfo paint_info = fragment_.PaintInfo();
 
   if (start_offset <= end_offset) {
-    PaintInternalFragment<Step>(fragment_paint_info, start_offset, end_offset);
+    PaintInternalFragment<Step>(paint_info, start_offset, end_offset);
   } else {
-    if (end_offset > 0) {
-      PaintInternalFragment<Step>(fragment_paint_info, ellipsis_offset_,
-                                  end_offset);
-    }
-    if (start_offset < truncation_point) {
-      PaintInternalFragment<Step>(fragment_paint_info, start_offset,
-                                  truncation_point);
-    }
+    if (end_offset > 0)
+      PaintInternalFragment<Step>(paint_info, ellipsis_offset_, end_offset);
+    if (start_offset < truncation_point)
+      PaintInternalFragment<Step>(paint_info, start_offset, truncation_point);
   }
 }
 
diff --git a/third_party/WebKit/Source/core/streams/ReadableStreamController.h b/third_party/WebKit/Source/core/streams/ReadableStreamController.h
index 490002f..1862d8a 100644
--- a/third_party/WebKit/Source/core/streams/ReadableStreamController.h
+++ b/third_party/WebKit/Source/core/streams/ReadableStreamController.h
@@ -37,7 +37,7 @@
   bool IsActive() const { return !js_controller_.IsEmpty(); }
 
   void Close() {
-    ScriptState* script_state = script_state_.Get();
+    ScriptState* script_state = script_state_.get();
     // This will assert that the context is valid; do not call this method when
     // the context is invalidated.
     ScriptState::Scope scope(script_state);
@@ -55,7 +55,7 @@
   }
 
   double DesiredSize() const {
-    ScriptState* script_state = script_state_.Get();
+    ScriptState* script_state = script_state_.get();
     // This will assert that the context is valid; do not call this method when
     // the context is invalidated.
     ScriptState::Scope scope(script_state);
@@ -74,7 +74,7 @@
 
   template <typename ChunkType>
   void Enqueue(ChunkType chunk) const {
-    ScriptState* script_state = script_state_.Get();
+    ScriptState* script_state = script_state_.get();
     // This will assert that the context is valid; do not call this method when
     // the context is invalidated.
     ScriptState::Scope scope(script_state);
@@ -93,7 +93,7 @@
 
   template <typename ErrorType>
   void GetError(ErrorType error) {
-    ScriptState* script_state = script_state_.Get();
+    ScriptState* script_state = script_state_.get();
     // This will assert that the context is valid; do not call this method when
     // the context is invalidated.
     ScriptState::Scope scope(script_state);
diff --git a/third_party/WebKit/Source/core/style/ClipPathOperation.h b/third_party/WebKit/Source/core/style/ClipPathOperation.h
index 1d30fbf2..223b732 100644
--- a/third_party/WebKit/Source/core/style/ClipPathOperation.h
+++ b/third_party/WebKit/Source/core/style/ClipPathOperation.h
@@ -100,8 +100,8 @@
     return WTF::AdoptRef(new ShapeClipPathOperation(std::move(shape)));
   }
 
-  const BasicShape* GetBasicShape() const { return shape_.Get(); }
-  bool IsValid() const { return shape_.Get(); }
+  const BasicShape* GetBasicShape() const { return shape_.get(); }
+  bool IsValid() const { return shape_.get(); }
   const Path& GetPath(const FloatRect& bounding_rect) {
     DCHECK(shape_);
     path_.reset();
@@ -131,9 +131,9 @@
     const ClipPathOperation& o) const {
   if (!IsSameType(o))
     return false;
-  BasicShape* other_shape = ToShapeClipPathOperation(o).shape_.Get();
-  if (!shape_.Get() || !other_shape)
-    return static_cast<bool>(shape_.Get()) == static_cast<bool>(other_shape);
+  BasicShape* other_shape = ToShapeClipPathOperation(o).shape_.get();
+  if (!shape_.get() || !other_shape)
+    return static_cast<bool>(shape_.get()) == static_cast<bool>(other_shape);
   return *shape_ == *other_shape;
 }
 
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
index 6c6ac79..a16cfb9 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -398,7 +398,7 @@
     return 0;
 
   for (size_t i = 0; i < cached_pseudo_styles_->size(); ++i) {
-    ComputedStyle* pseudo_style = cached_pseudo_styles_->at(i).Get();
+    ComputedStyle* pseudo_style = cached_pseudo_styles_->at(i).get();
     if (pseudo_style->StyleType() == pid)
       return pseudo_style;
   }
@@ -413,7 +413,7 @@
 
   DCHECK_GT(pseudo->StyleType(), kPseudoIdNone);
 
-  ComputedStyle* result = pseudo.Get();
+  ComputedStyle* result = pseudo.get();
 
   if (!cached_pseudo_styles_)
     cached_pseudo_styles_ = WTF::WrapUnique(new PseudoStyleCache);
@@ -427,7 +427,7 @@
   if (!cached_pseudo_styles_)
     return;
   for (size_t i = 0; i < cached_pseudo_styles_->size(); ++i) {
-    ComputedStyle* pseudo_style = cached_pseudo_styles_->at(i).Get();
+    ComputedStyle* pseudo_style = cached_pseudo_styles_->at(i).get();
     if (pseudo_style->StyleType() == pid) {
       cached_pseudo_styles_->EraseAt(i);
       return;
@@ -1425,7 +1425,7 @@
 }
 
 StyleInheritedVariables* ComputedStyle::InheritedVariables() const {
-  return InheritedVariablesInternal().Get();
+  return InheritedVariablesInternal().get();
 }
 
 StyleNonInheritedVariables* ComputedStyle::NonInheritedVariables() const {
diff --git a/third_party/WebKit/Source/core/style/DataEquivalency.h b/third_party/WebKit/Source/core/style/DataEquivalency.h
index 4951191..1f2cd84 100644
--- a/third_party/WebKit/Source/core/style/DataEquivalency.h
+++ b/third_party/WebKit/Source/core/style/DataEquivalency.h
@@ -26,7 +26,7 @@
 
 template <typename T>
 bool DataEquivalent(const RefPtr<T>& a, const RefPtr<T>& b) {
-  return DataEquivalent(a.Get(), b.Get());
+  return DataEquivalent(a.get(), b.get());
 }
 
 template <typename T>
diff --git a/third_party/WebKit/Source/core/style/DataRef.h b/third_party/WebKit/Source/core/style/DataRef.h
index 31b6840..be10214 100644
--- a/third_party/WebKit/Source/core/style/DataRef.h
+++ b/third_party/WebKit/Source/core/style/DataRef.h
@@ -34,7 +34,7 @@
   USING_FAST_MALLOC(DataRef);
 
  public:
-  const T* Get() const { return data_.Get(); }
+  const T* Get() const { return data_.get(); }
 
   const T& operator*() const { return *Get(); }
   const T* operator->() const { return Get(); }
@@ -42,7 +42,7 @@
   T* Access() {
     if (!data_->HasOneRef())
       data_ = data_->Copy();
-    return data_.Get();
+    return data_.get();
   }
 
   void Init() {
diff --git a/third_party/WebKit/Source/core/style/SVGComputedStyle.h b/third_party/WebKit/Source/core/style/SVGComputedStyle.h
index 7187e99..0e5b24e8 100644
--- a/third_party/WebKit/Source/core/style/SVGComputedStyle.h
+++ b/third_party/WebKit/Source/core/style/SVGComputedStyle.h
@@ -355,7 +355,7 @@
   const SVGPaintType& StrokePaintType() const { return stroke->paint_type; }
   const Color& StrokePaintColor() const { return stroke->paint_color; }
   const String& StrokePaintUri() const { return stroke->paint_uri; }
-  SVGDashArray* StrokeDashArray() const { return stroke->dash_array.Get(); }
+  SVGDashArray* StrokeDashArray() const { return stroke->dash_array.get(); }
   float StrokeMiterLimit() const { return stroke->miter_limit; }
   const UnzoomedLength& StrokeWidth() const { return stroke->width; }
   const Length& StrokeDashOffset() const { return stroke->dash_offset; }
@@ -367,7 +367,7 @@
   const Length& BaselineShiftValue() const {
     return misc->baseline_shift_value;
   }
-  StylePath* D() const { return geometry->d.Get(); }
+  StylePath* D() const { return geometry->d.get(); }
   const Length& Cx() const { return geometry->cx; }
   const Length& Cy() const { return geometry->cy; }
   const Length& X() const { return geometry->x; }
diff --git a/third_party/WebKit/Source/core/style/SVGComputedStyleTest.cpp b/third_party/WebKit/Source/core/style/SVGComputedStyleTest.cpp
index 2a383d9..f8404a0a 100644
--- a/third_party/WebKit/Source/core/style/SVGComputedStyleTest.cpp
+++ b/third_party/WebKit/Source/core/style/SVGComputedStyleTest.cpp
@@ -19,7 +19,7 @@
     RefPtr<type> value2 = value1->Copy();                       \
     svg1->Set##fieldName(value1);                               \
     svg2->Set##fieldName(value2);                               \
-    EXPECT_FALSE(svg1->Diff(svg2.Get()).HasDifference());       \
+    EXPECT_FALSE(svg1->Diff(svg2.get()).HasDifference());       \
   }
 
 // This is not very useful for fields directly stored by values, because they
@@ -31,7 +31,7 @@
     RefPtr<SVGComputedStyle> svg2 = SVGComputedStyle::Create();   \
     svg1->Set##fieldName(SVGComputedStyle::Initial##fieldName()); \
     svg2->Set##fieldName(SVGComputedStyle::Initial##fieldName()); \
-    EXPECT_FALSE(svg1->Diff(svg2.Get()).HasDifference());         \
+    EXPECT_FALSE(svg1->Diff(svg2.get()).HasDifference());         \
   }
 
 TEST(SVGComputedStyleTest, StrokeStyleShouldCompareValue) {
@@ -52,7 +52,7 @@
                          SVGComputedStyle::InitialStrokePaintColor(),
                          SVGComputedStyle::InitialStrokePaintUri(), true,
                          false);
-    EXPECT_FALSE(svg1->Diff(svg2.Get()).HasDifference());
+    EXPECT_FALSE(svg1->Diff(svg2.get()).HasDifference());
   }
   {
     RefPtr<SVGComputedStyle> svg1 = SVGComputedStyle::Create();
@@ -65,7 +65,7 @@
                          SVGComputedStyle::InitialStrokePaintColor(),
                          SVGComputedStyle::InitialStrokePaintUri(), false,
                          true);
-    EXPECT_FALSE(svg1->Diff(svg2.Get()).HasDifference());
+    EXPECT_FALSE(svg1->Diff(svg2.get()).HasDifference());
   }
 }
 
diff --git a/third_party/WebKit/Source/core/style/ShapeValue.h b/third_party/WebKit/Source/core/style/ShapeValue.h
index db4fba22..eb9cd5893 100644
--- a/third_party/WebKit/Source/core/style/ShapeValue.h
+++ b/third_party/WebKit/Source/core/style/ShapeValue.h
@@ -62,7 +62,7 @@
   }
 
   ShapeValueType GetType() const { return type_; }
-  BasicShape* Shape() const { return shape_.Get(); }
+  BasicShape* Shape() const { return shape_.get(); }
 
   StyleImage* GetImage() const { return image_.Get(); }
   bool IsImageValid() const {
diff --git a/third_party/WebKit/Source/core/style/StyleFetchedImage.cpp b/third_party/WebKit/Source/core/style/StyleFetchedImage.cpp
index 646c17ce..530d497 100644
--- a/third_party/WebKit/Source/core/style/StyleFetchedImage.cpp
+++ b/third_party/WebKit/Source/core/style/StyleFetchedImage.cpp
@@ -117,10 +117,12 @@
   document_.Clear();
 }
 
-RefPtr<Image> StyleFetchedImage::GetImage(const ImageResourceObserver&,
-                                          const Document&,
-                                          const ComputedStyle& style,
-                                          const IntSize& container_size) const {
+RefPtr<Image> StyleFetchedImage::GetImage(
+    const ImageResourceObserver&,
+    const Document&,
+    const ComputedStyle& style,
+    const IntSize& container_size,
+    const LayoutSize* logical_size) const {
   if (!image_->GetImage()->IsSVGImage())
     return image_->GetImage();
 
diff --git a/third_party/WebKit/Source/core/style/StyleFetchedImage.h b/third_party/WebKit/Source/core/style/StyleFetchedImage.h
index 4d08bec..3ef3e3a5 100644
--- a/third_party/WebKit/Source/core/style/StyleFetchedImage.h
+++ b/third_party/WebKit/Source/core/style/StyleFetchedImage.h
@@ -64,7 +64,8 @@
   RefPtr<Image> GetImage(const ImageResourceObserver&,
                          const Document&,
                          const ComputedStyle&,
-                         const IntSize&) const override;
+                         const IntSize& container_size,
+                         const LayoutSize* logical_size) const override;
   bool KnownToBeOpaque(const Document&, const ComputedStyle&) const override;
   ImageResourceContent* CachedImage() const override;
 
diff --git a/third_party/WebKit/Source/core/style/StyleFetchedImageSet.cpp b/third_party/WebKit/Source/core/style/StyleFetchedImageSet.cpp
index 082101d..8a2331abb 100644
--- a/third_party/WebKit/Source/core/style/StyleFetchedImageSet.cpp
+++ b/third_party/WebKit/Source/core/style/StyleFetchedImageSet.cpp
@@ -119,7 +119,8 @@
     const ImageResourceObserver&,
     const Document&,
     const ComputedStyle& style,
-    const IntSize& container_size) const {
+    const IntSize& container_size,
+    const LayoutSize* logical_size) const {
   if (!best_fit_image_->GetImage()->IsSVGImage())
     return best_fit_image_->GetImage();
 
diff --git a/third_party/WebKit/Source/core/style/StyleFetchedImageSet.h b/third_party/WebKit/Source/core/style/StyleFetchedImageSet.h
index 756558d..fcfec3a 100644
--- a/third_party/WebKit/Source/core/style/StyleFetchedImageSet.h
+++ b/third_party/WebKit/Source/core/style/StyleFetchedImageSet.h
@@ -72,7 +72,8 @@
   RefPtr<Image> GetImage(const ImageResourceObserver&,
                          const Document&,
                          const ComputedStyle&,
-                         const IntSize& container_size) const override;
+                         const IntSize& container_size,
+                         const LayoutSize* logical_size) const override;
   float ImageScaleFactor() const override { return image_scale_factor_; }
   bool KnownToBeOpaque(const Document&, const ComputedStyle&) const override;
   ImageResourceContent* CachedImage() const override;
diff --git a/third_party/WebKit/Source/core/style/StyleGeneratedImage.cpp b/third_party/WebKit/Source/core/style/StyleGeneratedImage.cpp
index d48c66d..f97b2df 100644
--- a/third_party/WebKit/Source/core/style/StyleGeneratedImage.cpp
+++ b/third_party/WebKit/Source/core/style/StyleGeneratedImage.cpp
@@ -71,8 +71,10 @@
     const ImageResourceObserver& observer,
     const Document& document,
     const ComputedStyle& style,
-    const IntSize& size) const {
-  return image_generator_value_->GetImage(observer, document, style, size);
+    const IntSize& container_size,
+    const LayoutSize* logical_size) const {
+  return image_generator_value_->GetImage(observer, document, style,
+                                          container_size, logical_size);
 }
 
 bool StyleGeneratedImage::KnownToBeOpaque(const Document& document,
diff --git a/third_party/WebKit/Source/core/style/StyleGeneratedImage.h b/third_party/WebKit/Source/core/style/StyleGeneratedImage.h
index d91fcb3..337edc0 100644
--- a/third_party/WebKit/Source/core/style/StyleGeneratedImage.h
+++ b/third_party/WebKit/Source/core/style/StyleGeneratedImage.h
@@ -52,10 +52,13 @@
   bool UsesImageContainerSize() const override { return !fixed_size_; }
   void AddClient(ImageResourceObserver*) override;
   void RemoveClient(ImageResourceObserver*) override;
+  // The |container_size| is the container size with subpixel snapping, where
+  // the |logical_size| is without it. Both sizes include zoom.
   RefPtr<Image> GetImage(const ImageResourceObserver&,
                          const Document&,
                          const ComputedStyle&,
-                         const IntSize&) const override;
+                         const IntSize& container_size,
+                         const LayoutSize* logical_size) const override;
   bool KnownToBeOpaque(const Document&, const ComputedStyle&) const override;
 
   DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/core/style/StyleImage.h b/third_party/WebKit/Source/core/style/StyleImage.h
index d98d969..5c550cfe 100644
--- a/third_party/WebKit/Source/core/style/StyleImage.h
+++ b/third_party/WebKit/Source/core/style/StyleImage.h
@@ -68,10 +68,17 @@
   // Note that the container_size is in the effective zoom level of
   // the style that applies to the given ImageResourceObserver, i.e if the zoom
   // level is 1.0 the container_size should be unzoomed.
+  // The |logical_size| is the |container_size| without applying subpixel
+  // snapping. Both sizes include zoom. This size is only currently computed for
+  // BoxPainterBase and NinePieceImagePainter as these are the only painters
+  // which use custom paint. We pass a nullptr for other subclasses.
+  // TODO(schenney): Pass the |container_size| unsnapped as a LayoutSize so that
+  // we don't need to pass an additional parameter.
   virtual RefPtr<Image> GetImage(const ImageResourceObserver&,
                                  const Document&,
                                  const ComputedStyle&,
-                                 const IntSize& container_size) const = 0;
+                                 const IntSize& container_size,
+                                 const LayoutSize* logical_size) const = 0;
   virtual WrappedImagePtr Data() const = 0;
   virtual float ImageScaleFactor() const { return 1; }
   virtual bool KnownToBeOpaque(const Document&, const ComputedStyle&) const = 0;
diff --git a/third_party/WebKit/Source/core/style/StyleInheritedVariables.cpp b/third_party/WebKit/Source/core/style/StyleInheritedVariables.cpp
index a84a7e3..ec1006ce 100644
--- a/third_party/WebKit/Source/core/style/StyleInheritedVariables.cpp
+++ b/third_party/WebKit/Source/core/style/StyleInheritedVariables.cpp
@@ -48,7 +48,7 @@
     return root_->GetVariable(name);
   if (result == data_.end())
     return nullptr;
-  return result->value.Get();
+  return result->value.get();
 }
 
 void StyleInheritedVariables::SetRegisteredVariable(
diff --git a/third_party/WebKit/Source/core/style/StyleInvalidImage.h b/third_party/WebKit/Source/core/style/StyleInvalidImage.h
index 259f310..7daac62 100644
--- a/third_party/WebKit/Source/core/style/StyleInvalidImage.h
+++ b/third_party/WebKit/Source/core/style/StyleInvalidImage.h
@@ -38,7 +38,8 @@
   RefPtr<Image> GetImage(const ImageResourceObserver&,
                          const Document&,
                          const ComputedStyle&,
-                         const IntSize&) const override {
+                         const IntSize& container_size,
+                         const LayoutSize* logical_size) const override {
     return nullptr;
   }
   bool KnownToBeOpaque(const Document&, const ComputedStyle&) const override {
diff --git a/third_party/WebKit/Source/core/style/StylePendingImage.h b/third_party/WebKit/Source/core/style/StylePendingImage.h
index ad93cb3..0c16ef6f 100644
--- a/third_party/WebKit/Source/core/style/StylePendingImage.h
+++ b/third_party/WebKit/Source/core/style/StylePendingImage.h
@@ -84,7 +84,8 @@
   RefPtr<Image> GetImage(const ImageResourceObserver&,
                          const Document&,
                          const ComputedStyle&,
-                         const IntSize&) const override {
+                         const IntSize& container_size,
+                         const LayoutSize* logical_size) const override {
     NOTREACHED();
     return nullptr;
   }
diff --git a/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp b/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp
index a13a0211..3372127c0d 100644
--- a/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp
@@ -189,7 +189,7 @@
   // also disallows the perfectly "valid" animation of 'className' on said
   // element. If SVGScriptElement.href is transitioned off of SVGAnimatedHref,
   // this can be removed.
-  if (isSVGScriptElement(*targetElement())) {
+  if (IsSVGScriptElement(*targetElement())) {
     type_ = kAnimatedUnknown;
     css_property_id_ = CSSPropertyInvalid;
   }
@@ -345,7 +345,7 @@
   DCHECK_EQ(result_animation_element->GetAnimatedPropertyType(),
             GetAnimatedPropertyType());
 
-  if (isSVGSetElement(*this))
+  if (IsSVGSetElement(*this))
     percentage = 1;
 
   if (GetCalcMode() == kCalcModeDiscrete)
@@ -406,7 +406,7 @@
       !AnimatedPropertyTypeSupportsAddition())
     return false;
 
-  DCHECK(!isSVGSetElement(*this));
+  DCHECK(!IsSVGSetElement(*this));
 
   from_property_ = CreatePropertyForAnimation(from_string);
   from_property_value_type_ = PropertyValueType(AttributeName(), from_string);
diff --git a/third_party/WebKit/Source/core/svg/SVGAnimateMotionElement.cpp b/third_party/WebKit/Source/core/svg/SVGAnimateMotionElement.cpp
index 47f0040..b3eb0871 100644
--- a/third_party/WebKit/Source/core/svg/SVGAnimateMotionElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGAnimateMotionElement.cpp
@@ -44,15 +44,15 @@
   // Spec: SVG 1.1 section 19.2.15
   // FIXME: svgTag is missing. Needs to be checked, if transforming <svg> could
   // cause problems.
-  return isSVGGElement(target) || isSVGDefsElement(target) ||
-         isSVGUseElement(target) || isSVGImageElement(target) ||
-         isSVGSwitchElement(target) || isSVGPathElement(target) ||
-         isSVGRectElement(target) || isSVGCircleElement(target) ||
-         isSVGEllipseElement(target) || isSVGLineElement(target) ||
-         isSVGPolylineElement(target) || isSVGPolygonElement(target) ||
-         isSVGTextElement(target) || isSVGClipPathElement(target) ||
-         isSVGMaskElement(target) || isSVGAElement(target) ||
-         isSVGForeignObjectElement(target);
+  return IsSVGGElement(target) || IsSVGDefsElement(target) ||
+         IsSVGUseElement(target) || IsSVGImageElement(target) ||
+         IsSVGSwitchElement(target) || IsSVGPathElement(target) ||
+         IsSVGRectElement(target) || IsSVGCircleElement(target) ||
+         IsSVGEllipseElement(target) || IsSVGLineElement(target) ||
+         IsSVGPolylineElement(target) || IsSVGPolygonElement(target) ||
+         IsSVGTextElement(target) || IsSVGClipPathElement(target) ||
+         IsSVGMaskElement(target) || IsSVGAElement(target) ||
+         IsSVGForeignObjectElement(target);
 }
 }
 
diff --git a/third_party/WebKit/Source/core/svg/SVGAnimationElement.cpp b/third_party/WebKit/Source/core/svg/SVGAnimationElement.cpp
index 1442d3c..dfaeb210 100644
--- a/third_party/WebKit/Source/core/svg/SVGAnimationElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGAnimationElement.cpp
@@ -175,7 +175,7 @@
   }
 
   if (name == SVGNames::keyPointsAttr) {
-    if (isSVGAnimateMotionElement(*this)) {
+    if (IsSVGAnimateMotionElement(*this)) {
       // This is specified to be an animateMotion attribute only but it is
       // simpler to put it here where the other timing calculatations are.
       if (!ParseKeyTimes(params.new_value, key_points_, false)) {
@@ -291,21 +291,22 @@
     UseCounter::Count(GetDocument(), WebFeature::kSVGCalcModeDiscrete);
     SetCalcMode(kCalcModeDiscrete);
   } else if (calc_mode == linear) {
-    if (isSVGAnimateMotionElement(*this))
+    if (IsSVGAnimateMotionElement(*this))
       UseCounter::Count(GetDocument(), WebFeature::kSVGCalcModeLinear);
     // else linear is the default.
     SetCalcMode(kCalcModeLinear);
   } else if (calc_mode == paced) {
-    if (!isSVGAnimateMotionElement(*this))
+    if (!IsSVGAnimateMotionElement(*this))
       UseCounter::Count(GetDocument(), WebFeature::kSVGCalcModePaced);
     // else paced is the default.
     SetCalcMode(kCalcModePaced);
   } else if (calc_mode == spline) {
     UseCounter::Count(GetDocument(), WebFeature::kSVGCalcModeSpline);
     SetCalcMode(kCalcModeSpline);
-  } else
-    SetCalcMode(isSVGAnimateMotionElement(*this) ? kCalcModePaced
+  } else {
+    SetCalcMode(IsSVGAnimateMotionElement(*this) ? kCalcModePaced
                                                  : kCalcModeLinear);
+  }
 }
 
 String SVGAnimationElement::ToValue() const {
diff --git a/third_party/WebKit/Source/core/svg/SVGDocumentExtensions.cpp b/third_party/WebKit/Source/core/svg/SVGDocumentExtensions.cpp
index 93d90f6..7465fe1 100644
--- a/third_party/WebKit/Source/core/svg/SVGDocumentExtensions.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGDocumentExtensions.cpp
@@ -163,8 +163,7 @@
 }
 
 SVGSVGElement* SVGDocumentExtensions::rootElement(const Document& document) {
-  Element* elem = document.documentElement();
-  return isSVGSVGElement(elem) ? toSVGSVGElement(elem) : 0;
+  return ToSVGSVGElementOrNull(document.documentElement());
 }
 
 SVGSVGElement* SVGDocumentExtensions::rootElement() const {
diff --git a/third_party/WebKit/Source/core/svg/SVGElement.cpp b/third_party/WebKit/Source/core/svg/SVGElement.cpp
index 014057d..4ad01d2 100644
--- a/third_party/WebKit/Source/core/svg/SVGElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGElement.cpp
@@ -127,7 +127,7 @@
 }
 
 bool SVGElement::IsOutermostSVGSVGElement() const {
-  if (!isSVGSVGElement(*this))
+  if (!IsSVGSVGElement(*this))
     return false;
 
   // Element may not be in the document, pretend we're outermost for viewport(),
@@ -137,7 +137,7 @@
 
   // We act like an outermost SVG element, if we're a direct child of a
   // <foreignObject> element.
-  if (isSVGForeignObjectElement(*parentNode()))
+  if (IsSVGForeignObjectElement(*parentNode()))
     return true;
 
   // If we're living in a shadow tree, we're a <svg> element that got created as
@@ -357,7 +357,7 @@
     ComputedStyle::ApplyTransformOrigin apply_transform_origin =
         ComputedStyle::kIncludeTransformOrigin;
     // SVGTextElements need special handling for the text positioning code.
-    if (isSVGTextElement(this)) {
+    if (IsSVGTextElement(this)) {
       // Do not take into account transform-origin, or percentage values.
       reference_box = FloatRect();
       apply_transform_origin = ComputedStyle::kExcludeTransformOrigin;
@@ -466,7 +466,7 @@
   if (!attr_name.NamespaceURI().IsNull())
     return CSSPropertyInvalid;
 
-  static HashMap<StringImpl*, CSSPropertyID>* property_name_to_id_map = 0;
+  static HashMap<StringImpl*, CSSPropertyID>* property_name_to_id_map = nullptr;
   if (!property_name_to_id_map) {
     property_name_to_id_map = new HashMap<StringImpl*, CSSPropertyID>;
     // This is a list of all base CSS and SVG CSS properties which are exposed
@@ -587,7 +587,7 @@
   }
 
   // Register root SVG elements for top level viewport change notifications.
-  if (isSVGSVGElement(*client_element)) {
+  if (IsSVGSVGElement(*client_element)) {
     SVGDocumentExtensions& svg_extensions = GetDocument().AccessSVGExtensions();
     if (client_element->HasRelativeLengths())
       svg_extensions.AddSVGRootWithRelativeLengthDescendents(
@@ -628,7 +628,7 @@
 SVGSVGElement* SVGElement::ownerSVGElement() const {
   ContainerNode* n = ParentOrShadowHostNode();
   while (n) {
-    if (isSVGSVGElement(*n))
+    if (IsSVGSVGElement(*n))
       return toSVGSVGElement(n);
 
     n = n->ParentOrShadowHostNode();
@@ -643,7 +643,7 @@
   // work otherwhise.
   ContainerNode* n = ParentOrShadowHostNode();
   while (n) {
-    if (isSVGSVGElement(*n) || isSVGImageElement(*n) || isSVGSymbolElement(*n))
+    if (IsSVGSVGElement(*n) || IsSVGImageElement(*n) || IsSVGSymbolElement(*n))
       return ToSVGElement(n);
 
     n = n->ParentOrShadowHostNode();
@@ -697,7 +697,7 @@
 
 SVGUseElement* SVGElement::CorrespondingUseElement() const {
   if (ShadowRoot* root = ContainingShadowRoot()) {
-    if (isSVGUseElement(root->host()))
+    if (IsSVGUseElement(root->host()))
       return &toSVGUseElement(root->host());
   }
   return nullptr;
@@ -946,7 +946,7 @@
 bool SVGElement::SendSVGLoadEventIfPossible() {
   if (!HaveLoadedRequiredResources())
     return false;
-  if ((IsStructurallyExternal() || isSVGSVGElement(*this)) &&
+  if ((IsStructurallyExternal() || IsSVGSVGElement(*this)) &&
       HasLoadListener(this))
     DispatchEvent(Event::Create(EventTypeNames::load));
   return true;
@@ -1290,7 +1290,7 @@
 
 SVGElementProxySet* SVGElement::ElementProxySet() {
   // Limit to specific element types.
-  if (!isSVGFilterElement(*this) && !isSVGClipPathElement(*this))
+  if (!IsSVGFilterElement(*this) && !IsSVGClipPathElement(*this))
     return nullptr;
   return &EnsureSVGRareData()->EnsureElementProxySet();
 }
diff --git a/third_party/WebKit/Source/core/svg/SVGElement.h b/third_party/WebKit/Source/core/svg/SVGElement.h
index b5689c5..bd2faee 100644
--- a/third_party/WebKit/Source/core/svg/SVGElement.h
+++ b/third_party/WebKit/Source/core/svg/SVGElement.h
@@ -163,7 +163,7 @@
 
   virtual bool HaveLoadedRequiredResources();
 
-  void InvalidateRelativeLengthClients(SubtreeLayoutScope* = 0);
+  void InvalidateRelativeLengthClients(SubtreeLayoutScope* = nullptr);
 
   void AddToPropertyMap(SVGAnimatedPropertyBase*);
 
diff --git a/third_party/WebKit/Source/core/svg/SVGElementRareData.cpp b/third_party/WebKit/Source/core/svg/SVGElementRareData.cpp
index ecc31819..3075ce7 100644
--- a/third_party/WebKit/Source/core/svg/SVGElementRareData.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGElementRareData.cpp
@@ -34,7 +34,7 @@
     needs_override_computed_style_update_ = false;
   }
   DCHECK(override_computed_style_);
-  return override_computed_style_.Get();
+  return override_computed_style_.get();
 }
 
 DEFINE_TRACE(SVGElementRareData) {
diff --git a/third_party/WebKit/Source/core/svg/SVGFEComponentTransferElement.cpp b/third_party/WebKit/Source/core/svg/SVGFEComponentTransferElement.cpp
index 5f17822a..f17e81ca 100644
--- a/third_party/WebKit/Source/core/svg/SVGFEComponentTransferElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGFEComponentTransferElement.cpp
@@ -71,14 +71,14 @@
 
   for (SVGElement* element = Traversal<SVGElement>::FirstChild(*this); element;
        element = Traversal<SVGElement>::NextSibling(*element)) {
-    if (isSVGFEFuncRElement(*element))
-      red = toSVGFEFuncRElement(*element).TransferFunction();
-    else if (isSVGFEFuncGElement(*element))
-      green = toSVGFEFuncGElement(*element).TransferFunction();
-    else if (isSVGFEFuncBElement(*element))
-      blue = toSVGFEFuncBElement(*element).TransferFunction();
-    else if (isSVGFEFuncAElement(*element))
-      alpha = toSVGFEFuncAElement(*element).TransferFunction();
+    if (auto* func_r = ToSVGFEFuncRElementOrNull(*element))
+      red = func_r->TransferFunction();
+    else if (auto* func_g = ToSVGFEFuncGElementOrNull(*element))
+      green = func_g->TransferFunction();
+    else if (auto* func_b = ToSVGFEFuncBElementOrNull(*element))
+      blue = func_b->TransferFunction();
+    else if (auto* func_a = ToSVGFEFuncAElementOrNull(*element))
+      alpha = func_a->TransferFunction();
   }
 
   FilterEffect* effect =
diff --git a/third_party/WebKit/Source/core/svg/SVGFEImageElement.cpp b/third_party/WebKit/Source/core/svg/SVGFEImageElement.cpp
index b8d3495d5..ed23b2e 100644
--- a/third_party/WebKit/Source/core/svg/SVGFEImageElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGFEImageElement.cpp
@@ -141,7 +141,7 @@
     return;
 
   Element* parent = parentElement();
-  if (!parent || !isSVGFilterElement(parent) || !parent->GetLayoutObject())
+  if (!parent || !IsSVGFilterElement(parent) || !parent->GetLayoutObject())
     return;
 
   if (LayoutObject* layout_object = this->GetLayoutObject())
diff --git a/third_party/WebKit/Source/core/svg/SVGFELightElement.cpp b/third_party/WebKit/Source/core/svg/SVGFELightElement.cpp
index b70a71eae..5781d5e 100644
--- a/third_party/WebKit/Source/core/svg/SVGFELightElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGFELightElement.cpp
@@ -119,12 +119,10 @@
       return;
 
     SVGElement::InvalidationGuard invalidation_guard(this);
-    if (isSVGFEDiffuseLightingElement(*parent))
-      toSVGFEDiffuseLightingElement(*parent).LightElementAttributeChanged(
-          this, attr_name);
-    else if (isSVGFESpecularLightingElement(*parent))
-      toSVGFESpecularLightingElement(*parent).LightElementAttributeChanged(
-          this, attr_name);
+    if (auto* diffuse = ToSVGFEDiffuseLightingElementOrNull(*parent))
+      diffuse->LightElementAttributeChanged(this, attr_name);
+    else if (auto* specular = ToSVGFESpecularLightingElementOrNull(*parent))
+      specular->LightElementAttributeChanged(this, attr_name);
 
     return;
   }
diff --git a/third_party/WebKit/Source/core/svg/SVGFilterPrimitiveStandardAttributes.cpp b/third_party/WebKit/Source/core/svg/SVGFilterPrimitiveStandardAttributes.cpp
index bb0bd07..2c87b96f 100644
--- a/third_party/WebKit/Source/core/svg/SVGFilterPrimitiveStandardAttributes.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGFilterPrimitiveStandardAttributes.cpp
@@ -168,7 +168,7 @@
 
 bool SVGFilterPrimitiveStandardAttributes::LayoutObjectIsNeeded(
     const ComputedStyle& style) {
-  if (isSVGFilterElement(parentNode()))
+  if (IsSVGFilterElement(parentNode()))
     return SVGElement::LayoutObjectIsNeeded(style);
 
   return false;
diff --git a/third_party/WebKit/Source/core/svg/SVGGraphicsElement.cpp b/third_party/WebKit/Source/core/svg/SVGGraphicsElement.cpp
index 4b88769..3a167ed 100644
--- a/third_party/WebKit/Source/core/svg/SVGGraphicsElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGGraphicsElement.cpp
@@ -51,8 +51,8 @@
 }
 
 static bool IsViewportElement(const Element& element) {
-  return (isSVGSVGElement(element) || isSVGSymbolElement(element) ||
-          isSVGForeignObjectElement(element) || isSVGImageElement(element));
+  return (IsSVGSVGElement(element) || IsSVGSymbolElement(element) ||
+          IsSVGForeignObjectElement(element) || IsSVGImageElement(element));
 }
 
 AffineTransform SVGGraphicsElement::ComputeCTM(
diff --git a/third_party/WebKit/Source/core/svg/SVGLengthContext.cpp b/third_party/WebKit/Source/core/svg/SVGLengthContext.cpp
index 0bbde9eb..0d9470c 100644
--- a/third_party/WebKit/Source/core/svg/SVGLengthContext.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGLengthContext.cpp
@@ -444,7 +444,7 @@
 
   // Take size from nearest viewport element.
   SVGElement* viewport_element = context_->viewportElement();
-  if (!isSVGSVGElement(viewport_element))
+  if (!IsSVGSVGElement(viewport_element))
     return false;
 
   const SVGSVGElement& svg = toSVGSVGElement(*viewport_element);
diff --git a/third_party/WebKit/Source/core/svg/SVGLinearGradientElement.cpp b/third_party/WebKit/Source/core/svg/SVGLinearGradientElement.cpp
index 16cebe2..15eaac59 100644
--- a/third_party/WebKit/Source/core/svg/SVGLinearGradientElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGLinearGradientElement.cpp
@@ -126,7 +126,7 @@
 
   while (true) {
     SetGradientAttributes(*current, attributes,
-                          isSVGLinearGradientElement(*current));
+                          IsSVGLinearGradientElement(*current));
     visited.insert(current);
 
     current = current->ReferencedElement();
diff --git a/third_party/WebKit/Source/core/svg/SVGMPathElement.cpp b/third_party/WebKit/Source/core/svg/SVGMPathElement.cpp
index 4bb1a13..0572b2d 100644
--- a/third_party/WebKit/Source/core/svg/SVGMPathElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGMPathElement.cpp
@@ -47,11 +47,11 @@
   if (!isConnected())
     return;
   Element* target = ObserveTarget(target_id_observer_, *this);
-  if (isSVGPathElement(target)) {
+  if (auto* path = ToSVGPathElementOrNull(target)) {
     // Register us with the target in the dependencies map. Any change of
     // hrefElement that leads to relayout/repainting now informs us, so we can
     // react to it.
-    AddReferenceTo(ToSVGElement(target));
+    AddReferenceTo(path);
   }
   TargetPathChanged();
 }
@@ -88,7 +88,7 @@
 
 SVGPathElement* SVGMPathElement::PathElement() {
   Element* target = TargetElementFromIRIString(HrefString(), GetTreeScope());
-  return isSVGPathElement(target) ? toSVGPathElement(target) : 0;
+  return ToSVGPathElementOrNull(target);
 }
 
 void SVGMPathElement::TargetPathChanged() {
@@ -96,8 +96,8 @@
 }
 
 void SVGMPathElement::NotifyParentOfPathChange(ContainerNode* parent) {
-  if (isSVGAnimateMotionElement(parent))
-    toSVGAnimateMotionElement(parent)->UpdateAnimationPath();
+  if (auto* motion = ToSVGAnimateMotionElementOrNull(parent))
+    motion->UpdateAnimationPath();
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGPathElement.cpp b/third_party/WebKit/Source/core/svg/SVGPathElement.cpp
index 45eb4fc..3ef9e88 100644
--- a/third_party/WebKit/Source/core/svg/SVGPathElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGPathElement.cpp
@@ -126,8 +126,8 @@
   // dependencies manually.
   if (SVGElementSet* dependencies = SetOfIncomingReferences()) {
     for (SVGElement* element : *dependencies) {
-      if (isSVGMPathElement(*element))
-        toSVGMPathElement(element)->TargetPathChanged();
+      if (auto* mpath = ToSVGMPathElementOrNull(*element))
+        mpath->TargetPathChanged();
     }
   }
 }
diff --git a/third_party/WebKit/Source/core/svg/SVGPatternElement.cpp b/third_party/WebKit/Source/core/svg/SVGPatternElement.cpp
index 08a72c3..fe4e5bd7 100644
--- a/third_party/WebKit/Source/core/svg/SVGPatternElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGPatternElement.cpp
@@ -204,7 +204,7 @@
         current->HrefString(), GetTreeScope());
 
     // Only consider attached SVG pattern elements.
-    if (!isSVGPatternElement(ref_node) || !ref_node->GetLayoutObject())
+    if (!IsSVGPatternElement(ref_node) || !ref_node->GetLayoutObject())
       break;
 
     current = toSVGPatternElement(ref_node);
diff --git a/third_party/WebKit/Source/core/svg/SVGRadialGradientElement.cpp b/third_party/WebKit/Source/core/svg/SVGRadialGradientElement.cpp
index c8a0540..b3afe89c 100644
--- a/third_party/WebKit/Source/core/svg/SVGRadialGradientElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGRadialGradientElement.cpp
@@ -141,7 +141,7 @@
 
   while (true) {
     SetGradientAttributes(*current, attributes,
-                          isSVGRadialGradientElement(*current));
+                          IsSVGRadialGradientElement(*current));
     visited.insert(current);
 
     current = current->ReferencedElement();
diff --git a/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp b/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp
index edafcee1..524e03871 100644
--- a/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp
@@ -317,7 +317,7 @@
 static bool IsIntersectionOrEnclosureTarget(LayoutObject* layout_object) {
   return layout_object->IsSVGShape() || layout_object->IsSVGText() ||
          layout_object->IsSVGImage() ||
-         isSVGUseElement(*layout_object->GetNode());
+         IsSVGUseElement(*layout_object->GetNode());
 }
 
 bool SVGSVGElement::CheckIntersectionOrEnclosure(
@@ -716,7 +716,7 @@
 
   SetViewSpec(nullptr);
 
-  if (!isSVGViewElement(anchor_node))
+  if (!IsSVGViewElement(anchor_node))
     return;
 
   SVGViewElement& view_element = toSVGViewElement(*anchor_node);
diff --git a/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp b/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp
index d2409558..861fc7e 100644
--- a/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp
@@ -166,7 +166,7 @@
 void SVGScriptElement::SetScriptElementForBinding(
     HTMLScriptElementOrSVGScriptElement& element) {
   if (!IsInV1ShadowTree())
-    element.setSVGScriptElement(this);
+    element.SetSVGScriptElement(this);
 }
 
 #if DCHECK_IS_ON()
diff --git a/third_party/WebKit/Source/core/svg/SVGTSpanElement.cpp b/third_party/WebKit/Source/core/svg/SVGTSpanElement.cpp
index 7f81aee..8190fd9 100644
--- a/third_party/WebKit/Source/core/svg/SVGTSpanElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGTSpanElement.cpp
@@ -36,8 +36,8 @@
 
 bool SVGTSpanElement::LayoutObjectIsNeeded(const ComputedStyle& style) {
   if (parentNode() &&
-      (isSVGAElement(*parentNode()) || isSVGTextElement(*parentNode()) ||
-       isSVGTextPathElement(*parentNode()) || isSVGTSpanElement(*parentNode())))
+      (IsSVGAElement(*parentNode()) || IsSVGTextElement(*parentNode()) ||
+       IsSVGTextPathElement(*parentNode()) || IsSVGTSpanElement(*parentNode())))
     return SVGElement::LayoutObjectIsNeeded(style);
 
   return false;
diff --git a/third_party/WebKit/Source/core/svg/SVGTextPathElement.cpp b/third_party/WebKit/Source/core/svg/SVGTextPathElement.cpp
index 6dfe799..39b0f81 100644
--- a/third_party/WebKit/Source/core/svg/SVGTextPathElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGTextPathElement.cpp
@@ -113,7 +113,7 @@
 
 bool SVGTextPathElement::LayoutObjectIsNeeded(const ComputedStyle& style) {
   if (parentNode() &&
-      (isSVGAElement(*parentNode()) || isSVGTextElement(*parentNode())))
+      (IsSVGAElement(*parentNode()) || IsSVGTextElement(*parentNode())))
     return SVGElement::LayoutObjectIsNeeded(style);
 
   return false;
@@ -124,7 +124,7 @@
   if (!isConnected())
     return;
   Element* target = ObserveTarget(target_id_observer_, *this);
-  if (isSVGPathElement(target)) {
+  if (IsSVGPathElement(target)) {
     // Register us with the target in the dependencies map. Any change of
     // hrefElement that leads to relayout/repainting now informs us, so we can
     // react to it.
diff --git a/third_party/WebKit/Source/core/svg/SVGTreeScopeResources.cpp b/third_party/WebKit/Source/core/svg/SVGTreeScopeResources.cpp
index 6fe3bd1..0ce7627 100644
--- a/third_party/WebKit/Source/core/svg/SVGTreeScopeResources.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGTreeScopeResources.cpp
@@ -216,8 +216,8 @@
     // TODO(fs): Ideally we'd always resolve pending resources async instead of
     // inside insertedInto and svgAttributeChanged. For now we only do it for
     // <use> since that would stamp out DOM.
-    if (isSVGUseElement(client_element))
-      toSVGUseElement(client_element)->InvalidateShadowTree();
+    if (auto* use = ToSVGUseElementOrNull(client_element))
+      use->InvalidateShadowTree();
     else
       client_element->BuildPendingResource();
 
diff --git a/third_party/WebKit/Source/core/svg/SVGUseElement.cpp b/third_party/WebKit/Source/core/svg/SVGUseElement.cpp
index bb22539..cfe31f7 100644
--- a/third_party/WebKit/Source/core/svg/SVGUseElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGUseElement.cpp
@@ -143,7 +143,7 @@
   DEFINE_STATIC_LOCAL(const AtomicString, hundred_percent_string, ("100%"));
   // Use |originalElement| for checking the element type, because we will
   // have replaced a <symbol> with an <svg> in the instance tree.
-  if (isSVGSymbolElement(original_element)) {
+  if (IsSVGSymbolElement(original_element)) {
     // Spec (<use> on <symbol>): This generated 'svg' will always have
     // explicit values for attributes width and height.  If attributes
     // width and/or height are provided on the 'use' element, then these
@@ -160,7 +160,7 @@
         use.height()->IsSpecified()
             ? AtomicString(use.height()->CurrentValue()->ValueAsString())
             : hundred_percent_string);
-  } else if (isSVGSVGElement(original_element)) {
+  } else if (IsSVGSVGElement(original_element)) {
     // Spec (<use> on <svg>): If attributes width and/or height are
     // provided on the 'use' element, then these values will override the
     // corresponding attributes on the 'svg' in the generated tree.
@@ -403,7 +403,7 @@
 Element* SVGUseElement::CreateInstanceTree(SVGElement& target_root) const {
   Element* instance_root = target_root.CloneElementWithChildren();
   DCHECK(instance_root->IsSVGElement());
-  if (isSVGSymbolElement(target_root)) {
+  if (IsSVGSymbolElement(target_root)) {
     // Spec: The referenced 'symbol' and its contents are deep-cloned into
     // the generated tree, with the exception that the 'symbol' is replaced
     // by an 'svg'. This generated 'svg' will always have explicit values
@@ -486,10 +486,10 @@
 }
 
 static bool IsDirectReference(const SVGElement& element) {
-  return isSVGPathElement(element) || isSVGRectElement(element) ||
-         isSVGCircleElement(element) || isSVGEllipseElement(element) ||
-         isSVGPolygonElement(element) || isSVGPolylineElement(element) ||
-         isSVGTextElement(element);
+  return IsSVGPathElement(element) || IsSVGRectElement(element) ||
+         IsSVGCircleElement(element) || IsSVGEllipseElement(element) ||
+         IsSVGPolygonElement(element) || IsSVGPolylineElement(element) ||
+         IsSVGTextElement(element);
 }
 
 void SVGUseElement::ToClipPath(Path& path) const {
@@ -542,7 +542,7 @@
   // references are handled as the invalidation bubbles up the dependency
   // chain.
   SVGUseElement* use_element =
-      isSVGUseElement(target) ? toSVGUseElement(&target)
+      IsSVGUseElement(target) ? toSVGUseElement(&target)
                               : Traversal<SVGUseElement>::FirstWithin(target);
   for (; use_element;
        use_element = Traversal<SVGUseElement>::NextSkippingChildren(
diff --git a/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.cpp b/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.cpp
index bf4d15d2..5f45b2d 100644
--- a/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.cpp
+++ b/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.cpp
@@ -1057,7 +1057,7 @@
     // If duration is indefinite the value does not actually change over time.
     // Same is true for <set>.
     SMILTime simple_duration = this->SimpleDuration();
-    if (simple_duration.IsIndefinite() || isSVGSetElement(*this)) {
+    if (simple_duration.IsIndefinite() || IsSVGSetElement(*this)) {
       SMILTime repeating_duration_end = interval_.begin + RepeatingDuration();
       // We are supposed to do freeze semantics when repeating ends, even if the
       // element is still active.
diff --git a/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp b/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
index e09cb64..3b35f0ed 100644
--- a/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
+++ b/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
@@ -150,13 +150,13 @@
   // Don't allow foreignObject elements or images that are not known to be
   // single-origin since these can leak cross-origin information.
   for (Node* node = root_element; node; node = FlatTreeTraversal::Next(*node)) {
-    if (isSVGForeignObjectElement(*node))
+    if (IsSVGForeignObjectElement(*node))
       return false;
-    if (isSVGImageElement(*node)) {
-      if (!toSVGImageElement(*node).CurrentFrameHasSingleSecurityOrigin())
+    if (auto* image = ToSVGImageElementOrNull(*node)) {
+      if (!image->CurrentFrameHasSingleSecurityOrigin())
         return false;
-    } else if (isSVGFEImageElement(*node)) {
-      if (!toSVGFEImageElement(*node).CurrentFrameHasSingleSecurityOrigin())
+    } else if (auto* fe_image = ToSVGFEImageElementOrNull(*node)) {
+      if (!fe_image->CurrentFrameHasSingleSecurityOrigin())
         return false;
     }
   }
diff --git a/third_party/WebKit/Source/core/svg/graphics/SVGImageTest.cpp b/third_party/WebKit/Source/core/svg/graphics/SVGImageTest.cpp
index 50bd450..81c7fc32 100644
--- a/third_party/WebKit/Source/core/svg/graphics/SVGImageTest.cpp
+++ b/third_party/WebKit/Source/core/svg/graphics/SVGImageTest.cpp
@@ -31,7 +31,7 @@
   }
 
   void PumpFrame() {
-    Image* image = image_.Get();
+    Image* image = image_.get();
     std::unique_ptr<SkCanvas> null_canvas = SkMakeNullCanvas();
     SkiaPaintCanvas canvas(null_canvas.get());
     PaintFlags flags;
diff --git a/third_party/WebKit/Source/core/testing/DictionaryTest.cpp b/third_party/WebKit/Source/core/testing/DictionaryTest.cpp
index 39e5568c..7b6e975 100644
--- a/third_party/WebKit/Source/core/testing/DictionaryTest.cpp
+++ b/third_party/WebKit/Source/core/testing/DictionaryTest.cpp
@@ -113,7 +113,7 @@
     result.setElementOrNullMember(element_or_null_member_);
   result.setObjectMember(object_member_);
   result.setObjectOrNullMemberWithDefault(object_or_null_member_with_default_);
-  if (!double_or_string_member_.isNull())
+  if (!double_or_string_member_.IsNull())
     result.setDoubleOrStringMember(double_or_string_member_);
   if (!double_or_string_sequence_member_.IsNull())
     result.setDoubleOrStringSequenceMember(
diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp
index 65ed58c..1b677d01 100644
--- a/third_party/WebKit/Source/core/testing/Internals.cpp
+++ b/third_party/WebKit/Source/core/testing/Internals.cpp
@@ -478,7 +478,7 @@
     return false;
   }
 
-  return isHTMLContentElement(*insertion_point) &&
+  return IsHTMLContentElement(*insertion_point) &&
          toHTMLContentElement(*insertion_point).IsSelectValid();
 }
 
@@ -562,10 +562,10 @@
   }
 
   ImageResourceContent* resource = nullptr;
-  if (isHTMLImageElement(*image)) {
-    resource = toHTMLImageElement(*image).CachedImage();
-  } else if (isSVGImageElement(*image)) {
-    resource = toSVGImageElement(*image).CachedImage();
+  if (auto* html_image = ToHTMLImageElementOrNull(*image)) {
+    resource = html_image->CachedImage();
+  } else if (auto* svg_image = ToSVGImageElementOrNull(*image)) {
+    resource = svg_image->CachedImage();
   } else {
     exception_state.ThrowDOMException(
         kInvalidAccessError, "The element provided is not a image element.");
@@ -593,10 +593,10 @@
   DCHECK(image);
 
   ImageResourceContent* resource = nullptr;
-  if (isHTMLImageElement(*image)) {
-    resource = toHTMLImageElement(*image).CachedImage();
-  } else if (isSVGImageElement(*image)) {
-    resource = toSVGImageElement(*image).CachedImage();
+  if (auto* html_image = ToHTMLImageElementOrNull(*image)) {
+    resource = html_image->CachedImage();
+  } else if (auto* svg_image = ToSVGImageElementOrNull(*image)) {
+    resource = svg_image->CachedImage();
   } else {
     exception_state.ThrowDOMException(
         kInvalidAccessError, "The element provided is not a image element.");
@@ -829,19 +829,17 @@
 void Internals::selectColorInColorChooser(Element* element,
                                           const String& color_value) {
   DCHECK(element);
-  if (!isHTMLInputElement(*element))
-    return;
   Color color;
   if (!color.SetFromString(color_value))
     return;
-  toHTMLInputElement(*element).SelectColorInColorChooser(color);
+  if (auto* input = ToHTMLInputElementOrNull(*element))
+    input->SelectColorInColorChooser(color);
 }
 
 void Internals::endColorChooser(Element* element) {
   DCHECK(element);
-  if (!isHTMLInputElement(*element))
-    return;
-  toHTMLInputElement(*element).EndColorChooser();
+  if (auto* input = ToHTMLInputElementOrNull(*element))
+    input->EndColorChooser();
 }
 
 bool Internals::hasAutofocusRequest(Document* document) {
@@ -1296,8 +1294,8 @@
 bool Internals::elementShouldAutoComplete(Element* element,
                                           ExceptionState& exception_state) {
   DCHECK(element);
-  if (isHTMLInputElement(*element))
-    return toHTMLInputElement(*element).ShouldAutocomplete();
+  if (auto* input = ToHTMLInputElementOrNull(*element))
+    return input->ShouldAutocomplete();
 
   exception_state.ThrowDOMException(kInvalidNodeTypeError,
                                     "The element provided is not an INPUT.");
@@ -1315,14 +1313,14 @@
   }
 
   String suggested_value;
-  if (isHTMLInputElement(*element))
-    suggested_value = toHTMLInputElement(*element).SuggestedValue();
+  if (auto* input = ToHTMLInputElementOrNull(*element))
+    return input->SuggestedValue();
 
-  if (isHTMLTextAreaElement(*element))
-    suggested_value = toHTMLTextAreaElement(*element).SuggestedValue();
+  if (auto* textarea = ToHTMLTextAreaElementOrNull(*element))
+    return textarea->SuggestedValue();
 
-  if (isHTMLSelectElement(*element))
-    suggested_value = toHTMLSelectElement(*element).SuggestedValue();
+  if (auto* select = ToHTMLSelectElementOrNull(*element))
+    return select->SuggestedValue();
 
   return suggested_value;
 }
@@ -1338,21 +1336,21 @@
     return;
   }
 
-  if (isHTMLInputElement(*element))
-    toHTMLInputElement(*element).SetSuggestedValue(value);
+  if (auto* input = ToHTMLInputElementOrNull(*element))
+    input->SetSuggestedValue(value);
 
-  if (isHTMLTextAreaElement(*element))
-    toHTMLTextAreaElement(*element).SetSuggestedValue(value);
+  if (auto* textarea = ToHTMLTextAreaElementOrNull(*element))
+    textarea->SetSuggestedValue(value);
 
-  if (isHTMLSelectElement(*element))
-    toHTMLSelectElement(*element).SetSuggestedValue(value);
+  if (auto* select = ToHTMLSelectElementOrNull(*element))
+    select->SetSuggestedValue(value);
 }
 
 void Internals::setEditingValue(Element* element,
                                 const String& value,
                                 ExceptionState& exception_state) {
   DCHECK(element);
-  if (!isHTMLInputElement(*element)) {
+  if (!IsHTMLInputElement(*element)) {
     exception_state.ThrowDOMException(kInvalidNodeTypeError,
                                       "The element provided is not an INPUT.");
     return;
@@ -1623,6 +1621,21 @@
   return requester->LastProcessedSequence();
 }
 
+void Internals::cancelCurrentSpellCheckRequest(
+    Document* document,
+    ExceptionState& exception_state) {
+  SpellCheckRequester* requester = GetSpellCheckRequester(document);
+
+  if (!requester) {
+    exception_state.ThrowDOMException(
+        kInvalidAccessError,
+        "No spell check requestor can be obtained for the provided document.");
+    return;
+  }
+
+  requester->CancelCheck();
+}
+
 String Internals::idleTimeSpellCheckerState(Document* document,
                                             ExceptionState& exception_state) {
   static const char* const kTexts[] = {
@@ -2595,8 +2608,8 @@
     document = document_;
   } else if (node->IsDocumentNode()) {
     document = ToDocument(node);
-  } else if (isHTMLIFrameElement(*node)) {
-    document = toHTMLIFrameElement(*node).contentDocument();
+  } else if (auto* iframe = ToHTMLIFrameElementOrNull(*node)) {
+    document = iframe->contentDocument();
   }
 
   if (!document) {
@@ -2910,7 +2923,7 @@
 
 void Internals::forceImageReload(Element* element,
                                  ExceptionState& exception_state) {
-  if (!element || !isHTMLImageElement(*element)) {
+  if (!element || !IsHTMLImageElement(*element)) {
     exception_state.ThrowDOMException(
         kInvalidAccessError, "The element should be HTMLImageElement.");
   }
@@ -2931,13 +2944,13 @@
 
 bool Internals::isSelectPopupVisible(Node* node) {
   DCHECK(node);
-  if (!isHTMLSelectElement(*node))
-    return false;
-  return toHTMLSelectElement(*node).PopupIsVisible();
+  if (auto* select = ToHTMLSelectElementOrNull(*node))
+    return select->PopupIsVisible();
+  return false;
 }
 
 bool Internals::selectPopupItemStyleIsRtl(Node* node, int item_index) {
-  if (!node || !isHTMLSelectElement(*node))
+  if (!node || !IsHTMLSelectElement(*node))
     return false;
 
   HTMLSelectElement& select = toHTMLSelectElement(*node);
@@ -2950,7 +2963,7 @@
 }
 
 int Internals::selectPopupItemStyleFontHeight(Node* node, int item_index) {
-  if (!node || !isHTMLSelectElement(*node))
+  if (!node || !IsHTMLSelectElement(*node))
     return false;
 
   HTMLSelectElement& select = toHTMLSelectElement(*node);
@@ -3011,7 +3024,7 @@
                                         bool reveal,
                                         ExceptionState& exception_state) {
   DCHECK(element);
-  if (!isHTMLInputElement(element)) {
+  if (!IsHTMLInputElement(element)) {
     exception_state.ThrowDOMException(kInvalidNodeTypeError,
                                       "The element provided is not an INPUT.");
     return;
diff --git a/third_party/WebKit/Source/core/testing/Internals.h b/third_party/WebKit/Source/core/testing/Internals.h
index 230f429..515f3f2f6 100644
--- a/third_party/WebKit/Source/core/testing/Internals.h
+++ b/third_party/WebKit/Source/core/testing/Internals.h
@@ -270,6 +270,7 @@
 
   int lastSpellCheckRequestSequence(Document*, ExceptionState&);
   int lastSpellCheckProcessedSequence(Document*, ExceptionState&);
+  void cancelCurrentSpellCheckRequest(Document*, ExceptionState&);
   String idleTimeSpellCheckerState(Document*, ExceptionState&);
   void runIdleTimeSpellChecker(Document*, ExceptionState&);
 
diff --git a/third_party/WebKit/Source/core/testing/Internals.idl b/third_party/WebKit/Source/core/testing/Internals.idl
index 8cb319d..281a73f 100644
--- a/third_party/WebKit/Source/core/testing/Internals.idl
+++ b/third_party/WebKit/Source/core/testing/Internals.idl
@@ -149,6 +149,7 @@
 
     [RaisesException] long lastSpellCheckRequestSequence(Document document);
     [RaisesException] long lastSpellCheckProcessedSequence(Document document);
+    [RaisesException] void cancelCurrentSpellCheckRequest(Document document);
     [RaisesException] DOMString idleTimeSpellCheckerState(Document document);
     [RaisesException] void runIdleTimeSpellChecker(Document document);
 
diff --git a/third_party/WebKit/Source/core/testing/RecordTest.cpp b/third_party/WebKit/Source/core/testing/RecordTest.cpp
index 73fc99d..17d9a96 100644
--- a/third_party/WebKit/Source/core/testing/RecordTest.cpp
+++ b/third_party/WebKit/Source/core/testing/RecordTest.cpp
@@ -73,7 +73,7 @@
 
 bool RecordTest::unionReceivedARecord(
     const BooleanOrByteStringByteStringRecord& arg) {
-  return arg.isByteStringByteStringRecord();
+  return arg.IsByteStringByteStringRecord();
 }
 
 DEFINE_TRACE(RecordTest) {
diff --git a/third_party/WebKit/Source/core/testing/SequenceTest.cpp b/third_party/WebKit/Source/core/testing/SequenceTest.cpp
index a0bfca5..8d21afea 100644
--- a/third_party/WebKit/Source/core/testing/SequenceTest.cpp
+++ b/third_party/WebKit/Source/core/testing/SequenceTest.cpp
@@ -44,7 +44,7 @@
 }
 
 bool SequenceTest::unionReceivedSequence(const DoubleOrDoubleSequence& arg) {
-  return arg.isDoubleSequence();
+  return arg.IsDoubleSequence();
 }
 
 DEFINE_TRACE(SequenceTest) {
diff --git a/third_party/WebKit/Source/core/testing/UnionTypesTest.cpp b/third_party/WebKit/Source/core/testing/UnionTypesTest.cpp
index c471b755..fc16c48 100644
--- a/third_party/WebKit/Source/core/testing/UnionTypesTest.cpp
+++ b/third_party/WebKit/Source/core/testing/UnionTypesTest.cpp
@@ -13,16 +13,16 @@
   switch (attribute_type_) {
     case kSpecificTypeNone:
       // Default value is zero (of double).
-      double_or_string_or_string_sequence.setDouble(0);
+      double_or_string_or_string_sequence.SetDouble(0);
       break;
     case kSpecificTypeDouble:
-      double_or_string_or_string_sequence.setDouble(attribute_double_);
+      double_or_string_or_string_sequence.SetDouble(attribute_double_);
       break;
     case kSpecificTypeString:
-      double_or_string_or_string_sequence.setString(attribute_string_);
+      double_or_string_or_string_sequence.SetString(attribute_string_);
       break;
     case kSpecificTypeStringSequence:
-      double_or_string_or_string_sequence.setStringSequence(
+      double_or_string_or_string_sequence.SetStringSequence(
           attribute_string_sequence_);
       break;
     default:
@@ -32,15 +32,15 @@
 
 void UnionTypesTest::setDoubleOrStringOrStringSequenceAttribute(
     const DoubleOrStringOrStringSequence& double_or_string_or_string_sequence) {
-  if (double_or_string_or_string_sequence.isDouble()) {
-    attribute_double_ = double_or_string_or_string_sequence.getAsDouble();
+  if (double_or_string_or_string_sequence.IsDouble()) {
+    attribute_double_ = double_or_string_or_string_sequence.GetAsDouble();
     attribute_type_ = kSpecificTypeDouble;
-  } else if (double_or_string_or_string_sequence.isString()) {
-    attribute_string_ = double_or_string_or_string_sequence.getAsString();
+  } else if (double_or_string_or_string_sequence.IsString()) {
+    attribute_string_ = double_or_string_or_string_sequence.GetAsString();
     attribute_type_ = kSpecificTypeString;
-  } else if (double_or_string_or_string_sequence.isStringSequence()) {
+  } else if (double_or_string_or_string_sequence.IsStringSequence()) {
     attribute_string_sequence_ =
-        double_or_string_or_string_sequence.getAsStringSequence();
+        double_or_string_or_string_sequence.GetAsStringSequence();
     attribute_type_ = kSpecificTypeStringSequence;
   } else {
     NOTREACHED();
@@ -48,25 +48,28 @@
 }
 
 String UnionTypesTest::doubleOrStringArg(DoubleOrString& double_or_string) {
-  if (double_or_string.isNull())
+  if (double_or_string.IsNull())
     return "null is passed";
-  if (double_or_string.isDouble())
+  if (double_or_string.IsDouble()) {
     return "double is passed: " +
-           String::NumberToStringECMAScript(double_or_string.getAsDouble());
-  if (double_or_string.isString())
-    return "string is passed: " + double_or_string.getAsString();
+           String::NumberToStringECMAScript(double_or_string.GetAsDouble());
+  }
+  if (double_or_string.IsString())
+    return "string is passed: " + double_or_string.GetAsString();
   NOTREACHED();
   return String();
 }
 
 String UnionTypesTest::doubleOrInternalEnumArg(
     DoubleOrInternalEnum& double_or_internal_enum) {
-  if (double_or_internal_enum.isDouble())
+  if (double_or_internal_enum.IsDouble()) {
     return "double is passed: " + String::NumberToStringECMAScript(
-                                      double_or_internal_enum.getAsDouble());
-  if (double_or_internal_enum.isInternalEnum())
+                                      double_or_internal_enum.GetAsDouble());
+  }
+  if (double_or_internal_enum.IsInternalEnum()) {
     return "InternalEnum is passed: " +
-           double_or_internal_enum.getAsInternalEnum();
+           double_or_internal_enum.GetAsInternalEnum();
+  }
   NOTREACHED();
   return String();
 }
@@ -78,14 +81,14 @@
 
   StringBuilder builder;
   for (DoubleOrString& double_or_string : sequence) {
-    DCHECK(!double_or_string.isNull());
-    if (double_or_string.isDouble()) {
+    DCHECK(!double_or_string.IsNull());
+    if (double_or_string.IsDouble()) {
       builder.Append("double: ");
       builder.Append(
-          String::NumberToStringECMAScript(double_or_string.getAsDouble()));
-    } else if (double_or_string.isString()) {
+          String::NumberToStringECMAScript(double_or_string.GetAsDouble()));
+    } else if (double_or_string.IsString()) {
       builder.Append("string: ");
-      builder.Append(double_or_string.getAsString());
+      builder.Append(double_or_string.GetAsString());
     } else {
       NOTREACHED();
     }
@@ -96,17 +99,17 @@
 
 String UnionTypesTest::nodeListOrElementArg(
     NodeListOrElement& node_list_or_element) {
-  DCHECK(!node_list_or_element.isNull());
+  DCHECK(!node_list_or_element.IsNull());
   return nodeListOrElementOrNullArg(node_list_or_element);
 }
 
 String UnionTypesTest::nodeListOrElementOrNullArg(
     NodeListOrElement& node_list_or_element_or_null) {
-  if (node_list_or_element_or_null.isNull())
+  if (node_list_or_element_or_null.IsNull())
     return "null or undefined is passed";
-  if (node_list_or_element_or_null.isNodeList())
+  if (node_list_or_element_or_null.IsNodeList())
     return "nodelist is passed";
-  if (node_list_or_element_or_null.isElement())
+  if (node_list_or_element_or_null.IsElement())
     return "element is passed";
   NOTREACHED();
   return String();
@@ -114,19 +117,20 @@
 
 String UnionTypesTest::doubleOrStringOrStringSequenceArg(
     const DoubleOrStringOrStringSequence& double_or_string_or_string_sequence) {
-  if (double_or_string_or_string_sequence.isNull())
+  if (double_or_string_or_string_sequence.IsNull())
     return "null";
 
-  if (double_or_string_or_string_sequence.isDouble())
+  if (double_or_string_or_string_sequence.IsDouble()) {
     return "double: " + String::NumberToStringECMAScript(
-                            double_or_string_or_string_sequence.getAsDouble());
+                            double_or_string_or_string_sequence.GetAsDouble());
+  }
 
-  if (double_or_string_or_string_sequence.isString())
-    return "string: " + double_or_string_or_string_sequence.getAsString();
+  if (double_or_string_or_string_sequence.IsString())
+    return "string: " + double_or_string_or_string_sequence.GetAsString();
 
-  DCHECK(double_or_string_or_string_sequence.isStringSequence());
+  DCHECK(double_or_string_or_string_sequence.IsStringSequence());
   const Vector<String>& sequence =
-      double_or_string_or_string_sequence.getAsStringSequence();
+      double_or_string_or_string_sequence.GetAsStringSequence();
   if (!sequence.size())
     return "sequence: []";
   StringBuilder builder;
diff --git a/third_party/WebKit/Source/core/timing/PerformanceBaseTest.cpp b/third_party/WebKit/Source/core/timing/PerformanceBaseTest.cpp
index b8a7164..1629d25 100644
--- a/third_party/WebKit/Source/core/timing/PerformanceBaseTest.cpp
+++ b/third_party/WebKit/Source/core/timing/PerformanceBaseTest.cpp
@@ -155,11 +155,11 @@
   RefPtr<SecurityOrigin> security_origin = SecurityOrigin::Create(url);
   // When finalResponse is an empty object.
   EXPECT_FALSE(AllowsTimingRedirect(redirect_chain, final_response,
-                                    *security_origin.Get(),
+                                    *security_origin.get(),
                                     GetExecutionContext()));
   final_response.SetURL(url);
   EXPECT_TRUE(AllowsTimingRedirect(redirect_chain, final_response,
-                                   *security_origin.Get(),
+                                   *security_origin.get(),
                                    GetExecutionContext()));
   // When there exist cross-origin redirects.
   AtomicString cross_origin_domain = "http://126.0.0.1:8000";
@@ -168,14 +168,14 @@
   redirect_response3.SetURL(redirect_url);
   redirect_chain.push_back(redirect_response3);
   EXPECT_FALSE(AllowsTimingRedirect(redirect_chain, final_response,
-                                    *security_origin.Get(),
+                                    *security_origin.get(),
                                     GetExecutionContext()));
 
   // When cross-origin redirect opts in.
   redirect_chain.back().SetHTTPHeaderField(HTTPNames::Timing_Allow_Origin,
                                            origin_domain);
   EXPECT_TRUE(AllowsTimingRedirect(redirect_chain, final_response,
-                                   *security_origin.Get(),
+                                   *security_origin.get(),
                                    GetExecutionContext()));
 }
 
diff --git a/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.cpp b/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.cpp
index db9156a..32f9b56 100644
--- a/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.cpp
+++ b/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.cpp
@@ -88,7 +88,7 @@
 PerformanceResourceTiming::~PerformanceResourceTiming() {}
 
 ResourceLoadTiming* PerformanceResourceTiming::GetResourceLoadTiming() const {
-  return timing_.Get();
+  return timing_.get();
 }
 
 bool PerformanceResourceTiming::AllowTimingDetails() const {
diff --git a/third_party/WebKit/Source/core/typed_arrays/DOMArrayBufferBase.h b/third_party/WebKit/Source/core/typed_arrays/DOMArrayBufferBase.h
index f3f82a0..d67adbb 100644
--- a/third_party/WebKit/Source/core/typed_arrays/DOMArrayBufferBase.h
+++ b/third_party/WebKit/Source/core/typed_arrays/DOMArrayBufferBase.h
@@ -18,8 +18,8 @@
  public:
   virtual ~DOMArrayBufferBase() {}
 
-  const WTF::ArrayBuffer* Buffer() const { return buffer_.Get(); }
-  WTF::ArrayBuffer* Buffer() { return buffer_.Get(); }
+  const WTF::ArrayBuffer* Buffer() const { return buffer_.get(); }
+  WTF::ArrayBuffer* Buffer() { return buffer_.get(); }
 
   const void* Data() const { return Buffer()->Data(); }
   void* Data() { return Buffer()->Data(); }
diff --git a/third_party/WebKit/Source/core/typed_arrays/DOMArrayBufferView.h b/third_party/WebKit/Source/core/typed_arrays/DOMArrayBufferView.h
index 73e66d2..d67ffb4df 100644
--- a/third_party/WebKit/Source/core/typed_arrays/DOMArrayBufferView.h
+++ b/third_party/WebKit/Source/core/typed_arrays/DOMArrayBufferView.h
@@ -57,8 +57,8 @@
     return buffer();
   }
 
-  const WTF::ArrayBufferView* View() const { return buffer_view_.Get(); }
-  WTF::ArrayBufferView* View() { return buffer_view_.Get(); }
+  const WTF::ArrayBufferView* View() const { return buffer_view_.get(); }
+  WTF::ArrayBufferView* View() { return buffer_view_.get(); }
 
   ViewType GetType() const { return View()->GetType(); }
   const char* TypeName() { return View()->TypeName(); }
diff --git a/third_party/WebKit/Source/core/typed_arrays/DOMArrayPiece.cpp b/third_party/WebKit/Source/core/typed_arrays/DOMArrayPiece.cpp
index 70523f85b..aaf7d5e 100644
--- a/third_party/WebKit/Source/core/typed_arrays/DOMArrayPiece.cpp
+++ b/third_party/WebKit/Source/core/typed_arrays/DOMArrayPiece.cpp
@@ -11,15 +11,15 @@
 DOMArrayPiece::DOMArrayPiece(
     const ArrayBufferOrArrayBufferView& array_buffer_or_view,
     InitWithUnionOption option) {
-  if (array_buffer_or_view.isArrayBuffer()) {
-    DOMArrayBuffer* array_buffer = array_buffer_or_view.getAsArrayBuffer();
+  if (array_buffer_or_view.IsArrayBuffer()) {
+    DOMArrayBuffer* array_buffer = array_buffer_or_view.GetAsArrayBuffer();
     InitWithData(array_buffer->Data(), array_buffer->ByteLength());
-  } else if (array_buffer_or_view.isArrayBufferView()) {
+  } else if (array_buffer_or_view.IsArrayBufferView()) {
     DOMArrayBufferView* array_buffer_view =
-        array_buffer_or_view.getAsArrayBufferView().View();
+        array_buffer_or_view.GetAsArrayBufferView().View();
     InitWithData(array_buffer_view->BaseAddress(),
                  array_buffer_view->byteLength());
-  } else if (array_buffer_or_view.isNull() &&
+  } else if (array_buffer_or_view.IsNull() &&
              option == kAllowNullPointToNullWithZeroSize) {
     InitWithData(nullptr, 0);
   }  // Otherwise, leave the obejct as null.
diff --git a/third_party/WebKit/Source/core/url/URLSearchParams.cpp b/third_party/WebKit/Source/core/url/URLSearchParams.cpp
index acd511e..5fab52b 100644
--- a/third_party/WebKit/Source/core/url/URLSearchParams.cpp
+++ b/third_party/WebKit/Source/core/url/URLSearchParams.cpp
@@ -48,22 +48,22 @@
 
 URLSearchParams* URLSearchParams::Create(const URLSearchParamsInit& init,
                                          ExceptionState& exception_state) {
-  if (init.isUSVString()) {
-    const String& query_string = init.getAsUSVString();
+  if (init.IsUSVString()) {
+    const String& query_string = init.GetAsUSVString();
     if (query_string.StartsWith('?'))
       return new URLSearchParams(query_string.Substring(1));
     return new URLSearchParams(query_string);
   }
-  if (init.isUSVStringUSVStringRecord()) {
-    return URLSearchParams::Create(init.getAsUSVStringUSVStringRecord(),
+  if (init.IsUSVStringUSVStringRecord()) {
+    return URLSearchParams::Create(init.GetAsUSVStringUSVStringRecord(),
                                    exception_state);
   }
-  if (init.isUSVStringSequenceSequence()) {
-    return URLSearchParams::Create(init.getAsUSVStringSequenceSequence(),
+  if (init.IsUSVStringSequenceSequence()) {
+    return URLSearchParams::Create(init.GetAsUSVStringSequenceSequence(),
                                    exception_state);
   }
 
-  DCHECK(init.isNull());
+  DCHECK(init.IsNull());
   return new URLSearchParams(String());
 }
 
diff --git a/third_party/WebKit/Source/core/workers/BUILD.gn b/third_party/WebKit/Source/core/workers/BUILD.gn
index 655db1e..4a01246 100644
--- a/third_party/WebKit/Source/core/workers/BUILD.gn
+++ b/third_party/WebKit/Source/core/workers/BUILD.gn
@@ -18,8 +18,6 @@
     "GlobalScopeCreationParams.h",
     "InProcessWorkerBase.cpp",
     "InProcessWorkerBase.h",
-    "InProcessWorkerMessagingProxy.cpp",
-    "InProcessWorkerMessagingProxy.h",
     "InProcessWorkerObjectProxy.cpp",
     "InProcessWorkerObjectProxy.h",
     "InstalledScriptsManager.cpp",
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp
index 42dbaeb5..f19cea11a 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp
@@ -4,21 +4,168 @@
 
 #include "core/workers/DedicatedWorkerMessagingProxy.h"
 
-#include "core/workers/DedicatedWorkerThread.h"
-#include "core/workers/WorkerClients.h"
 #include <memory>
+#include "bindings/core/v8/V8CacheOptions.h"
+#include "core/dom/Document.h"
+#include "core/dom/TaskRunnerHelper.h"
+#include "core/events/ErrorEvent.h"
+#include "core/events/MessageEvent.h"
+#include "core/frame/csp/ContentSecurityPolicy.h"
+#include "core/origin_trials/OriginTrialContext.h"
+#include "core/workers/DedicatedWorkerThread.h"
+#include "core/workers/GlobalScopeCreationParams.h"
+#include "core/workers/InProcessWorkerBase.h"
+#include "core/workers/InProcessWorkerObjectProxy.h"
+#include "core/workers/WorkerClients.h"
+#include "core/workers/WorkerInspectorProxy.h"
+#include "platform/CrossThreadFunctional.h"
+#include "platform/WebTaskRunner.h"
+#include "platform/wtf/WTF.h"
 
 namespace blink {
 
+struct DedicatedWorkerMessagingProxy::QueuedTask {
+  RefPtr<SerializedScriptValue> message;
+  MessagePortChannelArray channels;
+};
+
 DedicatedWorkerMessagingProxy::DedicatedWorkerMessagingProxy(
+    ExecutionContext* execution_context,
     InProcessWorkerBase* worker_object,
     WorkerClients* worker_clients)
-    : InProcessWorkerMessagingProxy(worker_object, worker_clients) {}
+    : ThreadedMessagingProxyBase(execution_context, worker_clients),
+      worker_object_(worker_object) {
+  worker_object_proxy_ =
+      InProcessWorkerObjectProxy::Create(this, GetParentFrameTaskRunners());
+}
 
-DedicatedWorkerMessagingProxy::~DedicatedWorkerMessagingProxy() {}
+DedicatedWorkerMessagingProxy::~DedicatedWorkerMessagingProxy() = default;
 
-bool DedicatedWorkerMessagingProxy::IsAtomicsWaitAllowed() {
-  return true;
+void DedicatedWorkerMessagingProxy::StartWorkerGlobalScope(
+    const KURL& script_url,
+    const String& user_agent,
+    const String& source_code,
+    const String& referrer_policy) {
+  DCHECK(IsParentContextThread());
+  if (AskedToTerminate()) {
+    // Worker.terminate() could be called from JS before the thread was
+    // created.
+    return;
+  }
+
+  Document* document = ToDocument(GetExecutionContext());
+  SecurityOrigin* starter_origin = document->GetSecurityOrigin();
+
+  ContentSecurityPolicy* csp = document->GetContentSecurityPolicy();
+  DCHECK(csp);
+
+  WorkerThreadStartMode start_mode =
+      GetWorkerInspectorProxy()->WorkerStartMode(document);
+  std::unique_ptr<WorkerSettings> worker_settings =
+      WTF::WrapUnique(new WorkerSettings(document->GetSettings()));
+
+  auto global_scope_creation_params =
+      WTF::MakeUnique<GlobalScopeCreationParams>(
+          script_url, user_agent, source_code, nullptr, start_mode,
+          csp->Headers().get(), referrer_policy, starter_origin,
+          ReleaseWorkerClients(), document->AddressSpace(),
+          OriginTrialContext::GetTokens(document).get(),
+          std::move(worker_settings), kV8CacheOptionsDefault);
+
+  InitializeWorkerThread(std::move(global_scope_creation_params),
+                         CreateBackingThreadStartupData(ToIsolate(document)),
+                         script_url);
+}
+
+void DedicatedWorkerMessagingProxy::PostMessageToWorkerGlobalScope(
+    RefPtr<SerializedScriptValue> message,
+    MessagePortChannelArray channels) {
+  DCHECK(IsParentContextThread());
+  if (AskedToTerminate())
+    return;
+
+  if (GetWorkerThread()) {
+    WTF::CrossThreadClosure task = CrossThreadBind(
+        &InProcessWorkerObjectProxy::ProcessMessageFromWorkerObject,
+        CrossThreadUnretained(&WorkerObjectProxy()), std::move(message),
+        WTF::Passed(std::move(channels)),
+        CrossThreadUnretained(GetWorkerThread()));
+    TaskRunnerHelper::Get(TaskType::kPostedMessage, GetWorkerThread())
+        ->PostTask(BLINK_FROM_HERE, std::move(task));
+  } else {
+    queued_early_tasks_.push_back(
+        QueuedTask{std::move(message), std::move(channels)});
+  }
+}
+
+void DedicatedWorkerMessagingProxy::WorkerThreadCreated() {
+  DCHECK(IsParentContextThread());
+  ThreadedMessagingProxyBase::WorkerThreadCreated();
+
+  for (auto& queued_task : queued_early_tasks_) {
+    WTF::CrossThreadClosure task = CrossThreadBind(
+        &InProcessWorkerObjectProxy::ProcessMessageFromWorkerObject,
+        CrossThreadUnretained(&WorkerObjectProxy()),
+        std::move(queued_task.message),
+        WTF::Passed(std::move(queued_task.channels)),
+        CrossThreadUnretained(GetWorkerThread()));
+    TaskRunnerHelper::Get(TaskType::kPostedMessage, GetWorkerThread())
+        ->PostTask(BLINK_FROM_HERE, std::move(task));
+  }
+  queued_early_tasks_.clear();
+}
+
+bool DedicatedWorkerMessagingProxy::HasPendingActivity() const {
+  DCHECK(IsParentContextThread());
+  return !AskedToTerminate();
+}
+
+void DedicatedWorkerMessagingProxy::PostMessageToWorkerObject(
+    RefPtr<SerializedScriptValue> message,
+    MessagePortChannelArray channels) {
+  DCHECK(IsParentContextThread());
+  if (!worker_object_ || AskedToTerminate())
+    return;
+
+  MessagePortArray* ports =
+      MessagePort::EntanglePorts(*GetExecutionContext(), std::move(channels));
+  worker_object_->DispatchEvent(
+      MessageEvent::Create(ports, std::move(message)));
+}
+
+void DedicatedWorkerMessagingProxy::DispatchErrorEvent(
+    const String& error_message,
+    std::unique_ptr<SourceLocation> location,
+    int exception_id) {
+  DCHECK(IsParentContextThread());
+  if (!worker_object_)
+    return;
+
+  // We don't bother checking the askedToTerminate() flag here, because
+  // exceptions should *always* be reported even if the thread is terminated.
+  // This is intentionally different than the behavior in MessageWorkerTask,
+  // because terminated workers no longer deliver messages (section 4.6 of the
+  // WebWorker spec), but they do report exceptions.
+
+  ErrorEvent* event =
+      ErrorEvent::Create(error_message, location->Clone(), nullptr);
+  if (worker_object_->DispatchEvent(event) != DispatchEventResult::kNotCanceled)
+    return;
+
+  // The HTML spec requires to queue an error event using the DOM manipulation
+  // task source.
+  // https://html.spec.whatwg.org/multipage/workers.html#runtime-script-errors-2
+  TaskRunnerHelper::Get(TaskType::kDOMManipulation, GetWorkerThread())
+      ->PostTask(BLINK_FROM_HERE,
+                 CrossThreadBind(
+                     &InProcessWorkerObjectProxy::ProcessUnhandledException,
+                     CrossThreadUnretained(worker_object_proxy_.get()),
+                     exception_id, CrossThreadUnretained(GetWorkerThread())));
+}
+
+DEFINE_TRACE(DedicatedWorkerMessagingProxy) {
+  visitor->Trace(worker_object_);
+  ThreadedMessagingProxyBase::Trace(visitor);
 }
 
 WTF::Optional<WorkerBackingThreadStartupData>
@@ -30,8 +177,7 @@
       isolate->IsHeapLimitIncreasedForDebugging()
           ? HeapLimitMode::kIncreasedForDebugging
           : HeapLimitMode::kDefault,
-      IsAtomicsWaitAllowed() ? AtomicsWaitMode::kAllow
-                             : AtomicsWaitMode::kDisallow);
+      AtomicsWaitMode::kAllow);
 }
 
 std::unique_ptr<WorkerThread>
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.h b/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.h
index 280af1f..74d03871 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.h
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.h
@@ -5,27 +5,83 @@
 #ifndef DedicatedWorkerMessagingProxy_h
 #define DedicatedWorkerMessagingProxy_h
 
-#include "core/CoreExport.h"
-#include "core/workers/InProcessWorkerMessagingProxy.h"
 #include <memory>
+#include "core/CoreExport.h"
+#include "core/dom/MessagePort.h"
+#include "core/workers/ThreadedMessagingProxyBase.h"
+#include "core/workers/WorkerBackingThreadStartupData.h"
+#include "platform/heap/Handle.h"
+#include "platform/wtf/Noncopyable.h"
+#include "platform/wtf/Optional.h"
+#include "platform/wtf/RefPtr.h"
 
 namespace blink {
 
-class CORE_EXPORT DedicatedWorkerMessagingProxy final
-    : public InProcessWorkerMessagingProxy {
+class InProcessWorkerBase;
+class InProcessWorkerObjectProxy;
+class SerializedScriptValue;
+class WorkerClients;
+
+// TODO(nhiroki): Add the class-level comment once
+// InProcessWorker->DedicatedWorker move is done (https://crbug.com/688116).
+class CORE_EXPORT DedicatedWorkerMessagingProxy
+    : public ThreadedMessagingProxyBase {
   WTF_MAKE_NONCOPYABLE(DedicatedWorkerMessagingProxy);
 
  public:
-  DedicatedWorkerMessagingProxy(InProcessWorkerBase*, WorkerClients*);
+  DedicatedWorkerMessagingProxy(ExecutionContext*,
+                                InProcessWorkerBase*,
+                                WorkerClients*);
   ~DedicatedWorkerMessagingProxy() override;
 
-  bool IsAtomicsWaitAllowed() override;
+  // These methods should only be used on the parent context thread.
+  void StartWorkerGlobalScope(const KURL& script_url,
+                              const String& user_agent,
+                              const String& source_code,
+                              const String& referrer_policy);
+  void PostMessageToWorkerGlobalScope(RefPtr<SerializedScriptValue>,
+                                      MessagePortChannelArray);
+
+  // Implements ThreadedMessagingProxyBase.
+  void WorkerThreadCreated() override;
+
+  bool HasPendingActivity() const;
+
+  // These methods come from worker context thread via
+  // InProcessWorkerObjectProxy and are called on the parent context thread.
+  void PostMessageToWorkerObject(RefPtr<SerializedScriptValue>,
+                                 MessagePortChannelArray);
+  void DispatchErrorEvent(const String& error_message,
+                          std::unique_ptr<SourceLocation>,
+                          int exception_id);
+
+  InProcessWorkerObjectProxy& WorkerObjectProxy() {
+    return *worker_object_proxy_.get();
+  }
+
+  DECLARE_VIRTUAL_TRACE();
 
  private:
+  friend class DedicatedWorkerMessagingProxyForTest;
+
   WTF::Optional<WorkerBackingThreadStartupData> CreateBackingThreadStartupData(
-      v8::Isolate*) override;
+      v8::Isolate*);
 
   std::unique_ptr<WorkerThread> CreateWorkerThread() override;
+
+  std::unique_ptr<InProcessWorkerObjectProxy> worker_object_proxy_;
+
+  // This must be weak. The base class (i.e., ThreadedMessagingProxyBase) has a
+  // strong persistent reference to itself via SelfKeepAlive (see class-level
+  // comments on ThreadedMessagingProxyBase.h for details). To cut the
+  // persistent reference, this worker object needs to call a cleanup function
+  // in its dtor. If this is a strong reference, the dtor is never called
+  // because the worker object is reachable from the persistent reference.
+  WeakMember<InProcessWorkerBase> worker_object_;
+
+  // Tasks are queued here until there's a thread object created.
+  struct QueuedTask;
+  Vector<QueuedTask> queued_early_tasks_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp
index 23f06a7..f86db5a 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp
@@ -9,9 +9,9 @@
 #include "core/inspector/ConsoleMessageStorage.h"
 #include "core/testing/DummyPageHolder.h"
 #include "core/workers/DedicatedWorkerGlobalScope.h"
+#include "core/workers/DedicatedWorkerMessagingProxy.h"
 #include "core/workers/DedicatedWorkerThread.h"
 #include "core/workers/GlobalScopeCreationParams.h"
-#include "core/workers/InProcessWorkerMessagingProxy.h"
 #include "core/workers/InProcessWorkerObjectProxy.h"
 #include "core/workers/WorkerBackingThreadStartupData.h"
 #include "core/workers/WorkerInspectorProxy.h"
@@ -79,11 +79,10 @@
     : public InProcessWorkerObjectProxy {
  public:
   InProcessWorkerObjectProxyForTest(
-      InProcessWorkerMessagingProxy* messaging_proxy,
+      DedicatedWorkerMessagingProxy* messaging_proxy,
       ParentFrameTaskRunners* parent_frame_task_runners)
       : InProcessWorkerObjectProxy(messaging_proxy, parent_frame_task_runners),
-        reported_features_(static_cast<int>(WebFeature::kNumberOfFeatures)) {
-  }
+        reported_features_(static_cast<int>(WebFeature::kNumberOfFeatures)) {}
 
   void CountFeature(WebFeature feature) override {
     // Any feature should be reported only one time.
@@ -103,19 +102,18 @@
   BitVector reported_features_;
 };
 
-class InProcessWorkerMessagingProxyForTest
-    : public InProcessWorkerMessagingProxy {
+class DedicatedWorkerMessagingProxyForTest
+    : public DedicatedWorkerMessagingProxy {
  public:
-  InProcessWorkerMessagingProxyForTest(ExecutionContext* execution_context)
-      : InProcessWorkerMessagingProxy(execution_context,
+  DedicatedWorkerMessagingProxyForTest(ExecutionContext* execution_context)
+      : DedicatedWorkerMessagingProxy(execution_context,
                                       nullptr /* workerObject */,
                                       nullptr /* workerClients */) {
     worker_object_proxy_ = WTF::MakeUnique<InProcessWorkerObjectProxyForTest>(
         this, GetParentFrameTaskRunners());
   }
 
-  ~InProcessWorkerMessagingProxyForTest() override {
-  }
+  ~DedicatedWorkerMessagingProxyForTest() override = default;
 
   void StartWithSourceCode(const String& source) {
     KURL script_url(kParsedURLString, "http://fake.url/");
@@ -129,11 +127,14 @@
         WTF::MakeUnique<GlobalScopeCreationParams>(
             script_url, "fake user agent", source, nullptr /* cachedMetaData */,
             kDontPauseWorkerGlobalScopeOnStart, headers.get(),
-            "" /* referrerPolicy */, security_origin_.Get(),
+            "" /* referrerPolicy */, security_origin_.get(),
             nullptr /* workerClients */, kWebAddressSpaceLocal,
             nullptr /* originTrialTokens */, nullptr /* workerSettings */,
             kV8CacheOptionsDefault),
-        CreateBackingThreadStartupData(nullptr /* isolate */), script_url);
+        WorkerBackingThreadStartupData(
+            WorkerBackingThreadStartupData::HeapLimitMode::kDefault,
+            WorkerBackingThreadStartupData::AtomicsWaitMode::kAllow),
+        script_url);
   }
 
   DedicatedWorkerThreadForTest* GetDedicatedWorkerThread() {
@@ -142,7 +143,7 @@
 
   DEFINE_INLINE_VIRTUAL_TRACE() {
     visitor->Trace(mock_worker_thread_lifecycle_observer_);
-    InProcessWorkerMessagingProxy::Trace(visitor);
+    DedicatedWorkerMessagingProxy::Trace(visitor);
   }
 
  private:
@@ -158,13 +159,6 @@
     return std::move(worker_thread);
   }
 
-  WTF::Optional<WorkerBackingThreadStartupData> CreateBackingThreadStartupData(
-      v8::Isolate*) override {
-    return WorkerBackingThreadStartupData(
-        WorkerBackingThreadStartupData::HeapLimitMode::kDefault,
-        WorkerBackingThreadStartupData::AtomicsWaitMode::kAllow);
-  }
-
   Member<MockWorkerThreadLifecycleObserver>
       mock_worker_thread_lifecycle_observer_;
   RefPtr<SecurityOrigin> security_origin_;
@@ -177,7 +171,7 @@
   void SetUp() override {
     page_ = DummyPageHolder::Create();
     worker_messaging_proxy_ =
-        new InProcessWorkerMessagingProxyForTest(&page_->GetDocument());
+        new DedicatedWorkerMessagingProxyForTest(&page_->GetDocument());
   }
 
   void TearDown() override {
@@ -190,7 +184,7 @@
         nullptr /* message */, MessagePortChannelArray());
   }
 
-  InProcessWorkerMessagingProxyForTest* WorkerMessagingProxy() {
+  DedicatedWorkerMessagingProxyForTest* WorkerMessagingProxy() {
     return worker_messaging_proxy_.Get();
   }
 
@@ -202,7 +196,7 @@
 
  private:
   std::unique_ptr<DummyPageHolder> page_;
-  Persistent<InProcessWorkerMessagingProxyForTest> worker_messaging_proxy_;
+  Persistent<DedicatedWorkerMessagingProxyForTest> worker_messaging_proxy_;
 };
 
 TEST_F(DedicatedWorkerTest, PendingActivity_NoActivityAfterContextDestroyed) {
diff --git a/third_party/WebKit/Source/core/workers/InProcessWorkerBase.cpp b/third_party/WebKit/Source/core/workers/InProcessWorkerBase.cpp
index 3f04a8f..6269f48 100644
--- a/third_party/WebKit/Source/core/workers/InProcessWorkerBase.cpp
+++ b/third_party/WebKit/Source/core/workers/InProcessWorkerBase.cpp
@@ -9,7 +9,7 @@
 #include "core/dom/ExecutionContext.h"
 #include "core/events/MessageEvent.h"
 #include "core/probe/CoreProbes.h"
-#include "core/workers/InProcessWorkerMessagingProxy.h"
+#include "core/workers/DedicatedWorkerMessagingProxy.h"
 #include "core/workers/WorkerScriptLoader.h"
 #include "platform/bindings/ScriptState.h"
 #include "platform/loader/fetch/ResourceFetcher.h"
@@ -67,7 +67,7 @@
       WTF::Bind(&InProcessWorkerBase::OnResponse, WrapPersistent(this)),
       WTF::Bind(&InProcessWorkerBase::OnFinished, WrapPersistent(this)));
 
-  context_proxy_ = CreateInProcessWorkerMessagingProxy(context);
+  context_proxy_ = CreateMessagingProxy(context);
 
   return true;
 }
diff --git a/third_party/WebKit/Source/core/workers/InProcessWorkerBase.h b/third_party/WebKit/Source/core/workers/InProcessWorkerBase.h
index eb1ff835..eed8e5c 100644
--- a/third_party/WebKit/Source/core/workers/InProcessWorkerBase.h
+++ b/third_party/WebKit/Source/core/workers/InProcessWorkerBase.h
@@ -17,9 +17,9 @@
 
 namespace blink {
 
+class DedicatedWorkerMessagingProxy;
 class ExceptionState;
 class ExecutionContext;
-class InProcessWorkerMessagingProxy;
 class ScriptState;
 class WorkerScriptLoader;
 
@@ -60,7 +60,7 @@
   // InProcessWorkerBase does not take ownership of the created proxy. The proxy
   // is expected to manage its own lifetime, and delete itself in response to
   // terminateWorkerGlobalScope().
-  virtual InProcessWorkerMessagingProxy* CreateInProcessWorkerMessagingProxy(
+  virtual DedicatedWorkerMessagingProxy* CreateMessagingProxy(
       ExecutionContext*) = 0;
 
  private:
@@ -70,7 +70,7 @@
 
   RefPtr<WorkerScriptLoader> script_loader_;
 
-  Member<InProcessWorkerMessagingProxy> context_proxy_;
+  Member<DedicatedWorkerMessagingProxy> context_proxy_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.cpp b/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.cpp
deleted file mode 100644
index 72a34ad..0000000
--- a/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
- * Copyright (C) 2009 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:
- * 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.
- *
- */
-
-#include "core/workers/InProcessWorkerMessagingProxy.h"
-
-#include <memory>
-#include "bindings/core/v8/V8CacheOptions.h"
-#include "core/dom/Document.h"
-#include "core/dom/SecurityContext.h"
-#include "core/dom/TaskRunnerHelper.h"
-#include "core/events/ErrorEvent.h"
-#include "core/events/MessageEvent.h"
-#include "core/frame/LocalFrame.h"
-#include "core/frame/csp/ContentSecurityPolicy.h"
-#include "core/loader/DocumentLoadTiming.h"
-#include "core/loader/DocumentLoader.h"
-#include "core/origin_trials/OriginTrialContext.h"
-#include "core/workers/GlobalScopeCreationParams.h"
-#include "core/workers/InProcessWorkerBase.h"
-#include "core/workers/InProcessWorkerObjectProxy.h"
-#include "core/workers/WorkerClients.h"
-#include "core/workers/WorkerGlobalScope.h"
-#include "core/workers/WorkerInspectorProxy.h"
-#include "platform/CrossThreadFunctional.h"
-#include "platform/WebTaskRunner.h"
-#include "platform/wtf/WTF.h"
-
-namespace blink {
-
-struct InProcessWorkerMessagingProxy::QueuedTask {
-  RefPtr<SerializedScriptValue> message;
-  MessagePortChannelArray channels;
-};
-
-InProcessWorkerMessagingProxy::InProcessWorkerMessagingProxy(
-    InProcessWorkerBase* worker_object,
-    WorkerClients* worker_clients)
-    : InProcessWorkerMessagingProxy(worker_object->GetExecutionContext(),
-                                    worker_object,
-                                    worker_clients) {
-  DCHECK(worker_object_);
-}
-
-InProcessWorkerMessagingProxy::InProcessWorkerMessagingProxy(
-    ExecutionContext* execution_context,
-    InProcessWorkerBase* worker_object,
-    WorkerClients* worker_clients)
-    : ThreadedMessagingProxyBase(execution_context, worker_clients),
-      worker_object_(worker_object) {
-  worker_object_proxy_ =
-      InProcessWorkerObjectProxy::Create(this, GetParentFrameTaskRunners());
-}
-
-InProcessWorkerMessagingProxy::~InProcessWorkerMessagingProxy() = default;
-
-void InProcessWorkerMessagingProxy::StartWorkerGlobalScope(
-    const KURL& script_url,
-    const String& user_agent,
-    const String& source_code,
-    const String& referrer_policy) {
-  DCHECK(IsParentContextThread());
-  if (AskedToTerminate()) {
-    // Worker.terminate() could be called from JS before the thread was
-    // created.
-    return;
-  }
-
-  Document* document = ToDocument(GetExecutionContext());
-  SecurityOrigin* starter_origin = document->GetSecurityOrigin();
-
-  ContentSecurityPolicy* csp = document->GetContentSecurityPolicy();
-  DCHECK(csp);
-
-  WorkerThreadStartMode start_mode =
-      GetWorkerInspectorProxy()->WorkerStartMode(document);
-  std::unique_ptr<WorkerSettings> worker_settings =
-      WTF::WrapUnique(new WorkerSettings(document->GetSettings()));
-
-  auto global_scope_creation_params =
-      WTF::MakeUnique<GlobalScopeCreationParams>(
-          script_url, user_agent, source_code, nullptr, start_mode,
-          csp->Headers().get(), referrer_policy, starter_origin,
-          ReleaseWorkerClients(), document->AddressSpace(),
-          OriginTrialContext::GetTokens(document).get(),
-          std::move(worker_settings), kV8CacheOptionsDefault);
-
-  InitializeWorkerThread(std::move(global_scope_creation_params),
-                         CreateBackingThreadStartupData(ToIsolate(document)),
-                         script_url);
-}
-
-void InProcessWorkerMessagingProxy::PostMessageToWorkerObject(
-    RefPtr<SerializedScriptValue> message,
-    MessagePortChannelArray channels) {
-  DCHECK(IsParentContextThread());
-  if (!worker_object_ || AskedToTerminate())
-    return;
-
-  MessagePortArray* ports =
-      MessagePort::EntanglePorts(*GetExecutionContext(), std::move(channels));
-  worker_object_->DispatchEvent(
-      MessageEvent::Create(ports, std::move(message)));
-}
-
-void InProcessWorkerMessagingProxy::PostMessageToWorkerGlobalScope(
-    RefPtr<SerializedScriptValue> message,
-    MessagePortChannelArray channels) {
-  DCHECK(IsParentContextThread());
-  if (AskedToTerminate())
-    return;
-
-  if (GetWorkerThread()) {
-    WTF::CrossThreadClosure task = CrossThreadBind(
-        &InProcessWorkerObjectProxy::ProcessMessageFromWorkerObject,
-        CrossThreadUnretained(&WorkerObjectProxy()), std::move(message),
-        WTF::Passed(std::move(channels)),
-        CrossThreadUnretained(GetWorkerThread()));
-    TaskRunnerHelper::Get(TaskType::kPostedMessage, GetWorkerThread())
-        ->PostTask(BLINK_FROM_HERE, std::move(task));
-  } else {
-    queued_early_tasks_.push_back(
-        QueuedTask{std::move(message), std::move(channels)});
-  }
-}
-
-void InProcessWorkerMessagingProxy::DispatchErrorEvent(
-    const String& error_message,
-    std::unique_ptr<SourceLocation> location,
-    int exception_id) {
-  DCHECK(IsParentContextThread());
-  if (!worker_object_)
-    return;
-
-  // We don't bother checking the askedToTerminate() flag here, because
-  // exceptions should *always* be reported even if the thread is terminated.
-  // This is intentionally different than the behavior in MessageWorkerTask,
-  // because terminated workers no longer deliver messages (section 4.6 of the
-  // WebWorker spec), but they do report exceptions.
-
-  ErrorEvent* event =
-      ErrorEvent::Create(error_message, location->Clone(), nullptr);
-  if (worker_object_->DispatchEvent(event) != DispatchEventResult::kNotCanceled)
-    return;
-
-  // The HTML spec requires to queue an error event using the DOM manipulation
-  // task source.
-  // https://html.spec.whatwg.org/multipage/workers.html#runtime-script-errors-2
-  TaskRunnerHelper::Get(TaskType::kDOMManipulation, GetWorkerThread())
-      ->PostTask(BLINK_FROM_HERE,
-                 CrossThreadBind(
-                     &InProcessWorkerObjectProxy::ProcessUnhandledException,
-                     CrossThreadUnretained(worker_object_proxy_.get()),
-                     exception_id, CrossThreadUnretained(GetWorkerThread())));
-}
-
-void InProcessWorkerMessagingProxy::WorkerThreadCreated() {
-  DCHECK(IsParentContextThread());
-  ThreadedMessagingProxyBase::WorkerThreadCreated();
-
-  for (auto& queued_task : queued_early_tasks_) {
-    WTF::CrossThreadClosure task = CrossThreadBind(
-        &InProcessWorkerObjectProxy::ProcessMessageFromWorkerObject,
-        CrossThreadUnretained(&WorkerObjectProxy()),
-        std::move(queued_task.message),
-        WTF::Passed(std::move(queued_task.channels)),
-        CrossThreadUnretained(GetWorkerThread()));
-    TaskRunnerHelper::Get(TaskType::kPostedMessage, GetWorkerThread())
-        ->PostTask(BLINK_FROM_HERE, std::move(task));
-  }
-  queued_early_tasks_.clear();
-}
-
-DEFINE_TRACE(InProcessWorkerMessagingProxy) {
-  visitor->Trace(worker_object_);
-  ThreadedMessagingProxyBase::Trace(visitor);
-}
-
-bool InProcessWorkerMessagingProxy::HasPendingActivity() const {
-  DCHECK(IsParentContextThread());
-  return !AskedToTerminate();
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.h b/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.h
deleted file mode 100644
index bd643be..0000000
--- a/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2008 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 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.
- *
- */
-
-#ifndef InProcessWorkerMessagingProxy_h
-#define InProcessWorkerMessagingProxy_h
-
-#include <memory>
-#include "core/CoreExport.h"
-#include "core/dom/ExecutionContext.h"
-#include "core/dom/MessagePort.h"
-#include "core/workers/ThreadedMessagingProxyBase.h"
-#include "core/workers/WorkerBackingThreadStartupData.h"
-#include "platform/heap/Handle.h"
-#include "platform/wtf/Noncopyable.h"
-#include "platform/wtf/Optional.h"
-#include "platform/wtf/RefPtr.h"
-
-namespace blink {
-
-class ExecutionContext;
-class InProcessWorkerBase;
-class InProcessWorkerObjectProxy;
-class SerializedScriptValue;
-class WorkerClients;
-
-class CORE_EXPORT InProcessWorkerMessagingProxy
-    : public ThreadedMessagingProxyBase {
-  WTF_MAKE_NONCOPYABLE(InProcessWorkerMessagingProxy);
-
- public:
-  // These methods should only be used on the parent context thread.
-  void StartWorkerGlobalScope(const KURL& script_url,
-                              const String& user_agent,
-                              const String& source_code,
-                              const String& referrer_policy);
-  void PostMessageToWorkerGlobalScope(RefPtr<SerializedScriptValue>,
-                                      MessagePortChannelArray);
-
-  // Implements ThreadedMessagingProxyBase.
-  void WorkerThreadCreated() override;
-
-  bool HasPendingActivity() const;
-
-  // These methods come from worker context thread via
-  // InProcessWorkerObjectProxy and are called on the parent context thread.
-  void PostMessageToWorkerObject(RefPtr<SerializedScriptValue>,
-                                 MessagePortChannelArray);
-  void DispatchErrorEvent(const String& error_message,
-                          std::unique_ptr<SourceLocation>,
-                          int exception_id);
-
-  DECLARE_VIRTUAL_TRACE();
-
- protected:
-  InProcessWorkerMessagingProxy(InProcessWorkerBase*, WorkerClients*);
-  ~InProcessWorkerMessagingProxy() override;
-
-  InProcessWorkerObjectProxy& WorkerObjectProxy() {
-    return *worker_object_proxy_.get();
-  }
-
-  // Whether Atomics.wait (a blocking function call) is allowed on this thread.
-  virtual bool IsAtomicsWaitAllowed() { return false; }
-
- private:
-  friend class InProcessWorkerMessagingProxyForTest;
-  InProcessWorkerMessagingProxy(ExecutionContext*,
-                                InProcessWorkerBase*,
-                                WorkerClients*);
-
-  // TODO(nhiroki): Remove this creation function once we no longer have
-  // CompositorWorker.
-  virtual WTF::Optional<WorkerBackingThreadStartupData>
-  CreateBackingThreadStartupData(v8::Isolate*) = 0;
-
-  std::unique_ptr<InProcessWorkerObjectProxy> worker_object_proxy_;
-
-  // This must be weak. The base class (i.e., ThreadedMessagingProxyBase) has a
-  // strong persistent reference to itself via SelfKeepAlive (see class-level
-  // comments on ThreadedMessagingProxyBase.h for details). To cut the
-  // persistent reference, this worker object needs to call a cleanup function
-  // in its dtor. If this is a strong reference, the dtor is never called
-  // because the worker object is reachable from the persistent reference.
-  WeakMember<InProcessWorkerBase> worker_object_;
-
-  // Tasks are queued here until there's a thread object created.
-  struct QueuedTask;
-  Vector<QueuedTask> queued_early_tasks_;
-};
-
-}  // namespace blink
-
-#endif  // InProcessWorkerMessagingProxy_h
diff --git a/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.cpp b/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.cpp
index b366fac6..8c4f6df 100644
--- a/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.cpp
+++ b/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.cpp
@@ -38,7 +38,7 @@
 #include "core/dom/TaskRunnerHelper.h"
 #include "core/events/MessageEvent.h"
 #include "core/inspector/ConsoleMessage.h"
-#include "core/workers/InProcessWorkerMessagingProxy.h"
+#include "core/workers/DedicatedWorkerMessagingProxy.h"
 #include "core/workers/ParentFrameTaskRunners.h"
 #include "core/workers/WorkerGlobalScope.h"
 #include "core/workers/WorkerThread.h"
@@ -51,7 +51,7 @@
 namespace blink {
 
 std::unique_ptr<InProcessWorkerObjectProxy> InProcessWorkerObjectProxy::Create(
-    InProcessWorkerMessagingProxy* messaging_proxy_weak_ptr,
+    DedicatedWorkerMessagingProxy* messaging_proxy_weak_ptr,
     ParentFrameTaskRunners* parent_frame_task_runners) {
   DCHECK(messaging_proxy_weak_ptr);
   return WTF::WrapUnique(new InProcessWorkerObjectProxy(
@@ -67,7 +67,7 @@
       ->Get(TaskType::kPostedMessage)
       ->PostTask(BLINK_FROM_HERE,
                  CrossThreadBind(
-                     &InProcessWorkerMessagingProxy::PostMessageToWorkerObject,
+                     &DedicatedWorkerMessagingProxy::PostMessageToWorkerObject,
                      messaging_proxy_weak_ptr_, std::move(message),
                      WTF::Passed(std::move(channels))));
 }
@@ -99,7 +99,7 @@
       ->Get(TaskType::kUnspecedTimer)
       ->PostTask(
           BLINK_FROM_HERE,
-          CrossThreadBind(&InProcessWorkerMessagingProxy::DispatchErrorEvent,
+          CrossThreadBind(&DedicatedWorkerMessagingProxy::DispatchErrorEvent,
                           messaging_proxy_weak_ptr_, error_message,
                           WTF::Passed(location->Clone()), exception_id));
 }
@@ -115,7 +115,7 @@
 }
 
 InProcessWorkerObjectProxy::InProcessWorkerObjectProxy(
-    InProcessWorkerMessagingProxy* messaging_proxy_weak_ptr,
+    DedicatedWorkerMessagingProxy* messaging_proxy_weak_ptr,
     ParentFrameTaskRunners* parent_frame_task_runners)
     : ThreadedObjectProxyBase(parent_frame_task_runners),
       messaging_proxy_weak_ptr_(messaging_proxy_weak_ptr) {}
diff --git a/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.h b/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.h
index e5b10bf..d4130a1e 100644
--- a/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.h
+++ b/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.h
@@ -42,7 +42,7 @@
 
 namespace blink {
 
-class InProcessWorkerMessagingProxy;
+class DedicatedWorkerMessagingProxy;
 class ParentFrameTaskRunners;
 class ThreadedMessagingProxyBase;
 class WorkerGlobalScope;
@@ -60,7 +60,7 @@
 
  public:
   static std::unique_ptr<InProcessWorkerObjectProxy> Create(
-      InProcessWorkerMessagingProxy*,
+      DedicatedWorkerMessagingProxy*,
       ParentFrameTaskRunners*);
   ~InProcessWorkerObjectProxy() override;
 
@@ -79,7 +79,7 @@
   void WillDestroyWorkerGlobalScope() override;
 
  protected:
-  InProcessWorkerObjectProxy(InProcessWorkerMessagingProxy*,
+  InProcessWorkerObjectProxy(DedicatedWorkerMessagingProxy*,
                              ParentFrameTaskRunners*);
 
   CrossThreadWeakPersistent<ThreadedMessagingProxyBase> MessagingProxyWeakPtr()
@@ -89,9 +89,9 @@
   friend class InProcessWorkerObjectProxyForTest;
 
   // No guarantees about the lifetimes of tasks posted by this proxy wrt the
-  // InProcessWorkerMessagingProxy so a weak pointer must be used when posting
+  // DedicatedWorkerMessagingProxy so a weak pointer must be used when posting
   // the tasks.
-  CrossThreadWeakPersistent<InProcessWorkerMessagingProxy>
+  CrossThreadWeakPersistent<DedicatedWorkerMessagingProxy>
       messaging_proxy_weak_ptr_;
 
   CrossThreadPersistent<WorkerGlobalScope> worker_global_scope_;
diff --git a/third_party/WebKit/Source/core/workers/MainThreadWorkletTest.cpp b/third_party/WebKit/Source/core/workers/MainThreadWorkletTest.cpp
index 5438647..7e27a5b 100644
--- a/third_party/WebKit/Source/core/workers/MainThreadWorkletTest.cpp
+++ b/third_party/WebKit/Source/core/workers/MainThreadWorkletTest.cpp
@@ -47,7 +47,7 @@
     reporting_proxy_ = WTF::MakeUnique<MainThreadWorkletReportingProxyForTest>(
         page_->GetFrame().GetDocument());
     global_scope_ = new MainThreadWorkletGlobalScope(
-        &page_->GetFrame(), url, "fake user agent", security_origin_.Get(),
+        &page_->GetFrame(), url, "fake user agent", security_origin_.get(),
         ToIsolate(page_->GetFrame().GetDocument()), *reporting_proxy_);
   }
 
diff --git a/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp b/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp
index d5de0ec..f6c5bc7d 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp
+++ b/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp
@@ -149,7 +149,7 @@
             script_url, "fake user agent", "// fake source code",
             std::move(cached_meta_data), kDontPauseWorkerGlobalScopeOnStart,
             &content_security_policy_headers, referrer_policy,
-            security_origin_.Get(), worker_clients, kWebAddressSpaceLocal,
+            security_origin_.get(), worker_clients, kWebAddressSpaceLocal,
             &origin_trial_tokens, std::move(worker_settings),
             kV8CacheOptionsDefault),
         WTF::nullopt, script_url);
diff --git a/third_party/WebKit/Source/core/workers/Worker.cpp b/third_party/WebKit/Source/core/workers/Worker.cpp
index b634d0ca..b9ba46f 100644
--- a/third_party/WebKit/Source/core/workers/Worker.cpp
+++ b/third_party/WebKit/Source/core/workers/Worker.cpp
@@ -44,7 +44,7 @@
   return EventTargetNames::Worker;
 }
 
-InProcessWorkerMessagingProxy* Worker::CreateInProcessWorkerMessagingProxy(
+DedicatedWorkerMessagingProxy* Worker::CreateMessagingProxy(
     ExecutionContext* context) {
   Document* document = ToDocument(context);
   WebLocalFrameImpl* web_frame =
@@ -57,7 +57,7 @@
       *worker_clients);
   ProvideContentSettingsClientToWorker(
       worker_clients, web_frame->Client()->CreateWorkerContentSettingsClient());
-  return new DedicatedWorkerMessagingProxy(this, worker_clients);
+  return new DedicatedWorkerMessagingProxy(context, this, worker_clients);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/Worker.h b/third_party/WebKit/Source/core/workers/Worker.h
index 6e161d6..5c0fc678 100644
--- a/third_party/WebKit/Source/core/workers/Worker.h
+++ b/third_party/WebKit/Source/core/workers/Worker.h
@@ -11,9 +11,9 @@
 
 namespace blink {
 
+class DedicatedWorkerMessagingProxy;
 class ExceptionState;
 class ExecutionContext;
-class InProcessWorkerMessagingProxy;
 
 class CORE_EXPORT Worker final : public InProcessWorkerBase {
   DEFINE_WRAPPERTYPEINFO();
@@ -26,7 +26,7 @@
  protected:
   explicit Worker(ExecutionContext*);
 
-  InProcessWorkerMessagingProxy* CreateInProcessWorkerMessagingProxy(
+  DedicatedWorkerMessagingProxy* CreateMessagingProxy(
       ExecutionContext*) override;
   const AtomicString& InterfaceName() const override;
 };
diff --git a/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp b/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp
index a559965..cef7d80 100644
--- a/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp
@@ -81,7 +81,7 @@
   void TearDown() override {}
 
   void Start() {
-    worker_thread_->StartWithSourceCode(security_origin_.Get(),
+    worker_thread_->StartWithSourceCode(security_origin_.get(),
                                         "//fake source code",
                                         ParentFrameTaskRunners::Create());
   }
@@ -89,7 +89,7 @@
   void StartWithSourceCodeNotToFinish() {
     // Use a JavaScript source code that makes an infinite loop so that we
     // can catch some kind of issues as a timeout.
-    worker_thread_->StartWithSourceCode(security_origin_.Get(),
+    worker_thread_->StartWithSourceCode(security_origin_.get(),
                                         "while(true) {}",
                                         ParentFrameTaskRunners::Create());
   }
@@ -304,7 +304,7 @@
           KURL(kParsedURLString, "http://fake.url/"), "fake user agent",
           "//fake source code", nullptr, /* cachedMetaData */
           kPauseWorkerGlobalScopeOnStart, headers.get(), "",
-          security_origin_.Get(), nullptr, /* workerClients */
+          security_origin_.get(), nullptr, /* workerClients */
           kWebAddressSpaceLocal, nullptr /* originTrialToken */,
           nullptr /* WorkerSettings */, kV8CacheOptionsDefault);
   worker_thread_->Start(std::move(global_scope_creation_params),
diff --git a/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h b/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h
index 3447b09..c41614a 100644
--- a/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h
+++ b/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h
@@ -52,63 +52,11 @@
   MOCK_METHOD1(ContextDestroyed, void(WorkerThreadLifecycleContext*));
 };
 
-class WorkerThreadForTest : public WorkerThread {
- public:
-  WorkerThreadForTest(ThreadableLoadingContext* loading_context,
-                      WorkerReportingProxy& mock_worker_reporting_proxy)
-      : WorkerThread(loading_context, mock_worker_reporting_proxy),
-        worker_backing_thread_(
-            WorkerBackingThread::CreateForTest("Test thread")) {}
-
-  ~WorkerThreadForTest() override {}
-
-  WorkerBackingThread& GetWorkerBackingThread() override {
-    return *worker_backing_thread_;
-  }
-  void ClearWorkerBackingThread() override { worker_backing_thread_ = nullptr; }
-
-  WorkerOrWorkletGlobalScope* CreateWorkerGlobalScope(
-      std::unique_ptr<GlobalScopeCreationParams>) override;
-
-  void StartWithSourceCode(SecurityOrigin* security_origin,
-                           const String& source,
-                           ParentFrameTaskRunners* parent_frame_task_runners) {
-    std::unique_ptr<Vector<CSPHeaderAndType>> headers =
-        WTF::MakeUnique<Vector<CSPHeaderAndType>>();
-    CSPHeaderAndType header_and_type("contentSecurityPolicy",
-                                     kContentSecurityPolicyHeaderTypeReport);
-    headers->push_back(header_and_type);
-
-    WorkerClients* clients = nullptr;
-
-    Start(WTF::MakeUnique<GlobalScopeCreationParams>(
-              KURL(kParsedURLString, "http://fake.url/"), "fake user agent",
-              source, nullptr, kDontPauseWorkerGlobalScopeOnStart,
-              headers.get(), "", security_origin, clients,
-              kWebAddressSpaceLocal, nullptr, nullptr, kV8CacheOptionsDefault),
-          WorkerBackingThreadStartupData::CreateDefault(),
-          parent_frame_task_runners);
-  }
-
-  void WaitForInit() {
-    std::unique_ptr<WaitableEvent> completion_event =
-        WTF::MakeUnique<WaitableEvent>();
-    GetWorkerBackingThread().BackingThread().PostTask(
-        BLINK_FROM_HERE,
-        CrossThreadBind(&WaitableEvent::Signal,
-                        CrossThreadUnretained(completion_event.get())));
-    completion_event->Wait();
-  }
-
- private:
-  std::unique_ptr<WorkerBackingThread> worker_backing_thread_;
-};
-
 class FakeWorkerGlobalScope : public WorkerGlobalScope {
  public:
   FakeWorkerGlobalScope(const KURL& url,
                         const String& user_agent,
-                        WorkerThreadForTest* thread,
+                        WorkerThread* thread,
                         std::unique_ptr<SecurityOrigin::PrivilegeData>
                             starter_origin_privilege_data,
                         WorkerClients* worker_clients)
@@ -129,13 +77,62 @@
   void ExceptionThrown(ErrorEvent*) override {}
 };
 
-inline WorkerOrWorkletGlobalScope* WorkerThreadForTest::CreateWorkerGlobalScope(
-    std::unique_ptr<GlobalScopeCreationParams> creation_params) {
-  return new FakeWorkerGlobalScope(
-      creation_params->script_url, creation_params->user_agent, this,
-      std::move(creation_params->starter_origin_privilege_data),
-      std::move(creation_params->worker_clients));
-}
+class WorkerThreadForTest : public WorkerThread {
+ public:
+  WorkerThreadForTest(ThreadableLoadingContext* loading_context,
+                      WorkerReportingProxy& mock_worker_reporting_proxy)
+      : WorkerThread(loading_context, mock_worker_reporting_proxy),
+        worker_backing_thread_(
+            WorkerBackingThread::CreateForTest("Test thread")) {}
+
+  ~WorkerThreadForTest() override {}
+
+  WorkerBackingThread& GetWorkerBackingThread() override {
+    return *worker_backing_thread_;
+  }
+  void ClearWorkerBackingThread() override { worker_backing_thread_.reset(); }
+
+  void StartWithSourceCode(SecurityOrigin* security_origin,
+                           const String& source,
+                           ParentFrameTaskRunners* parent_frame_task_runners,
+                           WorkerClients* worker_clients = nullptr) {
+    auto headers = WTF::MakeUnique<Vector<CSPHeaderAndType>>();
+    CSPHeaderAndType header_and_type("contentSecurityPolicy",
+                                     kContentSecurityPolicyHeaderTypeReport);
+    headers->push_back(header_and_type);
+
+    auto creation_params = WTF::MakeUnique<GlobalScopeCreationParams>(
+        KURL(kParsedURLString, "http://fake.url/"), "fake user agent", source,
+        nullptr, kDontPauseWorkerGlobalScopeOnStart, headers.get(), "",
+        security_origin, worker_clients, kWebAddressSpaceLocal, nullptr,
+        nullptr, kV8CacheOptionsDefault);
+
+    Start(std::move(creation_params),
+          WorkerBackingThreadStartupData::CreateDefault(),
+          parent_frame_task_runners);
+  }
+
+  void WaitForInit() {
+    WaitableEvent completion_event;
+    GetWorkerBackingThread().BackingThread().PostTask(
+        BLINK_FROM_HERE,
+        CrossThreadBind(&WaitableEvent::Signal,
+                        CrossThreadUnretained(&completion_event)));
+    completion_event.Wait();
+  }
+
+ protected:
+  WorkerOrWorkletGlobalScope* CreateWorkerGlobalScope(
+      std::unique_ptr<GlobalScopeCreationParams> creation_params) override {
+    return new FakeWorkerGlobalScope(
+        creation_params->script_url, creation_params->user_agent, this,
+        std::move(creation_params->starter_origin_privilege_data),
+        std::move(creation_params->worker_clients));
+  }
+
+ private:
+  std::unique_ptr<WorkerBackingThread> worker_backing_thread_;
+};
 
 }  // namespace blink
 
diff --git a/third_party/WebKit/Source/core/xml/parser/XMLDocumentParser.cpp b/third_party/WebKit/Source/core/xml/parser/XMLDocumentParser.cpp
index e8dc5e17..1a8b5f63 100644
--- a/third_party/WebKit/Source/core/xml/parser/XMLDocumentParser.cpp
+++ b/third_party/WebKit/Source/core/xml/parser/XMLDocumentParser.cpp
@@ -1022,14 +1022,14 @@
     return;
   }
 
-  if (isHTMLTemplateElement(*new_element))
-    PushCurrentNode(toHTMLTemplateElement(*new_element).content());
+  if (auto* template_element = ToHTMLTemplateElementOrNull(*new_element))
+    PushCurrentNode(template_element->content());
   else
     PushCurrentNode(new_element);
 
   // Note: |insertedByParser| will perform dispatching if this is an
   // HTMLHtmlElement.
-  if (isHTMLHtmlElement(*new_element) && is_first_element) {
+  if (IsHTMLHtmlElement(*new_element) && is_first_element) {
     toHTMLHtmlElement(*new_element).InsertedByParser();
   } else if (!parsing_fragment_ && is_first_element &&
              GetDocument()->GetFrame()) {
diff --git a/third_party/WebKit/Source/core/xml/parser/XMLDocumentParser.h b/third_party/WebKit/Source/core/xml/parser/XMLDocumentParser.h
index 428224b..5d1146d 100644
--- a/third_party/WebKit/Source/core/xml/parser/XMLDocumentParser.h
+++ b/third_party/WebKit/Source/core/xml/parser/XMLDocumentParser.h
@@ -97,7 +97,7 @@
   static bool ParseDocumentFragment(
       const String&,
       DocumentFragment*,
-      Element* parent = 0,
+      Element* parent = nullptr,
       ParserContentPolicy = kAllowScriptingContent);
 
   // Used by the XMLHttpRequest to check if the responseXML was well formed.
@@ -118,7 +118,7 @@
   void SetScriptStartPosition(TextPosition);
 
  private:
-  explicit XMLDocumentParser(Document&, LocalFrameView* = 0);
+  explicit XMLDocumentParser(Document&, LocalFrameView* = nullptr);
   XMLDocumentParser(DocumentFragment*, Element*, ParserContentPolicy);
 
   // From DocumentParser
diff --git a/third_party/WebKit/Source/core/xml/parser/XMLDocumentParserScope.cpp b/third_party/WebKit/Source/core/xml/parser/XMLDocumentParserScope.cpp
index 559cf11..a906e151 100644
--- a/third_party/WebKit/Source/core/xml/parser/XMLDocumentParserScope.cpp
+++ b/third_party/WebKit/Source/core/xml/parser/XMLDocumentParserScope.cpp
@@ -27,7 +27,7 @@
 
 namespace blink {
 
-Document* XMLDocumentParserScope::current_document_ = 0;
+Document* XMLDocumentParserScope::current_document_ = nullptr;
 
 XMLDocumentParserScope::XMLDocumentParserScope(Document* document)
     : old_document_(current_document_),
diff --git a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
index ce3f8c3..aeaa5de 100644
--- a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
+++ b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
@@ -327,7 +327,7 @@
 
 SecurityOrigin* XMLHttpRequest::GetSecurityOrigin() const {
   return isolated_world_security_origin_
-             ? isolated_world_security_origin_.Get()
+             ? isolated_world_security_origin_.get()
              : GetExecutionContext()->GetSecurityOrigin();
 }
 
@@ -779,43 +779,43 @@
     ExceptionState& exception_state) {
   probe::willSendXMLHttpOrFetchNetworkRequest(GetExecutionContext(), Url());
 
-  if (body.isNull()) {
+  if (body.IsNull()) {
     send(String(), exception_state);
     return;
   }
 
-  if (body.isArrayBuffer()) {
-    send(body.getAsArrayBuffer(), exception_state);
+  if (body.IsArrayBuffer()) {
+    send(body.GetAsArrayBuffer(), exception_state);
     return;
   }
 
-  if (body.isArrayBufferView()) {
-    send(body.getAsArrayBufferView().View(), exception_state);
+  if (body.IsArrayBufferView()) {
+    send(body.GetAsArrayBufferView().View(), exception_state);
     return;
   }
 
-  if (body.isBlob()) {
-    send(body.getAsBlob(), exception_state);
+  if (body.IsBlob()) {
+    send(body.GetAsBlob(), exception_state);
     return;
   }
 
-  if (body.isDocument()) {
-    send(body.getAsDocument(), exception_state);
+  if (body.IsDocument()) {
+    send(body.GetAsDocument(), exception_state);
     return;
   }
 
-  if (body.isFormData()) {
-    send(body.getAsFormData(), exception_state);
+  if (body.IsFormData()) {
+    send(body.GetAsFormData(), exception_state);
     return;
   }
 
-  if (body.isURLSearchParams()) {
-    send(body.getAsURLSearchParams(), exception_state);
+  if (body.IsURLSearchParams()) {
+    send(body.GetAsURLSearchParams(), exception_state);
     return;
   }
 
-  DCHECK(body.isString());
-  send(body.getAsString(), exception_state);
+  DCHECK(body.IsString());
+  send(body.GetAsString(), exception_state);
 }
 
 bool XMLHttpRequest::AreMethodAndURLValidForSend() {
diff --git a/third_party/WebKit/Source/devtools/front_end/Tests.js b/third_party/WebKit/Source/devtools/front_end/Tests.js
index deeccf62..e6c0d06e 100644
--- a/third_party/WebKit/Source/devtools/front_end/Tests.js
+++ b/third_party/WebKit/Source/devtools/front_end/Tests.js
@@ -974,6 +974,13 @@
     }
   };
 
+  TestSuite.prototype.testDOMWarnings = function() {
+    var messages = ConsoleModel.consoleModel.messages();
+    this.assertEquals(1, messages.length);
+    var expectedPrefix = '[DOM] Found 2 elements with non-unique id #dup:';
+    this.assertTrue(messages[0].messageText.startsWith(expectedPrefix));
+  };
+
   TestSuite.prototype.waitForTestResultsInConsole = function() {
     var messages = ConsoleModel.consoleModel.messages();
     for (var i = 0; i < messages.length; ++i) {
diff --git a/third_party/WebKit/Source/devtools/front_end/accessibility/AXBreadcrumbsPane.js b/third_party/WebKit/Source/devtools/front_end/accessibility/AXBreadcrumbsPane.js
index 3d9bf5d..1b07bcc 100644
--- a/third_party/WebKit/Source/devtools/front_end/accessibility/AXBreadcrumbsPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/accessibility/AXBreadcrumbsPane.js
@@ -73,11 +73,23 @@
 
     this._setPreselectedBreadcrumb(this._inspectedNodeBreadcrumb);
 
-    for (var child of axNode.children()) {
-      var childBreadcrumb = new Accessibility.AXBreadcrumb(child, depth, false);
-      this._inspectedNodeBreadcrumb.appendChild(childBreadcrumb);
+    /**
+     * @param {!Accessibility.AXBreadcrumb} parentBreadcrumb
+     * @param {!Accessibility.AccessibilityNode} axNode
+     * @param {number} localDepth
+     */
+    function append(parentBreadcrumb, axNode, localDepth) {
+      var childBreadcrumb = new Accessibility.AXBreadcrumb(axNode, localDepth, false);
+      parentBreadcrumb.appendChild(childBreadcrumb);
+
+      // In most cases there will be no children here, but there are some special cases.
+      for (var child of axNode.children())
+        append(childBreadcrumb, child, localDepth + 1);
     }
 
+    for (var child of axNode.children())
+      append(this._inspectedNodeBreadcrumb, child, depth);
+
     this._selectedByUser = false;
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/accessibility/AccessibilityNodeView.js b/third_party/WebKit/Source/devtools/front_end/accessibility/AccessibilityNodeView.js
index 1cac76ee..57bcbc4 100644
--- a/third_party/WebKit/Source/devtools/front_end/accessibility/AccessibilityNodeView.js
+++ b/third_party/WebKit/Source/devtools/front_end/accessibility/AccessibilityNodeView.js
@@ -570,10 +570,6 @@
       case 'activeModalDialog':
         reasonElement = UI.formatLocalized('Element is hidden by active modal dialog:\u00a0', []);
         break;
-      case 'ancestorDisallowsChild':
-        reasonElement = UI.formatLocalized('Element is not permitted as child of ', []);
-        break;
-      // http://www.w3.org/TR/wai-aria/roles#childrenArePresentational
       case 'ancestorIsLeafNode':
         reasonElement = UI.formatLocalized('Ancestor\'s children are all presentational:\u00a0', []);
         break;
@@ -581,7 +577,7 @@
         var ariaHiddenSpan = createElement('span', 'source-code').textContent = 'aria-hidden';
         reasonElement = UI.formatLocalized('Element is %s.', [ariaHiddenSpan]);
         break;
-      case 'ariaHiddenSubTree':
+      case 'ariaHiddenSubtree':
         var ariaHiddenSpan = createElement('span', 'source-code').textContent = 'aria-hidden';
         var trueSpan = createElement('span', 'source-code').textContent = 'true';
         reasonElement = UI.formatLocalized('%s is %s on ancestor:\u00a0', [ariaHiddenSpan, trueSpan]);
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 85c3f80..3e4d2e8 100644
--- a/third_party/WebKit/Source/devtools/front_end/audits2/audits2Panel.css
+++ b/third_party/WebKit/Source/devtools/front_end/audits2/audits2Panel.css
@@ -52,6 +52,10 @@
   background: #fff;
 }
 
+.lh-root .lh-container {
+  word-wrap: normal;
+}
+
 .audits2-landing-center button {
     margin-top: 20px;
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/audits2/lighthouse/report-styles.css b/third_party/WebKit/Source/devtools/front_end/audits2/lighthouse/report-styles.css
index 1a68eb6..229bc4e 100644
--- a/third_party/WebKit/Source/devtools/front_end/audits2/lighthouse/report-styles.css
+++ b/third_party/WebKit/Source/devtools/front_end/audits2/lighthouse/report-styles.css
@@ -685,6 +685,7 @@
 .lh-container {
   display: flex;
   max-width: var(--report-content-width);
+  word-wrap: break-word;
   margin: 0 auto;
 }
 
@@ -885,3 +886,4 @@
   object-fit: contain;
 }
 
+/*# sourceURL=report.styles.css */
diff --git a/third_party/WebKit/Source/devtools/front_end/audits2_worker/lighthouse/lighthouse-background.js b/third_party/WebKit/Source/devtools/front_end/audits2_worker/lighthouse/lighthouse-background.js
index b6757c78..9a988aa8 100644
--- a/third_party/WebKit/Source/devtools/front_end/audits2_worker/lighthouse/lighthouse-background.js
+++ b/third_party/WebKit/Source/devtools/front_end/audits2_worker/lighthouse/lighthouse-background.js
@@ -3480,7 +3480,8 @@
 name:'password-inputs-can-be-pasted-into',
 description:'Allows users to paste into password fields',
 failureDescription:'Prevents users to paste into password fields',
-helpText:'',
+helpText:'Preventing password pasting undermines good security policy. '+
+'[Learn more](https://www.ncsc.gov.uk/blog-post/let-them-paste-passwords)',
 requiredArtifacts:['PasswordInputsWithPreventedPaste']};
 
 }
@@ -8885,13 +8886,17 @@
 if(typeof auditDefinition.meta.failureDescription!=='string'&&
 auditDefinition.meta.informative!==true&&
 auditDefinition.meta.scoringMode!==Audit.SCORING_MODES.NUMERIC){
-log.warn('config',`${auditName} has no failureDescription and should.`);
+throw new Error(`${auditName} has no failureDescription and should.`);
 }
 
 if(typeof auditDefinition.meta.helpText!=='string'){
 throw new Error(
 `${auditName} has no meta.helpText property, or the property is not a string.`);
 
+}else if(auditDefinition.meta.helpText===''){
+throw new Error(
+`${auditName} has an empty meta.helpText string. Please add a description for the UI.`);
+
 }
 
 if(!Array.isArray(auditDefinition.meta.requiredArtifacts)){
@@ -10714,9 +10719,14 @@
 
 
 return this._beginNetworkStatusMonitoring(url).
-then(_=>this.sendCommand('Page.enable')).
-then(_=>this.sendCommand('Emulation.setScriptExecutionDisabled',{value:disableJS})).
-then(_=>this.sendCommand('Page.navigate',{url})).
+then(_=>{
+
+
+
+this.sendCommand('Page.enable');
+this.sendCommand('Emulation.setScriptExecutionDisabled',{value:disableJS});
+this.sendCommand('Page.navigate',{url});
+}).
 then(_=>waitForLoad&&this._waitForFullyLoaded(pauseAfterLoadMs,
 networkQuietThresholdMs,cpuQuietThresholdMs,maxWaitMs)).
 then(_=>this._endNetworkStatusMonitoring());
@@ -48901,6 +48911,6 @@
 
 },{"image-ssim":105}],115:[function(require,module,exports){
 module.exports={
-"version":"2.3.0"};
+"version":"2.3.1"};
 
 },{}]},{},[35]);
\ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js b/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js
index c083079..38df4776 100644
--- a/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js
+++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js
@@ -256,13 +256,17 @@
         messageElement = this._format([messageText]);
       }
     } else {
+      var messageInParameters =
+          this._message.parameters && messageText === /** @type {string} */ (this._message.parameters[0]);
       if (this._message.source === ConsoleModel.ConsoleMessage.MessageSource.Violation)
         messageText = Common.UIString('[Violation] %s', messageText);
       else if (this._message.source === ConsoleModel.ConsoleMessage.MessageSource.Intervention)
         messageText = Common.UIString('[Intervention] %s', messageText);
-      if (this._message.source === ConsoleModel.ConsoleMessage.MessageSource.Deprecation)
+      else if (this._message.source === ConsoleModel.ConsoleMessage.MessageSource.Deprecation)
         messageText = Common.UIString('[Deprecation] %s', messageText);
       var args = this._message.parameters || [messageText];
+      if (messageInParameters)
+        args[0] = messageText;
       messageElement = this._format(args);
     }
     messageElement.classList.add('console-message-text');
@@ -762,12 +766,13 @@
 
     /**
      * @param {boolean} force
+     * @param {boolean} includePreview
      * @param {!SDK.RemoteObject} obj
      * @return {!Element}
      * @this {Console.ConsoleViewMessage}
      */
-    function parameterFormatter(force, obj) {
-      return this._formatParameter(obj, force, false);
+    function parameterFormatter(force, includePreview, obj) {
+      return this._formatParameter(obj, force, includePreview);
     }
 
     function stringFormatter(obj) {
@@ -815,7 +820,7 @@
     }
 
     // Firebug uses %o for formatting objects.
-    formatters.o = parameterFormatter.bind(this, false);
+    formatters.o = parameterFormatter.bind(this, false /* force */, true /* includePreview */);
     formatters.s = stringFormatter;
     formatters.f = floatFormatter;
     // Firebug allows both %i and %d for formatting integers.
@@ -826,7 +831,7 @@
     formatters.c = styleFormatter;
 
     // Support %O to force object formatting, instead of the type-based %o formatting.
-    formatters.O = parameterFormatter.bind(this, true);
+    formatters.O = parameterFormatter.bind(this, true /* force */, false /* includePreview */);
 
     formatters._ = bypassFormatter;
 
@@ -1030,6 +1035,7 @@
         case ConsoleModel.ConsoleMessage.MessageSource.Violation:
         case ConsoleModel.ConsoleMessage.MessageSource.Deprecation:
         case ConsoleModel.ConsoleMessage.MessageSource.Intervention:
+        case ConsoleModel.ConsoleMessage.MessageSource.Recommendation:
           this._element.classList.add('console-warning-level');
           break;
       }
diff --git a/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js b/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js
index dd6f469b..5af64b4 100644
--- a/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js
@@ -194,8 +194,9 @@
     var data = /** @type {{logModel: !SDK.LogModel, entry: !Protocol.Log.LogEntry}} */ (event.data);
     var consoleMessage = new ConsoleModel.ConsoleMessage(
         data.logModel.target().model(SDK.RuntimeModel), data.entry.source, data.entry.level, data.entry.text, undefined,
-        data.entry.url, data.entry.lineNumber, undefined, data.entry.networkRequestId, undefined, data.entry.stackTrace,
-        data.entry.timestamp, undefined, undefined, data.entry.workerId);
+        data.entry.url, data.entry.lineNumber, undefined, data.entry.networkRequestId,
+        [data.entry.text, ...(data.entry.args || [])], data.entry.stackTrace, data.entry.timestamp, undefined,
+        undefined, data.entry.workerId);
     this.addMessage(consoleMessage);
   }
 
@@ -608,7 +609,7 @@
   }
 };
 
-// Note: Keep these constants in sync with the ones in Console.h
+// Note: Keep these constants in sync with the ones in ConsoleTypes.h
 /**
  * @enum {string}
  */
@@ -626,6 +627,7 @@
   Worker: 'worker',
   Violation: 'violation',
   Intervention: 'intervention',
+  Recommendation: 'recommendation',
   Other: 'other'
 };
 
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js b/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js
index e9de728..5b66cbf 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js
@@ -52,7 +52,7 @@
       return;
 
     if (isEnterKey(event)) {
-      event.consume(true);
+      event.consume();
       if (this._prompt.acceptAutoComplete())
         return;
     }
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
index c8072e4..a471d23f 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
@@ -697,9 +697,10 @@
 
   /**
    * @param {!SDK.DOMNode} node
+   * @param {boolean} focus
    * @return {!Promise}
    */
-  revealAndSelectNode(node) {
+  revealAndSelectNode(node, focus) {
     if (Elements.inspectElementModeController && Elements.inspectElementModeController.isInInspectElementMode())
       Elements.inspectElementModeController.stopInspection();
 
@@ -708,8 +709,8 @@
     node = Common.moduleSetting('showUAShadowDOM').get() ? node : this._leaveUserAgentShadowDOM(node);
     node.highlightForTwoSeconds();
 
-    return UI.viewManager.showView('elements').then(() => {
-      this.selectDOMNode(node, true);
+    return UI.viewManager.showView('elements', false, !focus).then(() => {
+      this.selectDOMNode(node, focus);
       delete this._omitDefaultSelection;
 
       if (!this._notFirstInspectElement)
@@ -887,9 +888,10 @@
   /**
    * @override
    * @param {!Object} node
+   * @param {boolean=} omitFocus
    * @return {!Promise}
    */
-  reveal(node) {
+  reveal(node, omitFocus) {
     var panel = Elements.ElementsPanel.instance();
     panel._pendingNodeReveal = true;
 
@@ -922,7 +924,7 @@
         panel._pendingNodeReveal = false;
 
         if (resolvedNode) {
-          panel.revealAndSelectNode(resolvedNode).then(resolve);
+          panel.revealAndSelectNode(resolvedNode, !omitFocus).then(resolve);
           return;
         }
         reject(new Error('Could not resolve node to reveal.'));
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
index fd8f9857..9c396df 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
@@ -1619,7 +1619,8 @@
       return;
 
     element.scrollIntoViewIfNeeded(false);
-    element.textContent = element.textContent;  // Reset selector marks in group.
+    // Reset selector marks in group, and normalize whitespace.
+    element.textContent = element.textContent.replace(/\s+/g, ' ').trim();
 
     var config =
         new UI.InplaceEditor.Config(this.editingSelectorCommitted.bind(this), this.editingSelectorCancelled.bind(this));
@@ -2599,7 +2600,6 @@
     var result;
 
     if (isEnterKey(event)) {
-      event.preventDefault();
       result = 'forward';
     } else if (event.keyCode === UI.KeyboardShortcut.Keys.Esc.code || event.key === 'Escape') {
       result = 'cancel';
diff --git a/third_party/WebKit/Source/devtools/front_end/network/RequestPreviewView.js b/third_party/WebKit/Source/devtools/front_end/network/RequestPreviewView.js
index 9348b837..1e46c9c 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/RequestPreviewView.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/RequestPreviewView.js
@@ -61,15 +61,15 @@
 
     // We can assume the status code has been set already because fetching contentData should wait for request to be
     // finished.
-    if (!this.request.hasErrorStatusCode() && this.request.resourceType() !== Common.resourceTypes.XHR)
+    if (!this.request.hasErrorStatusCode())
       return null;
 
     var whitelist = new Set(['text/html', 'text/plain', 'application/xhtml+xml']);
     if (!whitelist.has(this.request.mimeType))
       return null;
 
-    var dataURL = Common.ContentProvider.contentAsDataURL(
-        contentData.content, this.request.mimeType, contentData.encoded, contentData.encoded ? 'utf-8' : null);
+    var encodedContent = contentData.encoded ? contentData.content : btoa(contentData.content);
+    var dataURL = Common.ContentProvider.contentAsDataURL(encodedContent, this.request.mimeType, true, 'utf-8');
     return dataURL ? new Network.RequestHTMLView(dataURL) : null;
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/object_ui/ObjectPropertiesSection.js b/third_party/WebKit/Source/devtools/front_end/object_ui/ObjectPropertiesSection.js
index 0ae56e0..663cf32 100644
--- a/third_party/WebKit/Source/devtools/front_end/object_ui/ObjectPropertiesSection.js
+++ b/third_party/WebKit/Source/devtools/front_end/object_ui/ObjectPropertiesSection.js
@@ -880,7 +880,7 @@
    */
   _promptKeyDown(originalContent, event) {
     if (isEnterKey(event)) {
-      event.consume(true);
+      event.consume();
       this._editingCommitted(originalContent);
       return;
     }
diff --git a/third_party/WebKit/Source/devtools/front_end/object_ui/objectValue.css b/third_party/WebKit/Source/devtools/front_end/object_ui/objectValue.css
index 2b376e9..488511d 100644
--- a/third_party/WebKit/Source/devtools/front_end/object_ui/objectValue.css
+++ b/third_party/WebKit/Source/devtools/front_end/object_ui/objectValue.css
@@ -54,10 +54,9 @@
 }
 
 .object-value-node {
-    color: rgb(136, 18, 128);
     position: relative;
     vertical-align: baseline;
-    color: inherit;
+    color: rgb(48, 57, 66);
     display: inline-block;
 }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/quick_open/FilteredListWidget.js b/third_party/WebKit/Source/devtools/front_end/quick_open/FilteredListWidget.js
index 2a0fd62..0d964529 100644
--- a/third_party/WebKit/Source/devtools/front_end/quick_open/FilteredListWidget.js
+++ b/third_party/WebKit/Source/devtools/front_end/quick_open/FilteredListWidget.js
@@ -202,7 +202,6 @@
    * @param {!Event} event
    */
   _onEnter(event) {
-    event.preventDefault();
     if (!this._provider)
       return;
     var selectedIndexInProvider = this._provider.itemCount() ? this._list.selectedItem() : null;
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/DatabaseQueryView.js b/third_party/WebKit/Source/devtools/front_end/resources/DatabaseQueryView.js
index ab5faf087..c52a23ae 100644
--- a/third_party/WebKit/Source/devtools/front_end/resources/DatabaseQueryView.js
+++ b/third_party/WebKit/Source/devtools/front_end/resources/DatabaseQueryView.js
@@ -98,7 +98,7 @@
   }
 
   _enterKeyPressed(event) {
-    event.consume(true);
+    event.consume();
 
     this._prompt.clearAutocomplete();
 
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/ServiceWorkerCacheModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/ServiceWorkerCacheModel.js
index 9805634..6aeda8a 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/ServiceWorkerCacheModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/ServiceWorkerCacheModel.js
@@ -267,6 +267,22 @@
     this.dispatchEventToListeners(
         SDK.ServiceWorkerCacheModel.Events.CacheStorageContentUpdated, {origin: origin, cacheName: cacheName});
   }
+
+  /**
+   * @param {string} origin
+   * @override
+   */
+  indexedDBListUpdated(origin) {
+  }
+
+  /**
+   * @param {string} origin
+   * @param {string} databaseName
+   * @param {string} objectStoreName
+   * @override
+   */
+  indexedDBContentUpdated(origin, databaseName, objectStoreName) {
+  }
 };
 
 SDK.SDKModel.register(SDK.ServiceWorkerCacheModel, SDK.Target.Capability.Browser, false);
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js
index 08f79be..e917572 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js
@@ -290,7 +290,7 @@
    */
   _finishEditing(event, canceled) {
     if (event)
-      event.consume(true);
+      event.consume(canceled);
 
     this._editing = false;
     this._textPrompt.detach();
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/FilterBar.js b/third_party/WebKit/Source/devtools/front_end/ui/FilterBar.js
index a23996b..fe657af 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/FilterBar.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/FilterBar.js
@@ -179,8 +179,6 @@
     this._proxyElement = this._prompt.attach(this._filterInputElement);
     this._proxyElement.title = Common.UIString('e.g. /small[\\d]+/ url:a.com/b');
     this._prompt.setPlaceholder(Common.UIString('Filter'));
-
-    this._proxyElement.addEventListener('keydown', this._onInputKeyDown.bind(this), false);
     this._prompt.addEventListener(UI.TextPrompt.Events.TextChanged, this._valueChanged.bind(this));
 
     /** @type {?function(string, string, boolean=):!Promise<!UI.SuggestBox.Suggestions>} */
@@ -244,14 +242,6 @@
   _valueChanged() {
     this.dispatchEventToListeners(UI.FilterUI.Events.FilterChanged, null);
   }
-
-  /**
-   * @param {!Event} event
-   */
-  _onInputKeyDown(event) {
-    if (isEnterKey(event))
-      event.consume(true);
-  }
 };
 
 /**
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/TextPrompt.js b/third_party/WebKit/Source/devtools/front_end/ui/TextPrompt.js
index 219bb8e6..6f447eb9 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/TextPrompt.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/TextPrompt.js
@@ -296,6 +296,8 @@
       case 'Control':
         break;
     }
+    if (isEnterKey(event))
+      event.preventDefault();
 
     if (!handled && this._isSuggestBoxVisible())
       handled = this._suggestBox.keyPressed(event);
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 a798c20..cab7d4f3 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js
@@ -643,8 +643,6 @@
    * @param {!Event} event
    */
   _onKeydownCallback(event) {
-    if (isEnterKey(event))
-      event.consume(true);
     if (!isEscKey(event) || !this._prompt.text())
       return;
     this._internalSetValue('', true);
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/View.js b/third_party/WebKit/Source/devtools/front_end/ui/View.js
index d09ea7a..decad13a 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/View.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/View.js
@@ -346,9 +346,10 @@
   /**
    * @param {string} viewId
    * @param {boolean=} userGesture
+   * @param {boolean=} omitFocus
    * @return {!Promise}
    */
-  showView(viewId, userGesture) {
+  showView(viewId, userGesture, omitFocus) {
     var view = this._views.get(viewId);
     if (!view) {
       console.error('Could not find view for id: \'' + viewId + '\' ' + new Error().stack);
@@ -362,14 +363,14 @@
     var location = view[UI.ViewManager._Location.symbol];
     if (location) {
       location._reveal();
-      return location.showView(view, undefined, userGesture);
+      return location.showView(view, undefined, userGesture, omitFocus);
     }
 
     return this._resolveLocation(locationName).then(location => {
       if (!location)
         throw new Error('Could not resolve location for view: ' + viewId);
       location._reveal();
-      return location.showView(view, undefined, userGesture);
+      return location.showView(view, undefined, userGesture, omitFocus);
     });
   }
 
@@ -747,12 +748,14 @@
    * @param {!UI.View} view
    * @param {?UI.View=} insertBefore
    * @param {boolean=} userGesture
+   * @param {boolean=} omitFocus
    * @return {!Promise}
    */
-  showView(view, insertBefore, userGesture) {
+  showView(view, insertBefore, userGesture, omitFocus) {
     this.appendView(view, insertBefore);
     this._tabbedPane.selectTab(view.viewId(), userGesture);
-    this._tabbedPane.focus();
+    if (!omitFocus)
+      this._tabbedPane.focus();
     var widget = /** @type {!UI.ViewManager._ContainerWidget} */ (this._tabbedPane.tabView(view.viewId()));
     return widget._materialize();
   }
diff --git a/third_party/WebKit/Source/modules/EventTargetModulesFactory.json5 b/third_party/WebKit/Source/modules/EventTargetModulesFactory.json5
index 8d7205c..3829b73a8 100644
--- a/third_party/WebKit/Source/modules/EventTargetModulesFactory.json5
+++ b/third_party/WebKit/Source/modules/EventTargetModulesFactory.json5
@@ -46,6 +46,7 @@
     "modules/vr/VRDisplay",
     "modules/vr/latest/VR",
     "modules/vr/latest/VRDevice",
+    "modules/vr/latest/VRSession",
     "modules/webaudio/AudioContext",
     "modules/webaudio/AudioNode",
     "modules/webmidi/MIDIAccess",
diff --git a/third_party/WebKit/Source/modules/accessibility/AXInlineTextBox.cpp b/third_party/WebKit/Source/modules/accessibility/AXInlineTextBox.cpp
index 64791f6..e8d8be0 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXInlineTextBox.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXInlineTextBox.cpp
@@ -171,7 +171,7 @@
 AXObject* AXInlineTextBox::NextOnLine() const {
   RefPtr<AbstractInlineTextBox> next_on_line = inline_text_box_->NextOnLine();
   if (next_on_line)
-    return ax_object_cache_->GetOrCreate(next_on_line.Get());
+    return ax_object_cache_->GetOrCreate(next_on_line.get());
 
   if (!inline_text_box_->IsLast())
     return 0;
@@ -183,7 +183,7 @@
   RefPtr<AbstractInlineTextBox> previous_on_line =
       inline_text_box_->PreviousOnLine();
   if (previous_on_line)
-    return ax_object_cache_->GetOrCreate(previous_on_line.Get());
+    return ax_object_cache_->GetOrCreate(previous_on_line.get());
 
   if (!inline_text_box_->IsFirst())
     return 0;
diff --git a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
index ad7a4775..44aaed3 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
@@ -236,9 +236,9 @@
 static bool IsImageOrAltText(LayoutBoxModelObject* box, Node* node) {
   if (box && box->IsImage())
     return true;
-  if (isHTMLImageElement(node))
+  if (IsHTMLImageElement(node))
     return true;
-  if (isHTMLInputElement(node) &&
+  if (IsHTMLInputElement(node) &&
       toHTMLInputElement(node)->HasFallbackContent())
     return true;
   return false;
@@ -248,7 +248,7 @@
   Node* node = layout_object_->GetNode();
   LayoutBoxModelObject* css_box = GetLayoutBoxModelObject();
 
-  if ((css_box && css_box->IsListItem()) || isHTMLLIElement(node))
+  if ((css_box && css_box->IsListItem()) || IsHTMLLIElement(node))
     return kListItemRole;
   if (layout_object_->IsListMarker())
     return kListMarkerRole;
@@ -259,7 +259,7 @@
   if (css_box && IsImageOrAltText(css_box, node)) {
     if (node && node->IsLink())
       return kImageMapRole;
-    if (isHTMLInputElement(node))
+    if (IsHTMLInputElement(node))
       return AriaHasPopup() ? kPopUpButtonRole : kButtonRole;
     if (IsSVGImage())
       return kSVGRootRole;
@@ -267,7 +267,7 @@
   }
   // Note: if JavaScript is disabled, the layoutObject won't be a
   // LayoutHTMLCanvas.
-  if (isHTMLCanvasElement(node) && layout_object_->IsCanvas())
+  if (IsHTMLCanvasElement(node) && layout_object_->IsCanvas())
     return kCanvasRole;
 
   if (css_box && css_box->IsLayoutView())
@@ -380,11 +380,9 @@
   if (!IsLinkable(*this))
     return false;
 
-  Element* anchor = AnchorElement();
-  if (!isHTMLAnchorElement(anchor))
-    return false;
-
-  return !toHTMLAnchorElement(*anchor).Href().IsEmpty();
+  if (auto* anchor = ToHTMLAnchorElementOrNull(AnchorElement()))
+    return !anchor->Href().IsEmpty();
+  return false;
 }
 
 bool AXLayoutObject::IsLoaded() const {
@@ -603,7 +601,7 @@
 
   // don't ignore labels, because they serve as TitleUIElements
   Node* node = layout_object_->GetNode();
-  if (isHTMLLabelElement(node))
+  if (IsHTMLLabelElement(node))
     return false;
 
   // Anything that is content editable should not be ignored.
@@ -666,7 +664,7 @@
   // the side effect of causing the immediate parent accessible to be ignored.
   // This is especially problematic for platforms which have distinct roles for
   // textual block elements.
-  if (isHTMLSpanElement(node)) {
+  if (IsHTMLSpanElement(node)) {
     if (ignored_reasons)
       ignored_reasons->push_back(IgnoredReason(kAXUninteresting));
     return true;
@@ -944,15 +942,14 @@
   ImageBitmapOptions options;
   ImageBitmap* image_bitmap = nullptr;
   Document* document = &node->GetDocument();
-  if (isHTMLImageElement(node)) {
-    image_bitmap = ImageBitmap::Create(toHTMLImageElement(node),
-                                       Optional<IntRect>(), document, options);
-  } else if (isHTMLCanvasElement(node)) {
-    image_bitmap = ImageBitmap::Create(toHTMLCanvasElement(node),
-                                       Optional<IntRect>(), options);
-  } else if (isHTMLVideoElement(node)) {
-    image_bitmap = ImageBitmap::Create(toHTMLVideoElement(node),
-                                       Optional<IntRect>(), document, options);
+  if (auto* image = ToHTMLImageElementOrNull(node)) {
+    image_bitmap =
+        ImageBitmap::Create(image, Optional<IntRect>(), document, options);
+  } else if (auto* canvas = ToHTMLCanvasElementOrNull(node)) {
+    image_bitmap = ImageBitmap::Create(canvas, Optional<IntRect>(), options);
+  } else if (auto* video = ToHTMLVideoElementOrNull(node)) {
+    image_bitmap =
+        ImageBitmap::Create(video, Optional<IntRect>(), document, options);
   }
   if (!image_bitmap)
     return String();
@@ -1100,7 +1097,7 @@
 }
 
 KURL AXLayoutObject::Url() const {
-  if (IsAnchor() && isHTMLAnchorElement(layout_object_->GetNode())) {
+  if (IsAnchor() && IsHTMLAnchorElement(layout_object_->GetNode())) {
     if (HTMLAnchorElement* anchor = toHTMLAnchorElement(AnchorElement()))
       return anchor->Href();
   }
@@ -1108,7 +1105,7 @@
   if (IsWebArea())
     return layout_object_->GetDocument().Url();
 
-  if (IsImage() && isHTMLImageElement(layout_object_->GetNode()))
+  if (IsImage() && IsHTMLImageElement(layout_object_->GetNode()))
     return toHTMLImageElement(*layout_object_->GetNode()).Src();
 
   if (IsInputImage())
@@ -1254,7 +1251,7 @@
   // Handle other HTML input elements that aren't text controls, like date and
   // time controls, by returning the string value, with the exception of
   // checkboxes and radio buttons (which would return "on").
-  if (GetNode() && isHTMLInputElement(GetNode())) {
+  if (GetNode() && IsHTMLInputElement(GetNode())) {
     HTMLInputElement* input = toHTMLInputElement(GetNode());
     if (input->type() != InputTypeNames::checkbox &&
         input->type() != InputTypeNames::radio)
@@ -1432,11 +1429,11 @@
   if (!node)
     return nullptr;
 
-  if (isHTMLAreaElement(node))
-    return AccessibilityImageMapHitTest(toHTMLAreaElement(node), point);
+  if (auto* area = ToHTMLAreaElementOrNull(node))
+    return AccessibilityImageMapHitTest(area, point);
 
-  if (isHTMLOptionElement(node)) {
-    node = toHTMLOptionElement(*node).OwnerSelectElement();
+  if (auto* option = ToHTMLOptionElementOrNull(node)) {
+    node = option->OwnerSelectElement();
     if (!node)
       return nullptr;
   }
@@ -1735,7 +1732,7 @@
   if (!node)
     return nullptr;
   for (Node& runner : NodeTraversal::InclusiveAncestorsOf(*node)) {
-    if (isHTMLAnchorElement(runner) ||
+    if (IsHTMLAnchorElement(runner) ||
         (runner.GetLayoutObject() &&
          cache.GetOrCreate(runner.GetLayoutObject())->IsAnchor()))
       return ToElement(&runner);
@@ -2073,13 +2070,13 @@
     return false;
 
   LayoutBoxModelObject* layout_object = ToLayoutBoxModelObject(layout_object_);
-  if (layout_object->IsTextField() && isHTMLInputElement(*GetNode())) {
+  if (layout_object->IsTextField() && IsHTMLInputElement(*GetNode())) {
     toHTMLInputElement(*GetNode())
         .setValue(string, kDispatchInputAndChangeEvent);
     return true;
   }
 
-  if (layout_object->IsTextArea() && isHTMLTextAreaElement(*GetNode())) {
+  if (layout_object->IsTextArea() && IsHTMLTextAreaElement(*GetNode())) {
     toHTMLTextAreaElement(*GetNode())
         .setValue(string, kDispatchInputAndChangeEvent);
     return true;
@@ -2224,8 +2221,8 @@
   LayoutText* layout_text = ToLayoutText(GetLayoutObject());
   for (RefPtr<AbstractInlineTextBox> box =
            layout_text->FirstAbstractInlineTextBox();
-       box.Get(); box = box->NextInlineTextBox()) {
-    AXObject* ax_object = AxObjectCache().GetOrCreate(box.Get());
+       box.get(); box = box->NextInlineTextBox()) {
+    AXObject* ax_object = AxObjectCache().GetOrCreate(box.get());
     if (!ax_object->AccessibilityIsIgnored())
       children_.push_back(ax_object);
   }
@@ -2463,7 +2460,7 @@
 
 void AXLayoutObject::AddTextFieldChildren() {
   Node* node = this->GetNode();
-  if (!isHTMLInputElement(node))
+  if (!IsHTMLInputElement(node))
     return;
 
   HTMLInputElement& input = toHTMLInputElement(*node);
@@ -2506,7 +2503,7 @@
 }
 
 void AXLayoutObject::AddCanvasChildren() {
-  if (!isHTMLCanvasElement(GetNode()))
+  if (!IsHTMLCanvasElement(GetNode()))
     return;
 
   // If it's a canvas, it won't have laid out children, but it might have
@@ -2518,7 +2515,7 @@
 }
 
 void AXLayoutObject::AddPopupChildren() {
-  if (!isHTMLInputElement(GetNode()))
+  if (!IsHTMLInputElement(GetNode()))
     return;
   if (AXObject* ax_popup = toHTMLInputElement(GetNode())->PopupRootAXObject())
     children_.push_back(ax_popup);
diff --git a/third_party/WebKit/Source/modules/accessibility/AXListBox.cpp b/third_party/WebKit/Source/modules/accessibility/AXListBox.cpp
index af73e43d..50a0e75 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXListBox.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXListBox.cpp
@@ -58,7 +58,7 @@
 }
 
 AXObject* AXListBox::ActiveDescendant() {
-  if (!isHTMLSelectElement(GetNode()))
+  if (!IsHTMLSelectElement(GetNode()))
     return nullptr;
 
   HTMLSelectElement* select = toHTMLSelectElement(GetNode());
@@ -72,7 +72,7 @@
 }
 
 void AXListBox::ActiveIndexChanged() {
-  if (!isHTMLSelectElement(GetNode()))
+  if (!IsHTMLSelectElement(GetNode()))
     return;
 
   HTMLSelectElement* select = toHTMLSelectElement(GetNode());
diff --git a/third_party/WebKit/Source/modules/accessibility/AXListBoxOption.cpp b/third_party/WebKit/Source/modules/accessibility/AXListBoxOption.cpp
index bb2e373..52e4b313 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXListBoxOption.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXListBoxOption.cpp
@@ -80,7 +80,7 @@
 }
 
 bool AXListBoxOption::IsSelected() const {
-  return isHTMLOptionElement(GetNode()) &&
+  return IsHTMLOptionElement(GetNode()) &&
          toHTMLOptionElement(GetNode())->Selected();
 }
 
@@ -156,8 +156,8 @@
   if (!GetNode())
     return 0;
 
-  if (isHTMLOptionElement(GetNode()))
-    return toHTMLOptionElement(GetNode())->OwnerSelectElement();
+  if (auto* option = ToHTMLOptionElementOrNull(GetNode()))
+    return option->OwnerSelectElement();
 
   return 0;
 }
diff --git a/third_party/WebKit/Source/modules/accessibility/AXMediaControls.cpp b/third_party/WebKit/Source/modules/accessibility/AXMediaControls.cpp
index 7058ede..90dd624 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXMediaControls.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXMediaControls.cpp
@@ -333,12 +333,9 @@
 }
 
 String AccessibilityMediaTimeline::ValueDescription() const {
-  Node* node = layout_object_->GetNode();
-  if (!isHTMLInputElement(node))
-    return String();
-
-  return LocalizedMediaTimeDescription(
-      toHTMLInputElement(node)->value().ToFloat());
+  if (auto* input = ToHTMLInputElementOrNull(layout_object_->GetNode()))
+    return LocalizedMediaTimeDescription(input->value().ToFloat());
+  return String();
 }
 
 String AccessibilityMediaTimeline::Description(
diff --git a/third_party/WebKit/Source/modules/accessibility/AXMenuListOption.cpp b/third_party/WebKit/Source/modules/accessibility/AXMenuListOption.cpp
index 7378afab..0e422a5 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXMenuListOption.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXMenuListOption.cpp
@@ -190,8 +190,8 @@
   if (!GetNode())
     return 0;
 
-  if (isHTMLOptionElement(GetNode()))
-    return toHTMLOptionElement(GetNode())->OwnerSelectElement();
+  if (auto* option = ToHTMLOptionElementOrNull(GetNode()))
+    return option->OwnerSelectElement();
 
   return 0;
 }
diff --git a/third_party/WebKit/Source/modules/accessibility/AXMenuListPopup.cpp b/third_party/WebKit/Source/modules/accessibility/AXMenuListPopup.cpp
index bca7bbf..9f1e996 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXMenuListPopup.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXMenuListPopup.cpp
@@ -59,7 +59,7 @@
 AXMenuListOption* AXMenuListPopup::MenuListOptionAXObject(
     HTMLElement* element) const {
   DCHECK(element);
-  if (!isHTMLOptionElement(*element))
+  if (!IsHTMLOptionElement(*element))
     return 0;
 
   AXObject* object = AxObjectCache().GetOrCreate(element);
@@ -74,7 +74,7 @@
     return -1;
 
   Node* parent_node = parent_->GetNode();
-  if (!isHTMLSelectElement(parent_node))
+  if (!IsHTMLSelectElement(parent_node))
     return -1;
 
   HTMLSelectElement* html_select_element = toHTMLSelectElement(parent_node);
@@ -94,7 +94,7 @@
     return;
 
   Node* parent_node = parent_->GetNode();
-  if (!isHTMLSelectElement(parent_node))
+  if (!IsHTMLSelectElement(parent_node))
     return;
 
   HTMLSelectElement* html_select_element = toHTMLSelectElement(parent_node);
diff --git a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp
index 2591b47..b5e0c37 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp
@@ -75,6 +75,9 @@
 
 using namespace HTMLNames;
 
+// In ARIA 1.1, default value of aria-level was changed to 2.
+const int kDefaultHeadingLevel = 2;
+
 AXNodeObject::AXNodeObject(Node* node, AXObjectCacheImpl& ax_object_cache)
     : AXObject(ax_object_cache),
       children_dirty_(false),
@@ -172,8 +175,8 @@
 }
 
 static bool IsListElement(Node* node) {
-  return isHTMLUListElement(*node) || isHTMLOListElement(*node) ||
-         isHTMLDListElement(*node);
+  return IsHTMLUListElement(*node) || IsHTMLOListElement(*node) ||
+         IsHTMLDListElement(*node);
 }
 
 static bool IsPresentationalInTable(AXObject* parent,
@@ -196,16 +199,16 @@
   // cell(group)-> tr(unknown) -> tfoot, tbody, thead(ignored) ->
   //     table(presentation).
   if (IsHTMLTableCellElement(*current_element) &&
-      isHTMLTableRowElement(*parent_node))
+      IsHTMLTableRowElement(*parent_node))
     return parent->HasInheritedPresentationalRole();
 
-  if (isHTMLTableRowElement(*current_element) &&
+  if (IsHTMLTableRowElement(*current_element) &&
       IsHTMLTableSectionElement(ToHTMLElement(*parent_node))) {
     // Because TableSections have ignored role, presentation should be checked
     // with its parent node.
     AXObject* table_object = parent->ParentObject();
     Node* table_node = table_object ? table_object->GetNode() : 0;
-    return isHTMLTableElement(table_node) &&
+    return IsHTMLTableElement(table_node) &&
            table_object->HasInheritedPresentationalRole();
   }
   return false;
@@ -221,16 +224,16 @@
   if (current_role == kListItemRole)
     return IsListElement(parent_node);
   if (current_role == kListMarkerRole)
-    return isHTMLLIElement(*parent_node);
+    return IsHTMLLIElement(*parent_node);
   if (current_role == kMenuItemCheckBoxRole || current_role == kMenuItemRole ||
       current_role == kMenuItemRadioRole)
-    return isHTMLMenuElement(*parent_node);
+    return IsHTMLMenuElement(*parent_node);
 
   if (!current_element)
     return false;
   if (IsHTMLTableCellElement(*current_element))
-    return isHTMLTableRowElement(*parent_node);
-  if (isHTMLTableRowElement(*current_element))
+    return IsHTMLTableRowElement(*parent_node);
+  if (IsHTMLTableRowElement(*current_element))
     return IsHTMLTableSectionElement(ToHTMLElement(*parent_node));
 
   // In case of ListboxRole and its child, ListBoxOptionRole, inheritance of
@@ -324,7 +327,7 @@
   if (GetNode()->IsLink())
     return kLinkRole;
 
-  if (isHTMLAnchorElement(*GetNode())) {
+  if (IsHTMLAnchorElement(*GetNode())) {
     // We assume that an anchor element is LinkRole if it has event listners
     // even though it doesn't have hrefAttr.
     if (IsClickable())
@@ -332,34 +335,33 @@
     return kAnchorRole;
   }
 
-  if (isHTMLButtonElement(*GetNode()))
+  if (IsHTMLButtonElement(*GetNode()))
     return ButtonRoleType();
 
-  if (isHTMLDetailsElement(*GetNode()))
+  if (IsHTMLDetailsElement(*GetNode()))
     return kDetailsRole;
 
-  if (isHTMLSummaryElement(*GetNode())) {
+  if (IsHTMLSummaryElement(*GetNode())) {
     ContainerNode* parent = FlatTreeTraversal::Parent(*GetNode());
-    if (parent && isHTMLDetailsElement(parent))
+    if (parent && IsHTMLDetailsElement(parent))
       return kDisclosureTriangleRole;
     return kUnknownRole;
   }
 
-  if (isHTMLInputElement(*GetNode())) {
-    HTMLInputElement& input = toHTMLInputElement(*GetNode());
-    const AtomicString& type = input.type();
-    if (input.DataList())
+  if (auto* input = ToHTMLInputElementOrNull(*GetNode())) {
+    const AtomicString& type = input->type();
+    if (input->DataList())
       return kComboBoxRole;
     if (type == InputTypeNames::button) {
       if ((GetNode()->parentNode() &&
-           isHTMLMenuElement(GetNode()->parentNode())) ||
+           IsHTMLMenuElement(GetNode()->parentNode())) ||
           (ParentObject() && ParentObject()->RoleValue() == kMenuRole))
         return kMenuItemRole;
       return ButtonRoleType();
     }
     if (type == InputTypeNames::checkbox) {
       if ((GetNode()->parentNode() &&
-           isHTMLMenuElement(GetNode()->parentNode())) ||
+           IsHTMLMenuElement(GetNode()->parentNode())) ||
           (ParentObject() && ParentObject()->RoleValue() == kMenuRole))
         return kMenuItemCheckBoxRole;
       return kCheckBoxRole;
@@ -374,14 +376,14 @@
       return kButtonRole;
     if (type == InputTypeNames::radio) {
       if ((GetNode()->parentNode() &&
-           isHTMLMenuElement(GetNode()->parentNode())) ||
+           IsHTMLMenuElement(GetNode()->parentNode())) ||
           (ParentObject() && ParentObject()->RoleValue() == kMenuRole))
         return kMenuItemRadioRole;
       return kRadioButtonRole;
     }
     if (type == InputTypeNames::number)
       return kSpinButtonRole;
-    if (input.IsTextButton())
+    if (input->IsTextButton())
       return ButtonRoleType();
     if (type == InputTypeNames::range)
       return kSliderRole;
@@ -392,52 +394,49 @@
     return kTextFieldRole;
   }
 
-  if (isHTMLSelectElement(*GetNode())) {
-    HTMLSelectElement& select_element = toHTMLSelectElement(*GetNode());
-    return select_element.IsMultiple() ? kListBoxRole : kPopUpButtonRole;
-  }
+  if (auto* select_element = ToHTMLSelectElementOrNull(*GetNode()))
+    return select_element->IsMultiple() ? kListBoxRole : kPopUpButtonRole;
 
-  if (isHTMLOptionElement(*GetNode())) {
-    HTMLSelectElement* select_element =
-        toHTMLOptionElement(GetNode())->OwnerSelectElement();
+  if (auto* option = ToHTMLOptionElementOrNull(*GetNode())) {
+    HTMLSelectElement* select_element = option->OwnerSelectElement();
     return !select_element || select_element->IsMultiple()
                ? kListBoxOptionRole
                : kMenuListOptionRole;
   }
 
-  if (isHTMLTextAreaElement(*GetNode()))
+  if (IsHTMLTextAreaElement(*GetNode()))
     return kTextFieldRole;
 
   if (HeadingLevel())
     return kHeadingRole;
 
-  if (isHTMLDivElement(*GetNode()))
+  if (IsHTMLDivElement(*GetNode()))
     return kGenericContainerRole;
 
-  if (isHTMLMeterElement(*GetNode()))
+  if (IsHTMLMeterElement(*GetNode()))
     return kMeterRole;
 
-  if (isHTMLOutputElement(*GetNode()))
+  if (IsHTMLOutputElement(*GetNode()))
     return kStatusRole;
 
-  if (isHTMLParagraphElement(*GetNode()))
+  if (IsHTMLParagraphElement(*GetNode()))
     return kParagraphRole;
 
-  if (isHTMLLabelElement(*GetNode()))
+  if (IsHTMLLabelElement(*GetNode()))
     return kLabelRole;
 
-  if (isHTMLLegendElement(*GetNode()))
+  if (IsHTMLLegendElement(*GetNode()))
     return kLegendRole;
 
-  if (isHTMLRubyElement(*GetNode()))
+  if (IsHTMLRubyElement(*GetNode()))
     return kRubyRole;
 
-  if (isHTMLDListElement(*GetNode()))
+  if (IsHTMLDListElement(*GetNode()))
     return kDescriptionListRole;
 
-  if (isHTMLAudioElement(*GetNode()))
+  if (IsHTMLAudioElement(*GetNode()))
     return kAudioRole;
-  if (isHTMLVideoElement(*GetNode()))
+  if (IsHTMLVideoElement(*GetNode()))
     return kVideoRole;
 
   if (GetNode()->HasTagName(ddTag))
@@ -452,7 +451,7 @@
   if (GetNode()->HasTagName(rpTag) || GetNode()->HasTagName(rtTag))
     return kAnnotationRole;
 
-  if (isHTMLFormElement(*GetNode()))
+  if (IsHTMLFormElement(*GetNode()))
     return kFormRole;
 
   if (GetNode()->HasTagName(abbrTag))
@@ -482,15 +481,15 @@
   if (GetNode()->HasTagName(addressTag))
     return kContentInfoRole;
 
-  if (isHTMLDialogElement(*GetNode()))
+  if (IsHTMLDialogElement(*GetNode()))
     return kDialogRole;
 
   // The HTML element should not be exposed as an element. That's what the
   // LayoutView element does.
-  if (isHTMLHtmlElement(*GetNode()))
+  if (IsHTMLHtmlElement(*GetNode()))
     return kIgnoredRole;
 
-  if (isHTMLIFrameElement(*GetNode())) {
+  if (IsHTMLIFrameElement(*GetNode())) {
     const AtomicString& aria_role =
         GetAOMPropertyOrARIAAttribute(AOMStringProperty::kRole);
     if (aria_role == "none" || aria_role == "presentation")
@@ -531,7 +530,7 @@
   if (IsEmbeddedObject())
     return kEmbeddedObjectRole;
 
-  if (isHTMLHRElement(*GetNode()))
+  if (IsHTMLHRElement(*GetNode()))
     return kSplitterRole;
 
   if (IsFieldset())
@@ -592,7 +591,7 @@
   }
 
   // Default for <textarea> is true.
-  if (isHTMLTextAreaElement(*node))
+  if (IsHTMLTextAreaElement(*node))
     return true;
 
   // Default for other edit boxes is false, including for ARIA, says CORE-AAM.
@@ -660,7 +659,7 @@
   // handles these cases already, so we don't need to include them here.
   if (RoleValue() == kWebAreaRole)
     return false;
-  if (isHTMLBodyElement(GetNode()))
+  if (IsHTMLBodyElement(GetNode()))
     return false;
 
   // An SVG root is focusable by default, but it's probably not interactive, so
@@ -763,7 +762,7 @@
   if (!node)
     return true;
 
-  return isHTMLVideoElement(
+  return IsHTMLVideoElement(
       MediaControlElementsHelper::ToParentMediaElement(node));
 }
 
@@ -772,7 +771,7 @@
 }
 
 bool AXNodeObject::IsFieldset() const {
-  return isHTMLFieldSetElement(GetNode());
+  return IsHTMLFieldSetElement(GetNode());
 }
 
 bool AXNodeObject::IsHeading() const {
@@ -795,7 +794,7 @@
 
 bool AXNodeObject::IsInputImage() const {
   Node* node = this->GetNode();
-  if (RoleValue() == kButtonRole && isHTMLInputElement(node))
+  if (RoleValue() == kButtonRole && IsHTMLInputElement(node))
     return toHTMLInputElement(*node).type() == InputTypeNames::image;
 
   return false;
@@ -817,13 +816,12 @@
   if (element->ContainingShadowRoot())
     return false;
 
-  if (isHTMLAnchorElement(element)) {
-    HTMLAnchorElement* html_element = toHTMLAnchorElement(element);
-    return html_element->HasName() || html_element->HasID();
+  if (auto* anchor = ToHTMLAnchorElementOrNull(element)) {
+    return anchor->HasName() || anchor->HasID();
   }
 
-  if (element->HasID() && (IsLandmarkRelated() || isHTMLSpanElement(element) ||
-                           isHTMLDivElement(element))) {
+  if (element->HasID() && (IsLandmarkRelated() || IsHTMLSpanElement(element) ||
+                           IsHTMLDivElement(element))) {
     return true;
   }
   return false;
@@ -858,18 +856,16 @@
       break;
   }
 
-  return isHTMLSelectElement(GetNode()) &&
+  return IsHTMLSelectElement(GetNode()) &&
          toHTMLSelectElement(*GetNode()).IsMultiple();
 }
 
 bool AXNodeObject::IsNativeCheckboxOrRadio() const {
-  Node* node = this->GetNode();
-  if (!isHTMLInputElement(node))
-    return false;
-
-  HTMLInputElement* input = toHTMLInputElement(node);
-  return input->type() == InputTypeNames::checkbox ||
-         input->type() == InputTypeNames::radio;
+  if (auto* input = ToHTMLInputElementOrNull(GetNode())) {
+    return input->type() == InputTypeNames::checkbox ||
+           input->type() == InputTypeNames::radio;
+  }
+  return false;
 }
 
 bool AXNodeObject::IsNativeImage() const {
@@ -877,14 +873,14 @@
   if (!node)
     return false;
 
-  if (isHTMLImageElement(*node))
+  if (IsHTMLImageElement(*node))
     return true;
 
   if (IsHTMLPlugInElement(*node))
     return true;
 
-  if (isHTMLInputElement(*node))
-    return toHTMLInputElement(*node).type() == InputTypeNames::image;
+  if (auto* input = ToHTMLInputElementOrNull(*node))
+    return input->type() == InputTypeNames::image;
 
   return false;
 }
@@ -894,11 +890,11 @@
   if (!node)
     return false;
 
-  if (isHTMLTextAreaElement(*node))
+  if (IsHTMLTextAreaElement(*node))
     return true;
 
-  if (isHTMLInputElement(*node))
-    return toHTMLInputElement(node)->IsTextField();
+  if (auto* input = ToHTMLInputElementOrNull(*node))
+    return input->IsTextField();
 
   return false;
 }
@@ -918,7 +914,7 @@
 
 bool AXNodeObject::IsPasswordField() const {
   Node* node = this->GetNode();
-  if (!isHTMLInputElement(node))
+  if (!IsHTMLInputElement(node))
     return false;
 
   AccessibilityRole aria_role = AriaRoleAttribute();
@@ -941,14 +937,9 @@
 }
 
 bool AXNodeObject::IsNativeSlider() const {
-  Node* node = this->GetNode();
-  if (!node)
-    return false;
-
-  if (!isHTMLInputElement(node))
-    return false;
-
-  return toHTMLInputElement(node)->type() == InputTypeNames::range;
+  if (auto* input = ToHTMLInputElementOrNull(GetNode()))
+    return input->type() == InputTypeNames::range;
+  return false;
 }
 
 bool AXNodeObject::IsMoveableSplitter() const {
@@ -981,7 +972,7 @@
     return kNone;
 
   // An <optgroup> is not exposed directly in the AX tree.
-  if (isHTMLOptGroupElement(elem))
+  if (IsHTMLOptGroupElement(elem))
     return kNone;
 
   // According to ARIA, all elements of the base markup can be disabled.
@@ -1009,11 +1000,10 @@
   }
 
   // Only editable fields can be marked @readonly (unlike @aria-readonly).
-  if (isHTMLTextAreaElement(*elem) && toHTMLTextAreaElement(*elem).IsReadOnly())
+  if (IsHTMLTextAreaElement(*elem) && toHTMLTextAreaElement(*elem).IsReadOnly())
     return kReadOnly;
-  if (isHTMLInputElement(*elem)) {
-    HTMLInputElement& input = toHTMLInputElement(*elem);
-    if (input.IsTextField() && input.IsReadOnly())
+  if (auto* input = ToHTMLInputElementOrNull(*elem)) {
+    if (input->IsTextField() && input->IsReadOnly())
       return kReadOnly;
   }
 
@@ -1022,9 +1012,9 @@
 }
 
 AccessibilityExpanded AXNodeObject::IsExpanded() const {
-  if (GetNode() && isHTMLSummaryElement(*GetNode())) {
+  if (GetNode() && IsHTMLSummaryElement(*GetNode())) {
     if (GetNode()->parentNode() &&
-        isHTMLDetailsElement(GetNode()->parentNode()))
+        IsHTMLDetailsElement(GetNode()->parentNode()))
       return ToElement(GetNode()->parentNode())->hasAttribute(openAttr)
                  ? kExpandedExpanded
                  : kExpandedCollapsed;
@@ -1046,7 +1036,7 @@
   if (HasAOMPropertyOrARIAAttribute(AOMBooleanProperty::kModal, modal))
     return modal;
 
-  if (GetNode() && isHTMLDialogElement(*GetNode()))
+  if (GetNode() && IsHTMLDialogElement(*GetNode()))
     return ToElement(GetNode())->IsInTopLayer();
 
   return false;
@@ -1066,7 +1056,7 @@
 
 bool AXNodeObject::CanvasHasFallbackContent() const {
   Node* node = this->GetNode();
-  if (!isHTMLCanvasElement(node))
+  if (!IsHTMLCanvasElement(node))
     return false;
 
   // If it has any children that are elements, we'll assume it might be fallback
@@ -1086,7 +1076,6 @@
     if (HasAOMPropertyOrARIAAttribute(AOMUIntProperty::kLevel, level)) {
       if (level >= 1 && level <= 9)
         return level;
-      return 1;
     }
   }
 
@@ -1112,6 +1101,9 @@
   if (element.HasTagName(h6Tag))
     return 6;
 
+  if (RoleValue() == kHeadingRole)
+    return kDefaultHeadingLevel;
+
   return 0;
 }
 
@@ -1124,7 +1116,6 @@
   if (HasAOMPropertyOrARIAAttribute(AOMUIntProperty::kLevel, level)) {
     if (level >= 1 && level <= 9)
       return level;
-    return 1;
   }
 
   // Only tree item will calculate its level through the DOM currently.
@@ -1188,7 +1179,7 @@
 }
 
 AXObject* AXNodeObject::InPageLinkTarget() const {
-  if (!node_ || !isHTMLAnchorElement(node_) || !GetDocument())
+  if (!node_ || !IsHTMLAnchorElement(node_) || !GetDocument())
     return AXObject::InPageLinkTarget();
 
   HTMLAnchorElement* anchor = toHTMLAnchorElement(node_);
@@ -1256,8 +1247,7 @@
   if (!node_ || RoleValue() != kRadioButtonRole)
     return radio_buttons;
 
-  if (isHTMLInputElement(node_)) {
-    HTMLInputElement* radio_button = toHTMLInputElement(node_);
+  if (auto* radio_button = ToHTMLInputElementOrNull(node_)) {
     HeapVector<Member<HTMLInputElement>> html_radio_buttons =
         FindAllRadioButtonsWithSameName(radio_button);
     for (size_t i = 0; i < html_radio_buttons.size(); ++i) {
@@ -1321,7 +1311,7 @@
     return String();
 
   if (IsNativeTextControl() &&
-      (isHTMLTextAreaElement(*node) || isHTMLInputElement(*node)))
+      (IsHTMLTextAreaElement(*node) || IsHTMLInputElement(*node)))
     return ToTextControlElement(*node).value();
 
   if (!node->IsElementNode())
@@ -1331,7 +1321,7 @@
 }
 
 RGBA32 AXNodeObject::ColorValue() const {
-  if (!isHTMLInputElement(GetNode()) || !IsColorWell())
+  if (!IsHTMLInputElement(GetNode()) || !IsColorWell())
     return AXObject::ColorValue();
 
   HTMLInputElement* input = toHTMLInputElement(GetNode());
@@ -1518,8 +1508,8 @@
     return true;
   }
 
-  if (isHTMLMeterElement(GetNode())) {
-    *out_value = toHTMLMeterElement(*GetNode()).value();
+  if (auto* meter = ToHTMLMeterElementOrNull(GetNode())) {
+    *out_value = meter->value();
     return true;
   }
 
@@ -1538,8 +1528,8 @@
     return true;
   }
 
-  if (isHTMLMeterElement(GetNode())) {
-    *out_value = toHTMLMeterElement(*GetNode()).max();
+  if (auto* meter = ToHTMLMeterElementOrNull(GetNode())) {
+    *out_value = meter->max();
     return true;
   }
 
@@ -1571,8 +1561,8 @@
     return true;
   }
 
-  if (isHTMLMeterElement(GetNode())) {
-    *out_value = toHTMLMeterElement(*GetNode()).min();
+  if (auto* meter = ToHTMLMeterElementOrNull(GetNode())) {
+    *out_value = meter->min();
     return true;
   }
 
@@ -1593,11 +1583,10 @@
   if (!node)
     return String();
 
-  if (isHTMLSelectElement(*node)) {
-    HTMLSelectElement& select_element = toHTMLSelectElement(*node);
-    int selected_index = select_element.selectedIndex();
+  if (auto* select_element = ToHTMLSelectElementOrNull(*node)) {
+    int selected_index = select_element->selectedIndex();
     const HeapVector<Member<HTMLElement>>& list_items =
-        select_element.GetListItems();
+        select_element->GetListItems();
     if (selected_index >= 0 &&
         static_cast<size_t>(selected_index) < list_items.size()) {
       const AtomicString& overridden_description =
@@ -1605,8 +1594,8 @@
       if (!overridden_description.IsNull())
         return overridden_description;
     }
-    if (!select_element.IsMultiple())
-      return select_element.value();
+    if (!select_element->IsMultiple())
+      return select_element->value();
     return String();
   }
 
@@ -1616,8 +1605,7 @@
   // Handle other HTML input elements that aren't text controls, like date and
   // time controls, by returning the string value, with the exception of
   // checkboxes and radio buttons (which would return "on").
-  if (isHTMLInputElement(node)) {
-    HTMLInputElement* input = toHTMLInputElement(node);
+  if (auto* input = ToHTMLInputElementOrNull(node)) {
     if (input->type() != InputTypeNames::checkbox &&
         input->type() != InputTypeNames::radio)
       return input->value();
@@ -1717,7 +1705,7 @@
   // Step 2F / 2G from: http://www.w3.org/TR/accname-aam-1.1
   if (in_aria_labelled_by_traversal || NameFromContents(recursive)) {
     Node* node = GetNode();
-    if (!isHTMLSelectElement(node)) {  // Avoid option descendant text
+    if (!IsHTMLSelectElement(node)) {  // Avoid option descendant text
       name_from = kAXNameFromContents;
       if (name_sources) {
         name_sources->push_back(NameSource(found_text_alternative));
@@ -1726,7 +1714,7 @@
 
       if (node && node->IsTextNode())
         text_alternative = ToText(node)->wholeText();
-      else if (isHTMLBRElement(node))
+      else if (IsHTMLBRElement(node))
         text_alternative = String("\n");
       else
         text_alternative = TextFromDescendants(visited, false);
@@ -1946,8 +1934,8 @@
 
   // Skip over <optgroup> and consider the <select> the immediate parent of an
   // <option>.
-  if (isHTMLOptionElement(node))
-    parent_node = toHTMLOptionElement(node)->OwnerSelectElement();
+  if (auto* option = ToHTMLOptionElementOrNull(node))
+    parent_node = option->OwnerSelectElement();
 
   if (!parent_node)
     parent_node = node->parentNode();
@@ -2007,7 +1995,7 @@
 
   // The only time we add children from the DOM tree to a node with a
   // layoutObject is when it's a canvas.
-  if (GetLayoutObject() && !isHTMLCanvasElement(*node_))
+  if (GetLayoutObject() && !IsHTMLCanvasElement(*node_))
     return;
 
   HeapVector<Member<AXObject>> owned_children;
@@ -2061,7 +2049,7 @@
   if (!GetNode() && !IsAXLayoutObject())
     return false;
 
-  if (GetNode() && isHTMLMapElement(GetNode()))
+  if (GetNode() && IsHTMLMapElement(GetNode()))
     return false;  // Does not have a role, so check here
 
   // Placeholder gets exposed as an attribute on the input accessibility node,
@@ -2164,7 +2152,7 @@
   // NOTE: this assumes that any non-image with an anchor is an
   // HTMLAnchorElement
   for (; node; node = node->parentNode()) {
-    if (isHTMLAnchorElement(*node) ||
+    if (IsHTMLAnchorElement(*node) ||
         (node->GetLayoutObject() &&
          cache.GetOrCreate(node->GetLayoutObject())->IsAnchor()))
       return ToElement(node);
@@ -2420,9 +2408,7 @@
   String text_alternative;
   AXRelatedObjectVector local_related_objects;
 
-  const HTMLInputElement* input_element = nullptr;
-  if (isHTMLInputElement(GetNode()))
-    input_element = toHTMLInputElement(GetNode());
+  const HTMLInputElement* input_element = ToHTMLInputElementOrNull(GetNode());
 
   // 5.1/5.5 Text inputs, Other labelable Elements
   // If you change this logic, update AXNodeObject::nameFromLabelElement, too.
@@ -2667,7 +2653,7 @@
   }
 
   // 5.8 img or area Element
-  if (isHTMLImageElement(GetNode()) || isHTMLAreaElement(GetNode()) ||
+  if (IsHTMLImageElement(GetNode()) || IsHTMLAreaElement(GetNode()) ||
       (GetLayoutObject() && GetLayoutObject()->IsSVGImage())) {
     // alt
     const AtomicString& alt = GetAttribute(altAttr);
@@ -2693,9 +2679,7 @@
   }
 
   // 5.9 table Element
-  if (isHTMLTableElement(GetNode())) {
-    HTMLTableElement* table_element = toHTMLTableElement(GetNode());
-
+  if (auto* table_element = ToHTMLTableElementOrNull(GetNode())) {
     // caption
     name_from = kAXNameFromCaption;
     if (name_sources) {
@@ -2785,7 +2769,7 @@
   }
 
   // Fieldset / legend.
-  if (isHTMLFieldSetElement(GetNode())) {
+  if (IsHTMLFieldSetElement(GetNode())) {
     name_from = kAXNameFromRelatedElement;
     if (name_sources) {
       name_sources->push_back(NameSource(*found_text_alternative));
@@ -2968,9 +2952,7 @@
     }
   }
 
-  const HTMLInputElement* input_element = nullptr;
-  if (isHTMLInputElement(GetNode()))
-    input_element = toHTMLInputElement(GetNode());
+  const HTMLInputElement* input_element = ToHTMLInputElementOrNull(GetNode());
 
   // value, 5.2.2 from: http://rawgit.com/w3c/aria/master/html-aam/html-aam.html
   if (name_from != kAXNameFromValue && input_element &&
@@ -2996,7 +2978,7 @@
 
   // table caption, 5.9.2 from:
   // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html
-  if (name_from != kAXNameFromCaption && isHTMLTableElement(GetNode())) {
+  if (name_from != kAXNameFromCaption && IsHTMLTableElement(GetNode())) {
     HTMLTableElement* table_element = toHTMLTableElement(GetNode());
 
     description_from = kAXDescriptionFromRelatedElement;
@@ -3031,7 +3013,7 @@
 
   // summary, 5.6.2 from:
   // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html
-  if (name_from != kAXNameFromContents && isHTMLSummaryElement(GetNode())) {
+  if (name_from != kAXNameFromContents && IsHTMLSummaryElement(GetNode())) {
     description_from = kAXDescriptionFromContents;
     if (description_sources) {
       description_sources->push_back(DescriptionSource(found_description));
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
index 5a947f5..df31107f 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
@@ -596,7 +596,7 @@
     if (IsNativeCheckboxInMixedState(node))
       return kCheckedStateMixed;
 
-    if (isHTMLInputElement(*node) &&
+    if (IsHTMLInputElement(*node) &&
         toHTMLInputElement(*node).ShouldAppearChecked()) {
       return kCheckedStateTrue;
     }
@@ -606,7 +606,7 @@
 }
 
 bool AXObject::IsNativeCheckboxInMixedState(const Node* node) {
-  if (!isHTMLInputElement(node))
+  if (!IsHTMLInputElement(node))
     return false;
 
   const HTMLInputElement* input = toHTMLInputElement(node);
@@ -1141,7 +1141,7 @@
                                 &related_objects, nullptr);
 
   AccessibilityRole role = RoleValue();
-  if (!GetNode() || (!isHTMLBRElement(GetNode()) && role != kStaticTextRole &&
+  if (!GetNode() || (!IsHTMLBRElement(GetNode()) && role != kStaticTextRole &&
                      role != kInlineTextBoxRole))
     text = CollapseWhitespace(text);
 
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.cpp b/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.cpp
index 551040f..99fed572 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.cpp
@@ -177,14 +177,13 @@
     focused_node = document_;
 
   // If it's an image map, get the focused link within the image map.
-  if (isHTMLAreaElement(focused_node))
-    return FocusedImageMapUIElement(toHTMLAreaElement(focused_node));
+  if (auto* area = ToHTMLAreaElementOrNull(focused_node))
+    return FocusedImageMapUIElement(area);
 
   // See if there's a page popup, for example a calendar picker.
   Element* adjusted_focused_element = document_->AdjustedFocusedElement();
-  if (isHTMLInputElement(adjusted_focused_element)) {
-    if (AXObject* ax_popup =
-            toHTMLInputElement(adjusted_focused_element)->PopupRootAXObject()) {
+  if (auto* input = ToHTMLInputElementOrNull(adjusted_focused_element)) {
+    if (AXObject* ax_popup = input->PopupRootAXObject()) {
       if (Element* focused_element_in_popup =
               ax_popup->GetDocument()->FocusedElement())
         focused_node = focused_element_in_popup;
@@ -218,7 +217,7 @@
 // Returns true if |node| is an <option> element and its parent <select>
 // is a menu list (not a list box).
 static bool IsMenuListOption(const Node* node) {
-  if (!isHTMLOptionElement(node))
+  if (!IsHTMLOptionElement(node))
     return false;
   const HTMLSelectElement* select =
       toHTMLOptionElement(node)->OwnerSelectElement();
@@ -235,7 +234,7 @@
   // Menu list option and HTML area elements are indexed by DOM node, never by
   // layout object.
   LayoutObject* layout_object = node->GetLayoutObject();
-  if (IsMenuListOption(node) || isHTMLAreaElement(node))
+  if (IsMenuListOption(node) || IsHTMLAreaElement(node))
     layout_object = nullptr;
 
   AXID layout_id = layout_object ? layout_object_mapping_.at(layout_object) : 0;
@@ -306,8 +305,8 @@
   // ul/ol/dl type (it shouldn't be a list if aria says otherwise).
   if (NodeHasRole(node, "list") || NodeHasRole(node, "directory") ||
       (NodeHasRole(node, g_null_atom) &&
-       (isHTMLUListElement(node) || isHTMLOListElement(node) ||
-        isHTMLDListElement(node))))
+       (IsHTMLUListElement(node) || IsHTMLOListElement(node) ||
+        IsHTMLDListElement(node))))
     return AXList::Create(layout_object, *this);
 
   // aria tables
@@ -323,10 +322,10 @@
   if (node && node->IsMediaControlElement())
     return AccessibilityMediaControl::Create(layout_object, *this);
 
-  if (isHTMLOptionElement(node))
+  if (IsHTMLOptionElement(node))
     return AXListBoxOption::Create(layout_object, *this);
 
-  if (isHTMLInputElement(node) &&
+  if (IsHTMLInputElement(node) &&
       toHTMLInputElement(node)->type() == InputTypeNames::radio)
     return AXRadioInput::Create(layout_object, *this);
 
@@ -378,8 +377,8 @@
   if (IsMenuListOption(node))
     return AXMenuListOption::Create(toHTMLOptionElement(node), *this);
 
-  if (isHTMLAreaElement(node))
-    return AXImageMapLink::Create(toHTMLAreaElement(node), *this);
+  if (auto* area = ToHTMLAreaElementOrNull(node))
+    return AXImageMapLink::Create(area, *this);
 
   return AXNodeObject::Create(node, *this);
 }
@@ -414,13 +413,13 @@
   // If the node has a layout object, prefer using that as the primary key for
   // the AXObject, with the exception of an HTMLAreaElement, which is
   // created based on its node.
-  if (node->GetLayoutObject() && !isHTMLAreaElement(node))
+  if (node->GetLayoutObject() && !IsHTMLAreaElement(node))
     return GetOrCreate(node->GetLayoutObject());
 
   if (!node->parentElement())
     return 0;
 
-  if (isHTMLHeadElement(node))
+  if (IsHTMLHeadElement(node))
     return 0;
 
   AXObject* new_obj = CreateFromNode(node);
@@ -877,7 +876,7 @@
     HandleAriaRoleChanged(element);
   else if (attr_name == altAttr || attr_name == titleAttr)
     TextChanged(element);
-  else if (attr_name == forAttr && isHTMLLabelElement(*element))
+  else if (attr_name == forAttr && IsHTMLLabelElement(*element))
     LabelChanged(element);
   else if (attr_name == idAttr)
     relation_cache_->UpdateRelatedTree(element);
@@ -912,7 +911,6 @@
 }
 
 void AXObjectCacheImpl::LabelChanged(Element* element) {
-  DCHECK(isHTMLLabelElement(element));
   TextChanged(toHTMLLabelElement(element)->control());
 }
 
diff --git a/third_party/WebKit/Source/modules/accessibility/AXRelationCache.cpp b/third_party/WebKit/Source/modules/accessibility/AXRelationCache.cpp
index 9fcb057..02d696c 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXRelationCache.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXRelationCache.cpp
@@ -256,7 +256,7 @@
     }
 
     // Forward relation via <label for="[id]">.
-    if (isHTMLLabelElement(*node))
+    if (IsHTMLLabelElement(*node))
       LabelChanged(node);
 
     node = node->parentNode();
@@ -295,9 +295,7 @@
 }
 
 void AXRelationCache::LabelChanged(Node* node) {
-  DCHECK(isHTMLLabelElement(node));
-  LabelableElement* control = toHTMLLabelElement(node)->control();
-  if (control)
+  if (LabelableElement* control = toHTMLLabelElement(node)->control())
     TextChanged(Get(control));
 }
 
diff --git a/third_party/WebKit/Source/modules/accessibility/AXTable.cpp b/third_party/WebKit/Source/modules/accessibility/AXTable.cpp
index fc5828c..a5c861db 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXTable.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXTable.cpp
@@ -114,7 +114,7 @@
 
   LayoutTable* table = ToLayoutTable(layout_object_);
   Node* table_node = table->GetNode();
-  if (!isHTMLTableElement(table_node))
+  if (!IsHTMLTableElement(table_node))
     return false;
 
   // Do not consider it a data table if any of its descendants have an ARIA
@@ -382,7 +382,7 @@
   AXObjectCacheImpl& ax_cache = AxObjectCache();
 
   Node* table_node = table->GetNode();
-  if (!isHTMLTableElement(table_node))
+  if (!IsHTMLTableElement(table_node))
     return;
 
   // Add caption
diff --git a/third_party/WebKit/Source/modules/accessibility/InspectorAccessibilityAgent.cpp b/third_party/WebKit/Source/modules/accessibility/InspectorAccessibilityAgent.cpp
index d63cf0aa..4fa6b0a 100644
--- a/third_party/WebKit/Source/modules/accessibility/InspectorAccessibilityAgent.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/InspectorAccessibilityAgent.cpp
@@ -686,10 +686,9 @@
   std::unique_ptr<protocol::Array<AXNodeId>> child_ids =
       protocol::Array<AXNodeId>::create();
 
-  if (&ax_object != inspected_ax_object ||
-      (inspected_ax_object && !inspected_ax_object->AccessibilityIsIgnored())) {
+  if (!ax_object.AccessibilityIsIgnored())
     AddChildren(ax_object, inspected_ax_object, child_ids, nodes, cache);
-  }
+
   node_object.setChildIds(std::move(child_ids));
 }
 
@@ -714,7 +713,8 @@
     if (&ax_object != inspected_ax_object) {
       if (!inspected_ax_object)
         continue;
-      if (&ax_object != inspected_ax_object->ParentObjectUnignored())
+      if (&ax_object != inspected_ax_object->ParentObjectUnignored() &&
+          ax_object.GetNode())
         continue;
     }
 
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.cpp b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.cpp
index ede47957..4a3726ce 100644
--- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.cpp
+++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.cpp
@@ -313,9 +313,9 @@
     ExceptionState& exception_state) {
   Vector<WebServiceWorkerRequest> web_requests;
 
-  if (requests.isRequestOrUSVStringSequence()) {
+  if (requests.IsRequestOrUSVStringSequence()) {
     HeapVector<RequestOrUSVString> request_vector =
-        requests.getAsRequestOrUSVStringSequence();
+        requests.GetAsRequestOrUSVStringSequence();
 
     // Throw a TypeError when the developer has passed an empty sequence.
     if (!request_vector.size()) {
@@ -329,10 +329,10 @@
       const RequestOrUSVString& request_or_url = request_vector[i];
 
       Request* request = nullptr;
-      if (request_or_url.isRequest()) {
-        request = request_or_url.getAsRequest();
-      } else if (request_or_url.isUSVString()) {
-        request = Request::Create(script_state, request_or_url.getAsUSVString(),
+      if (request_or_url.IsRequest()) {
+        request = request_or_url.GetAsRequest();
+      } else if (request_or_url.IsUSVString()) {
+        request = Request::Create(script_state, request_or_url.GetAsUSVString(),
                                   exception_state);
         if (exception_state.HadException())
           return Vector<WebServiceWorkerRequest>();
@@ -344,12 +344,12 @@
       DCHECK(request);
       request->PopulateWebServiceWorkerRequest(web_requests[i]);
     }
-  } else if (requests.isRequest()) {
-    DCHECK(requests.getAsRequest());
+  } else if (requests.IsRequest()) {
+    DCHECK(requests.GetAsRequest());
     web_requests.resize(1);
-    requests.getAsRequest()->PopulateWebServiceWorkerRequest(web_requests[0]);
-  } else if (requests.isUSVString()) {
-    Request* request = Request::Create(script_state, requests.getAsUSVString(),
+    requests.GetAsRequest()->PopulateWebServiceWorkerRequest(web_requests[0]);
+  } else if (requests.IsUSVString()) {
+    Request* request = Request::Create(script_state, requests.GetAsUSVString(),
                                        exception_state);
     if (exception_state.HadException())
       return Vector<WebServiceWorkerRequest>();
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManagerTest.cpp b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManagerTest.cpp
index cc9cb04c..a79cff8 100644
--- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManagerTest.cpp
+++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManagerTest.cpp
@@ -62,7 +62,7 @@
   KURL image_url(kParsedURLString, "https://www.example.com/my_image.png");
 
   RequestOrUSVStringOrRequestOrUSVStringSequence requests =
-      RequestOrUSVStringOrRequestOrUSVStringSequence::fromUSVString(
+      RequestOrUSVStringOrRequestOrUSVStringSequence::FromUSVString(
           image_url.GetString());
 
   Vector<WebServiceWorkerRequest> web_requests =
@@ -88,7 +88,7 @@
   ASSERT_TRUE(request);
 
   RequestOrUSVStringOrRequestOrUSVStringSequence requests =
-      RequestOrUSVStringOrRequestOrUSVStringSequence::fromRequest(request);
+      RequestOrUSVStringOrRequestOrUSVStringSequence::FromRequest(request);
 
   Vector<WebServiceWorkerRequest> web_requests =
       CreateWebRequestVector(scope, requests);
@@ -110,9 +110,9 @@
                      "https://www.example.com/my_cat_video.avi");
 
   RequestOrUSVString image_request =
-      RequestOrUSVString::fromUSVString(image_url.GetString());
+      RequestOrUSVString::FromUSVString(image_url.GetString());
   RequestOrUSVString icon_request =
-      RequestOrUSVString::fromUSVString(icon_url.GetString());
+      RequestOrUSVString::FromUSVString(icon_url.GetString());
 
   Request* request = Request::Create(
       scope.GetScriptState(), cat_video_url.GetString(),
@@ -121,7 +121,7 @@
   ASSERT_TRUE(request);
 
   RequestOrUSVString cat_video_request =
-      RequestOrUSVString::fromRequest(request);
+      RequestOrUSVString::FromRequest(request);
 
   HeapVector<RequestOrUSVString> request_sequence;
   request_sequence.push_back(image_request);
@@ -130,7 +130,7 @@
 
   RequestOrUSVStringOrRequestOrUSVStringSequence requests =
       RequestOrUSVStringOrRequestOrUSVStringSequence::
-          fromRequestOrUSVStringSequence(request_sequence);
+          FromRequestOrUSVStringSequence(request_sequence);
 
   Vector<WebServiceWorkerRequest> web_requests =
       CreateWebRequestVector(scope, requests);
@@ -153,7 +153,7 @@
   HeapVector<RequestOrUSVString> request_sequence;
   RequestOrUSVStringOrRequestOrUSVStringSequence requests =
       RequestOrUSVStringOrRequestOrUSVStringSequence::
-          fromRequestOrUSVStringSequence(request_sequence);
+          FromRequestOrUSVStringSequence(request_sequence);
 
   Vector<WebServiceWorkerRequest> web_requests =
       CreateWebRequestVector(scope, requests);
@@ -168,7 +168,7 @@
 
   RequestOrUSVString null_request;
   RequestOrUSVString image_request =
-      RequestOrUSVString::fromUSVString(image_url.GetString());
+      RequestOrUSVString::FromUSVString(image_url.GetString());
 
   HeapVector<RequestOrUSVString> request_sequence;
   request_sequence.push_back(image_request);
@@ -176,7 +176,7 @@
 
   RequestOrUSVStringOrRequestOrUSVStringSequence requests =
       RequestOrUSVStringOrRequestOrUSVStringSequence::
-          fromRequestOrUSVStringSequence(request_sequence);
+          FromRequestOrUSVStringSequence(request_sequence);
 
   Vector<WebServiceWorkerRequest> web_requests =
       CreateWebRequestVector(scope, requests);
diff --git a/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.cpp b/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.cpp
index ff19b2c..8f37b8b0 100644
--- a/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.cpp
+++ b/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.cpp
@@ -114,12 +114,12 @@
   size_t beacon_size = 0;
   bool allowed;
 
-  if (data.isArrayBufferView()) {
+  if (data.IsArrayBufferView()) {
     allowed =
         PingLoader::SendBeacon(GetSupplementable()->GetFrame(), allowance, url,
-                               data.getAsArrayBufferView().View(), beacon_size);
-  } else if (data.isBlob()) {
-    Blob* blob = data.getAsBlob();
+                               data.GetAsArrayBufferView().View(), beacon_size);
+  } else if (data.IsBlob()) {
+    Blob* blob = data.GetAsBlob();
     if (!FetchUtils::IsCORSSafelistedContentType(AtomicString(blob->type()))) {
       UseCounter::Count(context,
                         WebFeature::kSendBeaconWithNonSimpleContentType);
@@ -134,12 +134,12 @@
     }
     allowed = PingLoader::SendBeacon(GetSupplementable()->GetFrame(), allowance,
                                      url, blob, beacon_size);
-  } else if (data.isString()) {
+  } else if (data.IsString()) {
     allowed = PingLoader::SendBeacon(GetSupplementable()->GetFrame(), allowance,
-                                     url, data.getAsString(), beacon_size);
-  } else if (data.isFormData()) {
+                                     url, data.GetAsString(), beacon_size);
+  } else if (data.IsFormData()) {
     allowed = PingLoader::SendBeacon(GetSupplementable()->GetFrame(), allowance,
-                                     url, data.getAsFormData(), beacon_size);
+                                     url, data.GetAsFormData(), beacon_size);
   } else {
     allowed = PingLoader::SendBeacon(GetSupplementable()->GetFrame(), allowance,
                                      url, String(), beacon_size);
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.cpp b/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.cpp
index bd8d00bf..f3c285de 100644
--- a/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.cpp
+++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.cpp
@@ -308,10 +308,10 @@
 
   // If name is an unsigned long, return BluetoothUUID.cannonicalUUI(name) and
   // abort this steps.
-  if (name.isUnsignedLong())
-    return BluetoothUUID::canonicalUUID(name.getAsUnsignedLong());
+  if (name.IsUnsignedLong())
+    return BluetoothUUID::canonicalUUID(name.GetAsUnsignedLong());
 
-  String name_str = name.getAsString();
+  String name_str = name.GetAsString();
 
   // If name is a valid UUID, return name and abort these steps.
   if (IsValidUUID(name_str))
diff --git a/third_party/WebKit/Source/modules/cachestorage/Cache.cpp b/third_party/WebKit/Source/modules/cachestorage/Cache.cpp
index ffd3cbcb..2bfaa1cd 100644
--- a/third_party/WebKit/Source/modules/cachestorage/Cache.cpp
+++ b/third_party/WebKit/Source/modules/cachestorage/Cache.cpp
@@ -386,11 +386,11 @@
                            const RequestInfo& request,
                            const CacheQueryOptions& options,
                            ExceptionState& exception_state) {
-  DCHECK(!request.isNull());
-  if (request.isRequest())
-    return MatchImpl(script_state, request.getAsRequest(), options);
+  DCHECK(!request.IsNull());
+  if (request.IsRequest())
+    return MatchImpl(script_state, request.GetAsRequest(), options);
   Request* new_request =
-      Request::Create(script_state, request.getAsUSVString(), exception_state);
+      Request::Create(script_state, request.GetAsUSVString(), exception_state);
   if (exception_state.HadException())
     return ScriptPromise();
   return MatchImpl(script_state, new_request, options);
@@ -405,11 +405,11 @@
                               const RequestInfo& request,
                               const CacheQueryOptions& options,
                               ExceptionState& exception_state) {
-  DCHECK(!request.isNull());
-  if (request.isRequest())
-    return MatchAllImpl(script_state, request.getAsRequest(), options);
+  DCHECK(!request.IsNull());
+  if (request.IsRequest())
+    return MatchAllImpl(script_state, request.GetAsRequest(), options);
   Request* new_request =
-      Request::Create(script_state, request.getAsUSVString(), exception_state);
+      Request::Create(script_state, request.GetAsUSVString(), exception_state);
   if (exception_state.HadException())
     return ScriptPromise();
   return MatchAllImpl(script_state, new_request, options);
@@ -418,12 +418,12 @@
 ScriptPromise Cache::add(ScriptState* script_state,
                          const RequestInfo& request,
                          ExceptionState& exception_state) {
-  DCHECK(!request.isNull());
+  DCHECK(!request.IsNull());
   HeapVector<Member<Request>> requests;
-  if (request.isRequest()) {
-    requests.push_back(request.getAsRequest());
+  if (request.IsRequest()) {
+    requests.push_back(request.GetAsRequest());
   } else {
-    requests.push_back(Request::Create(script_state, request.getAsUSVString(),
+    requests.push_back(Request::Create(script_state, request.GetAsUSVString(),
                                        exception_state));
     if (exception_state.HadException())
       return ScriptPromise();
@@ -437,10 +437,10 @@
                             ExceptionState& exception_state) {
   HeapVector<Member<Request>> requests;
   for (RequestInfo request : raw_requests) {
-    if (request.isRequest()) {
-      requests.push_back(request.getAsRequest());
+    if (request.IsRequest()) {
+      requests.push_back(request.GetAsRequest());
     } else {
-      requests.push_back(Request::Create(script_state, request.getAsUSVString(),
+      requests.push_back(Request::Create(script_state, request.GetAsUSVString(),
                                          exception_state));
       if (exception_state.HadException())
         return ScriptPromise();
@@ -454,11 +454,11 @@
                                     const RequestInfo& request,
                                     const CacheQueryOptions& options,
                                     ExceptionState& exception_state) {
-  DCHECK(!request.isNull());
-  if (request.isRequest())
-    return DeleteImpl(script_state, request.getAsRequest(), options);
+  DCHECK(!request.IsNull());
+  if (request.IsRequest())
+    return DeleteImpl(script_state, request.GetAsRequest(), options);
   Request* new_request =
-      Request::Create(script_state, request.getAsUSVString(), exception_state);
+      Request::Create(script_state, request.GetAsUSVString(), exception_state);
   if (exception_state.HadException())
     return ScriptPromise();
   return DeleteImpl(script_state, new_request, options);
@@ -468,13 +468,13 @@
                          const RequestInfo& request,
                          Response* response,
                          ExceptionState& exception_state) {
-  DCHECK(!request.isNull());
-  if (request.isRequest())
+  DCHECK(!request.IsNull());
+  if (request.IsRequest())
     return PutImpl(script_state,
-                   HeapVector<Member<Request>>(1, request.getAsRequest()),
+                   HeapVector<Member<Request>>(1, request.GetAsRequest()),
                    HeapVector<Member<Response>>(1, response));
   Request* new_request =
-      Request::Create(script_state, request.getAsUSVString(), exception_state);
+      Request::Create(script_state, request.GetAsUSVString(), exception_state);
   if (exception_state.HadException())
     return ScriptPromise();
   return PutImpl(script_state, HeapVector<Member<Request>>(1, new_request),
@@ -489,11 +489,11 @@
                           const RequestInfo& request,
                           const CacheQueryOptions& options,
                           ExceptionState& exception_state) {
-  DCHECK(!request.isNull());
-  if (request.isRequest())
-    return KeysImpl(script_state, request.getAsRequest(), options);
+  DCHECK(!request.IsNull());
+  if (request.IsRequest())
+    return KeysImpl(script_state, request.GetAsRequest(), options);
   Request* new_request =
-      Request::Create(script_state, request.getAsUSVString(), exception_state);
+      Request::Create(script_state, request.GetAsUSVString(), exception_state);
   if (exception_state.HadException())
     return ScriptPromise();
   return KeysImpl(script_state, new_request, options);
@@ -585,7 +585,7 @@
           V8ThrowException::CreateTypeError(
               script_state->GetIsolate(),
               "Add/AddAll only supports the GET request method."));
-    request_infos[i].setRequest(requests[i]);
+    request_infos[i].SetRequest(requests[i]);
 
     promises[i] = scoped_fetcher_->Fetch(script_state, request_infos[i],
                                          Dictionary(), exception_state);
diff --git a/third_party/WebKit/Source/modules/cachestorage/CacheStorage.cpp b/third_party/WebKit/Source/modules/cachestorage/CacheStorage.cpp
index f9ea1d07..34c6bd3 100644
--- a/third_party/WebKit/Source/modules/cachestorage/CacheStorage.cpp
+++ b/third_party/WebKit/Source/modules/cachestorage/CacheStorage.cpp
@@ -310,14 +310,14 @@
                                   const RequestInfo& request,
                                   const CacheQueryOptions& options,
                                   ExceptionState& exception_state) {
-  DCHECK(!request.isNull());
+  DCHECK(!request.IsNull());
   if (!CommonChecks(script_state, exception_state))
     return ScriptPromise();
 
-  if (request.isRequest())
-    return MatchImpl(script_state, request.getAsRequest(), options);
+  if (request.IsRequest())
+    return MatchImpl(script_state, request.GetAsRequest(), options);
   Request* new_request =
-      Request::Create(script_state, request.getAsUSVString(), exception_state);
+      Request::Create(script_state, request.GetAsUSVString(), exception_state);
   if (exception_state.HadException())
     return ScriptPromise();
   return MatchImpl(script_state, new_request, options);
diff --git a/third_party/WebKit/Source/modules/cachestorage/CacheTest.cpp b/third_party/WebKit/Source/modules/cachestorage/CacheTest.cpp
index 24d8d2b2..a217d66 100644
--- a/third_party/WebKit/Source/modules/cachestorage/CacheTest.cpp
+++ b/third_party/WebKit/Source/modules/cachestorage/CacheTest.cpp
@@ -55,10 +55,10 @@
     ++fetch_count_;
     if (expected_url_) {
       String fetched_url;
-      if (request_info.isRequest())
-        EXPECT_EQ(*expected_url_, request_info.getAsRequest()->url());
+      if (request_info.IsRequest())
+        EXPECT_EQ(*expected_url_, request_info.GetAsRequest()->url());
       else
-        EXPECT_EQ(*expected_url_, request_info.getAsUSVString());
+        EXPECT_EQ(*expected_url_, request_info.GetAsUSVString());
     }
 
     if (response_) {
@@ -341,13 +341,13 @@
 
 RequestInfo StringToRequestInfo(const String& value) {
   RequestInfo info;
-  info.setUSVString(value);
+  info.SetUSVString(value);
   return info;
 }
 
 RequestInfo RequestToRequestInfo(Request* value) {
   RequestInfo info;
-  info.setRequest(value);
+  info.SetRequest(value);
   return info;
 }
 
diff --git a/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp
index 1eb1556..bc49380ec8 100644
--- a/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp
+++ b/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp
@@ -156,14 +156,14 @@
     CanvasStyle* style,
     StringOrCanvasGradientOrCanvasPattern& return_value) {
   if (CanvasGradient* gradient = style->GetCanvasGradient()) {
-    return_value.setCanvasGradient(gradient);
+    return_value.SetCanvasGradient(gradient);
     return;
   }
   if (CanvasPattern* pattern = style->GetCanvasPattern()) {
-    return_value.setCanvasPattern(pattern);
+    return_value.SetCanvasPattern(pattern);
     return;
   }
-  return_value.setString(style->GetColor());
+  return_value.SetString(style->GetColor());
 }
 
 void BaseRenderingContext2D::strokeStyle(
@@ -173,12 +173,12 @@
 
 void BaseRenderingContext2D::setStrokeStyle(
     const StringOrCanvasGradientOrCanvasPattern& style) {
-  DCHECK(!style.isNull());
+  DCHECK(!style.IsNull());
 
   String color_string;
   CanvasStyle* canvas_style = nullptr;
-  if (style.isString()) {
-    color_string = style.getAsString();
+  if (style.IsString()) {
+    color_string = style.GetAsString();
     if (color_string == GetState().UnparsedStrokeColor())
       return;
     Color parsed_color = 0;
@@ -189,10 +189,10 @@
       return;
     }
     canvas_style = CanvasStyle::CreateFromRGBA(parsed_color.Rgb());
-  } else if (style.isCanvasGradient()) {
-    canvas_style = CanvasStyle::CreateFromGradient(style.getAsCanvasGradient());
-  } else if (style.isCanvasPattern()) {
-    CanvasPattern* canvas_pattern = style.getAsCanvasPattern();
+  } else if (style.IsCanvasGradient()) {
+    canvas_style = CanvasStyle::CreateFromGradient(style.GetAsCanvasGradient());
+  } else if (style.IsCanvasPattern()) {
+    CanvasPattern* canvas_pattern = style.GetAsCanvasPattern();
 
     if (OriginClean() && !canvas_pattern->OriginClean())
       SetOriginTainted();
@@ -214,12 +214,12 @@
 
 void BaseRenderingContext2D::setFillStyle(
     const StringOrCanvasGradientOrCanvasPattern& style) {
-  DCHECK(!style.isNull());
+  DCHECK(!style.IsNull());
   ValidateStateStack();
   String color_string;
   CanvasStyle* canvas_style = nullptr;
-  if (style.isString()) {
-    color_string = style.getAsString();
+  if (style.IsString()) {
+    color_string = style.GetAsString();
     if (color_string == GetState().UnparsedFillColor())
       return;
     Color parsed_color = 0;
@@ -230,10 +230,10 @@
       return;
     }
     canvas_style = CanvasStyle::CreateFromRGBA(parsed_color.Rgb());
-  } else if (style.isCanvasGradient()) {
-    canvas_style = CanvasStyle::CreateFromGradient(style.getAsCanvasGradient());
-  } else if (style.isCanvasPattern()) {
-    CanvasPattern* canvas_pattern = style.getAsCanvasPattern();
+  } else if (style.IsCanvasGradient()) {
+    canvas_style = CanvasStyle::CreateFromGradient(style.GetAsCanvasGradient());
+  } else if (style.IsCanvasPattern()) {
+    CanvasPattern* canvas_pattern = style.GetAsCanvasPattern();
 
     if (OriginClean() && !canvas_pattern->OriginClean())
       SetOriginTainted();
@@ -904,39 +904,39 @@
 static inline CanvasImageSource* ToImageSourceInternal(
     const CanvasImageSourceUnion& value,
     ExceptionState& exception_state) {
-  if (value.isCSSImageValue()) {
+  if (value.IsCSSImageValue()) {
     if (RuntimeEnabledFeatures::CSSPaintAPIEnabled())
-      return value.getAsCSSImageValue();
+      return value.GetAsCSSImageValue();
     exception_state.ThrowTypeError("CSSImageValue is not yet supported");
     return nullptr;
   }
-  if (value.isHTMLImageElement())
-    return value.getAsHTMLImageElement();
-  if (value.isHTMLVideoElement()) {
-    HTMLVideoElement* video = value.getAsHTMLVideoElement();
+  if (value.IsHTMLImageElement())
+    return value.GetAsHTMLImageElement();
+  if (value.IsHTMLVideoElement()) {
+    HTMLVideoElement* video = value.GetAsHTMLVideoElement();
     video->VideoWillBeDrawnToCanvas();
     return video;
   }
-  if (value.isSVGImageElement())
-    return value.getAsSVGImageElement();
-  if (value.isHTMLCanvasElement())
-    return value.getAsHTMLCanvasElement();
-  if (value.isImageBitmap()) {
-    if (static_cast<ImageBitmap*>(value.getAsImageBitmap())->IsNeutered()) {
+  if (value.IsSVGImageElement())
+    return value.GetAsSVGImageElement();
+  if (value.IsHTMLCanvasElement())
+    return value.GetAsHTMLCanvasElement();
+  if (value.IsImageBitmap()) {
+    if (static_cast<ImageBitmap*>(value.GetAsImageBitmap())->IsNeutered()) {
       exception_state.ThrowDOMException(
           kInvalidStateError, String::Format("The image source is detached"));
       return nullptr;
     }
-    return value.getAsImageBitmap();
+    return value.GetAsImageBitmap();
   }
-  if (value.isOffscreenCanvas()) {
-    if (static_cast<OffscreenCanvas*>(value.getAsOffscreenCanvas())
+  if (value.IsOffscreenCanvas()) {
+    if (static_cast<OffscreenCanvas*>(value.GetAsOffscreenCanvas())
             ->IsNeutered()) {
       exception_state.ThrowDOMException(
           kInvalidStateError, String::Format("The image source is detached"));
       return nullptr;
     }
-    return value.getAsOffscreenCanvas();
+    return value.GetAsOffscreenCanvas();
   }
   NOTREACHED();
   return nullptr;
@@ -1303,7 +1303,7 @@
       [this, &image_source, &image, &src_rect, dst_rect](
           PaintCanvas* c, const PaintFlags* flags)  // draw lambda
       {
-        DrawImageInternal(c, image_source, image.Get(), src_rect, dst_rect,
+        DrawImageInternal(c, image_source, image.get(), src_rect, dst_rect,
                           flags);
       },
       [this, &dst_rect](const SkIRect& clip_bounds)  // overdraw test lambda
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasGradient.h b/third_party/WebKit/Source/modules/canvas2d/CanvasGradient.h
index 400eea9..14011b76 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasGradient.h
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasGradient.h
@@ -53,7 +53,7 @@
     return new CanvasGradient(p0, r0, p1, r1);
   }
 
-  Gradient* GetGradient() const { return gradient_.Get(); }
+  Gradient* GetGradient() const { return gradient_.get(); }
 
   void addColorStop(float value, const String& color, ExceptionState&);
 
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasPattern.h b/third_party/WebKit/Source/modules/canvas2d/CanvasPattern.h
index 483565af..d414115 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasPattern.h
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasPattern.h
@@ -50,7 +50,7 @@
     return new CanvasPattern(std::move(image), repeat, origin_clean);
   }
 
-  Pattern* GetPattern() const { return pattern_.Get(); }
+  Pattern* GetPattern() const { return pattern_.get(); }
   const AffineTransform& GetTransform() const { return pattern_transform_; }
 
   bool OriginClean() const { return origin_clean_; }
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp
index 9313023..44cd4aa6 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp
@@ -140,7 +140,7 @@
 
 void CanvasRenderingContext2D::SetCanvasGetContextResult(
     RenderingContext& result) {
-  result.setCanvasRenderingContext2D(this);
+  result.SetCanvasRenderingContext2D(this);
 }
 
 CanvasRenderingContext2D::~CanvasRenderingContext2D() {}
@@ -492,7 +492,7 @@
       font_style->SetFontDescription(element_font_description);
       font_style->GetFont().Update(font_style->GetFont().GetFontSelector());
       canvas()->GetDocument().EnsureStyleResolver().ComputeFont(
-          font_style.Get(), *parsed_style);
+          font_style.get(), *parsed_style);
 
       // We need to reset Computed and Adjusted size so we skip zoom and
       // minimum font size.
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DAPITest.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DAPITest.cpp
index 957537e..9c6fee44 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DAPITest.cpp
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DAPITest.cpp
@@ -143,24 +143,24 @@
 String TrySettingStrokeStyle(CanvasRenderingContext2D* ctx,
                              const String& value) {
   StringOrCanvasGradientOrCanvasPattern arg1, arg2, arg3;
-  arg1.setString("#666");
+  arg1.SetString("#666");
   ctx->setStrokeStyle(arg1);
-  arg2.setString(value);
+  arg2.SetString(value);
   ctx->setStrokeStyle(arg2);
   ctx->strokeStyle(arg3);
-  EXPECT_TRUE(arg3.isString());
-  return arg3.getAsString();
+  EXPECT_TRUE(arg3.IsString());
+  return arg3.GetAsString();
 }
 
 String TrySettingFillStyle(CanvasRenderingContext2D* ctx, const String& value) {
   StringOrCanvasGradientOrCanvasPattern arg1, arg2, arg3;
-  arg1.setString("#666");
+  arg1.SetString("#666");
   ctx->setFillStyle(arg1);
-  arg2.setString(value);
+  arg2.SetString(value);
   ctx->setFillStyle(arg2);
   ctx->fillStyle(arg3);
-  EXPECT_TRUE(arg3.isString());
-  return arg3.getAsString();
+  EXPECT_TRUE(arg3.IsString());
+  return arg3.GetAsString();
 }
 
 String TrySettingShadowColor(CanvasRenderingContext2D* ctx,
@@ -198,15 +198,15 @@
   {
     StringOrCanvasGradientOrCanvasPattern value;
     Context2d()->strokeStyle(value);
-    EXPECT_TRUE(value.isString());
-    EXPECT_EQ(String("#000000"), value.getAsString());
+    EXPECT_TRUE(value.IsString());
+    EXPECT_EQ(String("#000000"), value.GetAsString());
   }
 
   {
     StringOrCanvasGradientOrCanvasPattern value;
     Context2d()->fillStyle(value);
-    EXPECT_TRUE(value.isString());
-    EXPECT_EQ(String("#000000"), value.getAsString());
+    EXPECT_TRUE(value.IsString());
+    EXPECT_EQ(String("#000000"), value.GetAsString());
   }
 
   EXPECT_EQ(String("rgba(0, 0, 0, 0)"), Context2d()->shadowColor());
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DState.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DState.cpp
index 131b473..ae14c567 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DState.cpp
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DState.cpp
@@ -332,8 +332,8 @@
     filter_style->SetFont(font_for_filter_);
 
     StyleResolverState resolver_state(style_resolution_host->GetDocument(),
-                                      style_resolution_host, filter_style.Get(),
-                                      filter_style.Get());
+                                      style_resolution_host, filter_style.get(),
+                                      filter_style.get());
     resolver_state.SetStyle(filter_style);
 
     StyleBuilder::ApplyProperty(CSSPropertyFilter, resolver_state,
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
index bfaa23c..bd4a8941 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
@@ -224,7 +224,7 @@
   EXPECT_FALSE(exception_state.HadException());
   opaque_gradient->addColorStop(1, String("blue"), exception_state);
   EXPECT_FALSE(exception_state.HadException());
-  this->OpaqueGradient().setCanvasGradient(opaque_gradient);
+  this->OpaqueGradient().SetCanvasGradient(opaque_gradient);
 
   CanvasGradient* alpha_gradient =
       CanvasGradient::Create(FloatPoint(0, 0), FloatPoint(10, 0));
@@ -234,7 +234,7 @@
                                exception_state);
   EXPECT_FALSE(exception_state.HadException());
   StringOrCanvasGradientOrCanvasPattern wrapped_alpha_gradient;
-  this->AlphaGradient().setCanvasGradient(alpha_gradient);
+  this->AlphaGradient().SetCanvasGradient(alpha_gradient);
 
   global_memory_cache_ = ReplaceMemoryCacheForTesting(MemoryCache::Create());
 }
@@ -841,7 +841,7 @@
       canvas->GetCanvasRenderingContext("2d", attributes));
   DummyExceptionStateForTesting exception_state;
   CanvasImageSourceUnion image_source;
-  image_source.setImageBitmap(image_bitmap_derived);
+  image_source.SetImageBitmap(image_bitmap_derived);
   context->drawImage(GetScriptState(), image_source, 0, 0, exception_state);
 }
 
@@ -1103,7 +1103,7 @@
   CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(
       canvas->GetCanvasRenderingContext("2d", attributes));
   StringOrCanvasGradientOrCanvasPattern fill_style;
-  fill_style.setString("#FF0000");
+  fill_style.SetString("#FF0000");
   context->setFillStyle(fill_style);
   context->fillRect(0, 0, 10, 10);
   NonThrowableExceptionState exception_state;
@@ -1412,7 +1412,7 @@
         pixels_from_get_image_data =
             context->getImageData(0, 0, 2, 2, exception_state)
                 ->dataUnion()
-                .getAsFloat32Array()
+                .GetAsFloat32Array()
                 .View()
                 ->Data();
         ColorCorrectionTestUtils::CompareColorCorrectedPixels(
diff --git a/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletGlobalScopeTest.cpp b/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletGlobalScopeTest.cpp
index efd7703a..c65edfe 100644
--- a/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletGlobalScopeTest.cpp
+++ b/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletGlobalScopeTest.cpp
@@ -49,7 +49,7 @@
         WTF::MakeUnique<GlobalScopeCreationParams>(
             KURL(kParsedURLString, "http://fake.url/"), "fake user agent", "",
             nullptr, kDontPauseWorkerGlobalScopeOnStart, nullptr, "",
-            security_origin_.Get(), clients, kWebAddressSpaceLocal, nullptr,
+            security_origin_.get(), clients, kWebAddressSpaceLocal, nullptr,
             nullptr, kV8CacheOptionsDefault),
         WTF::nullopt, ParentFrameTaskRunners::Create());
     return thread;
diff --git a/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThreadTest.cpp b/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThreadTest.cpp
index 616008b5..e35a914 100644
--- a/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThreadTest.cpp
+++ b/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThreadTest.cpp
@@ -85,7 +85,7 @@
         WTF::MakeUnique<GlobalScopeCreationParams>(
             KURL(kParsedURLString, "http://fake.url/"), "fake user agent", "",
             nullptr, kDontPauseWorkerGlobalScopeOnStart, nullptr, "",
-            security_origin_.Get(), clients, kWebAddressSpaceLocal, nullptr,
+            security_origin_.get(), clients, kWebAddressSpaceLocal, nullptr,
             nullptr, kV8CacheOptionsDefault),
         WTF::nullopt, ParentFrameTaskRunners::Create());
     return thread;
diff --git a/third_party/WebKit/Source/modules/compositorworker/WorkletAnimation.cpp b/third_party/WebKit/Source/modules/compositorworker/WorkletAnimation.cpp
index b3ff234..9b1f102 100644
--- a/third_party/WebKit/Source/modules/compositorworker/WorkletAnimation.cpp
+++ b/third_party/WebKit/Source/modules/compositorworker/WorkletAnimation.cpp
@@ -42,10 +42,10 @@
   }
 
   for (const auto& timeline : timelines) {
-    if (timeline.isScrollTimeline()) {
+    if (timeline.IsScrollTimeline()) {
       DoubleOrScrollTimelineAutoKeyword time_range;
-      timeline.getAsScrollTimeline()->timeRange(time_range);
-      if (time_range.isScrollTimelineAutoKeyword()) {
+      timeline.GetAsScrollTimeline()->timeRange(time_range);
+      if (time_range.IsScrollTimelineAutoKeyword()) {
         error_string = "ScrollTimeline timeRange must have non-auto value";
         return false;
       }
diff --git a/third_party/WebKit/Source/modules/credentialmanager/CredentialsContainer.cpp b/third_party/WebKit/Source/modules/credentialmanager/CredentialsContainer.cpp
index d1f4d233..03d8147 100644
--- a/third_party/WebKit/Source/modules/credentialmanager/CredentialsContainer.cpp
+++ b/third_party/WebKit/Source/modules/credentialmanager/CredentialsContainer.cpp
@@ -371,12 +371,12 @@
   }
 
   if (options.hasPassword()) {
-    if (options.password().isPasswordCredentialData()) {
+    if (options.password().IsPasswordCredentialData()) {
       resolver->Resolve(PasswordCredential::Create(
-          options.password().getAsPasswordCredentialData(), exception_state));
+          options.password().GetAsPasswordCredentialData(), exception_state));
     } else {
       resolver->Resolve(PasswordCredential::Create(
-          options.password().getAsHTMLFormElement(), exception_state));
+          options.password().GetAsHTMLFormElement(), exception_state));
     }
   } else if (options.hasFederated()) {
     resolver->Resolve(
diff --git a/third_party/WebKit/Source/modules/credentialmanager/PasswordCredential.cpp b/third_party/WebKit/Source/modules/credentialmanager/PasswordCredential.cpp
index 2e483ea..f79cfa39 100644
--- a/third_party/WebKit/Source/modules/credentialmanager/PasswordCredential.cpp
+++ b/third_party/WebKit/Source/modules/credentialmanager/PasswordCredential.cpp
@@ -62,7 +62,7 @@
     // won't have a matching value in |formData|, and we can safely skip it.
     FileOrUSVString result;
     form_data->get(element->GetName(), result);
-    if (!result.isUSVString())
+    if (!result.IsUSVString())
       continue;
 
     Vector<String> autofill_tokens;
@@ -74,14 +74,14 @@
         .Split(' ', autofill_tokens);
     for (const auto& token : autofill_tokens) {
       if (token == "current-password" || token == "new-password") {
-        data.setPassword(result.getAsUSVString());
+        data.setPassword(result.GetAsUSVString());
         password_name = element->GetName();
       } else if (token == "photo") {
-        data.setIconURL(result.getAsUSVString());
+        data.setIconURL(result.GetAsUSVString());
       } else if (token == "name" || token == "nickname") {
-        data.setName(result.getAsUSVString());
+        data.setName(result.GetAsUSVString());
       } else if (token == "username") {
-        data.setId(result.getAsUSVString());
+        data.setId(result.GetAsUSVString());
         id_name = element->GetName();
       }
     }
@@ -103,14 +103,14 @@
 
   FormDataOrURLSearchParams additional_data;
   if (form->enctype() == "multipart/form-data") {
-    additional_data.setFormData(form_data);
+    additional_data.SetFormData(form_data);
   } else {
     URLSearchParams* params = URLSearchParams::Create(String());
     for (const FormData::Entry* entry : form_data->Entries()) {
       if (entry->IsString())
         params->append(entry->name().data(), entry->Value().data());
     }
-    additional_data.setURLSearchParams(params);
+    additional_data.SetURLSearchParams(params);
   }
 
   credential->setAdditionalData(additional_data);
@@ -148,11 +148,11 @@
 
 RefPtr<EncodedFormData> PasswordCredential::EncodeFormData(
     String& content_type) const {
-  if (additional_data_.isURLSearchParams()) {
+  if (additional_data_.IsURLSearchParams()) {
     // If |additionalData| is a 'URLSearchParams' object, build a urlencoded
     // response.
     URLSearchParams* params = URLSearchParams::Create(String());
-    URLSearchParams* additional_data = additional_data_.getAsURLSearchParams();
+    URLSearchParams* additional_data = additional_data_.GetAsURLSearchParams();
     for (const auto& param : additional_data->Params()) {
       const String& name = param.first;
       if (name != idName() && name != passwordName())
@@ -169,8 +169,8 @@
 
   // Otherwise, we'll build a multipart response.
   FormData* form_data = FormData::Create(nullptr);
-  if (additional_data_.isFormData()) {
-    FormData* additional_data = additional_data_.getAsFormData();
+  if (additional_data_.IsFormData()) {
+    FormData* additional_data = additional_data_.GetAsFormData();
     for (const FormData::Entry* entry : additional_data->Entries()) {
       const String& name = form_data->Decode(entry->name());
       if (name == idName() || name == passwordName())
diff --git a/third_party/WebKit/Source/modules/credentialmanager/PasswordCredentialTest.cpp b/third_party/WebKit/Source/modules/credentialmanager/PasswordCredentialTest.cpp
index ce9947ce..cdd95f0 100644
--- a/third_party/WebKit/Source/modules/credentialmanager/PasswordCredentialTest.cpp
+++ b/third_party/WebKit/Source/modules/credentialmanager/PasswordCredentialTest.cpp
@@ -75,12 +75,12 @@
 
   FormDataOrURLSearchParams additional_data;
   credential->additionalData(additional_data);
-  ASSERT_TRUE(additional_data.isFormData());
-  EXPECT_TRUE(additional_data.getAsFormData()->has("theId"));
-  EXPECT_TRUE(additional_data.getAsFormData()->has("thePassword"));
-  EXPECT_TRUE(additional_data.getAsFormData()->has("theIcon"));
-  EXPECT_TRUE(additional_data.getAsFormData()->has("theName"));
-  EXPECT_TRUE(additional_data.getAsFormData()->has("theExtraField"));
+  ASSERT_TRUE(additional_data.GetAsFormData());
+  EXPECT_TRUE(additional_data.GetAsFormData()->has("theId"));
+  EXPECT_TRUE(additional_data.GetAsFormData()->has("thePassword"));
+  EXPECT_TRUE(additional_data.GetAsFormData()->has("theIcon"));
+  EXPECT_TRUE(additional_data.GetAsFormData()->has("theName"));
+  EXPECT_TRUE(additional_data.GetAsFormData()->has("theExtraField"));
 }
 
 TEST_F(PasswordCredentialTest, CreateFromURLEncodedForm) {
@@ -110,12 +110,12 @@
 
   FormDataOrURLSearchParams additional_data;
   credential->additionalData(additional_data);
-  ASSERT_TRUE(additional_data.isURLSearchParams());
-  EXPECT_TRUE(additional_data.getAsURLSearchParams()->has("theId"));
-  EXPECT_TRUE(additional_data.getAsURLSearchParams()->has("thePassword"));
-  EXPECT_TRUE(additional_data.getAsURLSearchParams()->has("theIcon"));
-  EXPECT_TRUE(additional_data.getAsURLSearchParams()->has("theName"));
-  EXPECT_TRUE(additional_data.getAsURLSearchParams()->has("theExtraField"));
+  ASSERT_TRUE(additional_data.IsURLSearchParams());
+  EXPECT_TRUE(additional_data.GetAsURLSearchParams()->has("theId"));
+  EXPECT_TRUE(additional_data.GetAsURLSearchParams()->has("thePassword"));
+  EXPECT_TRUE(additional_data.GetAsURLSearchParams()->has("theIcon"));
+  EXPECT_TRUE(additional_data.GetAsURLSearchParams()->has("theName"));
+  EXPECT_TRUE(additional_data.GetAsURLSearchParams()->has("theExtraField"));
 }
 
 TEST_F(PasswordCredentialTest, CreateFromFormNoPassword) {
diff --git a/third_party/WebKit/Source/modules/credentialmanager/WebAuthenticationClient.cpp b/third_party/WebKit/Source/modules/credentialmanager/WebAuthenticationClient.cpp
index 47beadd..d06bc8f 100644
--- a/third_party/WebKit/Source/modules/credentialmanager/WebAuthenticationClient.cpp
+++ b/third_party/WebKit/Source/modules/credentialmanager/WebAuthenticationClient.cpp
@@ -84,16 +84,16 @@
 
 // TODO(kpaulhamus): Make this a TypeConverter
 Vector<uint8_t> ConvertBufferSource(const blink::BufferSource& buffer) {
-  DCHECK(!buffer.isNull());
+  DCHECK(!buffer.IsNull());
   Vector<uint8_t> vector;
-  if (buffer.isArrayBuffer()) {
-    vector.Append(static_cast<uint8_t*>(buffer.getAsArrayBuffer()->Data()),
-                  buffer.getAsArrayBuffer()->ByteLength());
+  if (buffer.IsArrayBuffer()) {
+    vector.Append(static_cast<uint8_t*>(buffer.GetAsArrayBuffer()->Data()),
+                  buffer.GetAsArrayBuffer()->ByteLength());
   } else {
-    DCHECK(buffer.isArrayBufferView());
+    DCHECK(buffer.IsArrayBufferView());
     vector.Append(static_cast<uint8_t*>(
-                      buffer.getAsArrayBufferView().View()->BaseAddress()),
-                  buffer.getAsArrayBufferView().View()->byteLength());
+                      buffer.GetAsArrayBufferView().View()->BaseAddress()),
+                  buffer.GetAsArrayBufferView().View()->byteLength());
   }
   return vector;
 }
diff --git a/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.h b/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.h
index 8af6fe4..05ef1bb 100644
--- a/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.h
+++ b/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.h
@@ -71,7 +71,7 @@
   // ScriptPromise.
   ScriptPromise Promise();
 
-  WebCryptoResult Result() { return WebCryptoResult(this, cancel_.Get()); }
+  WebCryptoResult Result() { return WebCryptoResult(this, cancel_.get()); }
 
   DECLARE_VIRTUAL_TRACE();
 
diff --git a/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.cpp b/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.cpp
index b38d244..385f8dd 100644
--- a/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.cpp
+++ b/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.cpp
@@ -481,7 +481,7 @@
   Dictionary dictionary;
   if (DictionaryHelper::Get(raw, property_name, dictionary) &&
       !dictionary.IsUndefinedOrNull()) {
-    value.setDictionary(dictionary);
+    value.SetDictionary(dictionary);
     return true;
   }
 
@@ -493,7 +493,7 @@
     return false;
   }
 
-  value.setString(algorithm_name);
+  value.SetString(algorithm_name);
   return true;
 }
 
@@ -1063,12 +1063,12 @@
 
   // If the AlgorithmIdentifier is a String, treat it the same as a Dictionary
   // with a "name" attribute and nothing else.
-  if (raw.isString()) {
-    return ParseAlgorithmDictionary(raw.getAsString(), Dictionary(), op,
+  if (raw.IsString()) {
+    return ParseAlgorithmDictionary(raw.GetAsString(), Dictionary(), op,
                                     algorithm, context, error);
   }
 
-  Dictionary params = raw.getAsDictionary();
+  Dictionary params = raw.GetAsDictionary();
 
   // Get the name of the algorithm from the AlgorithmIdentifier.
   if (!params.IsObject()) {
diff --git a/third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp b/third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp
index ef5cdc2..534f53c 100644
--- a/third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp
+++ b/third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp
@@ -413,10 +413,10 @@
     case kWebCryptoKeyFormatRaw:
     case kWebCryptoKeyFormatPkcs8:
     case kWebCryptoKeyFormatSpki:
-      if (raw_key_data.isArrayBuffer()) {
-        key_data = CopyBytes(raw_key_data.getAsArrayBuffer());
-      } else if (raw_key_data.isArrayBufferView()) {
-        key_data = CopyBytes(raw_key_data.getAsArrayBufferView().View());
+      if (raw_key_data.IsArrayBuffer()) {
+        key_data = CopyBytes(raw_key_data.GetAsArrayBuffer());
+      } else if (raw_key_data.IsArrayBufferView()) {
+        key_data = CopyBytes(raw_key_data.GetAsArrayBufferView().View());
       } else {
         result->CompleteWithError(
             kWebCryptoErrorTypeType,
@@ -432,11 +432,11 @@
     //  (2) Let keyData be the keyData parameter passed to the importKey
     //      method.
     case kWebCryptoKeyFormatJwk:
-      if (raw_key_data.isDictionary()) {
+      if (raw_key_data.IsDictionary()) {
         // TODO(eroman): To match the spec error order, parsing of the
         // JsonWebKey should be done earlier (at the WebIDL layer of
         // parameter checking), regardless of the format being "jwk".
-        if (!ParseJsonWebKey(raw_key_data.getAsDictionary(), key_data, result))
+        if (!ParseJsonWebKey(raw_key_data.GetAsDictionary(), key_data, result))
           return promise;
       } else {
         result->CompleteWithError(kWebCryptoErrorTypeType,
diff --git a/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.cpp b/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.cpp
index 2a9e812..e5eb780 100644
--- a/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.cpp
+++ b/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.cpp
@@ -23,12 +23,13 @@
 
 namespace {
 
-IntSize GetSpecifiedSize(const IntSize& size, float zoom) {
+IntSize GetSpecifiedSize(const LayoutSize* size, float zoom) {
   float un_zoom_factor = 1 / zoom;
-  auto un_zoom_fn = [un_zoom_factor](int a) -> int {
+  auto un_zoom_fn = [un_zoom_factor](float a) -> int {
     return round(a * un_zoom_factor);
   };
-  return IntSize(un_zoom_fn(size.Width()), un_zoom_fn(size.Height()));
+  return IntSize(un_zoom_fn(size->Width().ToFloat()),
+                 un_zoom_fn(size->Height().ToFloat()));
 }
 
 }  // namespace
@@ -69,17 +70,19 @@
 
 RefPtr<Image> CSSPaintDefinition::Paint(
     const ImageResourceObserver& client,
-    const IntSize& size,
-    const CSSStyleValueVector* paint_arguments) {
+    const IntSize& container_size,
+    const CSSStyleValueVector* paint_arguments,
+    const LayoutSize* logical_size) {
   DCHECK(paint_arguments);
+  DCHECK(logical_size);
 
   // TODO: Break dependency on LayoutObject. Passing the Node should work.
   const LayoutObject& layout_object = static_cast<const LayoutObject&>(client);
 
   float zoom = layout_object.StyleRef().EffectiveZoom();
-  const IntSize specified_size = GetSpecifiedSize(size, zoom);
+  const IntSize specified_size = GetSpecifiedSize(logical_size, zoom);
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
 
   MaybeCreatePaintInstance();
 
@@ -95,7 +98,7 @@
 
   PaintRenderingContext2D* rendering_context = PaintRenderingContext2D::Create(
       ImageBuffer::Create(WTF::WrapUnique(new RecordingImageBufferSurface(
-          size, RecordingImageBufferSurface::kDisallowFallback,
+          container_size, RecordingImageBufferSurface::kDisallowFallback,
           context_settings_.alpha() ? kNonOpaque : kOpaque))),
       context_settings_, zoom);
   PaintSize* paint_size = PaintSize::Create(specified_size);
@@ -117,7 +120,7 @@
   block.SetVerbose(true);
 
   V8ScriptRunner::CallFunction(paint,
-                               ExecutionContext::From(script_state_.Get()),
+                               ExecutionContext::From(script_state_.get()),
                                instance, WTF_ARRAY_LENGTH(argv), argv, isolate);
 
   // The paint function may have produced an error, in which case produce an
diff --git a/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.h b/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.h
index 36d30f8..991102f 100644
--- a/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.h
+++ b/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.h
@@ -13,6 +13,7 @@
 #include "platform/bindings/TraceWrapperMember.h"
 #include "platform/bindings/TraceWrapperV8Reference.h"
 #include "platform/geometry/IntSize.h"
+#include "platform/geometry/LayoutSize.h"
 #include "platform/heap/Handle.h"
 #include "v8/include/v8.h"
 
@@ -45,9 +46,13 @@
   //
   // This may return a nullptr (representing an invalid image) if javascript
   // throws an error.
+  //
+  // The |container_size| is the container size with subpixel snapping, where
+  // the |logical_size| is without it. Both sizes include zoom.
   RefPtr<Image> Paint(const ImageResourceObserver&,
-                      const IntSize&,
-                      const CSSStyleValueVector*);
+                      const IntSize& container_size,
+                      const CSSStyleValueVector*,
+                      const LayoutSize* logical_size);
   const Vector<CSSPropertyID>& NativeInvalidationProperties() const {
     return native_invalidation_properties_;
   }
@@ -62,7 +67,7 @@
     return context_settings_;
   }
 
-  ScriptState* GetScriptState() const { return script_state_.Get(); }
+  ScriptState* GetScriptState() const { return script_state_.get(); }
 
   v8::Local<v8::Function> PaintFunctionForTesting(v8::Isolate* isolate) {
     return paint_.NewLocal(isolate);
diff --git a/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.cpp b/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.cpp
index 13cf81e..c4a002d 100644
--- a/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.cpp
+++ b/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.cpp
@@ -51,9 +51,11 @@
 
 RefPtr<Image> CSSPaintImageGeneratorImpl::Paint(
     const ImageResourceObserver& observer,
-    const IntSize& size,
-    const CSSStyleValueVector* data) {
-  return paint_worklet_->Paint(name_, observer, size, data);
+    const IntSize& container_size,
+    const CSSStyleValueVector* data,
+    const LayoutSize* logical_size) {
+  return paint_worklet_->Paint(name_, observer, container_size, data,
+                               logical_size);
 }
 
 bool CSSPaintImageGeneratorImpl::HasDocumentDefinition() const {
diff --git a/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.h b/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.h
index 84a47a16..fdef2c0 100644
--- a/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.h
+++ b/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.h
@@ -26,9 +26,12 @@
                                         Observer*);
   ~CSSPaintImageGeneratorImpl() override;
 
+  // The |container_size| is the container size with subpixel snapping, where
+  // the |logical_size| is without it. Both sizes include zoom.
   RefPtr<Image> Paint(const ImageResourceObserver&,
-                      const IntSize&,
-                      const CSSStyleValueVector*) final;
+                      const IntSize& container_size,
+                      const CSSStyleValueVector*,
+                      const LayoutSize* logical_size) final;
   const Vector<CSSPropertyID>& NativeInvalidationProperties() const final;
   const Vector<AtomicString>& CustomInvalidationProperties() const final;
   bool HasAlpha() const final;
diff --git a/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2DTest.cpp b/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2DTest.cpp
index 3a8c183..c9d929d 100644
--- a/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2DTest.cpp
+++ b/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2DTest.cpp
@@ -32,12 +32,12 @@
                            const String& expected,
                            const String& value) {
   StringOrCanvasGradientOrCanvasPattern result, arg, dummy;
-  dummy.setString("red");
-  arg.setString(value);
+  dummy.SetString("red");
+  arg.SetString(value);
   ctx->setStrokeStyle(dummy);
   ctx->setStrokeStyle(arg);
   ctx->strokeStyle(result);
-  EXPECT_EQ(expected, result.getAsString());
+  EXPECT_EQ(expected, result.GetAsString());
 }
 
 TEST_F(PaintRenderingContext2DTest, testParseColorOrCurrentColor) {
diff --git a/third_party/WebKit/Source/modules/csspaint/PaintWorklet.cpp b/third_party/WebKit/Source/modules/csspaint/PaintWorklet.cpp
index 5c7ae30ca..a31a24ca 100644
--- a/third_party/WebKit/Source/modules/csspaint/PaintWorklet.cpp
+++ b/third_party/WebKit/Source/modules/csspaint/PaintWorklet.cpp
@@ -58,8 +58,9 @@
 
 RefPtr<Image> PaintWorklet::Paint(const String& name,
                                   const ImageResourceObserver& observer,
-                                  const IntSize& size,
-                                  const CSSStyleValueVector* data) {
+                                  const IntSize& container_size,
+                                  const CSSStyleValueVector* data,
+                                  const LayoutSize* logical_size) {
   if (!document_definition_map_.Contains(name))
     return nullptr;
 
@@ -72,7 +73,7 @@
   PaintWorkletGlobalScopeProxy* proxy =
       PaintWorkletGlobalScopeProxy::From(FindAvailableGlobalScope());
   CSSPaintDefinition* paint_definition = proxy->FindDefinition(name);
-  return paint_definition->Paint(observer, size, data);
+  return paint_definition->Paint(observer, container_size, data, logical_size);
 }
 
 const char* PaintWorklet::SupplementName() {
diff --git a/third_party/WebKit/Source/modules/csspaint/PaintWorklet.h b/third_party/WebKit/Source/modules/csspaint/PaintWorklet.h
index 1d1a18a1..5ab86229 100644
--- a/third_party/WebKit/Source/modules/csspaint/PaintWorklet.h
+++ b/third_party/WebKit/Source/modules/csspaint/PaintWorklet.h
@@ -33,10 +33,13 @@
   ~PaintWorklet() override;
 
   void AddPendingGenerator(const String& name, CSSPaintImageGeneratorImpl*);
+  // The |container_size| is the container size with subpixel snapping, where
+  // the |logical_size| is without it. Both size include zoom.
   RefPtr<Image> Paint(const String& name,
                       const ImageResourceObserver&,
-                      const IntSize&,
-                      const CSSStyleValueVector*);
+                      const IntSize& container_size,
+                      const CSSStyleValueVector*,
+                      const LayoutSize* logical_size);
 
   typedef HeapHashMap<String, TraceWrapperMember<DocumentPaintDefinition>>
       DocumentDefinitionMap;
diff --git a/third_party/WebKit/Source/modules/encoding/TextDecoder.cpp b/third_party/WebKit/Source/modules/encoding/TextDecoder.cpp
index 91d1e45..3d8306a 100644
--- a/third_party/WebKit/Source/modules/encoding/TextDecoder.cpp
+++ b/third_party/WebKit/Source/modules/encoding/TextDecoder.cpp
@@ -79,17 +79,17 @@
 String TextDecoder::decode(const BufferSource& input,
                            const TextDecodeOptions& options,
                            ExceptionState& exception_state) {
-  DCHECK(!input.isNull());
-  if (input.isArrayBufferView()) {
+  DCHECK(!input.IsNull());
+  if (input.IsArrayBufferView()) {
     const char* start = static_cast<const char*>(
-        input.getAsArrayBufferView().View()->BaseAddress());
-    size_t length = input.getAsArrayBufferView().View()->byteLength();
+        input.GetAsArrayBufferView().View()->BaseAddress());
+    size_t length = input.GetAsArrayBufferView().View()->byteLength();
     return decode(start, length, options, exception_state);
   }
-  DCHECK(input.isArrayBuffer());
+  DCHECK(input.IsArrayBuffer());
   const char* start =
-      static_cast<const char*>(input.getAsArrayBuffer()->Data());
-  size_t length = input.getAsArrayBuffer()->ByteLength();
+      static_cast<const char*>(input.GetAsArrayBuffer()->Data());
+  size_t length = input.GetAsArrayBuffer()->ByteLength();
   return decode(start, length, options, exception_state);
 }
 
diff --git a/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyStatusMap.cpp b/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyStatusMap.cpp
index 1c5bf37..54be226 100644
--- a/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyStatusMap.cpp
+++ b/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyStatusMap.cpp
@@ -85,7 +85,7 @@
       return false;
 
     const auto& entry = map_->at(current_++);
-    key.setArrayBuffer(entry.KeyId());
+    key.SetArrayBuffer(entry.KeyId());
     value = entry.Status();
     return true;
   }
diff --git a/third_party/WebKit/Source/modules/exported/WebCryptoNormalize.cpp b/third_party/WebKit/Source/modules/exported/WebCryptoNormalize.cpp
index 37ebeb7..1f685385 100644
--- a/third_party/WebKit/Source/modules/exported/WebCryptoNormalize.cpp
+++ b/third_party/WebKit/Source/modules/exported/WebCryptoNormalize.cpp
@@ -55,7 +55,7 @@
   WebCryptoAlgorithm algorithm;
   AlgorithmError error;
   AlgorithmIdentifier algorithm_identifier;
-  algorithm_identifier.setDictionary(algorithm_dictionary);
+  algorithm_identifier.SetDictionary(algorithm_dictionary);
   if (!NormalizeAlgorithm(algorithm_identifier, operation, algorithm, &error)) {
     *exception_code = WebCryptoErrorToExceptionCode(error.error_type);
     *error_details = error.error_details;
diff --git a/third_party/WebKit/Source/modules/exported/WebStorageEventDispatcherImpl.cpp b/third_party/WebKit/Source/modules/exported/WebStorageEventDispatcherImpl.cpp
index a7ed35f1..75b87318 100644
--- a/third_party/WebKit/Source/modules/exported/WebStorageEventDispatcherImpl.cpp
+++ b/third_party/WebKit/Source/modules/exported/WebStorageEventDispatcherImpl.cpp
@@ -47,7 +47,7 @@
     WebStorageArea* source_area_instance) {
   RefPtr<SecurityOrigin> security_origin = SecurityOrigin::Create(origin);
   StorageArea::DispatchLocalStorageEvent(key, old_value, new_value,
-                                         security_origin.Get(), page_url,
+                                         security_origin.get(), page_url,
                                          source_area_instance);
 }
 
@@ -61,7 +61,7 @@
     WebStorageArea* source_area_instance) {
   RefPtr<SecurityOrigin> security_origin = SecurityOrigin::Create(origin);
   StorageArea::DispatchSessionStorageEvent(
-      key, old_value, new_value, security_origin.Get(), page_url,
+      key, old_value, new_value, security_origin.get(), page_url,
       session_namespace, source_area_instance);
 }
 
diff --git a/third_party/WebKit/Source/modules/fetch/BlobBytesConsumer.h b/third_party/WebKit/Source/modules/fetch/BlobBytesConsumer.h
index 78ae6a8..9076e59 100644
--- a/third_party/WebKit/Source/modules/fetch/BlobBytesConsumer.h
+++ b/third_party/WebKit/Source/modules/fetch/BlobBytesConsumer.h
@@ -73,7 +73,7 @@
                     ThreadableLoader*);
   ThreadableLoader* CreateLoader();
   void DidFailInternal();
-  bool IsClean() const { return blob_data_handle_.Get(); }
+  bool IsClean() const { return blob_data_handle_.get(); }
   void Close();
   void GetError();
   void Clear();
diff --git a/third_party/WebKit/Source/modules/fetch/BodyStreamBuffer.cpp b/third_party/WebKit/Source/modules/fetch/BodyStreamBuffer.cpp
index 3d5a134..fa40645e 100644
--- a/third_party/WebKit/Source/modules/fetch/BodyStreamBuffer.cpp
+++ b/third_party/WebKit/Source/modules/fetch/BodyStreamBuffer.cpp
@@ -125,13 +125,13 @@
 }
 
 ScriptValue BodyStreamBuffer::Stream() {
-  ScriptState::Scope scope(script_state_.Get());
-  v8::Local<v8::Value> body_value = ToV8(this, script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
+  v8::Local<v8::Value> body_value = ToV8(this, script_state_.get());
   DCHECK(!body_value.IsEmpty());
   DCHECK(body_value->IsObject());
   v8::Local<v8::Object> body = body_value.As<v8::Object>();
   return ScriptValue(
-      script_state_.Get(),
+      script_state_.get(),
       V8PrivateProperty::GetInternalBodyStream(script_state_->GetIsolate())
           .GetOrEmpty(body));
 }
@@ -178,7 +178,7 @@
   DCHECK(script_state_->ContextIsValid());
   loader_ = loader;
   loader->Start(ReleaseHandle(),
-                new LoaderClient(ExecutionContext::From(script_state_.Get()),
+                new LoaderClient(ExecutionContext::From(script_state_.get()),
                                  this, client));
 }
 
@@ -191,22 +191,22 @@
 
   if (made_from_readable_stream_) {
     ScriptValue stream1, stream2;
-    ReadableStreamOperations::Tee(script_state_.Get(), Stream(), &stream1,
+    ReadableStreamOperations::Tee(script_state_.get(), Stream(), &stream1,
                                   &stream2);
-    *branch1 = new BodyStreamBuffer(script_state_.Get(), stream1);
-    *branch2 = new BodyStreamBuffer(script_state_.Get(), stream2);
+    *branch1 = new BodyStreamBuffer(script_state_.get(), stream1);
+    *branch2 = new BodyStreamBuffer(script_state_.get(), stream2);
     return;
   }
   BytesConsumer* dest1 = nullptr;
   BytesConsumer* dest2 = nullptr;
-  BytesConsumer::Tee(ExecutionContext::From(script_state_.Get()),
+  BytesConsumer::Tee(ExecutionContext::From(script_state_.get()),
                      ReleaseHandle(), &dest1, &dest2);
-  *branch1 = new BodyStreamBuffer(script_state_.Get(), dest1);
-  *branch2 = new BodyStreamBuffer(script_state_.Get(), dest2);
+  *branch1 = new BodyStreamBuffer(script_state_.get(), dest1);
+  *branch2 = new BodyStreamBuffer(script_state_.get(), dest2);
 }
 
 ScriptPromise BodyStreamBuffer::pull(ScriptState* script_state) {
-  DCHECK_EQ(script_state, script_state_.Get());
+  DCHECK_EQ(script_state, script_state_.get());
   if (stream_needs_more_)
     return ScriptPromise::CastUndefined(script_state);
   stream_needs_more_ = true;
@@ -217,7 +217,7 @@
 
 ScriptPromise BodyStreamBuffer::Cancel(ScriptState* script_state,
                                        ScriptValue reason) {
-  DCHECK_EQ(script_state, script_state_.Get());
+  DCHECK_EQ(script_state, script_state_.get());
   Close();
   return ScriptPromise::CastUndefined(script_state);
 }
@@ -252,28 +252,28 @@
 }
 
 bool BodyStreamBuffer::IsStreamReadable() {
-  ScriptState::Scope scope(script_state_.Get());
-  return ReadableStreamOperations::IsReadable(script_state_.Get(), Stream());
+  ScriptState::Scope scope(script_state_.get());
+  return ReadableStreamOperations::IsReadable(script_state_.get(), Stream());
 }
 
 bool BodyStreamBuffer::IsStreamClosed() {
-  ScriptState::Scope scope(script_state_.Get());
-  return ReadableStreamOperations::IsClosed(script_state_.Get(), Stream());
+  ScriptState::Scope scope(script_state_.get());
+  return ReadableStreamOperations::IsClosed(script_state_.get(), Stream());
 }
 
 bool BodyStreamBuffer::IsStreamErrored() {
-  ScriptState::Scope scope(script_state_.Get());
-  return ReadableStreamOperations::IsErrored(script_state_.Get(), Stream());
+  ScriptState::Scope scope(script_state_.get());
+  return ReadableStreamOperations::IsErrored(script_state_.get(), Stream());
 }
 
 bool BodyStreamBuffer::IsStreamLocked() {
-  ScriptState::Scope scope(script_state_.Get());
-  return ReadableStreamOperations::IsLocked(script_state_.Get(), Stream());
+  ScriptState::Scope scope(script_state_.get());
+  return ReadableStreamOperations::IsLocked(script_state_.get(), Stream());
 }
 
 bool BodyStreamBuffer::IsStreamDisturbed() {
-  ScriptState::Scope scope(script_state_.Get());
-  return ReadableStreamOperations::IsDisturbed(script_state_.Get(), Stream());
+  ScriptState::Scope scope(script_state_.get());
+  return ReadableStreamOperations::IsDisturbed(script_state_.get(), Stream());
 }
 
 void BodyStreamBuffer::CloseAndLockAndDisturb() {
@@ -283,11 +283,11 @@
     Close();
   }
 
-  ScriptState::Scope scope(script_state_.Get());
+  ScriptState::Scope scope(script_state_.get());
   NonThrowableExceptionState exception_state;
   ScriptValue reader = ReadableStreamOperations::GetReader(
-      script_state_.Get(), Stream(), exception_state);
-  ReadableStreamOperations::DefaultReaderRead(script_state_.Get(), reader);
+      script_state_.get(), Stream(), exception_state);
+  ReadableStreamOperations::DefaultReaderRead(script_state_.get(), reader);
 }
 
 void BodyStreamBuffer::Close() {
@@ -297,7 +297,7 @@
 
 void BodyStreamBuffer::GetError() {
   {
-    ScriptState::Scope scope(script_state_.Get());
+    ScriptState::Scope scope(script_state_.get());
     Controller()->GetError(V8ThrowException::CreateTypeError(
         script_state_->GetIsolate(), "network error"));
   }
@@ -373,7 +373,7 @@
   DCHECK(!IsStreamDisturbed());
 
   if (made_from_readable_stream_) {
-    ScriptState::Scope scope(script_state_.Get());
+    ScriptState::Scope scope(script_state_.get());
     // We need to have |reader| alive by some means (as written in
     // ReadableStreamDataConsumerHandle). Based on the following facts
     //  - This function is used only from tee and startLoading.
@@ -382,8 +382,8 @@
     // , we don't need to keep the reader explicitly.
     NonThrowableExceptionState exception_state;
     ScriptValue reader = ReadableStreamOperations::GetReader(
-        script_state_.Get(), Stream(), exception_state);
-    return new ReadableStreamBytesConsumer(script_state_.Get(), reader);
+        script_state_.get(), Stream(), exception_state);
+    return new ReadableStreamBytesConsumer(script_state_.get(), reader);
   }
   // We need to call these before calling closeAndLockAndDisturb.
   const bool is_closed = IsStreamClosed();
diff --git a/third_party/WebKit/Source/modules/fetch/BodyStreamBuffer.h b/third_party/WebKit/Source/modules/fetch/BodyStreamBuffer.h
index 1e51e0e1..7b47c6db 100644
--- a/third_party/WebKit/Source/modules/fetch/BodyStreamBuffer.h
+++ b/third_party/WebKit/Source/modules/fetch/BodyStreamBuffer.h
@@ -57,7 +57,7 @@
   bool IsStreamLocked();
   bool IsStreamDisturbed();
   void CloseAndLockAndDisturb();
-  ScriptState* GetScriptState() { return script_state_.Get(); }
+  ScriptState* GetScriptState() { return script_state_.get(); }
 
   DEFINE_INLINE_TRACE() {
     visitor->Trace(consumer_);
diff --git a/third_party/WebKit/Source/modules/fetch/DataConsumerHandleTestUtil.h b/third_party/WebKit/Source/modules/fetch/DataConsumerHandleTestUtil.h
index 991ada6..261e2d3 100644
--- a/third_party/WebKit/Source/modules/fetch/DataConsumerHandleTestUtil.h
+++ b/third_party/WebKit/Source/modules/fetch/DataConsumerHandleTestUtil.h
@@ -62,7 +62,7 @@
 
     WebThreadSupportingGC* GetThread() { return thread_.get(); }
     ExecutionContext* GetExecutionContext() { return execution_context_.Get(); }
-    ScriptState* GetScriptState() { return script_state_.Get(); }
+    ScriptState* GetScriptState() { return script_state_.get(); }
     v8::Isolate* GetIsolate() { return isolate_holder_->isolate(); }
 
    private:
@@ -396,7 +396,7 @@
       std::unique_ptr<WaitableEvent> detached_;
     };
 
-    Context* GetContext() { return context_.Get(); }
+    Context* GetContext() { return context_.get(); }
     std::unique_ptr<Reader> ObtainReader(Client*) override;
 
    private:
diff --git a/third_party/WebKit/Source/modules/fetch/FetchManager.cpp b/third_party/WebKit/Source/modules/fetch/FetchManager.cpp
index 598eb0b..37619ed4 100644
--- a/third_party/WebKit/Source/modules/fetch/FetchManager.cpp
+++ b/third_party/WebKit/Source/modules/fetch/FetchManager.cpp
@@ -387,7 +387,7 @@
       }
     }
   } else if (!SecurityOrigin::Create(response.Url())
-                  ->IsSameSchemeHostPort(request_->Origin().Get())) {
+                  ->IsSameSchemeHostPort(request_->Origin().get())) {
     // Recompute the tainting if the request was redirected to a different
     // origin.
     switch (request_->Mode()) {
@@ -595,7 +595,7 @@
   // Note we don't support to call this method with |CORS flag|
   // "- |request|'s mode is |navigate|".
   if ((SecurityOrigin::Create(request_->Url())
-           ->IsSameSchemeHostPortAndSuborigin(request_->Origin().Get())) ||
+           ->IsSameSchemeHostPortAndSuborigin(request_->Origin().get())) ||
       (request_->Url().ProtocolIsData() && request_->SameOriginDataURLFlag()) ||
       (request_->Url().ProtocolIsAbout()) ||
       (request_->Mode() == WebURLRequest::kFetchRequestModeNavigate)) {
@@ -764,7 +764,7 @@
 
   ResourceLoaderOptions resource_loader_options;
   resource_loader_options.data_buffering_policy = kDoNotBufferData;
-  resource_loader_options.security_origin = request_->Origin().Get();
+  resource_loader_options.security_origin = request_->Origin().get();
 
   ThreadableLoaderOptions threadable_loader_options;
 
@@ -793,7 +793,7 @@
 
   ResourceLoaderOptions resource_loader_options;
   resource_loader_options.data_buffering_policy = kDoNotBufferData;
-  resource_loader_options.security_origin = request_->Origin().Get();
+  resource_loader_options.security_origin = request_->Origin().get();
 
   ThreadableLoaderOptions threadable_loader_options;
 
diff --git a/third_party/WebKit/Source/modules/fetch/FormDataBytesConsumer.cpp b/third_party/WebKit/Source/modules/fetch/FormDataBytesConsumer.cpp
index 3b0c684..ad6ac7cc 100644
--- a/third_party/WebKit/Source/modules/fetch/FormDataBytesConsumer.cpp
+++ b/third_party/WebKit/Source/modules/fetch/FormDataBytesConsumer.cpp
@@ -232,7 +232,7 @@
     ExecutionContext* execution_context,
     RefPtr<EncodedFormData> form_data,
     BytesConsumer* consumer)
-    : impl_(IsSimple(form_data.Get())
+    : impl_(IsSimple(form_data.get())
                 ? static_cast<BytesConsumer*>(
                       new SimpleFormDataBytesConsumer(std::move(form_data)))
                 : static_cast<BytesConsumer*>(
diff --git a/third_party/WebKit/Source/modules/fetch/Headers.cpp b/third_party/WebKit/Source/modules/fetch/Headers.cpp
index dd0a47c..733178f6 100644
--- a/third_party/WebKit/Source/modules/fetch/Headers.cpp
+++ b/third_party/WebKit/Source/modules/fetch/Headers.cpp
@@ -227,10 +227,10 @@
 void Headers::FillWith(const HeadersInit& init,
                        ExceptionState& exception_state) {
   DCHECK_EQ(header_list_->size(), 0U);
-  if (init.isByteStringSequenceSequence()) {
-    FillWith(init.getAsByteStringSequenceSequence(), exception_state);
-  } else if (init.isByteStringByteStringRecord()) {
-    FillWith(init.getAsByteStringByteStringRecord(), exception_state);
+  if (init.IsByteStringSequenceSequence()) {
+    FillWith(init.GetAsByteStringSequenceSequence(), exception_state);
+  } else if (init.IsByteStringByteStringRecord()) {
+    FillWith(init.GetAsByteStringByteStringRecord(), exception_state);
   } else {
     NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/modules/fetch/ReadableStreamBytesConsumer.cpp b/third_party/WebKit/Source/modules/fetch/ReadableStreamBytesConsumer.cpp
index 0c67aa3..4a81116f2 100644
--- a/third_party/WebKit/Source/modules/fetch/ReadableStreamBytesConsumer.cpp
+++ b/third_party/WebKit/Source/modules/fetch/ReadableStreamBytesConsumer.cpp
@@ -115,14 +115,14 @@
   }
   if (!is_reading_) {
     is_reading_ = true;
-    ScriptState::Scope scope(script_state_.Get());
-    ScriptValue reader(script_state_.Get(),
+    ScriptState::Scope scope(script_state_.get());
+    ScriptValue reader(script_state_.get(),
                        reader_.NewLocal(script_state_->GetIsolate()));
     // The owner must retain the reader.
     DCHECK(!reader.IsEmpty());
-    ReadableStreamOperations::DefaultReaderRead(script_state_.Get(), reader)
-        .Then(OnFulfilled::CreateFunction(script_state_.Get(), this),
-              OnRejected::CreateFunction(script_state_.Get(), this));
+    ReadableStreamOperations::DefaultReaderRead(script_state_.get(), reader)
+        .Then(OnFulfilled::CreateFunction(script_state_.get(), this),
+              OnRejected::CreateFunction(script_state_.get(), this));
   }
   return Result::kShouldWait;
 }
diff --git a/third_party/WebKit/Source/modules/fetch/Request.cpp b/third_party/WebKit/Source/modules/fetch/Request.cpp
index 562b1fa7..061db2b 100644
--- a/third_party/WebKit/Source/modules/fetch/Request.cpp
+++ b/third_party/WebKit/Source/modules/fetch/Request.cpp
@@ -194,7 +194,7 @@
         // substeps."
         request->SetReferrerString(FetchRequestData::ClientReferrerString());
       } else if (!origin->IsSameSchemeHostPortAndSuborigin(
-                     SecurityOrigin::Create(parsed_referrer).Get())) {
+                     SecurityOrigin::Create(parsed_referrer).get())) {
         // "If |parsedReferrer|'s origin is not same origin with
         // |origin|, throw a TypeError."
         exception_state.ThrowTypeError(
@@ -244,7 +244,7 @@
   } else if (init.credentials == "include") {
     request->SetCredentials(WebURLRequest::kFetchCredentialsModeInclude);
   } else if (init.credentials == "password") {
-    if (!init.attached_credential.Get()) {
+    if (!init.attached_credential.get()) {
       exception_state.ThrowTypeError(
           "Cannot construct a Request with a credential mode of 'password' "
           "without a PasswordCredential.");
@@ -318,7 +318,7 @@
   // We don't create a copy of r's Headers object when init's headers member
   // is present.
   Headers* headers = nullptr;
-  if (init.headers.isNull()) {
+  if (init.headers.IsNull()) {
     headers = r->getHeaders()->Clone();
   }
   // "Empty |r|'s request's header list."
@@ -336,7 +336,7 @@
     r->getHeaders()->SetGuard(Headers::kRequestNoCORSGuard);
   }
   // "Fill |r|'s Headers object with |headers|. Rethrow any exceptions."
-  if (!init.headers.isNull()) {
+  if (!init.headers.IsNull()) {
     r->getHeaders()->FillWith(init.headers, exception_state);
   } else {
     DCHECK(headers);
@@ -428,10 +428,10 @@
                          const RequestInfo& input,
                          const Dictionary& init,
                          ExceptionState& exception_state) {
-  DCHECK(!input.isNull());
-  if (input.isUSVString())
-    return Create(script_state, input.getAsUSVString(), init, exception_state);
-  return Create(script_state, input.getAsRequest(), init, exception_state);
+  DCHECK(!input.IsNull());
+  if (input.IsUSVString())
+    return Create(script_state, input.GetAsUSVString(), init, exception_state);
+  return Create(script_state, input.GetAsRequest(), init, exception_state);
 }
 
 Request* Request::Create(ScriptState* script_state,
diff --git a/third_party/WebKit/Source/modules/fetch/Request.idl b/third_party/WebKit/Source/modules/fetch/Request.idl
index edbef0b..ab7a576a7 100644
--- a/third_party/WebKit/Source/modules/fetch/Request.idl
+++ b/third_party/WebKit/Source/modules/fetch/Request.idl
@@ -33,7 +33,7 @@
 ] interface Request {
     readonly attribute ByteString method;
     readonly attribute USVString url;
-    [ImplementedAs=getHeaders] readonly attribute Headers headers;
+    [ImplementedAs=getHeaders, SameObject] readonly attribute Headers headers;
     readonly attribute DOMString referrer;
     [ImplementedAs=getReferrerPolicy] readonly attribute ReferrerPolicy referrerPolicy;
     readonly attribute RequestMode mode;
diff --git a/third_party/WebKit/Source/modules/fetch/RequestInit.cpp b/third_party/WebKit/Source/modules/fetch/RequestInit.cpp
index 36e962a..ae70f8c 100644
--- a/third_party/WebKit/Source/modules/fetch/RequestInit.cpp
+++ b/third_party/WebKit/Source/modules/fetch/RequestInit.cpp
@@ -138,7 +138,7 @@
     }
   }
 
-  if (attached_credential.Get() || !is_body_set || v8_body->IsUndefined() ||
+  if (attached_credential.get() || !is_body_set || v8_body->IsUndefined() ||
       v8_body->IsNull())
     return;
 
diff --git a/third_party/WebKit/Source/modules/fetch/Response.idl b/third_party/WebKit/Source/modules/fetch/Response.idl
index c882597..6ed61183 100644
--- a/third_party/WebKit/Source/modules/fetch/Response.idl
+++ b/third_party/WebKit/Source/modules/fetch/Response.idl
@@ -24,7 +24,7 @@
     readonly attribute unsigned short status;
     readonly attribute boolean ok;
     readonly attribute ByteString statusText;
-    readonly attribute Headers headers;
+    [SameObject] readonly attribute Headers headers;
 
     [RaisesException, CallWith=ScriptState, DoNotTestNewObject, NewObject] Response clone();
 
diff --git a/third_party/WebKit/Source/modules/imagebitmap/ImageBitmapRenderingContext.cpp b/third_party/WebKit/Source/modules/imagebitmap/ImageBitmapRenderingContext.cpp
index fcba977..c2f0570e 100644
--- a/third_party/WebKit/Source/modules/imagebitmap/ImageBitmapRenderingContext.cpp
+++ b/third_party/WebKit/Source/modules/imagebitmap/ImageBitmapRenderingContext.cpp
@@ -25,7 +25,7 @@
 
 void ImageBitmapRenderingContext::SetCanvasGetContextResult(
     RenderingContext& result) {
-  result.setImageBitmapRenderingContext(this);
+  result.SetImageBitmapRenderingContext(this);
 }
 
 void ImageBitmapRenderingContext::transferFromImageBitmap(
diff --git a/third_party/WebKit/Source/modules/imagecapture/ImageCapture.cpp b/third_party/WebKit/Source/modules/imagecapture/ImageCapture.cpp
index ca6bfc0..ec218ae 100644
--- a/third_party/WebKit/Source/modules/imagecapture/ImageCapture.cpp
+++ b/third_party/WebKit/Source/modules/imagecapture/ImageCapture.cpp
@@ -359,10 +359,10 @@
   // TODO(mcasas): support other Mode types beyond simple string i.e. the
   // equivalents of "sequence<DOMString>"" or "ConstrainDOMStringParameters".
   settings->has_white_balance_mode = constraints.hasWhiteBalanceMode() &&
-                                     constraints.whiteBalanceMode().isString();
+                                     constraints.whiteBalanceMode().IsString();
   if (settings->has_white_balance_mode) {
     const auto white_balance_mode =
-        constraints.whiteBalanceMode().getAsString();
+        constraints.whiteBalanceMode().GetAsString();
     if (capabilities_.whiteBalanceMode().Find(white_balance_mode) ==
         kNotFound) {
       resolver->Reject(DOMException::Create(kNotSupportedError,
@@ -373,9 +373,9 @@
     settings->white_balance_mode = ParseMeteringMode(white_balance_mode);
   }
   settings->has_exposure_mode =
-      constraints.hasExposureMode() && constraints.exposureMode().isString();
+      constraints.hasExposureMode() && constraints.exposureMode().IsString();
   if (settings->has_exposure_mode) {
-    const auto exposure_mode = constraints.exposureMode().getAsString();
+    const auto exposure_mode = constraints.exposureMode().GetAsString();
     if (capabilities_.exposureMode().Find(exposure_mode) == kNotFound) {
       resolver->Reject(DOMException::Create(kNotSupportedError,
                                             "Unsupported exposureMode."));
@@ -386,9 +386,9 @@
   }
 
   settings->has_focus_mode =
-      constraints.hasFocusMode() && constraints.focusMode().isString();
+      constraints.hasFocusMode() && constraints.focusMode().IsString();
   if (settings->has_focus_mode) {
-    const auto focus_mode = constraints.focusMode().getAsString();
+    const auto focus_mode = constraints.focusMode().GetAsString();
     if (capabilities_.focusMode().Find(focus_mode) == kNotFound) {
       resolver->Reject(
           DOMException::Create(kNotSupportedError, "Unsupported focusMode."));
@@ -400,9 +400,9 @@
 
   // TODO(mcasas): support ConstrainPoint2DParameters.
   if (constraints.hasPointsOfInterest() &&
-      constraints.pointsOfInterest().isPoint2DSequence()) {
+      constraints.pointsOfInterest().IsPoint2DSequence()) {
     for (const auto& point :
-         constraints.pointsOfInterest().getAsPoint2DSequence()) {
+         constraints.pointsOfInterest().GetAsPoint2DSequence()) {
       auto mojo_point = media::mojom::blink::Point2D::New();
       mojo_point->x = point.x();
       mojo_point->y = point.y();
@@ -414,10 +414,10 @@
   // TODO(mcasas): support ConstrainDoubleRange where applicable.
   settings->has_exposure_compensation =
       constraints.hasExposureCompensation() &&
-      constraints.exposureCompensation().isDouble();
+      constraints.exposureCompensation().IsDouble();
   if (settings->has_exposure_compensation) {
     const auto exposure_compensation =
-        constraints.exposureCompensation().getAsDouble();
+        constraints.exposureCompensation().GetAsDouble();
     if (exposure_compensation < capabilities_.exposureCompensation()->min() ||
         exposure_compensation > capabilities_.exposureCompensation()->max()) {
       resolver->Reject(DOMException::Create(
@@ -429,9 +429,9 @@
     settings->exposure_compensation = exposure_compensation;
   }
   settings->has_color_temperature = constraints.hasColorTemperature() &&
-                                    constraints.colorTemperature().isDouble();
+                                    constraints.colorTemperature().IsDouble();
   if (settings->has_color_temperature) {
-    const auto color_temperature = constraints.colorTemperature().getAsDouble();
+    const auto color_temperature = constraints.colorTemperature().GetAsDouble();
     if (color_temperature < capabilities_.colorTemperature()->min() ||
         color_temperature > capabilities_.colorTemperature()->max()) {
       resolver->Reject(DOMException::Create(
@@ -441,9 +441,9 @@
     temp_constraints.setColorTemperature(constraints.colorTemperature());
     settings->color_temperature = color_temperature;
   }
-  settings->has_iso = constraints.hasIso() && constraints.iso().isDouble();
+  settings->has_iso = constraints.hasIso() && constraints.iso().IsDouble();
   if (settings->has_iso) {
-    const auto iso = constraints.iso().getAsDouble();
+    const auto iso = constraints.iso().GetAsDouble();
     if (iso < capabilities_.iso()->min() || iso > capabilities_.iso()->max()) {
       resolver->Reject(
           DOMException::Create(kNotSupportedError, "iso setting out of range"));
@@ -454,9 +454,9 @@
   }
 
   settings->has_brightness =
-      constraints.hasBrightness() && constraints.brightness().isDouble();
+      constraints.hasBrightness() && constraints.brightness().IsDouble();
   if (settings->has_brightness) {
-    const auto brightness = constraints.brightness().getAsDouble();
+    const auto brightness = constraints.brightness().GetAsDouble();
     if (brightness < capabilities_.brightness()->min() ||
         brightness > capabilities_.brightness()->max()) {
       resolver->Reject(DOMException::Create(kNotSupportedError,
@@ -467,9 +467,9 @@
     settings->brightness = brightness;
   }
   settings->has_contrast =
-      constraints.hasContrast() && constraints.contrast().isDouble();
+      constraints.hasContrast() && constraints.contrast().IsDouble();
   if (settings->has_contrast) {
-    const auto contrast = constraints.contrast().getAsDouble();
+    const auto contrast = constraints.contrast().GetAsDouble();
     if (contrast < capabilities_.contrast()->min() ||
         contrast > capabilities_.contrast()->max()) {
       resolver->Reject(DOMException::Create(kNotSupportedError,
@@ -480,9 +480,9 @@
     settings->contrast = contrast;
   }
   settings->has_saturation =
-      constraints.hasSaturation() && constraints.saturation().isDouble();
+      constraints.hasSaturation() && constraints.saturation().IsDouble();
   if (settings->has_saturation) {
-    const auto saturation = constraints.saturation().getAsDouble();
+    const auto saturation = constraints.saturation().GetAsDouble();
     if (saturation < capabilities_.saturation()->min() ||
         saturation > capabilities_.saturation()->max()) {
       resolver->Reject(DOMException::Create(kNotSupportedError,
@@ -493,9 +493,9 @@
     settings->saturation = saturation;
   }
   settings->has_sharpness =
-      constraints.hasSharpness() && constraints.sharpness().isDouble();
+      constraints.hasSharpness() && constraints.sharpness().IsDouble();
   if (settings->has_sharpness) {
-    const auto sharpness = constraints.sharpness().getAsDouble();
+    const auto sharpness = constraints.sharpness().GetAsDouble();
     if (sharpness < capabilities_.sharpness()->min() ||
         sharpness > capabilities_.sharpness()->max()) {
       resolver->Reject(DOMException::Create(kNotSupportedError,
@@ -506,9 +506,9 @@
     settings->sharpness = sharpness;
   }
 
-  settings->has_zoom = constraints.hasZoom() && constraints.zoom().isDouble();
+  settings->has_zoom = constraints.hasZoom() && constraints.zoom().IsDouble();
   if (settings->has_zoom) {
-    const auto zoom = constraints.zoom().getAsDouble();
+    const auto zoom = constraints.zoom().GetAsDouble();
     if (zoom < capabilities_.zoom()->min() ||
         zoom > capabilities_.zoom()->max()) {
       resolver->Reject(DOMException::Create(kNotSupportedError,
@@ -521,9 +521,9 @@
 
   // TODO(mcasas): support ConstrainBooleanParameters where applicable.
   settings->has_torch =
-      constraints.hasTorch() && constraints.torch().isBoolean();
+      constraints.hasTorch() && constraints.torch().IsBoolean();
   if (settings->has_torch) {
-    const auto torch = constraints.torch().getAsBoolean();
+    const auto torch = constraints.torch().GetAsBoolean();
     if (torch && !capabilities_.torch()) {
       resolver->Reject(
           DOMException::Create(kNotSupportedError, "torch not supported"));
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBAny.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBAny.cpp
index 26be2129..f7e1f3f 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBAny.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBAny.cpp
@@ -93,7 +93,7 @@
 
 IDBValue* IDBAny::Value() const {
   DCHECK_EQ(type_, kIDBValueType);
-  return idb_value_.Get();
+  return idb_value_.get();
 }
 
 const Vector<RefPtr<IDBValue>>* IDBAny::Values() const {
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBCursor.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBCursor.cpp
index b331a3f..b29994b 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBCursor.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBCursor.cpp
@@ -388,10 +388,10 @@
     value = IDBAny::CreateUndefined();
   } else if (object_store->autoIncrement() &&
              !object_store->IdbKeyPath().IsNull()) {
-    RefPtr<IDBValue> idb_value = IDBValue::Create(value_.Get(), primary_key_,
+    RefPtr<IDBValue> idb_value = IDBValue::Create(value_.get(), primary_key_,
                                                   object_store->IdbKeyPath());
 #if DCHECK_IS_ON()
-    AssertPrimaryKeyValidOrInjectable(script_state, idb_value.Get());
+    AssertPrimaryKeyValidOrInjectable(script_state, idb_value.get());
 #endif  // DCHECK_IS_ON()
     value = IDBAny::Create(std::move(idb_value));
   } else {
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.cpp
index 64db9c12..21739d1 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.cpp
@@ -366,10 +366,10 @@
   RecordApiCallsHistogram(kIDBTransactionCall);
 
   HashSet<String> scope;
-  if (store_names.isString()) {
-    scope.insert(store_names.getAsString());
-  } else if (store_names.isStringSequence()) {
-    for (const String& name : store_names.getAsStringSequence())
+  if (store_names.IsString()) {
+    scope.insert(store_names.GetAsString());
+  } else if (store_names.IsStringSequence()) {
+    for (const String& name : store_names.GetAsStringSequence())
       scope.insert(name);
   } else {
     NOTREACHED();
@@ -566,7 +566,7 @@
   DCHECK(!version_change_transaction_->IsActive())
       << "Object store metadata reverted when versionchange transaction is "
          "still active";
-  DCHECK(old_metadata.Get());
+  DCHECK(old_metadata.get());
   metadata_.object_stores.Set(old_metadata->id, std::move(old_metadata));
 }
 
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBIndex.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBIndex.cpp
index e77e938..419c76b 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBIndex.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBIndex.cpp
@@ -53,7 +53,7 @@
       transaction_(transaction) {
   DCHECK(object_store_);
   DCHECK(transaction_);
-  DCHECK(metadata_.Get());
+  DCHECK(metadata_.get());
   DCHECK_NE(Id(), IDBIndexMetadata::kInvalidId);
 }
 
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBKeyPath.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBKeyPath.cpp
index a40ad4b..4461c81 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBKeyPath.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBKeyPath.cpp
@@ -114,16 +114,16 @@
 }
 
 IDBKeyPath::IDBKeyPath(const StringOrStringSequence& key_path) {
-  if (key_path.isNull()) {
+  if (key_path.IsNull()) {
     type_ = kNullType;
-  } else if (key_path.isString()) {
+  } else if (key_path.IsString()) {
     type_ = kStringType;
-    string_ = key_path.getAsString();
+    string_ = key_path.GetAsString();
     DCHECK(!string_.IsNull());
   } else {
-    DCHECK(key_path.isStringSequence());
+    DCHECK(key_path.IsStringSequence());
     type_ = kArrayType;
-    array_ = key_path.getAsStringSequence();
+    array_ = key_path.GetAsStringSequence();
 #if DCHECK_IS_ON()
     for (size_t i = 0; i < array_.size(); ++i)
       DCHECK(!array_[i].IsNull());
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBMetadata.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBMetadata.cpp
index 0cbb8e6..368a9fb 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBMetadata.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBMetadata.cpp
@@ -45,7 +45,7 @@
                                                auto_increment, max_index_id));
 
   for (const auto& it : indexes) {
-    IDBIndexMetadata* index = it.value.Get();
+    IDBIndexMetadata* index = it.value.get();
     RefPtr<IDBIndexMetadata> index_copy = WTF::AdoptRef(
         new IDBIndexMetadata(index->name, index->id, index->key_path,
                              index->unique, index->multi_entry));
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.cpp
index 5b1c36c..23d5234f 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.cpp
@@ -70,7 +70,7 @@
                                IDBTransaction* transaction)
     : metadata_(std::move(metadata)), transaction_(transaction) {
   DCHECK(transaction_);
-  DCHECK(metadata_.Get());
+  DCHECK(metadata_.get());
 }
 
 DEFINE_TRACE(IDBObjectStore) {
@@ -658,7 +658,7 @@
         transaction_id_(transaction_id),
         object_store_id_(object_store_id),
         index_metadata_(std::move(index_metadata)) {
-    DCHECK(index_metadata_.Get());
+    DCHECK(index_metadata_.get());
   }
 
   const IDBIndexMetadata& IndexMetadata() const { return *index_metadata_; }
@@ -668,7 +668,7 @@
       return;
     IDB_TRACE("IDBObjectStore::IndexPopulator::handleEvent");
 
-    DCHECK_EQ(ExecutionContext::From(script_state_.Get()), execution_context);
+    DCHECK_EQ(ExecutionContext::From(script_state_.get()), execution_context);
     DCHECK_EQ(event->type(), EventTypeNames::success);
     EventTarget* target = event->target();
     IDBRequest* request = static_cast<IDBRequest*>(target);
@@ -676,7 +676,7 @@
     if (!database_->Backend())  // If database is stopped?
       return;
 
-    ScriptState::Scope scope(script_state_.Get());
+    ScriptState::Scope scope(script_state_.get());
 
     IDBAny* cursor_any = request->ResultAsAny();
     IDBCursorWithValue* cursor = nullptr;
@@ -690,7 +690,7 @@
                        ASSERT_NO_EXCEPTION);
 
       IDBKey* primary_key = cursor->IdbPrimaryKey();
-      ScriptValue value = cursor->value(script_state_.Get());
+      ScriptValue value = cursor->value(script_state_.get());
 
       IndexKeys index_keys;
       GenerateIndexKeysForValue(script_state_->GetIsolate(), IndexMetadata(),
@@ -823,7 +823,7 @@
 
   DCHECK(Metadata().indexes.Contains(index_id));
   RefPtr<IDBIndexMetadata> index_metadata = Metadata().indexes.at(index_id);
-  DCHECK(index_metadata.Get());
+  DCHECK(index_metadata.get());
   IDBIndex* index =
       IDBIndex::Create(std::move(index_metadata), this, transaction_.Get());
   index_map_.Set(name, index);
@@ -1034,7 +1034,7 @@
     RefPtr<IDBObjectStoreMetadata> old_metadata) {
   DCHECK(transaction_->IsVersionChange());
   DCHECK(!transaction_->IsActive());
-  DCHECK(old_metadata.Get());
+  DCHECK(old_metadata.get());
   DCHECK(Id() == old_metadata->id);
 
   for (auto& index : index_map_.Values()) {
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBRequest.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBRequest.cpp
index dc6c0ca4..4dd21753 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBRequest.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBRequest.cpp
@@ -259,7 +259,7 @@
   cursor_key_ = key;
   cursor_primary_key_ = primary_key;
   cursor_value_ = std::move(value);
-  AckReceivedBlobs(cursor_value_.Get());
+  AckReceivedBlobs(cursor_value_.get());
 
   EnqueueResultInternal(IDBAny::Create(cursor));
 }
@@ -274,7 +274,7 @@
 
 void IDBRequest::AckReceivedBlobs(const Vector<RefPtr<IDBValue>>& values) {
   for (size_t i = 0; i < values.size(); ++i)
-    AckReceivedBlobs(values[i].Get());
+    AckReceivedBlobs(values[i].get());
 }
 
 bool IDBRequest::ShouldEnqueueEvent() const {
@@ -347,7 +347,7 @@
                                 RefPtr<IDBValue>&& value) {
   DCHECK(transit_blob_handles_.IsEmpty());
   DCHECK(transaction_);
-  bool is_wrapped = IDBValueUnwrapper::IsWrapped(value.Get());
+  bool is_wrapped = IDBValueUnwrapper::IsWrapped(value.get());
   if (!transaction_->HasQueuedResults() && !is_wrapped) {
     return EnqueueResponse(std::move(backend), key, primary_key,
                            std::move(value));
@@ -361,7 +361,7 @@
 void IDBRequest::HandleResponse(RefPtr<IDBValue>&& value) {
   DCHECK(transit_blob_handles_.IsEmpty());
   DCHECK(transaction_);
-  bool is_wrapped = IDBValueUnwrapper::IsWrapped(value.Get());
+  bool is_wrapped = IDBValueUnwrapper::IsWrapped(value.get());
   if (!transaction_->HasQueuedResults() && !is_wrapped)
     return EnqueueResponse(std::move(value));
   transaction_->EnqueueResult(WTF::MakeUnique<IDBRequestQueueItem>(
@@ -387,7 +387,7 @@
                                 RefPtr<IDBValue>&& value) {
   DCHECK(transit_blob_handles_.IsEmpty());
   DCHECK(transaction_);
-  bool is_wrapped = IDBValueUnwrapper::IsWrapped(value.Get());
+  bool is_wrapped = IDBValueUnwrapper::IsWrapped(value.get());
   if (!transaction_->HasQueuedResults() && !is_wrapped)
     return EnqueueResponse(key, primary_key, std::move(value));
 
@@ -511,7 +511,7 @@
     return;
   }
 
-  AckReceivedBlobs(value.Get());
+  AckReceivedBlobs(value.get());
 
   if (pending_cursor_) {
     // Value should be null, signifying the end of the cursor's range.
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBRequestLoader.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBRequestLoader.cpp
index 6756714..a92470c 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBRequestLoader.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBRequestLoader.cpp
@@ -59,7 +59,7 @@
       ReportSuccess();
       return;
     }
-    if (unwrapper.Parse(current_value_->Get()))
+    if (unwrapper.Parse(current_value_->get()))
       break;
     ++current_value_;
   }
@@ -102,7 +102,7 @@
 #endif  // DCHECK_IS_ON()
 
   *current_value_ = IDBValueUnwrapper::Unwrap(
-      current_value_->Get(), SharedBuffer::AdoptVector(wrapped_data_));
+      current_value_->get(), SharedBuffer::AdoptVector(wrapped_data_));
   ++current_value_;
 
   StartNextValue();
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBTestHelper.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBTestHelper.cpp
index 2e79ccf4..e865ced 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBTestHelper.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBTestHelper.cpp
@@ -41,7 +41,7 @@
       WTF::MakeUnique<Vector<WebBlobInfo>>(blob_infos), key, key_path);
 
   DCHECK_EQ(create_wrapped_value,
-            IDBValueUnwrapper::IsWrapped(idb_value.Get()));
+            IDBValueUnwrapper::IsWrapped(idb_value.get()));
   return idb_value;
 }
 
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.cpp
index ed3cd5a..a90a4c1 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.cpp
@@ -223,7 +223,7 @@
   DCHECK(database_->Metadata().object_stores.Contains(object_store_id));
   RefPtr<IDBObjectStoreMetadata> object_store_metadata =
       database_->Metadata().object_stores.at(object_store_id);
-  DCHECK(object_store_metadata.Get());
+  DCHECK(object_store_metadata.get());
 
   IDBObjectStore* object_store =
       IDBObjectStore::Create(std::move(object_store_metadata), this);
@@ -269,7 +269,7 @@
     DCHECK(database_->Metadata().object_stores.Contains(object_store_id));
     RefPtr<IDBObjectStoreMetadata> metadata =
         database_->Metadata().object_stores.at(object_store_id);
-    DCHECK(metadata.Get());
+    DCHECK(metadata.get());
     DCHECK_EQ(metadata->name, name);
     deleted_object_stores_.push_back(std::move(metadata));
   } else {
@@ -329,7 +329,7 @@
   }
 
   const IDBObjectStoreMetadata* old_store_metadata =
-      object_store_iterator->value.Get();
+      object_store_iterator->value.get();
   DCHECK(old_store_metadata);
   if (!old_store_metadata->indexes.Contains(index->Id())) {
     // The index's object store was created before this transaction, but the
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBValue.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBValue.cpp
index 84a3534..563e9df 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBValue.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBValue.cpp
@@ -116,7 +116,7 @@
 }
 
 bool IDBValue::IsNull() const {
-  return !data_.Get();
+  return !data_.get();
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBValueWrapping.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBValueWrapping.cpp
index 27d7824..56eec09 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBValueWrapping.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBValueWrapping.cpp
@@ -85,7 +85,7 @@
                           << " called on wrapper with serialization exception";
   DCHECK(!wrap_called_) << "Clone() called after WrapIfBiggerThan()";
 #endif  // DCHECK_IS_ON()
-  *clone = DeserializeScriptValue(script_state, serialized_value_.Get(),
+  *clone = DeserializeScriptValue(script_state, serialized_value_.get(),
                                   &blob_info_);
 }
 
@@ -171,7 +171,7 @@
 
 bool IDBValueUnwrapper::IsWrapped(const Vector<RefPtr<IDBValue>>& values) {
   for (const auto& value : values) {
-    if (IsWrapped(value.Get()))
+    if (IsWrapped(value.get()))
       return true;
   }
   return false;
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBValueWrappingTest.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBValueWrappingTest.cpp
index 44753b9..ac376a37a 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBValueWrappingTest.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBValueWrappingTest.cpp
@@ -36,7 +36,7 @@
       wrapped_marker_buffer,
       WTF::MakeUnique<Vector<RefPtr<BlobDataHandle>>>(blob_data_handles),
       WTF::MakeUnique<Vector<WebBlobInfo>>(blob_infos), key, key_path);
-  EXPECT_TRUE(IDBValueUnwrapper::IsWrapped(wrapped_value.Get()));
+  EXPECT_TRUE(IDBValueUnwrapper::IsWrapped(wrapped_value.get()));
 
   Vector<char> wrapped_marker_bytes(wrapped_marker_buffer->size());
   ASSERT_TRUE(wrapped_marker_buffer->GetBytes(wrapped_marker_bytes.data(),
@@ -52,7 +52,7 @@
         WTF::MakeUnique<Vector<RefPtr<BlobDataHandle>>>(blob_data_handles),
         WTF::MakeUnique<Vector<WebBlobInfo>>(blob_infos), key, key_path);
 
-    EXPECT_FALSE(IDBValueUnwrapper::IsWrapped(mutant_value.Get()));
+    EXPECT_FALSE(IDBValueUnwrapper::IsWrapped(mutant_value.get()));
   }
 
   // IsWrapped() looks at the first 3 bytes in the value. Flipping any bit in
@@ -67,7 +67,7 @@
                                wrapped_marker_bytes.size()),
           WTF::MakeUnique<Vector<RefPtr<BlobDataHandle>>>(blob_data_handles),
           WTF::MakeUnique<Vector<WebBlobInfo>>(blob_infos), key, key_path);
-      EXPECT_FALSE(IDBValueUnwrapper::IsWrapped(mutant_value.Get()));
+      EXPECT_FALSE(IDBValueUnwrapper::IsWrapped(mutant_value.get()));
 
       wrapped_marker_bytes[i] ^= mask;
     }
diff --git a/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.cpp b/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.cpp
index 65c57e53..0e8edce 100644
--- a/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.cpp
@@ -219,9 +219,9 @@
   virtual void Execute(IDBDatabase*) = 0;
   virtual RequestCallback* GetRequestCallback() = 0;
   ExecutionContext* Context() const {
-    return ExecutionContext::From(script_state_.Get());
+    return ExecutionContext::From(script_state_.get());
   }
-  ScriptState* GetScriptState() const { return script_state_.Get(); }
+  ScriptState* GetScriptState() const { return script_state_.get(); }
 
  private:
   RefPtr<ScriptState> script_state_;
@@ -320,7 +320,7 @@
     const String& mode = IndexedDBNames::readonly) {
   DummyExceptionStateForTesting exception_state;
   StringOrStringSequence scope;
-  scope.setString(object_store_name);
+  scope.SetString(object_store_name);
   IDBTransaction* idb_transaction =
       idb_database->transaction(script_state, scope, mode, exception_state);
   if (exception_state.HadException())
@@ -575,10 +575,10 @@
     }
 
     Document* document =
-        ToDocument(ExecutionContext::From(script_state_.Get()));
+        ToDocument(ExecutionContext::From(script_state_.get()));
     if (!document)
       return;
-    ScriptState* script_state = script_state_.Get();
+    ScriptState* script_state = script_state_.get();
     ScriptState::Scope scope(script_state);
     v8::Local<v8::Context> context = script_state->GetContext();
     v8_inspector::StringView object_group =
diff --git a/third_party/WebKit/Source/modules/media_controls/BUILD.gn b/third_party/WebKit/Source/modules/media_controls/BUILD.gn
index e023686..5cece65 100644
--- a/third_party/WebKit/Source/modules/media_controls/BUILD.gn
+++ b/third_party/WebKit/Source/modules/media_controls/BUILD.gn
@@ -54,6 +54,8 @@
     "elements/MediaControlPlayButtonElement.h",
     "elements/MediaControlRemainingTimeDisplayElement.cpp",
     "elements/MediaControlRemainingTimeDisplayElement.h",
+    "elements/MediaControlSliderElement.cpp",
+    "elements/MediaControlSliderElement.h",
     "elements/MediaControlTextTrackListElement.cpp",
     "elements/MediaControlTextTrackListElement.h",
     "elements/MediaControlTimeDisplayElement.cpp",
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp
index 58b136d..ad5670e 100644
--- a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp
@@ -1116,6 +1116,10 @@
   ComputeWhichControlsFit();
 }
 
+void MediaControlsImpl::OnLoadingProgress() {
+  timeline_->RenderBarSegments();
+}
+
 void MediaControlsImpl::ComputeWhichControlsFit() {
   // Hide all controls that don't fit, and show the ones that do.
   // This might be better suited for a layout, but since JS media controls
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h
index c04cad6..2ac2e4f 100644
--- a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h
+++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h
@@ -249,6 +249,7 @@
   void OnPanelKeypress();
   void OnMediaKeyboardEvent(Event* event) { DefaultEventHandler(event); }
   void OnWaiting();
+  void OnLoadingProgress();
 
   // Media control elements.
   Member<MediaControlOverlayEnclosureElement> overlay_enclosure_;
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp b/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp
index 88a704bb..7613657c 100644
--- a/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp
@@ -713,36 +713,6 @@
   EXPECT_EQ(duration / 2, current_time_display->CurrentValue());
 }
 
-TEST_F(MediaControlsImplTest, VolumeSliderPaintInvalidationOnInput) {
-  EnsureSizing();
-
-  Element* volume_slider = VolumeSliderElement();
-
-  MockLayoutObject layout_object(volume_slider);
-  LayoutObject* prev_layout_object = volume_slider->GetLayoutObject();
-  volume_slider->SetLayoutObject(&layout_object);
-
-  layout_object.ClearPaintInvalidationFlags();
-  EXPECT_FALSE(layout_object.ShouldDoFullPaintInvalidation());
-  Event* event = Event::Create(EventTypeNames::input);
-  volume_slider->DefaultEventHandler(event);
-  EXPECT_TRUE(layout_object.ShouldDoFullPaintInvalidation());
-
-  layout_object.ClearPaintInvalidationFlags();
-  EXPECT_FALSE(layout_object.ShouldDoFullPaintInvalidation());
-  event = Event::Create(EventTypeNames::input);
-  volume_slider->DefaultEventHandler(event);
-  EXPECT_TRUE(layout_object.ShouldDoFullPaintInvalidation());
-
-  layout_object.ClearPaintInvalidationFlags();
-  EXPECT_FALSE(layout_object.ShouldDoFullPaintInvalidation());
-  event = Event::Create(EventTypeNames::input);
-  volume_slider->DefaultEventHandler(event);
-  EXPECT_TRUE(layout_object.ShouldDoFullPaintInvalidation());
-
-  volume_slider->SetLayoutObject(prev_layout_object);
-}
-
 TEST_F(MediaControlsImplTest, TimelineMetricsWidth) {
   MediaControls().MediaElement().SetSrc("https://example.com/foo.mp4");
   testing::RunPendingTasks();
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsMediaEventListener.cpp b/third_party/WebKit/Source/modules/media_controls/MediaControlsMediaEventListener.cpp
index 71aed33..258b691 100644
--- a/third_party/WebKit/Source/modules/media_controls/MediaControlsMediaEventListener.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsMediaEventListener.cpp
@@ -39,6 +39,7 @@
   GetMediaElement().addEventListener(EventTypeNames::keydown, this, false);
   GetMediaElement().addEventListener(EventTypeNames::keyup, this, false);
   GetMediaElement().addEventListener(EventTypeNames::waiting, this, false);
+  GetMediaElement().addEventListener(EventTypeNames::progress, this, false);
 
   // Listen to two different fullscreen events in order to make sure the new and
   // old APIs are handled.
@@ -167,6 +168,10 @@
     media_controls_->OnWaiting();
     return;
   }
+  if (event->type() == EventTypeNames::progress) {
+    media_controls_->OnLoadingProgress();
+    return;
+  }
 
   // Fullscreen handling.
   if (event->type() == EventTypeNames::fullscreenchange ||
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.cpp
index 59ab136..36567a5 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.cpp
@@ -68,6 +68,7 @@
     }
   }
   UpdateOverflowString();
+  SetClass("on", IsPlayingRemotely());
 }
 
 bool MediaControlCastButtonElement::WillRespondToMouseClickEvents() {
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlElementsHelper.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlElementsHelper.cpp
index a3202c0..d56a6329 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlElementsHelper.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlElementsHelper.cpp
@@ -57,7 +57,7 @@
     const Node* node) {
   SECURITY_DCHECK(node->IsMediaControlElement());
   const HTMLElement* element = ToHTMLElement(node);
-  if (isHTMLInputElement(*element))
+  if (IsHTMLInputElement(*element))
     return static_cast<const MediaControlInputElement*>(element)->DisplayType();
   return static_cast<const MediaControlDivElement*>(element)->DisplayType();
 }
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlFullscreenButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlFullscreenButtonElement.cpp
index 8cc17ed..9d2f95e 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlFullscreenButtonElement.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlFullscreenButtonElement.cpp
@@ -26,6 +26,7 @@
 void MediaControlFullscreenButtonElement::SetIsFullscreen(bool is_fullscreen) {
   SetDisplayType(is_fullscreen ? kMediaExitFullscreenButton
                                : kMediaEnterFullscreenButton);
+  SetClass("fullscreen", is_fullscreen);
 }
 
 bool MediaControlFullscreenButtonElement::WillRespondToMouseClickEvents() {
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlInputElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlInputElement.cpp
index e01431c..e78eaf7 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlInputElement.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlInputElement.cpp
@@ -4,6 +4,7 @@
 
 #include "modules/media_controls/elements/MediaControlInputElement.h"
 
+#include "core/dom/DOMTokenList.h"
 #include "core/dom/events/Event.h"
 #include "core/html/HTMLLabelElement.h"
 #include "core/html/HTMLMediaElement.h"
@@ -114,7 +115,7 @@
   if (is_overflow_element_) {
     Element* parent = parentElement();
     DCHECK(parent);
-    DCHECK(isHTMLLabelElement(parent));
+    DCHECK(IsHTMLLabelElement(parent));
 
     if (IsWanted() && DoesFit())
       parent->RemoveInlineStyleProperty(CSSPropertyDisplay);
@@ -178,6 +179,14 @@
   ctr_histogram.Count(static_cast<int>(event));
 }
 
+void MediaControlInputElement::SetClass(const AtomicString& class_name,
+                                        bool should_have_class) {
+  if (should_have_class)
+    classList().Add(class_name);
+  else
+    classList().Remove(class_name);
+}
+
 DEFINE_TRACE(MediaControlInputElement) {
   HTMLInputElement::Trace(visitor);
   MediaControlElementBase::Trace(visitor);
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlInputElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlInputElement.h
index 9dca441..528035a3 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlInputElement.h
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlInputElement.h
@@ -59,6 +59,9 @@
   // Returns whether this element is used for the overflow menu.
   bool IsOverflowElement() const;
 
+  // Sets/removes a CSS class from this element based on |should_have_class|.
+  void SetClass(const AtomicString& class_name, bool should_have_class);
+
  private:
   friend class MediaControlInputElementTest;
 
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlMuteButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlMuteButtonElement.cpp
index c12eaeb..d9890ec8 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlMuteButtonElement.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlMuteButtonElement.cpp
@@ -28,9 +28,9 @@
   // TODO(mlamouri): checking for volume == 0 because the mute button will look
   // 'muted' when the volume is 0 even if the element is not muted. This allows
   // the painting and the display type to actually match.
-  SetDisplayType((MediaElement().muted() || MediaElement().volume() == 0)
-                     ? kMediaUnMuteButton
-                     : kMediaMuteButton);
+  bool muted = MediaElement().muted() || MediaElement().volume() == 0;
+  SetDisplayType(muted ? kMediaUnMuteButton : kMediaMuteButton);
+  SetClass("muted", muted);
   UpdateOverflowString();
 }
 
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlPlayButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlPlayButtonElement.cpp
index 6bd48224..fa96c1b 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlPlayButtonElement.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlPlayButtonElement.cpp
@@ -28,6 +28,7 @@
 void MediaControlPlayButtonElement::UpdateDisplayType() {
   SetDisplayType(MediaElement().paused() ? kMediaPlayButton
                                          : kMediaPauseButton);
+  SetClass("pause", MediaElement().paused());
   UpdateOverflowString();
 }
 
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlSliderElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlSliderElement.cpp
new file mode 100644
index 0000000..a8042bd
--- /dev/null
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlSliderElement.cpp
@@ -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 "modules/media_controls/elements/MediaControlSliderElement.h"
+
+#include "core/InputTypeNames.h"
+#include "core/dom/ElementShadow.h"
+#include "core/html/HTMLDivElement.h"
+#include "core/layout/LayoutBoxModelObject.h"
+#include "core/resize_observer/ResizeObserver.h"
+#include "core/resize_observer/ResizeObserverEntry.h"
+#include "platform/wtf/text/StringBuilder.h"
+
+namespace {
+
+void SetSegmentDivPosition(blink::HTMLDivElement* segment,
+                           blink::MediaControlSliderElement::Position position,
+                           int width) {
+  int segment_width = int(position.width * width);
+  int segment_left = int(position.left * width);
+
+  StringBuilder builder;
+  builder.Append("width: ");
+  builder.AppendNumber(segment_width);
+  builder.Append("px; left: ");
+  builder.AppendNumber(segment_left);
+  builder.Append("px;");
+  segment->setAttribute("style", builder.ToAtomicString());
+}
+
+}  // namespace.
+
+namespace blink {
+
+class MediaControlSliderElement::MediaControlSliderElementResizeObserverDelegate
+    final : public ResizeObserver::Delegate {
+ public:
+  explicit MediaControlSliderElementResizeObserverDelegate(
+      MediaControlSliderElement* element)
+      : element_(element) {
+    DCHECK(element);
+  }
+  ~MediaControlSliderElementResizeObserverDelegate() override = default;
+
+  void OnResize(
+      const HeapVector<Member<ResizeObserverEntry>>& entries) override {
+    DCHECK_EQ(1u, entries.size());
+    DCHECK_EQ(entries[0]->target(), element_);
+    element_->NotifyElementSizeChanged();
+  }
+
+  DEFINE_INLINE_TRACE() {
+    visitor->Trace(element_);
+    ResizeObserver::Delegate::Trace(visitor);
+  }
+
+ private:
+  Member<MediaControlSliderElement> element_;
+};
+
+MediaControlSliderElement::MediaControlSliderElement(
+    MediaControlsImpl& media_controls,
+    MediaControlElementType display_type)
+    : MediaControlInputElement(media_controls, display_type),
+      before_segment_position_(0, 0),
+      after_segment_position_(0, 0),
+      segment_highlight_before_(nullptr),
+      segment_highlight_after_(nullptr),
+      resize_observer_(ResizeObserver::Create(
+          GetDocument(),
+          new MediaControlSliderElementResizeObserverDelegate(this))) {
+  EnsureUserAgentShadowRoot();
+  setType(InputTypeNames::range);
+  setAttribute(HTMLNames::stepAttr, "any");
+  resize_observer_->observe(this);
+}
+
+void MediaControlSliderElement::SetupBarSegments() {
+  DCHECK((segment_highlight_after_ && segment_highlight_before_) ||
+         (!segment_highlight_after_ && !segment_highlight_before_));
+
+  if (segment_highlight_after_ || segment_highlight_before_)
+    return;
+
+  // The timeline element has a shadow root with the following
+  // structure:
+  //
+  // #shadow-root
+  //   - div
+  //     - div::-webkit-slider-runnable-track#track
+  ShadowRoot& shadow_root = Shadow()->OldestShadowRoot();
+  Element* track = shadow_root.getElementById(AtomicString("track"));
+  DCHECK(track);
+  track->setAttribute("class", "-internal-media-controls-segmented-track");
+
+  // Add the following structure to #track.
+  //
+  // div.-internal-track-segment-background (container)
+  //   - div.-internal-track-segment-highlight-before (blue highlight)
+  //   - div.-internal-track-segment-highlight-after (dark gray highlight)
+  HTMLDivElement* background = HTMLDivElement::Create(GetDocument());
+  background->setAttribute("class", "-internal-track-segment-background");
+  track->appendChild(background);
+
+  segment_highlight_before_ = HTMLDivElement::Create(GetDocument());
+  segment_highlight_before_->setAttribute(
+      "class", "-internal-track-segment-highlight-before");
+  background->appendChild(segment_highlight_before_);
+
+  segment_highlight_after_ = HTMLDivElement::Create(GetDocument());
+  segment_highlight_after_->setAttribute(
+      "class", "-internal-track-segment-highlight-after");
+  background->appendChild(segment_highlight_after_);
+}
+
+void MediaControlSliderElement::SetBeforeSegmentPosition(
+    MediaControlSliderElement::Position position) {
+  DCHECK(segment_highlight_before_);
+  before_segment_position_ = position;
+  SetSegmentDivPosition(segment_highlight_before_, before_segment_position_,
+                        Width());
+}
+
+void MediaControlSliderElement::SetAfterSegmentPosition(
+    MediaControlSliderElement::Position position) {
+  DCHECK(segment_highlight_after_);
+  after_segment_position_ = position;
+  SetSegmentDivPosition(segment_highlight_after_, after_segment_position_,
+                        Width());
+}
+
+int MediaControlSliderElement::Width() {
+  if (LayoutBoxModelObject* box = GetLayoutBoxModelObject())
+    return box->OffsetWidth().Round();
+  return 0;
+}
+
+void MediaControlSliderElement::NotifyElementSizeChanged() {
+  SetSegmentDivPosition(segment_highlight_before_, before_segment_position_,
+                        Width());
+  SetSegmentDivPosition(segment_highlight_after_, after_segment_position_,
+                        Width());
+}
+
+DEFINE_TRACE(MediaControlSliderElement) {
+  visitor->Trace(segment_highlight_before_);
+  visitor->Trace(segment_highlight_after_);
+  visitor->Trace(resize_observer_);
+  MediaControlInputElement::Trace(visitor);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlSliderElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlSliderElement.h
new file mode 100644
index 0000000..0bfd841
--- /dev/null
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlSliderElement.h
@@ -0,0 +1,58 @@
+// 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 MediaControlSliderElement_h
+#define MediaControlSliderElement_h
+
+#include "modules/ModulesExport.h"
+#include "modules/media_controls/elements/MediaControlInputElement.h"
+
+namespace blink {
+
+class MediaControlsImpl;
+class ResizeObserver;
+
+// MediaControlInputElement with additional logic for sliders.
+class MODULES_EXPORT MediaControlSliderElement
+    : public MediaControlInputElement {
+  USING_GARBAGE_COLLECTED_MIXIN(MediaControlSliderElement);
+
+ public:
+  DECLARE_VIRTUAL_TRACE();
+
+  // Stores the position of the segment in proportion from 0.0 to 1.0.
+  struct Position {
+    Position(double left, double width) : left(left), width(width){};
+    double left;
+    double width;
+  };
+
+ protected:
+  class MediaControlSliderElementResizeObserverDelegate;
+
+  MediaControlSliderElement(MediaControlsImpl&, MediaControlElementType);
+
+  void SetupBarSegments();
+  void SetBeforeSegmentPosition(Position);
+  void SetAfterSegmentPosition(Position);
+
+  void NotifyElementSizeChanged();
+
+  // Width in CSS pixels * pageZoomFactor (ignores CSS transforms for
+  // simplicity; deliberately ignores pinch zoom's pageScaleFactor).
+  int Width();
+
+ private:
+  Position before_segment_position_;
+  Position after_segment_position_;
+
+  Member<HTMLDivElement> segment_highlight_before_;
+  Member<HTMLDivElement> segment_highlight_after_;
+
+  Member<ResizeObserver> resize_observer_;
+};
+
+}  // namespace blink
+
+#endif  // MediaControlSliderElement_h
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTimelineElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTimelineElement.cpp
index 5e88aef..afcb81fe 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTimelineElement.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTimelineElement.cpp
@@ -20,14 +20,17 @@
 #include "public/platform/Platform.h"
 #include "public/platform/WebScreenInfo.h"
 
+namespace {
+
+const double kCurrentTimeBufferedDelta = 1.0;
+
+}  // namespace.
+
 namespace blink {
 
 MediaControlTimelineElement::MediaControlTimelineElement(
     MediaControlsImpl& media_controls)
-    : MediaControlInputElement(media_controls, kMediaSlider) {
-  EnsureUserAgentShadowRoot();
-  setType(InputTypeNames::range);
-  setAttribute(HTMLNames::stepAttr, "any");
+    : MediaControlSliderElement(media_controls, kMediaSlider) {
   SetShadowPseudoId(AtomicString("-webkit-media-controls-timeline"));
 }
 
@@ -37,17 +40,13 @@
 
 void MediaControlTimelineElement::SetPosition(double current_time) {
   setValue(String::Number(current_time));
-
-  if (LayoutObject* layout_object = this->GetLayoutObject())
-    layout_object->SetShouldDoFullPaintInvalidation();
+  RenderBarSegments();
 }
 
 void MediaControlTimelineElement::SetDuration(double duration) {
   SetFloatingPointAttribute(HTMLNames::maxAttr,
                             std::isfinite(duration) ? duration : 0);
-
-  if (LayoutObject* layout_object = this->GetLayoutObject())
-    layout_object->SetShouldDoFullPaintInvalidation();
+  RenderBarSegments();
 }
 
 void MediaControlTimelineElement::OnPlaying() {
@@ -56,7 +55,7 @@
     return;
   metrics_.RecordPlaying(
       frame->GetChromeClient().GetScreenInfo().orientation_type,
-      MediaElement().IsFullscreen(), TimelineWidth());
+      MediaElement().IsFullscreen(), Width());
 }
 
 const char* MediaControlTimelineElement::GetNameForHistograms() const {
@@ -67,6 +66,8 @@
   if (!isConnected() || !GetDocument().IsActive())
     return;
 
+  RenderBarSegments();
+
   // Only respond to main button of primary pointer(s).
   if (event->IsPointerEvent() && ToPointerEvent(event)->isPrimary() &&
       ToPointerEvent(event)->button() ==
@@ -84,7 +85,7 @@
       Platform::Current()->RecordAction(
           UserMetricsAction("Media.Controls.ScrubbingEnd"));
       GetMediaControls().EndScrubbing();
-      metrics_.RecordEndGesture(TimelineWidth(), MediaElement().duration());
+      metrics_.RecordEndGesture(Width(), MediaElement().duration());
     }
   }
 
@@ -92,7 +93,7 @@
     metrics_.StartKey();
   }
   if (event->type() == EventTypeNames::keyup && event->IsKeyboardEvent()) {
-    metrics_.RecordEndKey(TimelineWidth(), ToKeyboardEvent(event)->keyCode());
+    metrics_.RecordEndKey(Width(), ToKeyboardEvent(event)->keyCode());
   }
 
   MediaControlInputElement::DefaultEventHandler(event);
@@ -131,10 +132,64 @@
       event, GetLayoutObject());
 }
 
-int MediaControlTimelineElement::TimelineWidth() {
-  if (LayoutBoxModelObject* box = GetLayoutBoxModelObject())
-    return box->OffsetWidth().Round();
-  return 0;
+void MediaControlTimelineElement::RenderBarSegments() {
+  SetupBarSegments();
+
+  double current_time = MediaElement().currentTime();
+  double duration = MediaElement().duration();
+
+  // Draw the buffered range. Since the element may have multiple buffered
+  // ranges and it'd be distracting/'busy' to show all of them, show only the
+  // buffered range containing the current play head.
+  TimeRanges* buffered_time_ranges = MediaElement().buffered();
+  DCHECK(buffered_time_ranges);
+  if (std::isnan(duration) || std::isinf(duration) || !duration ||
+      std::isnan(current_time)) {
+    SetBeforeSegmentPosition(MediaControlSliderElement::Position(0, 0));
+    SetAfterSegmentPosition(MediaControlSliderElement::Position(0, 0));
+    return;
+  }
+
+  // int current_position = int(current_time * Width() / duration);
+  double current_position = current_time / duration;
+  for (unsigned i = 0; i < buffered_time_ranges->length(); ++i) {
+    float start = buffered_time_ranges->start(i, ASSERT_NO_EXCEPTION);
+    float end = buffered_time_ranges->end(i, ASSERT_NO_EXCEPTION);
+    // The delta is there to avoid corner cases when buffered
+    // ranges is out of sync with current time because of
+    // asynchronous media pipeline and current time caching in
+    // HTMLMediaElement.
+    // This is related to https://www.w3.org/Bugs/Public/show_bug.cgi?id=28125
+    // FIXME: Remove this workaround when WebMediaPlayer
+    // has an asynchronous pause interface.
+    if (std::isnan(start) || std::isnan(end) ||
+        start > current_time + kCurrentTimeBufferedDelta ||
+        end < current_time) {
+      continue;
+    }
+
+    // int start_position = int(start * Width() / duration);
+    // int end_position = int(end * Width() / duration);
+    double start_position = start / duration;
+    double end_position = end / duration;
+
+    // Draw highlight to show what we have played.
+    if (current_position > start_position) {
+      SetAfterSegmentPosition(MediaControlSliderElement::Position(
+          start_position, current_position));
+    }
+
+    // Draw dark grey highlight to show what we have loaded.
+    if (end_position > current_position) {
+      SetBeforeSegmentPosition(MediaControlSliderElement::Position(
+          current_position, end_position - current_position));
+    }
+    return;
+  }
+
+  // Reset the widths to hide the segments.
+  SetBeforeSegmentPosition(MediaControlSliderElement::Position(0, 0));
+  SetAfterSegmentPosition(MediaControlSliderElement::Position(0, 0));
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTimelineElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTimelineElement.h
index 2ad8a7ac..3b703baa 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTimelineElement.h
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTimelineElement.h
@@ -5,7 +5,7 @@
 #ifndef MediaControlTimelineElement_h
 #define MediaControlTimelineElement_h
 
-#include "modules/media_controls/elements/MediaControlInputElement.h"
+#include "modules/media_controls/elements/MediaControlSliderElement.h"
 #include "modules/media_controls/elements/MediaControlTimelineMetrics.h"
 
 namespace blink {
@@ -13,7 +13,7 @@
 class Event;
 class MediaControlsImpl;
 
-class MediaControlTimelineElement final : public MediaControlInputElement {
+class MediaControlTimelineElement final : public MediaControlSliderElement {
  public:
   explicit MediaControlTimelineElement(MediaControlsImpl&);
 
@@ -29,6 +29,8 @@
 
   void OnMediaKeyboardEvent(Event* event) { DefaultEventHandler(event); }
 
+  void RenderBarSegments();
+
  protected:
   const char* GetNameForHistograms() const override;
 
@@ -36,10 +38,6 @@
   void DefaultEventHandler(Event*) override;
   bool KeepEventInNode(Event*) override;
 
-  // Width in CSS pixels * pageZoomFactor (ignores CSS transforms for
-  // simplicity; deliberately ignores pinch zoom's pageScaleFactor).
-  int TimelineWidth();
-
   MediaControlTimelineMetrics metrics_;
 };
 
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlToggleClosedCaptionsButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlToggleClosedCaptionsButtonElement.cpp
index 6d17362a..1a8b828 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlToggleClosedCaptionsButtonElement.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlToggleClosedCaptionsButtonElement.cpp
@@ -31,6 +31,7 @@
   bool captions_visible = MediaElement().TextTracksVisible();
   SetDisplayType(captions_visible ? kMediaHideClosedCaptionsButton
                                   : kMediaShowClosedCaptionsButton);
+  SetClass("visible", captions_visible);
 }
 
 WebLocalizedString::Name
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlVolumeSliderElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlVolumeSliderElement.cpp
index 16956ff1..59647d0 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlVolumeSliderElement.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlVolumeSliderElement.cpp
@@ -5,7 +5,6 @@
 #include "modules/media_controls/elements/MediaControlVolumeSliderElement.h"
 
 #include "core/HTMLNames.h"
-#include "core/InputTypeNames.h"
 #include "core/dom/events/Event.h"
 #include "core/html/HTMLMediaElement.h"
 #include "core/layout/LayoutObject.h"
@@ -17,12 +16,10 @@
 
 MediaControlVolumeSliderElement::MediaControlVolumeSliderElement(
     MediaControlsImpl& media_controls)
-    : MediaControlInputElement(media_controls, kMediaVolumeSlider) {
-  EnsureUserAgentShadowRoot();
-  setType(InputTypeNames::range);
-  setAttribute(HTMLNames::stepAttr, "any");
+    : MediaControlSliderElement(media_controls, kMediaVolumeSlider) {
   setAttribute(HTMLNames::maxAttr, "1");
   SetShadowPseudoId(AtomicString("-webkit-media-controls-volume-slider"));
+  SetVolumeInternal(MediaElement().volume());
 }
 
 void MediaControlVolumeSliderElement::SetVolume(double volume) {
@@ -30,8 +27,7 @@
     return;
 
   setValue(String::Number(volume));
-  if (LayoutObject* layout_object = this->GetLayoutObject())
-    layout_object->SetShouldDoFullPaintInvalidation();
+  SetVolumeInternal(volume);
 }
 
 bool MediaControlVolumeSliderElement::WillRespondToMouseMoveEvents() {
@@ -77,11 +73,15 @@
     double volume = value().ToDouble();
     MediaElement().setVolume(volume);
     MediaElement().setMuted(false);
-    if (LayoutObject* layout_object = this->GetLayoutObject())
-      layout_object->SetShouldDoFullPaintInvalidation();
+    SetVolumeInternal(volume);
   }
 }
 
+void MediaControlVolumeSliderElement::SetVolumeInternal(double volume) {
+  SetupBarSegments();
+  SetAfterSegmentPosition(MediaControlSliderElement::Position(0, volume));
+}
+
 bool MediaControlVolumeSliderElement::KeepEventInNode(Event* event) {
   return MediaControlElementsHelper::IsUserInteractionEventForSlider(
       event, GetLayoutObject());
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlVolumeSliderElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlVolumeSliderElement.h
index b7dc4ed8..29d4f96 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlVolumeSliderElement.h
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlVolumeSliderElement.h
@@ -5,14 +5,14 @@
 #ifndef MediaControlVolumeSliderElement_h
 #define MediaControlVolumeSliderElement_h
 
-#include "modules/media_controls/elements/MediaControlInputElement.h"
+#include "modules/media_controls/elements/MediaControlSliderElement.h"
 
 namespace blink {
 
 class Event;
 class MediaControlsImpl;
 
-class MediaControlVolumeSliderElement final : public MediaControlInputElement {
+class MediaControlVolumeSliderElement final : public MediaControlSliderElement {
  public:
   explicit MediaControlVolumeSliderElement(MediaControlsImpl&);
 
@@ -31,6 +31,7 @@
  private:
   void DefaultEventHandler(Event*) override;
   bool KeepEventInNode(Event*) override;
+  void SetVolumeInternal(double);
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_cast_off.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_cast_off.png
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_cast_off.png
rename to third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_cast_off.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_cast_on.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_cast_on.png
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_cast_on.png
rename to third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_cast_on.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_closedcaption.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_closedcaption.png
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_closedcaption.png
rename to third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_closedcaption.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_closedcaption_disabled.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_closedcaption_disabled.png
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_closedcaption_disabled.png
rename to third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_closedcaption_disabled.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_closedcaptions_icon.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_closedcaptions_icon.png
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_closedcaptions_icon.png
rename to third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_closedcaptions_icon.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_download.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_download.png
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_download.png
rename to third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_download.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_enter_fullscreen.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_enter_fullscreen.png
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_enter_fullscreen.png
rename to third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_enter_fullscreen.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_exit_fullscreen.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_exit_fullscreen.png
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_exit_fullscreen.png
rename to third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_exit_fullscreen.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_overflow_menu.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_overflow_menu.png
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_overflow_menu.png
rename to third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_overflow_menu.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_overlay_cast_off.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_overlay_cast_off.png
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_overlay_cast_off.png
rename to third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_overlay_cast_off.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_overlay_cast_on.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_overlay_cast_on.png
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_overlay_cast_on.png
rename to third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_overlay_cast_on.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_overlay_play.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_overlay_play.png
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_overlay_play.png
rename to third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_overlay_play.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_pause.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_pause.png
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_pause.png
rename to third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_pause.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_play.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_play.png
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_play.png
rename to third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_play.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_slider_thumb.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_slider_thumb.png
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_slider_thumb.png
rename to third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_slider_thumb.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_sound_muted.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_sound_muted.png
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_sound_muted.png
rename to third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_sound_muted.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_sound_not_muted.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_sound_not_muted.png
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_sound_not_muted.png
rename to third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_sound_not_muted.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_subtitles_icon.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_subtitles_icon.png
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_subtitles_icon.png
rename to third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_subtitles_icon.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_trackselection_checkmark.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_trackselection_checkmark.png
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_trackselection_checkmark.png
rename to third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_trackselection_checkmark.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_volume_slider_thumb.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_volume_slider_thumb.png
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaplayer_volume_slider_thumb.png
rename to third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaplayer_volume_slider_thumb.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaremoting_cast.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaremoting_cast.png
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/mediaremoting_cast.png
rename to third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/legacy/mediaremoting_cast.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_200_percent/mediaremoting_cast.png b/third_party/WebKit/Source/modules/media_controls/resources/default_200_percent/legacy/mediaremoting_cast.png
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/default_200_percent/mediaremoting_cast.png
rename to third_party/WebKit/Source/modules/media_controls/resources/default_200_percent/legacy/mediaremoting_cast.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/legacyMediaControls.css b/third_party/WebKit/Source/modules/media_controls/resources/legacyMediaControls.css
new file mode 100644
index 0000000..2391a21e
--- /dev/null
+++ b/third_party/WebKit/Source/modules/media_controls/resources/legacyMediaControls.css
@@ -0,0 +1,774 @@
+/*
+ * Copyright (C) 2009 Apple Inc.  All rights reserved.
+ * Copyright (C) 2015 Google Inc.
+ *
+ * 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,
+ * 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.
+ */
+
+/* Chromium default media controls */
+
+/* WARNING: This css file can only style <audio> and <video> elements */
+
+audio:not([controls]) {
+    display: none !important;
+}
+
+audio {
+    width: 300px;
+    height: 32px;
+}
+
+audio::-webkit-media-controls,
+video::-webkit-media-controls {
+    width: inherit;
+    height: inherit;
+    position: relative;
+    direction: ltr;
+    display: flex;
+    flex-direction: column;
+    font-family: Segoe, "Helvetica Neue", Roboto, Arial, Helvetica, sans-serif;
+    justify-content: flex-end;
+    align-items: center;
+}
+
+audio::-webkit-media-controls-enclosure, video::-webkit-media-controls-enclosure {
+    width: 100%;
+    height: 32px;
+    flex-shrink: 0;
+    bottom: 0;
+    text-indent: 0;
+    padding: 0;
+    margin: 0;
+    box-sizing: border-box;
+}
+
+audio::-webkit-media-controls-panel, video::-webkit-media-controls-panel {
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    /* We use flex-start here to ensure that the play button is visible even
+     * if we are too small to show all controls.
+     */
+    justify-content: flex-start;
+    -webkit-user-select: none;
+    position: relative;
+    width: 100%;
+    z-index: 0;
+    overflow: hidden;
+    text-align: right;
+    bottom: auto;
+    height: 32px;
+    min-width: 48px;
+    line-height: 32px;
+    background-color: #fafafa;
+    /* The duration is also specified in MediaControlElements.cpp and LayoutTests/media/media-controls.js */
+    transition: opacity 0.3s;
+
+    font-size: 12px;
+    font-weight: normal;  /* Make sure that we don't inherit non-defaults. */
+    font-style: normal;
+}
+
+video:-webkit-full-page-media {
+    margin: auto;
+    position: absolute;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    left: 0;
+}
+
+audio:-webkit-full-page-media, video:-webkit-full-page-media {
+    max-height: 100%;
+    max-width: 100%;
+}
+
+audio:-webkit-full-page-media::-webkit-media-controls-panel,
+video:-webkit-full-page-media::-webkit-media-controls-panel {
+    bottom: 0px;
+}
+
+audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-button {
+    -webkit-appearance: -internal-media-control;
+    background-image: -webkit-image-set(
+      url(default_100_percent/legacy/mediaplayer_sound_not_muted.png) 1x);
+    background-size: 32px;
+    background-repeat: no-repeat;
+    background-position: center center;
+    display: flex;
+    flex: none;
+    box-sizing: border-box;
+    width: 32px;
+    height: 32px;
+    padding: 0px;
+    border-width: 0px;
+    background-color: initial;
+    color: inherit;
+}
+
+audio::-webkit-media-controls-mute-button.muted,
+video::-webkit-media-controls-mute-button.muted {
+    background-image: -webkit-image-set(
+      url(default_100_percent/legacy/mediaplayer_sound_muted.png) 1x);
+}
+
+audio::-webkit-media-controls-overlay-enclosure {
+    display: none;
+}
+
+video::-webkit-media-controls-overlay-enclosure {
+    display: flex;
+    position: relative;
+    flex-direction: column;
+    justify-content: flex-end;
+    align-items: center;
+    flex: 1 1;
+    min-height: 0;
+    width: 100%;
+    /* Prevent disambiguation zooms with the panel. If this changes, it must
+     * also be changed in core/html/shadow/MediaControls.cpp. */
+    margin-bottom: 10px;
+    text-indent: 0;
+    box-sizing: border-box;
+    overflow: hidden;
+}
+
+video::-webkit-media-controls-overlay-play-button {
+    -webkit-appearance: -internal-media-control;
+    background-image: -webkit-image-set(
+      url(default_100_percent/legacy/mediaplayer_overlay_play.png) 1x);
+    background-size: 48px;
+    background-repeat: no-repeat;
+    background-position: center center;
+    display: flex;
+    position: absolute;
+    top: 0;
+    left: 0;
+    margin: 0;
+    border-width: 0px;
+    background-color: transparent;
+    width: 100%;
+    height: 100%;
+    padding: 0;
+}
+
+/* TODO(xjz): Move media remoting elements to a separate css file. */
+video::-internal-media-remoting-interstitial {
+    width: inherit;
+    height: inherit;
+    position: relative;
+    direction: ltr;
+    display: flex;
+    flex-direction: column;
+    justify-content: flex-end;
+    align-items: center;
+    font-size: 16px;
+    background-color: black;
+    opacity: 0;
+    transition: opacity .3s ease-in-out;
+}
+
+video::-internal-media-remoting-background-image {
+    display: flex;
+    position: absolute;
+    margin: 0;
+    top: 0px;
+    left: 0px;
+    width: 100%;
+    height: 100%;
+    border: none;
+    border-width: 0px;
+    background-color: transparent;
+    padding: 0;
+    filter: grayscale(100%) blur(5px) opacity(40%);
+}
+
+video::-internal-media-remoting-cast-icon {
+    -webkit-appearance: none;
+    background-image: -webkit-image-set(
+      url(default_100_percent/legacy/mediaremoting_cast.png) 1x,
+      url(default_200_percent/legacy/mediaremoting_cast.png) 2x);
+    background-size: 32px;
+    background-repeat: no-repeat;
+    background-position: center center;
+    display: flex;
+    position: absolute;
+    margin: 0px;
+    border-width: 0px;
+    background-color: transparent;
+    height: 18px;
+    width: 22px;
+    padding: 0px;
+    left: calc(50% - 11px);
+    top: calc(50% - 40px);
+}
+
+video::-internal-media-remoting-cast-text-message {
+    display: inline;
+    position: absolute;
+    top: calc(50% - 10px);
+    border: none;
+    color: rgba(255,255,255,.54);
+    width: 100%;
+    text-wrap: none;
+    text-align: center;
+    background-color: transparent;
+    font-size: 81.25%;
+    font-family: Roboto-Regular, Sans-serif, Segoe, Serif, Helvetica;
+    padding: 0px;
+    margin: 0px;
+}
+
+video::-internal-media-remoting-disable-button {
+    display: flex;
+    position: absolute;
+    top: calc(50% + 60px);
+    left: calc(50% - 74px);
+    height: 28px;
+    border: 1pt solid rgba(255,255,255,.54);
+    border-radius: 2pt;
+    background-color: transparent;
+    color: rgba(255,255,255,.54);
+    margin: 0px;
+    padding: 5.5px 16px 0px 16px;
+    text-wrap: none;
+    font-size: 75%;
+    font-weight: 500;
+    font-family: Roboto-Medium, Sans-serif, Segoe, Serif, Helvetica;
+    box-sizing: border-box;
+    transition: border,color .5s ease-out;
+    z-index: 1;  /* Set this z-index to make the hover effect work. */
+}
+
+video::-internal-media-remoting-disable-button:hover {
+    border: 1pt solid rgba(255,255,255,.70);
+    color: rgba(255,255,255,.70);
+    cursor: pointer;
+}
+
+video::-internal-media-controls-overlay-cast-button {
+    -webkit-appearance: none;
+    background-image: -webkit-image-set(
+      url(default_100_percent/legacy/mediaplayer_overlay_cast_off.png) 1x);
+    background-size: cover;
+    background-repeat: no-repeat;
+    background-position: center center;
+    display: flex;
+    position: absolute;
+    top: 8px;
+    left: 8px;
+    margin-left: 0px;
+    margin-top: 0px;
+    border-width: 0px;
+    background-color: transparent;
+    width: 32px;
+    height: 32px;
+    padding: 0;
+    transition: opacity 0.3s;
+}
+
+video::-internal-media-controls-overlay-cast-button.on {
+    background-image: -webkit-image-set(
+      url(default_100_percent/legacy/mediaplayer_overlay_cast_on.png) 1x);
+}
+
+audio::-webkit-media-controls-play-button, video::-webkit-media-controls-play-button {
+    -webkit-appearance: -internal-media-control;
+    background-image: -webkit-image-set(
+      url(default_100_percent/legacy/mediaplayer_pause.png) 1x);
+    background-size: 32px;
+    background-repeat: no-repeat;
+    background-position: center center;
+    display: flex;
+    flex: none;
+    box-sizing: border-box;
+    width: 32px;
+    height: 32px;
+    padding: 0px;
+    border-width: 0px;
+    background-color: initial;
+    color: inherit;
+}
+
+audio::-webkit-media-controls-play-button.pause,
+video::-webkit-media-controls-play-button.pause {
+  background-image: -webkit-image-set(
+      url(default_100_percent/legacy/mediaplayer_play.png) 1x);
+}
+
+audio::-webkit-media-controls-timeline-container, video::-webkit-media-controls-timeline-container {
+    -webkit-appearance: media-controls-background;
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    justify-content: flex-end;
+    flex: 1 1;
+    -webkit-user-select: none;
+    height: 48px;
+    padding: 0;
+    min-width: 0;
+}
+
+audio::-webkit-media-controls-current-time-display, video::-webkit-media-controls-current-time-display {
+    -webkit-appearance: media-current-time-display;
+    -webkit-user-select: none;
+    flex: none;
+    display: flex;
+    border: none;
+    cursor: default;
+
+    height: 32px;
+
+    /* text runs right to the edge of the container */
+    padding: 0;
+
+    color: #5a5a5a;
+
+    letter-spacing: normal;
+    word-spacing: normal;
+    text-transform: none;
+    text-indent: 0;
+    text-shadow: none;
+    text-decoration: none;
+}
+
+audio::-webkit-media-controls-time-remaining-display, video::-webkit-media-controls-time-remaining-display {
+    -webkit-appearance: media-current-time-display;
+    -webkit-user-select: none;
+    flex: none;
+    display: flex;
+    border: none;
+    cursor: default;
+
+    height: 32px;
+
+    /* text runs right to the edge of the container, plus a little on
+     * the left to pad the leading "/" */
+    padding: 0 0 0 4px;
+
+    color: #5a5a5a;
+
+    letter-spacing: normal;
+    word-spacing: normal;
+    text-transform: none;
+    text-indent: 0;
+    text-shadow: none;
+    text-decoration: none;
+}
+
+audio::-webkit-media-controls-timeline, video::-webkit-media-controls-timeline {
+    -webkit-appearance: -internal-media-control;
+    display: flex;
+    flex: 1 1 auto;
+    height: 2px;
+
+    /* Leave 6px on either side for the thumb.  Use margin so that
+     * the slider doesn't extend into it.  We also add 12px border.
+     */
+    padding: 0;
+    margin: 0 18px 0 18px;
+    background-color: transparent;
+    min-width: 25px;
+    border: initial;
+    color: inherit;
+}
+
+audio::-webkit-media-controls-volume-slider, video::-webkit-media-controls-volume-slider {
+    -webkit-appearance: -internal-media-control;
+    display: flex;
+    /* The 1.9 value was empirically chosen to match old-flexbox behaviour
+     * and be aesthetically pleasing.
+     */
+    flex: 1 1.9 auto;
+    height: 2px;
+    max-width: 70px;
+    /* Leave room for the thumb, which has 6px radius.  Use margin rather
+     * than padding so that the slider doesn't extend into it.  We also
+     * leave an addition 12px margin.
+     */
+    padding: 0;
+    margin: 0 18px 0 18px;
+    background-color: transparent;
+    min-width: 25px;
+    border: initial;
+    color: inherit;
+}
+
+/**
+ * Segmented Track
+ */
+
+div.-internal-media-controls-segmented-track {
+    margin: 0 -18px;
+    position: relative;
+}
+
+div.-internal-media-controls-segmented-track .-internal-track-segment-background {
+    width: auto;
+    position: absolute;
+    background: #dadada;
+    height: 2px;
+    margin-top: -1px;
+    left: 18px;
+    right: 18px;
+    top: 50%;
+}
+
+div.-internal-media-controls-segmented-track .-internal-track-segment-highlight-before,
+div.-internal-media-controls-segmented-track .-internal-track-segment-highlight-after {
+    height: auto;
+    position: absolute;
+    top: 50%;
+    bottom: 0;
+    z-index: 1;
+    height: 2px;
+    margin-top: -1px;
+}
+
+div.-internal-media-controls-segmented-track .-internal-track-segment-highlight-after {
+    background-color: #4285f4;
+}
+
+div.-internal-media-controls-segmented-track .-internal-track-segment-highlight-before {
+    background-color: #5a5a5a;
+}
+
+/**
+ * Track Thumb
+ */
+
+input[pseudo="-webkit-media-controls-timeline" i]::-webkit-slider-thumb,
+input[pseudo="-webkit-media-controls-volume-slider" i]::-webkit-slider-thumb {
+    -webkit-appearance: -internal-media-control;
+    background-image: -webkit-image-set(
+      url(default_100_percent/legacy/mediaplayer_slider_thumb.png) 1x);
+    background-size: 12px;
+    background-repeat: no-repeat;
+    background-position: center center;
+
+    height: 36px;
+    z-index: 2;
+    width: 36px;
+    margin: 0;
+    padding: 0;
+    top: -24px;
+    position: absolute;
+}
+
+audio::-webkit-media-controls-fullscreen-button, video::-webkit-media-controls-fullscreen-button {
+    -webkit-appearance: -internal-media-control;
+    background-image: -webkit-image-set(
+      url(default_100_percent/legacy/mediaplayer_enter_fullscreen.png) 1x);
+    background-size: 32px;
+    background-repeat: no-repeat;
+    background-position: center center;
+    display: flex;
+    flex: none;
+    overflow: hidden;
+    box-sizing: border-box;
+    width: 32px;
+    height: 32px;
+    padding: 0px;
+    border-width: 0px;
+    background-color: initial;
+    color: inherit;
+}
+
+audio::-webkit-media-controls-fullscreen-button.fullscreen,
+video::-webkit-media-controls-fullscreen-button.fullscreen {
+    background-image: -webkit-image-set(
+      url(default_100_percent/legacy/mediaplayer_exit_fullscreen.png) 1x);
+}
+
+audio::-internal-media-controls-cast-button, video::-internal-media-controls-cast-button {
+    -webkit-appearance: none;
+    background-image: -webkit-image-set(
+      url(default_100_percent/legacy/mediaplayer_cast_off.png) 1x);
+    background-size: 32px;
+    background-repeat: no-repeat;
+    background-position: center center;
+    display: flex;
+    flex: none;
+    box-sizing: border-box;
+    width: 32px;
+    height: 32px;
+    padding: 0px;
+    border-width: 0px;
+    margin-left: 0px;
+    margin-right: 0px;
+    background-color: initial;
+    color: inherit;
+}
+
+audio::-internal-media-controls-cast-button.on,
+video::-internal-media-controls-cast-button.on {
+    background-image: -webkit-image-set(
+      url(default_100_percent/legacy/mediaplayer_cast_on.png) 1x);
+}
+
+audio::-webkit-media-controls-toggle-closed-captions-button {
+    display: none;
+}
+
+video::-webkit-media-controls-toggle-closed-captions-button {
+    -webkit-appearance: -internal-media-control;
+    background-image: -webkit-image-set(
+      url(default_100_percent/legacy/mediaplayer_closedcaption_disabled.png) 1x);
+    background-size: 32px;
+    background-repeat: no-repeat;
+    background-position: center center;
+    display: flex;
+    flex: none;
+    box-sizing: border-box;
+    width: 32px;
+    height: 32px;
+    padding: 0px;
+    border-width: 0px;
+    margin-left: 0px;
+    margin-right: 0px;
+    background-color: initial;
+    color: inherit;
+}
+
+video::-webkit-media-controls-toggle-closed-captions-button.visible {
+    background-image: -webkit-image-set(
+      url(default_100_percent/legacy/mediaplayer_closedcaption.png) 1x);
+}
+
+video::-internal-media-controls-text-track-list, video::-internal-media-controls-overflow-menu-list, audio::-internal-media-controls-overflow-menu-list {
+    position: fixed;
+    background-color: #fafafa;
+    max-width: 50%;
+    max-height: 250px;
+    min-width: 150px;
+    overflow-x: hidden;
+    overflow-y: auto;
+    white-space: nowrap;
+    font-size: 14px;
+    border-radius: 1px;
+    box-shadow: 0 8px 20px 1px rgba(0, 0, 0, 0.14),
+                0 3px 28px 2px rgba(0, 0, 0, 0.12),
+                0 5px 10px -3px rgba(0, 0, 0, 0.4);
+}
+
+video::-internal-media-controls-text-track-list-item {
+    display: block;
+    color: #424242;
+    text-align: start;
+    line-height: 40px;
+    padding-right: 16px;
+    text-overflow: ellipsis;
+}
+
+video::-internal-media-controls-text-track-list-item:hover, video::-internal-media-controls-overflow-menu-list-item:hover, audio::-internal-media-controls-overflow-menu-list-item:hover {
+    background-color: #e0e0e0;
+}
+
+video::-internal-media-controls-text-track-list-item-input {
+    -webkit-appearance: none;
+    background-image: -webkit-image-set(
+      url(default_100_percent/legacy/mediaplayer_trackselection_checkmark.png) 1x);
+    background-size: 32px;
+    background-repeat: no-repeat;
+    background-position: center center;
+    visibility: hidden;
+    left: 0;
+    vertical-align: middle;
+    margin: 0 5px 0 0;
+    width: 16px;
+    height: 16px;
+    margin-left: 12px;
+}
+
+video::-internal-media-controls-text-track-list-item-input:checked {
+    visibility: visible;
+}
+
+video::-internal-media-controls-text-track-list-kind-captions {
+    -webkit-appearance: none;
+    background-image: -webkit-image-set(
+      url(default_100_percent/legacy/mediaplayer_closedcaptions_icon.png) 1x);
+    background-size: 32px;
+    background-repeat: no-repeat;
+    background-position: center center;
+    height: 20px;
+    width: 20px;
+    margin-left: 10px;
+    vertical-align: middle;
+}
+
+video::-internal-media-controls-text-track-list-kind-subtitles {
+    -webkit-appearance: none;
+    background-image: -webkit-image-set(
+      url(default_100_percent/legacy/mediaplayer_subtitles_icon.png) 1x);
+    background-size: 32px;
+    background-repeat: no-repeat;
+    background-position: center center;
+    height: 20px;
+    width: 20px;
+    margin-left: 10px;
+    vertical-align: middle;
+}
+
+video::-internal-media-controls-overflow-button, audio::-internal-media-controls-overflow-button {
+    -webkit-appearance: none;
+    background-image: -webkit-image-set(
+      url(default_100_percent/legacy/mediaplayer_overflow_menu.png) 1x);
+    background-size: 32px;
+    background-repeat: no-repeat;
+    background-position: center center;
+    display: flex;
+    flex: none;
+    box-sizing: border-box;
+    width: 32px;
+    height: 32px;
+    padding: 0px;
+    border-width: 0px;
+    margin-left: 0px;
+    margin-right: 0px;
+    background-color: initial;
+    color: inherit;
+}
+
+video::-internal-media-controls-download-button, audio::-internal-media-controls-download-button {
+    -webkit-appearance: none;
+    background-image: -webkit-image-set(
+      url(default_100_percent/legacy/mediaplayer_download.png) 1x);
+    background-size: 32px;
+    background-repeat: no-repeat;
+    background-position: center center;
+    display: flex;
+    flex: none;
+    box-sizing: border-box;
+    width: 32px;
+    height: 32px;
+    padding: 0px;
+    border-width: 0px;
+    margin-left: 0px;
+    margin-right: 0px;
+    background-color: initial;
+    color: inherit;
+}
+
+video::-internal-media-controls-overflow-menu-list-item, audio::-internal-media-controls-overflow-menu-list-item {
+    display: flex;
+    align-items: center;
+    justify-content: flex-start;
+
+    color: #424242;
+    line-height: 40px;
+    padding-left: 28px;
+}
+
+label[pseudo="-internal-media-controls-overflow-menu-list-item"] input{
+    margin-left: -22px;
+    margin-right: 2px;
+}
+
+video::-webkit-media-text-track-container {
+    position: relative;
+    width: inherit;
+    height: inherit;
+    overflow: hidden;
+
+    font: 22px sans-serif;
+    text-align: center;
+    color: rgba(255, 255, 255, 1);
+
+    letter-spacing: normal;
+    word-spacing: normal;
+    text-transform: none;
+    text-indent: 0;
+    text-decoration: none;
+    pointer-events: none;
+    -webkit-user-select: none;
+    word-break: break-word;
+}
+
+video::cue {
+    display: inline;
+
+    background-color: rgba(0, 0, 0, 0.8);
+    padding: 2px 2px;
+}
+
+video::-webkit-media-text-track-region {
+    position: absolute;
+    line-height: 5.33vh;
+    writing-mode: horizontal-tb;
+    background: rgba(0, 0, 0, 0.8);
+    color: rgba(255, 255, 255, 1);
+    word-wrap: break-word;
+    overflow-wrap: break-word;
+    overflow: hidden;
+}
+
+video::-webkit-media-text-track-region-container {
+    position: relative;
+
+    display: flex;
+    flex-flow: column;
+    flex-direction: column;
+}
+
+video::-webkit-media-text-track-region-container.scrolling {
+    transition: top 433ms linear;
+}
+
+
+video::-webkit-media-text-track-display {
+    position: absolute;
+    overflow: hidden;
+    white-space: pre-wrap;
+    -webkit-box-sizing: border-box;
+    flex: 0 0 auto;
+}
+
+video::cue(:future) {
+    color: gray;
+}
+
+video::cue(b) {
+    font-weight: bold;
+}
+
+video::cue(u) {
+    text-decoration: underline;
+}
+
+video::cue(i) {
+    font-style: italic;
+}
+
+.state-no-source input[pseudo="-webkit-media-controls-play-button"],
+.state-no-source input[pseudo="-webkit-media-controls-mute-button"],
+.state-no-source input[pseudo="-webkit-media-controls-overlay-play-button"],
+.state-no-source input[pseudo="-webkit-media-controls-fullscreen-button"],
+.state-no-source input[pseudo="-internal-media-controls-download-button"],
+.state-no-source input[pseudo="-webkit-media-controls-timeline"],
+.state-no-source input[pseudo="-webkit-media-controls-volume-slider"] {
+    opacity: 0.4;
+}
+
+.state-no-source input[pseudo="-webkit-media-controls-timeline" i]::-webkit-slider-thumb,
+.state-no-source input[pseudo="-webkit-media-controls-volume-slider" i]::-webkit-slider-thumb {
+    display: none;
+}
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/mediaControlsAndroid.css b/third_party/WebKit/Source/modules/media_controls/resources/legacyMediaControlsAndroid.css
similarity index 100%
rename from third_party/WebKit/Source/modules/media_controls/resources/mediaControlsAndroid.css
rename to third_party/WebKit/Source/modules/media_controls/resources/legacyMediaControlsAndroid.css
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/mediaControls.css b/third_party/WebKit/Source/modules/media_controls/resources/mediaControls.css
deleted file mode 100644
index b42970b..0000000
--- a/third_party/WebKit/Source/modules/media_controls/resources/mediaControls.css
+++ /dev/null
@@ -1,626 +0,0 @@
-/*
- * Copyright (C) 2009 Apple Inc.  All rights reserved.
- * Copyright (C) 2015 Google Inc.
- *
- * 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,
- * 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.
- */
-
-/* Chromium default media controls */
-
-/* WARNING: This css file can only style <audio> and <video> elements */
-
-audio:not([controls]) {
-    display: none !important;
-}
-
-audio {
-    width: 300px;
-    height: 32px;
-}
-
-audio::-webkit-media-controls,
-video::-webkit-media-controls {
-    width: inherit;
-    height: inherit;
-    position: relative;
-    direction: ltr;
-    display: flex;
-    flex-direction: column;
-    font-family: Segoe, "Helvetica Neue", Roboto, Arial, Helvetica, sans-serif;
-    justify-content: flex-end;
-    align-items: center;
-}
-
-audio::-webkit-media-controls-enclosure, video::-webkit-media-controls-enclosure {
-    width: 100%;
-    height: 32px;
-    flex-shrink: 0;
-    bottom: 0;
-    text-indent: 0;
-    padding: 0;
-    margin: 0;
-    box-sizing: border-box;
-}
-
-audio::-webkit-media-controls-panel, video::-webkit-media-controls-panel {
-    display: flex;
-    flex-direction: row;
-    align-items: center;
-    /* We use flex-start here to ensure that the play button is visible even
-     * if we are too small to show all controls.
-     */
-    justify-content: flex-start;
-    -webkit-user-select: none;
-    position: relative;
-    width: 100%;
-    z-index: 0;
-    overflow: hidden;
-    text-align: right;
-    bottom: auto;
-    height: 32px;
-    min-width: 48px;
-    line-height: 32px;
-    background-color: #fafafa;
-    /* The duration is also specified in MediaControlElements.cpp and LayoutTests/media/media-controls.js */
-    transition: opacity 0.3s;
-
-    font-size: 12px;
-    font-weight: normal;  /* Make sure that we don't inherit non-defaults. */
-    font-style: normal;
-}
-
-video:-webkit-full-page-media {
-    margin: auto;
-    position: absolute;
-    top: 0;
-    right: 0;
-    bottom: 0;
-    left: 0;
-}
-
-audio:-webkit-full-page-media, video:-webkit-full-page-media {
-    max-height: 100%;
-    max-width: 100%;
-}
-
-audio:-webkit-full-page-media::-webkit-media-controls-panel,
-video:-webkit-full-page-media::-webkit-media-controls-panel {
-    bottom: 0px;
-}
-
-audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-button {
-    -webkit-appearance: media-mute-button;
-    display: flex;
-    flex: none;
-    box-sizing: border-box;
-    width: 32px;
-    height: 32px;
-    padding: 0px;
-    border-width: 0px;
-    background-color: initial;
-    color: inherit;
-}
-
-audio::-webkit-media-controls-overlay-enclosure {
-    display: none;
-}
-
-video::-webkit-media-controls-overlay-enclosure {
-    display: flex;
-    position: relative;
-    flex-direction: column;
-    justify-content: flex-end;
-    align-items: center;
-    flex: 1 1;
-    min-height: 0;
-    width: 100%;
-    /* Prevent disambiguation zooms with the panel. If this changes, it must
-     * also be changed in core/html/shadow/MediaControls.cpp. */
-    margin-bottom: 10px;
-    text-indent: 0;
-    box-sizing: border-box;
-    overflow: hidden;
-}
-
-video::-webkit-media-controls-overlay-play-button {
-    -webkit-appearance: media-overlay-play-button;
-    display: flex;
-    position: absolute;
-    top: 0;
-    left: 0;
-    margin: 0;
-    border-width: 0px;
-    background-color: transparent;
-    width: 100%;
-    height: 100%;
-    padding: 0;
-}
-
-/* TODO(xjz): Move media remoting elements to a separate css file. */
-video::-internal-media-remoting-interstitial {
-    width: inherit;
-    height: inherit;
-    position: relative;
-    direction: ltr;
-    display: flex;
-    flex-direction: column;
-    justify-content: flex-end;
-    align-items: center;
-    font-size: 16px;
-    background-color: black;
-    opacity: 0;
-    transition: opacity .3s ease-in-out;
-}
-
-video::-internal-media-remoting-background-image {
-    display: flex;
-    position: absolute;
-    margin: 0;
-    top: 0px;
-    left: 0px;
-    width: 100%;
-    height: 100%;
-    border: none;
-    border-width: 0px;
-    background-color: transparent;
-    padding: 0;
-    filter: grayscale(100%) blur(5px) opacity(40%);
-}
-
-video::-internal-media-remoting-cast-icon {
-    -webkit-appearance: -internal-media-remoting-cast-icon;
-    display: flex;
-    position: absolute;
-    margin: 0px;
-    border-width: 0px;
-    background-color: transparent;
-    height: 18px;
-    width: 22px;
-    padding: 0px;
-    left: calc(50% - 11px);
-    top: calc(50% - 40px);
-}
-
-video::-internal-media-remoting-cast-text-message {
-    display: inline;
-    position: absolute;
-    top: calc(50% - 10px);
-    border: none;
-    color: rgba(255,255,255,.54);
-    width: 100%;
-    text-wrap: none;
-    text-align: center;
-    background-color: transparent;
-    font-size: 81.25%;
-    font-family: Roboto-Regular, Sans-serif, Segoe, Serif, Helvetica;
-    padding: 0px;
-    margin: 0px;
-}
-
-video::-internal-media-remoting-disable-button {
-    display: flex;
-    position: absolute;
-    top: calc(50% + 60px);
-    left: calc(50% - 74px);
-    height: 28px;
-    border: 1pt solid rgba(255,255,255,.54);
-    border-radius: 2pt;
-    background-color: transparent;
-    color: rgba(255,255,255,.54);
-    margin: 0px;
-    padding: 5.5px 16px 0px 16px;
-    text-wrap: none;
-    font-size: 75%;
-    font-weight: 500;
-    font-family: Roboto-Medium, Sans-serif, Segoe, Serif, Helvetica;
-    box-sizing: border-box;
-    transition: border,color .5s ease-out;
-    z-index: 1;  /* Set this z-index to make the hover effect work. */
-}
-
-video::-internal-media-remoting-disable-button:hover {
-    border: 1pt solid rgba(255,255,255,.70);
-    color: rgba(255,255,255,.70);
-    cursor: pointer;
-}
-
-video::-internal-media-controls-overlay-cast-button {
-    -webkit-appearance: -internal-media-overlay-cast-off-button;
-    display: flex;
-    position: absolute;
-    top: 8px;
-    left: 8px;
-    margin-left: 0px;
-    margin-top: 0px;
-    border-width: 0px;
-    background-color: transparent;
-    width: 32px;
-    height: 32px;
-    padding: 0;
-    transition: opacity 0.3s;
-}
-
-audio::-webkit-media-controls-play-button, video::-webkit-media-controls-play-button {
-    -webkit-appearance: media-play-button;
-    display: flex;
-    flex: none;
-    box-sizing: border-box;
-    width: 32px;
-    height: 32px;
-    padding: 0px;
-    border-width: 0px;
-    background-color: initial;
-    color: inherit;
-}
-
-audio::-webkit-media-controls-timeline-container, video::-webkit-media-controls-timeline-container {
-    -webkit-appearance: media-controls-background;
-    display: flex;
-    flex-direction: row;
-    align-items: center;
-    justify-content: flex-end;
-    flex: 1 1;
-    -webkit-user-select: none;
-    height: 48px;
-    padding: 0;
-    min-width: 0;
-}
-
-audio::-webkit-media-controls-current-time-display, video::-webkit-media-controls-current-time-display {
-    -webkit-appearance: media-current-time-display;
-    -webkit-user-select: none;
-    flex: none;
-    display: flex;
-    border: none;
-    cursor: default;
-
-    height: 32px;
-
-    /* text runs right to the edge of the container */
-    padding: 0;
-
-    color: #5a5a5a;
-
-    letter-spacing: normal;
-    word-spacing: normal;
-    text-transform: none;
-    text-indent: 0;
-    text-shadow: none;
-    text-decoration: none;
-}
-
-audio::-webkit-media-controls-time-remaining-display, video::-webkit-media-controls-time-remaining-display {
-    -webkit-appearance: media-current-time-display;
-    -webkit-user-select: none;
-    flex: none;
-    display: flex;
-    border: none;
-    cursor: default;
-
-    height: 32px;
-
-    /* text runs right to the edge of the container, plus a little on
-     * the left to pad the leading "/" */
-    padding: 0 0 0 4px;
-
-    color: #5a5a5a;
-
-    letter-spacing: normal;
-    word-spacing: normal;
-    text-transform: none;
-    text-indent: 0;
-    text-shadow: none;
-    text-decoration: none;
-}
-
-audio::-webkit-media-controls-timeline, video::-webkit-media-controls-timeline {
-    -webkit-appearance: media-slider;
-    display: flex;
-    flex: 1 1 auto;
-    height: 2px;
-
-    /* Leave 6px on either side for the thumb.  Use margin so that
-     * the slider doesn't extend into it.  We also add 12px border.
-     */
-    padding: 0;
-    margin: 0 18px 0 18px;
-    background-color: transparent;
-    min-width: 25px;
-    border: initial;
-    color: inherit;
-}
-
-audio::-webkit-media-controls-volume-slider, video::-webkit-media-controls-volume-slider {
-    -webkit-appearance: media-volume-slider;
-    display: flex;
-    /* The 1.9 value was empirically chosen to match old-flexbox behaviour
-     * and be aesthetically pleasing.
-     */
-    flex: 1 1.9 auto;
-    height: 2px;
-    max-width: 70px;
-    /* Leave room for the thumb, which has 6px radius.  Use margin rather
-     * than padding so that the slider doesn't extend into it.  We also
-     * leave an addition 12px margin.
-     */
-    padding: 0;
-    margin: 0 18px 0 18px;
-    background-color: transparent;
-    min-width: 25px;
-    border: initial;
-    color: inherit;
-}
-
-/* FIXME these shouldn't use special pseudoShadowIds, but nicer rules.
-   https://code.google.com/p/chromium/issues/detail?id=112508
-   https://bugs.webkit.org/show_bug.cgi?id=62218
-*/
-input[type="range" i]::-webkit-media-slider-container {
-    display: flex;
-    align-items: center;
-    flex-direction: row; /* This property is updated by C++ code. */
-    box-sizing: border-box;
-    /** this positions the slider thumb for both time and volume. */
-    height: 2px;
-    width: 100%;
-    background-color: transparent; /* Background drawing is managed by C++ code to draw ranges. */
-}
-
-/* The negative right margin causes the track to overflow its container. */
-input[type="range" i]::-webkit-media-slider-container > div {
-    margin-right: -18px;  /* box is 36px wide, get to the middle */
-    margin-left:  -18px;
-}
-
-input[type="range" i]::-webkit-media-slider-thumb {
-    box-sizing: border-box;
-    width: 48px;
-    height: 48px;
-    padding: 0px;
-}
-
-audio::-webkit-media-controls-fullscreen-button, video::-webkit-media-controls-fullscreen-button {
-    -webkit-appearance: media-enter-fullscreen-button;
-    display: flex;
-    flex: none;
-    overflow: hidden;
-    box-sizing: border-box;
-    width: 32px;
-    height: 32px;
-    padding: 0px;
-    border-width: 0px;
-    background-color: initial;
-    color: inherit;
-}
-
-audio::-internal-media-controls-cast-button, video::-internal-media-controls-cast-button {
-    -webkit-appearance: -internal-media-cast-off-button;
-    display: flex;
-    flex: none;
-    box-sizing: border-box;
-    width: 32px;
-    height: 32px;
-    padding: 0px;
-    border-width: 0px;
-    margin-left: 0px;
-    margin-right: 0px;
-    background-color: initial;
-    color: inherit;
-}
-
-audio::-webkit-media-controls-toggle-closed-captions-button {
-    display: none;
-}
-
-video::-webkit-media-controls-toggle-closed-captions-button {
-    -webkit-appearance: media-toggle-closed-captions-button;
-    display: flex;
-    flex: none;
-    box-sizing: border-box;
-    width: 32px;
-    height: 32px;
-    padding: 0px;
-    border-width: 0px;
-    margin-left: 0px;
-    margin-right: 0px;
-    background-color: initial;
-    color: inherit;
-}
-
-video::-internal-media-controls-text-track-list, video::-internal-media-controls-overflow-menu-list, audio::-internal-media-controls-overflow-menu-list {
-    position: fixed;
-    background-color: #fafafa;
-    max-width: 50%;
-    max-height: 250px;
-    min-width: 150px;
-    overflow-x: hidden;
-    overflow-y: auto;
-    white-space: nowrap;
-    font-size: 14px;
-    border-radius: 1px;
-    box-shadow: 0 8px 20px 1px rgba(0, 0, 0, 0.14),
-                0 3px 28px 2px rgba(0, 0, 0, 0.12),
-                0 5px 10px -3px rgba(0, 0, 0, 0.4);
-}
-
-video::-internal-media-controls-text-track-list-item {
-    display: block;
-    color: #424242;
-    text-align: start;
-    line-height: 40px;
-    padding-right: 16px;
-    text-overflow: ellipsis;
-}
-
-video::-internal-media-controls-text-track-list-item:hover, video::-internal-media-controls-overflow-menu-list-item:hover, audio::-internal-media-controls-overflow-menu-list-item:hover {
-    background-color: #e0e0e0;
-}
-
-video::-internal-media-controls-text-track-list-item-input {
-    -webkit-appearance: -internal-media-track-selection-checkmark;
-    visibility: hidden;
-    left: 0;
-    vertical-align: middle;
-    margin: 0 5px 0 0;
-    width: 16px;
-    height: 16px;
-    margin-left: 12px;
-}
-
-video::-internal-media-controls-text-track-list-item-input:checked {
-    visibility: visible;
-}
-
-video::-internal-media-controls-text-track-list-kind-captions {
-    -webkit-appearance: -internal-media-closed-captions-icon;
-    height: 20px;
-    width: 20px;
-    margin-left: 10px;
-    vertical-align: middle;
-}
-
-video::-internal-media-controls-text-track-list-kind-subtitles {
-    -webkit-appearance: -internal-media-subtitles-icon;
-    height: 20px;
-    width: 20px;
-    margin-left: 10px;
-    vertical-align: middle;
-}
-
-video::-internal-media-controls-overflow-button, audio::-internal-media-controls-overflow-button {
-    -webkit-appearance: -internal-media-overflow-button;
-    display: flex;
-    flex: none;
-    box-sizing: border-box;
-    width: 32px;
-    height: 32px;
-    padding: 0px;
-    border-width: 0px;
-    margin-left: 0px;
-    margin-right: 0px;
-    background-color: initial;
-    color: inherit;
-}
-
-video::-internal-media-controls-download-button, audio::-internal-media-controls-download-button {
-    -webkit-appearance: -internal-media-download-button;
-    display: flex;
-    flex: none;
-    box-sizing: border-box;
-    width: 32px;
-    height: 32px;
-    padding: 0px;
-    border-width: 0px;
-    margin-left: 0px;
-    margin-right: 0px;
-    background-color: initial;
-    color: inherit;
-}
-
-video::-internal-media-controls-overflow-menu-list-item, audio::-internal-media-controls-overflow-menu-list-item {
-    display: flex;
-    align-items: center;
-    justify-content: flex-start;
-
-    color: #424242;
-    line-height: 40px;
-    padding-left: 28px;
-}
-
-label[pseudo="-internal-media-controls-overflow-menu-list-item"] input{
-    margin-left: -22px;
-    margin-right: 2px;
-}
-
-video::-webkit-media-text-track-container {
-    position: relative;
-    width: inherit;
-    height: inherit;
-    overflow: hidden;
-
-    font: 22px sans-serif;
-    text-align: center;
-    color: rgba(255, 255, 255, 1);
-
-    letter-spacing: normal;
-    word-spacing: normal;
-    text-transform: none;
-    text-indent: 0;
-    text-decoration: none;
-    pointer-events: none;
-    -webkit-user-select: none;
-    word-break: break-word;
-}
-
-video::cue {
-    display: inline;
-
-    background-color: rgba(0, 0, 0, 0.8);
-    padding: 2px 2px;
-}
-
-video::-webkit-media-text-track-region {
-    position: absolute;
-    line-height: 5.33vh;
-    writing-mode: horizontal-tb;
-    background: rgba(0, 0, 0, 0.8);
-    color: rgba(255, 255, 255, 1);
-    word-wrap: break-word;
-    overflow-wrap: break-word;
-    overflow: hidden;
-}
-
-video::-webkit-media-text-track-region-container {
-    position: relative;
-
-    display: flex;
-    flex-flow: column;
-    flex-direction: column;
-}
-
-video::-webkit-media-text-track-region-container.scrolling {
-    transition: top 433ms linear;
-}
-
-
-video::-webkit-media-text-track-display {
-    position: absolute;
-    overflow: hidden;
-    white-space: pre-wrap;
-    -webkit-box-sizing: border-box;
-    flex: 0 0 auto;
-}
-
-video::cue(:future) {
-    color: gray;
-}
-
-video::cue(b) {
-    font-weight: bold;
-}
-
-video::cue(u) {
-    text-decoration: underline;
-}
-
-video::cue(i) {
-    font-style: italic;
-}
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/media_controls_resources.grd b/third_party/WebKit/Source/modules/media_controls/resources/media_controls_resources.grd
index ec3c11b..f9c3d46 100644
--- a/third_party/WebKit/Source/modules/media_controls/resources/media_controls_resources.grd
+++ b/third_party/WebKit/Source/modules/media_controls/resources/media_controls_resources.grd
@@ -9,31 +9,32 @@
   </outputs>
   <release seq="1">
     <structures fallback_to_low_resolution="true">
-      <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_PAUSE_BUTTON" file="mediaplayer_pause.png" />
-      <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_PLAY_BUTTON" file="mediaplayer_play.png" />
-      <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_SOUND_NOT_MUTED_BUTTON" file="mediaplayer_sound_not_muted.png" />
-      <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_SOUND_MUTED_BUTTON" file="mediaplayer_sound_muted.png" />
-      <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_SLIDER_THUMB" file="mediaplayer_slider_thumb.png" />
-      <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB" file="mediaplayer_volume_slider_thumb.png" />
-      <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON" file="mediaplayer_closedcaption.png" />
-      <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_DISABLED" file="mediaplayer_closedcaption_disabled.png" />
-      <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_ENTER_FULLSCREEN_BUTTON" file="mediaplayer_enter_fullscreen.png" />
-      <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_EXIT_FULLSCREEN_BUTTON" file="mediaplayer_exit_fullscreen.png" />
-      <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_CAST_BUTTON_OFF" file="mediaplayer_cast_off.png" />
-      <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_CAST_BUTTON_ON" file="mediaplayer_cast_on.png" />
-      <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_OVERLAY_CAST_BUTTON_OFF" file="mediaplayer_overlay_cast_off.png" />
-      <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_OVERLAY_CAST_BUTTON_ON" file="mediaplayer_overlay_cast_on.png" />
-      <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_OVERLAY_PLAY_BUTTON" file="mediaplayer_overlay_play.png" />
-      <structure type="chrome_scaled_image" name="IDR_MEDIA_REMOTING_CAST_ICON" file="mediaremoting_cast.png" />
-      <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_TRACKSELECTION_CHECKMARK" file="mediaplayer_trackselection_checkmark.png" />
-      <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_CLOSEDCAPTIONS_ICON" file="mediaplayer_closedcaptions_icon.png" />
-      <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_OVERFLOW_MENU_ICON" file="mediaplayer_overflow_menu.png" />
-      <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_DOWNLOAD_ICON" file="mediaplayer_download.png" />
-      <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_SUBTITLES_ICON" file="mediaplayer_subtitles_icon.png" />
+      <structure type="chrome_scaled_image" name="IDR_LEGACY_MEDIAPLAYER_PAUSE_BUTTON" file="legacy/mediaplayer_pause.png" />
+      <structure type="chrome_scaled_image" name="IDR_LEGACY_MEDIAPLAYER_PLAY_BUTTON" file="legacy/mediaplayer_play.png" />
+      <structure type="chrome_scaled_image" name="IDR_LEGACY_MEDIAPLAYER_SOUND_NOT_MUTED_BUTTON" file="legacy/mediaplayer_sound_not_muted.png" />
+      <structure type="chrome_scaled_image" name="IDR_LEGACY_MEDIAPLAYER_SOUND_MUTED_BUTTON" file="legacy/mediaplayer_sound_muted.png" />
+      <structure type="chrome_scaled_image" name="IDR_LEGACY_MEDIAPLAYER_SLIDER_THUMB" file="legacy/mediaplayer_slider_thumb.png" />
+      <structure type="chrome_scaled_image" name="IDR_LEGACY_MEDIAPLAYER_VOLUME_SLIDER_THUMB" file="legacy/mediaplayer_volume_slider_thumb.png" />
+      <structure type="chrome_scaled_image" name="IDR_LEGACY_MEDIAPLAYER_CLOSEDCAPTION_BUTTON" file="legacy/mediaplayer_closedcaption.png" />
+      <structure type="chrome_scaled_image" name="IDR_LEGACY_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_DISABLED" file="legacy/mediaplayer_closedcaption_disabled.png" />
+      <structure type="chrome_scaled_image" name="IDR_LEGACY_MEDIAPLAYER_ENTER_FULLSCREEN_BUTTON" file="legacy/mediaplayer_enter_fullscreen.png" />
+      <structure type="chrome_scaled_image" name="IDR_LEGACY_MEDIAPLAYER_EXIT_FULLSCREEN_BUTTON" file="legacy/mediaplayer_exit_fullscreen.png" />
+      <structure type="chrome_scaled_image" name="IDR_LEGACY_MEDIAPLAYER_CAST_BUTTON_OFF" file="legacy/mediaplayer_cast_off.png" />
+      <structure type="chrome_scaled_image" name="IDR_LEGACY_MEDIAPLAYER_CAST_BUTTON_ON" file="legacy/mediaplayer_cast_on.png" />
+      <structure type="chrome_scaled_image" name="IDR_LEGACY_MEDIAPLAYER_OVERLAY_CAST_BUTTON_OFF" file="legacy/mediaplayer_overlay_cast_off.png" />
+      <structure type="chrome_scaled_image" name="IDR_LEGACY_MEDIAPLAYER_OVERLAY_CAST_BUTTON_ON" file="legacy/mediaplayer_overlay_cast_on.png" />
+      <structure type="chrome_scaled_image" name="IDR_LEGACY_MEDIAPLAYER_OVERLAY_PLAY_BUTTON" file="legacy/mediaplayer_overlay_play.png" />
+      <structure type="chrome_scaled_image" name="IDR_LEGACY_MEDIA_REMOTING_CAST_ICON" file="legacy/mediaremoting_cast.png" />
+      <structure type="chrome_scaled_image" name="IDR_LEGACY_MEDIAPLAYER_TRACKSELECTION_CHECKMARK" file="legacy/mediaplayer_trackselection_checkmark.png" />
+      <structure type="chrome_scaled_image" name="IDR_LEGACY_MEDIAPLAYER_CLOSEDCAPTIONS_ICON" file="legacy/mediaplayer_closedcaptions_icon.png" />
+      <structure type="chrome_scaled_image" name="IDR_LEGACY_MEDIAPLAYER_OVERFLOW_MENU_ICON" file="legacy/mediaplayer_overflow_menu.png" />
+      <structure type="chrome_scaled_image" name="IDR_LEGACY_MEDIAPLAYER_DOWNLOAD_ICON" file="legacy/mediaplayer_download.png" />
+      <structure type="chrome_scaled_image" name="IDR_LEGACY_MEDIAPLAYER_SUBTITLES_ICON" file="legacy/mediaplayer_subtitles_icon.png" />
+      <structure type="chrome_html" name="IDR_UASTYLE_LEGACY_MEDIA_CONTROLS_CSS" file="legacyMediaControls.css" flattenhtml="true" />
+      <structure type="chrome_html" name="IDR_UASTYLE_MODERN_MEDIA_CONTROLS_CSS" file="modernMediaControls.css" flattenhtml="true" />
     </structures>
     <includes>
-      <include name="IDR_UASTYLE_MEDIA_CONTROLS_ANDROID_CSS" file="mediaControlsAndroid.css" type="chrome_html" compress="gzip" />
-      <include name="IDR_UASTYLE_MEDIA_CONTROLS_CSS" file="mediaControls.css" type="chrome_html" compress="gzip" />
+      <include name="IDR_UASTYLE_LEGACY_MEDIA_CONTROLS_ANDROID_CSS" file="legacyMediaControlsAndroid.css" type="BINDATA" compress="gzip" />
     </includes>
   </release>
 </grit>
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/modernMediaControls.css b/third_party/WebKit/Source/modules/media_controls/resources/modernMediaControls.css
new file mode 100644
index 0000000..772ad9e
--- /dev/null
+++ b/third_party/WebKit/Source/modules/media_controls/resources/modernMediaControls.css
@@ -0,0 +1,3 @@
+/* Copyright (c) 2017 The Chromium Authors. All rights reserved.
+   Use of this source code is governed by a BSD-style license that can be
+   found in the LICENSE file.*/
diff --git a/third_party/WebKit/Source/modules/mediacapturefromelement/HTMLMediaElementCapture.cpp b/third_party/WebKit/Source/modules/mediacapturefromelement/HTMLMediaElementCapture.cpp
index 1ed71dc..8b89ff7 100644
--- a/third_party/WebKit/Source/modules/mediacapturefromelement/HTMLMediaElementCapture.cpp
+++ b/third_party/WebKit/Source/modules/mediacapturefromelement/HTMLMediaElementCapture.cpp
@@ -28,10 +28,8 @@
   WTF_MAKE_NONCOPYABLE(MediaElementEventListener);
 
  public:
-  MediaElementEventListener(HTMLMediaElement* element, MediaStream* stream)
-      : EventListener(kCPPEventListenerType),
-        media_element_(element),
-        media_stream_(stream) {}
+  MediaElementEventListener(HTMLMediaElement*, MediaStream*);
+  void UpdateSources(ExecutionContext*);
 
   DECLARE_VIRTUAL_TRACE();
 
@@ -44,8 +42,17 @@
 
   Member<HTMLMediaElement> media_element_;
   Member<MediaStream> media_stream_;
+  HeapHashSet<WeakMember<MediaStreamSource>> sources_;
 };
 
+MediaElementEventListener::MediaElementEventListener(HTMLMediaElement* element,
+                                                     MediaStream* stream)
+    : EventListener(kCPPEventListenerType),
+      media_element_(element),
+      media_stream_(stream) {
+  UpdateSources(element->GetExecutionContext());
+}
+
 void MediaElementEventListener::handleEvent(ExecutionContext* context,
                                             Event* event) {
   DVLOG(2) << __func__ << " " << event->type();
@@ -89,11 +96,25 @@
 
   DVLOG(2) << "#videotracks: " << video_tracks.size()
            << " #audiotracks: " << audio_tracks.size();
+
+  UpdateSources(context);
+}
+
+void MediaElementEventListener::UpdateSources(ExecutionContext* context) {
+  for (auto track : media_stream_->getTracks())
+    sources_.insert(track->Component()->Source());
+
+  if (!media_element_->IsMediaDataCORSSameOrigin(
+          context->GetSecurityOrigin())) {
+    for (auto source : sources_)
+      MediaStreamCenter::Instance().DidStopMediaStreamSource(source);
+  }
 }
 
 DEFINE_TRACE(MediaElementEventListener) {
   visitor->Trace(media_element_);
   visitor->Trace(media_stream_);
+  visitor->Trace(sources_);
   EventListener::Trace(visitor);
 }
 
@@ -112,24 +133,36 @@
     return nullptr;
   }
 
+  if (!(element.currentSrc().IsNull() && !element.GetSrcObject()) &&
+      !element.IsMediaDataCORSSameOrigin(
+          element.GetExecutionContext()->GetSecurityOrigin())) {
+    exception_state.ThrowSecurityError(
+        "Cannot capture from element with cross-origin data");
+    return nullptr;
+  }
+
   WebMediaStream web_stream;
   web_stream.Initialize(WebVector<WebMediaStreamTrack>(),
                         WebVector<WebMediaStreamTrack>());
 
-  // create() duplicates the MediaStreamTracks inside |webStream|.
+  // Create() duplicates the MediaStreamTracks inside |webStream|.
   MediaStream* stream =
       MediaStream::Create(element.GetExecutionContext(), web_stream);
 
-  EventListener* listener = new MediaElementEventListener(&element, stream);
+  MediaElementEventListener* listener =
+      new MediaElementEventListener(&element, stream);
   element.addEventListener(EventTypeNames::loadedmetadata, listener, false);
   element.addEventListener(EventTypeNames::ended, listener, false);
 
   // If |element| is actually playing a MediaStream, just clone it.
   if (element.GetLoadType() == WebMediaPlayer::kLoadTypeMediaStream) {
-    return MediaStream::Create(
-        element.GetExecutionContext(),
-        MediaStreamRegistry::Registry().LookupMediaStreamDescriptor(
-            element.currentSrc().GetString()));
+    MediaStreamDescriptor* const descriptor =
+        element.currentSrc().IsNull()
+            ? element.GetSrcObject()
+            : MediaStreamRegistry::Registry().LookupMediaStreamDescriptor(
+                  element.currentSrc().GetString());
+    DCHECK(descriptor);
+    return MediaStream::Create(element.GetExecutionContext(), descriptor);
   }
 
   if (element.HasVideo()) {
@@ -140,6 +173,7 @@
     Platform::Current()->CreateHTMLAudioElementCapturer(
         &web_stream, element.GetWebMediaPlayer());
   }
+  listener->UpdateSources(element.GetExecutionContext());
 
   // If element.currentSrc().isNull() then |stream| will have no tracks, those
   // will be added eventually afterwards via MediaElementEventListener.
diff --git a/third_party/WebKit/Source/modules/mediastream/MediaConstraintsImpl.cpp b/third_party/WebKit/Source/modules/mediastream/MediaConstraintsImpl.cpp
index 9c104cf..85e7d92e 100644
--- a/third_party/WebKit/Source/modules/mediastream/MediaConstraintsImpl.cpp
+++ b/third_party/WebKit/Source/modules/mediastream/MediaConstraintsImpl.cpp
@@ -506,18 +506,18 @@
 void CopyLongConstraint(const LongOrConstrainLongRange& blink_union_form,
                         NakedValueDisposition naked_treatment,
                         LongConstraint& web_form) {
-  if (blink_union_form.isLong()) {
+  if (blink_union_form.IsLong()) {
     switch (naked_treatment) {
       case NakedValueDisposition::kTreatAsIdeal:
-        web_form.SetIdeal(blink_union_form.getAsLong());
+        web_form.SetIdeal(blink_union_form.GetAsLong());
         break;
       case NakedValueDisposition::kTreatAsExact:
-        web_form.SetExact(blink_union_form.getAsLong());
+        web_form.SetExact(blink_union_form.GetAsLong());
         break;
     }
     return;
   }
-  const auto& blink_form = blink_union_form.getAsConstrainLongRange();
+  const auto& blink_form = blink_union_form.GetAsConstrainLongRange();
   if (blink_form.hasMin()) {
     web_form.SetMin(blink_form.min());
   }
@@ -535,18 +535,18 @@
 void CopyDoubleConstraint(const DoubleOrConstrainDoubleRange& blink_union_form,
                           NakedValueDisposition naked_treatment,
                           DoubleConstraint& web_form) {
-  if (blink_union_form.isDouble()) {
+  if (blink_union_form.IsDouble()) {
     switch (naked_treatment) {
       case NakedValueDisposition::kTreatAsIdeal:
-        web_form.SetIdeal(blink_union_form.getAsDouble());
+        web_form.SetIdeal(blink_union_form.GetAsDouble());
         break;
       case NakedValueDisposition::kTreatAsExact:
-        web_form.SetExact(blink_union_form.getAsDouble());
+        web_form.SetExact(blink_union_form.GetAsDouble());
         break;
     }
     return;
   }
-  const auto& blink_form = blink_union_form.getAsConstrainDoubleRange();
+  const auto& blink_form = blink_union_form.GetAsConstrainDoubleRange();
   if (blink_form.hasMin()) {
     web_form.SetMin(blink_form.min());
   }
@@ -566,42 +566,42 @@
         blink_union_form,
     NakedValueDisposition naked_treatment,
     StringConstraint& web_form) {
-  if (blink_union_form.isString()) {
+  if (blink_union_form.IsString()) {
     switch (naked_treatment) {
       case NakedValueDisposition::kTreatAsIdeal:
-        web_form.SetIdeal(Vector<String>(1, blink_union_form.getAsString()));
+        web_form.SetIdeal(Vector<String>(1, blink_union_form.GetAsString()));
         break;
       case NakedValueDisposition::kTreatAsExact:
-        web_form.SetExact(Vector<String>(1, blink_union_form.getAsString()));
+        web_form.SetExact(Vector<String>(1, blink_union_form.GetAsString()));
 
         break;
     }
     return;
   }
-  if (blink_union_form.isStringSequence()) {
+  if (blink_union_form.IsStringSequence()) {
     switch (naked_treatment) {
       case NakedValueDisposition::kTreatAsIdeal:
-        web_form.SetIdeal(blink_union_form.getAsStringSequence());
+        web_form.SetIdeal(blink_union_form.GetAsStringSequence());
         break;
       case NakedValueDisposition::kTreatAsExact:
-        web_form.SetExact(blink_union_form.getAsStringSequence());
+        web_form.SetExact(blink_union_form.GetAsStringSequence());
         break;
     }
     return;
   }
-  const auto& blink_form = blink_union_form.getAsConstrainDOMStringParameters();
+  const auto& blink_form = blink_union_form.GetAsConstrainDOMStringParameters();
   if (blink_form.hasIdeal()) {
-    if (blink_form.ideal().isStringSequence()) {
-      web_form.SetIdeal(blink_form.ideal().getAsStringSequence());
-    } else if (blink_form.ideal().isString()) {
-      web_form.SetIdeal(Vector<String>(1, blink_form.ideal().getAsString()));
+    if (blink_form.ideal().IsStringSequence()) {
+      web_form.SetIdeal(blink_form.ideal().GetAsStringSequence());
+    } else if (blink_form.ideal().IsString()) {
+      web_form.SetIdeal(Vector<String>(1, blink_form.ideal().GetAsString()));
     }
   }
   if (blink_form.hasExact()) {
-    if (blink_form.exact().isStringSequence()) {
-      web_form.SetExact(blink_form.exact().getAsStringSequence());
-    } else if (blink_form.exact().isString()) {
-      web_form.SetExact(Vector<String>(1, blink_form.exact().getAsString()));
+    if (blink_form.exact().IsStringSequence()) {
+      web_form.SetExact(blink_form.exact().GetAsStringSequence());
+    } else if (blink_form.exact().IsString()) {
+      web_form.SetExact(Vector<String>(1, blink_form.exact().GetAsString()));
     }
   }
 }
@@ -610,18 +610,18 @@
     const BooleanOrConstrainBooleanParameters& blink_union_form,
     NakedValueDisposition naked_treatment,
     BooleanConstraint& web_form) {
-  if (blink_union_form.isBoolean()) {
+  if (blink_union_form.IsBoolean()) {
     switch (naked_treatment) {
       case NakedValueDisposition::kTreatAsIdeal:
-        web_form.SetIdeal(blink_union_form.getAsBoolean());
+        web_form.SetIdeal(blink_union_form.GetAsBoolean());
         break;
       case NakedValueDisposition::kTreatAsExact:
-        web_form.SetExact(blink_union_form.getAsBoolean());
+        web_form.SetExact(blink_union_form.GetAsBoolean());
         break;
     }
     return;
   }
-  const auto& blink_form = blink_union_form.getAsConstrainBooleanParameters();
+  const auto& blink_form = blink_union_form.GetAsConstrainBooleanParameters();
   if (blink_form.hasIdeal()) {
     web_form.SetIdeal(blink_form.ideal());
   }
@@ -806,7 +806,7 @@
                                      NakedValueDisposition naked_treatment) {
   LongOrConstrainLongRange output_union;
   if (UseNakedNumeric(input, naked_treatment)) {
-    output_union.setLong(GetNakedValue<long>(input, naked_treatment));
+    output_union.SetLong(GetNakedValue<long>(input, naked_treatment));
   } else if (!input.IsEmpty()) {
     ConstrainLongRange output;
     if (input.HasExact())
@@ -817,7 +817,7 @@
       output.setMax(input.Max());
     if (input.HasIdeal())
       output.setIdeal(input.Ideal());
-    output_union.setConstrainLongRange(output);
+    output_union.SetConstrainLongRange(output);
   }
   return output_union;
 }
@@ -827,7 +827,7 @@
     NakedValueDisposition naked_treatment) {
   DoubleOrConstrainDoubleRange output_union;
   if (UseNakedNumeric(input, naked_treatment)) {
-    output_union.setDouble(GetNakedValue<double>(input, naked_treatment));
+    output_union.SetDouble(GetNakedValue<double>(input, naked_treatment));
   } else if (!input.IsEmpty()) {
     ConstrainDoubleRange output;
     if (input.HasExact())
@@ -838,7 +838,7 @@
       output.setMin(input.Min());
     if (input.HasMax())
       output.setMax(input.Max());
-    output_union.setConstrainDoubleRange(output);
+    output_union.SetConstrainDoubleRange(output);
   }
   return output_union;
 }
@@ -850,9 +850,9 @@
     Vector<String> buffer;
     for (const auto& scanner : input)
       buffer.push_back(scanner);
-    the_strings.setStringSequence(buffer);
+    the_strings.SetStringSequence(buffer);
   } else if (input.size() > 0) {
-    the_strings.setString(input[0]);
+    the_strings.SetString(input[0]);
   }
   return the_strings;
 }
@@ -868,9 +868,9 @@
       Vector<String> buffer;
       for (const auto& scanner : input_buffer)
         buffer.push_back(scanner);
-      output_union.setStringSequence(buffer);
+      output_union.SetStringSequence(buffer);
     } else if (input_buffer.size() > 0) {
-      output_union.setString(input_buffer[0]);
+      output_union.SetString(input_buffer[0]);
     }
   } else if (!input.IsEmpty()) {
     ConstrainDOMStringParameters output;
@@ -878,7 +878,7 @@
       output.setExact(ConvertStringSequence(input.Exact()));
     if (input.HasIdeal())
       output.setIdeal(ConvertStringSequence(input.Ideal()));
-    output_union.setConstrainDOMStringParameters(output);
+    output_union.SetConstrainDOMStringParameters(output);
   }
   return output_union;
 }
@@ -888,14 +888,14 @@
     NakedValueDisposition naked_treatment) {
   BooleanOrConstrainBooleanParameters output_union;
   if (UseNakedNonNumeric(input, naked_treatment)) {
-    output_union.setBoolean(GetNakedValue<bool>(input, naked_treatment));
+    output_union.SetBoolean(GetNakedValue<bool>(input, naked_treatment));
   } else if (!input.IsEmpty()) {
     ConstrainBooleanParameters output;
     if (input.HasExact())
       output.setExact(input.Exact());
     if (input.HasIdeal())
       output.setIdeal(input.Ideal());
-    output_union.setConstrainBooleanParameters(output);
+    output_union.SetConstrainBooleanParameters(output);
   }
   return output_union;
 }
diff --git a/third_party/WebKit/Source/modules/mediastream/MediaConstraintsTest.cpp b/third_party/WebKit/Source/modules/mediastream/MediaConstraintsTest.cpp
index b79eb4cd..7ee872f77f 100644
--- a/third_party/WebKit/Source/modules/mediastream/MediaConstraintsTest.cpp
+++ b/third_party/WebKit/Source/modules/mediastream/MediaConstraintsTest.cpp
@@ -136,8 +136,8 @@
   input.Initialize(basic, advanced);
   MediaConstraintsImpl::ConvertConstraints(input, output);
   ASSERT_TRUE(output.hasFacingMode());
-  ASSERT_TRUE(output.facingMode().isString());
-  EXPECT_EQ("foo", output.facingMode().getAsString());
+  ASSERT_TRUE(output.facingMode().IsString());
+  EXPECT_EQ("foo", output.facingMode().GetAsString());
 }
 
 TEST(MediaTrackConstraintsTest, ConvertWebDoubleStringConstraint) {
@@ -154,8 +154,8 @@
   input.Initialize(basic, advanced);
   MediaConstraintsImpl::ConvertConstraints(input, output);
   ASSERT_TRUE(output.hasFacingMode());
-  ASSERT_TRUE(output.facingMode().isStringSequence());
-  auto out_buffer = output.facingMode().getAsStringSequence();
+  ASSERT_TRUE(output.facingMode().IsStringSequence());
+  auto out_buffer = output.facingMode().GetAsStringSequence();
   EXPECT_EQ("foo", out_buffer[0]);
   EXPECT_EQ("bar", out_buffer[1]);
 }
@@ -164,7 +164,7 @@
   MediaTrackConstraints input;
   WebMediaConstraints output;
   StringOrStringSequenceOrConstrainDOMStringParameters parameter;
-  parameter.setString("foo");
+  parameter.SetString("foo");
   input.setFacingMode(parameter);
   output = MediaConstraintsImpl::ConvertConstraintsToWeb(input);
   ASSERT_TRUE(output.Basic().facing_mode.HasIdeal());
@@ -178,9 +178,9 @@
   StringOrStringSequenceOrConstrainDOMStringParameters parameter;
   ConstrainDOMStringParameters subparameter;
   StringOrStringSequence inner_string;
-  inner_string.setString("foo");
+  inner_string.SetString("foo");
   subparameter.setIdeal(inner_string);
-  parameter.setConstrainDOMStringParameters(subparameter);
+  parameter.SetConstrainDOMStringParameters(subparameter);
   input.setFacingMode(parameter);
   output = MediaConstraintsImpl::ConvertConstraintsToWeb(input);
   ASSERT_TRUE(output.Basic().facing_mode.HasIdeal());
@@ -191,15 +191,15 @@
   MediaTrackConstraints recycled;
   MediaConstraintsImpl::ConvertConstraints(output, recycled);
   ASSERT_TRUE(recycled.hasFacingMode());
-  ASSERT_TRUE(recycled.facingMode().isString());
-  ASSERT_EQ("foo", recycled.facingMode().getAsString());
+  ASSERT_TRUE(recycled.facingMode().IsString());
+  ASSERT_EQ("foo", recycled.facingMode().GetAsString());
 }
 
 TEST(MediaTrackConstraintsTest, NakedIsExactInAdvanced) {
   MediaTrackConstraints input;
   WebMediaConstraints output;
   StringOrStringSequenceOrConstrainDOMStringParameters parameter;
-  parameter.setString("foo");
+  parameter.SetString("foo");
   input.setFacingMode(parameter);
   HeapVector<MediaTrackConstraintSet> advanced(1);
   advanced[0].setFacingMode(parameter);
@@ -246,19 +246,19 @@
   MediaTrackConstraintSet element2 = output.advanced()[1];
 
   ASSERT_TRUE(output.hasFacingMode());
-  ASSERT_TRUE(output.facingMode().isString());
-  EXPECT_EQ("ideal", output.facingMode().getAsString());
+  ASSERT_TRUE(output.facingMode().IsString());
+  EXPECT_EQ("ideal", output.facingMode().GetAsString());
 
   ASSERT_TRUE(element1.hasFacingMode());
-  ASSERT_TRUE(element1.facingMode().isConstrainDOMStringParameters());
+  ASSERT_TRUE(element1.facingMode().IsConstrainDOMStringParameters());
   EXPECT_EQ("ideal", element1.facingMode()
-                         .getAsConstrainDOMStringParameters()
+                         .GetAsConstrainDOMStringParameters()
                          .ideal()
-                         .getAsString());
+                         .GetAsString());
 
   ASSERT_TRUE(element2.hasFacingMode());
-  ASSERT_TRUE(element2.facingMode().isString());
-  EXPECT_EQ("exact", element2.facingMode().getAsString());
+  ASSERT_TRUE(element2.facingMode().IsString());
+  EXPECT_EQ("exact", element2.facingMode().GetAsString());
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp b/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp
index e08cc59..e21a6ec 100644
--- a/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp
+++ b/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp
@@ -308,14 +308,14 @@
   WebMediaConstraints constraints;
 
   Dictionary constraints_dictionary;
-  if (options.isNull()) {
+  if (options.IsNull()) {
     // Do nothing.
-  } else if (options.isMediaTrackConstraints()) {
+  } else if (options.IsMediaTrackConstraints()) {
     constraints = MediaConstraintsImpl::Create(
-        context, options.getAsMediaTrackConstraints(), error_state);
+        context, options.GetAsMediaTrackConstraints(), error_state);
   } else {
-    DCHECK(options.isBoolean());
-    if (options.getAsBoolean()) {
+    DCHECK(options.IsBoolean());
+    if (options.GetAsBoolean()) {
       constraints = MediaConstraintsImpl::Create();
     }
   }
diff --git a/third_party/WebKit/Source/modules/modules_idl_files.gni b/third_party/WebKit/Source/modules/modules_idl_files.gni
index c29c11f..4e16c54 100644
--- a/third_party/WebKit/Source/modules/modules_idl_files.gni
+++ b/third_party/WebKit/Source/modules/modules_idl_files.gni
@@ -304,6 +304,8 @@
                     "vr/latest/VR.idl",
                     "vr/latest/VRDevice.idl",
                     "vr/latest/VRDeviceEvent.idl",
+                    "vr/latest/VRSession.idl",
+                    "vr/latest/VRSessionEvent.idl",
                     "webaudio/AnalyserNode.idl",
                     "webaudio/AudioBuffer.idl",
                     "webaudio/AudioBufferSourceNode.idl",
@@ -567,6 +569,7 @@
                     "vr/VRLayerInit.idl",
                     "vr/latest/VRDeviceEventInit.idl",
                     "vr/latest/VRSessionCreationOptions.idl",
+                    "vr/latest/VRSessionEventInit.idl",
                     "webaudio/AnalyserOptions.idl",
                     "webaudio/AudioBufferOptions.idl",
                     "webaudio/AudioBufferSourceOptions.idl",
diff --git a/third_party/WebKit/Source/modules/nfc/MessageCallback.h b/third_party/WebKit/Source/modules/nfc/MessageCallback.h
index 8f7392f3..cc753a2 100644
--- a/third_party/WebKit/Source/modules/nfc/MessageCallback.h
+++ b/third_party/WebKit/Source/modules/nfc/MessageCallback.h
@@ -21,7 +21,7 @@
   void SetScriptState(ScriptState* script_state) {
     script_state_ = script_state;
   }
-  ScriptState* GetScriptState() const { return script_state_.Get(); }
+  ScriptState* GetScriptState() const { return script_state_.get(); }
 
  private:
   RefPtr<ScriptState> script_state_;
diff --git a/third_party/WebKit/Source/modules/nfc/NFC.cpp b/third_party/WebKit/Source/modules/nfc/NFC.cpp
index 23088c7..fcd5547 100644
--- a/third_party/WebKit/Source/modules/nfc/NFC.cpp
+++ b/third_party/WebKit/Source/modules/nfc/NFC.cpp
@@ -291,14 +291,14 @@
 template <>
 struct TypeConverter<NFCMessagePtr, blink::NFCPushMessage> {
   static NFCMessagePtr Convert(const blink::NFCPushMessage& message) {
-    if (message.isString())
-      return NFCMessage::From(message.getAsString());
+    if (message.IsString())
+      return NFCMessage::From(message.GetAsString());
 
-    if (message.isNFCMessage())
-      return NFCMessage::From(message.getAsNFCMessage());
+    if (message.IsNFCMessage())
+      return NFCMessage::From(message.GetAsNFCMessage());
 
-    if (message.isArrayBuffer())
-      return NFCMessage::From(message.getAsArrayBuffer());
+    if (message.IsArrayBuffer())
+      return NFCMessage::From(message.GetAsArrayBuffer());
 
     NOTREACHED();
     return nullptr;
@@ -502,16 +502,16 @@
     ScriptState* script_state,
     const NFCPushMessage& push_message) {
   // If NFCPushMessage of invalid type, reject promise with TypeError
-  if (!push_message.isNFCMessage() && !push_message.isString() &&
-      !push_message.isArrayBuffer()) {
+  if (!push_message.IsNFCMessage() && !push_message.IsString() &&
+      !push_message.IsArrayBuffer()) {
     return RejectWithTypeError(script_state,
                                "Invalid NFCPushMessage type was provided.");
   }
 
-  if (push_message.isNFCMessage()) {
+  if (push_message.IsNFCMessage()) {
     // https://w3c.github.io/web-nfc/#the-push-method
     // If NFCMessage.records is empty, reject promise with TypeError
-    const NFCMessage& message = push_message.getAsNFCMessage();
+    const NFCMessage& message = push_message.GetAsNFCMessage();
     if (!message.hasRecords() || message.records().IsEmpty()) {
       return RejectWithTypeError(script_state,
                                  "Empty NFCMessage was provided.");
diff --git a/third_party/WebKit/Source/modules/notifications/NotificationDataTest.cpp b/third_party/WebKit/Source/modules/notifications/NotificationDataTest.cpp
index 8af7a6b..e8baf71 100644
--- a/third_party/WebKit/Source/modules/notifications/NotificationDataTest.cpp
+++ b/third_party/WebKit/Source/modules/notifications/NotificationDataTest.cpp
@@ -82,7 +82,7 @@
     vibration_pattern.push_back(kNotificationVibration[i]);
 
   UnsignedLongOrUnsignedLongSequence vibration_sequence;
-  vibration_sequence.setUnsignedLongSequence(vibration_pattern);
+  vibration_sequence.SetUnsignedLongSequence(vibration_pattern);
 
   HeapVector<NotificationAction> actions;
   for (size_t i = 0; i < Notification::maxActions(); ++i) {
@@ -158,7 +158,7 @@
     vibration_pattern.push_back(kNotificationVibration[i]);
 
   UnsignedLongOrUnsignedLongSequence vibration_sequence;
-  vibration_sequence.setUnsignedLongSequence(vibration_pattern);
+  vibration_sequence.SetUnsignedLongSequence(vibration_pattern);
 
   NotificationOptions options;
   options.setVibrate(vibration_sequence);
@@ -242,7 +242,7 @@
     unnormalized_pattern.push_back(kNotificationVibrationUnnormalized[i]);
 
   UnsignedLongOrUnsignedLongSequence vibration_sequence;
-  vibration_sequence.setUnsignedLongSequence(unnormalized_pattern);
+  vibration_sequence.SetUnsignedLongSequence(unnormalized_pattern);
 
   NotificationOptions options;
   options.setVibrate(vibration_sequence);
diff --git a/third_party/WebKit/Source/modules/notifications/ServiceWorkerRegistrationNotifications.cpp b/third_party/WebKit/Source/modules/notifications/ServiceWorkerRegistrationNotifications.cpp
index da4ed1f..eedf0b5 100644
--- a/third_party/WebKit/Source/modules/notifications/ServiceWorkerRegistrationNotifications.cpp
+++ b/third_party/WebKit/Source/modules/notifications/ServiceWorkerRegistrationNotifications.cpp
@@ -191,7 +191,7 @@
   DCHECK(notification_manager);
 
   notification_manager->ShowPersistent(
-      WebSecurityOrigin(origin.Get()), data, loader->GetResources(),
+      WebSecurityOrigin(origin.get()), data, loader->GetResources(),
       registration_->WebRegistration(), std::move(callbacks));
   loaders_.erase(loader);
 }
diff --git a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp
index bf2c9b2..4af48c3 100644
--- a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp
+++ b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp
@@ -165,7 +165,7 @@
 
 void OffscreenCanvasRenderingContext2D::SetOffscreenCanvasGetContextResult(
     OffscreenRenderingContext& result) {
-  result.setOffscreenCanvasRenderingContext2D(this);
+  result.SetOffscreenCanvasRenderingContext2D(this);
 }
 
 bool OffscreenCanvasRenderingContext2D::ParseColorOrCurrentColor(
diff --git a/third_party/WebKit/Source/modules/payments/PaymentEventDataConversion.cpp b/third_party/WebKit/Source/modules/payments/PaymentEventDataConversion.cpp
index 9f4e998..8571a44 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentEventDataConversion.cpp
+++ b/third_party/WebKit/Source/modules/payments/PaymentEventDataConversion.cpp
@@ -43,7 +43,7 @@
     supported_methods.push_back(web_method);
   }
   modifier.setSupportedMethods(
-      StringOrStringSequence::fromStringSequence(supported_methods));
+      StringOrStringSequence::FromStringSequence(supported_methods));
   modifier.setTotal(ToPaymentItem(web_modifier.total));
   HeapVector<PaymentItem> additional_display_items;
   for (const auto& web_item : web_modifier.additional_display_items) {
@@ -77,7 +77,7 @@
     supported_methods.push_back(method);
   }
   method_data.setSupportedMethods(
-      StringOrStringSequence::fromStringSequence(supported_methods));
+      StringOrStringSequence::FromStringSequence(supported_methods));
   method_data.setData(
       StringDataToScriptValue(script_state, web_method_data.stringified_data));
   return method_data;
diff --git a/third_party/WebKit/Source/modules/payments/PaymentEventDataConversionTest.cpp b/third_party/WebKit/Source/modules/payments/PaymentEventDataConversionTest.cpp
index de404e5..2f4b632 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentEventDataConversionTest.cpp
+++ b/third_party/WebKit/Source/modules/payments/PaymentEventDataConversionTest.cpp
@@ -73,12 +73,12 @@
   ASSERT_EQ(1UL, data.methodData()
                      .front()
                      .supportedMethods()
-                     .getAsStringSequence()
+                     .GetAsStringSequence()
                      .size());
   ASSERT_EQ("foo", data.methodData()
                        .front()
                        .supportedMethods()
-                       .getAsStringSequence()
+                       .GetAsStringSequence()
                        .front());
   ASSERT_TRUE(data.methodData().front().hasData());
   ASSERT_TRUE(data.methodData().front().data().IsObject());
@@ -114,12 +114,12 @@
   ASSERT_EQ(1UL, data.methodData()
                      .front()
                      .supportedMethods()
-                     .getAsStringSequence()
+                     .GetAsStringSequence()
                      .size());
   ASSERT_EQ("foo", data.methodData()
                        .front()
                        .supportedMethods()
-                       .getAsStringSequence()
+                       .GetAsStringSequence()
                        .front());
   ASSERT_TRUE(data.methodData().front().hasData());
   ASSERT_TRUE(data.methodData().front().data().IsObject());
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp b/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
index 5e9c113..705f912 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
+++ b/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
@@ -588,11 +588,11 @@
     }
 
     Vector<String> supported_methods;
-    if (modifier.supportedMethods().isString()) {
-      supported_methods.push_back(modifier.supportedMethods().getAsString());
+    if (modifier.supportedMethods().IsString()) {
+      supported_methods.push_back(modifier.supportedMethods().GetAsString());
     }
-    if (modifier.supportedMethods().isStringSequence()) {
-      supported_methods = modifier.supportedMethods().getAsStringSequence();
+    if (modifier.supportedMethods().IsStringSequence()) {
+      supported_methods = modifier.supportedMethods().GetAsStringSequence();
       if (supported_methods.size() > 1) {
         Deprecation::CountDeprecation(
             &execution_context,
@@ -741,13 +741,13 @@
 
   for (const PaymentMethodData payment_method_data : input) {
     Vector<String> supported_methods;
-    if (payment_method_data.supportedMethods().isString()) {
+    if (payment_method_data.supportedMethods().IsString()) {
       supported_methods.push_back(
-          payment_method_data.supportedMethods().getAsString());
+          payment_method_data.supportedMethods().GetAsString());
     }
-    if (payment_method_data.supportedMethods().isStringSequence()) {
+    if (payment_method_data.supportedMethods().IsStringSequence()) {
       supported_methods =
-          payment_method_data.supportedMethods().getAsStringSequence();
+          payment_method_data.supportedMethods().GetAsStringSequence();
       if (supported_methods.size() > 1) {
         Deprecation::CountDeprecation(
             &execution_context,
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.cpp b/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.cpp
index 06b9946..9366273 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.cpp
+++ b/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.cpp
@@ -81,7 +81,7 @@
   }
 
   if (!context->GetSecurityOrigin()->IsSameSchemeHostPortAndSuborigin(
-          SecurityOrigin::Create(parsed_url_to_open).Get())) {
+          SecurityOrigin::Create(parsed_url_to_open).get())) {
     resolver->Resolve(v8::Null(script_state->GetIsolate()));
     return promise;
   }
diff --git a/third_party/WebKit/Source/modules/payments/PaymentTestHelper.cpp b/third_party/WebKit/Source/modules/payments/PaymentTestHelper.cpp
index 5fa462d8..b8cf5f0 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentTestHelper.cpp
+++ b/third_party/WebKit/Source/modules/payments/PaymentTestHelper.cpp
@@ -136,7 +136,7 @@
 
   PaymentDetailsModifier modifier;
   StringOrStringSequence supportedMethods;
-  supportedMethods.setStringSequence(Vector<String>(1, "foo"));
+  supportedMethods.SetStringSequence(Vector<String>(1, "foo"));
   modifier.setSupportedMethods(supportedMethods);
   modifier.setTotal(total);
   modifier.setAdditionalDisplayItems(HeapVector<PaymentItem>(1, item));
@@ -194,7 +194,7 @@
 HeapVector<PaymentMethodData> BuildPaymentMethodDataForTest() {
   HeapVector<PaymentMethodData> method_data(1, PaymentMethodData());
   StringOrStringSequence supportedMethods;
-  supportedMethods.setStringSequence(Vector<String>(1, "foo"));
+  supportedMethods.SetStringSequence(Vector<String>(1, "foo"));
   method_data[0].setSupportedMethods(supportedMethods);
   return method_data;
 }
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.cpp b/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.cpp
index 76cc5c4..0ed49ad3 100644
--- a/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.cpp
+++ b/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.cpp
@@ -150,14 +150,14 @@
 
 bool IsIceCandidateMissingSdp(
     const RTCIceCandidateInitOrRTCIceCandidate& candidate) {
-  if (candidate.isRTCIceCandidateInit()) {
+  if (candidate.IsRTCIceCandidateInit()) {
     const RTCIceCandidateInit& ice_candidate_init =
-        candidate.getAsRTCIceCandidateInit();
+        candidate.GetAsRTCIceCandidateInit();
     return !ice_candidate_init.hasSdpMid() &&
            !ice_candidate_init.hasSdpMLineIndex();
   }
 
-  DCHECK(candidate.isRTCIceCandidate());
+  DCHECK(candidate.IsRTCIceCandidate());
   return false;
 }
 
@@ -184,10 +184,10 @@
 WebRTCICECandidate ConvertToWebRTCIceCandidate(
     ExecutionContext* context,
     const RTCIceCandidateInitOrRTCIceCandidate& candidate) {
-  DCHECK(!candidate.isNull());
-  if (candidate.isRTCIceCandidateInit()) {
+  DCHECK(!candidate.IsNull());
+  if (candidate.IsRTCIceCandidateInit()) {
     const RTCIceCandidateInit& ice_candidate_init =
-        candidate.getAsRTCIceCandidateInit();
+        candidate.GetAsRTCIceCandidateInit();
     // TODO(guidou): Change default value to -1. crbug.com/614958.
     unsigned short sdp_m_line_index = 0;
     if (ice_candidate_init.hasSdpMLineIndex()) {
@@ -200,8 +200,8 @@
                               ice_candidate_init.sdpMid(), sdp_m_line_index);
   }
 
-  DCHECK(candidate.isRTCIceCandidate());
-  return candidate.getAsRTCIceCandidate()->WebCandidate();
+  DCHECK(candidate.IsRTCIceCandidate());
+  return candidate.GetAsRTCIceCandidate()->WebCandidate();
 }
 
 // Helper class for RTCPeerConnection::generateCertificate.
@@ -281,11 +281,11 @@
       if (ice_server.hasURLs()) {
         UseCounter::Count(context, WebFeature::kRTCIceServerURLs);
         const StringOrStringSequence& urls = ice_server.urls();
-        if (urls.isString()) {
-          url_strings.push_back(urls.getAsString());
+        if (urls.IsString()) {
+          url_strings.push_back(urls.GetAsString());
         } else {
-          DCHECK(urls.isStringSequence());
-          url_strings = urls.getAsStringSequence();
+          DCHECK(urls.IsStringSequence());
+          url_strings = urls.GetAsStringSequence();
         }
       } else if (ice_server.hasURL()) {
         UseCounter::Count(context, WebFeature::kRTCIceServerURL);
@@ -859,8 +859,8 @@
   // Check if |keygenAlgorithm| contains the optional DOMTimeStamp |expires|
   // attribute.
   Nullable<DOMTimeStamp> expires;
-  if (keygen_algorithm.isDictionary()) {
-    Dictionary keygen_algorithm_dict = keygen_algorithm.getAsDictionary();
+  if (keygen_algorithm.IsDictionary()) {
+    Dictionary keygen_algorithm_dict = keygen_algorithm.GetAsDictionary();
     if (keygen_algorithm_dict.HasProperty("expires", exception_state)) {
       v8::Local<v8::Value> expires_value;
       keygen_algorithm_dict.Get("expires", expires_value);
diff --git a/third_party/WebKit/Source/modules/push_messaging/PushManagerTest.cpp b/third_party/WebKit/Source/modules/push_messaging/PushManagerTest.cpp
index 5cec2d3..a379716 100644
--- a/third_party/WebKit/Source/modules/push_messaging/PushManagerTest.cpp
+++ b/third_party/WebKit/Source/modules/push_messaging/PushManagerTest.cpp
@@ -30,7 +30,7 @@
 TEST(PushManagerTest, ValidSenderKey) {
   PushSubscriptionOptionsInit options;
   options.setApplicationServerKey(
-      ArrayBufferOrArrayBufferView::fromArrayBuffer(DOMArrayBuffer::Create(
+      ArrayBufferOrArrayBufferView::FromArrayBuffer(DOMArrayBuffer::Create(
           kApplicationServerKey, kApplicationServerKeyLength)));
 
   DummyExceptionStateForTesting exception_state;
@@ -55,7 +55,7 @@
   uint8_t sender_key[kMaxKeyLength + 1];
   memset(sender_key, 0, sizeof(sender_key));
   PushSubscriptionOptionsInit options;
-  options.setApplicationServerKey(ArrayBufferOrArrayBufferView::fromArrayBuffer(
+  options.setApplicationServerKey(ArrayBufferOrArrayBufferView::FromArrayBuffer(
       DOMArrayBuffer::Create(sender_key, kMaxKeyLength + 1)));
 
   DummyExceptionStateForTesting exception_state;
diff --git a/third_party/WebKit/Source/modules/push_messaging/PushMessageData.cpp b/third_party/WebKit/Source/modules/push_messaging/PushMessageData.cpp
index 265f92f..8847601 100644
--- a/third_party/WebKit/Source/modules/push_messaging/PushMessageData.cpp
+++ b/third_party/WebKit/Source/modules/push_messaging/PushMessageData.cpp
@@ -26,28 +26,28 @@
   if (message_string.IsNull())
     return nullptr;
   return PushMessageData::Create(
-      ArrayBufferOrArrayBufferViewOrUSVString::fromUSVString(message_string));
+      ArrayBufferOrArrayBufferViewOrUSVString::FromUSVString(message_string));
 }
 
 PushMessageData* PushMessageData::Create(
     const ArrayBufferOrArrayBufferViewOrUSVString& message_data) {
-  if (message_data.isArrayBuffer() || message_data.isArrayBufferView()) {
+  if (message_data.IsArrayBuffer() || message_data.IsArrayBufferView()) {
     DOMArrayBuffer* buffer =
-        message_data.isArrayBufferView()
-            ? message_data.getAsArrayBufferView().View()->buffer()
-            : message_data.getAsArrayBuffer();
+        message_data.IsArrayBufferView()
+            ? message_data.GetAsArrayBufferView().View()->buffer()
+            : message_data.GetAsArrayBuffer();
 
     return new PushMessageData(static_cast<const char*>(buffer->Data()),
                                buffer->ByteLength());
   }
 
-  if (message_data.isUSVString()) {
+  if (message_data.IsUSVString()) {
     CString encoded_string = UTF8Encoding().Encode(
-        message_data.getAsUSVString(), WTF::kEntitiesForUnencodables);
+        message_data.GetAsUSVString(), WTF::kEntitiesForUnencodables);
     return new PushMessageData(encoded_string.data(), encoded_string.length());
   }
 
-  DCHECK(message_data.isNull());
+  DCHECK(message_data.IsNull());
   return nullptr;
 }
 
diff --git a/third_party/WebKit/Source/modules/push_messaging/PushSubscriptionOptions.cpp b/third_party/WebKit/Source/modules/push_messaging/PushSubscriptionOptions.cpp
index ded32f3..43915e7 100644
--- a/third_party/WebKit/Source/modules/push_messaging/PushSubscriptionOptions.cpp
+++ b/third_party/WebKit/Source/modules/push_messaging/PushSubscriptionOptions.cpp
@@ -25,14 +25,14 @@
   unsigned char* input;
   int length;
   // Convert the input array into a string of bytes.
-  if (application_server_key.isArrayBuffer()) {
+  if (application_server_key.IsArrayBuffer()) {
     input = static_cast<unsigned char*>(
-        application_server_key.getAsArrayBuffer()->Data());
-    length = application_server_key.getAsArrayBuffer()->ByteLength();
-  } else if (application_server_key.isArrayBufferView()) {
+        application_server_key.GetAsArrayBuffer()->Data());
+    length = application_server_key.GetAsArrayBuffer()->ByteLength();
+  } else if (application_server_key.IsArrayBufferView()) {
     input = static_cast<unsigned char*>(
-        application_server_key.getAsArrayBufferView().View()->buffer()->Data());
-    length = application_server_key.getAsArrayBufferView()
+        application_server_key.GetAsArrayBufferView().View()->buffer()->Data());
+    length = application_server_key.GetAsArrayBufferView()
                  .View()
                  ->buffer()
                  ->ByteLength();
diff --git a/third_party/WebKit/Source/modules/sensor/OrientationSensor.cpp b/third_party/WebKit/Source/modules/sensor/OrientationSensor.cpp
index d291310..3fa2de3 100644
--- a/third_party/WebKit/Source/modules/sensor/OrientationSensor.cpp
+++ b/third_party/WebKit/Source/modules/sensor/OrientationSensor.cpp
@@ -100,12 +100,12 @@
 void OrientationSensor::populateMatrix(
     Float32ArrayOrFloat64ArrayOrDOMMatrix& matrix,
     ExceptionState& exception_state) {
-  if (matrix.isFloat32Array())
-    PopulateMatrixInternal(matrix.getAsFloat32Array().View(), exception_state);
-  else if (matrix.isFloat64Array())
-    PopulateMatrixInternal(matrix.getAsFloat64Array().View(), exception_state);
-  else if (matrix.isDOMMatrix())
-    PopulateMatrixInternal(matrix.getAsDOMMatrix(), exception_state);
+  if (matrix.IsFloat32Array())
+    PopulateMatrixInternal(matrix.GetAsFloat32Array().View(), exception_state);
+  else if (matrix.IsFloat64Array())
+    PopulateMatrixInternal(matrix.GetAsFloat64Array().View(), exception_state);
+  else if (matrix.IsDOMMatrix())
+    PopulateMatrixInternal(matrix.GetAsDOMMatrix(), exception_state);
   else
     NOTREACHED() << "Unexpected rotation matrix type.";
 }
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ExtendableMessageEvent.cpp b/third_party/WebKit/Source/modules/serviceworkers/ExtendableMessageEvent.cpp
index 1456b4c..df2f5ff 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ExtendableMessageEvent.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ExtendableMessageEvent.cpp
@@ -65,12 +65,12 @@
 void ExtendableMessageEvent::source(
     ClientOrServiceWorkerOrMessagePort& result) const {
   if (source_as_client_)
-    result = ClientOrServiceWorkerOrMessagePort::fromClient(source_as_client_);
+    result = ClientOrServiceWorkerOrMessagePort::FromClient(source_as_client_);
   else if (source_as_service_worker_)
-    result = ClientOrServiceWorkerOrMessagePort::fromServiceWorker(
+    result = ClientOrServiceWorkerOrMessagePort::FromServiceWorker(
         source_as_service_worker_);
   else if (source_as_message_port_)
-    result = ClientOrServiceWorkerOrMessagePort::fromMessagePort(
+    result = ClientOrServiceWorkerOrMessagePort::FromMessagePort(
         source_as_message_port_);
   else
     result = ClientOrServiceWorkerOrMessagePort();
@@ -103,12 +103,12 @@
   if (initializer.hasLastEventId())
     last_event_id_ = initializer.lastEventId();
   if (initializer.hasSource()) {
-    if (initializer.source().isClient())
-      source_as_client_ = initializer.source().getAsClient();
-    else if (initializer.source().isServiceWorker())
-      source_as_service_worker_ = initializer.source().getAsServiceWorker();
-    else if (initializer.source().isMessagePort())
-      source_as_message_port_ = initializer.source().getAsMessagePort();
+    if (initializer.source().IsClient())
+      source_as_client_ = initializer.source().GetAsClient();
+    else if (initializer.source().IsServiceWorker())
+      source_as_service_worker_ = initializer.source().GetAsServiceWorker();
+    else if (initializer.source().IsMessagePort())
+      source_as_message_port_ = initializer.source().GetAsMessagePort();
   }
   if (initializer.hasPorts())
     ports_ = new MessagePortArray(initializer.ports());
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ExtendableMessageEvent.h b/third_party/WebKit/Source/modules/serviceworkers/ExtendableMessageEvent.h
index d86274fb..dfb5e14 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ExtendableMessageEvent.h
+++ b/third_party/WebKit/Source/modules/serviceworkers/ExtendableMessageEvent.h
@@ -39,7 +39,7 @@
                                         WaitUntilObserver*);
 
   SerializedScriptValue* SerializedData() const {
-    return serialized_data_.Get();
+    return serialized_data_.get();
   }
   void SetSerializedData(RefPtr<SerializedScriptValue> serialized_data) {
     serialized_data_ = std::move(serialized_data);
diff --git a/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.cpp b/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.cpp
index e75911fd..d22b260e 100644
--- a/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.cpp
+++ b/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.cpp
@@ -50,20 +50,20 @@
   ScriptPromise promise = resolver->Promise();
 
   // ImageDatas cannot be tainted by definition.
-  if (image_source.isImageData())
-    return DetectShapesOnImageData(resolver, image_source.getAsImageData());
+  if (image_source.IsImageData())
+    return DetectShapesOnImageData(resolver, image_source.GetAsImageData());
 
   CanvasImageSource* canvas_image_source;
-  if (image_source.isHTMLImageElement()) {
-    canvas_image_source = image_source.getAsHTMLImageElement();
-  } else if (image_source.isImageBitmap()) {
-    canvas_image_source = image_source.getAsImageBitmap();
-  } else if (image_source.isHTMLVideoElement()) {
-    canvas_image_source = image_source.getAsHTMLVideoElement();
-  } else if (image_source.isHTMLCanvasElement()) {
-    canvas_image_source = image_source.getAsHTMLCanvasElement();
-  } else if (image_source.isOffscreenCanvas()) {
-    canvas_image_source = image_source.getAsOffscreenCanvas();
+  if (image_source.IsHTMLImageElement()) {
+    canvas_image_source = image_source.GetAsHTMLImageElement();
+  } else if (image_source.IsImageBitmap()) {
+    canvas_image_source = image_source.GetAsImageBitmap();
+  } else if (image_source.IsHTMLVideoElement()) {
+    canvas_image_source = image_source.GetAsHTMLVideoElement();
+  } else if (image_source.IsHTMLCanvasElement()) {
+    canvas_image_source = image_source.GetAsHTMLCanvasElement();
+  } else if (image_source.IsOffscreenCanvas()) {
+    canvas_image_source = image_source.GetAsOffscreenCanvas();
   } else {
     NOTREACHED() << "Unsupported CanvasImageSource";
     resolver->Reject(
@@ -78,9 +78,9 @@
     return promise;
   }
 
-  if (image_source.isHTMLImageElement()) {
+  if (image_source.IsHTMLImageElement()) {
     return DetectShapesOnImageElement(resolver,
-                                      image_source.getAsHTMLImageElement());
+                                      image_source.GetAsHTMLImageElement());
   }
 
   // TODO(mcasas): Check if |video| is actually playing a MediaStream by using
diff --git a/third_party/WebKit/Source/modules/speech/SpeechSynthesisVoice.h b/third_party/WebKit/Source/modules/speech/SpeechSynthesisVoice.h
index 5e8f38af..488e63e2 100644
--- a/third_party/WebKit/Source/modules/speech/SpeechSynthesisVoice.h
+++ b/third_party/WebKit/Source/modules/speech/SpeechSynthesisVoice.h
@@ -50,7 +50,7 @@
   bool isDefault() const { return platform_voice_->IsDefault(); }
 
   PlatformSpeechSynthesisVoice* PlatformVoice() const {
-    return platform_voice_.Get();
+    return platform_voice_.get();
   }
 
   DEFINE_INLINE_TRACE() {}
diff --git a/third_party/WebKit/Source/modules/vibration/VibrationController.cpp b/third_party/WebKit/Source/modules/vibration/VibrationController.cpp
index 3bb60b9..e1246c0 100644
--- a/third_party/WebKit/Source/modules/vibration/VibrationController.cpp
+++ b/third_party/WebKit/Source/modules/vibration/VibrationController.cpp
@@ -67,10 +67,10 @@
     const UnsignedLongOrUnsignedLongSequence& pattern) {
   VibrationPattern sanitized;
 
-  if (pattern.isUnsignedLong())
-    sanitized.push_back(pattern.getAsUnsignedLong());
-  else if (pattern.isUnsignedLongSequence())
-    sanitized = pattern.getAsUnsignedLongSequence();
+  if (pattern.IsUnsignedLong())
+    sanitized.push_back(pattern.GetAsUnsignedLong());
+  else if (pattern.IsUnsignedLongSequence())
+    sanitized = pattern.GetAsUnsignedLongSequence();
 
   return sanitizeVibrationPatternInternal(sanitized);
 }
diff --git a/third_party/WebKit/Source/modules/vr/BUILD.gn b/third_party/WebKit/Source/modules/vr/BUILD.gn
index a395560..20eac7e4 100644
--- a/third_party/WebKit/Source/modules/vr/BUILD.gn
+++ b/third_party/WebKit/Source/modules/vr/BUILD.gn
@@ -33,6 +33,10 @@
     "latest/VRDevice.h",
     "latest/VRDeviceEvent.cpp",
     "latest/VRDeviceEvent.h",
+    "latest/VRSession.cpp",
+    "latest/VRSession.h",
+    "latest/VRSessionEvent.cpp",
+    "latest/VRSessionEvent.h",
   ]
 
   deps = [
diff --git a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
index 582e201..c853d65 100644
--- a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
+++ b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
@@ -350,7 +350,7 @@
 
   // If what we were given has an invalid source, need to exit fullscreen with
   // previous, valid source, so delay m_layer reassignment
-  if (layers[0].source().isNull()) {
+  if (layers[0].source().IsNull()) {
     ForceExitPresent();
     DOMException* exception =
         DOMException::Create(kInvalidStateError, "Invalid layer source.");
@@ -361,13 +361,13 @@
   layer_ = layers[0];
 
   CanvasRenderingContext* rendering_context;
-  if (layer_.source().isHTMLCanvasElement()) {
+  if (layer_.source().IsHTMLCanvasElement()) {
     rendering_context =
-        layer_.source().getAsHTMLCanvasElement()->RenderingContext();
+        layer_.source().GetAsHTMLCanvasElement()->RenderingContext();
   } else {
-    DCHECK(layer_.source().isOffscreenCanvas());
+    DCHECK(layer_.source().IsOffscreenCanvas());
     rendering_context =
-        layer_.source().getAsOffscreenCanvas()->RenderingContext();
+        layer_.source().GetAsOffscreenCanvas()->RenderingContext();
   }
 
   if (!rendering_context || !rendering_context->Is3d()) {
@@ -513,12 +513,12 @@
         PresentationResult::kPresentationNotSupportedByDisplay);
     return;
   } else {
-    if (layer_.source().isHTMLCanvasElement()) {
+    if (layer_.source().IsHTMLCanvasElement()) {
       // TODO(klausw,crbug.com/698923): suppress compositor updates
       // since they aren't needed, they do a fair amount of extra
       // work.
     } else {
-      DCHECK(layer_.source().isOffscreenCanvas());
+      DCHECK(layer_.source().IsOffscreenCanvas());
       // TODO(junov, crbug.com/695497): Implement OffscreenCanvas presentation
       ForceExitPresent();
       DOMException* exception = DOMException::Create(
@@ -689,14 +689,14 @@
   // as implemented by AcceleratedStaticBitmapImage. Ensure this is
   // the case, don't attempt to render if using an unexpected drawing
   // path.
-  if (!image_ref.Get() || !image_ref->IsTextureBacked()) {
+  if (!image_ref.get() || !image_ref->IsTextureBacked()) {
     TRACE_EVENT0("gpu", "VRDisplay::GetImage_SlowFallback");
     // We get a non-texture-backed image when running layout tests
     // on desktop builds. Add a slow fallback so that these continue
     // working.
     image_ref = rendering_context_->GetImage(kPreferAcceleration,
                                              kSnapshotReasonCreateImageBitmap);
-    if (!image_ref.Get() || !image_ref->IsTextureBacked()) {
+    if (!image_ref.get() || !image_ref->IsTextureBacked()) {
       NOTREACHED()
           << "WebVR requires hardware-accelerated rendering to texture";
       return;
@@ -708,7 +708,7 @@
   // itself does not keep it alive. We must keep a reference to the
   // image until the mailbox was consumed.
   StaticBitmapImage* static_image =
-      static_cast<StaticBitmapImage*>(image_ref.Get());
+      static_cast<StaticBitmapImage*>(image_ref.get());
   TRACE_EVENT_BEGIN0("gpu", "VRDisplay::EnsureMailbox");
   static_image->EnsureMailbox(kVerifiedSyncToken);
   TRACE_EVENT_END0("gpu", "VRDisplay::EnsureMailbox");
@@ -805,7 +805,7 @@
 void VRDisplay::StopPresenting() {
   if (is_presenting_) {
     if (!capabilities_->hasExternalDisplay()) {
-      if (layer_.source().isHTMLCanvasElement()) {
+      if (layer_.source().IsHTMLCanvasElement()) {
         // TODO(klausw,crbug.com/698923): If compositor updates are
         // suppressed, restore them here.
       } else {
diff --git a/third_party/WebKit/Source/modules/vr/latest/VRDevice.cpp b/third_party/WebKit/Source/modules/vr/latest/VRDevice.cpp
index ced8849..7190a6ea 100644
--- a/third_party/WebKit/Source/modules/vr/latest/VRDevice.cpp
+++ b/third_party/WebKit/Source/modules/vr/latest/VRDevice.cpp
@@ -9,6 +9,7 @@
 #include "core/dom/UserGestureIndicator.h"
 #include "modules/EventTargetModules.h"
 #include "modules/vr/latest/VR.h"
+#include "modules/vr/latest/VRSession.h"
 
 namespace blink {
 
@@ -23,9 +24,6 @@
 const char kRequestNotInUserGesture[] =
     "Exclusive sessions can only be requested during a user gesture.";
 
-const char kSessionCreationNotImplemented[] =
-    "Session creation not implemented.";
-
 }  // namespace
 
 VRDevice::VRDevice(VR* vr,
@@ -105,10 +103,16 @@
     }
   }
 
-  // TODO: Session creation will be implemented in a follow up CL.
-  return ScriptPromise::RejectWithDOMException(
-      script_state,
-      DOMException::Create(kNotSupportedError, kSessionCreationNotImplemented));
+  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+  ScriptPromise promise = resolver->Promise();
+
+  VRSession* session = new VRSession(this, options.exclusive());
+
+  // TODO: A follow up CL will establish a VRPresentationProvider connection
+  // before resolving the promise.
+  resolver->Resolve(session);
+
+  return promise;
 }
 
 // TODO: Forward these calls on to the sessions once they've been implemented.
diff --git a/third_party/WebKit/Source/modules/vr/latest/VRSession.cpp b/third_party/WebKit/Source/modules/vr/latest/VRSession.cpp
new file mode 100644
index 0000000..0b0d8b1
--- /dev/null
+++ b/third_party/WebKit/Source/modules/vr/latest/VRSession.cpp
@@ -0,0 +1,89 @@
+// 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 "modules/vr/latest/VRSession.h"
+
+#include "bindings/core/v8/ScriptPromiseResolver.h"
+#include "core/dom/DOMException.h"
+#include "core/frame/LocalFrame.h"
+#include "modules/EventTargetModules.h"
+#include "modules/vr/latest/VR.h"
+#include "modules/vr/latest/VRDevice.h"
+#include "modules/vr/latest/VRSessionEvent.h"
+
+namespace blink {
+
+namespace {
+
+const char kSessionEnded[] = "VRSession has already ended.";
+
+}  // namespace
+
+VRSession::VRSession(VRDevice* device, bool exclusive)
+    : device_(device), exclusive_(exclusive) {}
+
+void VRSession::setDepthNear(double value) {
+  depth_near_ = value;
+}
+
+void VRSession::setDepthFar(double value) {
+  depth_far_ = value;
+}
+
+ExecutionContext* VRSession::GetExecutionContext() const {
+  return device_->GetExecutionContext();
+}
+
+const AtomicString& VRSession::InterfaceName() const {
+  return EventTargetNames::VRSession;
+}
+
+ScriptPromise VRSession::end(ScriptState* script_state) {
+  // Don't allow a session to end twice.
+  if (detached_) {
+    return ScriptPromise::RejectWithDOMException(
+        script_state, DOMException::Create(kInvalidStateError, kSessionEnded));
+  }
+
+  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+  ScriptPromise promise = resolver->Promise();
+
+  // TODO(bajones): If there's any work that needs to be done asynchronously on
+  // session end it should be completed before this promise is resolved.
+
+  ForceEnd();
+
+  resolver->Resolve();
+  return promise;
+}
+
+void VRSession::ForceEnd() {
+  // Detach this session from the device.
+  detached_ = true;
+
+  DispatchEvent(VRSessionEvent::Create(EventTypeNames::end, this));
+}
+
+void VRSession::OnFocus() {
+  if (!blurred_)
+    return;
+
+  blurred_ = false;
+  DispatchEvent(VRSessionEvent::Create(EventTypeNames::focus, this));
+}
+
+void VRSession::OnBlur() {
+  if (blurred_)
+    return;
+
+  blurred_ = true;
+  DispatchEvent(VRSessionEvent::Create(EventTypeNames::blur, this));
+}
+
+DEFINE_TRACE(VRSession) {
+  visitor->Trace(device_);
+  EventTargetWithInlineData::Trace(visitor);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/modules/vr/latest/VRSession.h b/third_party/WebKit/Source/modules/vr/latest/VRSession.h
new file mode 100644
index 0000000..675902f
--- /dev/null
+++ b/third_party/WebKit/Source/modules/vr/latest/VRSession.h
@@ -0,0 +1,68 @@
+// 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 VRSession_h
+#define VRSession_h
+
+#include "bindings/core/v8/ScriptPromise.h"
+#include "core/dom/events/EventTarget.h"
+#include "platform/heap/Handle.h"
+#include "platform/wtf/Forward.h"
+
+namespace blink {
+
+class VRDevice;
+
+class VRSession final : public EventTargetWithInlineData {
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  VRSession(VRDevice*, bool exclusive);
+
+  VRDevice* device() const { return device_; }
+  bool exclusive() const { return exclusive_; }
+
+  // Near and far depths are used when computing projection matrices for this
+  // Session's views. Changes will propegate to the appropriate matrices on the
+  // next frame after these values are updated.
+  double depthNear() const { return depth_near_; }
+  void setDepthNear(double value);
+  double depthFar() const { return depth_far_; }
+  void setDepthFar(double value);
+
+  DEFINE_ATTRIBUTE_EVENT_LISTENER(blur);
+  DEFINE_ATTRIBUTE_EVENT_LISTENER(focus);
+  DEFINE_ATTRIBUTE_EVENT_LISTENER(resetpose);
+  DEFINE_ATTRIBUTE_EVENT_LISTENER(end);
+
+  // Called by JavaScript to manually end the session.
+  ScriptPromise end(ScriptState*);
+
+  // Called when the session is ended, either via calling the "end" function or
+  // when the presentation service connection is closed.
+  void ForceEnd();
+
+  // EventTarget overrides.
+  ExecutionContext* GetExecutionContext() const override;
+  const AtomicString& InterfaceName() const override;
+
+  void OnFocus();
+  void OnBlur();
+
+  DECLARE_VIRTUAL_TRACE();
+
+ private:
+  const Member<VRDevice> device_;
+  const bool exclusive_;
+
+  double depth_near_ = 0.1;
+  double depth_far_ = 1000.0;
+  bool blurred_ = false;
+
+  bool detached_ = false;
+};
+
+}  // namespace blink
+
+#endif  // VRWebGLLayer_h
diff --git a/third_party/WebKit/Source/modules/vr/latest/VRSession.idl b/third_party/WebKit/Source/modules/vr/latest/VRSession.idl
new file mode 100644
index 0000000..86eec92
--- /dev/null
+++ b/third_party/WebKit/Source/modules/vr/latest/VRSession.idl
@@ -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.
+
+// https://w3c.github.io/webvr/spec/latest/#vrsession-interface
+[
+    RuntimeEnabled=WebVR2
+] interface VRSession : EventTarget {
+  readonly attribute VRDevice device;
+  readonly attribute boolean exclusive;
+
+  attribute double depthNear;
+  attribute double depthFar;
+
+  attribute EventHandler onblur;
+  attribute EventHandler onfocus;
+  attribute EventHandler onresetpose;
+  attribute EventHandler onend;
+
+  [CallWith=ScriptState] Promise end();
+};
diff --git a/third_party/WebKit/Source/modules/vr/latest/VRSessionEvent.cpp b/third_party/WebKit/Source/modules/vr/latest/VRSessionEvent.cpp
new file mode 100644
index 0000000..c7c3127
--- /dev/null
+++ b/third_party/WebKit/Source/modules/vr/latest/VRSessionEvent.cpp
@@ -0,0 +1,32 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "modules/vr/latest/VRSessionEvent.h"
+
+namespace blink {
+
+VRSessionEvent::VRSessionEvent() {}
+
+VRSessionEvent::VRSessionEvent(const AtomicString& type, VRSession* session)
+    : Event(type, true, false), session_(session) {}
+
+VRSessionEvent::VRSessionEvent(const AtomicString& type,
+                               const VRSessionEventInit& initializer)
+    : Event(type, initializer) {
+  if (initializer.hasSession())
+    session_ = initializer.session();
+}
+
+VRSessionEvent::~VRSessionEvent() {}
+
+const AtomicString& VRSessionEvent::InterfaceName() const {
+  return EventNames::VRSessionEvent;
+}
+
+DEFINE_TRACE(VRSessionEvent) {
+  visitor->Trace(session_);
+  Event::Trace(visitor);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/modules/vr/latest/VRSessionEvent.h b/third_party/WebKit/Source/modules/vr/latest/VRSessionEvent.h
new file mode 100644
index 0000000..186e5e7
--- /dev/null
+++ b/third_party/WebKit/Source/modules/vr/latest/VRSessionEvent.h
@@ -0,0 +1,46 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef VRSessionEvent_h
+#define VRSessionEvent_h
+
+#include "modules/EventModules.h"
+#include "modules/vr/latest/VRSession.h"
+#include "modules/vr/latest/VRSessionEventInit.h"
+
+namespace blink {
+
+class VRSessionEvent final : public Event {
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  static VRSessionEvent* Create() { return new VRSessionEvent; }
+  static VRSessionEvent* Create(const AtomicString& type, VRSession* session) {
+    return new VRSessionEvent(type, session);
+  }
+
+  static VRSessionEvent* Create(const AtomicString& type,
+                                const VRSessionEventInit& initializer) {
+    return new VRSessionEvent(type, initializer);
+  }
+
+  ~VRSessionEvent() override;
+
+  VRSession* session() const { return session_.Get(); }
+
+  const AtomicString& InterfaceName() const override;
+
+  DECLARE_VIRTUAL_TRACE();
+
+ private:
+  VRSessionEvent();
+  VRSessionEvent(const AtomicString& type, VRSession*);
+  VRSessionEvent(const AtomicString& type, const VRSessionEventInit&);
+
+  Member<VRSession> session_;
+};
+
+}  // namespace blink
+
+#endif  // VRDisplayEvent_h
diff --git a/third_party/WebKit/Source/modules/vr/latest/VRSessionEvent.idl b/third_party/WebKit/Source/modules/vr/latest/VRSessionEvent.idl
new file mode 100644
index 0000000..68df3b3
--- /dev/null
+++ b/third_party/WebKit/Source/modules/vr/latest/VRSessionEvent.idl
@@ -0,0 +1,12 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://w3c.github.io/webvr/spec/latest/#vrsessionevent-interface
+[
+    SecureContext,
+    RuntimeEnabled=WebVR2,
+    Constructor(DOMString type, VRSessionEventInit eventInitDict)
+] interface VRSessionEvent : Event {
+  readonly attribute VRSession session;
+};
\ No newline at end of file
diff --git a/third_party/WebKit/Source/modules/vr/latest/VRSessionEventInit.idl b/third_party/WebKit/Source/modules/vr/latest/VRSessionEventInit.idl
new file mode 100644
index 0000000..fc46fe2
--- /dev/null
+++ b/third_party/WebKit/Source/modules/vr/latest/VRSessionEventInit.idl
@@ -0,0 +1,10 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://w3c.github.io/webvr/spec/latest/#vrsessionevent-interface
+[
+    SecureContext
+] dictionary VRSessionEventInit : EventInit {
+  required VRSession session;
+};
\ No newline at end of file
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioBuffer.cpp b/third_party/WebKit/Source/modules/webaudio/AudioBuffer.cpp
index 7ad0ec8..de57a7f 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioBuffer.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioBuffer.cpp
@@ -133,7 +133,7 @@
   RefPtr<AudioBus> bus =
       CreateBusFromInMemoryAudioFile(data, data_size, mix_to_mono, sample_rate);
   if (bus) {
-    AudioBuffer* buffer = new AudioBuffer(bus.Get());
+    AudioBuffer* buffer = new AudioBuffer(bus.get());
     if (buffer->CreatedSuccessfully(bus->NumberOfChannels()))
       return buffer;
   }
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp
index 09b1ce5..392b3ac 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp
@@ -50,14 +50,14 @@
   }
 
   WebAudioLatencyHint latency_hint(WebAudioLatencyHint::kCategoryInteractive);
-  if (context_options.latencyHint().isAudioContextLatencyCategory()) {
+  if (context_options.latencyHint().IsAudioContextLatencyCategory()) {
     latency_hint = WebAudioLatencyHint(
-        context_options.latencyHint().getAsAudioContextLatencyCategory());
-  } else if (context_options.latencyHint().isDouble()) {
+        context_options.latencyHint().GetAsAudioContextLatencyCategory());
+  } else if (context_options.latencyHint().IsDouble()) {
     // This should be the requested output latency in seconds, without taking
     // into account double buffering (same as baseLatency).
     latency_hint =
-        WebAudioLatencyHint(context_options.latencyHint().getAsDouble());
+        WebAudioLatencyHint(context_options.latencyHint().GetAsDouble());
   }
 
   AudioContext* audio_context = new AudioContext(document, latency_hint);
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioContextTest.cpp b/third_party/WebKit/Source/modules/webaudio/AudioContextTest.cpp
index 6f91bc9..6d43a6e 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioContextTest.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioContextTest.cpp
@@ -111,14 +111,14 @@
 TEST_F(AudioContextTest, AudioContextOptions_WebAudioLatencyHint) {
   AudioContextOptions interactive_options;
   interactive_options.setLatencyHint(
-      AudioContextLatencyCategoryOrDouble::fromAudioContextLatencyCategory(
+      AudioContextLatencyCategoryOrDouble::FromAudioContextLatencyCategory(
           "interactive"));
   AudioContext* interactive_context = AudioContext::Create(
       GetDocument(), interactive_options, ASSERT_NO_EXCEPTION);
 
   AudioContextOptions balanced_options;
   balanced_options.setLatencyHint(
-      AudioContextLatencyCategoryOrDouble::fromAudioContextLatencyCategory(
+      AudioContextLatencyCategoryOrDouble::FromAudioContextLatencyCategory(
           "balanced"));
   AudioContext* balanced_context = AudioContext::Create(
       GetDocument(), balanced_options, ASSERT_NO_EXCEPTION);
@@ -127,7 +127,7 @@
 
   AudioContextOptions playback_options;
   playback_options.setLatencyHint(
-      AudioContextLatencyCategoryOrDouble::fromAudioContextLatencyCategory(
+      AudioContextLatencyCategoryOrDouble::FromAudioContextLatencyCategory(
           "playback"));
   AudioContext* playback_context = AudioContext::Create(
       GetDocument(), playback_options, ASSERT_NO_EXCEPTION);
@@ -135,7 +135,7 @@
 
   AudioContextOptions exact_too_small_options;
   exact_too_small_options.setLatencyHint(
-      AudioContextLatencyCategoryOrDouble::fromDouble(
+      AudioContextLatencyCategoryOrDouble::FromDouble(
           interactive_context->baseLatency() / 2));
   AudioContext* exact_too_small_context = AudioContext::Create(
       GetDocument(), exact_too_small_options, ASSERT_NO_EXCEPTION);
@@ -147,14 +147,14 @@
       2;
   AudioContextOptions exact_ok_options;
   exact_ok_options.setLatencyHint(
-      AudioContextLatencyCategoryOrDouble::fromDouble(exact_latency_sec));
+      AudioContextLatencyCategoryOrDouble::FromDouble(exact_latency_sec));
   AudioContext* exact_ok_context = AudioContext::Create(
       GetDocument(), exact_ok_options, ASSERT_NO_EXCEPTION);
   EXPECT_EQ(exact_ok_context->baseLatency(), exact_latency_sec);
 
   AudioContextOptions exact_too_big_options;
   exact_too_big_options.setLatencyHint(
-      AudioContextLatencyCategoryOrDouble::fromDouble(
+      AudioContextLatencyCategoryOrDouble::FromDouble(
           playback_context->baseLatency() * 2));
   AudioContext* exact_too_big_context = AudioContext::Create(
       GetDocument(), exact_too_big_options, ASSERT_NO_EXCEPTION);
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioListener.h b/third_party/WebKit/Source/modules/webaudio/AudioListener.h
index 924dbe2..ec09302 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioListener.h
+++ b/third_party/WebKit/Source/modules/webaudio/AudioListener.h
@@ -123,7 +123,7 @@
 
   // HRTF DB loader
   HRTFDatabaseLoader* HrtfDatabaseLoader() {
-    return hrtf_database_loader_.Get();
+    return hrtf_database_loader_.get();
   }
   void CreateAndLoadHRTFDatabaseLoader(float);
   bool IsHRTFDatabaseLoaded();
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioNodeInput.cpp b/third_party/WebKit/Source/modules/webaudio/AudioNodeInput.cpp
index 06bc04cc..77de215 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioNodeInput.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioNodeInput.cpp
@@ -162,7 +162,7 @@
 AudioBus* AudioNodeInput::InternalSummingBus() {
   DCHECK(GetDeferredTaskHandler().IsAudioThread());
 
-  return internal_summing_bus_.Get();
+  return internal_summing_bus_.get();
 }
 
 void AudioNodeInput::SumAllConnections(AudioBus* summing_bus,
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioNodeOutput.cpp b/third_party/WebKit/Source/modules/webaudio/AudioNodeOutput.cpp
index 28ebb98..8d06fc5 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioNodeOutput.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioNodeOutput.cpp
@@ -143,7 +143,7 @@
 
 AudioBus* AudioNodeOutput::Bus() const {
   DCHECK(GetDeferredTaskHandler().IsAudioThread());
-  return is_in_place_ ? in_place_bus_.Get() : internal_bus_.Get();
+  return is_in_place_ ? in_place_bus_.get() : internal_bus_.get();
 }
 
 unsigned AudioNodeOutput::FanOutCount() {
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScopeTest.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScopeTest.cpp
index dce0238..d937dd8c 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScopeTest.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScopeTest.cpp
@@ -56,7 +56,7 @@
         WTF::MakeUnique<GlobalScopeCreationParams>(
             KURL(kParsedURLString, "http://fake.url/"), "fake user agent", "",
             nullptr, kDontPauseWorkerGlobalScopeOnStart, nullptr, "",
-            security_origin_.Get(), nullptr, kWebAddressSpaceLocal, nullptr,
+            security_origin_.get(), nullptr, kWebAddressSpaceLocal, nullptr,
             nullptr, kV8CacheOptionsDefault),
         WTF::nullopt, ParentFrameTaskRunners::Create());
     return thread;
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletThreadTest.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletThreadTest.cpp
index 6851bdf..1cf5111 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletThreadTest.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletThreadTest.cpp
@@ -46,7 +46,7 @@
         WTF::MakeUnique<GlobalScopeCreationParams>(
             KURL(kParsedURLString, "http://fake.url/"), "fake user agent", "",
             nullptr, kDontPauseWorkerGlobalScopeOnStart, nullptr, "",
-            security_origin_.Get(), nullptr, kWebAddressSpaceLocal, nullptr,
+            security_origin_.get(), nullptr, kWebAddressSpaceLocal, nullptr,
             nullptr, kV8CacheOptionsDefault),
         WTF::nullopt, ParentFrameTaskRunners::Create());
     return thread;
diff --git a/third_party/WebKit/Source/modules/webaudio/ConvolverNode.cpp b/third_party/WebKit/Source/modules/webaudio/ConvolverNode.cpp
index 142e25b..890e363c 100644
--- a/third_party/WebKit/Source/modules/webaudio/ConvolverNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/ConvolverNode.cpp
@@ -138,7 +138,7 @@
 
   // Create the reverb with the given impulse response.
   std::unique_ptr<Reverb> reverb = WTF::WrapUnique(new Reverb(
-      buffer_bus.Get(), AudioUtilities::kRenderQuantumFrames, MaxFFTSize,
+      buffer_bus.get(), AudioUtilities::kRenderQuantumFrames, MaxFFTSize,
       Context() && Context()->HasRealtimeConstraint(), normalize_));
 
   {
diff --git a/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.cpp b/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.cpp
index 2efce7e..c837b5b5 100644
--- a/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.cpp
@@ -105,7 +105,7 @@
 
   // consumeAudio has an internal lock (also used by setAudioFormat).
   // This can cause audio to glitch.  This is outside of our control.
-  source_->ConsumeAudio(mix_bus_.Get(), number_of_frames);
+  source_->ConsumeAudio(mix_bus_.get(), number_of_frames);
 }
 
 void MediaStreamAudioDestinationHandler::SetChannelCount(
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp b/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp
index c6b5f7cc..cc5d288 100644
--- a/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp
@@ -216,7 +216,7 @@
   while (frames_to_process_ > 0) {
     // Suspend the rendering if a scheduled suspend found at the current
     // sample frame. Otherwise render one quantum.
-    if (RenderIfNotSuspended(0, render_bus_.Get(),
+    if (RenderIfNotSuspended(0, render_bus_.get(),
                              AudioUtilities::kRenderQuantumFrames))
       return;
 
diff --git a/third_party/WebKit/Source/modules/webdatabase/Database.cpp b/third_party/WebKit/Source/modules/webdatabase/Database.cpp
index 97e2ecb..40bacb4 100644
--- a/third_party/WebKit/Source/modules/webdatabase/Database.cpp
+++ b/third_party/WebKit/Source/modules/webdatabase/Database.cpp
@@ -984,9 +984,9 @@
   if (!GetExecutionContext())
     return nullptr;
   if (GetExecutionContext()->IsContextThread())
-    return context_thread_security_origin_.Get();
+    return context_thread_security_origin_.get();
   if (GetDatabaseContext()->GetDatabaseThread()->IsDatabaseThread())
-    return database_thread_security_origin_.Get();
+    return database_thread_security_origin_.get();
   return nullptr;
 }
 
@@ -995,7 +995,7 @@
 }
 
 WebTaskRunner* Database::GetDatabaseTaskRunner() const {
-  return database_task_runner_.Get();
+  return database_task_runner_.get();
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/webdatabase/Database.h b/third_party/WebKit/Source/modules/webdatabase/Database.h
index 51dd28e..d492d17b 100644
--- a/third_party/WebKit/Source/modules/webdatabase/Database.h
+++ b/third_party/WebKit/Source/modules/webdatabase/Database.h
@@ -153,7 +153,7 @@
                       SQLTransactionErrorCallback*,
                       VoidCallback* success_callback,
                       bool read_only,
-                      const ChangeVersionData* = 0);
+                      const ChangeVersionData* = nullptr);
   Vector<String> PerformGetTableNames();
 
   void ReportOpenDatabaseResult(int error_site,
diff --git a/third_party/WebKit/Source/modules/webdatabase/QuotaTrackerTest.cpp b/third_party/WebKit/Source/modules/webdatabase/QuotaTrackerTest.cpp
index bf4eb5c..88ba009a0 100644
--- a/third_party/WebKit/Source/modules/webdatabase/QuotaTrackerTest.cpp
+++ b/third_party/WebKit/Source/modules/webdatabase/QuotaTrackerTest.cpp
@@ -18,11 +18,11 @@
 
   const String database_name = "db";
   const unsigned long long kDatabaseSize = 1234ULL;
-  tracker.UpdateDatabaseSize(origin.Get(), database_name, kDatabaseSize);
+  tracker.UpdateDatabaseSize(origin.get(), database_name, kDatabaseSize);
 
   unsigned long long used = 0;
   unsigned long long available = 0;
-  tracker.GetDatabaseSizeAndSpaceAvailableToOrigin(origin.Get(), database_name,
+  tracker.GetDatabaseSizeAndSpaceAvailableToOrigin(origin.get(), database_name,
                                                    &used, &available);
 
   EXPECT_EQ(used, kDatabaseSize);
@@ -36,14 +36,14 @@
 
   const String database_name = "db";
   const unsigned long long kDatabaseSize = 1234ULL;
-  tracker.UpdateDatabaseSize(origin.Get(), database_name, kDatabaseSize);
+  tracker.UpdateDatabaseSize(origin.get(), database_name, kDatabaseSize);
 
   // QuotaTracker should not care about policy, just identity.
   origin->BlockLocalAccessFromLocalOrigin();
 
   unsigned long long used = 0;
   unsigned long long available = 0;
-  tracker.GetDatabaseSizeAndSpaceAvailableToOrigin(origin.Get(), database_name,
+  tracker.GetDatabaseSizeAndSpaceAvailableToOrigin(origin.get(), database_name,
                                                    &used, &available);
 
   EXPECT_EQ(used, kDatabaseSize);
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.cpp b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.cpp
index 33d37b9..6369dc7 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.cpp
@@ -98,12 +98,12 @@
 
 void WebGL2RenderingContext::SetCanvasGetContextResult(
     RenderingContext& result) {
-  result.setWebGL2RenderingContext(this);
+  result.SetWebGL2RenderingContext(this);
 }
 
 void WebGL2RenderingContext::SetOffscreenCanvasGetContextResult(
     OffscreenRenderingContext& result) {
-  result.setWebGL2RenderingContext(this);
+  result.SetWebGL2RenderingContext(this);
 }
 
 ImageBitmap* WebGL2RenderingContext::TransferToImageBitmap(
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
index ec7160bb..608a7bb4 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
@@ -3376,7 +3376,7 @@
   }
 
   ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
-                                                   drawing_buffer_.Get());
+                                                   drawing_buffer_.get());
   ClearIfComposited();
   ContextGL()->DrawArraysInstancedANGLE(mode, first, count, instance_count);
   MarkContextChanged(kCanvasChanged);
@@ -3397,7 +3397,7 @@
   }
 
   ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
-                                                   drawing_buffer_.Get());
+                                                   drawing_buffer_.get());
   ClearIfComposited();
   ContextGL()->DrawElementsInstancedANGLE(
       mode, count, type, reinterpret_cast<void*>(static_cast<intptr_t>(offset)),
@@ -3421,7 +3421,7 @@
   }
 
   ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
-                                                   drawing_buffer_.Get());
+                                                   drawing_buffer_.get());
   ClearIfComposited();
   ContextGL()->DrawRangeElements(
       mode, start, end, count, type,
@@ -3434,7 +3434,7 @@
     return;
 
   ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
-                                                   drawing_buffer_.Get());
+                                                   drawing_buffer_.get());
   GLsizei n = buffers.size();
   const GLenum* bufs = buffers.data();
   for (GLsizei i = 0; i < n; ++i) {
@@ -3538,7 +3538,7 @@
     return;
 
   ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
-                                                   drawing_buffer_.Get());
+                                                   drawing_buffer_.get());
 
   ContextGL()->ClearBufferiv(buffer, drawbuffer,
                              value.View()->DataMaybeShared() + src_offset);
@@ -3553,7 +3553,7 @@
     return;
 
   ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
-                                                   drawing_buffer_.Get());
+                                                   drawing_buffer_.get());
 
   ContextGL()->ClearBufferiv(buffer, drawbuffer, value.data() + src_offset);
 }
@@ -3569,7 +3569,7 @@
     return;
 
   ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
-                                                   drawing_buffer_.Get());
+                                                   drawing_buffer_.get());
 
   ContextGL()->ClearBufferuiv(buffer, drawbuffer,
                               value.View()->DataMaybeShared() + src_offset);
@@ -3584,7 +3584,7 @@
     return;
 
   ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
-                                                   drawing_buffer_.Get());
+                                                   drawing_buffer_.get());
 
   ContextGL()->ClearBufferuiv(buffer, drawbuffer, value.data() + src_offset);
 }
@@ -3606,7 +3606,7 @@
   // added, the type of the back buffer might change, so do the
   // emulation for all clearBuffer entry points instead of just here.
   ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
-                                                   drawing_buffer_.Get());
+                                                   drawing_buffer_.get());
 
   ContextGL()->ClearBufferfv(buffer, drawbuffer,
                              value.View()->DataMaybeShared() + src_offset);
@@ -3627,7 +3627,7 @@
   // added, the type of the back buffer might change, so do the
   // emulation for all clearBuffer entry points instead of just here.
   ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
-                                                   drawing_buffer_.Get());
+                                                   drawing_buffer_.get());
 
   ContextGL()->ClearBufferfv(buffer, drawbuffer, value.data() + src_offset);
 }
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.cpp
index b2c9574..949151c 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.cpp
@@ -127,12 +127,12 @@
 
 void WebGLRenderingContext::SetCanvasGetContextResult(
     RenderingContext& result) {
-  result.setWebGLRenderingContext(this);
+  result.SetWebGLRenderingContext(this);
 }
 
 void WebGLRenderingContext::SetOffscreenCanvasGetContextResult(
     OffscreenRenderingContext& result) {
-  result.setWebGLRenderingContext(this);
+  result.SetWebGLRenderingContext(this);
 }
 
 ImageBitmap* WebGLRenderingContext::TransferToImageBitmap(
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
index 50a1f6cb..6c918a3 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
@@ -1954,7 +1954,7 @@
   }
 
   ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
-                                                   drawing_buffer_.Get());
+                                                   drawing_buffer_.get());
 
   if (ClearIfComposited(mask) != kCombinedClear) {
     // If clearing the default back buffer's depth buffer, also clear the
@@ -2412,7 +2412,7 @@
   }
 
   ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
-                                                   drawing_buffer_.Get());
+                                                   drawing_buffer_.get());
   ClearIfComposited();
   ContextGL()->DrawArrays(mode, first, count);
   MarkContextChanged(kCanvasChanged);
@@ -2432,7 +2432,7 @@
   }
 
   ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
-                                                   drawing_buffer_.Get());
+                                                   drawing_buffer_.get());
   ClearIfComposited();
   ContextGL()->DrawElements(
       mode, count, type,
@@ -2454,7 +2454,7 @@
   }
 
   ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
-                                                   drawing_buffer_.Get());
+                                                   drawing_buffer_.get());
   ClearIfComposited();
   ContextGL()->DrawArraysInstancedANGLE(mode, first, count, primcount);
   MarkContextChanged(kCanvasChanged);
@@ -2475,7 +2475,7 @@
   }
 
   ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
-                                                   drawing_buffer_.Get());
+                                                   drawing_buffer_.get());
   ClearIfComposited();
   ContextGL()->DrawElementsInstancedANGLE(
       mode, count, type, reinterpret_cast<void*>(static_cast<intptr_t>(offset)),
@@ -4864,7 +4864,7 @@
     return;
 
   TexImageImpl(function_id, target, level, internalformat, xoffset, yoffset,
-               zoffset, format, type, image_for_render.Get(),
+               zoffset, format, type, image_for_render.get(),
                WebGLImageConversion::kHtmlDomImage, unpack_flip_y_,
                unpack_premultiply_alpha_, source_image_rect, depth,
                unpack_image_height);
@@ -5110,7 +5110,7 @@
                    canvas
                        ->CopiedImage(kBackBuffer, kPreferAcceleration,
                                      FunctionIDToSnapshotReason(function_id))
-                       .Get(),
+                       .get(),
                    WebGLImageConversion::kHtmlDomCanvas, unpack_flip_y_,
                    unpack_premultiply_alpha_, source_sub_rectangle, 1, 0);
       return;
@@ -5144,7 +5144,7 @@
                  canvas
                      ->CopiedImage(kBackBuffer, kPreferAcceleration,
                                    FunctionIDToSnapshotReason(function_id))
-                     .Get(),
+                     .get(),
                  WebGLImageConversion::kHtmlDomCanvas, unpack_flip_y_,
                  unpack_premultiply_alpha_, source_sub_rectangle, depth,
                  unpack_image_height);
@@ -5324,7 +5324,7 @@
   if (!image)
     return;
   TexImageImpl(function_id, target, level, internalformat, xoffset, yoffset,
-               zoffset, format, type, image.Get(),
+               zoffset, format, type, image.get(),
                WebGLImageConversion::kHtmlDomVideo, unpack_flip_y_,
                unpack_premultiply_alpha_, source_image_rect, depth,
                unpack_image_height);
@@ -7809,7 +7809,7 @@
 }
 
 DrawingBuffer* WebGLRenderingContextBase::GetDrawingBuffer() const {
-  return drawing_buffer_.Get();
+  return drawing_buffer_.get();
 }
 
 void WebGLRenderingContextBase::ResetUnpackParameters() {
@@ -7825,9 +7825,9 @@
 void WebGLRenderingContextBase::getHTMLOrOffscreenCanvas(
     HTMLCanvasElementOrOffscreenCanvas& result) const {
   if (canvas()) {
-    result.setHTMLCanvasElement(static_cast<HTMLCanvasElement*>(host()));
+    result.SetHTMLCanvasElement(static_cast<HTMLCanvasElement*>(host()));
   } else {
-    result.setOffscreenCanvas(static_cast<OffscreenCanvas*>(host()));
+    result.SetOffscreenCanvas(static_cast<OffscreenCanvas*>(host()));
   }
 }
 
diff --git a/third_party/WebKit/Source/modules/websockets/DOMWebSocket.cpp b/third_party/WebKit/Source/modules/websockets/DOMWebSocket.cpp
index 0e74e15..0c7831e 100644
--- a/third_party/WebKit/Source/modules/websockets/DOMWebSocket.cpp
+++ b/third_party/WebKit/Source/modules/websockets/DOMWebSocket.cpp
@@ -266,16 +266,16 @@
   DOMWebSocket* web_socket = new DOMWebSocket(context);
   web_socket->SuspendIfNeeded();
 
-  if (protocols.isNull()) {
+  if (protocols.IsNull()) {
     Vector<String> protocols_vector;
     web_socket->Connect(url, protocols_vector, exception_state);
-  } else if (protocols.isString()) {
+  } else if (protocols.IsString()) {
     Vector<String> protocols_vector;
-    protocols_vector.push_back(protocols.getAsString());
+    protocols_vector.push_back(protocols.GetAsString());
     web_socket->Connect(url, protocols_vector, exception_state);
   } else {
-    DCHECK(protocols.isStringSequence());
-    web_socket->Connect(url, protocols.getAsStringSequence(), exception_state);
+    DCHECK(protocols.IsStringSequence());
+    web_socket->Connect(url, protocols.GetAsStringSequence(), exception_state);
   }
 
   if (exception_state.HadException())
diff --git a/third_party/WebKit/Source/modules/websockets/DOMWebSocketTest.cpp b/third_party/WebKit/Source/modules/websockets/DOMWebSocketTest.cpp
index f03928f..b0f2698 100644
--- a/third_party/WebKit/Source/modules/websockets/DOMWebSocketTest.cpp
+++ b/third_party/WebKit/Source/modules/websockets/DOMWebSocketTest.cpp
@@ -51,7 +51,7 @@
   MOCK_METHOD1(Send, void(const CString&));
   MOCK_METHOD3(Send, void(const DOMArrayBuffer&, unsigned, unsigned));
   MOCK_METHOD1(SendMock, void(BlobDataHandle*));
-  void Send(RefPtr<BlobDataHandle> handle) { SendMock(handle.Get()); }
+  void Send(RefPtr<BlobDataHandle> handle) { SendMock(handle.get()); }
   MOCK_METHOD1(SendTextAsCharVectorMock, void(Vector<char>*));
   void SendTextAsCharVector(std::unique_ptr<Vector<char>> vector) {
     SendTextAsCharVectorMock(vector.get());
diff --git a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp
index 5003f6e0..c173b73 100644
--- a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp
+++ b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp
@@ -252,7 +252,7 @@
       loading_context_->GetExecutionContext()->UserAgent(), this,
       TaskRunnerHelper::Get(TaskType::kNetworking,
                             loading_context_->GetExecutionContext())
-          .Get());
+          .get());
 
   // TODO(ricea): Maybe lookup GetDocument()->GetFrame() less often?
   if (handshake_throttle_ && GetDocument() && GetDocument()->GetFrame() &&
@@ -585,7 +585,7 @@
         TRACE_EVENT_SCOPE_THREAD, "data",
         InspectorWebSocketEvent::Data(GetDocument(), identifier_));
     probe::willSendWebSocketHandshakeRequest(GetDocument(), identifier_,
-                                             request.Get());
+                                             request.get());
   }
   handshake_request_ = std::move(request);
 }
@@ -604,7 +604,7 @@
         TRACE_EVENT_SCOPE_THREAD, "data",
         InspectorWebSocketEvent::Data(GetDocument(), identifier_));
     probe::didReceiveWebSocketHandshakeResponse(
-        GetDocument(), identifier_, handshake_request_.Get(), response);
+        GetDocument(), identifier_, handshake_request_.get(), response);
   }
   handshake_request_ = nullptr;
 }
diff --git a/third_party/WebKit/Source/modules/webusb/USBDevice.cpp b/third_party/WebKit/Source/modules/webusb/USBDevice.cpp
index 8017efcfd..d7c9412c 100644
--- a/third_party/WebKit/Source/modules/webusb/USBDevice.cpp
+++ b/third_party/WebKit/Source/modules/webusb/USBDevice.cpp
@@ -87,15 +87,16 @@
 
 Vector<uint8_t> ConvertBufferSource(
     const ArrayBufferOrArrayBufferView& buffer) {
-  DCHECK(!buffer.isNull());
+  DCHECK(!buffer.IsNull());
   Vector<uint8_t> vector;
-  if (buffer.isArrayBuffer())
-    vector.Append(static_cast<uint8_t*>(buffer.getAsArrayBuffer()->Data()),
-                  buffer.getAsArrayBuffer()->ByteLength());
-  else
+  if (buffer.IsArrayBuffer()) {
+    vector.Append(static_cast<uint8_t*>(buffer.GetAsArrayBuffer()->Data()),
+                  buffer.GetAsArrayBuffer()->ByteLength());
+  } else {
     vector.Append(static_cast<uint8_t*>(
-                      buffer.getAsArrayBufferView().View()->BaseAddress()),
-                  buffer.getAsArrayBufferView().View()->byteLength());
+                      buffer.GetAsArrayBufferView().View()->BaseAddress()),
+                  buffer.GetAsArrayBufferView().View()->byteLength());
+  }
   return vector;
 }
 
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn
index 4dabaab..0159504a 100644
--- a/third_party/WebKit/Source/platform/BUILD.gn
+++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -731,7 +731,9 @@
     "fonts/FontSelectorClient.h",
     "fonts/FontSmoothingMode.cpp",
     "fonts/FontSmoothingMode.h",
+    "fonts/FontVariantEastAsian.cpp",
     "fonts/FontVariantEastAsian.h",
+    "fonts/FontVariantNumeric.cpp",
     "fonts/FontVariantNumeric.h",
     "fonts/FontWidthVariant.cpp",
     "fonts/FontWidthVariant.h",
diff --git a/third_party/WebKit/Source/platform/CrossThreadCopier.h b/third_party/WebKit/Source/platform/CrossThreadCopier.h
index a9f4297..7db4f84 100644
--- a/third_party/WebKit/Source/platform/CrossThreadCopier.h
+++ b/third_party/WebKit/Source/platform/CrossThreadCopier.h
@@ -150,6 +150,13 @@
   }
 };
 
+template <size_t inlineCapacity, typename Allocator>
+struct CrossThreadCopier<Vector<uint64_t, inlineCapacity, Allocator>> {
+  STATIC_ONLY(CrossThreadCopier);
+  using Type = Vector<uint64_t, inlineCapacity, Allocator>;
+  static Type Copy(Type value) { return value; }
+};
+
 template <typename T>
 struct CrossThreadCopier<CrossThreadPersistent<T>>
     : public CrossThreadCopierPassThrough<CrossThreadPersistent<T>> {
diff --git a/third_party/WebKit/Source/platform/Cursor.h b/third_party/WebKit/Source/platform/Cursor.h
index 4bbb5d22..a5fa6a11 100644
--- a/third_party/WebKit/Source/platform/Cursor.h
+++ b/third_party/WebKit/Source/platform/Cursor.h
@@ -110,7 +110,7 @@
     DCHECK_LE(type_, kCustom);
     return type_;
   }
-  Image* GetImage() const { return image_.Get(); }
+  Image* GetImage() const { return image_.get(); }
   const IntPoint& HotSpot() const { return hot_spot_; }
   // Image scale in image pixels per logical (UI) pixel.
   float ImageScaleFactor() const { return image_scale_factor_; }
diff --git a/third_party/WebKit/Source/platform/DragImage.cpp b/third_party/WebKit/Source/platform/DragImage.cpp
index fb95566..aaff25b 100644
--- a/third_party/WebKit/Source/platform/DragImage.cpp
+++ b/third_party/WebKit/Source/platform/DragImage.cpp
@@ -310,7 +310,7 @@
                           device_scale_factor, text_paint);
 
   RefPtr<StaticBitmapImage> image = buffer->NewImageSnapshot();
-  return DragImage::Create(image.Get(), kDoNotRespectImageOrientation,
+  return DragImage::Create(image.get(), kDoNotRespectImageOrientation,
                            device_scale_factor);
 }
 
diff --git a/third_party/WebKit/Source/platform/DragImageTest.cpp b/third_party/WebKit/Source/platform/DragImageTest.cpp
index 857b5171c..af5cf56e 100644
--- a/third_party/WebKit/Source/platform/DragImageTest.cpp
+++ b/third_party/WebKit/Source/platform/DragImageTest.cpp
@@ -112,12 +112,12 @@
   EXPECT_FALSE(DragImage::Create(0));
 
   RefPtr<TestImage> null_test_image(TestImage::Create(IntSize()));
-  EXPECT_FALSE(DragImage::Create(null_test_image.Get()));
+  EXPECT_FALSE(DragImage::Create(null_test_image.get()));
 }
 
 TEST(DragImageTest, NonNullHandling) {
   RefPtr<TestImage> test_image(TestImage::Create(IntSize(2, 2)));
-  std::unique_ptr<DragImage> drag_image = DragImage::Create(test_image.Get());
+  std::unique_ptr<DragImage> drag_image = DragImage::Create(test_image.get());
   ASSERT_TRUE(drag_image);
 
   drag_image->Scale(0.5, 0.5);
@@ -131,7 +131,7 @@
   // of imageForCurrentFrame().
   // FIXME: how is this test any different from test NullHandling?
   RefPtr<TestImage> test_image(TestImage::Create(IntSize()));
-  EXPECT_FALSE(DragImage::Create(test_image.Get()));
+  EXPECT_FALSE(DragImage::Create(test_image.get()));
 }
 
 TEST(DragImageTest, TrimWhitespace) {
@@ -174,7 +174,7 @@
   RefPtr<TestImage> test_image =
       TestImage::Create(SkImage::MakeFromBitmap(test_bitmap));
   std::unique_ptr<DragImage> drag_image = DragImage::Create(
-      test_image.Get(), kDoNotRespectImageOrientation, 1, kInterpolationNone);
+      test_image.get(), kDoNotRespectImageOrientation, 1, kInterpolationNone);
   ASSERT_TRUE(drag_image);
   drag_image->Scale(2, 2);
   const SkBitmap& drag_bitmap = drag_image->Bitmap();
diff --git a/third_party/WebKit/Source/platform/LayoutLocale.cpp b/third_party/WebKit/Source/platform/LayoutLocale.cpp
index c1454637..7ae5a86e 100644
--- a/third_party/WebKit/Source/platform/LayoutLocale.cpp
+++ b/third_party/WebKit/Source/platform/LayoutLocale.cpp
@@ -119,7 +119,7 @@
   auto result = FontGlobalContext::GetLayoutLocaleMap().insert(locale, nullptr);
   if (result.is_new_entry)
     result.stored_value->value = WTF::AdoptRef(new LayoutLocale(locale));
-  return result.stored_value->value.Get();
+  return result.stored_value->value.get();
 }
 
 const LayoutLocale& LayoutLocale::GetDefault() {
@@ -153,11 +153,11 @@
 
 Hyphenation* LayoutLocale::GetHyphenation() const {
   if (hyphenation_computed_)
-    return hyphenation_.Get();
+    return hyphenation_.get();
 
   hyphenation_computed_ = true;
   hyphenation_ = Hyphenation::PlatformGetHyphenation(LocaleString());
-  return hyphenation_.Get();
+  return hyphenation_.get();
 }
 
 void LayoutLocale::SetHyphenationForTesting(const AtomicString& locale_string,
diff --git a/third_party/WebKit/Source/platform/PODArena.h b/third_party/WebKit/Source/platform/PODArena.h
index d654b3fc..2538aa1a 100644
--- a/third_party/WebKit/Source/platform/PODArena.h
+++ b/third_party/WebKit/Source/platform/PODArena.h
@@ -130,7 +130,7 @@
       if (rounded_size > current_chunk_size_)
         current_chunk_size_ = rounded_size;
       chunks_.push_back(
-          WTF::WrapUnique(new Chunk(allocator_.Get(), current_chunk_size_)));
+          WTF::WrapUnique(new Chunk(allocator_.get(), current_chunk_size_)));
       current_ = chunks_.back().get();
       ptr = current_->Allocate(rounded_size);
     }
diff --git a/third_party/WebKit/Source/platform/PODRedBlackTree.h b/third_party/WebKit/Source/platform/PODRedBlackTree.h
index 7cf6fb0..16f9793 100644
--- a/third_party/WebKit/Source/platform/PODRedBlackTree.h
+++ b/third_party/WebKit/Source/platform/PODRedBlackTree.h
@@ -158,7 +158,7 @@
     root_ = 0;
   }
 
-  bool IsInitialized() const { return arena_.Get(); }
+  bool IsInitialized() const { return arena_.get(); }
 
   void InitIfNeeded() {
     if (!arena_)
diff --git a/third_party/WebKit/Source/platform/PngFuzzer.cpp b/third_party/WebKit/Source/platform/PngFuzzer.cpp
index da57b87..d3ab068 100644
--- a/third_party/WebKit/Source/platform/PngFuzzer.cpp
+++ b/third_party/WebKit/Source/platform/PngFuzzer.cpp
@@ -42,7 +42,7 @@
   // TODO (scroggo): Also test ImageDecoder::AlphaNotPremultiplied?
   auto decoder = CreateDecoder(ImageDecoder::kAlphaPremultiplied);
   const bool kAllDataReceived = true;
-  decoder->SetData(buffer.Get(), kAllDataReceived);
+  decoder->SetData(buffer.get(), kAllDataReceived);
   decoder->FrameCount();
   if (decoder->Failed())
     return 0;
diff --git a/third_party/WebKit/Source/platform/Prerender.h b/third_party/WebKit/Source/platform/Prerender.h
index 9b065911..abb158b 100644
--- a/third_party/WebKit/Source/platform/Prerender.h
+++ b/third_party/WebKit/Source/platform/Prerender.h
@@ -78,7 +78,7 @@
   void SetExtraData(RefPtr<ExtraData> extra_data) {
     extra_data_ = std::move(extra_data);
   }
-  ExtraData* GetExtraData() { return extra_data_.Get(); }
+  ExtraData* GetExtraData() { return extra_data_.get(); }
 
   void DidStartPrerender();
   void DidStopPrerender();
diff --git a/third_party/WebKit/Source/platform/animation/AnimationTranslationUtil.cpp b/third_party/WebKit/Source/platform/animation/AnimationTranslationUtil.cpp
index 398ed25..46866f6 100644
--- a/third_party/WebKit/Source/platform/animation/AnimationTranslationUtil.cpp
+++ b/third_party/WebKit/Source/platform/animation/AnimationTranslationUtil.cpp
@@ -51,7 +51,7 @@
       case TransformOperation::kScale3D:
       case TransformOperation::kScale: {
         auto transform =
-            static_cast<const ScaleTransformOperation*>(operation.Get());
+            static_cast<const ScaleTransformOperation*>(operation.get());
         out_transform_operations->AppendScale(transform->X(), transform->Y(),
                                               transform->Z());
         break;
@@ -62,7 +62,7 @@
       case TransformOperation::kTranslate3D:
       case TransformOperation::kTranslate: {
         auto transform =
-            static_cast<const TranslateTransformOperation*>(operation.Get());
+            static_cast<const TranslateTransformOperation*>(operation.get());
         DCHECK(transform->X().IsFixed() && transform->Y().IsFixed());
         out_transform_operations->AppendTranslate(
             transform->X().Value(), transform->Y().Value(), transform->Z());
@@ -73,7 +73,7 @@
       case TransformOperation::kRotate3D:
       case TransformOperation::kRotate: {
         auto transform =
-            static_cast<const RotateTransformOperation*>(operation.Get());
+            static_cast<const RotateTransformOperation*>(operation.get());
         out_transform_operations->AppendRotate(
             transform->X(), transform->Y(), transform->Z(), transform->Angle());
         break;
@@ -82,14 +82,14 @@
       case TransformOperation::kSkewY:
       case TransformOperation::kSkew: {
         auto transform =
-            static_cast<const SkewTransformOperation*>(operation.Get());
+            static_cast<const SkewTransformOperation*>(operation.get());
         out_transform_operations->AppendSkew(transform->AngleX(),
                                              transform->AngleY());
         break;
       }
       case TransformOperation::kMatrix: {
         auto transform =
-            static_cast<const MatrixTransformOperation*>(operation.Get());
+            static_cast<const MatrixTransformOperation*>(operation.get());
         TransformationMatrix m = transform->Matrix();
         out_transform_operations->AppendMatrix(
             TransformationMatrix::ToSkMatrix44(m));
@@ -97,7 +97,7 @@
       }
       case TransformOperation::kMatrix3D: {
         auto transform =
-            static_cast<const Matrix3DTransformOperation*>(operation.Get());
+            static_cast<const Matrix3DTransformOperation*>(operation.get());
         TransformationMatrix m = transform->Matrix();
         out_transform_operations->AppendMatrix(
             TransformationMatrix::ToSkMatrix44(m));
@@ -105,7 +105,7 @@
       }
       case TransformOperation::kPerspective: {
         auto transform =
-            static_cast<const PerspectiveTransformOperation*>(operation.Get());
+            static_cast<const PerspectiveTransformOperation*>(operation.get());
         out_transform_operations->AppendPerspective(transform->Perspective());
         break;
       }
diff --git a/third_party/WebKit/Source/platform/audio/AudioBus.cpp b/third_party/WebKit/Source/platform/audio/AudioBus.cpp
index 50fe463..827a80a 100644
--- a/third_party/WebKit/Source/platform/audio/AudioBus.cpp
+++ b/third_party/WebKit/Source/platform/audio/AudioBus.cpp
@@ -37,7 +37,6 @@
 #include "platform/audio/DenormalDisabler.h"
 #include "platform/audio/SincResampler.h"
 #include "platform/audio/VectorMath.h"
-#include "platform/wtf/PtrUtil.h"
 #include "public/platform/Platform.h"
 #include "public/platform/WebAudioBus.h"
 
@@ -537,9 +536,10 @@
 
   if (frames_to_dezipper) {
     if (!dezipper_gain_values_.get() ||
-        dezipper_gain_values_->size() < frames_to_dezipper)
+        dezipper_gain_values_->size() < frames_to_dezipper) {
       dezipper_gain_values_ =
-          WTF::MakeUnique<AudioFloatArray>(frames_to_dezipper);
+          std::make_unique<AudioFloatArray>(frames_to_dezipper);
+    }
 
     float* gain_values = dezipper_gain_values_->Data();
     for (unsigned i = 0; i < frames_to_dezipper; ++i) {
@@ -663,7 +663,7 @@
   RefPtr<AudioBus> mixed_mono_bus;
   if (mix_to_mono) {
     mixed_mono_bus = AudioBus::CreateByMixingToMono(source_bus);
-    resampler_source_bus = mixed_mono_bus.Get();
+    resampler_source_bus = mixed_mono_bus.get();
   } else {
     // Directly resample without down-mixing.
     resampler_source_bus = source_bus;
@@ -759,14 +759,14 @@
   RefPtr<AudioBus> audio_bus =
       DecodeAudioFileData(flat_data.Data(), flat_data.size());
 
-  if (!audio_bus.Get())
+  if (!audio_bus.get())
     return nullptr;
 
   // If the bus is already at the requested sample-rate then return as is.
   if (audio_bus->SampleRate() == sample_rate)
     return audio_bus;
 
-  return AudioBus::CreateBySampleRateConverting(audio_bus.Get(), false,
+  return AudioBus::CreateBySampleRateConverting(audio_bus.get(), false,
                                                 sample_rate);
 }
 
@@ -776,7 +776,7 @@
                                                 float sample_rate) {
   RefPtr<AudioBus> audio_bus =
       DecodeAudioFileData(static_cast<const char*>(data), data_size);
-  if (!audio_bus.Get())
+  if (!audio_bus.get())
     return nullptr;
 
   // If the bus needs no conversion then return as is.
@@ -784,7 +784,7 @@
       audio_bus->SampleRate() == sample_rate)
     return audio_bus;
 
-  return AudioBus::CreateBySampleRateConverting(audio_bus.Get(), mix_to_mono,
+  return AudioBus::CreateBySampleRateConverting(audio_bus.get(), mix_to_mono,
                                                 sample_rate);
 }
 
diff --git a/third_party/WebKit/Source/platform/audio/AudioDestination.cpp b/third_party/WebKit/Source/platform/audio/AudioDestination.cpp
index f70b774..4badc8a9 100644
--- a/third_party/WebKit/Source/platform/audio/AudioDestination.cpp
+++ b/third_party/WebKit/Source/platform/audio/AudioDestination.cpp
@@ -127,7 +127,7 @@
   for (unsigned i = 0; i < number_of_output_channels_; ++i)
     output_bus_->SetChannelMemory(i, destination_data[i], number_of_frames);
 
-  size_t frames_to_render = fifo_->Pull(output_bus_.Get(), number_of_frames);
+  size_t frames_to_render = fifo_->Pull(output_bus_.get(), number_of_frames);
 
   // Use the dual-thread rendering model if the thread from AudioWorkletThread
   // is available.
@@ -180,9 +180,9 @@
       output_position.position = 0.0;
 
     // Process WebAudio graph and push the rendered output to FIFO.
-    callback_.Render(nullptr, render_bus_.Get(),
+    callback_.Render(nullptr, render_bus_.get(),
                      AudioUtilities::kRenderQuantumFrames, output_position);
-    fifo_->Push(render_bus_.Get());
+    fifo_->Push(render_bus_.get());
   }
 
   frames_elapsed_ += frames_requested;
diff --git a/third_party/WebKit/Source/platform/audio/AudioResampler.cpp b/third_party/WebKit/Source/platform/audio/AudioResampler.cpp
index b77bb6a..67f87c3 100644
--- a/third_party/WebKit/Source/platform/audio/AudioResampler.cpp
+++ b/third_party/WebKit/Source/platform/audio/AudioResampler.cpp
@@ -25,21 +25,21 @@
 
 #include "platform/audio/AudioResampler.h"
 #include <algorithm>
+#include <memory>
 #include "platform/wtf/MathExtras.h"
-#include "platform/wtf/PtrUtil.h"
 
 namespace blink {
 
 const double AudioResampler::kMaxRate = 8.0;
 
 AudioResampler::AudioResampler() : rate_(1.0) {
-  kernels_.push_back(WTF::MakeUnique<AudioResamplerKernel>(this));
+  kernels_.push_back(std::make_unique<AudioResamplerKernel>(this));
   source_bus_ = AudioBus::Create(1, 0, false);
 }
 
 AudioResampler::AudioResampler(unsigned number_of_channels) : rate_(1.0) {
   for (unsigned i = 0; i < number_of_channels; ++i)
-    kernels_.push_back(WTF::MakeUnique<AudioResamplerKernel>(this));
+    kernels_.push_back(std::make_unique<AudioResamplerKernel>(this));
 
   source_bus_ = AudioBus::Create(number_of_channels, 0, false);
 }
@@ -52,7 +52,7 @@
   // First deal with adding or removing kernels.
   if (number_of_channels > current_size) {
     for (unsigned i = current_size; i < number_of_channels; ++i)
-      kernels_.push_back(WTF::MakeUnique<AudioResamplerKernel>(this));
+      kernels_.push_back(std::make_unique<AudioResamplerKernel>(this));
   } else
     kernels_.resize(number_of_channels);
 
@@ -92,7 +92,7 @@
   }
 
   // Ask the provider to supply the desired number of source frames.
-  provider->ProvideInput(source_bus_.Get(), source_bus_->length());
+  provider->ProvideInput(source_bus_.get(), source_bus_->length());
 
   // Now that we have the source data, resample each channel into the
   // destination bus.
diff --git a/third_party/WebKit/Source/platform/audio/DynamicsCompressorKernel.cpp b/third_party/WebKit/Source/platform/audio/DynamicsCompressorKernel.cpp
index ce9bd1c0..044453c 100644
--- a/third_party/WebKit/Source/platform/audio/DynamicsCompressorKernel.cpp
+++ b/third_party/WebKit/Source/platform/audio/DynamicsCompressorKernel.cpp
@@ -76,7 +76,7 @@
   pre_delay_buffers_.clear();
   for (unsigned i = 0; i < number_of_channels; ++i) {
     pre_delay_buffers_.push_back(
-        WTF::MakeUnique<AudioFloatArray>(kMaxPreDelayFrames));
+        std::make_unique<AudioFloatArray>(kMaxPreDelayFrames));
   }
 }
 
diff --git a/third_party/WebKit/Source/platform/audio/HRTFDatabaseLoader.cpp b/third_party/WebKit/Source/platform/audio/HRTFDatabaseLoader.cpp
index 3721b43..abd8cef 100644
--- a/third_party/WebKit/Source/platform/audio/HRTFDatabaseLoader.cpp
+++ b/third_party/WebKit/Source/platform/audio/HRTFDatabaseLoader.cpp
@@ -57,7 +57,7 @@
   }
 
   loader = WTF::AdoptRef(new HRTFDatabaseLoader(sample_rate));
-  GetLoaderMap().insert(sample_rate, loader.Get());
+  GetLoaderMap().insert(sample_rate, loader.get());
   loader->LoadAsynchronously();
   return loader;
 }
diff --git a/third_party/WebKit/Source/platform/audio/HRTFElevation.cpp b/third_party/WebKit/Source/platform/audio/HRTFElevation.cpp
index e3ce000..c1884e4 100644
--- a/third_party/WebKit/Source/platform/audio/HRTFElevation.cpp
+++ b/third_party/WebKit/Source/platform/audio/HRTFElevation.cpp
@@ -33,7 +33,6 @@
 #include <memory>
 #include "platform/audio/AudioBus.h"
 #include "platform/audio/HRTFPanner.h"
-#include "platform/wtf/PtrUtil.h"
 #include "platform/wtf/ThreadingPrimitives.h"
 #include "platform/wtf/text/StringHash.h"
 
@@ -169,9 +168,9 @@
   unsigned start_frame = index * kResponseFrameSize;
   unsigned stop_frame = start_frame + kResponseFrameSize;
   RefPtr<AudioBus> pre_sample_rate_converted_response(
-      AudioBus::CreateBufferFromRange(bus.Get(), start_frame, stop_frame));
+      AudioBus::CreateBufferFromRange(bus.get(), start_frame, stop_frame));
   RefPtr<AudioBus> response(AudioBus::CreateBySampleRateConverting(
-      pre_sample_rate_converted_response.Get(), false, sample_rate));
+      pre_sample_rate_converted_response.get(), false, sample_rate));
   AudioChannel* left_ear_impulse_response =
       response->Channel(AudioBus::kChannelLeft);
   AudioChannel* right_ear_impulse_response =
@@ -232,9 +231,9 @@
     return nullptr;
 
   std::unique_ptr<HRTFKernelList> kernel_list_l =
-      WTF::MakeUnique<HRTFKernelList>(kNumberOfTotalAzimuths);
+      std::make_unique<HRTFKernelList>(kNumberOfTotalAzimuths);
   std::unique_ptr<HRTFKernelList> kernel_list_r =
-      WTF::MakeUnique<HRTFKernelList>(kNumberOfTotalAzimuths);
+      std::make_unique<HRTFKernelList>(kNumberOfTotalAzimuths);
 
   // Load convolution kernels from HRTF files.
   int interpolated_index = 0;
@@ -289,9 +288,9 @@
   DCHECK_LT(x, 1.0);
 
   std::unique_ptr<HRTFKernelList> kernel_list_l =
-      WTF::MakeUnique<HRTFKernelList>(kNumberOfTotalAzimuths);
+      std::make_unique<HRTFKernelList>(kNumberOfTotalAzimuths);
   std::unique_ptr<HRTFKernelList> kernel_list_r =
-      WTF::MakeUnique<HRTFKernelList>(kNumberOfTotalAzimuths);
+      std::make_unique<HRTFKernelList>(kNumberOfTotalAzimuths);
 
   HRTFKernelList* kernel_list_l1 = hrtf_elevation1->KernelListL();
   HRTFKernelList* kernel_list_r1 = hrtf_elevation1->KernelListR();
diff --git a/third_party/WebKit/Source/platform/audio/HRTFKernel.cpp b/third_party/WebKit/Source/platform/audio/HRTFKernel.cpp
index 4bc1b3d..6102cad9 100644
--- a/third_party/WebKit/Source/platform/audio/HRTFKernel.cpp
+++ b/third_party/WebKit/Source/platform/audio/HRTFKernel.cpp
@@ -97,7 +97,7 @@
     }
   }
 
-  fft_frame_ = WTF::MakeUnique<FFTFrame>(fft_size);
+  fft_frame_ = std::make_unique<FFTFrame>(fft_size);
   fft_frame_->DoPaddedFFT(impulse_response, truncated_response_length);
 }
 
diff --git a/third_party/WebKit/Source/platform/audio/MultiChannelResampler.cpp b/third_party/WebKit/Source/platform/audio/MultiChannelResampler.cpp
index 96f39fc..61b6b24 100644
--- a/third_party/WebKit/Source/platform/audio/MultiChannelResampler.cpp
+++ b/third_party/WebKit/Source/platform/audio/MultiChannelResampler.cpp
@@ -27,8 +27,9 @@
  */
 
 #include "platform/audio/MultiChannelResampler.h"
+
+#include <memory>
 #include "platform/audio/AudioBus.h"
-#include "platform/wtf/PtrUtil.h"
 
 namespace blink {
 
@@ -62,14 +63,14 @@
       frames_to_process_ = frames_to_process;
       multi_channel_bus_ =
           AudioBus::Create(number_of_channels_, frames_to_process);
-      multi_channel_provider_->ProvideInput(multi_channel_bus_.Get(),
+      multi_channel_provider_->ProvideInput(multi_channel_bus_.get(),
                                             frames_to_process);
     }
 
     // All channels must ask for the same amount. This should always be the
     // case, but let's just make sure.
     bool is_good =
-        multi_channel_bus_.Get() && frames_to_process == frames_to_process_;
+        multi_channel_bus_.get() && frames_to_process == frames_to_process_;
     DCHECK(is_good);
     if (!is_good)
       return;
@@ -101,7 +102,7 @@
   // Create each channel's resampler.
   for (unsigned channel_index = 0; channel_index < number_of_channels;
        ++channel_index)
-    kernels_.push_back(WTF::MakeUnique<SincResampler>(scale_factor));
+    kernels_.push_back(std::make_unique<SincResampler>(scale_factor));
 }
 
 void MultiChannelResampler::Process(AudioSourceProvider* provider,
diff --git a/third_party/WebKit/Source/platform/audio/Panner.cpp b/third_party/WebKit/Source/platform/audio/Panner.cpp
index d6a3cbb..bea4286 100644
--- a/third_party/WebKit/Source/platform/audio/Panner.cpp
+++ b/third_party/WebKit/Source/platform/audio/Panner.cpp
@@ -31,7 +31,6 @@
 #include <memory>
 #include "platform/audio/EqualPowerPanner.h"
 #include "platform/audio/HRTFPanner.h"
-#include "platform/wtf/PtrUtil.h"
 
 namespace blink {
 
@@ -40,10 +39,10 @@
                                        HRTFDatabaseLoader* database_loader) {
   switch (model) {
     case kPanningModelEqualPower:
-      return WTF::MakeUnique<EqualPowerPanner>(sample_rate);
+      return std::make_unique<EqualPowerPanner>(sample_rate);
 
     case kPanningModelHRTF:
-      return WTF::MakeUnique<HRTFPanner>(sample_rate, database_loader);
+      return std::make_unique<HRTFPanner>(sample_rate, database_loader);
 
     default:
       NOTREACHED();
diff --git a/third_party/WebKit/Source/platform/audio/PushPullFIFO.h b/third_party/WebKit/Source/platform/audio/PushPullFIFO.h
index 9a92fa0f..63b347b8 100644
--- a/third_party/WebKit/Source/platform/audio/PushPullFIFO.h
+++ b/third_party/WebKit/Source/platform/audio/PushPullFIFO.h
@@ -71,7 +71,7 @@
   unsigned NumberOfChannels() const { return fifo_bus_->NumberOfChannels(); }
 
   // TODO(hongchan): For single thread unit test only. Consider refactoring.
-  AudioBus* GetFIFOBusForTest() const { return fifo_bus_.Get(); }
+  AudioBus* GetFIFOBusForTest() const { return fifo_bus_.get(); }
 
   // For single thread unit test only. Get the current configuration that
   // consists of FIFO length, number of channels, read/write index position and
diff --git a/third_party/WebKit/Source/platform/audio/PushPullFIFOMultithreadTest.cpp b/third_party/WebKit/Source/platform/audio/PushPullFIFOMultithreadTest.cpp
index 276256e6..4545a4d 100644
--- a/third_party/WebKit/Source/platform/audio/PushPullFIFOMultithreadTest.cpp
+++ b/third_party/WebKit/Source/platform/audio/PushPullFIFOMultithreadTest.cpp
@@ -12,7 +12,6 @@
 #include "platform/audio/AudioUtilities.h"
 #include "platform/testing/UnitTestHelpers.h"
 #include "platform/wtf/Functional.h"
-#include "platform/wtf/PtrUtil.h"
 #include "public/platform/Platform.h"
 #include "public/platform/WebThread.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -29,7 +28,7 @@
       : fifo_(fifo),
         bus_(AudioBus::Create(fifo->NumberOfChannels(), bus_length)),
         client_thread_(Platform::Current()->CreateThread("client thread")),
-        done_event_(WTF::MakeUnique<WaitableEvent>()),
+        done_event_(std::make_unique<WaitableEvent>()),
         jitter_range_ms_(jitter_range_ms) {}
 
   WaitableEvent* Start(double duration_ms, double interval_ms) {
@@ -45,13 +44,9 @@
   virtual void Stop(int callback_counter) = 0;
   virtual void RunTask() = 0;
 
-  void Pull(size_t frames_to_pull) {
-    fifo_->Pull(bus_.Get(), frames_to_pull);
-  }
+  void Pull(size_t frames_to_pull) { fifo_->Pull(bus_.get(), frames_to_pull); }
 
-  void Push() {
-    fifo_->Push(bus_.Get());
-  }
+  void Push() { fifo_->Push(bus_.get()); }
 
  private:
   void RunTaskOnOwnThread() {
diff --git a/third_party/WebKit/Source/platform/audio/PushPullFIFOTest.cpp b/third_party/WebKit/Source/platform/audio/PushPullFIFOTest.cpp
index c0d1b77..4e71bbd 100644
--- a/third_party/WebKit/Source/platform/audio/PushPullFIFOTest.cpp
+++ b/third_party/WebKit/Source/platform/audio/PushPullFIFOTest.cpp
@@ -38,20 +38,20 @@
   // i.e.) input_bus->length() == kRenderQuantumFrames
   RefPtr<AudioBus> input_bus_129_frames =
       AudioBus::Create(2, AudioUtilities::kRenderQuantumFrames + 1);
-  EXPECT_DEATH(test_fifo->Push(input_bus_129_frames.Get()), "");
+  EXPECT_DEATH(test_fifo->Push(input_bus_129_frames.get()), "");
   RefPtr<AudioBus> input_bus_127_frames =
       AudioBus::Create(2, AudioUtilities::kRenderQuantumFrames - 1);
-  EXPECT_DEATH(test_fifo->Push(input_bus_127_frames.Get()), "");
+  EXPECT_DEATH(test_fifo->Push(input_bus_127_frames.get()), "");
 
   // Pull request frames cannot exceed the length of output bus.
   // i.e.) frames_requested <= output_bus->length()
   RefPtr<AudioBus> output_bus_512_frames = AudioBus::Create(2, 512);
-  EXPECT_DEATH(test_fifo->Pull(output_bus_512_frames.Get(), 513), "");
+  EXPECT_DEATH(test_fifo->Pull(output_bus_512_frames.get(), 513), "");
 
   // Pull request frames cannot exceed the length of FIFO.
   // i.e.) frames_requested <= fifo_length_
   RefPtr<AudioBus> output_bus_1025_frames = AudioBus::Create(2, 1025);
-  EXPECT_DEATH(test_fifo->Pull(output_bus_1025_frames.Get(), 1025), "");
+  EXPECT_DEATH(test_fifo->Pull(output_bus_1025_frames.get(), 1025), "");
 }
 
 // Fills each AudioChannel in an AudioBus with a series of linearly increasing
@@ -152,14 +152,14 @@
     if (strcmp(action.action, "PUSH") == 0) {
       RefPtr<AudioBus> input_bus =
           AudioBus::Create(setup.number_of_channels, action.number_of_frames);
-      frame_counter = FillBusWithLinearRamp(input_bus.Get(), frame_counter);
-      fifo->Push(input_bus.Get());
+      frame_counter = FillBusWithLinearRamp(input_bus.get(), frame_counter);
+      fifo->Push(input_bus.get());
       LOG(INFO) << "PUSH " << action.number_of_frames
                 << " frames (frameCounter=" << frame_counter << ")";
     } else {
       output_bus =
           AudioBus::Create(setup.number_of_channels, action.number_of_frames);
-      fifo->Pull(output_bus.Get(), action.number_of_frames);
+      fifo->Pull(output_bus.get(), action.number_of_frames);
       LOG(INFO) << "PULL " << action.number_of_frames << " frames";
     }
   }
@@ -182,7 +182,7 @@
   // Verify samples from the most recent output bus.
   for (const auto& sample : expected_state.output_samples) {
     EXPECT_TRUE(
-        VerifyBusValueAtIndex(output_bus.Get(), sample.index, sample.value));
+        VerifyBusValueAtIndex(output_bus.get(), sample.index, sample.value));
   }
 }
 
diff --git a/third_party/WebKit/Source/platform/audio/ReverbConvolverStage.cpp b/third_party/WebKit/Source/platform/audio/ReverbConvolverStage.cpp
index 69672c2c..8ef1557 100644
--- a/third_party/WebKit/Source/platform/audio/ReverbConvolverStage.cpp
+++ b/third_party/WebKit/Source/platform/audio/ReverbConvolverStage.cpp
@@ -27,6 +27,8 @@
  */
 
 #include "platform/audio/ReverbConvolverStage.h"
+
+#include <memory>
 #include "platform/audio/ReverbAccumulationBuffer.h"
 #include "platform/audio/ReverbConvolver.h"
 #include "platform/audio/ReverbInputBuffer.h"
@@ -56,16 +58,16 @@
   DCHECK(accumulation_buffer);
 
   if (!direct_mode_) {
-    fft_kernel_ = WTF::MakeUnique<FFTFrame>(fft_size);
+    fft_kernel_ = std::make_unique<FFTFrame>(fft_size);
     fft_kernel_->DoPaddedFFT(impulse_response + stage_offset, stage_length);
-    fft_convolver_ = WTF::MakeUnique<FFTConvolver>(fft_size);
+    fft_convolver_ = std::make_unique<FFTConvolver>(fft_size);
   } else {
     DCHECK(!stage_offset);
     DCHECK_LE(stage_length, fft_size / 2);
 
     direct_kernel_ = WTF::WrapUnique(new AudioFloatArray(fft_size / 2));
     direct_kernel_->CopyToRange(impulse_response, 0, stage_length);
-    direct_convolver_ = WTF::MakeUnique<DirectConvolver>(render_slice_size);
+    direct_convolver_ = std::make_unique<DirectConvolver>(render_slice_size);
   }
   temporary_buffer_.Allocate(render_slice_size);
 
diff --git a/third_party/WebKit/Source/platform/audio/SincResampler.cpp b/third_party/WebKit/Source/platform/audio/SincResampler.cpp
index b46acc9a..a1285a1 100644
--- a/third_party/WebKit/Source/platform/audio/SincResampler.cpp
+++ b/third_party/WebKit/Source/platform/audio/SincResampler.cpp
@@ -144,7 +144,7 @@
   // FIXME: Find a way to make the following const-correct:
   bus->SetChannelMemory(0, buffer, number_of_source_frames);
 
-  source_provider_->ProvideInput(bus.Get(), number_of_source_frames);
+  source_provider_->ProvideInput(bus.get(), number_of_source_frames);
 }
 
 namespace {
diff --git a/third_party/WebKit/Source/platform/bindings/DOMWrapperWorld.cpp b/third_party/WebKit/Source/platform/bindings/DOMWrapperWorld.cpp
index 04fac35..b924d92 100644
--- a/third_party/WebKit/Source/platform/bindings/DOMWrapperWorld.cpp
+++ b/third_party/WebKit/Source/platform/bindings/DOMWrapperWorld.cpp
@@ -181,7 +181,7 @@
   DCHECK(this->IsIsolatedWorld());
   IsolatedWorldSecurityOriginMap& origins = IsolatedWorldSecurityOrigins();
   IsolatedWorldSecurityOriginMap::iterator it = origins.find(GetWorldId());
-  return it == origins.end() ? 0 : it->value.Get();
+  return it == origins.end() ? 0 : it->value.get();
 }
 
 void DOMWrapperWorld::SetIsolatedWorldSecurityOrigin(
diff --git a/third_party/WebKit/Source/platform/bindings/ScriptState.h b/third_party/WebKit/Source/platform/bindings/ScriptState.h
index 043987c..2baf97d3 100644
--- a/third_party/WebKit/Source/platform/bindings/ScriptState.h
+++ b/third_party/WebKit/Source/platform/bindings/ScriptState.h
@@ -180,8 +180,8 @@
       context_.Set(script_state_->GetIsolate(), script_state_->GetContext());
   }
 
-  ScriptState* operator->() const { return script_state_.Get(); }
-  ScriptState* Get() const { return script_state_.Get(); }
+  ScriptState* operator->() const { return script_state_.get(); }
+  ScriptState* Get() const { return script_state_.get(); }
   void Clear() {
     script_state_ = nullptr;
     context_.Clear();
diff --git a/third_party/WebKit/Source/platform/bindings/ScriptWrappableVisitor.cpp b/third_party/WebKit/Source/platform/bindings/ScriptWrappableVisitor.cpp
index f9790066..993d1b64 100644
--- a/third_party/WebKit/Source/platform/bindings/ScriptWrappableVisitor.cpp
+++ b/third_party/WebKit/Source/platform/bindings/ScriptWrappableVisitor.cpp
@@ -96,8 +96,10 @@
 }
 
 void ScriptWrappableVisitor::ScheduleIdleLazyCleanup() {
-  // Some threads (e.g. PPAPI thread) don't have a scheduler.
-  if (!Platform::Current()->CurrentThread()->Scheduler())
+  WebThread* const thread = Platform::Current()->CurrentThread();
+  // Thread might already be gone, or some threads (e.g. PPAPI) don't have a
+  // scheduler.
+  if (!thread || !thread->Scheduler())
     return;
 
   if (idle_cleanup_task_scheduled_)
diff --git a/third_party/WebKit/Source/platform/bindings/V8ValueCache.h b/third_party/WebKit/Source/platform/bindings/V8ValueCache.h
index 9bf17e9..fa3b7d8 100644
--- a/third_party/WebKit/Source/platform/bindings/V8ValueCache.h
+++ b/third_party/WebKit/Source/platform/bindings/V8ValueCache.h
@@ -89,7 +89,7 @@
   v8::Local<v8::String> V8ExternalString(v8::Isolate* isolate,
                                          StringImpl* string_impl) {
     DCHECK(string_impl);
-    if (last_string_impl_.Get() == string_impl)
+    if (last_string_impl_.get() == string_impl)
       return last_v8_string_.NewLocal(isolate);
     return V8ExternalStringSlow(isolate, string_impl);
   }
@@ -97,7 +97,7 @@
   void SetReturnValueFromString(v8::ReturnValue<v8::Value> return_value,
                                 StringImpl* string_impl) {
     DCHECK(string_impl);
-    if (last_string_impl_.Get() == string_impl)
+    if (last_string_impl_.get() == string_impl)
       last_v8_string_.SetReturnValue(return_value);
     else
       SetReturnValueFromStringSlow(return_value, string_impl);
diff --git a/third_party/WebKit/Source/platform/exported/WebAudioBus.cpp b/third_party/WebKit/Source/platform/exported/WebAudioBus.cpp
index 9e6484f..f7833c60 100644
--- a/third_party/WebKit/Source/platform/exported/WebAudioBus.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebAudioBus.cpp
@@ -29,8 +29,6 @@
 
 namespace blink {
 
-class WebAudioBusPrivate : public AudioBus {};
-
 void WebAudioBus::Initialize(unsigned number_of_channels,
                              size_t length,
                              double sample_rate) {
@@ -38,10 +36,9 @@
   audio_bus->SetSampleRate(sample_rate);
 
   if (private_)
-    (static_cast<AudioBus*>(private_))->Deref();
+    private_->Deref();
 
-  audio_bus->Ref();
-  private_ = static_cast<WebAudioBusPrivate*>(audio_bus.Get());
+  private_ = audio_bus.LeakRef();
 }
 
 void WebAudioBus::ResizeSmaller(size_t new_length) {
@@ -54,8 +51,8 @@
 
 void WebAudioBus::Reset() {
   if (private_) {
-    (static_cast<AudioBus*>(private_))->Deref();
-    private_ = 0;
+    private_->Deref();
+    private_ = nullptr;
   }
 }
 
@@ -79,14 +76,15 @@
 
 float* WebAudioBus::ChannelData(unsigned channel_index) {
   if (!private_)
-    return 0;
+    return nullptr;
   DCHECK_LT(channel_index, NumberOfChannels());
   return private_->Channel(channel_index)->MutableData();
 }
 
 RefPtr<AudioBus> WebAudioBus::Release() {
-  RefPtr<AudioBus> audio_bus(WTF::AdoptRef(static_cast<AudioBus*>(private_)));
-  private_ = 0;
+  RefPtr<AudioBus> audio_bus(private_);
+  private_->Deref();
+  private_ = nullptr;
   return audio_bus;
 }
 
diff --git a/third_party/WebKit/Source/platform/exported/WebCredential.cpp b/third_party/WebKit/Source/platform/exported/WebCredential.cpp
index f013022..f01c886 100644
--- a/third_party/WebKit/Source/platform/exported/WebCredential.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebCredential.cpp
@@ -4,8 +4,8 @@
 
 #include "public/platform/WebCredential.h"
 
+#include <memory>
 #include "platform/credentialmanager/PlatformCredential.h"
-#include "platform/wtf/PtrUtil.h"
 #include "public/platform/WebFederatedCredential.h"
 #include "public/platform/WebPasswordCredential.h"
 
@@ -14,11 +14,11 @@
 std::unique_ptr<WebCredential> WebCredential::Create(
     PlatformCredential* credential) {
   if (credential->IsPassword()) {
-    return WTF::MakeUnique<WebPasswordCredential>(credential);
+    return std::make_unique<WebPasswordCredential>(credential);
   }
 
   if (credential->IsFederated()) {
-    return WTF::MakeUnique<WebFederatedCredential>(credential);
+    return std::make_unique<WebFederatedCredential>(credential);
   }
 
   NOTREACHED();
diff --git a/third_party/WebKit/Source/platform/exported/WebCryptoKeyAlgorithm.cpp b/third_party/WebKit/Source/platform/exported/WebCryptoKeyAlgorithm.cpp
index a788d0f..0744222 100644
--- a/third_party/WebKit/Source/platform/exported/WebCryptoKeyAlgorithm.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebCryptoKeyAlgorithm.cpp
@@ -31,7 +31,6 @@
 #include "public/platform/WebCryptoKeyAlgorithm.h"
 
 #include <memory>
-#include "platform/wtf/PtrUtil.h"
 #include "platform/wtf/ThreadSafeRefCounted.h"
 
 namespace blink {
@@ -74,7 +73,7 @@
       key_length_bits != 256)
     return WebCryptoKeyAlgorithm();
   return WebCryptoKeyAlgorithm(
-      id, WTF::MakeUnique<WebCryptoAesKeyAlgorithmParams>(key_length_bits));
+      id, std::make_unique<WebCryptoAesKeyAlgorithmParams>(key_length_bits));
 }
 
 WebCryptoKeyAlgorithm WebCryptoKeyAlgorithm::CreateHmac(
@@ -107,7 +106,7 @@
     WebCryptoAlgorithmId id,
     WebCryptoNamedCurve named_curve) {
   return WebCryptoKeyAlgorithm(
-      id, WTF::MakeUnique<WebCryptoEcKeyAlgorithmParams>(named_curve));
+      id, std::make_unique<WebCryptoEcKeyAlgorithmParams>(named_curve));
 }
 
 WebCryptoKeyAlgorithm WebCryptoKeyAlgorithm::CreateWithoutParams(
diff --git a/third_party/WebKit/Source/platform/exported/WebImageTest.cpp b/third_party/WebKit/Source/platform/exported/WebImageTest.cpp
index df9d6f3d..fb06d7bf 100644
--- a/third_party/WebKit/Source/platform/exported/WebImageTest.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebImageTest.cpp
@@ -46,7 +46,7 @@
 
 TEST(WebImageTest, PNGImage) {
   RefPtr<SharedBuffer> data = ReadFile("white-1x1.png");
-  ASSERT_TRUE(data.Get());
+  ASSERT_TRUE(data.get());
 
   WebImage image = WebImage::FromData(WebData(data), WebSize());
   EXPECT_TRUE(image.Size() == WebSize(1, 1));
@@ -56,7 +56,7 @@
 
 TEST(WebImageTest, ICOImage) {
   RefPtr<SharedBuffer> data = ReadFile("black-and-white.ico");
-  ASSERT_TRUE(data.Get());
+  ASSERT_TRUE(data.get());
 
   WebVector<WebImage> images = WebImage::FramesFromData(WebData(data));
   ASSERT_EQ(2u, images.size());
@@ -70,7 +70,7 @@
 
 TEST(WebImageTest, ICOValidHeaderMissingBitmap) {
   RefPtr<SharedBuffer> data = ReadFile("valid_header_missing_bitmap.ico");
-  ASSERT_TRUE(data.Get());
+  ASSERT_TRUE(data.get());
 
   WebVector<WebImage> images = WebImage::FramesFromData(WebData(data));
   ASSERT_TRUE(images.IsEmpty());
diff --git a/third_party/WebKit/Source/platform/exported/WebPrerender.cpp b/third_party/WebKit/Source/platform/exported/WebPrerender.cpp
index b84c506..9227ab5 100644
--- a/third_party/WebKit/Source/platform/exported/WebPrerender.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebPrerender.cpp
@@ -101,7 +101,7 @@
   RefPtr<Prerender::ExtraData> webcore_extra_data = private_->GetExtraData();
   if (!webcore_extra_data)
     return 0;
-  return static_cast<PrerenderExtraDataContainer*>(webcore_extra_data.Get())
+  return static_cast<PrerenderExtraDataContainer*>(webcore_extra_data.get())
       ->GetExtraData();
 }
 
diff --git a/third_party/WebKit/Source/platform/exported/WebRuntimeFeatures.cpp b/third_party/WebKit/Source/platform/exported/WebRuntimeFeatures.cpp
index 054f7f2e..05b2b66c 100644
--- a/third_party/WebKit/Source/platform/exported/WebRuntimeFeatures.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebRuntimeFeatures.cpp
@@ -184,6 +184,10 @@
   RuntimeEnabledFeatures::SetMediaSessionEnabled(enable);
 }
 
+void WebRuntimeFeatures::EnableModernMediaControls(bool enable) {
+  RuntimeEnabledFeatures::SetModernMediaControlsEnabled(enable);
+}
+
 void WebRuntimeFeatures::EnableModuleScripts(bool enable) {
   RuntimeEnabledFeatures::SetModuleScriptsEnabled(enable);
 }
diff --git a/third_party/WebKit/Source/platform/exported/WebServiceWorkerInstalledScriptsManager.cpp b/third_party/WebKit/Source/platform/exported/WebServiceWorkerInstalledScriptsManager.cpp
index e54b1fc0..3ba7905 100644
--- a/third_party/WebKit/Source/platform/exported/WebServiceWorkerInstalledScriptsManager.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebServiceWorkerInstalledScriptsManager.cpp
@@ -4,6 +4,8 @@
 
 #include "public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h"
 
+#include <memory>
+
 namespace blink {
 
 // static
@@ -35,7 +37,7 @@
       encoding_(std::move(encoding)),
       script_text_(std::move(script_text)),
       meta_data_(std::move(meta_data)),
-      headers_(WTF::MakeUnique<CrossThreadHTTPHeaderMapData>()) {}
+      headers_(std::make_unique<CrossThreadHTTPHeaderMapData>()) {}
 
 WebServiceWorkerInstalledScriptsManager::RawScriptData::~RawScriptData() =
     default;
diff --git a/third_party/WebKit/Source/platform/exported/WebString.cpp b/third_party/WebKit/Source/platform/exported/WebString.cpp
index 2147203..1f5280b 100644
--- a/third_party/WebKit/Source/platform/exported/WebString.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebString.cpp
@@ -59,7 +59,7 @@
 }
 
 void WebString::Assign(const WebUChar* data, size_t length) {
-  Assign(StringImpl::Create8BitIfPossible(data, length).Get());
+  Assign(StringImpl::Create8BitIfPossible(data, length).get());
 }
 
 size_t WebString::length() const {
diff --git a/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp b/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp
index a17e498..731f873 100644
--- a/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp
@@ -374,7 +374,7 @@
   RefPtr<ResourceRequest::ExtraData> data = resource_request_->GetExtraData();
   if (!data)
     return 0;
-  return static_cast<URLRequestExtraDataContainer*>(data.Get())->GetExtraData();
+  return static_cast<URLRequestExtraDataContainer*>(data.get())->GetExtraData();
 }
 
 void WebURLRequest::SetExtraData(WebURLRequest::ExtraData* extra_data) {
diff --git a/third_party/WebKit/Source/platform/exported/WebURLResponse.cpp b/third_party/WebKit/Source/platform/exported/WebURLResponse.cpp
index ee21ca9..5aaaee6 100644
--- a/third_party/WebKit/Source/platform/exported/WebURLResponse.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebURLResponse.cpp
@@ -363,7 +363,7 @@
   RefPtr<ResourceResponse::ExtraData> data = resource_response_->GetExtraData();
   if (!data)
     return 0;
-  return static_cast<URLResponseExtraDataContainer*>(data.Get())
+  return static_cast<URLResponseExtraDataContainer*>(data.get())
       ->GetExtraData();
 }
 
diff --git a/third_party/WebKit/Source/platform/feature_policy/FeaturePolicyFuzzer.cpp b/third_party/WebKit/Source/platform/feature_policy/FeaturePolicyFuzzer.cpp
index 6661e361..152911bf 100644
--- a/third_party/WebKit/Source/platform/feature_policy/FeaturePolicyFuzzer.cpp
+++ b/third_party/WebKit/Source/platform/feature_policy/FeaturePolicyFuzzer.cpp
@@ -20,7 +20,7 @@
   // TODO(csharrison): Be smarter about parsing this origin for performance.
   RefPtr<blink::SecurityOrigin> origin =
       blink::SecurityOrigin::CreateFromString("https://example.com/");
-  blink::ParseFeaturePolicyHeader(WTF::String(data, size), origin.Get(),
+  blink::ParseFeaturePolicyHeader(WTF::String(data, size), origin.get(),
                                   &messages);
   return 0;
 }
diff --git a/third_party/WebKit/Source/platform/feature_policy/FeaturePolicyTest.cpp b/third_party/WebKit/Source/platform/feature_policy/FeaturePolicyTest.cpp
index 85bec50..9f7cd4e 100644
--- a/third_party/WebKit/Source/platform/feature_policy/FeaturePolicyTest.cpp
+++ b/third_party/WebKit/Source/platform/feature_policy/FeaturePolicyTest.cpp
@@ -72,7 +72,7 @@
   Vector<String> messages;
   for (const char* policy_string : kValidPolicies) {
     messages.clear();
-    ParseFeaturePolicy(policy_string, origin_a_.Get(), origin_b_.Get(),
+    ParseFeaturePolicy(policy_string, origin_a_.get(), origin_b_.get(),
                        &messages, test_feature_name_map);
     EXPECT_EQ(0UL, messages.size());
   }
@@ -82,7 +82,7 @@
   Vector<String> messages;
   for (const char* policy_string : kInvalidPolicies) {
     messages.clear();
-    ParseFeaturePolicy(policy_string, origin_a_.Get(), origin_b_.Get(),
+    ParseFeaturePolicy(policy_string, origin_a_.get(), origin_b_.get(),
                        &messages, test_feature_name_map);
     EXPECT_NE(0UL, messages.size());
   }
@@ -93,12 +93,12 @@
 
   // Empty policy.
   WebParsedFeaturePolicy parsed_policy = ParseFeaturePolicy(
-      "", origin_a_.Get(), origin_b_.Get(), &messages, test_feature_name_map);
+      "", origin_a_.get(), origin_b_.get(), &messages, test_feature_name_map);
   EXPECT_EQ(0UL, parsed_policy.size());
 
   // Simple policy with 'self'.
   parsed_policy =
-      ParseFeaturePolicy("vibrate 'self'", origin_a_.Get(), origin_b_.Get(),
+      ParseFeaturePolicy("vibrate 'self'", origin_a_.get(), origin_b_.get(),
                          &messages, test_feature_name_map);
   EXPECT_EQ(1UL, parsed_policy.size());
 
@@ -109,7 +109,7 @@
       parsed_policy[0].origins[0].Get()));
   // Simple policy with *.
   parsed_policy =
-      ParseFeaturePolicy("vibrate *", origin_a_.Get(), origin_b_.Get(),
+      ParseFeaturePolicy("vibrate *", origin_a_.get(), origin_b_.get(),
                          &messages, test_feature_name_map);
   EXPECT_EQ(1UL, parsed_policy.size());
   EXPECT_EQ(WebFeaturePolicyFeature::kVibrate, parsed_policy[0].feature);
@@ -121,7 +121,7 @@
       "vibrate *; "
       "fullscreen https://example.net https://example.org; "
       "payment 'self'",
-      origin_a_.Get(), origin_b_.Get(), &messages, test_feature_name_map);
+      origin_a_.get(), origin_b_.get(), &messages, test_feature_name_map);
   EXPECT_EQ(3UL, parsed_policy.size());
   EXPECT_EQ(WebFeaturePolicyFeature::kVibrate, parsed_policy[0].feature);
   EXPECT_TRUE(parsed_policy[0].matches_all_origins);
@@ -144,7 +144,7 @@
       "vibrate * https://example.net; "
       "fullscreen https://example.net none https://example.org,"
       "payment 'self' badorigin",
-      origin_a_.Get(), origin_b_.Get(), &messages, test_feature_name_map);
+      origin_a_.get(), origin_b_.get(), &messages, test_feature_name_map);
   EXPECT_EQ(3UL, parsed_policy.size());
   EXPECT_EQ(WebFeaturePolicyFeature::kVibrate, parsed_policy[0].feature);
   EXPECT_TRUE(parsed_policy[0].matches_all_origins);
@@ -166,7 +166,7 @@
   messages.clear();
   parsed_policy =
       ParseFeaturePolicy("vibrate badname fullscreen payment", nullptr,
-                         origin_a_.Get(), &messages, test_feature_name_map);
+                         origin_a_.get(), &messages, test_feature_name_map);
   // Expect 2 messages: one about deprecation warning, one about unrecognized
   // feature name.
   EXPECT_EQ(2UL, messages.size());
@@ -189,7 +189,7 @@
 
   // Header policies with no optional origin lists.
   parsed_policy =
-      ParseFeaturePolicy("vibrate;fullscreen;payment", origin_a_.Get(), nullptr,
+      ParseFeaturePolicy("vibrate;fullscreen;payment", origin_a_.get(), nullptr,
                          &messages, test_feature_name_map);
   EXPECT_EQ(3UL, parsed_policy.size());
   EXPECT_EQ(WebFeaturePolicyFeature::kVibrate, parsed_policy[0].feature);
diff --git a/third_party/WebKit/Source/platform/fonts/FontCache.cpp b/third_party/WebKit/Source/platform/fonts/FontCache.cpp
index 7371502..eb2208f 100644
--- a/third_party/WebKit/Source/platform/fonts/FontCache.cpp
+++ b/third_party/WebKit/Source/platform/fonts/FontCache.cpp
@@ -53,7 +53,6 @@
 #include "platform/runtime_enabled_features.h"
 #include "platform/wtf/HashMap.h"
 #include "platform/wtf/ListHashSet.h"
-#include "platform/wtf/PtrUtil.h"
 #include "platform/wtf/StdLibExtras.h"
 #include "platform/wtf/Vector.h"
 #include "platform/wtf/debug/Alias.h"
@@ -186,7 +185,7 @@
 #if defined(OS_MACOSX)
   return CreateFontPlatformData(font_description, creation_params, font_size);
 #else
-  return WTF::MakeUnique<FontPlatformData>(font_platform_data, font_size);
+  return std::make_unique<FontPlatformData>(font_platform_data, font_size);
 #endif
 }
 
diff --git a/third_party/WebKit/Source/platform/fonts/FontData.h b/third_party/WebKit/Source/platform/fonts/FontData.h
index e517c9d..239715d 100644
--- a/third_party/WebKit/Source/platform/fonts/FontData.h
+++ b/third_party/WebKit/Source/platform/fonts/FontData.h
@@ -59,7 +59,7 @@
 #define DEFINE_FONT_DATA_TYPE_CASTS(thisType, predicate)     \
   template <typename T>                                      \
   inline thisType* To##thisType(const RefPtr<T>& fontData) { \
-    return To##thisType(fontData.Get());                     \
+    return To##thisType(fontData.get());                     \
   }                                                          \
   DEFINE_TYPE_CASTS(thisType, FontData, fontData,            \
                     fontData->IsSegmented() == predicate,    \
diff --git a/third_party/WebKit/Source/platform/fonts/FontDataForRangeSet.cpp b/third_party/WebKit/Source/platform/fonts/FontDataForRangeSet.cpp
index 4b030d5..305e387b 100644
--- a/third_party/WebKit/Source/platform/fonts/FontDataForRangeSet.cpp
+++ b/third_party/WebKit/Source/platform/fonts/FontDataForRangeSet.cpp
@@ -15,7 +15,7 @@
 
 FontDataForRangeSetFromCache::~FontDataForRangeSetFromCache() {
   if (font_data_ && !font_data_->IsCustomFont()) {
-    FontCache::GetFontCache()->ReleaseFontData(font_data_.Get());
+    FontCache::GetFontCache()->ReleaseFontData(font_data_.get());
   }
 }
 
diff --git a/third_party/WebKit/Source/platform/fonts/FontDataForRangeSet.h b/third_party/WebKit/Source/platform/fonts/FontDataForRangeSet.h
index b53c394b..84a09d9 100644
--- a/third_party/WebKit/Source/platform/fonts/FontDataForRangeSet.h
+++ b/third_party/WebKit/Source/platform/fonts/FontDataForRangeSet.h
@@ -53,9 +53,9 @@
   bool IsEntireRange() const {
     return !range_set_ || range_set_->IsEntireRange();
   }
-  UnicodeRangeSet* Ranges() const { return range_set_.Get(); }
-  bool HasFontData() const { return font_data_.Get(); }
-  const SimpleFontData* FontData() const { return font_data_.Get(); }
+  UnicodeRangeSet* Ranges() const { return range_set_.get(); }
+  bool HasFontData() const { return font_data_.get(); }
+  const SimpleFontData* FontData() const { return font_data_.get(); }
 
  protected:
   RefPtr<SimpleFontData> font_data_;
diff --git a/third_party/WebKit/Source/platform/fonts/FontDescription.cpp b/third_party/WebKit/Source/platform/fonts/FontDescription.cpp
index 986398d6..054ac50c 100644
--- a/third_party/WebKit/Source/platform/fonts/FontDescription.cpp
+++ b/third_party/WebKit/Source/platform/fonts/FontDescription.cpp
@@ -448,7 +448,6 @@
 }
 
 String FontDescription::ToString() const {
-  // TODO(wkorman): Incorporate |variant_numeric| and |variant_east_asian|.
   return String::Format(
       "family_list=[%s], feature_settings=[%s], variation_settings=[%s], "
       "locale=%s, "
@@ -461,7 +460,8 @@
       "variant_ligatures=[%s], "
       "keyword_size=%u, font_smoothing=%s, text_rendering=%s, "
       "synthetic_bold=%s, synthetic_italic=%s, subpixel_positioning=%s, "
-      "subpixel_ascent_descent=%s",
+      "subpixel_ascent_descent=%s, variant_numeric=[%s], "
+      "variant_east_asian=[%s]",
       family_list_.ToString().Ascii().data(),
       (feature_settings_ ? feature_settings_->ToString().Ascii().data() : ""),
       (variation_settings_ ? variation_settings_->ToString().Ascii().data()
@@ -487,7 +487,9 @@
       blink::ToString(TextRendering()).Ascii().data(),
       ToBooleanString(IsSyntheticBold()), ToBooleanString(IsSyntheticItalic()),
       ToBooleanString(UseSubpixelPositioning()),
-      ToBooleanString(SubpixelAscentDescent()));
+      ToBooleanString(SubpixelAscentDescent()),
+      VariantNumeric().ToString().Ascii().data(),
+      VariantEastAsian().ToString().Ascii().data());
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/FontDescription.h b/third_party/WebKit/Source/platform/fonts/FontDescription.h
index 90ed273..bdae47e 100644
--- a/third_party/WebKit/Source/platform/fonts/FontDescription.h
+++ b/third_party/WebKit/Source/platform/fonts/FontDescription.h
@@ -204,9 +204,9 @@
   TextRenderingMode TextRendering() const {
     return static_cast<TextRenderingMode>(fields_.text_rendering_);
   }
-  const LayoutLocale* Locale() const { return locale_.Get(); }
+  const LayoutLocale* Locale() const { return locale_.get(); }
   const LayoutLocale& LocaleOrDefault() const {
-    return LayoutLocale::ValueOrDefault(locale_.Get());
+    return LayoutLocale::ValueOrDefault(locale_.get());
   }
   UScriptCode GetScript() const { return LocaleOrDefault().GetScript(); }
   bool IsSyntheticBold() const { return fields_.synthetic_bold_; }
@@ -237,10 +237,10 @@
     return static_cast<FontWidthVariant>(fields_.width_variant_);
   }
   FontFeatureSettings* FeatureSettings() const {
-    return feature_settings_.Get();
+    return feature_settings_.get();
   }
   FontVariationSettings* VariationSettings() const {
-    return variation_settings_.Get();
+    return variation_settings_.get();
   }
 
   float EffectiveFontSize()
diff --git a/third_party/WebKit/Source/platform/fonts/FontDescriptionTest.cpp b/third_party/WebKit/Source/platform/fonts/FontDescriptionTest.cpp
index 1244656..4b53318 100644
--- a/third_party/WebKit/Source/platform/fonts/FontDescriptionTest.cpp
+++ b/third_party/WebKit/Source/platform/fonts/FontDescriptionTest.cpp
@@ -111,7 +111,11 @@
       "historical=Normal, contextual=Normal], keyword_size=0, "
       "font_smoothing=Auto, text_rendering=OptimizeLegibility, "
       "synthetic_bold=false, synthetic_italic=false, "
-      "subpixel_positioning=false, subpixel_ascent_descent=false",
+      "subpixel_positioning=false, subpixel_ascent_descent=false, "
+      "variant_numeric=[numeric_figure=NormalFigure, "
+      "numeric_spacing=NormalSpacing, numeric_fraction=Normal, ordinal=Off, "
+      "slashed_zero=Off], variant_east_asian=[form=Normal, width=Normal, "
+      "ruby=false]",
       description.ToString());
 }
 
diff --git a/third_party/WebKit/Source/platform/fonts/FontFallbackIterator.cpp b/third_party/WebKit/Source/platform/fonts/FontFallbackIterator.cpp
index 2f647dc..1e88918e8 100644
--- a/third_party/WebKit/Source/platform/fonts/FontFallbackIterator.cpp
+++ b/third_party/WebKit/Source/platform/fonts/FontFallbackIterator.cpp
@@ -115,7 +115,7 @@
     FontCache* font_cache = FontCache::GetFontCache();
     fallback_stage_ = kOutOfLuck;
     RefPtr<SimpleFontData> last_resort =
-        font_cache->GetLastResortFallbackFont(font_description_).Get();
+        font_cache->GetLastResortFallbackFont(font_description_).get();
     if (!last_resort)
       FontCache::CrashWithFontInfo(&font_description_);
     // Don't skip the LastResort font in uniqueOrNext() since HarfBuzzShaper
@@ -175,7 +175,7 @@
     current_font_data_index_++;
   }
 
-  if (RangeSetContributesForHint(hint_list, current_segmented_face.Get())) {
+  if (RangeSetContributesForHint(hint_list, current_segmented_face.get())) {
     const SimpleFontData* font_data = current_segmented_face->FontData();
     if (const CustomFontData* custom_font_data = font_data->GetCustomFontData())
       custom_font_data->BeginLoadIfNeeded();
diff --git a/third_party/WebKit/Source/platform/fonts/FontFallbackList.cpp b/third_party/WebKit/Source/platform/fonts/FontFallbackList.cpp
index 09b75882..00ca971 100644
--- a/third_party/WebKit/Source/platform/fonts/FontFallbackList.cpp
+++ b/third_party/WebKit/Source/platform/fonts/FontFallbackList.cpp
@@ -107,10 +107,9 @@
       if (font_data)
         return font_data->FontDataForCharacter(kSpaceCharacter);
 
+      FontCache* cache = FontCache::GetFontCache();
       SimpleFontData* last_resort_fallback =
-          FontCache::GetFontCache()
-              ->GetLastResortFallbackFont(font_description)
-              .Get();
+          cache->GetLastResortFallbackFont(font_description).get();
       DCHECK(last_resort_fallback);
       return last_resort_fallback;
     }
@@ -217,9 +216,9 @@
 const FontData* FontFallbackList::FontDataAt(
     const FontDescription& font_description,
     unsigned realized_font_index) const {
+  // This fallback font is already in our list.
   if (realized_font_index < font_list_.size())
-    return font_list_[realized_font_index]
-        .Get();  // This fallback font is already in our list.
+    return font_list_[realized_font_index].get();
 
   // Make sure we're not passing in some crazy value here.
   DCHECK_EQ(realized_font_index, font_list_.size());
@@ -239,7 +238,7 @@
     if (result->IsLoadingFallback())
       has_loading_fallback_ = true;
   }
-  return result.Get();
+  return result.get();
 }
 
 bool FontFallbackList::IsValid() const {
diff --git a/third_party/WebKit/Source/platform/fonts/FontFamily.h b/third_party/WebKit/Source/platform/fonts/FontFamily.h
index 16a644f..99973f7b1 100644
--- a/third_party/WebKit/Source/platform/fonts/FontFamily.h
+++ b/third_party/WebKit/Source/platform/fonts/FontFamily.h
@@ -88,7 +88,7 @@
 }
 
 inline const FontFamily* FontFamily::Next() const {
-  return next_.Get();
+  return next_.get();
 }
 
 inline void FontFamily::AppendFamily(RefPtr<SharedFontFamily> family) {
diff --git a/third_party/WebKit/Source/platform/fonts/FontFamilyTest.cpp b/third_party/WebKit/Source/platform/fonts/FontFamilyTest.cpp
index 9cc03b4..0e2d729c3 100644
--- a/third_party/WebKit/Source/platform/fonts/FontFamilyTest.cpp
+++ b/third_party/WebKit/Source/platform/fonts/FontFamilyTest.cpp
@@ -14,7 +14,7 @@
   RefPtr<SharedFontFamily> family = SharedFontFamily::Create();
   family->SetFamily(name);
   parent.AppendFamily(family);
-  return family.Get();
+  return family.get();
 }
 
 }  // namespace
diff --git a/third_party/WebKit/Source/platform/fonts/FontPlatformData.cpp b/third_party/WebKit/Source/platform/fonts/FontPlatformData.cpp
index e615ee0..8e96605 100644
--- a/third_party/WebKit/Source/platform/fonts/FontPlatformData.cpp
+++ b/third_party/WebKit/Source/platform/fonts/FontPlatformData.cpp
@@ -244,7 +244,7 @@
     harf_buzz_face_ =
         HarfBuzzFace::Create(const_cast<FontPlatformData*>(this), UniqueID());
 
-  return harf_buzz_face_.Get();
+  return harf_buzz_face_.get();
 }
 
 static inline bool TableHasSpace(hb_face_t* face,
diff --git a/third_party/WebKit/Source/platform/fonts/FontVariantEastAsian.cpp b/third_party/WebKit/Source/platform/fonts/FontVariantEastAsian.cpp
new file mode 100644
index 0000000..51bff78
--- /dev/null
+++ b/third_party/WebKit/Source/platform/fonts/FontVariantEastAsian.cpp
@@ -0,0 +1,51 @@
+// 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 "platform/fonts/FontVariantEastAsian.h"
+
+#include "platform/wtf/text/WTFString.h"
+
+namespace blink {
+
+static const char* kUnknownString = "Unknown";
+
+String FontVariantEastAsian::ToString(EastAsianForm form) {
+  switch (form) {
+    case EastAsianForm::kNormalForm:
+      return "Normal";
+    case EastAsianForm::kJis78:
+      return "Jis78";
+    case EastAsianForm::kJis83:
+      return "Jis83";
+    case EastAsianForm::kJis90:
+      return "Jis90";
+    case EastAsianForm::kJis04:
+      return "Jis04";
+    case EastAsianForm::kSimplified:
+      return "Simplified";
+    case EastAsianForm::kTraditional:
+      return "Traditional";
+  }
+  return kUnknownString;
+}
+
+String FontVariantEastAsian::ToString(EastAsianWidth width) {
+  switch (width) {
+    case FontVariantEastAsian::kNormalWidth:
+      return "Normal";
+    case FontVariantEastAsian::kFullWidth:
+      return "Full";
+    case FontVariantEastAsian::kProportionalWidth:
+      return "Proportional";
+  }
+  return kUnknownString;
+}
+
+String FontVariantEastAsian::ToString() const {
+  return String::Format(
+      "form=%s, width=%s, ruby=%s", ToString(Form()).Ascii().data(),
+      ToString(Width()).Ascii().data(), Ruby() ? "true" : "false");
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/FontVariantEastAsian.h b/third_party/WebKit/Source/platform/fonts/FontVariantEastAsian.h
index 0efae1d..0953c4d 100644
--- a/third_party/WebKit/Source/platform/fonts/FontVariantEastAsian.h
+++ b/third_party/WebKit/Source/platform/fonts/FontVariantEastAsian.h
@@ -6,6 +6,7 @@
 #define FontVariantEastAsian_h
 
 #include "platform/wtf/Allocator.h"
+#include "platform/wtf/Forward.h"
 
 namespace blink {
 
@@ -23,6 +24,7 @@
     kTraditional
     // Ensure |BitFields| has enough bits when adding values.
   };
+  static String ToString(EastAsianForm);
 
   enum EastAsianWidth {
     kNormalWidth,
@@ -30,6 +32,7 @@
     kProportionalWidth
     // Ensure |BitFields| has enough bits when adding values.
   };
+  static String ToString(EastAsianWidth);
 
   FontVariantEastAsian() : fields_as_unsigned_(0) {}
 
@@ -55,6 +58,8 @@
     return fields_as_unsigned_ == other.fields_as_unsigned_;
   }
 
+  String ToString() const;
+
  private:
   FontVariantEastAsian(unsigned init_value) : fields_as_unsigned_(init_value) {}
 
diff --git a/third_party/WebKit/Source/platform/fonts/FontVariantNumeric.cpp b/third_party/WebKit/Source/platform/fonts/FontVariantNumeric.cpp
new file mode 100644
index 0000000..7face8c
--- /dev/null
+++ b/third_party/WebKit/Source/platform/fonts/FontVariantNumeric.cpp
@@ -0,0 +1,80 @@
+// 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 "platform/fonts/FontVariantNumeric.h"
+
+#include "platform/wtf/text/WTFString.h"
+
+namespace blink {
+
+static const char* kUnknownString = "Unknown";
+
+String FontVariantNumeric::ToString(NumericFigure figure) {
+  switch (figure) {
+    case kNormalFigure:
+      return "NormalFigure";
+    case kLiningNums:
+      return "LiningNums";
+    case kOldstyleNums:
+      return "OldstyleNums";
+  }
+  return kUnknownString;
+}
+
+String FontVariantNumeric::ToString(NumericSpacing spacing) {
+  switch (spacing) {
+    case kNormalSpacing:
+      return "NormalSpacing";
+    case kProportionalNums:
+      return "ProportionalNums";
+    case kTabularNums:
+      return "TabularNums";
+  }
+  return kUnknownString;
+}
+
+String FontVariantNumeric::ToString(NumericFraction fraction) {
+  switch (fraction) {
+    case kNormalFraction:
+      return "Normal";
+    case kDiagonalFractions:
+      return "Diagonal";
+    case kStackedFractions:
+      return "Stacked";
+  }
+  return kUnknownString;
+}
+
+String FontVariantNumeric::ToString(Ordinal ordinal) {
+  switch (ordinal) {
+    case kOrdinalOff:
+      return "Off";
+    case kOrdinalOn:
+      return "On";
+  }
+  return kUnknownString;
+}
+
+String FontVariantNumeric::ToString(SlashedZero slashed) {
+  switch (slashed) {
+    case kSlashedZeroOff:
+      return "Off";
+    case kSlashedZeroOn:
+      return "On";
+  }
+  return kUnknownString;
+}
+
+String FontVariantNumeric::ToString() const {
+  return String::Format(
+      "numeric_figure=%s, numeric_spacing=%s, numeric_fraction=%s, ordinal=%s, "
+      "slashed_zero=%s",
+      ToString(NumericFigureValue()).Ascii().data(),
+      ToString(NumericSpacingValue()).Ascii().data(),
+      ToString(NumericFractionValue()).Ascii().data(),
+      ToString(OrdinalValue()).Ascii().data(),
+      ToString(SlashedZeroValue()).Ascii().data());
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/FontVariantNumeric.h b/third_party/WebKit/Source/platform/fonts/FontVariantNumeric.h
index 4109c9d..0adaafc0 100644
--- a/third_party/WebKit/Source/platform/fonts/FontVariantNumeric.h
+++ b/third_party/WebKit/Source/platform/fonts/FontVariantNumeric.h
@@ -6,6 +6,7 @@
 #define FontVariantNumeric_h
 
 #include "platform/wtf/Allocator.h"
+#include "platform/wtf/Forward.h"
 
 namespace blink {
 
@@ -14,18 +15,23 @@
 
  public:
   enum NumericFigure { kNormalFigure = 0, kLiningNums, kOldstyleNums };
+  static String ToString(NumericFigure);
 
   enum NumericSpacing { kNormalSpacing = 0, kProportionalNums, kTabularNums };
+  static String ToString(NumericSpacing);
 
   enum NumericFraction {
     kNormalFraction = 0,
     kDiagonalFractions,
     kStackedFractions
   };
+  static String ToString(NumericFraction);
 
   enum Ordinal { kOrdinalOff = 0, kOrdinalOn };
+  static String ToString(Ordinal);
 
   enum SlashedZero { kSlashedZeroOff = 0, kSlashedZeroOn };
+  static String ToString(SlashedZero);
 
   FontVariantNumeric() : fields_as_unsigned_(0) {}
 
@@ -69,6 +75,8 @@
     return fields_as_unsigned_ == other.fields_as_unsigned_;
   }
 
+  String ToString() const;
+
  private:
   FontVariantNumeric(unsigned init_value) : fields_as_unsigned_(init_value) {}
 
@@ -87,7 +95,7 @@
   static_assert(sizeof(BitFields) == sizeof(unsigned),
                 "Mapped union types must match in size.");
 
-  // Used in setVariant to store the value in m_fields.m_variantNumeric;
+  // Used in SetVariant to store the value in m_fields.m_variantNumeric;
   friend class FontDescription;
 };
 }
diff --git a/third_party/WebKit/Source/platform/fonts/GenericFontFamilySettings.cpp b/third_party/WebKit/Source/platform/fonts/GenericFontFamilySettings.cpp
index bf4cc1b9..c7211be 100644
--- a/third_party/WebKit/Source/platform/fonts/GenericFontFamilySettings.cpp
+++ b/third_party/WebKit/Source/platform/fonts/GenericFontFamilySettings.cpp
@@ -30,6 +30,7 @@
 
 #include "platform/fonts/GenericFontFamilySettings.h"
 
+#include <memory>
 #include "platform/fonts/FontCache.h"
 
 namespace blink {
@@ -53,7 +54,7 @@
       vector.emplace_back(kv.key, kv.value.GetString().IsolatedCopy());
   };
 
-  dest.isolated_copy_ = WTF::MakeUnique<IsolatedCopyVector[]>(7);
+  dest.isolated_copy_ = std::make_unique<IsolatedCopyVector[]>(7);
   copy_to_vector(standard_font_family_map_, dest.isolated_copy_[0]);
   copy_to_vector(serif_font_family_map_, dest.isolated_copy_[1]);
   copy_to_vector(fixed_font_family_map_, dest.isolated_copy_[2]);
diff --git a/third_party/WebKit/Source/platform/fonts/OrientationIterator.cpp b/third_party/WebKit/Source/platform/fonts/OrientationIterator.cpp
index d5e80eb..188d2e3 100644
--- a/third_party/WebKit/Source/platform/fonts/OrientationIterator.cpp
+++ b/third_party/WebKit/Source/platform/fonts/OrientationIterator.cpp
@@ -4,14 +4,14 @@
 
 #include "platform/fonts/OrientationIterator.h"
 
-#include "platform/wtf/PtrUtil.h"
+#include <memory>
 
 namespace blink {
 
 OrientationIterator::OrientationIterator(const UChar* buffer,
                                          unsigned buffer_size,
                                          FontOrientation run_orientation)
-    : utf16_iterator_(WTF::MakeUnique<UTF16TextIterator>(buffer, buffer_size)),
+    : utf16_iterator_(std::make_unique<UTF16TextIterator>(buffer, buffer_size)),
       buffer_size_(buffer_size),
       at_end_(buffer_size == 0) {
   // There's not much point in segmenting by isUprightInVertical if the text
diff --git a/third_party/WebKit/Source/platform/fonts/SimpleFontData.cpp b/third_party/WebKit/Source/platform/fonts/SimpleFontData.cpp
index 74c5c43d..adaa53e 100644
--- a/third_party/WebKit/Source/platform/fonts/SimpleFontData.cpp
+++ b/third_party/WebKit/Source/platform/fonts/SimpleFontData.cpp
@@ -79,7 +79,7 @@
   if (platform_data.IsVerticalAnyUpright() && !is_text_orientation_fallback) {
     vertical_data_ = platform_data.VerticalData();
     has_vertical_glyphs_ =
-        vertical_data_.Get() && vertical_data_->HasVerticalMetrics();
+        vertical_data_.get() && vertical_data_->HasVerticalMetrics();
   }
 }
 
diff --git a/third_party/WebKit/Source/platform/fonts/SimpleFontData.h b/third_party/WebKit/Source/platform/fonts/SimpleFontData.h
index 4ad38f88..ef2d1c5 100644
--- a/third_party/WebKit/Source/platform/fonts/SimpleFontData.h
+++ b/third_party/WebKit/Source/platform/fonts/SimpleFontData.h
@@ -81,7 +81,7 @@
 
   const FontPlatformData& PlatformData() const { return platform_data_; }
   const OpenTypeVerticalData* VerticalData() const {
-    return vertical_data_.Get();
+    return vertical_data_.get();
   }
 
   RefPtr<SimpleFontData> SmallCapsFontData(const FontDescription&) const;
@@ -153,7 +153,7 @@
 
   Glyph GlyphForCharacter(UChar32) const;
 
-  bool IsCustomFont() const override { return custom_font_data_.Get(); }
+  bool IsCustomFont() const override { return custom_font_data_.get(); }
   bool IsLoading() const override {
     return custom_font_data_ ? custom_font_data_->IsLoading() : false;
   }
@@ -170,7 +170,7 @@
     missing_glyph_data_ = glyph_data;
   }
 
-  CustomFontData* GetCustomFontData() const { return custom_font_data_.Get(); }
+  CustomFontData* GetCustomFontData() const { return custom_font_data_.get(); }
 
   unsigned VisualOverflowInflationForAscent() const {
     return visual_overflow_inflation_for_ascent_;
diff --git a/third_party/WebKit/Source/platform/fonts/SmallCapsIterator.cpp b/third_party/WebKit/Source/platform/fonts/SmallCapsIterator.cpp
index 861b98c8..7fe7c16f4 100644
--- a/third_party/WebKit/Source/platform/fonts/SmallCapsIterator.cpp
+++ b/third_party/WebKit/Source/platform/fonts/SmallCapsIterator.cpp
@@ -5,12 +5,12 @@
 #include "platform/fonts/SmallCapsIterator.h"
 
 #include <unicode/utypes.h>
-#include "platform/wtf/PtrUtil.h"
+#include <memory>
 
 namespace blink {
 
 SmallCapsIterator::SmallCapsIterator(const UChar* buffer, unsigned buffer_size)
-    : utf16_iterator_(WTF::MakeUnique<UTF16TextIterator>(buffer, buffer_size)),
+    : utf16_iterator_(std::make_unique<UTF16TextIterator>(buffer, buffer_size)),
       buffer_size_(buffer_size),
       next_u_char32_(0),
       at_end_(buffer_size == 0),
diff --git a/third_party/WebKit/Source/platform/fonts/SymbolsIterator.cpp b/third_party/WebKit/Source/platform/fonts/SymbolsIterator.cpp
index f25e549bf..617e954 100644
--- a/third_party/WebKit/Source/platform/fonts/SymbolsIterator.cpp
+++ b/third_party/WebKit/Source/platform/fonts/SymbolsIterator.cpp
@@ -6,14 +6,14 @@
 
 #include <unicode/uchar.h>
 #include <unicode/uniset.h>
-#include "platform/wtf/PtrUtil.h"
+#include <memory>
 
 namespace blink {
 
 using namespace WTF::Unicode;
 
 SymbolsIterator::SymbolsIterator(const UChar* buffer, unsigned buffer_size)
-    : utf16_iterator_(WTF::MakeUnique<UTF16TextIterator>(buffer, buffer_size)),
+    : utf16_iterator_(std::make_unique<UTF16TextIterator>(buffer, buffer_size)),
       buffer_size_(buffer_size),
       next_char_(0),
       at_end_(buffer_size == 0),
diff --git a/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm b/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm
index 5b4f943..5c194da 100644
--- a/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm
+++ b/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm
@@ -40,7 +40,6 @@
 #include "platform/fonts/SimpleFontData.h"
 #include "platform/fonts/mac/FontFamilyMatcherMac.h"
 #include "platform/wtf/Functional.h"
-#include "platform/wtf/PtrUtil.h"
 #include "platform/wtf/StdLibExtras.h"
 #include "public/platform/Platform.h"
 #include "public/platform/WebTraceLocation.h"
@@ -288,7 +287,7 @@
   // stored in non-system locations.  When loading fails, we do not want to use
   // the returned FontPlatformData since it will not have a valid SkTypeface.
   std::unique_ptr<FontPlatformData> platform_data =
-      WTF::MakeUnique<FontPlatformData>(
+      std::make_unique<FontPlatformData>(
           platform_font, size, synthetic_bold, synthetic_italic,
           font_description.Orientation(), font_description.VariationSettings());
   if (!platform_data->Typeface()) {
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShapeIterator.h b/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShapeIterator.h
index b2e6960d..c8821474 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShapeIterator.h
+++ b/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShapeIterator.h
@@ -71,7 +71,7 @@
         return false;
       *word_result = ShapeWord(text_run_, font_);
       start_index_ = 1;
-      return word_result->Get();
+      return word_result->get();
     }
 
     return NextWord(word_result);
@@ -165,7 +165,7 @@
       *result = ShapeWord(sub_run, font_);
     }
     start_index_ = end_index;
-    return result->Get();
+    return result->get();
   }
 
   unsigned EndIndexUntil(UChar ch) const {
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShaperTest.cpp b/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShaperTest.cpp
index fd2d7d7..2100e79 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShaperTest.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShaperTest.cpp
@@ -8,7 +8,6 @@
 #include "platform/fonts/FontCache.h"
 #include "platform/fonts/shaping/CachingWordShapeIterator.h"
 #include "platform/fonts/shaping/ShapeResultTestInfo.h"
-#include "platform/wtf/PtrUtil.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
@@ -25,7 +24,7 @@
     font.Update(nullptr);
     ASSERT_TRUE(font.CanShapeWordByWord());
     fallback_fonts = nullptr;
-    cache = WTF::MakeUnique<ShapeCache>();
+    cache = std::make_unique<ShapeCache>();
   }
 
   FontCachePurgePreventer font_cache_purge_preventer;
@@ -40,7 +39,7 @@
 
 static inline const ShapeResultTestInfo* TestInfo(
     RefPtr<const ShapeResult>& result) {
-  return static_cast<const ShapeResultTestInfo*>(result.Get());
+  return static_cast<const ShapeResultTestInfo*>(result.get());
 }
 
 TEST_F(CachingWordShaperTest, LatinLeftToRightByWord) {
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzFontCache.h b/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzFontCache.h
index 22de9e0..8e634235 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzFontCache.h
+++ b/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzFontCache.h
@@ -5,6 +5,7 @@
 #ifndef HarfBuzzFontCache_h
 #define HarfBuzzFontCache_h
 
+#include <memory>
 #include "platform/fonts/UnicodeRangeSet.h"
 
 struct hb_font_t;
@@ -44,7 +45,7 @@
     SimpleFontData* simple_font_data =
         FontCache::GetFontCache()
             ->FontDataFromFontPlatformData(platform_data)
-            .Get();
+            .get();
     if (simple_font_data_)
       FontCache::GetFontCache()->ReleaseFontData(simple_font_data_);
     simple_font_data_ = simple_font_data;
@@ -75,7 +76,7 @@
  private:
   explicit HbFontCacheEntry(hb_font_t* font)
       : hb_font_(HbFontUniquePtr(font)),
-        hb_font_data_(WTF::MakeUnique<HarfBuzzFontData>()){};
+        hb_font_data_(std::make_unique<HarfBuzzFontData>()){};
 
   HbFontUniquePtr hb_font_;
   std::unique_ptr<HarfBuzzFontData> hb_font_data_;
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaper.cpp b/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaper.cpp
index 1af3439..a68db02 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaper.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaper.cpp
@@ -415,7 +415,7 @@
   if (run_orientation == FontOrientation::kVerticalRotated ||
       (run_orientation == FontOrientation::kVerticalMixed &&
        render_orientation == OrientationIterator::kOrientationRotateSideways))
-    return original_font->VerticalRightOrientationFontData().Get();
+    return original_font->VerticalRightOrientationFontData().get();
 
   return original_font;
 }
@@ -801,7 +801,7 @@
     const SimpleFontData* smallcaps_adjusted_font =
         needs_caps_handling &&
                 caps_support.NeedsSyntheticFont(small_caps_behavior)
-            ? font_data->SmallCapsFontData(font_description).Get()
+            ? font_data->SmallCapsFontData(font_description).get()
             : font_data;
 
     // Compatibility with SimpleFontData approach of keeping a flag for
@@ -881,11 +881,11 @@
     // Only shape segments overlapping with the range indicated by start and
     // end. Not only those strictly within.
     if (start < segment_range.end && end > segment_range.start)
-      ShapeSegment(&range_data, segment_range, result.Get());
+      ShapeSegment(&range_data, segment_range, result.get());
   }
 
 #if DCHECK_IS_ON()
-  CheckShapeResultRange(result.Get(), start, end, text_, font);
+  CheckShapeResultRange(result.get(), start, end, text_, font);
 #endif
 
   return result;
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaperTest.cpp b/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaperTest.cpp
index ba6f144..79af7d51 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaperTest.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaperTest.cpp
@@ -42,7 +42,7 @@
 };
 
 static inline ShapeResultTestInfo* TestInfo(RefPtr<ShapeResult>& result) {
-  return static_cast<ShapeResultTestInfo*>(result.Get());
+  return static_cast<ShapeResultTestInfo*>(result.get());
 }
 
 TEST_F(HarfBuzzShaperTest, MutableUnique) {
@@ -52,12 +52,12 @@
 
   // At this point, |result| has only one ref count.
   RefPtr<ShapeResult> result2 = result->MutableUnique();
-  EXPECT_EQ(result.Get(), result2.Get());
+  EXPECT_EQ(result.get(), result2.get());
   EXPECT_FALSE(result2->HasOneRef());
 
   // Since |result| has 2 ref counts, it should return a clone.
   RefPtr<ShapeResult> result3 = result->MutableUnique();
-  EXPECT_NE(result.Get(), result3.Get());
+  EXPECT_NE(result.get(), result3.get());
   EXPECT_TRUE(result3->HasOneRef());
 }
 
@@ -319,8 +319,8 @@
 
   RefPtr<ShapeResult> composite_result =
       ShapeResult::Create(&font, 0, direction);
-  result1->CopyRange(0, 3, composite_result.Get());
-  result2->CopyRange(3, string.length(), composite_result.Get());
+  result1->CopyRange(0, 3, composite_result.get());
+  result2->CopyRange(3, string.length(), composite_result.get());
 
   EXPECT_EQ(result->Bounds(), composite_result->Bounds());
 }
@@ -347,8 +347,8 @@
 
   RefPtr<ShapeResult> composite_result =
       ShapeResult::Create(&font, 0, direction);
-  result1->CopyRange(0, 3, composite_result.Get());
-  result2->CopyRange(3, string.length(), composite_result.Get());
+  result1->CopyRange(0, 3, composite_result.get());
+  result2->CopyRange(3, string.length(), composite_result.get());
 
   EXPECT_EQ(result->Bounds(), composite_result->Bounds());
 }
@@ -532,17 +532,17 @@
 
   // Split the result.
   RefPtr<ShapeResult> result1 = ShapeResult::Create(&font, 0, direction);
-  result->CopyRange(0, test_data.break_point, result1.Get());
+  result->CopyRange(0, test_data.break_point, result1.get());
   EXPECT_EQ(test_data.break_point, result1->NumCharacters());
   RefPtr<ShapeResult> result2 = ShapeResult::Create(&font, 0, direction);
-  result->CopyRange(test_data.break_point, string.length(), result2.Get());
+  result->CopyRange(test_data.break_point, string.length(), result2.get());
   EXPECT_EQ(string.length() - test_data.break_point, result2->NumCharacters());
 
   // Combine them.
   RefPtr<ShapeResult> composite_result =
       ShapeResult::Create(&font, 0, direction);
-  result1->CopyRange(0, test_data.break_point, composite_result.Get());
-  result2->CopyRange(0, string.length(), composite_result.Get());
+  result1->CopyRange(0, test_data.break_point, composite_result.get());
+  result2->CopyRange(0, string.length(), composite_result.get());
   EXPECT_EQ(string.length(), composite_result->NumCharacters());
 
   // Test character indexes match.
@@ -574,8 +574,8 @@
   // Combine them.
   RefPtr<ShapeResult> composite_result =
       ShapeResult::Create(&font, 0, direction);
-  result1->CopyRange(0, test_data.break_point, composite_result.Get());
-  result2->CopyRange(0, string.length(), composite_result.Get());
+  result1->CopyRange(0, test_data.break_point, composite_result.get());
+  result2->CopyRange(0, string.length(), composite_result.get());
   EXPECT_EQ(string.length(), composite_result->NumCharacters());
 
   // Test character indexes match.
@@ -595,10 +595,10 @@
 
   RefPtr<ShapeResult> composite_result =
       ShapeResult::Create(&font, 0, direction);
-  result->CopyRange(0, 10, composite_result.Get());
-  result->CopyRange(10, 20, composite_result.Get());
-  result->CopyRange(20, 30, composite_result.Get());
-  result->CopyRange(30, 33, composite_result.Get());
+  result->CopyRange(0, 10, composite_result.get());
+  result->CopyRange(10, 20, composite_result.get());
+  result->CopyRange(20, 30, composite_result.get());
+  result->CopyRange(30, 33, composite_result.get());
 
   EXPECT_EQ(result->NumCharacters(), composite_result->NumCharacters());
   EXPECT_EQ(result->SnappedWidth(), composite_result->SnappedWidth());
@@ -625,9 +625,9 @@
 
   RefPtr<ShapeResult> composite_result =
       ShapeResult::Create(&font, 0, direction);
-  result->CopyRange(0, 4, composite_result.Get());
-  result->CopyRange(4, 6, composite_result.Get());
-  result->CopyRange(6, 8, composite_result.Get());
+  result->CopyRange(0, 4, composite_result.get());
+  result->CopyRange(4, 6, composite_result.get());
+  result->CopyRange(6, 8, composite_result.get());
 
   EXPECT_EQ(result->NumCharacters(), composite_result->NumCharacters());
   EXPECT_EQ(result->SnappedWidth(), composite_result->SnappedWidth());
@@ -667,7 +667,7 @@
 
   // CopyRange(5, 7) should copy 1 character from [1] and 1 from [2].
   RefPtr<ShapeResult> target = ShapeResult::Create(&font, 0, direction);
-  result->CopyRange(5, 7, target.Get());
+  result->CopyRange(5, 7, target.get());
   EXPECT_EQ(2u, target->NumCharacters());
 }
 
@@ -682,8 +682,8 @@
 
   RefPtr<ShapeResult> composite_result =
       ShapeResult::Create(&font, 0, direction);
-  result1->CopyRange(0, 6, composite_result.Get());
-  result2->CopyRange(6, string.length(), composite_result.Get());
+  result1->CopyRange(0, 6, composite_result.get());
+  result2->CopyRange(6, string.length(), composite_result.get());
 
   RefPtr<ShapeResult> result = shaper.Shape(&font, direction);
   EXPECT_EQ(result->Bounds(), composite_result->Bounds());
@@ -719,8 +719,8 @@
   // copying and multi-run break information works.
   RefPtr<ShapeResult> copied_result =
       ShapeResult::Create(&testFont, 0, TextDirection::kLtr);
-  result->CopyRange(0, 3, copied_result.Get());
-  result->CopyRange(3, string.length(), copied_result.Get());
+  result->CopyRange(0, 3, copied_result.get());
+  result->CopyRange(3, string.length(), copied_result.get());
 
   EXPECT_EQ(0u, copied_result->NextSafeToBreakOffset(0));
   EXPECT_EQ(3u, copied_result->NextSafeToBreakOffset(1));
@@ -758,8 +758,8 @@
   // copying and multi-run break information works.
   RefPtr<ShapeResult> copied_result =
       ShapeResult::Create(&testFont, 0, TextDirection::kLtr);
-  result->CopyRange(0, 3, copied_result.Get());
-  result->CopyRange(3, string.length(), copied_result.Get());
+  result->CopyRange(0, 3, copied_result.get());
+  result->CopyRange(3, string.length(), copied_result.get());
 
   EXPECT_EQ(6u, copied_result->PreviousSafeToBreakOffset(6));
   EXPECT_EQ(4u, copied_result->PreviousSafeToBreakOffset(5));
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenter.cpp b/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenter.cpp
index 2ff7daf..05d2cd2 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenter.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenter.cpp
@@ -4,13 +4,13 @@
 
 #include "platform/fonts/shaping/RunSegmenter.h"
 
+#include <memory>
 #include "platform/fonts/ScriptRunIterator.h"
 #include "platform/fonts/SmallCapsIterator.h"
 #include "platform/fonts/SymbolsIterator.h"
 #include "platform/fonts/UTF16TextIterator.h"
 #include "platform/text/Character.h"
 #include "platform/wtf/Assertions.h"
-#include "platform/wtf/PtrUtil.h"
 
 namespace blink {
 
@@ -20,14 +20,14 @@
     : buffer_size_(buffer_size),
       candidate_range_(NullRange()),
       script_run_iterator_(
-          WTF::MakeUnique<ScriptRunIterator>(buffer, buffer_size)),
+          std::make_unique<ScriptRunIterator>(buffer, buffer_size)),
       orientation_iterator_(
           run_orientation == FontOrientation::kVerticalMixed
               ? WTF::WrapUnique(new OrientationIterator(buffer,
                                                         buffer_size,
                                                         run_orientation))
               : nullptr),
-      symbols_iterator_(WTF::MakeUnique<SymbolsIterator>(buffer, buffer_size)),
+      symbols_iterator_(std::make_unique<SymbolsIterator>(buffer, buffer_size)),
       last_split_(0),
       script_run_iterator_position_(0),
       orientation_iterator_position_(
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResult.cpp b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResult.cpp
index 2fd83c5..5f2f362 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResult.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResult.cpp
@@ -376,8 +376,8 @@
     if (runs_[i] && runs_[i]->font_data_ &&
         runs_[i]->font_data_ != primary_font_ &&
         !runs_[i]->font_data_->IsTextOrientationFallbackOf(
-            primary_font_.Get())) {
-      fallback->insert(runs_[i]->font_data_.Get());
+            primary_font_.get())) {
+      fallback->insert(runs_[i]->font_data_.get());
     }
   }
 }
@@ -498,7 +498,7 @@
                                         hb_buffer_t* harf_buzz_buffer,
                                         FloatRect* glyph_bounding_box) {
   DCHECK_EQ(is_horizontal_run, run->IsHorizontal());
-  const SimpleFontData* current_font_data = run->font_data_.Get();
+  const SimpleFontData* current_font_data = run->font_data_.get();
   const hb_glyph_info_t* glyph_infos =
       hb_buffer_get_glyph_infos(harf_buzz_buffer, 0);
   const hb_glyph_position_t* glyph_positions =
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBloberizer.cpp b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBloberizer.cpp
index 382a102..f9edcb3 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBloberizer.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBloberizer.cpp
@@ -103,14 +103,14 @@
       const RefPtr<const ShapeResult>& word_result = results[resolved_index];
       word_offset -= word_result->NumCharacters();
       advance =
-          FillGlyphsForResult(word_result.Get(), run_info.run, run_info.from,
+          FillGlyphsForResult(word_result.get(), run_info.run, run_info.from,
                               run_info.to, advance, word_offset);
     }
   } else {
     unsigned word_offset = 0;
     for (const auto& word_result : results) {
       advance =
-          FillGlyphsForResult(word_result.Get(), run_info.run, run_info.from,
+          FillGlyphsForResult(word_result.get(), run_info.run, run_info.from,
                               run_info.to, advance, word_offset);
       word_offset += word_result->NumCharacters();
     }
@@ -264,7 +264,7 @@
             uint16_t character_index) -> bool {
 
           AddGlyphToBloberizer(*this, total_advance, run->direction_,
-                               run->font_data_.Get(), glyph_data, text,
+                               run->font_data_.get(), glyph_data, text,
                                character_index);
           return true;
         });
@@ -293,7 +293,7 @@
   for (unsigned i = 0; i < results.size(); ++i) {
     const auto& word_result =
         IsLtr(text_direction) ? results[i] : results[results.size() - 1 - i];
-    advance = FillFastHorizontalGlyphs(word_result.Get(), advance);
+    advance = FillFastHorizontalGlyphs(word_result.get(), advance);
   }
 
   return advance;
@@ -314,7 +314,7 @@
                           [&](const HarfBuzzRunGlyphData& glyph_data,
                               float total_advance) -> bool {
                             DCHECK(!glyph_data.offset.Height());
-                            Add(glyph_data.glyph, run->font_data_.Get(),
+                            Add(glyph_data.glyph, run->font_data_.get(),
                                 total_advance + glyph_data.offset.Width());
                             return true;
                           });
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBloberizerTest.cpp b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBloberizerTest.cpp
index 41de0cfa..b4ada96 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBloberizerTest.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBloberizerTest.cpp
@@ -4,6 +4,7 @@
 
 #include "platform/fonts/shaping/ShapeResultBloberizer.h"
 
+#include <memory>
 #include "platform/fonts/CharacterRange.h"
 #include "platform/fonts/Font.h"
 #include "platform/fonts/SimpleFontData.h"
@@ -50,7 +51,7 @@
     font.Update(nullptr);
     ASSERT_TRUE(font.CanShapeWordByWord());
     fallback_fonts = nullptr;
-    cache = WTF::MakeUnique<ShapeCache>();
+    cache = std::make_unique<ShapeCache>();
   }
 
   FontCachePurgePreventer font_cache_purge_preventer;
@@ -92,11 +93,11 @@
   RefPtr<SimpleFontData> font2 = TestSimpleFontData::Create();
 
   // 2 pending glyphs
-  bloberizer.Add(42, font1.Get(), 10);
-  bloberizer.Add(43, font1.Get(), 15);
+  bloberizer.Add(42, font1.get(), 10);
+  bloberizer.Add(43, font1.get(), 15);
 
   EXPECT_EQ(ShapeResultBloberizerTestInfo::PendingRunFontData(bloberizer),
-            font1.Get());
+            font1.get());
   EXPECT_FALSE(
       ShapeResultBloberizerTestInfo::HasPendingRunVerticalOffsets(bloberizer));
   {
@@ -118,10 +119,10 @@
   EXPECT_EQ(ShapeResultBloberizerTestInfo::CommittedBlobCount(bloberizer), 0ul);
 
   // one more glyph, different font => pending run flush
-  bloberizer.Add(44, font2.Get(), 12);
+  bloberizer.Add(44, font2.get(), 12);
 
   EXPECT_EQ(ShapeResultBloberizerTestInfo::PendingRunFontData(bloberizer),
-            font2.Get());
+            font2.get());
   EXPECT_FALSE(
       ShapeResultBloberizerTestInfo::HasPendingRunVerticalOffsets(bloberizer));
   {
@@ -152,11 +153,11 @@
   RefPtr<SimpleFontData> font2 = TestSimpleFontData::Create();
 
   // 2 pending glyphs
-  bloberizer.Add(42, font1.Get(), FloatPoint(10, 0));
-  bloberizer.Add(43, font1.Get(), FloatPoint(15, 0));
+  bloberizer.Add(42, font1.get(), FloatPoint(10, 0));
+  bloberizer.Add(43, font1.get(), FloatPoint(15, 0));
 
   EXPECT_EQ(ShapeResultBloberizerTestInfo::PendingRunFontData(bloberizer),
-            font1.Get());
+            font1.get());
   EXPECT_TRUE(
       ShapeResultBloberizerTestInfo::HasPendingRunVerticalOffsets(bloberizer));
   {
@@ -180,10 +181,10 @@
   EXPECT_EQ(ShapeResultBloberizerTestInfo::CommittedBlobCount(bloberizer), 0ul);
 
   // one more glyph, different font => pending run flush
-  bloberizer.Add(44, font2.Get(), FloatPoint(12, 2));
+  bloberizer.Add(44, font2.get(), FloatPoint(12, 2));
 
   EXPECT_EQ(ShapeResultBloberizerTestInfo::PendingRunFontData(bloberizer),
-            font2.Get());
+            font2.get());
   EXPECT_TRUE(
       ShapeResultBloberizerTestInfo::HasPendingRunVerticalOffsets(bloberizer));
   {
@@ -228,23 +229,23 @@
     size_t expected_committed_blobs;
   } append_ops[] = {
       // append 2 horizontal glyphs -> these go into the pending glyph buffer
-      {font_normal.Get(), 1u, 0u, 0u},
-      {font_normal.Get(), 2u, 0u, 0u},
+      {font_normal.get(), 1u, 0u, 0u},
+      {font_normal.get(), 2u, 0u, 0u},
 
       // append 3 vertical rotated glyphs -> push the prev pending (horizontal)
       // glyphs into a new run in the current (horizontal) blob
-      {font_rotated.Get(), 1u, 1u, 0u},
-      {font_rotated.Get(), 2u, 1u, 0u},
-      {font_rotated.Get(), 3u, 1u, 0u},
+      {font_rotated.get(), 1u, 1u, 0u},
+      {font_rotated.get(), 2u, 1u, 0u},
+      {font_rotated.get(), 3u, 1u, 0u},
 
       // append 2 more horizontal glyphs -> flush the current (horizontal) blob,
       // push prev (vertical) pending glyphs into new vertical blob run
-      {font_normal.Get(), 1u, 1u, 1u},
-      {font_normal.Get(), 2u, 1u, 1u},
+      {font_normal.get(), 1u, 1u, 1u},
+      {font_normal.get(), 2u, 1u, 1u},
 
       // append 1 more vertical glyph -> flush current (vertical) blob, push
       // prev (horizontal) pending glyphs into a new horizontal blob run
-      {font_rotated.Get(), 1u, 1u, 2u},
+      {font_rotated.get(), 1u, 1u, 2u},
   };
 
   for (const auto& op : append_ops) {
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBuffer.cpp b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBuffer.cpp
index 046c47c..923c68b5 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBuffer.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBuffer.cpp
@@ -206,7 +206,7 @@
   for (const auto& result : results_) {
     for (const auto& run : result->runs_) {
       font_data.push_back(
-          RunFontData({run->font_data_.Get(), run->glyph_data_.size()}));
+          RunFontData({run->font_data_.get(), run->glyph_data_.size()}));
     }
   }
   return font_data;
@@ -222,7 +222,7 @@
 
       return GlyphData(
           run->glyph_data_[0].glyph,
-          run->font_data_->EmphasisMarkFontData(font_description).Get());
+          run->font_data_->EmphasisMarkFontData(font_description).get());
     }
   }
 
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultInlineHeaders.h b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultInlineHeaders.h
index af75462..23255f2 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultInlineHeaders.h
+++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultInlineHeaders.h
@@ -124,7 +124,7 @@
           });
     }
 
-    auto run = std::make_unique<RunInfo>(font_data_.Get(), direction_, script_,
+    auto run = std::make_unique<RunInfo>(font_data_.get(), direction_, script_,
                                          start_index_ + start, number_of_glyphs,
                                          number_of_characters);
 
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultTestInfo.cpp b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultTestInfo.cpp
index 1a5bf5e..993c2ee 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultTestInfo.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultTestInfo.cpp
@@ -49,7 +49,7 @@
 
 SimpleFontData* ShapeResultTestInfo::FontDataForTesting(
     unsigned run_index) const {
-  return runs_[run_index]->font_data_.Get();
+  return runs_[run_index]->font_data_.get();
 }
 
 Vector<unsigned> ShapeResultTestInfo::CharacterIndexesForTesting() const {
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreaker.cpp b/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreaker.cpp
index e31387e..8eea44a 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreaker.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreaker.cpp
@@ -352,11 +352,11 @@
   RefPtr<ShapeResult> line_result = ShapeResult::Create(font_, 0, direction);
   unsigned max_length = std::numeric_limits<unsigned>::max();
   if (line_start_result)
-    line_start_result->CopyRange(0, max_length, line_result.Get());
+    line_start_result->CopyRange(0, max_length, line_result.get());
   if (last_safe > first_safe)
-    result_->CopyRange(first_safe, last_safe, line_result.Get());
+    result_->CopyRange(first_safe, last_safe, line_result.get());
   if (line_end_result)
-    line_end_result->CopyRange(last_safe, max_length, line_result.Get());
+    line_end_result->CopyRange(last_safe, max_length, line_result.get());
 
   DCHECK_GT(break_opportunity, start);
   // TODO(layout-dev): This hits on Mac and Mac only for a number of tests in
@@ -384,11 +384,11 @@
   if (first_safe == start) {
     // If |start| is safe-to-break no reshape is needed.
     line_result = ShapeResult::Create(font_, 0, direction);
-    result_->CopyRange(start, range_end, line_result.Get());
+    result_->CopyRange(start, range_end, line_result.get());
   } else if (first_safe < range_end) {
     // Otherwise reshape to |first_safe|, then copy the rest.
     line_result = Shape(direction, start, first_safe);
-    result_->CopyRange(first_safe, range_end, line_result.Get());
+    result_->CopyRange(first_safe, range_end, line_result.get());
   } else {
     // If no safe-to-break offset is found in range, reshape the entire range.
     line_result = Shape(direction, start, range_end);
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreakerTest.cpp b/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreakerTest.cpp
index f1f4ece..f5720f62 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreakerTest.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreakerTest.cpp
@@ -107,7 +107,7 @@
   RefPtr<ShapeResult> first1 = shaper.Shape(&font, direction, 0, 4);
   ASSERT_LT(first1->SnappedWidth(), first2->SnappedWidth());
 
-  ShapingLineBreaker breaker(&shaper, &font, result.Get(), &break_iterator);
+  ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator);
   RefPtr<ShapeResult> line;
   unsigned break_offset = 0;
 
@@ -165,7 +165,7 @@
   RefPtr<ShapeResult> first = shaper.Shape(&font, direction, 0, 4);
   RefPtr<ShapeResult> mid_third = shaper.Shape(&font, direction, 0, 16);
 
-  ShapingLineBreaker breaker(&shaper, &font, result.Get(), &break_iterator);
+  ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator);
   unsigned break_offset = 0;
 
   ShapeLine(&breaker, 0, result->SnappedWidth() - 1, &break_offset);
@@ -191,7 +191,7 @@
   RefPtr<ShapeResult> result = shaper.Shape(&font, direction);
   RefPtr<ShapeResult> midpoint = shaper.Shape(&font, direction, 0, 16);
 
-  ShapingLineBreaker breaker(&shaper, &font, result.Get(), &break_iterator);
+  ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator);
   RefPtr<ShapeResult> line;
   unsigned break_offset = 0;
 
@@ -212,7 +212,7 @@
   HarfBuzzShaper shaper(string.Characters16(), string.length());
   RefPtr<ShapeResult> result = shaper.Shape(&font, direction);
 
-  ShapingLineBreaker breaker(&shaper, &font, result.Get(), &break_iterator);
+  ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator);
   RefPtr<ShapeResult> line;
   unsigned break_offset = 0;
   LayoutUnit zero(0);
@@ -253,7 +253,7 @@
       });
   LayoutUnit longest_word_width = (*longest_word)->SnappedWidth();
 
-  ShapingLineBreaker breaker(&shaper, &font, result.Get(), &break_iterator);
+  ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator);
   RefPtr<ShapeResult> line;
   unsigned break_offset = 0;
 
@@ -281,7 +281,7 @@
   HarfBuzzShaper shaper(string.Characters16(), string.length());
   RefPtr<ShapeResult> result = shaper.Shape(&font, direction, 0, 2);
 
-  ShapingLineBreaker breaker(&shaper, &font, result.Get(), &break_iterator);
+  ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator);
   RefPtr<ShapeResult> line;
   unsigned break_offset = 0;
 
diff --git a/third_party/WebKit/Source/platform/graphics/BitmapImage.cpp b/third_party/WebKit/Source/platform/graphics/BitmapImage.cpp
index 60689bc..296ced5f8 100644
--- a/third_party/WebKit/Source/platform/graphics/BitmapImage.cpp
+++ b/third_party/WebKit/Source/platform/graphics/BitmapImage.cpp
@@ -403,7 +403,10 @@
 
 RefPtr<Image> BitmapImage::ImageForDefaultFrame() {
   if (FrameCount() > 1) {
-    return StaticBitmapImage::Create(FrameAtIndex(0u));
+    PaintImage paint_image = FrameAtIndex(PaintImage::kDefaultFrameIndex);
+    if (paint_image.ShouldAnimate())
+      paint_image = paint_image.MakeStatic();
+    return StaticBitmapImage::Create(std::move(paint_image));
   }
 
   return Image::ImageForDefaultFrame();
diff --git a/third_party/WebKit/Source/platform/graphics/BitmapImage.h b/third_party/WebKit/Source/platform/graphics/BitmapImage.h
index fbcf343d..3d7fc2f 100644
--- a/third_party/WebKit/Source/platform/graphics/BitmapImage.h
+++ b/third_party/WebKit/Source/platform/graphics/BitmapImage.h
@@ -116,8 +116,8 @@
     kCertain     // The repetition count is known to be correct.
   };
 
-  BitmapImage(const SkBitmap&, ImageObserver* = 0);
-  BitmapImage(ImageObserver* = 0, bool is_multi_part = false);
+  BitmapImage(const SkBitmap&, ImageObserver* = nullptr);
+  BitmapImage(ImageObserver* = nullptr, bool is_multi_part = false);
 
   void Draw(PaintCanvas*,
             const PaintFlags&,
diff --git a/third_party/WebKit/Source/platform/graphics/BitmapImageTest.cpp b/third_party/WebKit/Source/platform/graphics/BitmapImageTest.cpp
index c697a61..9b3ed8f6 100644
--- a/third_party/WebKit/Source/platform/graphics/BitmapImageTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/BitmapImageTest.cpp
@@ -92,7 +92,7 @@
 
   void LoadImage(const char* file_name, bool load_all_frames = true) {
     RefPtr<SharedBuffer> image_data = ReadFile(file_name);
-    ASSERT_TRUE(image_data.Get());
+    ASSERT_TRUE(image_data.get());
 
     image_->SetData(image_data, true);
     EXPECT_EQ(0u, DecodedSize());
@@ -183,7 +183,7 @@
 TEST_F(BitmapImageTest, isAllDataReceived) {
   RefPtr<SharedBuffer> image_data =
       ReadFile("/LayoutTests/images/resources/green.jpg");
-  ASSERT_TRUE(image_data.Get());
+  ASSERT_TRUE(image_data.get());
 
   RefPtr<BitmapImage> image = BitmapImage::Create();
   EXPECT_FALSE(image->IsAllDataReceived());
@@ -264,7 +264,7 @@
 TEST_F(BitmapImageTest, ConstantImageIdForPartiallyLoadedImages) {
   RefPtr<SharedBuffer> image_data =
       ReadFile("/LayoutTests/images/resources/green.jpg");
-  ASSERT_TRUE(image_data.Get());
+  ASSERT_TRUE(image_data.get());
 
   // Create a new buffer to partially supply the data.
   RefPtr<SharedBuffer> partial_buffer = SharedBuffer::Create();
@@ -377,7 +377,6 @@
   TimeDelta duration_;
   int repetition_count_;
   size_t frame_count_;
-  ImageFrame::Status status_;
   bool last_frame_complete_;
 
   static double now_;
@@ -520,6 +519,21 @@
             image.reset_animation_sequence_id());
 }
 
+TEST_F(BitmapImageTestWithMockDecoder, PaintImageForStaticBitmapImage) {
+  repetition_count_ = kAnimationLoopInfinite;
+  frame_count_ = 5;
+  last_frame_complete_ = true;
+  image_->SetData(SharedBuffer::Create("data", sizeof("data")), false);
+
+  // PaintImage for the original image is animated.
+  EXPECT_TRUE(image_->PaintImageForCurrentFrame().ShouldAnimate());
+
+  // But the StaticBitmapImage is not.
+  EXPECT_FALSE(image_->ImageForDefaultFrame()
+                   ->PaintImageForCurrentFrame()
+                   .ShouldAnimate());
+}
+
 template <typename HistogramEnumType>
 struct HistogramTestParams {
   const char* filename;
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
index b1e95df14..5b899649 100644
--- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
+++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
@@ -1159,7 +1159,7 @@
   RefPtr<StaticBitmapImage> image = StaticBitmapImage::Create(
       surface_->makeImageSnapshot(), ContextProviderWrapper());
   if (image->IsTextureBacked()) {
-    static_cast<AcceleratedStaticBitmapImage*>(image.Get())
+    static_cast<AcceleratedStaticBitmapImage*>(image.get())
         ->RetainOriginalSkImageForCopyOnWrite();
   }
   return image;
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp
index 57a4e743..47657c4 100644
--- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp
@@ -46,7 +46,6 @@
 #include "platform/runtime_enabled_features.h"
 #include "platform/scheduler/child/web_scheduler.h"
 #include "platform/testing/TestingPlatformSupport.h"
-#include "platform/wtf/PtrUtil.h"
 #include "platform/wtf/RefPtr.h"
 #include "public/platform/Platform.h"
 #include "public/platform/WebThread.h"
@@ -1063,7 +1062,7 @@
 
   // Test entering hibernation
   std::unique_ptr<WaitableEvent> hibernation_started_event =
-      WTF::MakeUnique<WaitableEvent>();
+      std::make_unique<WaitableEvent>();
   EXPECT_CALL(
       *mock_logger_ptr,
       ReportHibernationEvent(Canvas2DLayerBridge::kHibernationScheduled));
diff --git a/third_party/WebKit/Source/platform/graphics/CompositorMutableProperties.h b/third_party/WebKit/Source/platform/graphics/CompositorMutableProperties.h
index 8aecbfff..4082f458 100644
--- a/third_party/WebKit/Source/platform/graphics/CompositorMutableProperties.h
+++ b/third_party/WebKit/Source/platform/graphics/CompositorMutableProperties.h
@@ -5,11 +5,18 @@
 #ifndef CompositorMutableProperties_h
 #define CompositorMutableProperties_h
 
-#include "cc/trees/mutable_properties.h"
-
 namespace blink {
 
-using CompositorMutableProperty = cc::MutableProperty;
+struct CompositorMutableProperty {
+  enum : uint32_t { kNone = 0 };
+  enum : uint32_t { kOpacity = 1 << 0 };
+  enum : uint32_t { kScrollLeft = 1 << 1 };
+  enum : uint32_t { kScrollTop = 1 << 2 };
+  enum : uint32_t { kTransform = 1 << 3 };
+  enum : uint32_t { kTransformRelated = kTransform | kScrollLeft | kScrollTop };
+
+  enum : int { kNumProperties = 4 };
+};
 
 }  // namespace blink
 
diff --git a/third_party/WebKit/Source/platform/graphics/CompositorMutatorClientTest.cpp b/third_party/WebKit/Source/platform/graphics/CompositorMutatorClientTest.cpp
index c31d8c3..a6f6a1e4 100644
--- a/third_party/WebKit/Source/platform/graphics/CompositorMutatorClientTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/CompositorMutatorClientTest.cpp
@@ -9,7 +9,6 @@
 #include "platform/graphics/CompositorMutation.h"
 #include "platform/graphics/CompositorMutationsTarget.h"
 #include "platform/graphics/CompositorMutator.h"
-#include "platform/wtf/PtrUtil.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -35,7 +34,7 @@
 
   CompositorMutatorClient client(new StubCompositorMutator, &target);
   std::unique_ptr<CompositorMutations> mutations =
-      WTF::MakeUnique<CompositorMutations>();
+      std::make_unique<CompositorMutations>();
   client.SetMutationsForTesting(std::move(mutations));
 
   EXPECT_CALL(target, ApplyMutations(_));
diff --git a/third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp b/third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp
index 6472286..c933275 100644
--- a/third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp
@@ -8,7 +8,6 @@
 #include <memory>
 #include "platform/wtf/Allocator.h"
 #include "platform/wtf/ContainerAnnotations.h"
-#include "platform/wtf/PtrUtil.h"
 #include "platform/wtf/allocator/Partitions.h"
 
 namespace blink {
@@ -171,7 +170,7 @@
     const char* type_name) {
   DCHECK(buffers_.IsEmpty() || end_index_ == buffers_.size() - 1);
   std::unique_ptr<Buffer> new_buffer =
-      WTF::MakeUnique<Buffer>(buffer_size, type_name);
+      std::make_unique<Buffer>(buffer_size, type_name);
   Buffer* buffer_to_return = new_buffer.get();
   buffers_.push_back(std::move(new_buffer));
   end_index_ = buffers_.size() - 1;
diff --git a/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.cpp b/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.cpp
index ad7cc1b..bd8bd59 100644
--- a/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.cpp
+++ b/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.cpp
@@ -149,7 +149,7 @@
 
   PlatformInstrumentation::WillDecodeLazyPixelRef(lazy_pixel_ref);
   const bool decoded = frame_generator_->DecodeAndScale(
-      data_.Get(), all_data_received_, frame_index, decode_info, pixels,
+      data_.get(), all_data_received_, frame_index, decode_info, pixels,
       row_bytes, alpha_option);
   PlatformInstrumentation::DidDecodeLazyPixelRef();
 
@@ -179,7 +179,7 @@
   if (color_space)
     *color_space = kJPEG_SkYUVColorSpace;
 
-  return frame_generator_->GetYUVComponentSizes(data_.Get(), size_info);
+  return frame_generator_->GetYUVComponentSizes(data_.get(), size_info);
 }
 
 bool DecodingImageGenerator::GetYUV8Planes(const SkYUVSizeInfo& size_info,
@@ -195,7 +195,7 @@
 
   PlatformInstrumentation::WillDecodeLazyPixelRef(lazy_pixel_ref);
   bool decoded =
-      frame_generator_->DecodeToYUV(data_.Get(), frame_index, size_info.fSizes,
+      frame_generator_->DecodeToYUV(data_.get(), frame_index, size_info.fSizes,
                                     planes, size_info.fWidthBytes);
   PlatformInstrumentation::DidDecodeLazyPixelRef();
 
diff --git a/third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.h b/third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.h
index 7665753..a1e011c 100644
--- a/third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.h
+++ b/third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.h
@@ -83,7 +83,7 @@
   explicit DeferredImageDecoder(std::unique_ptr<ImageDecoder> metadata_decoder);
 
   friend class DeferredImageDecoderTest;
-  ImageFrameGenerator* FrameGenerator() { return frame_generator_.Get(); }
+  ImageFrameGenerator* FrameGenerator() { return frame_generator_.get(); }
 
   void ActivateLazyDecoding();
   void PrepareLazyDecodedFrames();
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
index 0e9a58e..8c0b66b3 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
@@ -1235,11 +1235,6 @@
   return CompositorElementId();
 }
 
-void GraphicsLayer::SetCompositorMutableProperties(uint32_t properties) {
-  if (WebLayer* layer = PlatformLayer())
-    layer->SetCompositorMutableProperties(properties);
-}
-
 sk_sp<PaintRecord> GraphicsLayer::CaptureRecord() {
   if (!DrawsContent())
     return nullptr;
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
index 10c1ad5..a64bf38 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
@@ -272,8 +272,6 @@
   void SetElementId(const CompositorElementId&);
   CompositorElementId GetElementId() const;
 
-  void SetCompositorMutableProperties(uint32_t);
-
   WebContentLayerClient& WebContentLayerClientForTesting() { return *this; }
 
   // DisplayItemClient methods
diff --git a/third_party/WebKit/Source/platform/graphics/HighContrastImageClassifierTest.cpp b/third_party/WebKit/Source/platform/graphics/HighContrastImageClassifierTest.cpp
index fce6be90..e852e9c 100644
--- a/third_party/WebKit/Source/platform/graphics/HighContrastImageClassifierTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/HighContrastImageClassifierTest.cpp
@@ -18,7 +18,7 @@
     String file_path = testing::BlinkRootDir();
     file_path.append(file_name);
     RefPtr<SharedBuffer> image_data = testing::ReadFromFile(file_path);
-    EXPECT_TRUE(image_data.Get());
+    EXPECT_TRUE(image_data.get());
 
     RefPtr<BitmapImage> image = BitmapImage::Create();
     image->SetData(image_data, true);
@@ -34,10 +34,10 @@
 TEST_F(HighContrastImageClassifierTest, ShouldApplyHighContrastFilterToImage) {
   RefPtr<BitmapImage> image = LoadImage(
       "/LayoutTests/images/resources/blue-wheel-srgb-color-profile.png");
-  EXPECT_FALSE(classifier_.ShouldApplyHighContrastFilterToImage(*image.Get()));
+  EXPECT_FALSE(classifier_.ShouldApplyHighContrastFilterToImage(*image.get()));
 
   image = LoadImage("/LayoutTests/images/resources/grid.png");
-  EXPECT_TRUE(classifier_.ShouldApplyHighContrastFilterToImage(*image.Get()));
+  EXPECT_TRUE(classifier_.ShouldApplyHighContrastFilterToImage(*image.get()));
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/Image.cpp b/third_party/WebKit/Source/platform/graphics/Image.cpp
index 8883042e..72d7ad5 100644
--- a/third_party/WebKit/Source/platform/graphics/Image.cpp
+++ b/third_party/WebKit/Source/platform/graphics/Image.cpp
@@ -84,7 +84,7 @@
 Image::SizeAvailability Image::SetData(RefPtr<SharedBuffer> data,
                                        bool all_data_received) {
   encoded_image_data_ = std::move(data);
-  if (!encoded_image_data_.Get())
+  if (!encoded_image_data_.get())
     return kSizeAvailable;
 
   int length = encoded_image_data_->size();
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.cpp b/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.cpp
index 45934be..0f68c7b 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.cpp
@@ -79,7 +79,7 @@
   snapshot = snapshot->MakeUnaccelerated();
 
   DCHECK(!snapshot->IsTextureBacked());
-  context.DrawImage(snapshot.Get(), dest_rect, &src_rect, op);
+  context.DrawImage(snapshot.get(), dest_rect, &src_rect, op);
 }
 
 void ImageBufferSurface::Flush(FlushReason) {
diff --git a/third_party/WebKit/Source/platform/graphics/ImageDecodingStoreTest.cpp b/third_party/WebKit/Source/platform/graphics/ImageDecodingStoreTest.cpp
index c501c18..fdd794be 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageDecodingStoreTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ImageDecodingStoreTest.cpp
@@ -79,18 +79,18 @@
   std::unique_ptr<ImageDecoder> decoder = MockImageDecoder::Create(this);
   decoder->SetSize(1, 1);
   const ImageDecoder* ref_decoder = decoder.get();
-  ImageDecodingStore::Instance().InsertDecoder(generator_.Get(),
+  ImageDecodingStore::Instance().InsertDecoder(generator_.get(),
                                                std::move(decoder));
   EXPECT_EQ(1, ImageDecodingStore::Instance().CacheEntries());
   EXPECT_EQ(4u, ImageDecodingStore::Instance().MemoryUsageInBytes());
 
   ImageDecoder* test_decoder;
   EXPECT_TRUE(ImageDecodingStore::Instance().LockDecoder(
-      generator_.Get(), size, ImageDecoder::kAlphaPremultiplied,
+      generator_.get(), size, ImageDecoder::kAlphaPremultiplied,
       &test_decoder));
   EXPECT_TRUE(test_decoder);
   EXPECT_EQ(ref_decoder, test_decoder);
-  ImageDecodingStore::Instance().UnlockDecoder(generator_.Get(), test_decoder);
+  ImageDecodingStore::Instance().UnlockDecoder(generator_.get(), test_decoder);
   EXPECT_EQ(1, ImageDecodingStore::Instance().CacheEntries());
 }
 
@@ -101,11 +101,11 @@
   decoder1->SetSize(1, 1);
   decoder2->SetSize(2, 2);
   decoder3->SetSize(3, 3);
-  ImageDecodingStore::Instance().InsertDecoder(generator_.Get(),
+  ImageDecodingStore::Instance().InsertDecoder(generator_.get(),
                                                std::move(decoder1));
-  ImageDecodingStore::Instance().InsertDecoder(generator_.Get(),
+  ImageDecodingStore::Instance().InsertDecoder(generator_.get(),
                                                std::move(decoder2));
-  ImageDecodingStore::Instance().InsertDecoder(generator_.Get(),
+  ImageDecodingStore::Instance().InsertDecoder(generator_.get(),
                                                std::move(decoder3));
   EXPECT_EQ(3, ImageDecodingStore::Instance().CacheEntries());
   EXPECT_EQ(56u, ImageDecodingStore::Instance().MemoryUsageInBytes());
@@ -130,17 +130,17 @@
   decoder1->SetSize(1, 1);
   decoder2->SetSize(2, 2);
   decoder3->SetSize(3, 3);
-  ImageDecodingStore::Instance().InsertDecoder(generator_.Get(),
+  ImageDecodingStore::Instance().InsertDecoder(generator_.get(),
                                                std::move(decoder1));
-  ImageDecodingStore::Instance().InsertDecoder(generator_.Get(),
+  ImageDecodingStore::Instance().InsertDecoder(generator_.get(),
                                                std::move(decoder2));
-  ImageDecodingStore::Instance().InsertDecoder(generator_.Get(),
+  ImageDecodingStore::Instance().InsertDecoder(generator_.get(),
                                                std::move(decoder3));
   EXPECT_EQ(3, ImageDecodingStore::Instance().CacheEntries());
 
   ImageDecoder* test_decoder;
   EXPECT_TRUE(ImageDecodingStore::Instance().LockDecoder(
-      generator_.Get(), SkISize::Make(2, 2), ImageDecoder::kAlphaPremultiplied,
+      generator_.get(), SkISize::Make(2, 2), ImageDecoder::kAlphaPremultiplied,
       &test_decoder));
 
   EvictOneCache();
@@ -149,7 +149,7 @@
   EXPECT_EQ(1, ImageDecodingStore::Instance().CacheEntries());
   EXPECT_EQ(16u, ImageDecodingStore::Instance().MemoryUsageInBytes());
 
-  ImageDecodingStore::Instance().UnlockDecoder(generator_.Get(), test_decoder);
+  ImageDecodingStore::Instance().UnlockDecoder(generator_.get(), test_decoder);
   EvictOneCache();
   EXPECT_FALSE(ImageDecodingStore::Instance().CacheEntries());
   EXPECT_FALSE(ImageDecodingStore::Instance().MemoryUsageInBytes());
@@ -160,22 +160,22 @@
   std::unique_ptr<ImageDecoder> decoder = MockImageDecoder::Create(this);
   decoder->SetSize(1, 1);
   const ImageDecoder* ref_decoder = decoder.get();
-  ImageDecodingStore::Instance().InsertDecoder(generator_.Get(),
+  ImageDecodingStore::Instance().InsertDecoder(generator_.get(),
                                                std::move(decoder));
   EXPECT_EQ(1, ImageDecodingStore::Instance().CacheEntries());
   EXPECT_EQ(4u, ImageDecodingStore::Instance().MemoryUsageInBytes());
 
   ImageDecoder* test_decoder;
   EXPECT_TRUE(ImageDecodingStore::Instance().LockDecoder(
-      generator_.Get(), size, ImageDecoder::kAlphaPremultiplied,
+      generator_.get(), size, ImageDecoder::kAlphaPremultiplied,
       &test_decoder));
   EXPECT_TRUE(test_decoder);
   EXPECT_EQ(ref_decoder, test_decoder);
-  ImageDecodingStore::Instance().RemoveDecoder(generator_.Get(), test_decoder);
+  ImageDecodingStore::Instance().RemoveDecoder(generator_.get(), test_decoder);
   EXPECT_FALSE(ImageDecodingStore::Instance().CacheEntries());
 
   EXPECT_FALSE(ImageDecodingStore::Instance().LockDecoder(
-      generator_.Get(), size, ImageDecoder::kAlphaPremultiplied,
+      generator_.get(), size, ImageDecoder::kAlphaPremultiplied,
       &test_decoder));
 }
 
diff --git a/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp b/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp
index ebd3afd7..8b6a7af4 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp
@@ -30,7 +30,6 @@
 #include "platform/graphics/ImageDecodingStore.h"
 #include "platform/image-decoders/ImageDecoder.h"
 #include "platform/instrumentation/tracing/TraceEvent.h"
-#include "platform/wtf/PtrUtil.h"
 #include "third_party/skia/include/core/SkYUVSizeInfo.h"
 
 namespace blink {
@@ -203,7 +202,7 @@
   DCHECK(decoder);
 
   std::unique_ptr<ImagePlanes> image_planes =
-      WTF::MakeUnique<ImagePlanes>(planes, row_bytes);
+      std::make_unique<ImagePlanes>(planes, row_bytes);
   decoder->SetImagePlanes(std::move(image_planes));
 
   DCHECK(decoder->CanDecodeToYUV());
diff --git a/third_party/WebKit/Source/platform/graphics/ImageFrameGeneratorTest.cpp b/third_party/WebKit/Source/platform/graphics/ImageFrameGeneratorTest.cpp
index 845cee2..6084723 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageFrameGeneratorTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ImageFrameGeneratorTest.cpp
@@ -164,14 +164,14 @@
   SetFrameStatus(ImageFrame::kFramePartial);
 
   char buffer[100 * 100 * 4];
-  generator_->DecodeAndScale(segment_reader_.Get(), false, 0, ImageInfo(),
+  generator_->DecodeAndScale(segment_reader_.get(), false, 0, ImageInfo(),
                              buffer, 100 * 4,
                              ImageDecoder::kAlphaPremultiplied);
   EXPECT_EQ(1, decode_request_count_);
   EXPECT_EQ(0, memory_allocator_set_count_);
 
   AddNewData();
-  generator_->DecodeAndScale(segment_reader_.Get(), false, 0, ImageInfo(),
+  generator_->DecodeAndScale(segment_reader_.get(), false, 0, ImageInfo(),
                              buffer, 100 * 4,
                              ImageDecoder::kAlphaPremultiplied);
   EXPECT_EQ(2, decode_request_count_);
@@ -191,7 +191,7 @@
   SetFrameStatus(ImageFrame::kFramePartial);
 
   char buffer[100 * 100 * 4];
-  generator_->DecodeAndScale(segment_reader_.Get(), false, 0, ImageInfo(),
+  generator_->DecodeAndScale(segment_reader_.get(), false, 0, ImageInfo(),
                              buffer, 100 * 4,
                              ImageDecoder::kAlphaPremultiplied);
   EXPECT_EQ(1, decode_request_count_);
@@ -200,7 +200,7 @@
   EXPECT_EQ(2, memory_allocator_set_count_);
 
   AddNewData();
-  generator_->DecodeAndScale(segment_reader_.Get(), false, 0, ImageInfo(),
+  generator_->DecodeAndScale(segment_reader_.get(), false, 0, ImageInfo(),
                              buffer, 100 * 4,
                              ImageDecoder::kAlphaPremultiplied);
   EXPECT_EQ(2, decode_request_count_);
@@ -213,7 +213,7 @@
   SetFrameStatus(ImageFrame::kFramePartial);
 
   char buffer[100 * 100 * 4];
-  generator_->DecodeAndScale(segment_reader_.Get(), false, 0, ImageInfo(),
+  generator_->DecodeAndScale(segment_reader_.get(), false, 0, ImageInfo(),
                              buffer, 100 * 4,
                              ImageDecoder::kAlphaPremultiplied);
   EXPECT_EQ(1, decode_request_count_);
@@ -223,14 +223,14 @@
   SetFrameStatus(ImageFrame::kFrameComplete);
   AddNewData();
 
-  generator_->DecodeAndScale(segment_reader_.Get(), false, 0, ImageInfo(),
+  generator_->DecodeAndScale(segment_reader_.get(), false, 0, ImageInfo(),
                              buffer, 100 * 4,
                              ImageDecoder::kAlphaPremultiplied);
   EXPECT_EQ(2, decode_request_count_);
   EXPECT_EQ(1, decoders_destroyed_);
 
   // Decoder created again.
-  generator_->DecodeAndScale(segment_reader_.Get(), false, 0, ImageInfo(),
+  generator_->DecodeAndScale(segment_reader_.get(), false, 0, ImageInfo(),
                              buffer, 100 * 4,
                              ImageDecoder::kAlphaPremultiplied);
   EXPECT_EQ(3, decode_request_count_);
@@ -247,7 +247,7 @@
   SetFrameStatus(ImageFrame::kFramePartial);
 
   char buffer[100 * 100 * 4];
-  generator_->DecodeAndScale(segment_reader_.Get(), false, 0, ImageInfo(),
+  generator_->DecodeAndScale(segment_reader_.get(), false, 0, ImageInfo(),
                              buffer, 100 * 4,
                              ImageDecoder::kAlphaPremultiplied);
   EXPECT_EQ(1, decode_request_count_);
@@ -266,7 +266,7 @@
   EXPECT_EQ(1, decoders_destroyed_);
 
   // Decoder created again.
-  generator_->DecodeAndScale(segment_reader_.Get(), false, 0, ImageInfo(),
+  generator_->DecodeAndScale(segment_reader_.get(), false, 0, ImageInfo(),
                              buffer, 100 * 4,
                              ImageDecoder::kAlphaPremultiplied);
   EXPECT_EQ(3, decode_request_count_);
@@ -281,7 +281,7 @@
   SetFrameStatus(ImageFrame::kFramePartial);
 
   char buffer[100 * 100 * 4];
-  generator_->DecodeAndScale(segment_reader_.Get(), false, 0, ImageInfo(),
+  generator_->DecodeAndScale(segment_reader_.get(), false, 0, ImageInfo(),
                              buffer, 100 * 4,
                              ImageDecoder::kAlphaPremultiplied);
   EXPECT_TRUE(generator_->HasAlpha(0));
@@ -289,15 +289,15 @@
 
   ImageDecoder* temp_decoder = 0;
   EXPECT_TRUE(ImageDecodingStore::Instance().LockDecoder(
-      generator_.Get(), FullSize(), ImageDecoder::kAlphaPremultiplied,
+      generator_.get(), FullSize(), ImageDecoder::kAlphaPremultiplied,
       &temp_decoder));
   ASSERT_TRUE(temp_decoder);
   temp_decoder->DecodeFrameBufferAtIndex(0)->SetHasAlpha(false);
-  ImageDecodingStore::Instance().UnlockDecoder(generator_.Get(), temp_decoder);
+  ImageDecodingStore::Instance().UnlockDecoder(generator_.get(), temp_decoder);
   EXPECT_EQ(2, decode_request_count_);
 
   SetFrameStatus(ImageFrame::kFrameComplete);
-  generator_->DecodeAndScale(segment_reader_.Get(), false, 0, ImageInfo(),
+  generator_->DecodeAndScale(segment_reader_.get(), false, 0, ImageInfo(),
                              buffer, 100 * 4,
                              ImageDecoder::kAlphaPremultiplied);
   EXPECT_EQ(3, decode_request_count_);
@@ -309,7 +309,7 @@
   SetFrameStatus(ImageFrame::kFrameComplete);
 
   char buffer[100 * 100 * 4];
-  generator_->DecodeAndScale(segment_reader_.Get(), true, 0, ImageInfo(),
+  generator_->DecodeAndScale(segment_reader_.get(), true, 0, ImageInfo(),
                              buffer, 100 * 4,
                              ImageDecoder::kAlphaPremultiplied);
   EXPECT_EQ(1, decode_request_count_);
@@ -318,7 +318,7 @@
 
   SetFrameStatus(ImageFrame::kFrameComplete);
 
-  generator_->DecodeAndScale(segment_reader_.Get(), true, 1, ImageInfo(),
+  generator_->DecodeAndScale(segment_reader_.get(), true, 1, ImageInfo(),
                              buffer, 100 * 4,
                              ImageDecoder::kAlphaPremultiplied);
   EXPECT_EQ(2, decode_request_count_);
@@ -330,7 +330,7 @@
   // Decoding the last frame of a multi-frame images should trigger clearing
   // all the frame data, but not destroying the decoder.  See comments in
   // ImageFrameGenerator::tryToResumeDecode().
-  generator_->DecodeAndScale(segment_reader_.Get(), true, 2, ImageInfo(),
+  generator_->DecodeAndScale(segment_reader_.get(), true, 2, ImageInfo(),
                              buffer, 100 * 4,
                              ImageDecoder::kAlphaPremultiplied);
   EXPECT_EQ(3, decode_request_count_);
diff --git a/third_party/WebKit/Source/platform/graphics/ImageLayerChromiumTest.cpp b/third_party/WebKit/Source/platform/graphics/ImageLayerChromiumTest.cpp
index dd98d851..c5f9e9d 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageLayerChromiumTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ImageLayerChromiumTest.cpp
@@ -104,9 +104,9 @@
 
   bool opaque = false;
   RefPtr<Image> image = TestImage::Create(IntSize(100, 100), opaque);
-  ASSERT_TRUE(image.Get());
+  ASSERT_TRUE(image.get());
 
-  graphics_layer->SetContentsToImage(image.Get());
+  graphics_layer->SetContentsToImage(image.get());
   ASSERT_TRUE(graphics_layer->HasContentsLayer());
   ASSERT_TRUE(graphics_layer->ContentsLayer());
 
@@ -123,17 +123,17 @@
 
   bool opaque = true;
   RefPtr<Image> opaque_image = TestImage::Create(IntSize(100, 100), opaque);
-  ASSERT_TRUE(opaque_image.Get());
+  ASSERT_TRUE(opaque_image.get());
   RefPtr<Image> non_opaque_image =
       TestImage::Create(IntSize(100, 100), !opaque);
-  ASSERT_TRUE(non_opaque_image.Get());
+  ASSERT_TRUE(non_opaque_image.get());
 
   ASSERT_FALSE(graphics_layer->ContentsLayer());
 
-  graphics_layer->SetContentsToImage(opaque_image.Get());
+  graphics_layer->SetContentsToImage(opaque_image.get());
   ASSERT_TRUE(graphics_layer->ContentsLayer()->Opaque());
 
-  graphics_layer->SetContentsToImage(non_opaque_image.Get());
+  graphics_layer->SetContentsToImage(non_opaque_image.get());
   ASSERT_FALSE(graphics_layer->ContentsLayer()->Opaque());
 }
 
diff --git a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasResourceProvider.cpp b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasResourceProvider.cpp
index 50764db1..8e9984a 100644
--- a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasResourceProvider.cpp
+++ b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasResourceProvider.cpp
@@ -165,6 +165,7 @@
 
   std::unique_ptr<FrameResource> frame_resource =
       CreateOrRecycleFrameResource();
+  frame_resource->context_provider_wrapper_ = image->ContextProviderWrapper();
   frame_resource->image_ = std::move(image);
   resources_.insert(next_resource_id_, std::move(frame_resource));
 }
diff --git a/third_party/WebKit/Source/platform/graphics/PictureSnapshot.cpp b/third_party/WebKit/Source/platform/graphics/PictureSnapshot.cpp
index 957bb0f5..64b94b4 100644
--- a/third_party/WebKit/Source/platform/graphics/PictureSnapshot.cpp
+++ b/third_party/WebKit/Source/platform/graphics/PictureSnapshot.cpp
@@ -43,7 +43,6 @@
 #include "platform/image-encoders/ImageEncoder.h"
 #include "platform/wtf/CurrentTime.h"
 #include "platform/wtf/HexNumber.h"
-#include "platform/wtf/PtrUtil.h"
 #include "platform/wtf/text/Base64.h"
 #include "platform/wtf/text/TextEncoding.h"
 #include "third_party/skia/include/core/SkData.h"
@@ -143,7 +142,7 @@
     canvas.ResetStepCount();
     picture_->playback(&canvas, &canvas);
   }
-  std::unique_ptr<Vector<char>> base64_data = WTF::MakeUnique<Vector<char>>();
+  std::unique_ptr<Vector<char>> base64_data = std::make_unique<Vector<char>>();
   Vector<char> encoded_image;
 
   SkPixmap src;
@@ -169,7 +168,7 @@
     double min_duration,
     const FloatRect* clip_rect) const {
   std::unique_ptr<PictureSnapshot::Timings> timings =
-      WTF::MakeUnique<PictureSnapshot::Timings>();
+      std::make_unique<PictureSnapshot::Timings>();
   timings->ReserveCapacity(min_repeat_count);
   const SkIRect bounds = picture_->cullRect().roundOut();
   SkBitmap bitmap;
diff --git a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp
index af9580e..9628d23 100644
--- a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp
@@ -13,7 +13,6 @@
 #include "platform/graphics/paint/PaintCanvas.h"
 #include "platform/graphics/paint/PaintRecord.h"
 #include "platform/testing/TestingPlatformSupport.h"
-#include "platform/wtf/PtrUtil.h"
 #include "platform/wtf/RefPtr.h"
 #include "public/platform/Platform.h"
 #include "public/platform/WebThread.h"
@@ -28,7 +27,7 @@
 class RecordingImageBufferSurfaceTest : public Test {
  protected:
   RecordingImageBufferSurfaceTest() {
-    auto test_surface = WTF::MakeUnique<RecordingImageBufferSurface>(
+    auto test_surface = std::make_unique<RecordingImageBufferSurface>(
         IntSize(10, 10), RecordingImageBufferSurface::kAllowFallback,
         kNonOpaque);
     test_surface_ = test_surface.get();
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/ContentLayerClientImpl.cpp b/third_party/WebKit/Source/platform/graphics/compositing/ContentLayerClientImpl.cpp
index c047fe6..92fb6ac 100644
--- a/third_party/WebKit/Source/platform/graphics/compositing/ContentLayerClientImpl.cpp
+++ b/third_party/WebKit/Source/platform/graphics/compositing/ContentLayerClientImpl.cpp
@@ -4,6 +4,7 @@
 
 #include "platform/graphics/compositing/ContentLayerClientImpl.h"
 
+#include <memory>
 #include "cc/paint/paint_op_buffer.h"
 #include "platform/geometry/GeometryAsJSON.h"
 #include "platform/graphics/compositing/PaintChunksToCcLayer.h"
@@ -20,7 +21,7 @@
 void ContentLayerClientImpl::SetTracksRasterInvalidations(bool should_track) {
   if (should_track) {
     raster_invalidation_tracking_info_ =
-        WTF::MakeUnique<RasterInvalidationTrackingInfo>();
+        std::make_unique<RasterInvalidationTrackingInfo>();
 
     for (const auto& info : paint_chunks_info_) {
       raster_invalidation_tracking_info_->old_client_debug_names.Set(
@@ -349,7 +350,7 @@
   if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() &&
       !raster_invalidation_tracking_info_) {
     raster_invalidation_tracking_info_ =
-        WTF::MakeUnique<RasterInvalidationTrackingInfo>();
+        std::make_unique<RasterInvalidationTrackingInfo>();
   }
 
   bool layer_bounds_was_empty = layer_bounds_.IsEmpty();
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/ContentLayerClientImplTest.cpp b/third_party/WebKit/Source/platform/graphics/compositing/ContentLayerClientImplTest.cpp
index bcc28f1..71a5c63 100644
--- a/third_party/WebKit/Source/platform/graphics/compositing/ContentLayerClientImplTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/compositing/ContentLayerClientImplTest.cpp
@@ -248,12 +248,12 @@
   RefPtr<ClipPaintPropertyNode> clip2 = ClipPaintPropertyNode::Create(
       clip0, TransformPaintPropertyNode::Root(), clip_rect);
 
-  PropertyTreeState layer_state(TransformPaintPropertyNode::Root(), clip0.Get(),
+  PropertyTreeState layer_state(TransformPaintPropertyNode::Root(), clip0.get(),
                                 EffectPaintPropertyNode::Root());
   chunks_array[0].properties = PaintChunkProperties(layer_state);
   chunks_array[1].properties = PaintChunkProperties(layer_state);
   chunks_array[2].properties = PaintChunkProperties(
-      PropertyTreeState(TransformPaintPropertyNode::Root(), clip2.Get(),
+      PropertyTreeState(TransformPaintPropertyNode::Root(), clip2.get(),
                         EffectPaintPropertyNode::Root()));
 
   c.SetTracksRasterInvalidations(true);
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp
index a95aa96..63cf22b 100644
--- a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp
+++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp
@@ -4,6 +4,7 @@
 
 #include "platform/graphics/compositing/PaintArtifactCompositor.h"
 
+#include <memory>
 #include "cc/layers/layer.h"
 #include "cc/layers/picture_layer.h"
 #include "cc/paint/display_item_list.h"
@@ -178,13 +179,13 @@
   }
 
   // TODO(pdr): Add a helper for blink::FloatPoint to gfx::Vector2dF.
-  auto offset = scroll_node.Offset();
+  auto offset = scroll_node.ContainerRect().Location();
   layer_offset = gfx::Vector2dF(offset.X(), offset.Y());
   // TODO(pdr): The scroll layer's bounds are currently set to the clipped
   // container bounds but this does not include the border. We may want to
   // change this behavior to make non-composited and composited hit testing
   // match (see: crbug.com/753124).
-  auto bounds = scroll_node.ContainerBounds();
+  auto bounds = scroll_node.ContainerRect().Size();
   // Mark the layer as scrollable.
   // TODO(pdr): When SPV2 launches this parameter for bounds will not be needed.
   scroll_layer->SetScrollable(bounds);
@@ -207,7 +208,7 @@
       return std::move(client);
   }
 
-  auto client = WTF::MakeUnique<ContentLayerClientImpl>();
+  auto client = std::make_unique<ContentLayerClientImpl>();
   client->SetTracksRasterInvalidations(tracks_raster_invalidations_);
   return client;
 }
@@ -261,7 +262,8 @@
     const PaintChunk& first_paint_chunk,
     bool chunk_requires_own_layer)
     : bounds(first_paint_chunk.bounds),
-      known_to_be_opaque(first_paint_chunk.known_to_be_opaque),
+      rect_known_to_be_opaque(
+          first_paint_chunk.known_to_be_opaque ? bounds : FloatRect()),
       backface_hidden(first_paint_chunk.properties.backface_hidden),
       property_tree_state(first_paint_chunk.properties.property_tree_state),
       requires_own_layer(chunk_requires_own_layer) {
@@ -276,13 +278,11 @@
   FloatClipRect guest_bounds_in_home(guest.bounds);
   GeometryMapper::LocalToAncestorVisualRect(
       guest.property_tree_state, property_tree_state, guest_bounds_in_home);
-  FloatRect old_bounds = bounds;
   bounds.Unite(guest_bounds_in_home.Rect());
-  if (bounds != old_bounds)
-    known_to_be_opaque = false;
   // TODO(crbug.com/701991): Upgrade GeometryMapper.
   // If we knew the new bounds is enclosed by the mapped opaque region of
-  // the guest layer, we can deduce the merged layer being opaque too.
+  // the guest layer, we can deduce the merged layer being opaque too, and
+  // update rect_known_to_be_opaque accordingly.
 }
 
 static bool CanUpcastTo(const PropertyTreeState& guest,
@@ -313,7 +313,7 @@
   // region. To determine whether the layer is still opaque, we need to
   // query conservative opaque rect after mapping to an ancestor space,
   // which is not supported by GeometryMapper yet.
-  known_to_be_opaque = false;
+  rect_known_to_be_opaque = FloatRect();
 }
 
 static bool IsNonCompositingAncestorOf(
@@ -665,20 +665,31 @@
   for (auto& entry : synthesized_clip_cache_)
     entry.in_use = false;
 
-  for (const PendingLayer& pending_layer : pending_layers) {
+  for (auto& pending_layer : pending_layers) {
+    const auto& property_state = pending_layer.property_tree_state;
+    const auto* transform = property_state.Transform();
+    const auto* clip = property_state.Clip();
+
+    if (clip->LocalTransformSpace() == transform) {
+      // Limit layer bounds to hide the areas that will be never visible because
+      // of the clip.
+      pending_layer.bounds.Intersect(clip->ClipRect().Rect());
+    } else if (const auto* scroll = transform->ScrollNode()) {
+      // Limit layer bounds to the scroll range to hide the areas that will
+      // never be scrolled into the visible area.
+      pending_layer.bounds.Intersect(FloatRect(scroll->ContentsRect()));
+    }
+
     gfx::Vector2dF layer_offset;
     scoped_refptr<cc::Layer> layer = CompositedLayerForPendingLayer(
         paint_artifact, pending_layer, layer_offset, new_content_layer_clients,
         new_scroll_hit_test_layers);
 
-    auto property_state = pending_layer.property_tree_state;
-    const auto* transform = property_state.Transform();
     int transform_id =
         property_tree_manager.EnsureCompositorTransformNode(transform);
-    int clip_id =
-        property_tree_manager.EnsureCompositorClipNode(property_state.Clip());
+    int clip_id = property_tree_manager.EnsureCompositorClipNode(clip);
     int effect_id = property_tree_manager.SwitchToEffectNodeWithSynthesizedClip(
-        *property_state.Effect(), *property_state.Clip());
+        *property_state.Effect(), *clip);
     // The compositor scroll node is not directly stored in the property tree
     // state but can be created via the scroll offset translation node.
     const auto& scroll_translation =
@@ -719,11 +730,8 @@
     layer->SetScrollTreeIndex(scroll_id);
     layer->SetClipTreeIndex(clip_id);
     layer->SetEffectTreeIndex(effect_id);
-
-    layer->SetContentsOpaque(
-        // Don't set opaque if the pending_layer's bounds are at subpixels.
-        EnclosingIntRect(pending_layer.bounds) == pending_layer.bounds &&
-        pending_layer.known_to_be_opaque);
+    layer->SetContentsOpaque(pending_layer.rect_known_to_be_opaque.Contains(
+        FloatRect(EnclosingIntRect(pending_layer.bounds))));
     layer->SetDoubleSided(!pending_layer.backface_hidden);
     layer->SetShouldCheckBackfaceVisibility(pending_layer.backface_hidden);
   }
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.h b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.h
index 50175af..d9a9ae8e 100644
--- a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.h
+++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.h
@@ -120,7 +120,7 @@
 
     FloatRect bounds;
     Vector<const PaintChunk*> paint_chunks;
-    bool known_to_be_opaque;
+    FloatRect rect_known_to_be_opaque;
     bool backface_hidden;
     PropertyTreeState property_tree_state;
     bool requires_own_layer;
@@ -221,7 +221,7 @@
   std::unique_ptr<ExtraDataForTesting> extra_data_for_testing_;
 
   friend class StubChromeClientForSPv2;
-  friend class PaintArtifactCompositorTestWithPropertyTrees;
+  friend class PaintArtifactCompositorTest;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp
index cb37568..24b29dd 100644
--- a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp
@@ -84,11 +84,10 @@
   unsigned did_scroll_count;
 };
 
-class PaintArtifactCompositorTestWithPropertyTrees
-    : public ::testing::Test,
-      private ScopedSlimmingPaintV2ForTest {
+class PaintArtifactCompositorTest : public ::testing::Test,
+                                    private ScopedSlimmingPaintV2ForTest {
  protected:
-  PaintArtifactCompositorTestWithPropertyTrees()
+  PaintArtifactCompositorTest()
       : ScopedSlimmingPaintV2ForTest(true),
         task_runner_(new base::TestSimpleTaskRunner),
         task_runner_handle_(task_runner_) {}
@@ -104,7 +103,7 @@
     settings.single_thread_proxy_scheduler = false;
     settings.use_layer_lists = true;
     web_layer_tree_view_ =
-        WTF::MakeUnique<WebLayerTreeViewWithLayerTreeFrameSink>(settings);
+        std::make_unique<WebLayerTreeViewWithLayerTreeFrameSink>(settings);
     web_layer_tree_view_->SetRootLayer(
         *paint_artifact_compositor_->GetWebLayer());
   }
@@ -245,6 +244,8 @@
   std::unique_ptr<WebLayerTreeViewWithLayerTreeFrameSink> web_layer_tree_view_;
 };
 
+const auto kNotScrollingOnMain = MainThreadScrollingReason::kNotScrollingOnMain;
+
 // Convenient shorthands.
 const TransformPaintPropertyNode* t0() {
   return TransformPaintPropertyNode::Root();
@@ -256,13 +257,13 @@
   return EffectPaintPropertyNode::Root();
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, EmptyPaintArtifact) {
+TEST_F(PaintArtifactCompositorTest, EmptyPaintArtifact) {
   PaintArtifact empty_artifact;
   Update(empty_artifact);
   EXPECT_TRUE(RootLayer()->children().empty());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, OneChunkWithAnOffset) {
+TEST_F(PaintArtifactCompositorTest, OneChunkWithAnOffset) {
   TestPaintArtifact artifact;
   artifact.Chunk(DefaultPaintChunkProperties())
       .RectDrawing(FloatRect(50, -50, 100, 100), Color::kWhite);
@@ -277,7 +278,7 @@
   EXPECT_EQ(gfx::Size(100, 100), child->bounds());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, OneTransform) {
+TEST_F(PaintArtifactCompositorTest, OneTransform) {
   // A 90 degree clockwise rotation about (100, 100).
   RefPtr<TransformPaintPropertyNode> transform =
       TransformPaintPropertyNode::Create(
@@ -324,7 +325,7 @@
   }
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, TransformCombining) {
+TEST_F(PaintArtifactCompositorTest, TransformCombining) {
   // A translation by (5, 5) within a 2x scale about (10, 10).
   RefPtr<TransformPaintPropertyNode> transform1 =
       TransformPaintPropertyNode::Create(
@@ -369,8 +370,7 @@
             ContentLayerAt(1)->transform_tree_index());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       FlattensInheritedTransform) {
+TEST_F(PaintArtifactCompositorTest, FlattensInheritedTransform) {
   for (bool transform_is_flattened : {true, false}) {
     SCOPED_TRACE(transform_is_flattened);
 
@@ -427,7 +427,7 @@
   }
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, SortingContextID) {
+TEST_F(PaintArtifactCompositorTest, SortingContextID) {
   // Has no 3D rendering context.
   RefPtr<TransformPaintPropertyNode> transform1 =
       TransformPaintPropertyNode::Create(TransformPaintPropertyNode::Root(),
@@ -513,7 +513,7 @@
   EXPECT_NE(light_gray_sorting_context_id, black_sorting_context_id);
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, OneClip) {
+TEST_F(PaintArtifactCompositorTest, OneClip) {
   RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::Create(
       ClipPaintPropertyNode::Root(), TransformPaintPropertyNode::Root(),
       FloatRoundedRect(100, 100, 300, 200));
@@ -527,10 +527,13 @@
 
   ASSERT_EQ(1u, ContentLayerCount());
   const cc::Layer* layer = ContentLayerAt(0);
+  // The layer is clipped.
+  EXPECT_EQ(gfx::Size(180, 180), layer->bounds());
+  EXPECT_EQ(gfx::Vector2dF(220, 100), layer->offset_to_transform_parent());
   EXPECT_THAT(
       layer->GetPicture(),
-      Pointee(DrawsRectangle(FloatRect(0, 0, 300, 200), Color::kBlack)));
-  EXPECT_EQ(Translation(220, 80), layer->ScreenSpaceTransform());
+      Pointee(DrawsRectangle(FloatRect(0, 0, 300, 180), Color::kBlack)));
+  EXPECT_EQ(Translation(220, 100), layer->ScreenSpaceTransform());
 
   const cc::ClipNode* clip_node =
       GetPropertyTrees().clip_tree.Node(layer->clip_tree_index());
@@ -538,7 +541,7 @@
   EXPECT_EQ(gfx::RectF(100, 100, 300, 200), clip_node->clip);
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, NestedClips) {
+TEST_F(PaintArtifactCompositorTest, NestedClips) {
   RefPtr<ClipPaintPropertyNode> clip1 = ClipPaintPropertyNode::Create(
       ClipPaintPropertyNode::Root(), TransformPaintPropertyNode::Root(),
       FloatRoundedRect(100, 100, 700, 700),
@@ -608,7 +611,7 @@
   EXPECT_EQ(outer_clip->id, inner_clip->parent_id);
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, DeeplyNestedClips) {
+TEST_F(PaintArtifactCompositorTest, DeeplyNestedClips) {
   Vector<RefPtr<ClipPaintPropertyNode>> clips;
   for (unsigned i = 1; i <= 10; i++) {
     clips.push_back(ClipPaintPropertyNode::Create(
@@ -624,26 +627,28 @@
       .RectDrawing(FloatRect(0, 0, 200, 200), Color::kWhite);
   Update(artifact.Build());
 
-  // Check the drawing layer.
+  // Check the drawing layer. It's clipped.
   ASSERT_EQ(1u, ContentLayerCount());
   const cc::Layer* drawing_layer = ContentLayerAt(0);
+  EXPECT_EQ(gfx::Size(100, 100), drawing_layer->bounds());
+  EXPECT_EQ(gfx::Vector2dF(50, 0), drawing_layer->offset_to_transform_parent());
   EXPECT_THAT(
       drawing_layer->GetPicture(),
-      Pointee(DrawsRectangle(FloatRect(0, 0, 200, 200), Color::kWhite)));
-  EXPECT_EQ(gfx::Transform(), drawing_layer->ScreenSpaceTransform());
+      Pointee(DrawsRectangle(FloatRect(0, 0, 150, 200), Color::kWhite)));
+  EXPECT_EQ(Translation(50, 0), drawing_layer->ScreenSpaceTransform());
 
   // Check the clip nodes.
   const cc::ClipNode* clip_node =
       GetPropertyTrees().clip_tree.Node(drawing_layer->clip_tree_index());
   for (auto it = clips.rbegin(); it != clips.rend(); ++it) {
-    const ClipPaintPropertyNode* paint_clip_node = it->Get();
+    const ClipPaintPropertyNode* paint_clip_node = it->get();
     EXPECT_EQ(cc::ClipNode::ClipType::APPLIES_LOCAL_CLIP, clip_node->clip_type);
     EXPECT_EQ(paint_clip_node->ClipRect().Rect(), clip_node->clip);
     clip_node = GetPropertyTrees().clip_tree.Node(clip_node->parent_id);
   }
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, SiblingClips) {
+TEST_F(PaintArtifactCompositorTest, SiblingClips) {
   RefPtr<ClipPaintPropertyNode> common_clip = ClipPaintPropertyNode::Create(
       ClipPaintPropertyNode::Root(), TransformPaintPropertyNode::Root(),
       FloatRoundedRect(0, 0, 800, 600));
@@ -677,10 +682,13 @@
   ASSERT_EQ(gfx::RectF(0, 0, 400, 600), white_clip->clip);
 
   const cc::Layer* black_layer = ContentLayerAt(1);
+  // The layer is clipped.
+  EXPECT_EQ(gfx::Size(240, 480), black_layer->bounds());
+  EXPECT_EQ(gfx::Vector2dF(400, 0), black_layer->offset_to_transform_parent());
   EXPECT_THAT(
       black_layer->GetPicture(),
-      Pointee(DrawsRectangle(FloatRect(0, 0, 640, 480), Color::kBlack)));
-  EXPECT_EQ(gfx::Transform(), black_layer->ScreenSpaceTransform());
+      Pointee(DrawsRectangle(FloatRect(0, 0, 240, 480), Color::kBlack)));
+  EXPECT_EQ(Translation(400, 0), black_layer->ScreenSpaceTransform());
   const cc::ClipNode* black_clip =
       GetPropertyTrees().clip_tree.Node(black_layer->clip_tree_index());
   EXPECT_EQ(cc::ClipNode::ClipType::APPLIES_LOCAL_CLIP, black_clip->clip_type);
@@ -694,8 +702,7 @@
   ASSERT_EQ(gfx::RectF(0, 0, 800, 600), common_clip_node->clip);
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       ForeignLayerPassesThrough) {
+TEST_F(PaintArtifactCompositorTest, ForeignLayerPassesThrough) {
   scoped_refptr<cc::Layer> layer = cc::Layer::Create();
 
   TestPaintArtifact test_artifact;
@@ -720,7 +727,7 @@
   EXPECT_EQ(Translation(50, 60), layer->ScreenSpaceTransform());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, EffectTreeConversion) {
+TEST_F(PaintArtifactCompositorTest, EffectTreeConversion) {
   RefPtr<EffectPaintPropertyNode> effect1 = EffectPaintPropertyNode::Create(
       EffectPaintPropertyNode::Root(), TransformPaintPropertyNode::Root(),
       ClipPaintPropertyNode::Root(), kColorFilterNone,
@@ -740,15 +747,15 @@
   TestPaintArtifact artifact;
   artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
-             effect2.Get())
+             effect2.get())
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
   artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
-             effect1.Get())
+             effect1.get())
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
   artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
-             effect3.Get())
+             effect3.get())
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
   Update(artifact.Build());
 
@@ -783,11 +790,11 @@
   EXPECT_EQ(converted_effect3.id, ContentLayerAt(2)->effect_tree_index());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, OneScrollNode) {
+TEST_F(PaintArtifactCompositorTest, OneScrollNode) {
   CompositorElementId scroll_element_id = ScrollElementId(2);
   RefPtr<ScrollPaintPropertyNode> scroll = ScrollPaintPropertyNode::Create(
-      ScrollPaintPropertyNode::Root(), IntPoint(3, 5), IntSize(11, 13),
-      IntSize(27, 31), true, false, 0 /* mainThreadScrollingReasons */,
+      ScrollPaintPropertyNode::Root(), IntRect(3, 5, 11, 13),
+      IntRect(-3, -5, 27, 31), true, false, kNotScrollingOnMain,
       scroll_element_id);
   RefPtr<TransformPaintPropertyNode> scroll_translation =
       TransformPaintPropertyNode::Create(
@@ -803,7 +810,7 @@
   artifact
       .Chunk(scroll_translation, ClipPaintPropertyNode::Root(),
              EffectPaintPropertyNode::Root())
-      .RectDrawing(FloatRect(11, 13, 17, 19), Color::kWhite);
+      .RectDrawing(FloatRect(-110, 12, 170, 19), Color::kWhite);
   Update(artifact.Build());
 
   const cc::ScrollTree& scroll_tree = GetPropertyTrees().scroll_tree;
@@ -824,8 +831,7 @@
       *transform_tree.Node(scroll_node.transform_id);
   EXPECT_TRUE(transform_node.local.IsIdentity());
   EXPECT_EQ(gfx::ScrollOffset(-7, -9), transform_node.scroll_offset);
-  EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
-            scroll_node.main_thread_scrolling_reasons);
+  EXPECT_EQ(kNotScrollingOnMain, scroll_node.main_thread_scrolling_reasons);
 
   auto* layer = ContentLayerAt(0);
   auto transform_node_index = layer->transform_tree_index();
@@ -833,6 +839,12 @@
   auto scroll_node_index = layer->scroll_tree_index();
   EXPECT_EQ(scroll_node_index, scroll_node.id);
 
+  // The scrolling contents layer is clipped to the scrolling range.
+  EXPECT_EQ(gfx::Size(27, 14), layer->bounds());
+  EXPECT_EQ(gfx::Vector2dF(-3, 12), layer->offset_to_transform_parent());
+  EXPECT_THAT(layer->GetPicture(),
+              Pointee(DrawsRectangle(FloatRect(0, 0, 63, 19), Color::kWhite)));
+
   auto* scroll_layer = ScrollHitTestLayerAt(0);
   EXPECT_TRUE(scroll_layer->scrollable());
   // The scroll layer should be sized to the container bounds.
@@ -849,10 +861,10 @@
   EXPECT_EQ(gfx::ScrollOffset(1, 2), ScrollClient().last_scroll_offset);
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, TransformUnderScrollNode) {
+TEST_F(PaintArtifactCompositorTest, TransformUnderScrollNode) {
   RefPtr<ScrollPaintPropertyNode> scroll = ScrollPaintPropertyNode::Create(
-      ScrollPaintPropertyNode::Root(), IntPoint(), IntSize(11, 13),
-      IntSize(27, 31), true, false, 0 /* mainThreadScrollingReasons */,
+      ScrollPaintPropertyNode::Root(), IntRect(0, 0, 11, 13),
+      IntRect(-3, -5, 27, 31), true, false, kNotScrollingOnMain,
       CompositorElementId());
   RefPtr<TransformPaintPropertyNode> scroll_translation =
       TransformPaintPropertyNode::Create(
@@ -869,10 +881,10 @@
   artifact
       .Chunk(scroll_translation, ClipPaintPropertyNode::Root(),
              EffectPaintPropertyNode::Root())
-      .RectDrawing(FloatRect(2, 4, 6, 8), Color::kBlack)
+      .RectDrawing(FloatRect(-20, 4, 60, 8), Color::kBlack)
       .Chunk(transform, ClipPaintPropertyNode::Root(),
              EffectPaintPropertyNode::Root())
-      .RectDrawing(FloatRect(1, 3, 5, 7), Color::kWhite);
+      .RectDrawing(FloatRect(1, -30, 5, 70), Color::kWhite);
   Update(artifact.Build());
 
   const cc::ScrollTree& scroll_tree = GetPropertyTrees().scroll_tree;
@@ -881,26 +893,38 @@
   const cc::ScrollNode& scroll_node = *scroll_tree.Node(2);
 
   // Both layers should refer to the same scroll tree node.
-  EXPECT_EQ(scroll_node.id, ContentLayerAt(0)->scroll_tree_index());
-  EXPECT_EQ(scroll_node.id, ContentLayerAt(1)->scroll_tree_index());
+  const auto* layer0 = ContentLayerAt(0);
+  const auto* layer1 = ContentLayerAt(1);
+  EXPECT_EQ(scroll_node.id, layer0->scroll_tree_index());
+  EXPECT_EQ(scroll_node.id, layer1->scroll_tree_index());
+
+  // The scrolling layer is clipped to the scrollable range.
+  EXPECT_EQ(gfx::Vector2dF(-3, 4), layer0->offset_to_transform_parent());
+  EXPECT_EQ(gfx::Size(27, 8), layer0->bounds());
+  EXPECT_THAT(layer0->GetPicture(),
+              Pointee(DrawsRectangle(FloatRect(0, 0, 43, 8), Color::kBlack)));
+
+  // The layer under the transform without a scroll node is not clipped.
+  EXPECT_EQ(gfx::Vector2dF(1, -30), layer1->offset_to_transform_parent());
+  EXPECT_EQ(gfx::Size(5, 70), layer1->bounds());
+  EXPECT_THAT(layer1->GetPicture(),
+              Pointee(DrawsRectangle(FloatRect(0, 0, 5, 70), Color::kWhite)));
 
   const cc::TransformTree& transform_tree = GetPropertyTrees().transform_tree;
   const cc::TransformNode& scroll_transform_node =
       *transform_tree.Node(scroll_node.transform_id);
   // The layers have different transform nodes.
-  EXPECT_EQ(scroll_transform_node.id,
-            ContentLayerAt(0)->transform_tree_index());
-  EXPECT_NE(scroll_transform_node.id,
-            ContentLayerAt(1)->transform_tree_index());
+  EXPECT_EQ(scroll_transform_node.id, layer0->transform_tree_index());
+  EXPECT_NE(scroll_transform_node.id, layer1->transform_tree_index());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, NestedScrollNodes) {
+TEST_F(PaintArtifactCompositorTest, NestedScrollNodes) {
   RefPtr<EffectPaintPropertyNode> effect =
       CreateOpacityOnlyEffect(EffectPaintPropertyNode::Root(), 0.5);
 
   CompositorElementId scroll_element_id_a = ScrollElementId(2);
   RefPtr<ScrollPaintPropertyNode> scroll_a = ScrollPaintPropertyNode::Create(
-      ScrollPaintPropertyNode::Root(), IntPoint(), IntSize(2, 3), IntSize(5, 7),
+      ScrollPaintPropertyNode::Root(), IntRect(0, 0, 2, 3), IntRect(0, 0, 5, 7),
       false, true,
       MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects,
       scroll_element_id_a);
@@ -913,8 +937,8 @@
 
   CompositorElementId scroll_element_id_b = ScrollElementId(3);
   RefPtr<ScrollPaintPropertyNode> scroll_b = ScrollPaintPropertyNode::Create(
-      scroll_translation_a->ScrollNode(), IntPoint(), IntSize(19, 23),
-      IntSize(29, 31), true, false, 0 /* mainThreadScrollingReasons */,
+      scroll_translation_a->ScrollNode(), IntRect(0, 0, 19, 23),
+      IntRect(0, 0, 29, 31), true, false, kNotScrollingOnMain,
       scroll_element_id_b);
   RefPtr<TransformPaintPropertyNode> scroll_translation_b =
       TransformPaintPropertyNode::Create(
@@ -971,15 +995,15 @@
   EXPECT_EQ(gfx::ScrollOffset(-37, -41), transform_node_b.scroll_offset);
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, ScrollHitTestLayerOrder) {
+TEST_F(PaintArtifactCompositorTest, ScrollHitTestLayerOrder) {
   RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::Create(
       ClipPaintPropertyNode::Root(), TransformPaintPropertyNode::Root(),
       FloatRoundedRect(0, 0, 100, 100));
 
   CompositorElementId scroll_element_id = ScrollElementId(2);
   RefPtr<ScrollPaintPropertyNode> scroll = ScrollPaintPropertyNode::Create(
-      ScrollPaintPropertyNode::Root(), IntPoint(), IntSize(100, 100),
-      IntSize(100, 100), true, false, 0 /* mainThreadScrollingReasons */,
+      ScrollPaintPropertyNode::Root(), IntRect(0, 0, 100, 100),
+      IntRect(0, 0, 100, 100), true, false, kNotScrollingOnMain,
       scroll_element_id);
   RefPtr<TransformPaintPropertyNode> scroll_translation =
       TransformPaintPropertyNode::Create(
@@ -1021,15 +1045,14 @@
   EXPECT_EQ(CompositorElementId(), ContentLayerAt(1)->element_id());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       NestedScrollHitTestLayerOrder) {
+TEST_F(PaintArtifactCompositorTest, NestedScrollHitTestLayerOrder) {
   RefPtr<ClipPaintPropertyNode> clip_1 = ClipPaintPropertyNode::Create(
       ClipPaintPropertyNode::Root(), TransformPaintPropertyNode::Root(),
       FloatRoundedRect(0, 0, 100, 100));
   CompositorElementId scroll_1_element_id = ScrollElementId(1);
   RefPtr<ScrollPaintPropertyNode> scroll_1 = ScrollPaintPropertyNode::Create(
-      ScrollPaintPropertyNode::Root(), IntPoint(), IntSize(100, 100),
-      IntSize(100, 100), true, false, 0 /* mainThreadScrollingReasons */,
+      ScrollPaintPropertyNode::Root(), IntRect(0, 0, 100, 100),
+      IntRect(0, 0, 100, 100), true, false, kNotScrollingOnMain,
       scroll_1_element_id);
   RefPtr<TransformPaintPropertyNode> scroll_translation_1 =
       TransformPaintPropertyNode::Create(
@@ -1042,8 +1065,8 @@
       clip_1, scroll_translation_1, FloatRoundedRect(0, 0, 50, 50));
   CompositorElementId scroll_2_element_id = ScrollElementId(2);
   RefPtr<ScrollPaintPropertyNode> scroll_2 = ScrollPaintPropertyNode::Create(
-      ScrollPaintPropertyNode::Root(), IntPoint(), IntSize(50, 50),
-      IntSize(50, 50), true, false, 0 /* mainThreadScrollingReasons */,
+      ScrollPaintPropertyNode::Root(), IntRect(0, 0, 50, 50),
+      IntRect(0, 0, 50, 50), true, false, kNotScrollingOnMain,
       scroll_2_element_id);
   RefPtr<TransformPaintPropertyNode> scroll_translation_2 =
       TransformPaintPropertyNode::Create(
@@ -1094,11 +1117,11 @@
 
 // If a scroll node is encountered before its parent, ensure the parent scroll
 // node is correctly created.
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, AncestorScrollNodes) {
+TEST_F(PaintArtifactCompositorTest, AncestorScrollNodes) {
   CompositorElementId scroll_element_id_a = ScrollElementId(2);
   RefPtr<ScrollPaintPropertyNode> scroll_a = ScrollPaintPropertyNode::Create(
-      ScrollPaintPropertyNode::Root(), IntPoint(), IntSize(2, 3), IntSize(5, 7),
-      false, true, 0 /* mainThreadScrollingReasons */, scroll_element_id_a);
+      ScrollPaintPropertyNode::Root(), IntRect(0, 0, 2, 3), IntRect(0, 0, 5, 7),
+      false, true, kNotScrollingOnMain, scroll_element_id_a);
   RefPtr<TransformPaintPropertyNode> scroll_translation_a =
       TransformPaintPropertyNode::Create(
           TransformPaintPropertyNode::Root(),
@@ -1108,8 +1131,8 @@
 
   CompositorElementId scroll_element_id_b = ScrollElementId(3);
   RefPtr<ScrollPaintPropertyNode> scroll_b = ScrollPaintPropertyNode::Create(
-      scroll_translation_a->ScrollNode(), IntPoint(), IntSize(19, 23),
-      IntSize(29, 31), true, false, 0 /* mainThreadScrollingReasons */,
+      scroll_translation_a->ScrollNode(), IntRect(0, 0, 19, 23),
+      IntRect(0, 0, 29, 31), true, false, kNotScrollingOnMain,
       scroll_element_id_b);
   RefPtr<TransformPaintPropertyNode> scroll_translation_b =
       TransformPaintPropertyNode::Create(
@@ -1160,7 +1183,7 @@
   EXPECT_EQ(gfx::ScrollOffset(-37, -41), transform_node_b.scroll_offset);
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, MergeSimpleChunks) {
+TEST_F(PaintArtifactCompositorTest, MergeSimpleChunks) {
   TestPaintArtifact test_artifact;
   test_artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
@@ -1189,7 +1212,7 @@
   }
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, MergeClip) {
+TEST_F(PaintArtifactCompositorTest, MergeClip) {
   RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::Create(
       ClipPaintPropertyNode::Root(), TransformPaintPropertyNode::Root(),
       FloatRoundedRect(10, 20, 50, 60));
@@ -1200,7 +1223,7 @@
              EffectPaintPropertyNode::Root())
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
   test_artifact
-      .Chunk(TransformPaintPropertyNode::Root(), clip.Get(),
+      .Chunk(TransformPaintPropertyNode::Root(), clip.get(),
              EffectPaintPropertyNode::Root())
       .RectDrawing(FloatRect(0, 0, 200, 300), Color::kBlack);
   test_artifact
@@ -1229,7 +1252,7 @@
   }
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, Merge2DTransform) {
+TEST_F(PaintArtifactCompositorTest, Merge2DTransform) {
   RefPtr<TransformPaintPropertyNode> transform =
       TransformPaintPropertyNode::Create(
           TransformPaintPropertyNode::Root(),
@@ -1242,7 +1265,7 @@
              EffectPaintPropertyNode::Root())
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
   test_artifact
-      .Chunk(transform.Get(), ClipPaintPropertyNode::Root(),
+      .Chunk(transform.get(), ClipPaintPropertyNode::Root(),
              EffectPaintPropertyNode::Root())
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
   test_artifact
@@ -1271,8 +1294,7 @@
   }
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       Merge2DTransformDirectAncestor) {
+TEST_F(PaintArtifactCompositorTest, Merge2DTransformDirectAncestor) {
   RefPtr<TransformPaintPropertyNode> transform =
       TransformPaintPropertyNode::Create(
           TransformPaintPropertyNode::Root(), TransformationMatrix(),
@@ -1280,18 +1302,18 @@
 
   RefPtr<TransformPaintPropertyNode> transform2 =
       TransformPaintPropertyNode::Create(
-          transform.Get(), TransformationMatrix().Translate(50, 50),
+          transform.get(), TransformationMatrix().Translate(50, 50),
           FloatPoint3D(100, 100, 0), false, 0);
 
   TestPaintArtifact test_artifact;
   test_artifact
-      .Chunk(transform.Get(), ClipPaintPropertyNode::Root(),
+      .Chunk(transform.get(), ClipPaintPropertyNode::Root(),
              EffectPaintPropertyNode::Root())
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
   // The second chunk can merge into the first because it has a descendant
   // state of the first's transform and no direct compositing reason.
   test_artifact
-      .Chunk(transform2.Get(), ClipPaintPropertyNode::Root(),
+      .Chunk(transform2.get(), ClipPaintPropertyNode::Root(),
              EffectPaintPropertyNode::Root())
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
 
@@ -1313,7 +1335,7 @@
   }
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, MergeTransformOrigin) {
+TEST_F(PaintArtifactCompositorTest, MergeTransformOrigin) {
   RefPtr<TransformPaintPropertyNode> transform =
       TransformPaintPropertyNode::Create(TransformPaintPropertyNode::Root(),
                                          TransformationMatrix().Rotate(45),
@@ -1325,7 +1347,7 @@
              EffectPaintPropertyNode::Root())
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
   test_artifact
-      .Chunk(transform.Get(), ClipPaintPropertyNode::Root(),
+      .Chunk(transform.get(), ClipPaintPropertyNode::Root(),
              EffectPaintPropertyNode::Root())
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
   test_artifact
@@ -1345,7 +1367,7 @@
     rects_with_color.push_back(RectWithColor(
         FloatRect(29.2893, 0.578644, 141.421, 141.421), Color::kBlack));
     rects_with_color.push_back(
-        RectWithColor(FloatRect(00, 42, 200, 300), Color::kGray));
+        RectWithColor(FloatRect(0, 42, 200, 300), Color::kGray));
 
     const cc::Layer* layer = ContentLayerAt(0);
     EXPECT_THAT(layer->GetPicture(),
@@ -1353,7 +1375,7 @@
   }
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, MergeOpacity) {
+TEST_F(PaintArtifactCompositorTest, MergeOpacity) {
   float opacity = 2.0 / 255.0;
   RefPtr<EffectPaintPropertyNode> effect =
       CreateOpacityOnlyEffect(EffectPaintPropertyNode::Root(), opacity);
@@ -1365,7 +1387,7 @@
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
   test_artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
-             effect.Get())
+             effect.get())
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
   test_artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
@@ -1393,7 +1415,7 @@
   }
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, MergeNested) {
+TEST_F(PaintArtifactCompositorTest, MergeNested) {
   // Tests merging of an opacity effect, inside of a clip, inside of a
   // transform.
 
@@ -1404,12 +1426,12 @@
           false, 0);
 
   RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::Create(
-      ClipPaintPropertyNode::Root(), transform.Get(),
+      ClipPaintPropertyNode::Root(), transform.get(),
       FloatRoundedRect(10, 20, 50, 60));
 
   float opacity = 2.0 / 255.0;
   RefPtr<EffectPaintPropertyNode> effect = EffectPaintPropertyNode::Create(
-      EffectPaintPropertyNode::Root(), transform.Get(), clip.Get(),
+      EffectPaintPropertyNode::Root(), transform.get(), clip.get(),
       kColorFilterNone, CompositorFilterOperations(), opacity,
       SkBlendMode::kSrcOver);
 
@@ -1418,7 +1440,7 @@
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
              EffectPaintPropertyNode::Root())
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
-  test_artifact.Chunk(transform.Get(), clip.Get(), effect.Get())
+  test_artifact.Chunk(transform.get(), clip.get(), effect.get())
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
   test_artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
@@ -1446,7 +1468,7 @@
   }
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, ClipPushedUp) {
+TEST_F(PaintArtifactCompositorTest, ClipPushedUp) {
   // Tests merging of an element which has a clipapplied to it,
   // but has an ancestor transform of them. This can happen for fixed-
   // or absolute-position elements which escape scroll transforms.
@@ -1459,11 +1481,11 @@
 
   RefPtr<TransformPaintPropertyNode> transform2 =
       TransformPaintPropertyNode::Create(
-          transform.Get(), TransformationMatrix().Translate(20, 25),
+          transform.get(), TransformationMatrix().Translate(20, 25),
           FloatPoint3D(100, 100, 0), false, 0);
 
   RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::Create(
-      ClipPaintPropertyNode::Root(), transform2.Get(),
+      ClipPaintPropertyNode::Root(), transform2.get(),
       FloatRoundedRect(10, 20, 50, 60));
 
   TestPaintArtifact test_artifact;
@@ -1472,7 +1494,7 @@
              EffectPaintPropertyNode::Root())
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
   test_artifact
-      .Chunk(TransformPaintPropertyNode::Root(), clip.Get(),
+      .Chunk(TransformPaintPropertyNode::Root(), clip.get(),
              EffectPaintPropertyNode::Root())
       .RectDrawing(FloatRect(0, 0, 300, 400), Color::kBlack);
   test_artifact
@@ -1504,7 +1526,7 @@
 // TODO(crbug.com/696842): The effect refuses to "decomposite" because it's in
 // a deeper transform space than its chunk. We should allow decomposite if
 // the two transform nodes share the same direct compositing ancestor.
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, EffectPushedUp_DISABLED) {
+TEST_F(PaintArtifactCompositorTest, EffectPushedUp_DISABLED) {
   // Tests merging of an element which has an effect applied to it,
   // but has an ancestor transform of them. This can happen for fixed-
   // or absolute-position elements which escape scroll transforms.
@@ -1517,12 +1539,12 @@
 
   RefPtr<TransformPaintPropertyNode> transform2 =
       TransformPaintPropertyNode::Create(
-          transform.Get(), TransformationMatrix().Translate(20, 25),
+          transform.get(), TransformationMatrix().Translate(20, 25),
           FloatPoint3D(100, 100, 0), false, 0);
 
   float opacity = 2.0 / 255.0;
   RefPtr<EffectPaintPropertyNode> effect = EffectPaintPropertyNode::Create(
-      EffectPaintPropertyNode::Root(), transform2.Get(),
+      EffectPaintPropertyNode::Root(), transform2.get(),
       ClipPaintPropertyNode::Root(), kColorFilterNone,
       CompositorFilterOperations(), opacity, SkBlendMode::kSrcOver);
 
@@ -1533,7 +1555,7 @@
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
   test_artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
-             effect.Get())
+             effect.get())
       .RectDrawing(FloatRect(0, 0, 300, 400), Color::kBlack);
   test_artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
@@ -1563,8 +1585,7 @@
 // TODO(crbug.com/696842): The effect refuses to "decomposite" because it's in
 // a deeper transform space than its chunk. We should allow decomposite if
 // the two transform nodes share the same direct compositing ancestor.
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       EffectAndClipPushedUp_DISABLED) {
+TEST_F(PaintArtifactCompositorTest, EffectAndClipPushedUp_DISABLED) {
   // Tests merging of an element which has an effect applied to it,
   // but has an ancestor transform of them. This can happen for fixed-
   // or absolute-position elements which escape scroll transforms.
@@ -1577,16 +1598,16 @@
 
   RefPtr<TransformPaintPropertyNode> transform2 =
       TransformPaintPropertyNode::Create(
-          transform.Get(), TransformationMatrix().Translate(20, 25),
+          transform.get(), TransformationMatrix().Translate(20, 25),
           FloatPoint3D(100, 100, 0), false, 0);
 
   RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::Create(
-      ClipPaintPropertyNode::Root(), transform.Get(),
+      ClipPaintPropertyNode::Root(), transform.get(),
       FloatRoundedRect(10, 20, 50, 60));
 
   float opacity = 2.0 / 255.0;
   RefPtr<EffectPaintPropertyNode> effect = EffectPaintPropertyNode::Create(
-      EffectPaintPropertyNode::Root(), transform2.Get(), clip.Get(),
+      EffectPaintPropertyNode::Root(), transform2.get(), clip.get(),
       kColorFilterNone, CompositorFilterOperations(), opacity,
       SkBlendMode::kSrcOver);
 
@@ -1596,7 +1617,7 @@
              EffectPaintPropertyNode::Root())
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
   test_artifact
-      .Chunk(TransformPaintPropertyNode::Root(), clip.Get(), effect.Get())
+      .Chunk(TransformPaintPropertyNode::Root(), clip.get(), effect.get())
       .RectDrawing(FloatRect(0, 0, 300, 400), Color::kBlack);
   test_artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
@@ -1625,7 +1646,7 @@
   }
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, ClipAndEffectNoTransform) {
+TEST_F(PaintArtifactCompositorTest, ClipAndEffectNoTransform) {
   // Tests merging of an element which has a clip and effect in the root
   // transform space.
 
@@ -1636,7 +1657,7 @@
   float opacity = 2.0 / 255.0;
   RefPtr<EffectPaintPropertyNode> effect = EffectPaintPropertyNode::Create(
       EffectPaintPropertyNode::Root(), TransformPaintPropertyNode::Root(),
-      clip.Get(), kColorFilterNone, CompositorFilterOperations(), opacity,
+      clip.get(), kColorFilterNone, CompositorFilterOperations(), opacity,
       SkBlendMode::kSrcOver);
 
   TestPaintArtifact test_artifact;
@@ -1645,7 +1666,7 @@
              EffectPaintPropertyNode::Root())
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
   test_artifact
-      .Chunk(TransformPaintPropertyNode::Root(), clip.Get(), effect.Get())
+      .Chunk(TransformPaintPropertyNode::Root(), clip.get(), effect.get())
       .RectDrawing(FloatRect(0, 0, 300, 400), Color::kBlack);
   test_artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
@@ -1672,7 +1693,7 @@
   }
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, TwoClips) {
+TEST_F(PaintArtifactCompositorTest, TwoClips) {
   // Tests merging of an element which has two clips in the root
   // transform space.
 
@@ -1681,7 +1702,7 @@
       FloatRoundedRect(20, 30, 10, 20));
 
   RefPtr<ClipPaintPropertyNode> clip2 = ClipPaintPropertyNode::Create(
-      clip.Get(), TransformPaintPropertyNode::Root(),
+      clip.get(), TransformPaintPropertyNode::Root(),
       FloatRoundedRect(10, 20, 50, 60));
 
   TestPaintArtifact test_artifact;
@@ -1690,7 +1711,7 @@
              EffectPaintPropertyNode::Root())
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
   test_artifact
-      .Chunk(TransformPaintPropertyNode::Root(), clip2.Get(),
+      .Chunk(TransformPaintPropertyNode::Root(), clip2.get(),
              EffectPaintPropertyNode::Root())
       .RectDrawing(FloatRect(0, 0, 300, 400), Color::kBlack);
   test_artifact
@@ -1718,7 +1739,7 @@
   }
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, TwoTransformsClipBetween) {
+TEST_F(PaintArtifactCompositorTest, TwoTransformsClipBetween) {
   RefPtr<TransformPaintPropertyNode> transform =
       TransformPaintPropertyNode::Create(
           TransformPaintPropertyNode::Root(),
@@ -1729,7 +1750,7 @@
       FloatRoundedRect(0, 0, 50, 60));
   RefPtr<TransformPaintPropertyNode> transform2 =
       TransformPaintPropertyNode::Create(
-          transform.Get(), TransformationMatrix().Translate(20, 25),
+          transform.get(), TransformationMatrix().Translate(20, 25),
           FloatPoint3D(100, 100, 0), false, 0);
   TestPaintArtifact test_artifact;
   test_artifact
@@ -1737,7 +1758,7 @@
              EffectPaintPropertyNode::Root())
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
   test_artifact
-      .Chunk(transform2.Get(), clip.Get(), EffectPaintPropertyNode::Root())
+      .Chunk(transform2.get(), clip.get(), EffectPaintPropertyNode::Root())
       .RectDrawing(FloatRect(0, 0, 300, 400), Color::kBlack);
   test_artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
@@ -1762,7 +1783,7 @@
   }
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, OverlapTransform) {
+TEST_F(PaintArtifactCompositorTest, OverlapTransform) {
   RefPtr<TransformPaintPropertyNode> transform =
       TransformPaintPropertyNode::Create(
           TransformPaintPropertyNode::Root(),
@@ -1773,7 +1794,7 @@
   test_artifact.Chunk(DefaultPaintChunkProperties())
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
   test_artifact
-      .Chunk(transform.Get(), ClipPaintPropertyNode::Root(),
+      .Chunk(transform.get(), ClipPaintPropertyNode::Root(),
              EffectPaintPropertyNode::Root())
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
   test_artifact.Chunk(DefaultPaintChunkProperties())
@@ -1788,7 +1809,7 @@
   ASSERT_EQ(3u, ContentLayerCount());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, MightOverlap) {
+TEST_F(PaintArtifactCompositorTest, MightOverlap) {
   PaintChunk paint_chunk = DefaultChunk();
   paint_chunk.bounds = FloatRect(0, 0, 100, 100);
   PendingLayer pending_layer(paint_chunk, false);
@@ -1807,7 +1828,7 @@
           TransformationMatrix().Translate(99, 0), FloatPoint3D(100, 100, 0),
           false);
   {
-    paint_chunk2.properties.property_tree_state.SetTransform(transform.Get());
+    paint_chunk2.properties.property_tree_state.SetTransform(transform.get());
     PendingLayer pending_layer2(paint_chunk2, false);
     EXPECT_TRUE(MightOverlap(pending_layer, pending_layer2));
   }
@@ -1818,13 +1839,13 @@
           TransformationMatrix().Translate(100, 0), FloatPoint3D(100, 100, 0),
           false);
   {
-    paint_chunk2.properties.property_tree_state.SetTransform(transform2.Get());
+    paint_chunk2.properties.property_tree_state.SetTransform(transform2.get());
     PendingLayer pending_layer2(paint_chunk2, false);
     EXPECT_FALSE(MightOverlap(pending_layer, pending_layer2));
   }
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, PendingLayer) {
+TEST_F(PaintArtifactCompositorTest, PendingLayer) {
   PaintChunk chunk1 = DefaultChunk();
   chunk1.properties.property_tree_state = PropertyTreeState(
       TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
@@ -1836,8 +1857,8 @@
   PendingLayer pending_layer(chunk1, false);
 
   EXPECT_TRUE(pending_layer.backface_hidden);
-  EXPECT_TRUE(pending_layer.known_to_be_opaque);
   EXPECT_EQ(FloatRect(0, 0, 30, 40), pending_layer.bounds);
+  EXPECT_EQ(pending_layer.bounds, pending_layer.rect_known_to_be_opaque);
 
   PaintChunk chunk2 = DefaultChunk();
   chunk2.properties.property_tree_state = chunk1.properties.property_tree_state;
@@ -1848,8 +1869,8 @@
 
   EXPECT_TRUE(pending_layer.backface_hidden);
   // Bounds not equal to one PaintChunk.
-  EXPECT_FALSE(pending_layer.known_to_be_opaque);
   EXPECT_EQ(FloatRect(0, 0, 40, 60), pending_layer.bounds);
+  EXPECT_NE(pending_layer.bounds, pending_layer.rect_known_to_be_opaque);
 
   PaintChunk chunk3 = DefaultChunk();
   chunk3.properties.property_tree_state = chunk1.properties.property_tree_state;
@@ -1859,11 +1880,11 @@
   pending_layer.Merge(PendingLayer(chunk3, false));
 
   EXPECT_TRUE(pending_layer.backface_hidden);
-  EXPECT_FALSE(pending_layer.known_to_be_opaque);
   EXPECT_EQ(FloatRect(-5, -25, 45, 85), pending_layer.bounds);
+  EXPECT_NE(pending_layer.bounds, pending_layer.rect_known_to_be_opaque);
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, PendingLayerWithGeometry) {
+TEST_F(PaintArtifactCompositorTest, PendingLayerWithGeometry) {
   RefPtr<TransformPaintPropertyNode> transform =
       TransformPaintPropertyNode::Create(
           TransformPaintPropertyNode::Root(),
@@ -1891,8 +1912,7 @@
 
 // TODO(crbug.com/701991):
 // The test is disabled because opaque rect mapping is not implemented yet.
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       PendingLayerKnownOpaque_DISABLED) {
+TEST_F(PaintArtifactCompositorTest, PendingLayerKnownOpaque_DISABLED) {
   PaintChunk chunk1 = DefaultChunk();
   chunk1.properties.property_tree_state = PropertyTreeState(
       TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
@@ -1901,7 +1921,7 @@
   chunk1.known_to_be_opaque = false;
   PendingLayer pending_layer(chunk1, false);
 
-  EXPECT_FALSE(pending_layer.known_to_be_opaque);
+  EXPECT_TRUE(pending_layer.rect_known_to_be_opaque.IsEmpty());
 
   PaintChunk chunk2 = DefaultChunk();
   chunk2.properties.property_tree_state = chunk1.properties.property_tree_state;
@@ -1910,7 +1930,8 @@
   pending_layer.Merge(PendingLayer(chunk2, false));
 
   // Chunk 2 doesn't cover the entire layer, so not opaque.
-  EXPECT_FALSE(pending_layer.known_to_be_opaque);
+  EXPECT_EQ(chunk2.bounds, pending_layer.rect_known_to_be_opaque);
+  EXPECT_NE(pending_layer.bounds, pending_layer.rect_known_to_be_opaque);
 
   PaintChunk chunk3 = DefaultChunk();
   chunk3.properties.property_tree_state = chunk1.properties.property_tree_state;
@@ -1919,7 +1940,8 @@
   pending_layer.Merge(PendingLayer(chunk3, false));
 
   // Chunk 3 covers the entire layer, so now it's opaque.
-  EXPECT_TRUE(pending_layer.known_to_be_opaque);
+  EXPECT_EQ(chunk3.bounds, pending_layer.bounds);
+  EXPECT_EQ(pending_layer.bounds, pending_layer.rect_known_to_be_opaque);
 }
 
 RefPtr<EffectPaintPropertyNode> CreateSampleEffectNodeWithElementId() {
@@ -1940,7 +1962,7 @@
       expected_compositor_element_id);
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, TransformWithElementId) {
+TEST_F(PaintArtifactCompositorTest, TransformWithElementId) {
   RefPtr<TransformPaintPropertyNode> transform =
       CreateSampleTransformNodeWithElementId();
   TestPaintArtifact artifact;
@@ -1954,20 +1976,20 @@
             ElementIdToTransformNodeIndex(transform->GetCompositorElementId()));
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, EffectWithElementId) {
+TEST_F(PaintArtifactCompositorTest, EffectWithElementId) {
   RefPtr<EffectPaintPropertyNode> effect =
       CreateSampleEffectNodeWithElementId();
   TestPaintArtifact artifact;
   artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
-             effect.Get())
+             effect.get())
       .RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack);
   Update(artifact.Build());
 
   EXPECT_EQ(2, ElementIdToEffectNodeIndex(effect->GetCompositorElementId()));
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, CompositedLuminanceMask) {
+TEST_F(PaintArtifactCompositorTest, CompositedLuminanceMask) {
   RefPtr<EffectPaintPropertyNode> masked = EffectPaintPropertyNode::Create(
       EffectPaintPropertyNode::Root(), TransformPaintPropertyNode::Root(),
       ClipPaintPropertyNode::Root(), kColorFilterNone,
@@ -1981,11 +2003,11 @@
   TestPaintArtifact artifact;
   artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
-             masked.Get())
+             masked.get())
       .RectDrawing(FloatRect(100, 100, 200, 200), Color::kGray);
   artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
-             masking.Get())
+             masking.get())
       .RectDrawing(FloatRect(150, 150, 100, 100), Color::kWhite);
   Update(artifact.Build());
   ASSERT_EQ(2u, ContentLayerCount());
@@ -2014,8 +2036,7 @@
             masking_group->filters.at(0).type());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       UpdateProducesNewSequenceNumber) {
+TEST_F(PaintArtifactCompositorTest, UpdateProducesNewSequenceNumber) {
   // A 90 degree clockwise rotation about (100, 100).
   RefPtr<TransformPaintPropertyNode> transform =
       TransformPaintPropertyNode::Create(
@@ -2066,7 +2087,7 @@
   }
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, DecompositeClip) {
+TEST_F(PaintArtifactCompositorTest, DecompositeClip) {
   // A clipped paint chunk that gets merged into a previous layer should
   // only contribute clipped bounds to the layer bound.
 
@@ -2080,7 +2101,7 @@
              EffectPaintPropertyNode::Root())
       .RectDrawing(FloatRect(50, 50, 100, 100), Color::kGray);
   artifact
-      .Chunk(TransformPaintPropertyNode::Root(), clip.Get(),
+      .Chunk(TransformPaintPropertyNode::Root(), clip.get(),
              EffectPaintPropertyNode::Root())
       .RectDrawing(FloatRect(100, 100, 100, 100), Color::kGray);
   Update(artifact.Build());
@@ -2091,7 +2112,7 @@
   EXPECT_EQ(gfx::Size(125, 125), layer->bounds());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, DecompositeEffect) {
+TEST_F(PaintArtifactCompositorTest, DecompositeEffect) {
   // An effect node without direct compositing reason and does not need to
   // group compositing descendants should not be composited and can merge
   // with other chunks.
@@ -2106,7 +2127,7 @@
       .RectDrawing(FloatRect(50, 25, 100, 100), Color::kGray);
   artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
-             effect.Get())
+             effect.get())
       .RectDrawing(FloatRect(25, 75, 100, 100), Color::kGray);
   artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
@@ -2121,7 +2142,7 @@
   EXPECT_EQ(1, layer->effect_tree_index());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, DirectlyCompositedEffect) {
+TEST_F(PaintArtifactCompositorTest, DirectlyCompositedEffect) {
   // An effect node with direct compositing shall be composited.
   RefPtr<EffectPaintPropertyNode> effect = EffectPaintPropertyNode::Create(
       EffectPaintPropertyNode::Root(), TransformPaintPropertyNode::Root(),
@@ -2136,7 +2157,7 @@
       .RectDrawing(FloatRect(50, 25, 100, 100), Color::kGray);
   artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
-             effect.Get())
+             effect.get())
       .RectDrawing(FloatRect(25, 75, 100, 100), Color::kGray);
   artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
@@ -2164,7 +2185,7 @@
   EXPECT_EQ(1, layer3->effect_tree_index());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, DecompositeDeepEffect) {
+TEST_F(PaintArtifactCompositorTest, DecompositeDeepEffect) {
   // A paint chunk may enter multiple level effects with or without compositing
   // reasons. This test verifies we still decomposite effects without a direct
   // reason, but stop at a directly composited effect.
@@ -2185,7 +2206,7 @@
       .RectDrawing(FloatRect(50, 25, 100, 100), Color::kGray);
   artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
-             effect3.Get())
+             effect3.get())
       .RectDrawing(FloatRect(25, 75, 100, 100), Color::kGray);
   artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
@@ -2216,8 +2237,7 @@
   EXPECT_EQ(1, layer3->effect_tree_index());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       IndirectlyCompositedEffect) {
+TEST_F(PaintArtifactCompositorTest, IndirectlyCompositedEffect) {
   // An effect node without direct compositing still needs to be composited
   // for grouping, if some chunks need to be composited.
   RefPtr<EffectPaintPropertyNode> effect =
@@ -2234,9 +2254,9 @@
       .RectDrawing(FloatRect(50, 25, 100, 100), Color::kGray);
   artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
-             effect.Get())
+             effect.get())
       .RectDrawing(FloatRect(25, 75, 100, 100), Color::kGray);
-  artifact.Chunk(transform.Get(), ClipPaintPropertyNode::Root(), effect.Get())
+  artifact.Chunk(transform.get(), ClipPaintPropertyNode::Root(), effect.get())
       .RectDrawing(FloatRect(75, 75, 100, 100), Color::kGray);
   Update(artifact.Build());
   ASSERT_EQ(3u, ContentLayerCount());
@@ -2260,8 +2280,7 @@
   EXPECT_EQ(effect_node->id, layer3->effect_tree_index());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       DecompositedEffectNotMergingDueToOverlap) {
+TEST_F(PaintArtifactCompositorTest, DecompositedEffectNotMergingDueToOverlap) {
   // This tests an effect that doesn't need to be composited, but needs
   // separate backing due to overlap with a previous composited effect.
   RefPtr<EffectPaintPropertyNode> effect1 =
@@ -2279,22 +2298,22 @@
       .RectDrawing(FloatRect(0, 0, 50, 50), Color::kGray);
   artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
-             effect1.Get())
+             effect1.get())
       .RectDrawing(FloatRect(100, 0, 50, 50), Color::kGray);
   // This chunk has a transform that must be composited, thus causing effect1
   // to be composited too.
-  artifact.Chunk(transform.Get(), ClipPaintPropertyNode::Root(), effect1.Get())
+  artifact.Chunk(transform.get(), ClipPaintPropertyNode::Root(), effect1.get())
       .RectDrawing(FloatRect(200, 0, 50, 50), Color::kGray);
   artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
-             effect2.Get())
+             effect2.get())
       .RectDrawing(FloatRect(200, 100, 50, 50), Color::kGray);
   // This chunk overlaps with the 2nd chunk, but is seemingly safe to merge.
   // However because effect1 gets composited due to a composited transform,
   // we can't merge with effect1 nor skip it to merge with the first chunk.
   artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
-             effect2.Get())
+             effect2.get())
       .RectDrawing(FloatRect(100, 0, 50, 50), Color::kGray);
 
   Update(artifact.Build());
@@ -2324,8 +2343,7 @@
   EXPECT_EQ(1, layer4->effect_tree_index());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       UpdatePopulatesCompositedElementIds) {
+TEST_F(PaintArtifactCompositorTest, UpdatePopulatesCompositedElementIds) {
   RefPtr<TransformPaintPropertyNode> transform =
       CreateSampleTransformNodeWithElementId();
   RefPtr<EffectPaintPropertyNode> effect =
@@ -2336,7 +2354,7 @@
              EffectPaintPropertyNode::Root())
       .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack)
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
-             effect.Get())
+             effect.get())
       .RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack);
 
   CompositorElementIdSet composited_element_ids;
@@ -2349,7 +2367,7 @@
       composited_element_ids.Contains(effect->GetCompositorElementId()));
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, SkipChunkWithOpacityZero) {
+TEST_F(PaintArtifactCompositorTest, SkipChunkWithOpacityZero) {
   {
     TestPaintArtifact artifact;
     CreateSimpleArtifactWithOpacity(artifact, 0, false, false);
@@ -2372,7 +2390,7 @@
   }
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, SkipChunkWithTinyOpacity) {
+TEST_F(PaintArtifactCompositorTest, SkipChunkWithTinyOpacity) {
   {
     TestPaintArtifact artifact;
     CreateSimpleArtifactWithOpacity(artifact, 0.0003f, false, false);
@@ -2395,8 +2413,7 @@
   }
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       DontSkipChunkWithMinimumOpacity) {
+TEST_F(PaintArtifactCompositorTest, DontSkipChunkWithMinimumOpacity) {
   {
     TestPaintArtifact artifact;
     CreateSimpleArtifactWithOpacity(artifact, 0.0004f, false, false);
@@ -2419,8 +2436,7 @@
   }
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       DontSkipChunkWithAboveMinimumOpacity) {
+TEST_F(PaintArtifactCompositorTest, DontSkipChunkWithAboveMinimumOpacity) {
   {
     TestPaintArtifact artifact;
     CreateSimpleArtifactWithOpacity(artifact, 0.3f, false, false);
@@ -2454,7 +2470,7 @@
       SkBlendMode::kSrcOver, reason);
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
+TEST_F(PaintArtifactCompositorTest,
        DontSkipChunkWithTinyOpacityAndDirectCompositingReason) {
   RefPtr<EffectPaintPropertyNode> effect =
       CreateEffectWithOpacityAndReason(0.0001f, kCompositingReasonCanvas);
@@ -2467,7 +2483,7 @@
   ASSERT_EQ(1u, ContentLayerCount());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
+TEST_F(PaintArtifactCompositorTest,
        SkipChunkWithTinyOpacityAndVisibleChildEffectNode) {
   RefPtr<EffectPaintPropertyNode> tinyEffect =
       CreateEffectWithOpacityAndReason(0.0001f, kCompositingReasonNone);
@@ -2484,7 +2500,7 @@
 }
 
 TEST_F(
-    PaintArtifactCompositorTestWithPropertyTrees,
+    PaintArtifactCompositorTest,
     DontSkipChunkWithTinyOpacityAndVisibleChildEffectNodeWithCompositingParent) {
   RefPtr<EffectPaintPropertyNode> tinyEffect =
       CreateEffectWithOpacityAndReason(0.0001f, kCompositingReasonCanvas);
@@ -2500,7 +2516,7 @@
   ASSERT_EQ(1u, ContentLayerCount());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
+TEST_F(PaintArtifactCompositorTest,
        SkipChunkWithTinyOpacityAndVisibleChildEffectNodeWithCompositingChild) {
   RefPtr<EffectPaintPropertyNode> tinyEffect =
       CreateEffectWithOpacityAndReason(0.0001f, kCompositingReasonNone);
@@ -2516,8 +2532,7 @@
   ASSERT_EQ(0u, ContentLayerCount());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       UpdateManagesLayerElementIds) {
+TEST_F(PaintArtifactCompositorTest, UpdateManagesLayerElementIds) {
   RefPtr<TransformPaintPropertyNode> transform =
       CreateSampleTransformNodeWithElementId();
   CompositorElementId element_id = transform->GetCompositorElementId();
@@ -2543,7 +2558,7 @@
   }
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, SynthesizedClipSimple) {
+TEST_F(PaintArtifactCompositorTest, SynthesizedClipSimple) {
   // This tests the simplist case that a single layer needs to be clipped
   // by a single composited rounded clip.
   FloatSize corner(5, 5);
@@ -2594,8 +2609,7 @@
   EXPECT_EQ(SkBlendMode::kDstIn, mask_effect_0.blend_mode);
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       SynthesizedClipContiguous) {
+TEST_F(PaintArtifactCompositorTest, SynthesizedClipContiguous) {
   // This tests the case that a two back-to-back composited layers having
   // the same composited rounded clip can share the synthesized mask.
   RefPtr<TransformPaintPropertyNode> t1 = TransformPaintPropertyNode::Create(
@@ -2664,8 +2678,7 @@
   EXPECT_EQ(SkBlendMode::kDstIn, mask_effect_0.blend_mode);
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       SynthesizedClipDiscontiguous) {
+TEST_F(PaintArtifactCompositorTest, SynthesizedClipDiscontiguous) {
   // This tests the case that a two composited layers having the same
   // composited rounded clip cannot share the synthesized mask if there is
   // another layer in the middle.
@@ -2759,8 +2772,7 @@
   EXPECT_EQ(SkBlendMode::kDstIn, mask_effect_1.blend_mode);
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       SynthesizedClipAcrossChildEffect) {
+TEST_F(PaintArtifactCompositorTest, SynthesizedClipAcrossChildEffect) {
   // This tests the case that an effect having the same output clip as the
   // layers before and after it can share the synthesized mask.
   FloatSize corner(5, 5);
@@ -2831,8 +2843,7 @@
   EXPECT_EQ(SkBlendMode::kDstIn, mask_effect_0.blend_mode);
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       SynthesizedClipRespectOutputClip) {
+TEST_F(PaintArtifactCompositorTest, SynthesizedClipRespectOutputClip) {
   // This tests the case that a layer cannot share the synthesized mask despite
   // having the same composited rounded clip if it's enclosed by an effect not
   // clipped by the common clip.
@@ -2938,8 +2949,7 @@
   EXPECT_EQ(SkBlendMode::kDstIn, mask_effect_2.blend_mode);
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       SynthesizedClipDelegateBlending) {
+TEST_F(PaintArtifactCompositorTest, SynthesizedClipDelegateBlending) {
   // This tests the case that an effect with exotic blending cannot share
   // the synthesized mask with its siblings because its blending has to be
   // applied by the outermost mask.
@@ -3043,13 +3053,13 @@
   EXPECT_EQ(SkBlendMode::kDstIn, mask_effect_2.blend_mode);
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, WillBeRemovedFromFrame) {
+TEST_F(PaintArtifactCompositorTest, WillBeRemovedFromFrame) {
   RefPtr<EffectPaintPropertyNode> effect =
       CreateSampleEffectNodeWithElementId();
   TestPaintArtifact artifact;
   artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
-             effect.Get())
+             effect.get())
       .RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack);
   Update(artifact.Build());
 
@@ -3060,7 +3070,7 @@
   EXPECT_EQ(0u, ContentLayerCount());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, ContentsNonOpaque) {
+TEST_F(PaintArtifactCompositorTest, ContentsNonOpaque) {
   TestPaintArtifact artifact;
   artifact.Chunk(DefaultPaintChunkProperties())
       .RectDrawing(FloatRect(100, 100, 200, 200), Color::kBlack);
@@ -3069,7 +3079,7 @@
   EXPECT_FALSE(ContentLayerAt(0)->contents_opaque());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, ContentsOpaque) {
+TEST_F(PaintArtifactCompositorTest, ContentsOpaque) {
   TestPaintArtifact artifact;
   artifact.Chunk(DefaultPaintChunkProperties())
       .RectDrawing(FloatRect(100, 100, 200, 200), Color::kBlack)
@@ -3079,7 +3089,7 @@
   EXPECT_TRUE(ContentLayerAt(0)->contents_opaque());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees, ContentsOpaqueSubpixel) {
+TEST_F(PaintArtifactCompositorTest, ContentsOpaqueSubpixel) {
   TestPaintArtifact artifact;
   artifact.Chunk(DefaultPaintChunkProperties())
       .RectDrawing(FloatRect(100.5, 100.5, 200, 200), Color::kBlack)
@@ -3090,8 +3100,7 @@
   EXPECT_FALSE(ContentLayerAt(0)->contents_opaque());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       ContentsOpaqueUnitedNonOpaque) {
+TEST_F(PaintArtifactCompositorTest, ContentsOpaqueUnitedNonOpaque) {
   TestPaintArtifact artifact;
   artifact.Chunk(DefaultPaintChunkProperties())
       .RectDrawing(FloatRect(100, 100, 200, 200), Color::kBlack)
@@ -3105,8 +3114,7 @@
   EXPECT_FALSE(ContentLayerAt(0)->contents_opaque());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       ContentsOpaqueUnitedOpaque1) {
+TEST_F(PaintArtifactCompositorTest, ContentsOpaqueUnitedOpaque1) {
   TestPaintArtifact artifact;
   artifact.Chunk(DefaultPaintChunkProperties())
       .RectDrawing(FloatRect(100, 100, 300, 300), Color::kBlack)
@@ -3120,8 +3128,7 @@
   EXPECT_TRUE(ContentLayerAt(0)->contents_opaque());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       ContentsOpaqueUnitedOpaque2) {
+TEST_F(PaintArtifactCompositorTest, ContentsOpaqueUnitedOpaque2) {
   TestPaintArtifact artifact;
   artifact.Chunk(DefaultPaintChunkProperties())
       .RectDrawing(FloatRect(100, 100, 200, 200), Color::kBlack)
@@ -3137,8 +3144,7 @@
   EXPECT_FALSE(ContentLayerAt(0)->contents_opaque());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       DecompositeEffectWithNoOutputClip) {
+TEST_F(PaintArtifactCompositorTest, DecompositeEffectWithNoOutputClip) {
   // This test verifies effect nodes with no output clip correctly decomposites
   // if there is no compositing reasons.
   RefPtr<ClipPaintPropertyNode> clip1 = ClipPaintPropertyNode::Create(
@@ -3153,7 +3159,7 @@
   TestPaintArtifact artifact;
   artifact.Chunk(DefaultPaintChunkProperties())
       .RectDrawing(FloatRect(50, 50, 100, 100), Color::kGray);
-  artifact.Chunk(TransformPaintPropertyNode::Root(), clip1.Get(), effect1.Get())
+  artifact.Chunk(TransformPaintPropertyNode::Root(), clip1.get(), effect1.get())
       .RectDrawing(FloatRect(100, 100, 100, 100), Color::kGray);
   Update(artifact.Build());
   ASSERT_EQ(1u, ContentLayerCount());
@@ -3164,8 +3170,7 @@
   EXPECT_EQ(1, layer->effect_tree_index());
 }
 
-TEST_F(PaintArtifactCompositorTestWithPropertyTrees,
-       CompositedEffectWithNoOutputClip) {
+TEST_F(PaintArtifactCompositorTest, CompositedEffectWithNoOutputClip) {
   // This test verifies effect nodes with no output clip but has compositing
   // reason correctly squash children chunks and assign clip node.
   RefPtr<ClipPaintPropertyNode> clip1 = ClipPaintPropertyNode::Create(
@@ -3180,9 +3185,9 @@
   TestPaintArtifact artifact;
   artifact
       .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
-             effect1.Get())
+             effect1.get())
       .RectDrawing(FloatRect(50, 50, 100, 100), Color::kGray);
-  artifact.Chunk(TransformPaintPropertyNode::Root(), clip1.Get(), effect1.Get())
+  artifact.Chunk(TransformPaintPropertyNode::Root(), clip1.get(), effect1.get())
       .RectDrawing(FloatRect(100, 100, 100, 100), Color::kGray);
   Update(artifact.Build());
   ASSERT_EQ(1u, ContentLayerCount());
@@ -3194,4 +3199,66 @@
   EXPECT_EQ(2, layer->effect_tree_index());
 }
 
+TEST_F(PaintArtifactCompositorTest, LayerRasterInvalidationWithClip) {
+  // The layer's painting is initially not lipped.
+  auto clip = ClipPaintPropertyNode::Create(ClipPaintPropertyNode::Root(),
+                                            TransformPaintPropertyNode::Root(),
+                                            FloatRoundedRect(10, 20, 300, 400));
+  TestPaintArtifact artifact1;
+  artifact1
+      .Chunk(TransformPaintPropertyNode::Root(), clip,
+             EffectPaintPropertyNode::Root())
+      .RectDrawing(FloatRect(50, 50, 200, 200), Color::kBlack);
+  Update(artifact1.Build());
+  ASSERT_EQ(1u, ContentLayerCount());
+
+  auto* layer = ContentLayerAt(0);
+  EXPECT_EQ(gfx::Vector2dF(50, 50), layer->offset_to_transform_parent());
+  EXPECT_EQ(gfx::Size(200, 200), layer->bounds());
+  EXPECT_THAT(
+      layer->GetPicture(),
+      Pointee(DrawsRectangle(FloatRect(0, 0, 200, 200), Color::kBlack)));
+
+  // The layer's painting overflows the left, top, right edges of the clip .
+  TestPaintArtifact artifact2;
+  artifact2
+      .Chunk(artifact1.Client(0), TransformPaintPropertyNode::Root(), clip,
+             EffectPaintPropertyNode::Root())
+      .RectDrawing(artifact1.Client(1), FloatRect(0, 0, 400, 200),
+                   Color::kBlack);
+  layer->ResetNeedsDisplayForTesting();
+  Update(artifact2.Build());
+  ASSERT_EQ(1u, ContentLayerCount());
+  ASSERT_EQ(layer, ContentLayerAt(0));
+
+  // We invalidate the whole layer because it's origin changed.
+  EXPECT_EQ(gfx::Rect(0, 0, 300, 180), layer->update_rect());
+  EXPECT_EQ(gfx::Vector2dF(10, 20), layer->offset_to_transform_parent());
+  EXPECT_EQ(gfx::Size(300, 180), layer->bounds());
+  EXPECT_THAT(
+      layer->GetPicture(),
+      Pointee(DrawsRectangle(FloatRect(0, 0, 390, 180), Color::kBlack)));
+
+  // The layer's painting overflows all edges of the clip.
+  TestPaintArtifact artifact3;
+  artifact3
+      .Chunk(artifact1.Client(0), TransformPaintPropertyNode::Root(), clip,
+             EffectPaintPropertyNode::Root())
+      .RectDrawing(artifact1.Client(1), FloatRect(-100, -200, 500, 800),
+                   Color::kBlack);
+  layer->ResetNeedsDisplayForTesting();
+  Update(artifact3.Build());
+  ASSERT_EQ(1u, ContentLayerCount());
+  ASSERT_EQ(layer, ContentLayerAt(0));
+
+  // We should not invalidate the layer because the origin didn't change
+  // because of the clip.
+  EXPECT_EQ(gfx::Rect(), layer->update_rect());
+  EXPECT_EQ(gfx::Vector2dF(10, 20), layer->offset_to_transform_parent());
+  EXPECT_EQ(gfx::Size(300, 400), layer->bounds());
+  EXPECT_THAT(
+      layer->GetPicture(),
+      Pointee(DrawsRectangle(FloatRect(0, 0, 390, 580), Color::kBlack)));
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayerTest.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayerTest.cpp
index de0f8ab..33852d8 100644
--- a/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayerTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayerTest.cpp
@@ -164,8 +164,8 @@
   // This test verifies effects are applied as a group.
   RefPtr<EffectPaintPropertyNode> e1 = CreateOpacityOnlyEffect(e0(), 0.5f);
   TestChunks chunks;
-  chunks.AddChunk(t0(), c0(), e1.Get());
-  chunks.AddChunk(t0(), c0(), e1.Get());
+  chunks.AddChunk(t0(), c0(), e1.get());
+  chunks.AddChunk(t0(), c0(), e1.get());
 
   sk_sp<PaintRecord> output =
       PaintChunksToCcLayer::Convert(
@@ -185,11 +185,11 @@
 TEST_F(PaintChunksToCcLayerTest, EffectGroupingNested) {
   // This test verifies nested effects are grouped properly.
   RefPtr<EffectPaintPropertyNode> e1 = CreateOpacityOnlyEffect(e0(), 0.5f);
-  RefPtr<EffectPaintPropertyNode> e2 = CreateOpacityOnlyEffect(e1.Get(), 0.5f);
-  RefPtr<EffectPaintPropertyNode> e3 = CreateOpacityOnlyEffect(e1.Get(), 0.5f);
+  RefPtr<EffectPaintPropertyNode> e2 = CreateOpacityOnlyEffect(e1.get(), 0.5f);
+  RefPtr<EffectPaintPropertyNode> e3 = CreateOpacityOnlyEffect(e1.get(), 0.5f);
   TestChunks chunks;
-  chunks.AddChunk(t0(), c0(), e2.Get());
-  chunks.AddChunk(t0(), c0(), e3.Get());
+  chunks.AddChunk(t0(), c0(), e2.get());
+  chunks.AddChunk(t0(), c0(), e3.get());
 
   sk_sp<PaintRecord> output =
       PaintChunksToCcLayer::Convert(
@@ -219,22 +219,22 @@
   RefPtr<ClipPaintPropertyNode> c1 = ClipPaintPropertyNode::Create(
       c0(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
   RefPtr<ClipPaintPropertyNode> c2 = ClipPaintPropertyNode::Create(
-      c1.Get(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+      c1.get(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
   RefPtr<ClipPaintPropertyNode> c3 = ClipPaintPropertyNode::Create(
-      c2.Get(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+      c2.get(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
   RefPtr<ClipPaintPropertyNode> c4 = ClipPaintPropertyNode::Create(
-      c3.Get(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+      c3.get(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
   RefPtr<EffectPaintPropertyNode> e1 = EffectPaintPropertyNode::Create(
-      e0(), t0(), c2.Get(), ColorFilter(), CompositorFilterOperations(), 0.5f,
+      e0(), t0(), c2.get(), ColorFilter(), CompositorFilterOperations(), 0.5f,
       SkBlendMode::kSrcOver);
   RefPtr<EffectPaintPropertyNode> e2 = EffectPaintPropertyNode::Create(
-      e1.Get(), t0(), c4.Get(), ColorFilter(), CompositorFilterOperations(),
+      e1.get(), t0(), c4.get(), ColorFilter(), CompositorFilterOperations(),
       0.5f, SkBlendMode::kSrcOver);
   TestChunks chunks;
-  chunks.AddChunk(t0(), c3.Get(), e0());
-  chunks.AddChunk(t0(), c4.Get(), e2.Get());
-  chunks.AddChunk(t0(), c3.Get(), e1.Get());
-  chunks.AddChunk(t0(), c4.Get(), e0());
+  chunks.AddChunk(t0(), c3.get(), e0());
+  chunks.AddChunk(t0(), c4.get(), e2.get());
+  chunks.AddChunk(t0(), c3.get(), e1.get());
+  chunks.AddChunk(t0(), c4.get(), e0());
 
   sk_sp<PaintRecord> output =
       PaintChunksToCcLayer::Convert(
@@ -278,9 +278,9 @@
   RefPtr<TransformPaintPropertyNode> t1 = TransformPaintPropertyNode::Create(
       t0(), TransformationMatrix().Scale(2.f), FloatPoint3D());
   RefPtr<ClipPaintPropertyNode> c1 = ClipPaintPropertyNode::Create(
-      c0(), t1.Get(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+      c0(), t1.get(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
   TestChunks chunks;
-  chunks.AddChunk(t0(), c1.Get(), e0());
+  chunks.AddChunk(t0(), c1.get(), e0());
 
   sk_sp<PaintRecord> output =
       PaintChunksToCcLayer::Convert(
@@ -310,10 +310,10 @@
   RefPtr<TransformPaintPropertyNode> t1 = TransformPaintPropertyNode::Create(
       t0(), TransformationMatrix().Scale(2.f), FloatPoint3D());
   RefPtr<EffectPaintPropertyNode> e1 = EffectPaintPropertyNode::Create(
-      e0(), t1.Get(), c0(), ColorFilter(), CompositorFilterOperations(), 0.5f,
+      e0(), t1.get(), c0(), ColorFilter(), CompositorFilterOperations(), 0.5f,
       SkBlendMode::kSrcOver);
   TestChunks chunks;
-  chunks.AddChunk(t0(), c0(), e1.Get());
+  chunks.AddChunk(t0(), c0(), e1.get());
 
   sk_sp<PaintRecord> output =
       PaintChunksToCcLayer::Convert(
@@ -341,12 +341,12 @@
       c0(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
   RefPtr<EffectPaintPropertyNode> e1 = CreateOpacityOnlyEffect(e0(), 0.5f);
   TestChunks chunks;
-  chunks.AddChunk(t1.Get(), c1.Get(), e1.Get());
+  chunks.AddChunk(t1.get(), c1.get(), e1.get());
 
   sk_sp<PaintRecord> output =
       PaintChunksToCcLayer::Convert(
           chunks.GetChunkList(),
-          PropertyTreeState(t1.Get(), c1.Get(), e1.Get()), gfx::Vector2dF(),
+          PropertyTreeState(t1.get(), c1.get(), e1.get()), gfx::Vector2dF(),
           chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
           ->ReleaseAsRecord();
   EXPECT_THAT(output,
@@ -362,12 +362,12 @@
       c0(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
   RefPtr<EffectPaintPropertyNode> e1 = CreateOpacityOnlyEffect(e0(), 0.5f);
   TestChunks chunks;
-  chunks.AddChunk(t0(), c1.Get(), e1.Get());
+  chunks.AddChunk(t0(), c1.get(), e1.get());
 
   sk_sp<PaintRecord> output =
       PaintChunksToCcLayer::Convert(
           chunks.GetChunkList(),
-          PropertyTreeState(t1.Get(), c1.Get(), e1.Get()), gfx::Vector2dF(),
+          PropertyTreeState(t1.get(), c1.get(), e1.get()), gfx::Vector2dF(),
           chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
           ->ReleaseAsRecord();
   EXPECT_THAT(output,
@@ -382,17 +382,17 @@
   RefPtr<ClipPaintPropertyNode> c1 = ClipPaintPropertyNode::Create(
       c0(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
   RefPtr<ClipPaintPropertyNode> c2 = ClipPaintPropertyNode::Create(
-      c1.Get(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+      c1.get(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
   RefPtr<EffectPaintPropertyNode> e1 = EffectPaintPropertyNode::Create(
       e0(), t0(), nullptr, kColorFilterNone, CompositorFilterOperations(), 0.5,
       SkBlendMode::kSrcOver);
 
   TestChunks chunks;
-  chunks.AddChunk(t0(), c2.Get(), e1.Get());
+  chunks.AddChunk(t0(), c2.get(), e1.get());
 
   sk_sp<PaintRecord> output =
       PaintChunksToCcLayer::Convert(
-          chunks.GetChunkList(), PropertyTreeState(t0(), c1.Get(), e0()),
+          chunks.GetChunkList(), PropertyTreeState(t0(), c1.get(), e0()),
           gfx::Vector2dF(), chunks.items,
           cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
           ->ReleaseAsRecord();
@@ -414,11 +414,11 @@
       e0(), t0(), c0(), kColorFilterNone, CompositorFilterOperations(), 0.5,
       SkBlendMode::kSrcOver);
   RefPtr<EffectPaintPropertyNode> e2 = EffectPaintPropertyNode::Create(
-      e1.Get(), t0(), nullptr, kColorFilterNone, CompositorFilterOperations(),
+      e1.get(), t0(), nullptr, kColorFilterNone, CompositorFilterOperations(),
       0.5, SkBlendMode::kSrcOver);
 
   TestChunks chunks;
-  chunks.AddChunk(t0(), c1.Get(), e2.Get());
+  chunks.AddChunk(t0(), c1.get(), e2.get());
 
   sk_sp<PaintRecord> output =
       PaintChunksToCcLayer::Convert(
@@ -446,15 +446,15 @@
       e0(), t0(), c0(), kColorFilterNone, CompositorFilterOperations(), 0.5,
       SkBlendMode::kSrcOver);
   RefPtr<EffectPaintPropertyNode> e2 = EffectPaintPropertyNode::Create(
-      e1.Get(), t0(), nullptr, kColorFilterNone, CompositorFilterOperations(),
+      e1.get(), t0(), nullptr, kColorFilterNone, CompositorFilterOperations(),
       0.5, SkBlendMode::kSrcOver);
 
   TestChunks chunks;
-  chunks.AddChunk(t0(), c1.Get(), e2.Get());
+  chunks.AddChunk(t0(), c1.get(), e2.get());
 
   sk_sp<PaintRecord> output =
       PaintChunksToCcLayer::Convert(
-          chunks.GetChunkList(), PropertyTreeState(t0(), c0(), e1.Get()),
+          chunks.GetChunkList(), PropertyTreeState(t0(), c0(), e1.get()),
           gfx::Vector2dF(), chunks.items,
           cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
           ->ReleaseAsRecord();
@@ -476,15 +476,15 @@
       e0(), t0(), c0(), kColorFilterNone, CompositorFilterOperations(), 0.5,
       SkBlendMode::kSrcOver);
   RefPtr<EffectPaintPropertyNode> e2 = EffectPaintPropertyNode::Create(
-      e1.Get(), t0(), nullptr, kColorFilterNone, CompositorFilterOperations(),
+      e1.get(), t0(), nullptr, kColorFilterNone, CompositorFilterOperations(),
       0.5, SkBlendMode::kSrcOver);
 
   TestChunks chunks;
-  chunks.AddChunk(t0(), c1.Get(), e2.Get());
+  chunks.AddChunk(t0(), c1.get(), e2.get());
 
   sk_sp<PaintRecord> output =
       PaintChunksToCcLayer::Convert(
-          chunks.GetChunkList(), PropertyTreeState(t0(), c1.Get(), e1.Get()),
+          chunks.GetChunkList(), PropertyTreeState(t0(), c1.get(), e1.get()),
           gfx::Vector2dF(), chunks.items,
           cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
           ->ReleaseAsRecord();
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PropertyTreeManager.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PropertyTreeManager.cpp
index 1a0fc53..23a29c2 100644
--- a/third_party/WebKit/Source/platform/graphics/compositing/PropertyTreeManager.cpp
+++ b/third_party/WebKit/Source/platform/graphics/compositing/PropertyTreeManager.cpp
@@ -255,8 +255,8 @@
   cc::ScrollNode& compositor_node = *GetScrollTree().Node(id);
   compositor_node.scrollable = true;
 
-  compositor_node.container_bounds = scroll_node->ContainerBounds();
-  compositor_node.bounds = scroll_node->Bounds();
+  compositor_node.container_bounds = scroll_node->ContainerRect().Size();
+  compositor_node.bounds = scroll_node->ContentsRect().Size();
   compositor_node.user_scrollable_horizontal =
       scroll_node->UserScrollableHorizontal();
   compositor_node.user_scrollable_vertical =
diff --git a/third_party/WebKit/Source/platform/graphics/filters/FEDiffuseLighting.cpp b/third_party/WebKit/Source/platform/graphics/filters/FEDiffuseLighting.cpp
index 3362062..683608df3 100644
--- a/third_party/WebKit/Source/platform/graphics/filters/FEDiffuseLighting.cpp
+++ b/third_party/WebKit/Source/platform/graphics/filters/FEDiffuseLighting.cpp
@@ -87,7 +87,7 @@
 }
 
 const LightSource* FEDiffuseLighting::GetLightSource() const {
-  return light_source_.Get();
+  return light_source_.get();
 }
 
 void FEDiffuseLighting::SetLightSource(RefPtr<LightSource> light_source) {
diff --git a/third_party/WebKit/Source/platform/graphics/filters/FELighting.cpp b/third_party/WebKit/Source/platform/graphics/filters/FELighting.cpp
index 8411dfc..5ed49c8 100644
--- a/third_party/WebKit/Source/platform/graphics/filters/FELighting.cpp
+++ b/third_party/WebKit/Source/platform/graphics/filters/FELighting.cpp
@@ -64,7 +64,7 @@
   switch (light_source_->GetType()) {
     case LS_DISTANT: {
       DistantLightSource* distant_light_source =
-          static_cast<DistantLightSource*>(light_source_.Get());
+          static_cast<DistantLightSource*>(light_source_.get());
       float azimuth_rad = deg2rad(distant_light_source->Azimuth());
       float elevation_rad = deg2rad(distant_light_source->Elevation());
       const SkPoint3 direction = SkPoint3::Make(
@@ -80,7 +80,7 @@
     }
     case LS_POINT: {
       PointLightSource* point_light_source =
-          static_cast<PointLightSource*>(light_source_.Get());
+          static_cast<PointLightSource*>(light_source_.get());
       const FloatPoint3D position = point_light_source->GetPosition();
       const SkPoint3 sk_position =
           SkPoint3::Make(position.X(), position.Y(), position.Z());
@@ -94,7 +94,7 @@
     }
     case LS_SPOT: {
       SpotLightSource* spot_light_source =
-          static_cast<SpotLightSource*>(light_source_.Get());
+          static_cast<SpotLightSource*>(light_source_.get());
       const SkPoint3 location =
           SkPoint3::Make(spot_light_source->GetPosition().X(),
                          spot_light_source->GetPosition().Y(),
diff --git a/third_party/WebKit/Source/platform/graphics/filters/FESpecularLighting.cpp b/third_party/WebKit/Source/platform/graphics/filters/FESpecularLighting.cpp
index 4c53449..4982984 100644
--- a/third_party/WebKit/Source/platform/graphics/filters/FESpecularLighting.cpp
+++ b/third_party/WebKit/Source/platform/graphics/filters/FESpecularLighting.cpp
@@ -105,7 +105,7 @@
 }
 
 const LightSource* FESpecularLighting::GetLightSource() const {
-  return light_source_.Get();
+  return light_source_.get();
 }
 
 void FESpecularLighting::SetLightSource(RefPtr<LightSource> light_source) {
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
index d437208..3d8a25c4 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
@@ -396,7 +396,19 @@
 #if defined(OS_MACOSX)
     gl_->DescheduleUntilFinishedCHROMIUM();
 #endif
-    gl_->Flush();
+    // It's critical to order the execution of this context's work relative
+    // to other contexts, in particular the compositor. Previously this
+    // used to be a Flush, and there was a bug that we didn't flush before
+    // InsertFenceSyncCHROMIUM, above. On some platforms this caused
+    // incorrect rendering with complex WebGL content that wasn't always
+    // properly flushed to the driver. There is now a basic assumption that
+    // there are implicit flushes between contexts at the lowest level.
+    //
+    // Note also that theoretically this should be ShallowFlushCHROMIUM,
+    // but as we are moving toward using unverified sync tokens everywhere,
+    // and this code is working, we would rather not incur two synchronous
+    // IPCs here (which that would imply).
+    gl_->OrderingBarrierCHROMIUM();
     gl_->GenSyncTokenCHROMIUM(
         fence_sync, color_buffer_for_mailbox->produce_sync_token.GetData());
   }
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp
index fe6cb11..cade020 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp
@@ -246,7 +246,7 @@
   drawing_buffer_->BeginDestruction();
   ASSERT_EQ(live, true);
 
-  DrawingBufferForTests* raw_pointer = drawing_buffer_.Get();
+  DrawingBufferForTests* raw_pointer = drawing_buffer_.get();
   drawing_buffer_ = nullptr;
   ASSERT_EQ(live, true);
 
@@ -294,7 +294,7 @@
   release_callback2->Run(gpu::SyncToken(), false /* lostResource */);
   EXPECT_EQ(live, true);
 
-  DrawingBufferForTests* raw_ptr = drawing_buffer_.Get();
+  DrawingBufferForTests* raw_ptr = drawing_buffer_.get();
   drawing_buffer_ = nullptr;
   EXPECT_EQ(live, true);
 
diff --git a/third_party/WebKit/Source/platform/graphics/paint/ClipPaintPropertyNode.cpp b/third_party/WebKit/Source/platform/graphics/paint/ClipPaintPropertyNode.cpp
index 6bb26a7..874535a 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/ClipPaintPropertyNode.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/ClipPaintPropertyNode.cpp
@@ -22,7 +22,7 @@
   if (Parent())
     json->SetString("parent", String::Format("%p", Parent()));
   json->SetString("localTransformSpace",
-                  String::Format("%p", local_transform_space_.Get()));
+                  String::Format("%p", local_transform_space_.get()));
   json->SetString("rect", clip_rect_.ToString());
   if (direct_compositing_reasons_ != kCompositingReasonNone) {
     json->SetString("directCompositingReasons",
diff --git a/third_party/WebKit/Source/platform/graphics/paint/ClipPaintPropertyNode.h b/third_party/WebKit/Source/platform/graphics/paint/ClipPaintPropertyNode.h
index a0ccce4..3859e5a 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/ClipPaintPropertyNode.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/ClipPaintPropertyNode.h
@@ -57,7 +57,7 @@
   }
 
   const TransformPaintPropertyNode* LocalTransformSpace() const {
-    return local_transform_space_.Get();
+    return local_transform_space_.get();
   }
   const FloatRoundedRect& ClipRect() const { return clip_rect_; }
 
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemClient.h b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemClient.h
index 0ad29a5..44e18441 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemClient.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemClient.h
@@ -47,6 +47,14 @@
     return LayoutUnit();
   }
 
+  // The rect that needs to be invalidated partially in this client. It's in the
+  // same coordinate space as VisualRect().
+  virtual LayoutRect PartialInvalidationRect() const { return LayoutRect(); }
+
+  // Called by PaintController::CommitNewDisplayItems() for all clients after
+  // painting.
+  virtual void ClearPartialInvalidationRect() const {}
+
   // This is declared here instead of in LayoutObject for verifying the
   // condition in DrawingRecorder.
   // Returns true if the object itself will not generate any effective painted
diff --git a/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.cpp b/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.cpp
index a85fa28..7ac69844 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.cpp
@@ -31,8 +31,8 @@
   if (Parent())
     json->SetString("parent", String::Format("%p", Parent()));
   json->SetString("localTransformSpace",
-                  String::Format("%p", local_transform_space_.Get()));
-  json->SetString("outputClip", String::Format("%p", output_clip_.Get()));
+                  String::Format("%p", local_transform_space_.get()));
+  json->SetString("outputClip", String::Format("%p", output_clip_.get()));
   if (color_filter_ != kColorFilterNone)
     json->SetInteger("colorFilter", color_filter_);
   if (!filter_.IsEmpty())
diff --git a/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h b/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h
index d60342d3..baecaad 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h
@@ -83,9 +83,9 @@
   }
 
   const TransformPaintPropertyNode* LocalTransformSpace() const {
-    return local_transform_space_.Get();
+    return local_transform_space_.get();
   }
-  const ClipPaintPropertyNode* OutputClip() const { return output_clip_.Get(); }
+  const ClipPaintPropertyNode* OutputClip() const { return output_clip_.get(); }
 
   SkBlendMode BlendMode() const { return blend_mode_; }
   float Opacity() const { return opacity_; }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp
index 584f55f53..65da5136 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp
@@ -146,7 +146,7 @@
                                          TransformationMatrix(),
                                          FloatPoint3D());
   PropertyTreeState local_state = PropertyTreeState::Root();
-  local_state.SetTransform(transform.Get());
+  local_state.SetTransform(transform.get());
 
   FloatRect input(0, 0, 100, 100);
 
@@ -162,7 +162,7 @@
       TransformPaintPropertyNode::Create(TransformPaintPropertyNode::Root(),
                                          transform_matrix, FloatPoint3D());
   PropertyTreeState local_state = PropertyTreeState::Root();
-  local_state.SetTransform(transform.Get());
+  local_state.SetTransform(transform.get());
 
   FloatRect input(0, 0, 100, 100);
   FloatRect output = transform_matrix.MapRect(input);
@@ -185,7 +185,7 @@
                                          transform_matrix,
                                          FloatPoint3D(0, 0, 0));
   PropertyTreeState local_state = PropertyTreeState::Root();
-  local_state.SetTransform(transform.Get());
+  local_state.SetTransform(transform.get());
 
   FloatRect input(0, 0, 100, 100);
   FloatRect output = transform_matrix.MapRect(input);
@@ -204,7 +204,7 @@
                                          transform_matrix,
                                          FloatPoint3D(50, 50, 0));
   PropertyTreeState local_state = PropertyTreeState::Root();
-  local_state.SetTransform(transform.Get());
+  local_state.SetTransform(transform.get());
 
   FloatRect input(0, 0, 100, 100);
   transform_matrix.ApplyTransformOrigin(50, 50, 0);
@@ -229,7 +229,7 @@
                                          FloatPoint3D());
 
   PropertyTreeState local_state = PropertyTreeState::Root();
-  local_state.SetTransform(transform2.Get());
+  local_state.SetTransform(transform2.get());
 
   FloatRect input(0, 0, 100, 100);
   TransformationMatrix final = rotate_transform * scale_transform;
@@ -255,7 +255,7 @@
                                          true);  // Flattens
 
   PropertyTreeState local_state = PropertyTreeState::Root();
-  local_state.SetTransform(transform2.Get());
+  local_state.SetTransform(transform2.get());
 
   FloatRect input(0, 0, 100, 100);
   rotate_transform.FlattenTo2d();
@@ -281,7 +281,7 @@
                                          FloatPoint3D());
 
   PropertyTreeState local_state = PropertyTreeState::Root();
-  local_state.SetTransform(transform2.Get());
+  local_state.SetTransform(transform2.get());
 
   FloatRect input(0, 0, 100, 100);
   // Note: unlike NestedTransforms, the order of these transforms matters. This
@@ -308,10 +308,10 @@
                                          FloatPoint3D());
 
   PropertyTreeState local_state = PropertyTreeState::Root();
-  local_state.SetTransform(transform2.Get());
+  local_state.SetTransform(transform2.get());
 
   PropertyTreeState intermediate_state = PropertyTreeState::Root();
-  intermediate_state.SetTransform(transform1.Get());
+  intermediate_state.SetTransform(transform1.get());
 
   FloatRect input(0, 0, 100, 100);
   FloatRect output = scale_transform.MapRect(input);
@@ -327,7 +327,7 @@
       FloatRoundedRect(10, 10, 50, 50));
 
   PropertyTreeState local_state = PropertyTreeState::Root();
-  local_state.SetClip(clip.Get());
+  local_state.SetClip(clip.get());
 
   FloatRect input(0, 0, 100, 100);
   FloatRect output(10, 10, 50, 50);
@@ -351,7 +351,7 @@
       ClipPaintPropertyNode::Root(), TransformPaintPropertyNode::Root(), rect);
 
   PropertyTreeState local_state = PropertyTreeState::Root();
-  local_state.SetClip(clip.Get());
+  local_state.SetClip(clip.get());
 
   FloatRect input(0, 0, 100, 100);
   FloatRect output(10, 10, 50, 50);
@@ -385,7 +385,7 @@
 
   PropertyTreeState local_state = PropertyTreeState::Root();
   PropertyTreeState ancestor_state = PropertyTreeState::Root();
-  local_state.SetClip(clip2.Get());
+  local_state.SetClip(clip2.get());
 
   FloatRect input(0, 0, 100, 100);
   FloatRect output1(10, 10, 30, 40);
@@ -402,7 +402,7 @@
                  clip_rect,       // Clip rect in ancestor space
                  local_state, ancestor_state);
 
-  ancestor_state.SetClip(clip1.Get());
+  ancestor_state.SetClip(clip1.get());
   FloatRect output2(10, 10, 50, 50);
 
   FloatClipRect clip_rect2;
@@ -430,14 +430,14 @@
                               FloatSize()));
 
   RefPtr<ClipPaintPropertyNode> clip1 = ClipPaintPropertyNode::Create(
-      ClipPaintPropertyNode::Root(), transform.Get(), clip_rect1);
+      ClipPaintPropertyNode::Root(), transform.get(), clip_rect1);
 
   RefPtr<ClipPaintPropertyNode> clip2 = ClipPaintPropertyNode::Create(
-      clip1, transform.Get(), FloatRoundedRect(10, 10, 30, 40));
+      clip1, transform.get(), FloatRoundedRect(10, 10, 30, 40));
 
   PropertyTreeState local_state = PropertyTreeState::Root();
   PropertyTreeState ancestor_state = PropertyTreeState::Root();
-  local_state.SetClip(clip2.Get());
+  local_state.SetClip(clip2.get());
 
   FloatRect input(0, 0, 100, 100);
   FloatRect output1(10, 10, 30, 40);
@@ -455,7 +455,7 @@
                  local_state, ancestor_state);
 
   expected_clip.SetRect(clip1->ClipRect().Rect());
-  local_state.SetClip(clip1.Get());
+  local_state.SetClip(clip1.get());
   FloatRect output2(10, 10, 50, 50);
   CHECK_MAPPINGS(input,    // Input
                  output2,  // Visual rect
@@ -474,12 +474,12 @@
                                          rotate_transform, FloatPoint3D());
 
   RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::Create(
-      ClipPaintPropertyNode::Root(), transform.Get(),
+      ClipPaintPropertyNode::Root(), transform.get(),
       FloatRoundedRect(10, 10, 50, 50));
 
   PropertyTreeState local_state = PropertyTreeState::Root();
-  local_state.SetClip(clip.Get());
-  local_state.SetTransform(transform.Get());
+  local_state.SetClip(clip.get());
+  local_state.SetTransform(transform.get());
 
   FloatRect input(0, 0, 100, 100);
   FloatRect output(input);
@@ -509,8 +509,8 @@
       FloatRoundedRect(10, 10, 200, 200));
 
   PropertyTreeState local_state = PropertyTreeState::Root();
-  local_state.SetClip(clip.Get());
-  local_state.SetTransform(transform.Get());
+  local_state.SetClip(clip.get());
+  local_state.SetTransform(transform.get());
 
   FloatRect input(0, 0, 100, 100);
   FloatRect output(input);
@@ -539,15 +539,15 @@
                                          rotate_transform, FloatPoint3D());
 
   RefPtr<ClipPaintPropertyNode> clip2 = ClipPaintPropertyNode::Create(
-      clip1, transform.Get(), FloatRoundedRect(10, 10, 200, 200));
+      clip1, transform.get(), FloatRoundedRect(10, 10, 200, 200));
 
   FloatRect input(0, 0, 100, 100);
 
   bool has_radius = false;
   {
     PropertyTreeState local_state = PropertyTreeState::Root();
-    local_state.SetClip(clip1.Get());
-    local_state.SetTransform(transform.Get());
+    local_state.SetClip(clip1.get());
+    local_state.SetTransform(transform.get());
 
     FloatRect output(input);
     output = rotate_transform.MapRect(output);
@@ -564,8 +564,8 @@
 
   {
     PropertyTreeState local_state = PropertyTreeState::Root();
-    local_state.SetClip(clip2.Get());
-    local_state.SetTransform(transform.Get());
+    local_state.SetClip(clip2.get());
+    local_state.SetTransform(transform.get());
 
     FloatRect mapped_clip = rotate_transform.MapRect(clip2->ClipRect().Rect());
     mapped_clip.Intersect(clip1->ClipRect().Rect());
@@ -605,9 +605,9 @@
                                          rotate_transform2, FloatPoint3D());
 
   PropertyTreeState transform1_state = PropertyTreeState::Root();
-  transform1_state.SetTransform(transform1.Get());
+  transform1_state.SetTransform(transform1.get());
   PropertyTreeState transform2_state = PropertyTreeState::Root();
-  transform2_state.SetTransform(transform2.Get());
+  transform2_state.SetTransform(transform2.get());
 
   FloatRect input(0, 0, 100, 100);
   FloatClipRect result_clip(input);
@@ -616,7 +616,7 @@
   EXPECT_FLOAT_RECT_NEAR(FloatRect(-100, 0, 100, 100), result_clip.Rect());
 
   FloatRect result = input;
-  GeometryMapper::SourceToDestinationRect(transform1.Get(), transform2.Get(),
+  GeometryMapper::SourceToDestinationRect(transform1.get(), transform2.get(),
                                           result);
   EXPECT_FLOAT_RECT_NEAR(FloatRect(-100, 0, 100, 100), result);
 
@@ -626,7 +626,7 @@
   EXPECT_FLOAT_RECT_NEAR(FloatRect(0, -100, 100, 100), result_clip.Rect());
 
   result = input;
-  GeometryMapper::SourceToDestinationRect(transform2.Get(), transform1.Get(),
+  GeometryMapper::SourceToDestinationRect(transform2.get(), transform1.get(),
                                           result);
   EXPECT_FLOAT_RECT_NEAR(FloatRect(0, -100, 100, 100), result);
 }
@@ -647,14 +647,14 @@
                                          rotate_transform2, FloatPoint3D());
 
   RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::Create(
-      ClipPaintPropertyNode::Root(), transform2.Get(),
+      ClipPaintPropertyNode::Root(), transform2.get(),
       FloatRoundedRect(10, 20, 30, 40));
 
   PropertyTreeState transform1_state = PropertyTreeState::Root();
-  transform1_state.SetTransform(transform1.Get());
+  transform1_state.SetTransform(transform1.get());
   PropertyTreeState transform2_and_clip_state = PropertyTreeState::Root();
-  transform2_and_clip_state.SetTransform(transform2.Get());
-  transform2_and_clip_state.SetClip(clip.Get());
+  transform2_and_clip_state.SetTransform(transform2.get());
+  transform2_and_clip_state.SetClip(clip.get());
 
   bool success;
   FloatRect input(0, 0, 100, 100);
@@ -703,8 +703,8 @@
       EffectPaintPropertyNode::Root(), transform_above_effect,
       clip_above_effect, kColorFilterNone, filters, 1.0, SkBlendMode::kSrcOver);
 
-  PropertyTreeState local_state(transform_below_effect.Get(),
-                                clip_below_effect.Get(), effect.Get());
+  PropertyTreeState local_state(transform_below_effect.get(),
+                                clip_below_effect.get(), effect.get());
 
   FloatRect input(0, 0, 50, 50);
   // 1. transformBelowEffect
@@ -760,7 +760,7 @@
       ClipPaintPropertyNode::Root(), TransformPaintPropertyNode::Root(),
       FloatRoundedRect(10, 10, 50, 50));
 
-  PropertyTreeState dest(TransformPaintPropertyNode::Root(), clip.Get(),
+  PropertyTreeState dest(TransformPaintPropertyNode::Root(), clip.get(),
                          EffectPaintPropertyNode::Root());
 
   FloatClipRect floatClipRect(FloatRect(0, 0, 10, 200));
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintChunkerTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintChunkerTest.cpp
index ed72634..e870b07c 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintChunkerTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintChunkerTest.cpp
@@ -96,7 +96,7 @@
       TransformPaintPropertyNode::Create(nullptr,
                                          TransformationMatrix(0, 1, 2, 3, 4, 5),
                                          FloatPoint3D(9, 8, 7))
-          .Get());
+          .get());
 
   PaintChunk::Id id2(client_, DisplayItemType(2));
   chunker.UpdateCurrentPaintChunkProperties(&id2, simple_transform);
@@ -107,7 +107,7 @@
       TransformPaintPropertyNode::Create(nullptr,
                                          TransformationMatrix(0, 1, 2, 3, 4, 5),
                                          FloatPoint3D(9, 8, 7))
-          .Get());
+          .get());
   PaintChunk::Id id3(client_, DisplayItemType(3));
   chunker.UpdateCurrentPaintChunkProperties(&id3, another_transform);
   chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
@@ -132,7 +132,7 @@
       TransformPaintPropertyNode::Create(nullptr,
                                          TransformationMatrix(0, 0, 0, 0, 0, 0),
                                          FloatPoint3D(9, 8, 7))
-          .Get());
+          .get());
   PaintChunk::Id id2(client_, DisplayItemType(2));
   chunker.UpdateCurrentPaintChunkProperties(&id2, simple_transform);
   chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
@@ -143,7 +143,7 @@
   simple_transform_and_effect.property_tree_state.SetTransform(
       simple_transform.property_tree_state.Transform());
   simple_transform_and_effect.property_tree_state.SetEffect(
-      CreateOpacityOnlyEffect(EffectPaintPropertyNode::Root(), 0.5f).Get());
+      CreateOpacityOnlyEffect(EffectPaintPropertyNode::Root(), 0.5f).get());
   PaintChunk::Id id3(client_, DisplayItemType(3));
   chunker.UpdateCurrentPaintChunkProperties(&id3, simple_transform_and_effect);
   chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
@@ -155,13 +155,13 @@
       .SetTransform(TransformPaintPropertyNode::Create(
                         nullptr, TransformationMatrix(1, 1, 0, 0, 0, 0),
                         FloatPoint3D(9, 8, 7))
-                        .Get());
+                        .get());
   simple_transform_and_effect_with_updated_transform.property_tree_state
       .SetEffect(CreateOpacityOnlyEffect(
                      EffectPaintPropertyNode::Root(),
                      simple_transform_and_effect.property_tree_state.Effect()
                          ->Opacity())
-                     .Get());
+                     .get());
   PaintChunk::Id id4(client_, DisplayItemType(4));
   chunker.UpdateCurrentPaintChunkProperties(
       &id4, simple_transform_and_effect_with_updated_transform);
@@ -211,7 +211,7 @@
       TransformPaintPropertyNode::Create(nullptr,
                                          TransformationMatrix(0, 1, 2, 3, 4, 5),
                                          FloatPoint3D(9, 8, 7))
-          .Get());
+          .get());
   PaintChunk::Id id2(client_, DisplayItemType(2));
   chunker.UpdateCurrentPaintChunkProperties(&id2, simple_transform);
   chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
@@ -244,7 +244,7 @@
       TransformPaintPropertyNode::Create(nullptr,
                                          TransformationMatrix(0, 1, 2, 3, 4, 5),
                                          FloatPoint3D(9, 8, 7))
-          .Get());
+          .get());
   PaintChunk::Id id2(client_, DisplayItemType(2));
   chunker.UpdateCurrentPaintChunkProperties(nullptr, first_transform);
 
@@ -253,7 +253,7 @@
       TransformPaintPropertyNode::Create(nullptr,
                                          TransformationMatrix(9, 8, 7, 6, 5, 4),
                                          FloatPoint3D(3, 2, 1))
-          .Get());
+          .get());
   PaintChunk::Id id3(client_, DisplayItemType(3));
   chunker.UpdateCurrentPaintChunkProperties(&id3, second_transform);
 
@@ -380,7 +380,7 @@
       TransformPaintPropertyNode::Create(nullptr,
                                          TransformationMatrix(0, 1, 2, 3, 4, 5),
                                          FloatPoint3D(9, 8, 7))
-          .Get());
+          .get());
   PaintChunk::Id id2(client_, DisplayItemType(2));
   chunker.UpdateCurrentPaintChunkProperties(&id2, simple_transform);
 
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
index 7fd0812..28d0297 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
@@ -4,6 +4,7 @@
 
 #include "platform/graphics/paint/PaintController.h"
 
+#include <memory>
 #include "platform/graphics/GraphicsLayer.h"
 #include "platform/graphics/paint/DrawingDisplayItem.h"
 #include "platform/instrumentation/tracing/TraceEvent.h"
@@ -20,7 +21,7 @@
 void PaintController::SetTracksRasterInvalidations(bool value) {
   if (value) {
     raster_invalidation_tracking_info_ =
-        WTF::MakeUnique<RasterInvalidationTrackingInfo>();
+        std::make_unique<RasterInvalidationTrackingInfo>();
 
     // This is called just after a full document cycle update, so all clients in
     // current_paint_artifact_ should be still alive.
@@ -41,7 +42,7 @@
   if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() &&
       !raster_invalidation_tracking_info_) {
     raster_invalidation_tracking_info_ =
-        WTF::MakeUnique<RasterInvalidationTrackingInfo>();
+        std::make_unique<RasterInvalidationTrackingInfo>();
   }
 }
 
@@ -606,6 +607,9 @@
 
   Vector<const DisplayItemClient*> skipped_cache_clients;
   for (const auto& item : new_display_item_list_) {
+    if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
+      item.Client().ClearPartialInvalidationRect();
+
     if (item.IsCacheable()) {
       item.Client().SetDisplayItemsCached(current_cache_generation_);
     } else {
@@ -880,13 +884,21 @@
     return;
   }
 
-  if (client.GetPaintInvalidationReason() ==
-      PaintInvalidationReason::kIncremental) {
-    GenerateIncrementalRasterInvalidation(chunk, *old_item, *new_item);
+  if (client.GetPaintInvalidationReason() !=
+          PaintInvalidationReason::kRectangle &&
+      client.GetPaintInvalidationReason() !=
+          PaintInvalidationReason::kIncremental) {
+    GenerateFullRasterInvalidation(chunk, *old_item, *new_item);
     return;
   }
 
-  GenerateFullRasterInvalidation(chunk, *old_item, *new_item);
+  GenerateIncrementalRasterInvalidation(chunk, *old_item, *new_item);
+
+  auto partial_rect = client.PartialInvalidationRect();
+  if (!partial_rect.IsEmpty()) {
+    AddRasterInvalidation(client, chunk, FloatRect(partial_rect),
+                          PaintInvalidationReason::kRectangle);
+  }
 }
 
 static FloatRect ComputeRightDelta(const FloatPoint& location,
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
index c72bdf4..9aa872e8 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
@@ -538,7 +538,7 @@
   LayoutRect initial_rect(100, 100, 100, 100);
   std::unique_ptr<FakeDisplayItemClient> clients[6];
   for (auto& client : clients)
-    client = WTF::MakeUnique<FakeDisplayItemClient>("", initial_rect);
+    client = std::make_unique<FakeDisplayItemClient>("", initial_rect);
   GraphicsContext context(GetPaintController());
 
   GetPaintController().UpdateCurrentPaintChunkProperties(
@@ -761,7 +761,7 @@
     if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
       PaintChunk::Id id(first, kClipType);
       PaintChunkProperties properties = DefaultPaintChunkProperties();
-      properties.property_tree_state.SetClip(clip.Get());
+      properties.property_tree_state.SetClip(clip.get());
       GetPaintController().UpdateCurrentPaintChunkProperties(&id, properties);
     }
     ClipRecorder clip_recorder(context, first, kClipType, IntRect(1, 1, 2, 2));
@@ -833,7 +833,7 @@
     if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
       PaintChunk::Id id(second, kClipType);
       PaintChunkProperties properties = DefaultPaintChunkProperties();
-      properties.property_tree_state.SetClip(clip2.Get());
+      properties.property_tree_state.SetClip(clip2.get());
 
       GetPaintController().UpdateCurrentPaintChunkProperties(&id, properties);
     }
@@ -1195,7 +1195,7 @@
     if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
       PaintChunk::Id id(container1, kBackgroundDrawingType);
       container1_properties.property_tree_state.SetEffect(
-          CreateOpacityOnlyEffect(EffectPaintPropertyNode::Root(), 0.5).Get());
+          CreateOpacityOnlyEffect(EffectPaintPropertyNode::Root(), 0.5).get());
       GetPaintController().UpdateCurrentPaintChunkProperties(
           &id, container1_properties);
     }
@@ -1213,7 +1213,7 @@
     if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
       PaintChunk::Id id(container2, kBackgroundDrawingType);
       container2_properties.property_tree_state.SetEffect(
-          CreateOpacityOnlyEffect(EffectPaintPropertyNode::Root(), 0.5).Get());
+          CreateOpacityOnlyEffect(EffectPaintPropertyNode::Root(), 0.5).get());
       GetPaintController().UpdateCurrentPaintChunkProperties(
           &id, container2_properties);
     }
@@ -1480,7 +1480,7 @@
     if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
       PaintChunk::Id id(container1, kBackgroundDrawingType);
       container1_properties.property_tree_state.SetEffect(
-          CreateOpacityOnlyEffect(EffectPaintPropertyNode::Root(), 0.5).Get());
+          CreateOpacityOnlyEffect(EffectPaintPropertyNode::Root(), 0.5).get());
       GetPaintController().UpdateCurrentPaintChunkProperties(
           &id, container1_properties);
     }
@@ -1493,7 +1493,7 @@
     if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
       PaintChunk::Id id(container2, kBackgroundDrawingType);
       container2_properties.property_tree_state.SetEffect(
-          CreateOpacityOnlyEffect(EffectPaintPropertyNode::Root(), 0.5).Get());
+          CreateOpacityOnlyEffect(EffectPaintPropertyNode::Root(), 0.5).get());
       GetPaintController().UpdateCurrentPaintChunkProperties(
           &id, container2_properties);
     }
@@ -1634,7 +1634,7 @@
     if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
       PaintChunk::Id id(container1, kBackgroundDrawingType);
       container1_background_properties.property_tree_state.SetEffect(
-          CreateOpacityOnlyEffect(EffectPaintPropertyNode::Root(), 0.5).Get());
+          CreateOpacityOnlyEffect(EffectPaintPropertyNode::Root(), 0.5).get());
       GetPaintController().UpdateCurrentPaintChunkProperties(
           &id, container1_background_properties);
     }
@@ -1646,7 +1646,7 @@
         PaintChunk::Id id(content1, kBackgroundDrawingType);
         content1_properties.property_tree_state.SetEffect(
             CreateOpacityOnlyEffect(EffectPaintPropertyNode::Root(), 0.6)
-                .Get());
+                .get());
         GetPaintController().UpdateCurrentPaintChunkProperties(
             &id, content1_properties);
       }
@@ -1659,7 +1659,7 @@
     if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
       PaintChunk::Id id(container1, kForegroundDrawingType);
       container1_foreground_properties.property_tree_state.SetEffect(
-          CreateOpacityOnlyEffect(EffectPaintPropertyNode::Root(), 0.5).Get());
+          CreateOpacityOnlyEffect(EffectPaintPropertyNode::Root(), 0.5).get());
       GetPaintController().UpdateCurrentPaintChunkProperties(
           &id, container1_foreground_properties);
     }
@@ -1670,7 +1670,7 @@
     if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
       PaintChunk::Id id(container2, kBackgroundDrawingType);
       container2_background_properties.property_tree_state.SetEffect(
-          CreateOpacityOnlyEffect(EffectPaintPropertyNode::Root(), 0.7).Get());
+          CreateOpacityOnlyEffect(EffectPaintPropertyNode::Root(), 0.7).get());
       GetPaintController().UpdateCurrentPaintChunkProperties(
           &id, container2_background_properties);
     }
@@ -1682,7 +1682,7 @@
         PaintChunk::Id id(content2, kBackgroundDrawingType);
         content2_properties.property_tree_state.SetEffect(
             CreateOpacityOnlyEffect(EffectPaintPropertyNode::Root(), 0.8)
-                .Get());
+                .get());
         GetPaintController().UpdateCurrentPaintChunkProperties(
             &id, content2_properties);
       }
@@ -2211,6 +2211,71 @@
   EXPECT_FALSE(result.image_painted);
 }
 
+TEST_P(PaintControllerTest, PartialInvalidation) {
+  if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
+    return;
+
+  FakeDisplayItemClient client("client", LayoutRect(100, 100, 300, 300));
+  GraphicsContext context(GetPaintController());
+
+  // Test partial rect invalidation in a new chunk.
+  GetPaintController().UpdateCurrentPaintChunkProperties(
+      &root_paint_chunk_id_, DefaultPaintChunkProperties());
+  client.SetPartialInvalidationRect(LayoutRect(200, 200, 100, 100));
+  DrawRect(context, client, kBackgroundDrawingType,
+           FloatRect(100, 100, 300, 300));
+  GetPaintController().CommitNewDisplayItems();
+  ASSERT_EQ(1u, GetPaintController().PaintChunks().size());
+  // Raster invalidation for the whole new chunk will be issued during
+  // PaintArtifactCompositor::Update().
+  EXPECT_TRUE(GetPaintController()
+                  .PaintChunks()[0]
+                  .raster_invalidation_rects.IsEmpty());
+  EXPECT_EQ(LayoutRect(), client.PartialInvalidationRect());
+
+  // Test partial rect invalidation without other invalidations.
+  GetPaintController().UpdateCurrentPaintChunkProperties(
+      &root_paint_chunk_id_, DefaultPaintChunkProperties());
+  client.SetPartialInvalidationRect(LayoutRect(150, 160, 170, 180));
+  DrawRect(context, client, kBackgroundDrawingType,
+           FloatRect(100, 100, 300, 300));
+  GetPaintController().CommitNewDisplayItems();
+  ASSERT_EQ(1u, GetPaintController().PaintChunks().size());
+  EXPECT_THAT(GetPaintController().PaintChunks()[0].raster_invalidation_rects,
+              // Partial invalidation.
+              UnorderedElementsAre(FloatRect(150, 160, 170, 180)));
+  EXPECT_EQ(LayoutRect(), client.PartialInvalidationRect());
+
+  // Test partial rect invalidation with full invalidation.
+  GetPaintController().UpdateCurrentPaintChunkProperties(
+      &root_paint_chunk_id_, DefaultPaintChunkProperties());
+  client.SetPartialInvalidationRect(LayoutRect(150, 160, 170, 180));
+  client.SetDisplayItemsUncached();
+  DrawRect(context, client, kBackgroundDrawingType,
+           FloatRect(100, 100, 300, 300));
+  GetPaintController().CommitNewDisplayItems();
+  ASSERT_EQ(1u, GetPaintController().PaintChunks().size());
+  EXPECT_THAT(GetPaintController().PaintChunks()[0].raster_invalidation_rects,
+              // Partial invalidation is shadowed by full invalidation.
+              UnorderedElementsAre(FloatRect(100, 100, 300, 300)));
+  EXPECT_EQ(LayoutRect(), client.PartialInvalidationRect());
+
+  // Test partial rect invalidation with incremental invalidation.
+  GetPaintController().UpdateCurrentPaintChunkProperties(
+      &root_paint_chunk_id_, DefaultPaintChunkProperties());
+  client.SetPartialInvalidationRect(LayoutRect(150, 160, 170, 180));
+  client.SetVisualRect(LayoutRect(100, 100, 300, 400));
+  DrawRect(context, client, kBackgroundDrawingType,
+           FloatRect(100, 100, 300, 400));
+  GetPaintController().CommitNewDisplayItems();
+  ASSERT_EQ(1u, GetPaintController().PaintChunks().size());
+  EXPECT_THAT(GetPaintController().PaintChunks()[0].raster_invalidation_rects,
+              // Both partial invalidation and incremental invalidation.
+              UnorderedElementsAre(FloatRect(100, 400, 300, 100),
+                                   FloatRect(150, 160, 170, 180)));
+  EXPECT_EQ(LayoutRect(), client.PartialInvalidationRect());
+}
+
 // Death tests don't work properly on Android.
 #if defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
 
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintPropertyNode.h b/third_party/WebKit/Source/platform/graphics/paint/PaintPropertyNode.h
index 1e4d22f5..d057a146 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintPropertyNode.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintPropertyNode.h
@@ -36,7 +36,7 @@
 class PaintPropertyNode : public RefCounted<NodeType> {
  public:
   // Parent property node, or nullptr if this is the root node.
-  const NodeType* Parent() const { return parent_.Get(); }
+  const NodeType* Parent() const { return parent_.get(); }
   bool IsRoot() const { return !parent_; }
 
   bool IsAncestorOf(const NodeType& other) const {
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeState.h b/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeState.h
index 3b75cf6..9bf5b4c 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeState.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeState.h
@@ -28,22 +28,18 @@
   bool HasDirectCompositingReasons() const;
 
   const TransformPaintPropertyNode* Transform() const {
-    return transform_.Get();
+    return transform_.get();
   }
   void SetTransform(RefPtr<const TransformPaintPropertyNode> node) {
     transform_ = std::move(node);
   }
 
-  const ClipPaintPropertyNode* Clip() const {
-    return clip_.Get();
-  }
+  const ClipPaintPropertyNode* Clip() const { return clip_.get(); }
   void SetClip(RefPtr<const ClipPaintPropertyNode> node) {
     clip_ = std::move(node);
   }
 
-  const EffectPaintPropertyNode* Effect() const {
-    return effect_.Get();
-  }
+  const EffectPaintPropertyNode* Effect() const { return effect_.get(); }
   void SetEffect(RefPtr<const EffectPaintPropertyNode> node) {
     effect_ = std::move(node);
   }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeStateTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeStateTest.cpp
index e2263769..6dbf8b76 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeStateTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeStateTest.cpp
@@ -25,7 +25,7 @@
                                          TransformationMatrix(), FloatPoint3D(),
                                          false, 0, kCompositingReasonNone,
                                          expected_compositor_element_id);
-  PropertyTreeState state(transform.Get(), ClipPaintPropertyNode::Root(),
+  PropertyTreeState state(transform.get(), ClipPaintPropertyNode::Root(),
                           EffectPaintPropertyNode::Root());
   EXPECT_EQ(expected_compositor_element_id,
             state.GetCompositorElementId(CompositorElementIdSet()));
@@ -39,7 +39,7 @@
       CompositorFilterOperations(), 1.0, SkBlendMode::kSrcOver,
       kCompositingReasonNone, expected_compositor_element_id);
   PropertyTreeState state(TransformPaintPropertyNode::Root(),
-                          ClipPaintPropertyNode::Root(), effect.Get());
+                          ClipPaintPropertyNode::Root(), effect.get());
   EXPECT_EQ(expected_compositor_element_id,
             state.GetCompositorElementId(CompositorElementIdSet()));
 }
@@ -56,8 +56,8 @@
       ClipPaintPropertyNode::Root(), kColorFilterNone,
       CompositorFilterOperations(), 1.0, SkBlendMode::kSrcOver,
       kCompositingReasonNone, expected_compositor_element_id);
-  PropertyTreeState state(transform.Get(), ClipPaintPropertyNode::Root(),
-                          effect.Get());
+  PropertyTreeState state(transform.get(), ClipPaintPropertyNode::Root(),
+                          effect.get());
   EXPECT_EQ(expected_compositor_element_id,
             state.GetCompositorElementId(CompositorElementIdSet()));
 }
@@ -75,8 +75,8 @@
       ClipPaintPropertyNode::Root(), kColorFilterNone,
       CompositorFilterOperations(), 1.0, SkBlendMode::kSrcOver,
       kCompositingReasonNone, second_compositor_element_id);
-  PropertyTreeState state(transform.Get(), ClipPaintPropertyNode::Root(),
-                          effect.Get());
+  PropertyTreeState state(transform.get(), ClipPaintPropertyNode::Root(),
+                          effect.get());
 
   CompositorElementIdSet composited_element_ids;
   composited_element_ids.insert(first_compositor_element_id);
diff --git a/third_party/WebKit/Source/platform/graphics/paint/ScrollPaintPropertyNode.cpp b/third_party/WebKit/Source/platform/graphics/paint/ScrollPaintPropertyNode.cpp
index eb688028..cf2aaeb 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/ScrollPaintPropertyNode.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/ScrollPaintPropertyNode.cpp
@@ -11,8 +11,9 @@
 ScrollPaintPropertyNode* ScrollPaintPropertyNode::Root() {
   DEFINE_STATIC_REF(ScrollPaintPropertyNode, root,
                     (ScrollPaintPropertyNode::Create(
-                        nullptr, IntPoint(), IntSize(), IntSize(), false, false,
-                        0, CompositorElementId())));
+                        nullptr, IntRect(), IntRect(), false, false,
+                        MainThreadScrollingReason::kNotScrollingOnMain,
+                        CompositorElementId())));
   return root;
 }
 
@@ -20,12 +21,10 @@
   auto json = JSONObject::Create();
   if (Parent())
     json->SetString("parent", String::Format("%p", Parent()));
-  if (bounds_offset_ != IntPoint())
-    json->SetString("boundsOffset", bounds_offset_.ToString());
-  if (!container_bounds_.IsEmpty())
-    json->SetString("containerBounds", container_bounds_.ToString());
-  if (!bounds_.IsEmpty())
-    json->SetString("containerBounds", bounds_.ToString());
+  if (container_rect_ != IntRect())
+    json->SetString("containerRect", container_rect_.ToString());
+  if (contents_rect_ != IntRect())
+    json->SetString("contentsRect", contents_rect_.ToString());
   if (user_scrollable_horizontal_ || user_scrollable_vertical_) {
     json->SetString("userScrollable",
                     user_scrollable_horizontal_
diff --git a/third_party/WebKit/Source/platform/graphics/paint/ScrollPaintPropertyNode.h b/third_party/WebKit/Source/platform/graphics/paint/ScrollPaintPropertyNode.h
index 4c44e8f..34568d5 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/ScrollPaintPropertyNode.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/ScrollPaintPropertyNode.h
@@ -8,6 +8,7 @@
 #include "platform/PlatformExport.h"
 #include "platform/geometry/FloatPoint.h"
 #include "platform/geometry/FloatSize.h"
+#include "platform/geometry/IntRect.h"
 #include "platform/graphics/CompositorElementId.h"
 #include "platform/graphics/paint/PaintPropertyNode.h"
 #include "platform/scroll/MainThreadScrollingReason.h"
@@ -39,31 +40,28 @@
 
   static RefPtr<ScrollPaintPropertyNode> Create(
       RefPtr<const ScrollPaintPropertyNode> parent,
-      const IntPoint& bounds_offset,
-      const IntSize& container_bounds,
-      const IntSize& bounds,
+      const IntRect& container_rect,
+      const IntRect& contents_rect,
       bool user_scrollable_horizontal,
       bool user_scrollable_vertical,
       MainThreadScrollingReasons main_thread_scrolling_reasons,
       CompositorElementId compositor_element_id) {
     return WTF::AdoptRef(new ScrollPaintPropertyNode(
-        std::move(parent), bounds_offset, container_bounds, bounds,
+        std::move(parent), container_rect, contents_rect,
         user_scrollable_horizontal, user_scrollable_vertical,
         main_thread_scrolling_reasons, compositor_element_id));
   }
 
   bool Update(RefPtr<const ScrollPaintPropertyNode> parent,
-              const IntPoint& bounds_offset,
-              const IntSize& container_bounds,
-              const IntSize& bounds,
+              const IntRect& container_rect,
+              const IntRect& contents_rect,
               bool user_scrollable_horizontal,
               bool user_scrollable_vertical,
               MainThreadScrollingReasons main_thread_scrolling_reasons,
               CompositorElementId compositor_element_id) {
     bool parent_changed = PaintPropertyNode::Update(std::move(parent));
 
-    if (bounds_offset == bounds_offset_ &&
-        container_bounds == container_bounds_ && bounds == bounds_ &&
+    if (container_rect == container_rect_ && contents_rect == contents_rect_ &&
         user_scrollable_horizontal == user_scrollable_horizontal_ &&
         user_scrollable_vertical == user_scrollable_vertical_ &&
         main_thread_scrolling_reasons == main_thread_scrolling_reasons_ &&
@@ -71,9 +69,8 @@
       return parent_changed;
 
     SetChanged();
-    bounds_offset_ = bounds_offset;
-    container_bounds_ = container_bounds;
-    bounds_ = bounds;
+    container_rect_ = container_rect;
+    contents_rect_ = contents_rect;
     user_scrollable_horizontal_ = user_scrollable_horizontal;
     user_scrollable_vertical_ = user_scrollable_vertical;
     main_thread_scrolling_reasons_ = main_thread_scrolling_reasons;
@@ -82,15 +79,15 @@
     return true;
   }
 
-  // Offset for |ContainerBounds| and |Bounds|.
-  const IntPoint& Offset() const { return bounds_offset_; }
+  // Rect of the container area that the contents scrolls in, in the space of
+  // the parent of the associated transform node (ScrollTranslation).
+  // It doesn't include non-overlay scrollbars. Overlay scrollbars do not affect
+  // the rect.
+  const IntRect& ContainerRect() const { return container_rect_; }
 
-  // Size of the container area that the contents scrolls in, not including
-  // non-overlay scrollbars. Overlay scrollbars do not affect these bounds.
-  const IntSize& ContainerBounds() const { return container_bounds_; }
-
-  // Size of the content that is scrolled within the container bounds.
-  const IntSize& Bounds() const { return bounds_; }
+  // Rect of the contents that is scrolled within the container rect, in the
+  // space of the associated transform node (ScrollTranslation).
+  const IntRect& ContentsRect() const { return contents_rect_; }
 
   bool UserScrollableHorizontal() const { return user_scrollable_horizontal_; }
   bool UserScrollableVertical() const { return user_scrollable_vertical_; }
@@ -122,7 +119,7 @@
   RefPtr<ScrollPaintPropertyNode> Clone() const {
     RefPtr<ScrollPaintPropertyNode> cloned =
         WTF::AdoptRef(new ScrollPaintPropertyNode(
-            Parent(), bounds_offset_, container_bounds_, bounds_,
+            Parent(), container_rect_, contents_rect_,
             user_scrollable_horizontal_, user_scrollable_vertical_,
             main_thread_scrolling_reasons_, compositor_element_id_));
     return cloned;
@@ -131,8 +128,8 @@
   // The equality operator is used by FindPropertiesNeedingUpdate.h for checking
   // if a scroll node has changed.
   bool operator==(const ScrollPaintPropertyNode& o) const {
-    return Parent() == o.Parent() && bounds_offset_ == o.bounds_offset_ &&
-           container_bounds_ == o.container_bounds_ && bounds_ == o.bounds_ &&
+    return Parent() == o.Parent() && container_rect_ == o.container_rect_ &&
+           contents_rect_ == o.contents_rect_ &&
            user_scrollable_horizontal_ == o.user_scrollable_horizontal_ &&
            user_scrollable_vertical_ == o.user_scrollable_vertical_ &&
            main_thread_scrolling_reasons_ == o.main_thread_scrolling_reasons_ &&
@@ -147,17 +144,15 @@
  private:
   ScrollPaintPropertyNode(
       RefPtr<const ScrollPaintPropertyNode> parent,
-      IntPoint bounds_offset,
-      IntSize container_bounds,
-      IntSize bounds,
+      const IntRect& container_rect,
+      const IntRect& contents_rect,
       bool user_scrollable_horizontal,
       bool user_scrollable_vertical,
       MainThreadScrollingReasons main_thread_scrolling_reasons,
       CompositorElementId compositor_element_id)
       : PaintPropertyNode(std::move(parent)),
-        bounds_offset_(bounds_offset),
-        container_bounds_(container_bounds),
-        bounds_(bounds),
+        container_rect_(container_rect),
+        contents_rect_(contents_rect),
         user_scrollable_horizontal_(user_scrollable_horizontal),
         user_scrollable_vertical_(user_scrollable_vertical),
         main_thread_scrolling_reasons_(main_thread_scrolling_reasons),
@@ -171,9 +166,8 @@
                CompositorElementIdNamespace::kScroll;
   }
 
-  IntPoint bounds_offset_;
-  IntSize container_bounds_;
-  IntSize bounds_;
+  IntRect container_rect_;
+  IntRect contents_rect_;
   bool user_scrollable_horizontal_ : 1;
   bool user_scrollable_vertical_ : 1;
   MainThreadScrollingReasons main_thread_scrolling_reasons_;
diff --git a/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.cpp b/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.cpp
index a19a370..4b321f93 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.cpp
@@ -54,7 +54,7 @@
                     compositor_element_id_.ToString().c_str());
   }
   if (scroll_)
-    json->SetString("scroll", String::Format("%p", scroll_.Get()));
+    json->SetString("scroll", String::Format("%p", scroll_.get()));
   return json;
 }
 
diff --git a/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h b/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h
index fd65ec28..b556635 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h
@@ -97,7 +97,7 @@
   const FloatPoint3D& Origin() const { return origin_; }
 
   // The associated scroll node, or nullptr otherwise.
-  const ScrollPaintPropertyNode* ScrollNode() const { return scroll_.Get(); }
+  const ScrollPaintPropertyNode* ScrollNode() const { return scroll_.get(); }
 
   // If this is a scroll offset translation (i.e., has an associated scroll
   // node), returns this. Otherwise, returns the transform node that this node
diff --git a/third_party/WebKit/Source/platform/graphics/test/MockImageDecoder.h b/third_party/WebKit/Source/platform/graphics/test/MockImageDecoder.h
index 11304e3..6a4ce5f 100644
--- a/third_party/WebKit/Source/platform/graphics/test/MockImageDecoder.h
+++ b/third_party/WebKit/Source/platform/graphics/test/MockImageDecoder.h
@@ -29,7 +29,6 @@
 #include <memory>
 #include "platform/graphics/ImageFrameGenerator.h"
 #include "platform/image-decoders/ImageDecoder.h"
-#include "platform/wtf/PtrUtil.h"
 
 namespace blink {
 
@@ -67,7 +66,7 @@
  public:
   static std::unique_ptr<MockImageDecoder> Create(
       MockImageDecoderClient* client) {
-    return WTF::MakeUnique<MockImageDecoder>(client);
+    return std::make_unique<MockImageDecoder>(client);
   }
 
   MockImageDecoder(MockImageDecoderClient* client)
diff --git a/third_party/WebKit/Source/platform/heap/ThreadingTraits.h b/third_party/WebKit/Source/platform/heap/ThreadingTraits.h
index d29bc1d..d3ea0b2 100644
--- a/third_party/WebKit/Source/platform/heap/ThreadingTraits.h
+++ b/third_party/WebKit/Source/platform/heap/ThreadingTraits.h
@@ -39,12 +39,15 @@
 // Remove them.
 class Node;
 class NodeList;
+class NodeRareDataBase;
 
 template <
     typename T,
     bool mainThreadOnly =
         WTF::IsSubclass<typename std::remove_const<T>::type, Node>::value ||
-        WTF::IsSubclass<typename std::remove_const<T>::type, NodeList>::value>
+        WTF::IsSubclass<typename std::remove_const<T>::type, NodeList>::value ||
+        WTF::IsSubclass<typename std::remove_const<T>::type,
+                        NodeRareDataBase>::value>
 struct DefaultThreadingTrait;
 
 template <typename T>
diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h
index 3e46cd9..e440c80 100644
--- a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h
+++ b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h
@@ -122,7 +122,7 @@
       return;
     data_ = std::move(data);
     is_all_data_received_ = all_data_received;
-    OnSetData(data_.Get());
+    OnSetData(data_.get());
   }
 
   void SetData(RefPtr<SharedBuffer> data, bool all_data_received) {
diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTestHelpers.cpp b/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTestHelpers.cpp
index ad22138..565d2b88 100644
--- a/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTestHelpers.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTestHelpers.cpp
@@ -79,7 +79,7 @@
     source_data[1]->Append(source++, 1u);
     // Alternate the buffers to cover the JPEGImageDecoder::OnSetData restart
     // code.
-    decoder->SetData(source_data[length & 1].Get(), length == data.size());
+    decoder->SetData(source_data[length & 1].get(), length == data.size());
 
     EXPECT_LE(frame_count, decoder->FrameCount());
     frame_count = decoder->FrameCount();
@@ -129,7 +129,7 @@
   segmented_data->Append(data.data(), data.size());
 
   std::unique_ptr<ImageDecoder> decoder = create_decoder();
-  decoder->SetData(segmented_data.Get(), true);
+  decoder->SetData(segmented_data.get(), true);
 
   ASSERT_TRUE(decoder->IsSizeAvailable());
 
@@ -206,9 +206,9 @@
   // ... and then decode frames from 'reallocated_data'.
   Vector<char> copy = data->Copy();
   RefPtr<SharedBuffer> reallocated_data = SharedBuffer::AdoptVector(copy);
-  ASSERT_TRUE(reallocated_data.Get());
+  ASSERT_TRUE(reallocated_data.get());
   data->Clear();
-  decoder->SetData(reallocated_data.Get(), true);
+  decoder->SetData(reallocated_data.get(), true);
 
   for (size_t i = 0; i < frame_count; ++i) {
     const ImageFrame* const frame = decoder->DecodeFrameBufferAtIndex(i);
@@ -232,7 +232,7 @@
   const char* source = source_buffer.data();
   for (size_t length = 1; length <= frame_offset; ++length) {
     temp_data->Append(source++, 1u);
-    decoder->SetData(temp_data.Get(), false);
+    decoder->SetData(temp_data.get(), false);
 
     if (length < frame_offset) {
       EXPECT_FALSE(decoder->IsSizeAvailable());
@@ -270,7 +270,7 @@
   for (size_t i = 1; i <= full_length; i += increment) {
     decoder = create_decoder();
     data->Append(source++, 1u);
-    decoder->SetData(data.Get(), i == full_length);
+    decoder->SetData(data.get(), i == full_length);
     ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0);
     if (!frame) {
       truncated_hashes.push_back(0);
@@ -285,7 +285,7 @@
   source = full_data.data();
   for (size_t i = 1; i <= full_length; i += increment) {
     data->Append(source++, 1u);
-    decoder->SetData(data.Get(), i == full_length);
+    decoder->SetData(data.get(), i == full_length);
     ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0);
     if (!frame) {
       progressive_hashes.push_back(0);
@@ -310,7 +310,7 @@
   const char* source = full_data.data();
   do {
     data->Append(source++, 1u);
-    decoder->SetData(data.Get(), false);
+    decoder->SetData(data.get(), false);
   } while (!decoder->FrameCount() ||
            decoder->DecodeFrameBufferAtIndex(0)->GetStatus() ==
                ImageFrame::kFrameEmpty);
@@ -347,7 +347,7 @@
   const char* source = full_data.data();
   do {
     data->Append(source++, 1u);
-    decoder->SetData(data.Get(), false);
+    decoder->SetData(data.get(), false);
   } while (!decoder->FrameCount() ||
            decoder->DecodeFrameBufferAtIndex(0)->GetStatus() ==
                ImageFrame::kFrameEmpty);
@@ -370,8 +370,8 @@
                           size_t expected_frame_count,
                           int expected_repetition_count) {
   RefPtr<SharedBuffer> data = ReadFile(file);
-  ASSERT_TRUE(data.Get());
-  TestByteByByteDecode(create_decoder, data.Get(), expected_frame_count,
+  ASSERT_TRUE(data.get());
+  TestByteByByteDecode(create_decoder, data.get(), expected_frame_count,
                        expected_repetition_count);
 }
 void TestByteByByteDecode(DecoderCreator create_decoder,
@@ -380,50 +380,50 @@
                           size_t expected_frame_count,
                           int expected_repetition_count) {
   RefPtr<SharedBuffer> data = ReadFile(dir, file);
-  ASSERT_TRUE(data.Get());
-  TestByteByByteDecode(create_decoder, data.Get(), expected_frame_count,
+  ASSERT_TRUE(data.get());
+  TestByteByByteDecode(create_decoder, data.get(), expected_frame_count,
                        expected_repetition_count);
 }
 
 void TestMergeBuffer(DecoderCreator create_decoder, const char* file) {
   RefPtr<SharedBuffer> data = ReadFile(file);
-  ASSERT_TRUE(data.Get());
-  TestMergeBuffer(create_decoder, data.Get());
+  ASSERT_TRUE(data.get());
+  TestMergeBuffer(create_decoder, data.get());
 }
 
 void TestMergeBuffer(DecoderCreator create_decoder,
                      const char* dir,
                      const char* file) {
   RefPtr<SharedBuffer> data = ReadFile(dir, file);
-  ASSERT_TRUE(data.Get());
-  TestMergeBuffer(create_decoder, data.Get());
+  ASSERT_TRUE(data.get());
+  TestMergeBuffer(create_decoder, data.get());
 }
 
 void TestRandomFrameDecode(DecoderCreator create_decoder,
                            const char* file,
                            size_t skipping_step) {
   RefPtr<SharedBuffer> data = ReadFile(file);
-  ASSERT_TRUE(data.Get());
+  ASSERT_TRUE(data.get());
   SCOPED_TRACE(file);
-  TestRandomFrameDecode(create_decoder, data.Get(), skipping_step);
+  TestRandomFrameDecode(create_decoder, data.get(), skipping_step);
 }
 void TestRandomFrameDecode(DecoderCreator create_decoder,
                            const char* dir,
                            const char* file,
                            size_t skipping_step) {
   RefPtr<SharedBuffer> data = ReadFile(dir, file);
-  ASSERT_TRUE(data.Get());
+  ASSERT_TRUE(data.get());
   SCOPED_TRACE(file);
-  TestRandomFrameDecode(create_decoder, data.Get(), skipping_step);
+  TestRandomFrameDecode(create_decoder, data.get(), skipping_step);
 }
 
 void TestRandomDecodeAfterClearFrameBufferCache(DecoderCreator create_decoder,
                                                 const char* file,
                                                 size_t skipping_step) {
   RefPtr<SharedBuffer> data = ReadFile(file);
-  ASSERT_TRUE(data.Get());
+  ASSERT_TRUE(data.get());
   SCOPED_TRACE(file);
-  TestRandomDecodeAfterClearFrameBufferCache(create_decoder, data.Get(),
+  TestRandomDecodeAfterClearFrameBufferCache(create_decoder, data.get(),
                                              skipping_step);
 }
 
@@ -432,25 +432,25 @@
                                                 const char* file,
                                                 size_t skipping_step) {
   RefPtr<SharedBuffer> data = ReadFile(dir, file);
-  ASSERT_TRUE(data.Get());
+  ASSERT_TRUE(data.get());
   SCOPED_TRACE(file);
-  TestRandomDecodeAfterClearFrameBufferCache(create_decoder, data.Get(),
+  TestRandomDecodeAfterClearFrameBufferCache(create_decoder, data.get(),
                                              skipping_step);
 }
 
 void TestDecodeAfterReallocatingData(DecoderCreator create_decoder,
                                      const char* file) {
   RefPtr<SharedBuffer> data = ReadFile(file);
-  ASSERT_TRUE(data.Get());
-  TestDecodeAfterReallocatingData(create_decoder, data.Get());
+  ASSERT_TRUE(data.get());
+  TestDecodeAfterReallocatingData(create_decoder, data.get());
 }
 
 void TestDecodeAfterReallocatingData(DecoderCreator create_decoder,
                                      const char* dir,
                                      const char* file) {
   RefPtr<SharedBuffer> data = ReadFile(dir, file);
-  ASSERT_TRUE(data.Get());
-  TestDecodeAfterReallocatingData(create_decoder, data.Get());
+  ASSERT_TRUE(data.get());
+  TestDecodeAfterReallocatingData(create_decoder, data.get());
 }
 
 void TestByteByByteSizeAvailable(DecoderCreator create_decoder,
@@ -459,8 +459,8 @@
                                  bool has_color_space,
                                  int expected_repetition_count) {
   RefPtr<SharedBuffer> data = ReadFile(file);
-  ASSERT_TRUE(data.Get());
-  TestByteByByteSizeAvailable(create_decoder, data.Get(), frame_offset,
+  ASSERT_TRUE(data.get());
+  TestByteByByteSizeAvailable(create_decoder, data.get(), frame_offset,
                               has_color_space, expected_repetition_count);
 }
 
@@ -471,8 +471,8 @@
                                  bool has_color_space,
                                  int expected_repetition_count) {
   RefPtr<SharedBuffer> data = ReadFile(dir, file);
-  ASSERT_TRUE(data.Get());
-  TestByteByByteSizeAvailable(create_decoder, data.Get(), frame_offset,
+  ASSERT_TRUE(data.get());
+  TestByteByByteSizeAvailable(create_decoder, data.get(), frame_offset,
                               has_color_space, expected_repetition_count);
 }
 
@@ -480,8 +480,8 @@
                              const char* file,
                              size_t increment) {
   RefPtr<SharedBuffer> data = ReadFile(file);
-  ASSERT_TRUE(data.Get());
-  TestProgressiveDecoding(create_decoder, data.Get(), increment);
+  ASSERT_TRUE(data.get());
+  TestProgressiveDecoding(create_decoder, data.get(), increment);
 }
 
 void TestProgressiveDecoding(DecoderCreator create_decoder,
@@ -489,8 +489,8 @@
                              const char* file,
                              size_t increment) {
   RefPtr<SharedBuffer> data = ReadFile(dir, file);
-  ASSERT_TRUE(data.Get());
-  TestProgressiveDecoding(create_decoder, data.Get(), increment);
+  ASSERT_TRUE(data.get());
+  TestProgressiveDecoding(create_decoder, data.get(), increment);
 }
 
 void TestUpdateRequiredPreviousFrameAfterFirstDecode(
@@ -498,16 +498,16 @@
     const char* dir,
     const char* file) {
   RefPtr<SharedBuffer> data = ReadFile(dir, file);
-  ASSERT_TRUE(data.Get());
-  TestUpdateRequiredPreviousFrameAfterFirstDecode(create_decoder, data.Get());
+  ASSERT_TRUE(data.get());
+  TestUpdateRequiredPreviousFrameAfterFirstDecode(create_decoder, data.get());
 }
 
 void TestUpdateRequiredPreviousFrameAfterFirstDecode(
     DecoderCreator create_decoder,
     const char* file) {
   RefPtr<SharedBuffer> data = ReadFile(file);
-  ASSERT_TRUE(data.Get());
-  TestUpdateRequiredPreviousFrameAfterFirstDecode(create_decoder, data.Get());
+  ASSERT_TRUE(data.get());
+  TestUpdateRequiredPreviousFrameAfterFirstDecode(create_decoder, data.get());
 }
 
 void TestResumePartialDecodeAfterClearFrameBufferCache(
@@ -515,16 +515,16 @@
     const char* dir,
     const char* file) {
   RefPtr<SharedBuffer> data = ReadFile(dir, file);
-  ASSERT_TRUE(data.Get());
-  TestResumePartialDecodeAfterClearFrameBufferCache(create_decoder, data.Get());
+  ASSERT_TRUE(data.get());
+  TestResumePartialDecodeAfterClearFrameBufferCache(create_decoder, data.get());
 }
 
 void TestResumePartialDecodeAfterClearFrameBufferCache(
     DecoderCreator create_decoder,
     const char* file) {
   RefPtr<SharedBuffer> data = ReadFile(file);
-  ASSERT_TRUE(data.Get());
-  TestResumePartialDecodeAfterClearFrameBufferCache(create_decoder, data.Get());
+  ASSERT_TRUE(data.get());
+  TestResumePartialDecodeAfterClearFrameBufferCache(create_decoder, data.get());
 }
 
 static uint32_t PremultiplyColor(uint32_t c) {
@@ -569,15 +569,15 @@
 void TestAlphaBlending(DecoderCreatorWithAlpha create_decoder,
                        const char* file) {
   RefPtr<SharedBuffer> data = ReadFile(file);
-  ASSERT_TRUE(data.Get());
+  ASSERT_TRUE(data.get());
 
   std::unique_ptr<ImageDecoder> decoder_a =
       create_decoder(ImageDecoder::kAlphaPremultiplied);
-  decoder_a->SetData(data.Get(), true);
+  decoder_a->SetData(data.get(), true);
 
   std::unique_ptr<ImageDecoder> decoder_b =
       create_decoder(ImageDecoder::kAlphaNotPremultiplied);
-  decoder_b->SetData(data.Get(), true);
+  decoder_b->SetData(data.get(), true);
 
   size_t frame_count = decoder_a->FrameCount();
   ASSERT_EQ(frame_count, decoder_b->FrameCount());
diff --git a/third_party/WebKit/Source/platform/image-decoders/bmp/BMPImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/bmp/BMPImageDecoder.cpp
index b225a10..7dd1505 100644
--- a/third_party/WebKit/Source/platform/image-decoders/bmp/BMPImageDecoder.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/bmp/BMPImageDecoder.cpp
@@ -84,7 +84,7 @@
   if (!reader_) {
     reader_ = WTF::WrapUnique(
         new BMPImageReader(this, decoded_offset_, img_data_offset, false));
-    reader_->SetData(data_.Get());
+    reader_->SetData(data_.get());
   }
 
   if (!frame_buffer_cache_.IsEmpty())
diff --git a/third_party/WebKit/Source/platform/image-decoders/bmp/BMPImageDecoderTest.cpp b/third_party/WebKit/Source/platform/image-decoders/bmp/BMPImageDecoderTest.cpp
index a27d3def..d158dd9 100644
--- a/third_party/WebKit/Source/platform/image-decoders/bmp/BMPImageDecoderTest.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/bmp/BMPImageDecoderTest.cpp
@@ -26,10 +26,10 @@
   static constexpr char kBmpFile[] =
       "/LayoutTests/images/resources/lenna.bmp";  // 256x256
   RefPtr<SharedBuffer> data = ReadFile(kBmpFile);
-  ASSERT_TRUE(data.Get());
+  ASSERT_TRUE(data.get());
 
   std::unique_ptr<ImageDecoder> decoder = CreateBMPDecoder();
-  decoder->SetData(data.Get(), true);
+  decoder->SetData(data.get(), true);
   EXPECT_TRUE(decoder->IsSizeAvailable());
   EXPECT_EQ(256, decoder->Size().Width());
   EXPECT_EQ(256, decoder->Size().Height());
@@ -39,10 +39,10 @@
   static constexpr char kBmpFile[] =
       "/LayoutTests/images/resources/lenna.bmp";  // 256x256
   RefPtr<SharedBuffer> data = ReadFile(kBmpFile);
-  ASSERT_TRUE(data.Get());
+  ASSERT_TRUE(data.get());
 
   std::unique_ptr<ImageDecoder> decoder = CreateBMPDecoder();
-  decoder->SetData(data.Get(), true);
+  decoder->SetData(data.get(), true);
 
   ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0);
   ASSERT_TRUE(frame);
@@ -57,10 +57,10 @@
   static constexpr char kBmpFile[] =
       "/LayoutTests/images/resources/0x0.bmp";  // 0x0
   RefPtr<SharedBuffer> data = ReadFile(kBmpFile);
-  ASSERT_TRUE(data.Get());
+  ASSERT_TRUE(data.get());
 
   std::unique_ptr<ImageDecoder> decoder = CreateBMPDecoder();
-  decoder->SetData(data.Get(), true);
+  decoder->SetData(data.get(), true);
 
   ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0);
   ASSERT_TRUE(frame);
@@ -74,7 +74,7 @@
   RefPtr<SharedBuffer> data = ReadFile(kBmpFile);
   std::unique_ptr<ImageDecoder> decoder = CreateBMPDecoder();
   // Test when not all data is received.
-  decoder->SetData(data.Get(), false);
+  decoder->SetData(data.get(), false);
   EXPECT_FALSE(decoder->IsSizeAvailable());
   EXPECT_TRUE(decoder->Failed());
 }
@@ -93,10 +93,10 @@
   static constexpr char kBmpFile[] =
       "/LayoutTests/images/resources/crbug752898.bmp";
   RefPtr<SharedBuffer> data = ReadFile(kBmpFile);
-  ASSERT_TRUE(data.Get());
+  ASSERT_TRUE(data.get());
 
   std::unique_ptr<ImageDecoder> decoder = CreateBMPDecoder();
-  decoder->SetData(data.Get(), true);
+  decoder->SetData(data.get(), true);
   decoder->DecodeFrameBufferAtIndex(0);
 }
 
diff --git a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoderTest.cpp b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoderTest.cpp
index fb2f76d..7ad0428 100644
--- a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoderTest.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoderTest.cpp
@@ -56,8 +56,8 @@
                          int expected_repetition_count) {
   std::unique_ptr<ImageDecoder> decoder = CreateDecoder();
   RefPtr<SharedBuffer> data = ReadFile(dir, file);
-  ASSERT_TRUE(data.Get());
-  decoder->SetData(data.Get(), true);
+  ASSERT_TRUE(data.get());
+  decoder->SetData(data.get(), true);
 
   EXPECT_EQ(expected_repetition_count, decoder->RepetitionCount());
 }
@@ -68,8 +68,8 @@
   std::unique_ptr<ImageDecoder> decoder = CreateDecoder();
 
   RefPtr<SharedBuffer> data = ReadFile(kLayoutTestResourcesDir, "animated.gif");
-  ASSERT_TRUE(data.Get());
-  decoder->SetData(data.Get(), true);
+  ASSERT_TRUE(data.get());
+  decoder->SetData(data.get(), true);
 
   ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0);
   uint32_t generation_id0 = frame->Bitmap().getGenerationID();
@@ -92,8 +92,8 @@
   std::unique_ptr<ImageDecoder> decoder = CreateDecoder();
 
   RefPtr<SharedBuffer> data = ReadFile(kLayoutTestResourcesDir, "animated.gif");
-  ASSERT_TRUE(data.Get());
-  decoder->SetData(data.Get(), true);
+  ASSERT_TRUE(data.get());
+  decoder->SetData(data.get(), true);
 
   ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0);
   EXPECT_EQ(ImageFrame::kFrameComplete, frame->GetStatus());
@@ -118,7 +118,7 @@
   // Pass data to decoder byte by byte.
   for (size_t length = 1; length <= data.size(); ++length) {
     RefPtr<SharedBuffer> temp_data = SharedBuffer::Create(data.data(), length);
-    decoder->SetData(temp_data.Get(), length == data.size());
+    decoder->SetData(temp_data.get(), length == data.size());
 
     EXPECT_LE(frame_count, decoder->FrameCount());
     frame_count = decoder->FrameCount();
@@ -141,8 +141,8 @@
   std::unique_ptr<ImageDecoder> decoder = CreateDecoder();
 
   RefPtr<SharedBuffer> data = ReadFile(kDecodersTestingDir, "broken.gif");
-  ASSERT_TRUE(data.Get());
-  decoder->SetData(data.Get(), true);
+  ASSERT_TRUE(data.get());
+  decoder->SetData(data.get(), true);
 
   // One frame is detected but cannot be decoded.
   EXPECT_EQ(1u, decoder->FrameCount());
@@ -163,7 +163,7 @@
   ASSERT_GE(data.size(), 10u);
   RefPtr<SharedBuffer> temp_data =
       SharedBuffer::Create(data.data(), data.size() - 10);
-  decoder->SetData(temp_data.Get(), true);
+  decoder->SetData(temp_data.get(), true);
 
   EXPECT_EQ(2u, decoder->FrameCount());
   EXPECT_FALSE(decoder->Failed());
@@ -178,8 +178,8 @@
   std::unique_ptr<ImageDecoder> decoder = CreateDecoder();
 
   RefPtr<SharedBuffer> data = ReadFile(kLayoutTestResourcesDir, "animated.gif");
-  ASSERT_TRUE(data.Get());
-  decoder->SetData(data.Get(), true);
+  ASSERT_TRUE(data.get());
+  decoder->SetData(data.get(), true);
 
   EXPECT_EQ(2u, decoder->FrameCount());
   EXPECT_FALSE(decoder->Failed());
@@ -193,20 +193,20 @@
 
   RefPtr<SharedBuffer> data_buffer =
       ReadFile(kLayoutTestResourcesDir, "animated.gif");
-  ASSERT_TRUE(data_buffer.Get());
+  ASSERT_TRUE(data_buffer.get());
   const Vector<char> data = data_buffer->Copy();
 
   ASSERT_GE(data.size(), 10u);
   RefPtr<SharedBuffer> temp_data =
       SharedBuffer::Create(data.data(), data.size() - 10);
-  decoder->SetData(temp_data.Get(), false);
+  decoder->SetData(temp_data.get(), false);
 
   EXPECT_EQ(2u, decoder->FrameCount());
   EXPECT_FALSE(decoder->Failed());
   EXPECT_TRUE(decoder->FrameIsReceivedAtIndex(0));
   EXPECT_FALSE(decoder->FrameIsReceivedAtIndex(1));
 
-  decoder->SetData(data_buffer.Get(), true);
+  decoder->SetData(data_buffer.get(), true);
   EXPECT_EQ(2u, decoder->FrameCount());
   EXPECT_TRUE(decoder->FrameIsReceivedAtIndex(0));
   EXPECT_TRUE(decoder->FrameIsReceivedAtIndex(1));
@@ -217,17 +217,17 @@
       ReadFile(kDecodersTestingDir, "radient.gif");
   RefPtr<SharedBuffer> test_data =
       ReadFile(kDecodersTestingDir, "radient-bad-terminator.gif");
-  ASSERT_TRUE(reference_data.Get());
-  ASSERT_TRUE(test_data.Get());
+  ASSERT_TRUE(reference_data.get());
+  ASSERT_TRUE(test_data.get());
 
   std::unique_ptr<ImageDecoder> reference_decoder = CreateDecoder();
-  reference_decoder->SetData(reference_data.Get(), true);
+  reference_decoder->SetData(reference_data.get(), true);
   EXPECT_EQ(1u, reference_decoder->FrameCount());
   ImageFrame* reference_frame = reference_decoder->DecodeFrameBufferAtIndex(0);
   DCHECK(reference_frame);
 
   std::unique_ptr<ImageDecoder> test_decoder = CreateDecoder();
-  test_decoder->SetData(test_data.Get(), true);
+  test_decoder->SetData(test_data.get(), true);
   EXPECT_EQ(1u, test_decoder->FrameCount());
   ImageFrame* test_frame = test_decoder->DecodeFrameBufferAtIndex(0);
   DCHECK(test_frame);
@@ -273,10 +273,10 @@
 TEST(GIFImageDecoderTest, badInitialCode) {
   RefPtr<SharedBuffer> test_data =
       ReadFile(kDecodersTestingDir, "bad-initial-code.gif");
-  ASSERT_TRUE(test_data.Get());
+  ASSERT_TRUE(test_data.get());
 
   std::unique_ptr<ImageDecoder> test_decoder = CreateDecoder();
-  test_decoder->SetData(test_data.Get(), true);
+  test_decoder->SetData(test_data.get(), true);
   EXPECT_EQ(1u, test_decoder->FrameCount());
   ASSERT_TRUE(test_decoder->DecodeFrameBufferAtIndex(0));
   EXPECT_TRUE(test_decoder->Failed());
@@ -287,10 +287,10 @@
 TEST(GIFImageDecoderTest, badCode) {
   RefPtr<SharedBuffer> test_data =
       ReadFile(kDecodersTestingDir, "bad-code.gif");
-  ASSERT_TRUE(test_data.Get());
+  ASSERT_TRUE(test_data.get());
 
   std::unique_ptr<ImageDecoder> test_decoder = CreateDecoder();
-  test_decoder->SetData(test_data.Get(), true);
+  test_decoder->SetData(test_data.get(), true);
   EXPECT_EQ(1u, test_decoder->FrameCount());
   ASSERT_TRUE(test_decoder->DecodeFrameBufferAtIndex(0));
   EXPECT_TRUE(test_decoder->Failed());
@@ -302,8 +302,8 @@
   // The image has 2 frames, with disposal method 4 and 5, respectively.
   RefPtr<SharedBuffer> data =
       ReadFile(kDecodersTestingDir, "invalid-disposal-method.gif");
-  ASSERT_TRUE(data.Get());
-  decoder->SetData(data.Get(), true);
+  ASSERT_TRUE(data.get());
+  decoder->SetData(data.get(), true);
 
   EXPECT_EQ(2u, decoder->FrameCount());
   // Disposal method 4 is converted to ImageFrame::DisposeOverwritePrevious.
@@ -330,7 +330,7 @@
   for (size_t i = 1; i <= full_data.size(); ++i) {
     decoder = CreateDecoder();
     RefPtr<SharedBuffer> data = SharedBuffer::Create(full_data.data(), i);
-    decoder->SetData(data.Get(), i == full_data.size());
+    decoder->SetData(data.get(), i == full_data.size());
 
     if (decoder->IsSizeAvailable() && !frame_size.Width() &&
         !frame_size.Height()) {
@@ -351,7 +351,7 @@
 TEST(GIFImageDecoderTest, bitmapAlphaType) {
   RefPtr<SharedBuffer> full_data_buffer =
       ReadFile(kDecodersTestingDir, "radient.gif");
-  ASSERT_TRUE(full_data_buffer.Get());
+  ASSERT_TRUE(full_data_buffer.get());
   const Vector<char> full_data = full_data_buffer->Copy();
 
   // Empirically chosen truncation size:
@@ -373,9 +373,9 @@
 
   // Partially decoded frame => the frame alpha type is unknown and should
   // reflect the requested format.
-  premul_decoder->SetData(partial_data.Get(), false);
+  premul_decoder->SetData(partial_data.get(), false);
   ASSERT_TRUE(premul_decoder->FrameCount());
-  unpremul_decoder->SetData(partial_data.Get(), false);
+  unpremul_decoder->SetData(partial_data.get(), false);
   ASSERT_TRUE(unpremul_decoder->FrameCount());
   ImageFrame* premul_frame = premul_decoder->DecodeFrameBufferAtIndex(0);
   EXPECT_TRUE(premul_frame &&
@@ -387,9 +387,9 @@
   EXPECT_EQ(kUnpremul_SkAlphaType, unpremul_frame->Bitmap().alphaType());
 
   // Fully decoded frame => the frame alpha type is known (opaque).
-  premul_decoder->SetData(full_data_buffer.Get(), true);
+  premul_decoder->SetData(full_data_buffer.get(), true);
   ASSERT_TRUE(premul_decoder->FrameCount());
-  unpremul_decoder->SetData(full_data_buffer.Get(), true);
+  unpremul_decoder->SetData(full_data_buffer.get(), true);
   ASSERT_TRUE(unpremul_decoder->FrameCount());
   premul_frame = premul_decoder->DecodeFrameBufferAtIndex(0);
   EXPECT_TRUE(premul_frame &&
@@ -413,10 +413,10 @@
 // InitializeNewFrame.
 TEST(GIFImageDecoderTest, externalAllocator) {
   auto data = ReadFile(kLayoutTestResourcesDir, "boston.gif");
-  ASSERT_TRUE(data.Get());
+  ASSERT_TRUE(data.get());
 
   auto decoder = CreateDecoder();
-  decoder->SetData(data.Get(), true);
+  decoder->SetData(data.get(), true);
 
   Allocator allocator;
   decoder->SetMemoryAllocator(&allocator);
@@ -431,11 +431,11 @@
 
 TEST(GIFImageDecoderTest, recursiveDecodeFailure) {
   auto data = ReadFile(kLayoutTestResourcesDir, "count-down-color-test.gif");
-  ASSERT_TRUE(data.Get());
+  ASSERT_TRUE(data.get());
 
   {
     auto decoder = CreateDecoder();
-    decoder->SetData(data.Get(), true);
+    decoder->SetData(data.get(), true);
     for (size_t i = 0; i <= 3; ++i) {
       ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(i);
       ASSERT_NE(frame, nullptr);
@@ -452,7 +452,7 @@
                         data->size() - kErrorOffset - 1);
   {
     auto decoder = CreateDecoder();
-    decoder->SetData(modified_data.Get(), true);
+    decoder->SetData(modified_data.get(), true);
     decoder->DecodeFrameBufferAtIndex(2);
     ASSERT_TRUE(decoder->Failed());
   }
@@ -460,7 +460,7 @@
   {
     // Decode frame 3, recursively decoding frame 2, which 3 depends on.
     auto decoder = CreateDecoder();
-    decoder->SetData(modified_data.Get(), true);
+    decoder->SetData(modified_data.get(), true);
     ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(3);
     EXPECT_TRUE(decoder->Failed());
     ASSERT_NE(frame, nullptr);
diff --git a/third_party/WebKit/Source/platform/image-decoders/ico/ICOImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/ico/ICOImageDecoder.cpp
index 1b59ffe7..ed2581374 100644
--- a/third_party/WebKit/Source/platform/image-decoders/ico/ICOImageDecoder.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/ico/ICOImageDecoder.cpp
@@ -150,7 +150,7 @@
   if (!png_decoders_[index])
     return;
 
-  png_decoders_[index]->SetData(data_.Get(), IsAllDataReceived());
+  png_decoders_[index]->SetData(data_.get(), IsAllDataReceived());
 }
 
 void ICOImageDecoder::Decode(size_t index, bool only_size) {
@@ -199,7 +199,7 @@
     if (!bmp_readers_[index]) {
       bmp_readers_[index] = WTF::WrapUnique(
           new BMPImageReader(this, dir_entry.image_offset_, 0, true));
-      bmp_readers_[index]->SetData(data_.Get());
+      bmp_readers_[index]->SetData(data_.get());
     }
     // Update the pointer to the buffer as it could change after
     // frame_buffer_cache_.resize().
diff --git a/third_party/WebKit/Source/platform/image-decoders/ico/ICOImageDecoderTest.cpp b/third_party/WebKit/Source/platform/image-decoders/ico/ICOImageDecoderTest.cpp
index f2efa63..c0d96eb6 100644
--- a/third_party/WebKit/Source/platform/image-decoders/ico/ICOImageDecoderTest.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/ico/ICOImageDecoderTest.cpp
@@ -29,11 +29,11 @@
       SharedBuffer::Create(data.data(), data.size() / 2);
   auto decoder = CreateICODecoder();
 
-  decoder->SetData(truncated_data.Get(), false);
+  decoder->SetData(truncated_data.get(), false);
   decoder->DecodeFrameBufferAtIndex(0);
   EXPECT_FALSE(decoder->Failed());
 
-  decoder->SetData(truncated_data.Get(), true);
+  decoder->SetData(truncated_data.get(), true);
   decoder->DecodeFrameBufferAtIndex(0);
   EXPECT_TRUE(decoder->Failed());
 }
@@ -54,7 +54,7 @@
                         data.size() - kCrcOffset - kCrcSize);
 
   auto decoder = CreateICODecoder();
-  decoder->SetData(modified_data.Get(), true);
+  decoder->SetData(modified_data.get(), true);
 
   // ICOImageDecoder reports the frame count based on whether enough data has
   // been received according to the icon directory. So even though the
@@ -100,7 +100,7 @@
       SharedBuffer::Create(ico_file_data->Data(), kSizeOfBadBlock);
   auto decoder = CreateICODecoder();
 
-  decoder->SetData(truncated_data.Get(), false);
+  decoder->SetData(truncated_data.get(), false);
   decoder->SetMemoryAllocator(nullptr);
   EXPECT_FALSE(decoder->Failed());
 
diff --git a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
index 9f61f8e..896ff99 100644
--- a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
@@ -376,7 +376,7 @@
   }
 
   void SetData(SegmentReader* data) {
-    if (data_.Get() == data)
+    if (data_.get() == data)
       return;
 
     data_ = data;
@@ -1033,7 +1033,7 @@
 
   if (!reader_) {
     reader_ = WTF::MakeUnique<JPEGImageReader>(this);
-    reader_->SetData(data_.Get());
+    reader_->SetData(data_.get());
   }
 
   // If we couldn't decode the image but have received all the data, decoding
diff --git a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoderTest.cpp b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoderTest.cpp
index 9c592b7..8ef6464 100644
--- a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoderTest.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoderTest.cpp
@@ -66,7 +66,7 @@
   ASSERT_TRUE(data);
 
   std::unique_ptr<ImageDecoder> decoder = CreateJPEGDecoder(max_decoded_bytes);
-  decoder->SetData(data.Get(), true);
+  decoder->SetData(data.get(), true);
 
   ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0);
   ASSERT_TRUE(frame);
@@ -85,7 +85,7 @@
   ASSERT_TRUE(data);
 
   std::unique_ptr<ImageDecoder> decoder = CreateJPEGDecoder(max_decoded_bytes);
-  decoder->SetData(data.Get(), true);
+  decoder->SetData(data.get(), true);
 
   // Setting a dummy ImagePlanes object signals to the decoder that we want to
   // do YUV decoding.
@@ -260,7 +260,7 @@
   ASSERT_TRUE(data);
 
   std::unique_ptr<ImageDecoder> decoder = CreateJPEGDecoder(230 * 230 * 4);
-  decoder->SetData(data.Get(), true);
+  decoder->SetData(data.get(), true);
 
   std::unique_ptr<ImagePlanes> image_planes = WTF::MakeUnique<ImagePlanes>();
   decoder->SetImagePlanes(std::move(image_planes));
@@ -303,10 +303,10 @@
 TEST(JPEGImageDecoderTest, manyProgressiveScans) {
   RefPtr<SharedBuffer> test_data =
       ReadFile(kDecodersTestingDir, "many-progressive-scans.jpg");
-  ASSERT_TRUE(test_data.Get());
+  ASSERT_TRUE(test_data.get());
 
   std::unique_ptr<ImageDecoder> test_decoder = CreateJPEGDecoder();
-  test_decoder->SetData(test_data.Get(), true);
+  test_decoder->SetData(test_data.get(), true);
   EXPECT_EQ(1u, test_decoder->FrameCount());
   ASSERT_TRUE(test_decoder->DecodeFrameBufferAtIndex(0));
   EXPECT_TRUE(test_decoder->Failed());
@@ -319,7 +319,7 @@
 
   std::unique_ptr<ImageDecoder> decoder =
       CreateJPEGDecoder(std::numeric_limits<int>::max());
-  decoder->SetData(data.Get(), true);
+  decoder->SetData(data.get(), true);
   // This will decode the size and needs to be called to avoid DCHECKs
   ASSERT_TRUE(decoder->IsSizeAvailable());
   std::vector<SkISize> expected_sizes = {
@@ -345,7 +345,7 @@
 
   std::unique_ptr<ImageDecoder> decoder =
       CreateJPEGDecoder(std::numeric_limits<int>::max());
-  decoder->SetData(data.Get(), true);
+  decoder->SetData(data.get(), true);
   // This will decode the size and needs to be called to avoid DCHECKs
   ASSERT_TRUE(decoder->IsSizeAvailable());
   std::vector<SkISize> expected_sizes = {
@@ -370,7 +370,7 @@
 
   // Limit the memory so that 128 would be the largest size possible.
   std::unique_ptr<ImageDecoder> decoder = CreateJPEGDecoder(130 * 130 * 4);
-  decoder->SetData(data.Get(), true);
+  decoder->SetData(data.get(), true);
   // This will decode the size and needs to be called to avoid DCHECKs
   ASSERT_TRUE(decoder->IsSizeAvailable());
   std::vector<SkISize> expected_sizes = {
diff --git a/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoderTest.cpp b/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoderTest.cpp
index 7168f3cb..eedd143 100644
--- a/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoderTest.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoderTest.cpp
@@ -48,7 +48,7 @@
   auto decoder = CreatePNGDecoder();
   auto data = ReadFile(png_file);
   EXPECT_FALSE(data->IsEmpty());
-  decoder->SetData(data.Get(), true);
+  decoder->SetData(data.get(), true);
   return decoder;
 }
 
@@ -72,7 +72,7 @@
   RefPtr<SharedBuffer> partial_data = SharedBuffer::Create();
   for (size_t length = 1; length <= bytes_needed_to_decode_size; length++) {
     partial_data->Append(source++, 1u);
-    decoder->SetData(partial_data.Get(), false);
+    decoder->SetData(partial_data.get(), false);
 
     if (length < bytes_needed_to_decode_size) {
       EXPECT_FALSE(decoder->IsSizeAvailable());
@@ -231,7 +231,7 @@
   ASSERT_FALSE(full_data->IsEmpty());
 
   auto decoder_upfront = CreatePNGDecoder();
-  decoder_upfront->SetData(full_data.Get(), true);
+  decoder_upfront->SetData(full_data.get(), true);
   EXPECT_GE(decoder_upfront->FrameCount(), 1u);
   const ImageFrame* const frame_upfront =
       decoder_upfront->DecodeFrameBufferAtIndex(0);
@@ -248,7 +248,7 @@
   EXPECT_EQ(frame->GetStatus(), ImageFrame::kFramePartial);
   const unsigned hash_partial = HashBitmap(frame->Bitmap());
 
-  decoder->SetData(full_data.Get(), true);
+  decoder->SetData(full_data.get(), true);
   frame = decoder->DecodeFrameBufferAtIndex(0);
   EXPECT_EQ(frame->GetStatus(), ImageFrame::kFrameComplete);
   const unsigned hash_full = HashBitmap(frame->Bitmap());
@@ -278,7 +278,7 @@
                full_data->size() - idat_offset - 16u);
 
   auto decoder = CreatePNGDecoder();
-  decoder->SetData(data.Get(), true);
+  decoder->SetData(data.get(), true);
 
   EXPECT_EQ(expected_frame_count, decoder->FrameCount());
 
@@ -378,7 +378,7 @@
   for (size_t length = 1; length <= frame_offsets[kExpectedFrameCount - 1];
        length++) {
     partial_data->Append(source++, 1u);
-    decoder->SetData(partial_data.Get(), false);
+    decoder->SetData(partial_data.get(), false);
     EXPECT_FALSE(decoder->Failed());
     if (length < frame_offsets[frames_parsed]) {
       EXPECT_EQ(frames_parsed, decoder->FrameCount());
@@ -539,7 +539,7 @@
   {
     // This broken APNG will be treated as a static png.
     auto decoder = CreatePNGDecoder();
-    decoder->SetData(modified_data.Get(), true);
+    decoder->SetData(modified_data.get(), true);
     ExpectStatic(decoder.get());
   }
 
@@ -553,7 +553,7 @@
     modified_data2->Append(modified_data->Data() + kOffsetActl + kAcTLSize,
                            modified_data->size() - kOffsetActl - kAcTLSize);
     auto decoder = CreatePNGDecoder();
-    decoder->SetData(modified_data2.Get(), true);
+    decoder->SetData(modified_data2.get(), true);
     ExpectStatic(decoder.get());
 
     // Likewise, if an acTL follows the fdAT, it is ignored.
@@ -564,7 +564,7 @@
     modified_data3->Append(modified_data2->Data() + kInsertionOffset,
                            modified_data2->size() - kInsertionOffset);
     decoder = CreatePNGDecoder();
-    decoder->SetData(modified_data3.Get(), true);
+    decoder->SetData(modified_data3.get(), true);
     ExpectStatic(decoder.get());
   }
 }
@@ -592,7 +592,7 @@
   modified_data->Append(data->Data() + kAfterFctl, data->size() - kAfterFctl);
 
   auto decoder = CreatePNGDecoder();
-  decoder->SetData(modified_data.Get(), true);
+  decoder->SetData(modified_data.get(), true);
   ExpectStatic(decoder.get());
 }
 
@@ -681,14 +681,14 @@
   const size_t kExpectedFramesAfter249Bytes = 2;
   RefPtr<SharedBuffer> temp_data =
       SharedBuffer::Create(full_data->Data(), kOffsetTwoFrames);
-  decoder->SetData(temp_data.Get(), false);
+  decoder->SetData(temp_data.get(), false);
   EXPECT_EQ(kExpectedFramesAfter249Bytes, decoder->FrameCount());
   EXPECT_FALSE(decoder->Failed());
 
   // Provide the rest of the data except for the last IEND chunk.
   const size_t kExpectedFramesAfterAllExcept12Bytes = 3;
   temp_data = SharedBuffer::Create(full_data->Data(), full_data->size() - 12);
-  decoder->SetData(temp_data.Get(), true);
+  decoder->SetData(temp_data.get(), true);
   ASSERT_EQ(kExpectedFramesAfterAllExcept12Bytes, decoder->FrameCount());
 
   for (size_t i = 0; i < kExpectedFramesAfterAllExcept12Bytes; i++) {
@@ -731,7 +731,7 @@
   data->Append(full_data->Data() + full_data->size() - 12u, 12u);
   data->Append(full_data->Data() + kOffsetIDAT,
                full_data->size() - kOffsetIDAT);
-  decoder->SetData(data.Get(), true);
+  decoder->SetData(data.get(), true);
 
   const size_t kExpectedFrameCount = 0u;
   EXPECT_EQ(kExpectedFrameCount, decoder->FrameCount());
@@ -761,7 +761,7 @@
   data->Append(full_data->Data() + kIENDOffset,
                full_data->size() - kIENDOffset);
   auto decoder = CreatePNGDecoder();
-  decoder->SetData(data.Get(), true);
+  decoder->SetData(data.get(), true);
   decoder->FrameCount();
   EXPECT_TRUE(decoder->Failed());
 
@@ -773,7 +773,7 @@
   // Append the rest.
   data->Append(full_data->Data() + kPostIDAT, full_data->size() - kPostIDAT);
   decoder = CreatePNGDecoder();
-  decoder->SetData(data.Get(), true);
+  decoder->SetData(data.get(), true);
   decoder->FrameCount();
   EXPECT_TRUE(decoder->Failed());
 }
@@ -806,7 +806,7 @@
   data->Append(full_data->Data() + kOffsetDisposalOp + 6u,
                full_data->size() - kOffsetDisposalOp - 6u);
 
-  decoder->SetData(data.Get(), true);
+  decoder->SetData(data.get(), true);
   decoder->FrameCount();
   ASSERT_TRUE(decoder->Failed());
 }
@@ -833,13 +833,13 @@
   const size_t kMiddleFirstFrame = 160u;
   RefPtr<SharedBuffer> data =
       SharedBuffer::Create(full_data->Data(), kMiddleFirstFrame);
-  decoder->SetData(data.Get(), false);
+  decoder->SetData(data.get(), false);
 
   ASSERT_EQ(1u, decoder->FrameCount());
   ASSERT_EQ(ImageFrame::kFramePartial,
             decoder->DecodeFrameBufferAtIndex(0)->GetStatus());
 
-  decoder->SetData(full_data.Get(), true);
+  decoder->SetData(full_data.get(), true);
   ASSERT_EQ(3u, decoder->FrameCount());
   ASSERT_EQ(ImageFrame::kFrameComplete,
             decoder->DecodeFrameBufferAtIndex(1)->GetStatus());
@@ -882,7 +882,7 @@
   ASSERT_EQ(original_data->size(), data->size());
 
   auto decoder = CreatePNGDecoder();
-  decoder->SetData(data.Get(), true);
+  decoder->SetData(data.get(), true);
 
   ASSERT_EQ(4u, decoder->FrameCount());
   ASSERT_FALSE(decoder->Failed());
@@ -901,7 +901,7 @@
 
   // Now decode starting from frame 1.
   decoder = CreatePNGDecoder();
-  decoder->SetData(data.Get(), true);
+  decoder->SetData(data.get(), true);
 
   frame = decoder->DecodeFrameBufferAtIndex(1);
   ASSERT_TRUE(frame);
@@ -938,7 +938,7 @@
   ASSERT_EQ(original_data->size(), data->size());
 
   // This will test both byte by byte and using the full data, and compare.
-  TestByteByByteDecode(CreatePNGDecoder, data.Get(), 1, kAnimationNone);
+  TestByteByByteDecode(CreatePNGDecoder, data.get(), 1, kAnimationNone);
 }
 
 // Static PNG tests
@@ -1001,13 +1001,13 @@
   };
   for (const auto& rec : g_recs) {
     auto full_data = ReadFile(rec.name);
-    ASSERT_TRUE(full_data.Get());
+    ASSERT_TRUE(full_data.get());
 
     // Create with enough data for part of the first frame.
     auto decoder = CreatePNGDecoder();
     auto data =
         SharedBuffer::Create(full_data->Data(), rec.offset_in_first_frame);
-    decoder->SetData(data.Get(), false);
+    decoder->SetData(data.get(), false);
 
     EXPECT_FALSE(decoder->FrameIsReceivedAtIndex(0));
 
@@ -1025,7 +1025,7 @@
     EXPECT_NE(ImageFrame::kFrameComplete, frame->GetStatus());
     EXPECT_FALSE(decoder->FrameIsReceivedAtIndex(0));
 
-    decoder->SetData(full_data.Get(), true);
+    decoder->SetData(full_data.get(), true);
 
     // With full data, parsing the size still does not mark a frame as
     // complete for animated images.
diff --git a/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoderTest.cpp b/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoderTest.cpp
index 3df8c9d..b5a2bbf 100644
--- a/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoderTest.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoderTest.cpp
@@ -71,8 +71,8 @@
   std::unique_ptr<ImageDecoder> decoder = CreateWEBPDecoder();
 
   RefPtr<SharedBuffer> data = ReadFile(webp_file);
-  ASSERT_TRUE(data.Get());
-  decoder->SetData(data.Get(), true);
+  ASSERT_TRUE(data.get());
+  decoder->SetData(data.get(), true);
 
   if (parse_error_expected) {
     EXPECT_EQ(0u, decoder->FrameCount());
@@ -94,8 +94,8 @@
 
   RefPtr<SharedBuffer> data =
       ReadFile("/LayoutTests/images/resources/webp-animated.webp");
-  ASSERT_TRUE(data.Get());
-  decoder->SetData(data.Get(), true);
+  ASSERT_TRUE(data.get());
+  decoder->SetData(data.get(), true);
 
   ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0);
   uint32_t generation_id0 = frame->Bitmap().getGenerationID();
@@ -111,8 +111,8 @@
 
   RefPtr<SharedBuffer> data =
       ReadFile("/LayoutTests/images/resources/webp-animated.webp");
-  ASSERT_TRUE(data.Get());
-  decoder->SetData(data.Get(), true);
+  ASSERT_TRUE(data.get());
+  decoder->SetData(data.get(), true);
 
   const int kCanvasWidth = 11;
   const int kCanvasHeight = 29;
@@ -155,8 +155,8 @@
 
   RefPtr<SharedBuffer> data =
       ReadFile("/LayoutTests/images/resources/webp-animated-opaque.webp");
-  ASSERT_TRUE(data.Get());
-  decoder->SetData(data.Get(), true);
+  ASSERT_TRUE(data.get());
+  decoder->SetData(data.get(), true);
 
   const int kCanvasWidth = 94;
   const int kCanvasHeight = 87;
@@ -201,8 +201,8 @@
 
   RefPtr<SharedBuffer> data =
       ReadFile("/LayoutTests/images/resources/webp-animated-no-blend.webp");
-  ASSERT_TRUE(data.Get());
-  decoder->SetData(data.Get(), true);
+  ASSERT_TRUE(data.get());
+  decoder->SetData(data.get(), true);
 
   const int kCanvasWidth = 94;
   const int kCanvasHeight = 87;
@@ -260,8 +260,8 @@
 
   RefPtr<SharedBuffer> data =
       ReadFile("/LayoutTests/images/resources/invalid-animated-webp2.webp");
-  ASSERT_TRUE(data.Get());
-  decoder->SetData(data.Get(), true);
+  ASSERT_TRUE(data.get());
+  decoder->SetData(data.get(), true);
 
   size_t frame_count = 8;
   EXPECT_EQ(frame_count, decoder->FrameCount());
@@ -286,7 +286,7 @@
           ->Copy();
   RefPtr<SharedBuffer> data =
       SharedBuffer::Create(full_data.data(), full_data.size() - 1);
-  decoder->SetData(data.Get(), false);
+  decoder->SetData(data.get(), false);
 
   ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(1);
   ASSERT_TRUE(frame);
@@ -304,7 +304,7 @@
 
   RefPtr<SharedBuffer> full_data_buffer =
       ReadFile("/LayoutTests/images/resources/invalid_vp8_vp8x.webp");
-  ASSERT_TRUE(full_data_buffer.Get());
+  ASSERT_TRUE(full_data_buffer.get());
   const Vector<char> full_data = full_data_buffer->Copy();
 
   // Parse partial data up to which error in bitstream is not detected.
@@ -312,7 +312,7 @@
   ASSERT_GT(full_data.size(), kPartialSize);
   RefPtr<SharedBuffer> data =
       SharedBuffer::Create(full_data.data(), kPartialSize);
-  decoder->SetData(data.Get(), false);
+  decoder->SetData(data.get(), false);
   EXPECT_EQ(1u, decoder->FrameCount());
   ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0);
   ASSERT_TRUE(frame);
@@ -320,7 +320,7 @@
   EXPECT_FALSE(decoder->Failed());
 
   // Parse full data now. The error in bitstream should now be detected.
-  decoder->SetData(full_data_buffer.Get(), true);
+  decoder->SetData(full_data_buffer.get(), true);
   EXPECT_EQ(1u, decoder->FrameCount());
   frame = decoder->DecodeFrameBufferAtIndex(0);
   ASSERT_TRUE(frame);
@@ -339,13 +339,13 @@
 
   RefPtr<SharedBuffer> data_buffer =
       ReadFile("/LayoutTests/images/resources/webp-animated.webp");
-  ASSERT_TRUE(data_buffer.Get());
+  ASSERT_TRUE(data_buffer.get());
   const Vector<char> data = data_buffer->Copy();
 
   ASSERT_GE(data.size(), 10u);
   RefPtr<SharedBuffer> temp_data =
       SharedBuffer::Create(data.data(), data.size() - 10);
-  decoder->SetData(temp_data.Get(), false);
+  decoder->SetData(temp_data.get(), false);
 
   EXPECT_EQ(2u, decoder->FrameCount());
   EXPECT_FALSE(decoder->Failed());
@@ -355,7 +355,7 @@
   EXPECT_TRUE(decoder->FrameIsReceivedAtIndex(1));
   EXPECT_EQ(TimeDelta::FromMilliseconds(500), decoder->FrameDurationAtIndex(1));
 
-  decoder->SetData(data_buffer.Get(), true);
+  decoder->SetData(data_buffer.get(), true);
   EXPECT_EQ(3u, decoder->FrameCount());
   EXPECT_TRUE(decoder->FrameIsReceivedAtIndex(0));
   EXPECT_EQ(TimeDelta::FromMilliseconds(1000),
@@ -450,8 +450,8 @@
 
   RefPtr<SharedBuffer> full_data =
       ReadFile("/LayoutTests/images/resources/webp-animated.webp");
-  ASSERT_TRUE(full_data.Get());
-  decoder->SetData(full_data.Get(), true);
+  ASSERT_TRUE(full_data.get());
+  decoder->SetData(full_data.get(), true);
 
   ASSERT_EQ(3u, decoder->FrameCount());
   // We need to store pointers to the image frames, since calling
@@ -550,8 +550,8 @@
   std::unique_ptr<ImageDecoder> decoder = CreateWEBPDecoder();
   RefPtr<SharedBuffer> data =
       ReadFile("/LayoutTests/images/resources/webp-color-profile-lossy.webp");
-  ASSERT_TRUE(data.Get());
-  decoder->SetData(data.Get(), true);
+  ASSERT_TRUE(data.get());
+  decoder->SetData(data.get(), true);
   EXPECT_EQ(1u, decoder->FrameCount());
   EXPECT_EQ(kAnimationNone, decoder->RepetitionCount());
 }
diff --git a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
index 319d25c8..4542512 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
@@ -577,7 +577,7 @@
   response_ = response;
   if (this->GetResponse().WasFetchedViaServiceWorker()) {
     cache_handler_ = ServiceWorkerResponseCachedMetadataHandler::Create(
-        this, fetcher_security_origin_.Get());
+        this, fetcher_security_origin_.get());
   }
 }
 
diff --git a/third_party/WebKit/Source/platform/loader/fetch/Resource.h b/third_party/WebKit/Source/platform/loader/fetch/Resource.h
index 74666d6..4d34fb5 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/Resource.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/Resource.h
@@ -389,7 +389,7 @@
   void SetPreviewsState(WebURLRequest::PreviewsState);
   void ClearRangeRequestHeader();
 
-  SharedBuffer* Data() const { return data_.Get(); }
+  SharedBuffer* Data() const { return data_.get(); }
   void ClearData();
 
   void TriggerNotificationForFinishObservers();
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
index 5423904..fc319f4 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
@@ -359,7 +359,7 @@
     RefPtr<ResourceTimingInfo> info = ResourceTimingInfo::Create(
         params.Options().initiator_info.name, MonotonicallyIncreasingTime(),
         resource->GetType() == Resource::kMainResource);
-    PopulateTimingInfo(info.Get(), resource);
+    PopulateTimingInfo(info.get(), resource);
     info->ClearLoadTimings();
     info->SetLoadFinishTime(info->InitialTime());
     scheduled_resource_timing_reports_.push_back(std::move(info));
@@ -884,7 +884,7 @@
   }
 
   if (!is_main_resource ||
-      Context().UpdateTimingInfoForIFrameNavigation(info.Get())) {
+      Context().UpdateTimingInfoForIFrameNavigation(info.get())) {
     resource_timing_info_map_.insert(resource, std::move(info));
   }
 }
@@ -1306,7 +1306,7 @@
 }
 
 ResourceTimingInfo* ResourceFetcher::GetNavigationTimingInfo() {
-  return navigation_timing_info_.Get();
+  return navigation_timing_info_.get();
 }
 
 void ResourceFetcher::HandleLoadCompletion(Resource* resource) {
@@ -1337,9 +1337,9 @@
   if (resource->GetType() == Resource::kMainResource) {
     DCHECK(navigation_timing_info_);
     // Store redirect responses that were packed inside the final response.
-    AddRedirectsToTimingInfo(resource, navigation_timing_info_.Get());
+    AddRedirectsToTimingInfo(resource, navigation_timing_info_.get());
     if (resource->GetResponse().IsHTTP()) {
-      PopulateTimingInfo(navigation_timing_info_.Get(), resource);
+      PopulateTimingInfo(navigation_timing_info_.get(), resource);
       navigation_timing_info_->AddFinalTransferSize(
           encoded_data_length == -1 ? 0 : encoded_data_length);
     }
@@ -1347,11 +1347,11 @@
   if (RefPtr<ResourceTimingInfo> info =
           resource_timing_info_map_.Take(resource)) {
     // Store redirect responses that were packed inside the final response.
-    AddRedirectsToTimingInfo(resource, info.Get());
+    AddRedirectsToTimingInfo(resource, info.get());
 
     if (resource->GetResponse().IsHTTP() &&
         resource->GetResponse().HttpStatusCode() < 400) {
-      PopulateTimingInfo(info.Get(), resource);
+      PopulateTimingInfo(info.get(), resource);
       info->SetLoadFinishTime(finish_time);
       // encodedDataLength == -1 means "not available".
       // TODO(ricea): Find cases where it is not available but the
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp
index 6ac4ffee..fba1744 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp
@@ -271,9 +271,9 @@
             kEnableCORSHandlingByResourceFetcher &&
         fetch_request_mode == WebURLRequest::kFetchRequestModeCORS) {
       RefPtr<SecurityOrigin> source_origin = options.security_origin;
-      if (!source_origin.Get())
+      if (!source_origin.get())
         source_origin = Context().GetSecurityOrigin();
-      WebSecurityOrigin source_web_origin(source_origin.Get());
+      WebSecurityOrigin source_web_origin(source_origin.get());
       WrappedResourceRequest new_request_wrapper(new_request);
       WebString cors_error_msg;
       if (!WebCORS::HandleRedirect(
@@ -400,7 +400,7 @@
   if (resource_->GetType() == Resource::Type::kMainResource)
     return CORSStatus::kNotApplicable;
 
-  SecurityOrigin* source_origin = resource_->Options().security_origin.Get();
+  SecurityOrigin* source_origin = resource_->Options().security_origin.get();
 
   if (!source_origin)
     source_origin = Context().GetSecurityOrigin();
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceLoaderOptionsTest.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceLoaderOptionsTest.cpp
index fbb6586..1e2ca21 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceLoaderOptionsTest.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceLoaderOptionsTest.cpp
@@ -59,7 +59,7 @@
   // Check that pointers are different between |original| and |copyData|
   EXPECT_NE(original.initiator_info.name.Impl(),
             copy_data.initiator_info.name.Impl());
-  EXPECT_NE(original.security_origin.Get(), copy_data.security_origin.Get());
+  EXPECT_NE(original.security_origin.get(), copy_data.security_origin.get());
   EXPECT_NE(original.security_origin->Protocol().Impl(),
             copy_data.security_origin->Protocol().Impl());
   EXPECT_NE(original.security_origin->Host().Impl(),
@@ -89,7 +89,7 @@
   //           copy.initiatorInfo.name.impl());
   // should pass. However, in the unit test here, these two pointers are the
   // same, because initiatorInfo.name is AtomicString.
-  EXPECT_NE(original.security_origin.Get(), copy.security_origin.Get());
+  EXPECT_NE(original.security_origin.get(), copy.security_origin.get());
   EXPECT_NE(original.security_origin->Protocol().Impl(),
             copy.security_origin->Protocol().Impl());
   EXPECT_NE(original.security_origin->Host().Impl(),
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp
index ece439c..c7b26f8 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp
@@ -287,7 +287,7 @@
 
 void ResourceRequest::AddHTTPOriginIfNeeded(const String& origin_string) {
   if (NeedsHTTPOrigin())
-    SetHTTPOrigin(SecurityOrigin::CreateFromString(origin_string).Get());
+    SetHTTPOrigin(SecurityOrigin::CreateFromString(origin_string).get());
 }
 
 void ResourceRequest::ClearHTTPUserAgent() {
@@ -295,7 +295,7 @@
 }
 
 EncodedFormData* ResourceRequest::HttpBody() const {
-  return http_body_.Get();
+  return http_body_.get();
 }
 
 void ResourceRequest::SetHTTPBody(RefPtr<EncodedFormData> http_body) {
@@ -303,7 +303,7 @@
 }
 
 EncodedFormData* ResourceRequest::AttachedCredential() const {
-  return attached_credential_.Get();
+  return attached_credential_.get();
 }
 
 void ResourceRequest::SetAttachedCredential(
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.h b/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.h
index ae038fe2..0fa19ab 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.h
@@ -240,7 +240,7 @@
   }
 
   // Extra data associated with this request.
-  ExtraData* GetExtraData() const { return extra_data_.Get(); }
+  ExtraData* GetExtraData() const { return extra_data_.get(); }
   void SetExtraData(RefPtr<ExtraData> extra_data) {
     extra_data_ = std::move(extra_data);
   }
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.cpp
index cf745bc..c09cfd70 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.cpp
@@ -554,7 +554,7 @@
 }
 
 ResourceLoadTiming* ResourceResponse::GetResourceLoadTiming() const {
-  return resource_load_timing_.Get();
+  return resource_load_timing_.get();
 }
 
 void ResourceResponse::SetResourceLoadTiming(
@@ -563,7 +563,7 @@
 }
 
 RefPtr<ResourceLoadInfo> ResourceResponse::GetResourceLoadInfo() const {
-  return resource_load_info_.Get();
+  return resource_load_info_.get();
 }
 
 void ResourceResponse::SetResourceLoadInfo(RefPtr<ResourceLoadInfo> load_info) {
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.h b/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.h
index eb99edd..050e4140 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.h
@@ -381,7 +381,7 @@
   void SetDownloadedFilePath(const String&);
 
   // Extra data associated with this response.
-  ExtraData* GetExtraData() const { return extra_data_.Get(); }
+  ExtraData* GetExtraData() const { return extra_data_.get(); }
   void SetExtraData(RefPtr<ExtraData> extra_data) {
     extra_data_ = std::move(extra_data);
   }
diff --git a/third_party/WebKit/Source/platform/loader/fetch/SubstituteData.h b/third_party/WebKit/Source/platform/loader/fetch/SubstituteData.h
index 200eb500..a14bf84e 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/SubstituteData.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/SubstituteData.h
@@ -51,9 +51,9 @@
         text_encoding_(text_encoding),
         failing_url_(failing_url) {}
 
-  bool IsValid() const { return content_.Get(); }
+  bool IsValid() const { return content_.get(); }
 
-  SharedBuffer* Content() const { return content_.Get(); }
+  SharedBuffer* Content() const { return content_.get(); }
   const AtomicString& MimeType() const { return mime_type_; }
   const AtomicString& TextEncoding() const { return text_encoding_; }
   const KURL& FailingURL() const { return failing_url_; }
diff --git a/third_party/WebKit/Source/platform/loader/testing/MockFetchContext.h b/third_party/WebKit/Source/platform/loader/testing/MockFetchContext.h
index 0a1410b4..9470784 100644
--- a/third_party/WebKit/Source/platform/loader/testing/MockFetchContext.h
+++ b/third_party/WebKit/Source/platform/loader/testing/MockFetchContext.h
@@ -40,7 +40,7 @@
   long long GetTransferSize() const { return transfer_size_; }
 
   SecurityOrigin* GetSecurityOrigin() const override {
-    return security_origin_.Get();
+    return security_origin_.get();
   }
 
   void SetSecurityOrigin(RefPtr<SecurityOrigin> security_origin) {
diff --git a/third_party/WebKit/Source/platform/mediastream/MediaStreamCenter.cpp b/third_party/WebKit/Source/platform/mediastream/MediaStreamCenter.cpp
index e48fafb..9e98c1f 100644
--- a/third_party/WebKit/Source/platform/mediastream/MediaStreamCenter.cpp
+++ b/third_party/WebKit/Source/platform/mediastream/MediaStreamCenter.cpp
@@ -41,6 +41,7 @@
 #include "public/platform/WebAudioSourceProvider.h"
 #include "public/platform/WebMediaStream.h"
 #include "public/platform/WebMediaStreamCenter.h"
+#include "public/platform/WebMediaStreamSource.h"
 #include "public/platform/WebMediaStreamTrack.h"
 
 namespace blink {
@@ -116,6 +117,11 @@
   return nullptr;
 }
 
+void MediaStreamCenter::DidStopMediaStreamSource(MediaStreamSource* source) {
+  if (private_)
+    private_->DidStopMediaStreamSource(source);
+}
+
 void MediaStreamCenter::StopLocalMediaStream(const WebMediaStream& web_stream) {
   MediaStreamDescriptor* stream = web_stream;
   MediaStreamDescriptorClient* client = stream->Client();
diff --git a/third_party/WebKit/Source/platform/mediastream/MediaStreamCenter.h b/third_party/WebKit/Source/platform/mediastream/MediaStreamCenter.h
index 474e2ac..dad0262 100644
--- a/third_party/WebKit/Source/platform/mediastream/MediaStreamCenter.h
+++ b/third_party/WebKit/Source/platform/mediastream/MediaStreamCenter.h
@@ -44,6 +44,7 @@
 class AudioSourceProvider;
 class MediaStreamComponent;
 class MediaStreamDescriptor;
+class MediaStreamSource;
 class WebMediaStream;
 class WebMediaStreamCenter;
 
@@ -69,6 +70,8 @@
   void DidCreateMediaStreamAndTracks(MediaStreamDescriptor*);
   void DidStopLocalMediaStream(MediaStreamDescriptor*);
 
+  void DidStopMediaStreamSource(MediaStreamSource*);
+
   // blink::WebMediaStreamCenterClient
   void StopLocalMediaStream(const WebMediaStream&) override;
 
diff --git a/third_party/WebKit/Source/platform/mhtml/ArchiveResource.h b/third_party/WebKit/Source/platform/mhtml/ArchiveResource.h
index 1079b616..09c236d 100644
--- a/third_party/WebKit/Source/platform/mhtml/ArchiveResource.h
+++ b/third_party/WebKit/Source/platform/mhtml/ArchiveResource.h
@@ -50,7 +50,7 @@
 
   const KURL& Url() const { return url_; }
   const String& ContentID() const { return content_id_; }
-  SharedBuffer* Data() const { return data_.Get(); }
+  SharedBuffer* Data() const { return data_.get(); }
   const AtomicString& MimeType() const { return mime_type_; }
   const AtomicString& TextEncoding() const { return text_encoding_; }
 
diff --git a/third_party/WebKit/Source/platform/mojo/KURLSecurityOriginTest.cpp b/third_party/WebKit/Source/platform/mojo/KURLSecurityOriginTest.cpp
index 0530ea8..ba6d825 100644
--- a/third_party/WebKit/Source/platform/mojo/KURLSecurityOriginTest.cpp
+++ b/third_party/WebKit/Source/platform/mojo/KURLSecurityOriginTest.cpp
@@ -78,8 +78,8 @@
       SecurityOrigin::Create("http", "www.google.com", 80);
   RefPtr<SecurityOrigin> output;
   EXPECT_TRUE(proxy->BounceOrigin(non_unique, &output));
-  EXPECT_TRUE(non_unique->IsSameSchemeHostPortAndSuborigin(output.Get()));
-  EXPECT_TRUE(non_unique->IsSameSchemeHostPort(output.Get()));
+  EXPECT_TRUE(non_unique->IsSameSchemeHostPortAndSuborigin(output.get()));
+  EXPECT_TRUE(non_unique->IsSameSchemeHostPort(output.get()));
   EXPECT_FALSE(output->HasSuborigin());
   EXPECT_FALSE(output->IsUnique());
 
@@ -90,8 +90,8 @@
   RefPtr<SecurityOrigin> with_sub_origin =
       SecurityOrigin::Create("http", "www.google.com", 80, "suborigin");
   EXPECT_TRUE(proxy->BounceOrigin(with_sub_origin, &output));
-  EXPECT_TRUE(with_sub_origin->IsSameSchemeHostPortAndSuborigin(output.Get()));
-  EXPECT_TRUE(with_sub_origin->IsSameSchemeHostPort(output.Get()));
+  EXPECT_TRUE(with_sub_origin->IsSameSchemeHostPortAndSuborigin(output.get()));
+  EXPECT_TRUE(with_sub_origin->IsSameSchemeHostPort(output.get()));
   EXPECT_TRUE(output->HasSuborigin());
   EXPECT_FALSE(output->IsUnique());
 }
diff --git a/third_party/WebKit/Source/platform/network/EncodedFormDataTest.cpp b/third_party/WebKit/Source/platform/network/EncodedFormDataTest.cpp
index 4bb72d69..3b0e6a2 100644
--- a/third_party/WebKit/Source/platform/network/EncodedFormDataTest.cpp
+++ b/third_party/WebKit/Source/platform/network/EncodedFormDataTest.cpp
@@ -84,7 +84,7 @@
   EXPECT_EQ(*original, *copy);
 
   // Check pointers are different, i.e. deep-copied.
-  ASSERT_NE(original.Get(), copy.Get());
+  ASSERT_NE(original.get(), copy.get());
 
   for (size_t i = 0; i < 4; ++i) {
     if (copy_elements[i].filename_.Impl()) {
diff --git a/third_party/WebKit/Source/platform/network/NetworkStateNotifierTest.cpp b/third_party/WebKit/Source/platform/network/NetworkStateNotifierTest.cpp
index 3dbf126..87647f7c 100644
--- a/third_party/WebKit/Source/platform/network/NetworkStateNotifierTest.cpp
+++ b/third_party/WebKit/Source/platform/network/NetworkStateNotifierTest.cpp
@@ -138,8 +138,8 @@
     notifier_.SetOnLine(false);
   }
 
-  WebTaskRunner* GetTaskRunner() { return task_runner_.Get(); }
-  WebTaskRunner* GetTaskRunner2() { return task_runner2_.Get(); }
+  WebTaskRunner* GetTaskRunner() { return task_runner_.get(); }
+  WebTaskRunner* GetTaskRunner2() { return task_runner2_.get(); }
 
   void TearDown() override {
     RunPendingTasks();
diff --git a/third_party/WebKit/Source/platform/plugins/PluginData.h b/third_party/WebKit/Source/platform/plugins/PluginData.h
index 8ef8fb4..14a9444 100644
--- a/third_party/WebKit/Source/platform/plugins/PluginData.h
+++ b/third_party/WebKit/Source/platform/plugins/PluginData.h
@@ -93,7 +93,7 @@
 
   const HeapVector<Member<PluginInfo>>& Plugins() const { return plugins_; }
   const HeapVector<Member<MimeClassInfo>>& Mimes() const { return mimes_; }
-  const SecurityOrigin* Origin() const { return main_frame_origin_.Get(); }
+  const SecurityOrigin* Origin() const { return main_frame_origin_.get(); }
   void UpdatePluginList(SecurityOrigin* main_frame_origin);
   void ResetPluginData();
 
diff --git a/third_party/WebKit/Source/platform/runtime_enabled_features.json5 b/third_party/WebKit/Source/platform/runtime_enabled_features.json5
index 3ee1363..0898920 100644
--- a/third_party/WebKit/Source/platform/runtime_enabled_features.json5
+++ b/third_party/WebKit/Source/platform/runtime_enabled_features.json5
@@ -614,6 +614,9 @@
       name: "MobileLayoutTheme",
     },
     {
+      name: "ModernMediaControls",
+    },
+    {
       name: "ModuleScripts",
       status: "stable",
     },
@@ -998,6 +1001,11 @@
     {
       name: "TouchpadAndWheelScrollLatching",
     },
+    // When enabled, tracks the number of times each LayoutBlock
+    // goes through layout. For testing purposes only.
+    {
+      name: "TrackLayoutPassesPerBlock",
+    },
     {
       name: "TrustedDOMTypes",
       status: "experimental",
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc
index b075584..54a9f07e 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc
@@ -278,6 +278,7 @@
   for (int i = 0; i < work_batch_size_; i++) {
     IncomingImmediateWorkMap queues_to_reload;
 
+    bool was_nested = false;
     {
       base::AutoLock lock(any_thread_lock_);
       if (i == 0) {
@@ -291,12 +292,17 @@
         // Ideally we'd have an OnNestedMessageloopExit observer, but in it's
         // absence we may need to clear this flag after running a task (which
         // ran a nested messageloop).
+        if (any_thread().is_nested && !is_nested)
+          was_nested = true;
         any_thread().is_nested = is_nested;
       }
       DCHECK_EQ(any_thread().is_nested, delegate_->IsNested());
       std::swap(queues_to_reload, any_thread().has_incoming_immediate_work);
     }
 
+    if (observer_ && was_nested)
+      observer_->OnExitNestedRunLoop();
+
     // It's important we call ReloadEmptyWorkQueues out side of the lock to
     // avoid a lock order inversion.
     ReloadEmptyWorkQueues(queues_to_reload);
@@ -333,6 +339,7 @@
   // when there's no more work left to be done, rather than posting a
   // continuation task.
 
+  bool was_nested = false;
   {
     MoveableAutoLock lock(any_thread_lock_);
     base::Optional<NextTaskDelay> next_delay =
@@ -341,11 +348,16 @@
     any_thread().do_work_running_count--;
     DCHECK_GE(any_thread().do_work_running_count, 0);
 
+    if (any_thread().is_nested && !is_nested)
+      was_nested = true;
     any_thread().is_nested = is_nested;
     DCHECK_EQ(any_thread().is_nested, delegate_->IsNested());
 
     PostDoWorkContinuationLocked(next_delay, &lazy_now, std::move(lock));
   }
+
+  if (observer_ && was_nested)
+    observer_->OnExitNestedRunLoop();
 }
 
 void TaskQueueManager::PostDoWorkContinuationLocked(
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.h b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.h
index 8a2cc70..5a7d2002 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.h
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.h
@@ -120,6 +120,8 @@
     virtual void OnTriedToExecuteBlockedTask() = 0;
 
     virtual void OnBeginNestedRunLoop() = 0;
+
+    virtual void OnExitNestedRunLoop() = 0;
   };
 
   // Called once to set the Observer. This function is called on the main
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc
index 0371ab3..d94574a 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc
@@ -44,8 +44,8 @@
 
 namespace blink {
 namespace scheduler {
-namespace task_queue_manager_unittest {  // To avoid symbol collisions in jumbo
-                                         // builds.
+// To avoid symbol collisions in jumbo builds.
+namespace task_queue_manager_unittest {
 
 class TaskQueueManagerForTest : public TaskQueueManager {
  public:
@@ -1418,6 +1418,7 @@
  public:
   MOCK_METHOD0(OnTriedToExecuteBlockedTask, void());
   MOCK_METHOD0(OnBeginNestedRunLoop, void());
+  MOCK_METHOD0(OnExitNestedRunLoop, void());
 };
 
 }  // namespace
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector_unittest.cc
index 7bd996f..1a4ab991 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector_unittest.cc
@@ -24,6 +24,8 @@
 namespace blink {
 namespace scheduler {
 namespace internal {
+// To avoid symbol collisions in jumbo builds.
+namespace task_queue_selector_unittest {
 
 class MockObserver : public TaskQueueSelector::Observer {
  public:
@@ -564,6 +566,7 @@
     ChooseOldestWithPriorityTest,
     ::testing::ValuesIn(kChooseOldestWithPriorityTestCases));
 
+}  // namespace task_queue_selector_unittest
 }  // namespace internal
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/child/idle_helper.h b/third_party/WebKit/Source/platform/scheduler/child/idle_helper.h
index aec0d27..37e9772 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/idle_helper.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/idle_helper.h
@@ -15,6 +15,10 @@
 
 namespace blink {
 namespace scheduler {
+namespace idle_helper_unittest {
+class BaseIdleHelperTest;
+class IdleHelperTest;
+}  // namespace idle_helper_unittest
 
 class SchedulerHelper;
 
@@ -149,8 +153,8 @@
   static const char* IdlePeriodStateToString(IdlePeriodState state);
 
  private:
-  friend class BaseIdleHelperTest;
-  friend class IdleHelperTest;
+  friend class idle_helper_unittest::BaseIdleHelperTest;
+  friend class idle_helper_unittest::IdleHelperTest;
 
   const scoped_refptr<TaskQueue>& idle_queue() const { return idle_queue_; }
 
diff --git a/third_party/WebKit/Source/platform/scheduler/child/idle_helper_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/idle_helper_unittest.cc
index 5725bff..6f8b670 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/idle_helper_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/idle_helper_unittest.cc
@@ -34,8 +34,9 @@
 
 namespace blink {
 namespace scheduler {
+// To avoid symbol collisions in jumbo builds.
+namespace idle_helper_unittest {
 
-namespace {
 void AppendToVectorTestTask(std::vector<std::string>* vector,
                             std::string value) {
   vector->push_back(value);
@@ -175,8 +176,6 @@
   DISALLOW_COPY_AND_ASSIGN(ScopedAutoAdvanceNowEnabler);
 };
 
-};  // namespace
-
 class IdleHelperForTest : public IdleHelper, public IdleHelper::Delegate {
  public:
   explicit IdleHelperForTest(
@@ -1209,5 +1208,6 @@
   EXPECT_EQ(expected_deadline, deadline_in_task);
 }
 
+}  // namespace idle_helper_unittest
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.cc b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.cc
index d83d9a3..fe5df991 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.cc
@@ -135,5 +135,10 @@
     observer_->OnBeginNestedRunLoop();
 }
 
+void SchedulerHelper::OnExitNestedRunLoop() {
+  if (observer_)
+    observer_->OnExitNestedRunLoop();
+}
+
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.h b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.h
index 7dae827..c4e7eb1a 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.h
@@ -28,6 +28,7 @@
   // TaskQueueManager::Observer implementation:
   void OnTriedToExecuteBlockedTask() override;
   void OnBeginNestedRunLoop() override;
+  void OnExitNestedRunLoop() override;
 
   // Returns the default task queue.
   virtual scoped_refptr<TaskQueue> DefaultTaskQueue() = 0;
@@ -68,6 +69,9 @@
 
     // Called when scheduler executes task with nested run loop.
     virtual void OnBeginNestedRunLoop() = 0;
+
+    // Called when the scheduler spots we've exited a nested run loop.
+    virtual void OnExitNestedRunLoop() = 0;
   };
 
   // Called once to set the Observer. This function is called on the main
diff --git a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper_unittest.cc
index c210ed7..3ab2925 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper_unittest.cc
@@ -26,6 +26,7 @@
 
 namespace blink {
 namespace scheduler {
+namespace scheduler_helper_unittest {
 
 namespace {
 void AppendToVectorTestTask(std::vector<std::string>* vector,
@@ -189,6 +190,7 @@
  public:
   MOCK_METHOD0(OnTriedToExecuteBlockedTask, void());
   MOCK_METHOD0(OnBeginNestedRunLoop, void());
+  MOCK_METHOD0(OnExitNestedRunLoop, void());
 };
 
 }  // namespace
@@ -214,6 +216,6 @@
 
   scheduler_helper_->SetObserver(nullptr);
 }
-
+}  // namespace scheduler_helper_unittest
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/child/web_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/child/web_scheduler_impl.cc
index 94eff7d..d2bc0e6 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/web_scheduler_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/web_scheduler_impl.cc
@@ -63,11 +63,11 @@
 }
 
 blink::WebTaskRunner* WebSchedulerImpl::LoadingTaskRunner() {
-  return loading_web_task_runner_.Get();
+  return loading_web_task_runner_.get();
 }
 
 blink::WebTaskRunner* WebSchedulerImpl::TimerTaskRunner() {
-  return timer_web_task_runner_.Get();
+  return timer_web_task_runner_.get();
 }
 
 blink::WebTaskRunner* WebSchedulerImpl::CompositorTaskRunner() {
diff --git a/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc
index dc80369..374f281c 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc
@@ -20,7 +20,7 @@
 
 namespace blink {
 namespace scheduler {
-namespace {
+namespace webthread_impl_for_worker_scheduler_unittest {
 
 class MockTask {
  public:
@@ -68,8 +68,6 @@
   web_scheduler_impl->Shutdown();
 }
 
-}  // namespace
-
 class WebThreadImplForWorkerSchedulerTest : public ::testing::Test {
  public:
   WebThreadImplForWorkerSchedulerTest() {}
@@ -194,5 +192,6 @@
   thread_.reset();
 }
 
+}  // namespace webthread_impl_for_worker_scheduler_unittest
 }  // namespace scheduler
 }  // namespace blink
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 7e0a07d..bb0d561 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
@@ -18,16 +18,14 @@
 
 namespace blink {
 namespace scheduler {
-
-namespace {
+// To avoid symbol collisions in jumbo builds.
+namespace worker_global_scope_scheduler_unittest {
 
 void AppendToVectorTestTask(std::vector<std::string>* vector,
                             std::string value) {
   vector->push_back(value);
 }
 
-}  // namespace
-
 class WorkerGlobalScopeSchedulerTest : public ::testing::Test {
  public:
   WorkerGlobalScopeSchedulerTest()
@@ -87,5 +85,6 @@
   EXPECT_TRUE(run_order.empty());
 }
 
+}  // namespace worker_global_scope_scheduler_unittest
 }  // namespace scheduler
 }  // namespace blink
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 0f15292..dbf2b92 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
@@ -20,8 +20,9 @@
 
 namespace blink {
 namespace scheduler {
+// To avoid symbol collisions in jumbo builds.
+namespace worker_scheduler_impl_unittest {
 
-namespace {
 void NopTask() {}
 
 int TimeTicksToIntMs(const base::TimeTicks& time) {
@@ -51,8 +52,6 @@
                                          TimeTicksToIntMs(deadline)));
 }
 
-};  // namespace
-
 class WorkerSchedulerImplForTest : public WorkerSchedulerImpl {
  public:
   WorkerSchedulerImplForTest(
@@ -399,5 +398,6 @@
   EXPECT_THAT(timeline, ElementsAreArray(expected_timeline));
 }
 
+}  // namespace worker_scheduler_impl_unittest
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc
index 0da89a5..1961f3c 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc
@@ -17,6 +17,8 @@
 
 namespace blink {
 namespace scheduler {
+// Namespace to avoid symbol collisions in jumbo builds.
+namespace auto_advancing_virtual_time_domain_unittest {
 
 class AutoAdvancingVirtualTimeDomainTest : public ::testing::Test {
  public:
@@ -95,5 +97,6 @@
   EXPECT_FALSE(task_run);
 }
 
+}  // namespace auto_advancing_virtual_time_domain_unittest
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/render_widget_signals_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/render_widget_signals_unittest.cc
index a07f183..8a3f164 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/render_widget_signals_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/render_widget_signals_unittest.cc
@@ -15,8 +15,9 @@
 
 namespace blink {
 namespace scheduler {
+// To avoid symbol collisions in jumbo builds.
+namespace render_widget_signals_unittest {
 
-namespace {
 class MockObserver : public RenderWidgetSignals::Observer {
  public:
   MockObserver() {}
@@ -29,7 +30,6 @@
  private:
   DISALLOW_COPY_AND_ASSIGN(MockObserver);
 };
-}
 
 class RenderWidgetSignalsTest : public ::testing::Test {
  public:
@@ -264,5 +264,6 @@
   IgnoreWidgetDestructionCallbacks();
 }
 
+}  // namespace render_widget_signals_unittest
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler.cc
index 2671683..6bbbf0b 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler.cc
@@ -10,7 +10,6 @@
 #include "base/metrics/field_trial.h"
 #include "base/time/default_tick_clock.h"
 #include "base/trace_event/trace_event.h"
-#include "base/trace_event/trace_event_impl.h"
 #include "platform/scheduler/child/scheduler_tqm_delegate_impl.h"
 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
 
@@ -26,13 +25,12 @@
 // static
 std::unique_ptr<RendererScheduler> RendererScheduler::Create() {
   // Ensure categories appear as an option in chrome://tracing.
-  base::trace_event::TraceLog::GetCategoryGroupEnabled(
-      TRACE_DISABLED_BY_DEFAULT("worker.scheduler"));
-  base::trace_event::TraceLog::GetCategoryGroupEnabled(
+  TRACE_EVENT_WARMUP_CATEGORY(TRACE_DISABLED_BY_DEFAULT("worker.scheduler"));
+  TRACE_EVENT_WARMUP_CATEGORY(
       TRACE_DISABLED_BY_DEFAULT("worker.scheduler.debug"));
-  base::trace_event::TraceLog::GetCategoryGroupEnabled(
+  TRACE_EVENT_WARMUP_CATEGORY(
       TRACE_DISABLED_BY_DEFAULT("renderer.scheduler.debug"));
-  base::trace_event::TraceLog::GetCategoryGroupEnabled(
+  TRACE_EVENT_WARMUP_CATEGORY(
       TRACE_DISABLED_BY_DEFAULT("renderer.scheduler.enable_verbose_snapshots"));
 
   base::MessageLoop* message_loop = base::MessageLoop::current();
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 c8665ac..03319313 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
@@ -1775,6 +1775,14 @@
 
   UMA_HISTOGRAM_COUNTS_100("RendererScheduler.WebViewsPerScheduler",
                            main_thread_only().web_view_schedulers.size());
+
+  size_t frame_count = 0;
+  for (WebViewSchedulerImpl* web_view_scheduler :
+       main_thread_only().web_view_schedulers) {
+    frame_count += web_view_scheduler->FrameCount();
+  }
+  UMA_HISTOGRAM_COUNTS_100("RendererScheduler.WebFramesPerScheduler",
+                           frame_count);
 }
 
 void RendererSchedulerImpl::SetTopLevelBlameContext(
@@ -1936,6 +1944,18 @@
   seqlock_queueing_time_estimator_.seqlock.WriteBegin();
   seqlock_queueing_time_estimator_.data.OnBeginNestedRunLoop();
   seqlock_queueing_time_estimator_.seqlock.WriteEnd();
+
+  for (WebViewSchedulerImpl* web_view_scheduler :
+       main_thread_only().web_view_schedulers) {
+    web_view_scheduler->OnBeginNestedRunLoop();
+  }
+}
+
+void RendererSchedulerImpl::OnExitNestedRunLoop() {
+  for (WebViewSchedulerImpl* web_view_scheduler :
+       main_thread_only().web_view_schedulers) {
+    web_view_scheduler->OnExitNestedRunLoop();
+  }
 }
 
 void RendererSchedulerImpl::AddTaskTimeObserver(
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h
index e2418e6..af421082 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h
@@ -40,6 +40,11 @@
 
 namespace blink {
 namespace scheduler {
+namespace renderer_scheduler_impl_unittest {
+class RendererSchedulerImplForTest;
+class RendererSchedulerImplTest;
+FORWARD_DECLARE_TEST(RendererSchedulerImplTest, Tracing);
+}  // namespace renderer_scheduler_impl_unittest
 class AutoAdvancingVirtualTimeDomain;
 class RenderWidgetSchedulingState;
 class WebViewSchedulerImpl;
@@ -137,6 +142,7 @@
   // SchedulerHelper::Observer implementation:
   void OnTriedToExecuteBlockedTask() override;
   void OnBeginNestedRunLoop() override;
+  void OnExitNestedRunLoop() override;
 
   // QueueingTimeEstimator::Client implementation:
   void OnQueueingTimeForWindowEstimated(base::TimeDelta queueing_time,
@@ -256,9 +262,11 @@
   friend class RendererMetricsHelper;
 
   friend class RendererMetricsHelperTest;
-  friend class RendererSchedulerImplForTest;
-  friend class RendererSchedulerImplTest;
-  FRIEND_TEST_ALL_PREFIXES(RendererSchedulerImplTest, Tracing);
+  friend class renderer_scheduler_impl_unittest::RendererSchedulerImplForTest;
+  friend class renderer_scheduler_impl_unittest::RendererSchedulerImplTest;
+  FRIEND_TEST_ALL_PREFIXES(
+      renderer_scheduler_impl_unittest::RendererSchedulerImplTest,
+      Tracing);
 
   enum class ExpensiveTaskPolicy { RUN, BLOCK, THROTTLE };
 
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 859a6b0..5e1cb2f 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
@@ -30,8 +30,8 @@
 
 namespace blink {
 namespace scheduler {
-
-namespace {
+// To avoid symbol collisions in jumbo builds.
+namespace renderer_scheduler_impl_unittest {
 
 using ScopedStopLoadingInBackgroundAndroidForTest =
     ScopedRuntimeEnabledFeatureForTest<
@@ -208,8 +208,6 @@
   DISALLOW_COPY_AND_ASSIGN(ScopedAutoAdvanceNowEnabler);
 };
 
-};  // namespace
-
 class RendererSchedulerImplForTest : public RendererSchedulerImpl {
  public:
   using RendererSchedulerImpl::OnIdlePeriodEnded;
@@ -3943,15 +3941,11 @@
   EXPECT_TRUE(value);
 }
 
-namespace {
-
 void RecordingTimeTestTask(std::vector<base::TimeTicks>* run_times,
                            base::SimpleTestTickClock* clock) {
   run_times->push_back(clock->NowTicks());
 }
 
-}  // namespace
-
 // TODO(altimin@): Re-enable after splitting the timer policy into separate
 // policies.
 TEST_F(RendererSchedulerImplTest,
@@ -4174,5 +4168,6 @@
                                    std::string("L5"), std::string("L6")));
 }
 
+}  // namespace renderer_scheduler_impl_unittest
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_web_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_web_scheduler_impl.cc
index e092b54..f0ce5bee 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_web_scheduler_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_web_scheduler_impl.cc
@@ -28,7 +28,7 @@
 RendererWebSchedulerImpl::~RendererWebSchedulerImpl() {}
 
 WebTaskRunner* RendererWebSchedulerImpl::CompositorTaskRunner() {
-  return compositor_task_runner_.Get();
+  return compositor_task_runner_.get();
 }
 
 void RendererWebSchedulerImpl::PauseTimerQueue() {
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler_unittest.cc
index 9500845..d0e3c864 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler_unittest.cc
@@ -28,8 +28,8 @@
 
 namespace blink {
 namespace scheduler {
-namespace task_queue_throttler_unittest {  // To avoid symbol collisions in
-                                           // jumbo builds.
+// To avoid symbol collisions in jumbo builds.
+namespace task_queue_throttler_unittest {
 
 bool MessageLoopTaskCounter(size_t* count) {
   *count = *count + 1;
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
index 841f2944..d194e783 100644
--- 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
@@ -20,8 +20,8 @@
 
 namespace blink {
 namespace scheduler {
-namespace web_frame_scheduler_impl_unittest {  // To avoid symbol collisions in
-                                               // jumbo builds.
+// To avoid symbol collisions in jumbo builds.
+namespace web_frame_scheduler_impl_unittest {
 
 class WebFrameSchedulerImplTest : public ::testing::Test {
  public:
@@ -99,7 +99,7 @@
 void RunRepeatingTask(RefPtr<WebTaskRunner> task_runner, int* run_count) {
   ++*run_count;
 
-  WebTaskRunner* task_runner_ptr = task_runner.Get();
+  WebTaskRunner* task_runner_ptr = task_runner.get();
   task_runner_ptr->PostDelayedTask(
       BLINK_FROM_HERE, MakeRepeatingTask(std::move(task_runner), run_count),
       TimeDelta::FromMilliseconds(1));
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl.cc
index 7959f4d..8d3fb95 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl.cc
@@ -110,6 +110,7 @@
       is_audio_playing_(false),
       reported_background_throttling_since_navigation_(false),
       has_active_connection_(false),
+      nested_runloop_(false),
       background_time_budget_pool_(nullptr),
       delegate_(delegate) {
   renderer_scheduler->AddWebViewScheduler(this);
@@ -264,6 +265,16 @@
   ApplyVirtualTimePolicy();
 }
 
+void WebViewSchedulerImpl::OnBeginNestedRunLoop() {
+  nested_runloop_ = true;
+  ApplyVirtualTimePolicy();
+}
+
+void WebViewSchedulerImpl::OnExitNestedRunLoop() {
+  nested_runloop_ = false;
+  ApplyVirtualTimePolicy();
+}
+
 void WebViewSchedulerImpl::SetVirtualTimePolicy(VirtualTimePolicy policy) {
   virtual_time_policy_ = policy;
 
@@ -330,10 +341,12 @@
 
   // We pause virtual time until we've seen a loading task posted, because
   // otherwise we could advance virtual time arbitarially far before the
-  // first load arrives.
+  // first load arrives.  We also pause virtual time while the run loop is
+  // nested because that implies something modal is happening such as the
+  // DevTools debugger pausing the system.
   SetAllowVirtualTimeToAdvance(pending_loads_.size() == 0 &&
                                background_parser_count_ == 0 &&
-                               provisional_loads_.empty() &&
+                               provisional_loads_.empty() && !nested_runloop_ &&
                                expect_backward_forwards_navigation_.empty());
 }
 
@@ -452,6 +465,10 @@
   }
 }
 
+size_t WebViewSchedulerImpl::FrameCount() const {
+  return frame_schedulers_.size();
+}
+
 // static
 const char* WebViewSchedulerImpl::VirtualTimePolicyToString(
     VirtualTimePolicy virtual_time_policy) {
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl.h b/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl.h
index 97f8e07e..bf0f2e9 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl.h
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl.h
@@ -74,10 +74,16 @@
   void DidBeginProvisionalLoad(WebFrameSchedulerImpl* frame_scheduler);
   void DidEndProvisionalLoad(WebFrameSchedulerImpl* frame_scheduler);
 
+  void OnBeginNestedRunLoop();
+  void OnExitNestedRunLoop();
+
   bool IsAudioPlaying() const;
 
   void OnConnectionUpdated();
 
+  // Return a number of child web frame schedulers for this WebViewScheduler.
+  size_t FrameCount() const;
+
   void AsValueInto(base::trace_event::TracedValue* state) const;
 
  private:
@@ -122,6 +128,7 @@
   bool is_audio_playing_;
   bool reported_background_throttling_since_navigation_;
   bool has_active_connection_;
+  bool nested_runloop_;
   CPUTimeBudgetPool* background_time_budget_pool_;  // Not owned.
   WebViewScheduler::WebViewSchedulerDelegate* delegate_;  // Not owned.
   base::ObserverList<VirtualTimeObserver> virtual_time_observers_;
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl_unittest.cc
index b180386b..dd37ee025 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl_unittest.cc
@@ -27,8 +27,8 @@
 
 namespace blink {
 namespace scheduler {
-namespace web_view_scheduler_impl_unittest {  // To avoid symbol collisions in
-                                              // jumbo builds.
+// To avoid symbol collisions in jumbo builds.
+namespace web_view_scheduler_impl_unittest {
 
 class WebViewSchedulerImplTest : public ::testing::Test {
  public:
@@ -95,7 +95,7 @@
 void RunRepeatingTask(RefPtr<blink::WebTaskRunner> task_runner,
                       int* run_count) {
   ++*run_count;
-  blink::WebTaskRunner* task_runner_ptr = task_runner.Get();
+  blink::WebTaskRunner* task_runner_ptr = task_runner.get();
   task_runner_ptr->PostDelayedTask(
       BLINK_FROM_HERE, MakeRepeatingTask(std::move(task_runner), run_count),
       TimeDelta::FromMilliseconds(1));
@@ -557,6 +557,18 @@
   EXPECT_TRUE(web_view_scheduler_->VirtualTimeAllowedToAdvance());
 }
 
+TEST_F(WebViewSchedulerImplTest, NestedMessageLoop_DETERMINISTIC_LOADING) {
+  web_view_scheduler_->SetVirtualTimePolicy(
+      VirtualTimePolicy::DETERMINISTIC_LOADING);
+  EXPECT_TRUE(web_view_scheduler_->VirtualTimeAllowedToAdvance());
+
+  web_view_scheduler_->OnBeginNestedRunLoop();
+  EXPECT_FALSE(web_view_scheduler_->VirtualTimeAllowedToAdvance());
+
+  web_view_scheduler_->OnExitNestedRunLoop();
+  EXPECT_TRUE(web_view_scheduler_->VirtualTimeAllowedToAdvance());
+}
+
 TEST_F(WebViewSchedulerImplTest, ProvisionalLoads) {
   web_view_scheduler_->SetVirtualTimePolicy(
       VirtualTimePolicy::DETERMINISTIC_LOADING);
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.cc b/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.cc
index 2fad99d..3152dcc 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.cc
@@ -44,7 +44,7 @@
 }
 
 blink::WebTaskRunner* WebThreadImplForRendererScheduler::GetWebTaskRunner() {
-  return web_task_runner_.Get();
+  return web_task_runner_.get();
 }
 
 void WebThreadImplForRendererScheduler::AddTaskObserverInternal(
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc
index 3f931690..a5dd6666 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc
@@ -23,7 +23,8 @@
 
 namespace blink {
 namespace scheduler {
-namespace {
+// To avoid symbol collisions in jumbo builds.
+namespace webthread_impl_for_renderer_scheduler_unittest {
 
 const int kWorkBatchSize = 2;
 
@@ -37,7 +38,6 @@
   MOCK_METHOD0(WillProcessTask, void());
   MOCK_METHOD0(DidProcessTask, void());
 };
-}  // namespace
 
 class WebThreadImplForRendererSchedulerTest : public ::testing::Test {
  public:
@@ -203,5 +203,6 @@
   thread_->RemoveTaskObserver(&observer);
 }
 
+}  // namespace webthread_impl_for_renderer_scheduler_unittest
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesisUtterance.h b/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesisUtterance.h
index f33855b..52d9dcd 100644
--- a/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesisUtterance.h
+++ b/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesisUtterance.h
@@ -53,7 +53,7 @@
   const String& Lang() const { return lang_; }
   void SetLang(const String& lang) { lang_ = lang; }
 
-  PlatformSpeechSynthesisVoice* Voice() const { return voice_.Get(); }
+  PlatformSpeechSynthesisVoice* Voice() const { return voice_.get(); }
   void SetVoice(PlatformSpeechSynthesisVoice* voice) { voice_ = voice; }
 
   // Range = [0, 1] where 1 is the default.
diff --git a/third_party/WebKit/Source/platform/testing/FakeDisplayItemClient.h b/third_party/WebKit/Source/platform/testing/FakeDisplayItemClient.h
index bdc35a1..3742758 100644
--- a/third_party/WebKit/Source/platform/testing/FakeDisplayItemClient.h
+++ b/third_party/WebKit/Source/platform/testing/FakeDisplayItemClient.h
@@ -19,8 +19,18 @@
 
   String DebugName() const final { return name_; }
   LayoutRect VisualRect() const override { return visual_rect_; }
+  LayoutRect PartialInvalidationRect() const override {
+    return partial_invalidation_rect_;
+  }
+  void ClearPartialInvalidationRect() const override {
+    partial_invalidation_rect_ = LayoutRect();
+  }
 
   void SetVisualRect(const LayoutRect& r) { visual_rect_ = r; }
+  void SetPartialInvalidationRect(const LayoutRect& r) {
+    SetDisplayItemsUncached(PaintInvalidationReason::kRectangle);
+    partial_invalidation_rect_ = r;
+  }
 
   // This simulates a paint without needing a PaintController.
   void UpdateCacheGeneration() {
@@ -30,6 +40,7 @@
  private:
   String name_;
   LayoutRect visual_rect_;
+  mutable LayoutRect partial_invalidation_rect_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/testing/FontTestHelpers.cpp b/third_party/WebKit/Source/platform/testing/FontTestHelpers.cpp
index 5087ec7..c5dc0f5 100644
--- a/third_party/WebKit/Source/platform/testing/FontTestHelpers.cpp
+++ b/third_party/WebKit/Source/platform/testing/FontTestHelpers.cpp
@@ -22,7 +22,7 @@
     RefPtr<SharedBuffer> font_buffer = testing::ReadFromFile(path);
     String ots_parse_message;
     return new TestFontSelector(
-        FontCustomPlatformData::Create(font_buffer.Get(), ots_parse_message));
+        FontCustomPlatformData::Create(font_buffer.get(), ots_parse_message));
   }
 
   ~TestFontSelector() override {}
diff --git a/third_party/WebKit/Source/platform/testing/ImageDecodeBench.cpp b/third_party/WebKit/Source/platform/testing/ImageDecodeBench.cpp
index ac4b83da..538b734 100644
--- a/third_party/WebKit/Source/platform/testing/ImageDecodeBench.cpp
+++ b/third_party/WebKit/Source/platform/testing/ImageDecodeBench.cpp
@@ -238,7 +238,7 @@
     position += length;
 
     bool all_data_received = position == data->size();
-    decoder->SetData(packet_data.Get(), all_data_received);
+    decoder->SetData(packet_data.get(), all_data_received);
 
     size_t frame_count = decoder->FrameCount();
     for (; next_frame_to_decode < frame_count; ++next_frame_to_decode) {
@@ -315,7 +315,7 @@
   // segments into one, contiguous block of memory.
 
   RefPtr<SharedBuffer> data = ReadFile(argv[1]);
-  if (!data.Get() || !data->size()) {
+  if (!data.get() || !data->size()) {
     fprintf(stderr, "Error reading image data from [%s]\n", argv[1]);
     exit(2);
   }
@@ -324,7 +324,7 @@
 
   // Warm-up: throw out the first iteration for more consistent results.
 
-  if (!DecodeImageData(data.Get(), apply_color_correction, packet_size)) {
+  if (!DecodeImageData(data.get(), apply_color_correction, packet_size)) {
     fprintf(stderr, "Image decode failed [%s]\n", argv[1]);
     exit(3);
   }
@@ -336,7 +336,7 @@
   for (size_t i = 0; i < iterations; ++i) {
     double start_time = GetCurrentTime();
     bool decoded =
-        DecodeImageData(data.Get(), apply_color_correction, packet_size);
+        DecodeImageData(data.get(), apply_color_correction, packet_size);
     double elapsed_time = GetCurrentTime() - start_time;
     total_time += elapsed_time;
     if (!decoded) {
diff --git a/third_party/WebKit/Source/platform/testing/RuntimeEnabledFeaturesTestHelpers.h b/third_party/WebKit/Source/platform/testing/RuntimeEnabledFeaturesTestHelpers.h
index e4d932b..25aef04 100644
--- a/third_party/WebKit/Source/platform/testing/RuntimeEnabledFeaturesTestHelpers.h
+++ b/third_party/WebKit/Source/platform/testing/RuntimeEnabledFeaturesTestHelpers.h
@@ -60,6 +60,18 @@
     RuntimeEnabledFeatures::MojoBlobsEnabled,
     RuntimeEnabledFeatures::SetMojoBlobsEnabled>
     ScopedMojoBlobsForTest;
+typedef ScopedRuntimeEnabledFeatureForTest<
+    RuntimeEnabledFeatures::OverlayScrollbarsEnabled,
+    RuntimeEnabledFeatures::SetOverlayScrollbarsEnabled>
+    ScopedOverlayScrollbarsForTest;
+typedef ScopedRuntimeEnabledFeatureForTest<
+    RuntimeEnabledFeatures::SkipCompositingSmallScrollersEnabled,
+    RuntimeEnabledFeatures::SetSkipCompositingSmallScrollersEnabled>
+    ScopedSkipCompositingSmallScrollersForTest;
+typedef ScopedRuntimeEnabledFeatureForTest<
+    RuntimeEnabledFeatures::CompositeOpaqueScrollersEnabled,
+    RuntimeEnabledFeatures::SetCompositeOpaqueScrollersEnabled>
+    ScopedCompositeOpaqueScrollersForTest;
 
 }  // namespace blink
 
diff --git a/third_party/WebKit/Source/platform/testing/TestPaintArtifact.cpp b/third_party/WebKit/Source/platform/testing/TestPaintArtifact.cpp
index c7c7d86..da1f0f1 100644
--- a/third_party/WebKit/Source/platform/testing/TestPaintArtifact.cpp
+++ b/third_party/WebKit/Source/platform/testing/TestPaintArtifact.cpp
@@ -23,26 +23,23 @@
 
 class TestPaintArtifact::DummyRectClient : public FakeDisplayItemClient {
  public:
-  DummyRectClient(const FloatRect& rect = FloatRect(),
-                  Color color = Color::kTransparent)
-      : rect_(rect), color_(color) {}
   LayoutRect VisualRect() const final { return EnclosingLayoutRect(rect_); }
-  sk_sp<PaintRecord> MakeRecord() const;
+  void SetVisualRect(const FloatRect& rect) { rect_ = rect; }
+
+  sk_sp<PaintRecord> MakeRecord(const FloatRect& rect, Color color) {
+    rect_ = rect;
+    PaintRecorder recorder;
+    PaintCanvas* canvas = recorder.beginRecording(rect);
+    PaintFlags flags;
+    flags.setColor(color.Rgb());
+    canvas->drawRect(rect, flags);
+    return recorder.finishRecordingAsPicture();
+  }
 
  private:
   FloatRect rect_;
-  Color color_;
 };
 
-sk_sp<PaintRecord> TestPaintArtifact::DummyRectClient::MakeRecord() const {
-  PaintRecorder recorder;
-  PaintCanvas* canvas = recorder.beginRecording(rect_);
-  PaintFlags flags;
-  flags.setColor(color_.Rgb());
-  canvas->drawRect(rect_, flags);
-  return recorder.finishRecordingAsPicture();
-}
-
 TestPaintArtifact::TestPaintArtifact() : display_item_list_(0), built_(false) {}
 
 TestPaintArtifact::~TestPaintArtifact() {}
@@ -51,30 +48,49 @@
     RefPtr<const TransformPaintPropertyNode> transform,
     RefPtr<const ClipPaintPropertyNode> clip,
     RefPtr<const EffectPaintPropertyNode> effect) {
-  PropertyTreeState property_tree_state(transform.Get(), clip.Get(),
-                                        effect.Get());
+  return Chunk(NewClient(), transform, clip, effect);
+}
+
+TestPaintArtifact& TestPaintArtifact::Chunk(
+    DisplayItemClient& client,
+    RefPtr<const TransformPaintPropertyNode> transform,
+    RefPtr<const ClipPaintPropertyNode> clip,
+    RefPtr<const EffectPaintPropertyNode> effect) {
+  PropertyTreeState property_tree_state(transform.get(), clip.get(),
+                                        effect.get());
   PaintChunkProperties properties(property_tree_state);
-  return Chunk(properties);
+  return Chunk(client, properties);
 }
 
 TestPaintArtifact& TestPaintArtifact::Chunk(
     const PaintChunkProperties& properties) {
+  return Chunk(NewClient(), properties);
+}
+
+TestPaintArtifact& TestPaintArtifact::Chunk(
+    DisplayItemClient& client,
+    const PaintChunkProperties& properties) {
   if (!paint_chunks_.IsEmpty())
     paint_chunks_.back().end_index = display_item_list_.size();
-  auto client = WTF::MakeUnique<DummyRectClient>();
   paint_chunks_.push_back(PaintChunk(
       display_item_list_.size(), 0,
-      PaintChunk::Id(*client, DisplayItem::kDrawingFirst), properties));
-  dummy_clients_.push_back(std::move(client));
+      PaintChunk::Id(client, DisplayItem::kDrawingFirst), properties));
+  // Assume PaintController has processed this chunk.
+  paint_chunks_.back().client_is_just_created = false;
   return *this;
 }
 
 TestPaintArtifact& TestPaintArtifact::RectDrawing(const FloatRect& bounds,
                                                   Color color) {
-  auto client = WTF::MakeUnique<DummyRectClient>(bounds, color);
+  return RectDrawing(NewClient(), bounds, color);
+}
+
+TestPaintArtifact& TestPaintArtifact::RectDrawing(DisplayItemClient& client,
+                                                  const FloatRect& bounds,
+                                                  Color color) {
   display_item_list_.AllocateAndConstruct<DrawingDisplayItem>(
-      *client, DisplayItem::kDrawingFirst, client->MakeRecord(), bounds);
-  dummy_clients_.push_back(std::move(client));
+      client, DisplayItem::kDrawingFirst,
+      static_cast<DummyRectClient&>(client).MakeRecord(bounds, color), bounds);
   return *this;
 }
 
@@ -82,21 +98,32 @@
     const FloatPoint& location,
     const IntSize& size,
     scoped_refptr<cc::Layer> layer) {
-  FloatRect float_bounds(location, FloatSize(size));
-  auto client = WTF::MakeUnique<DummyRectClient>(float_bounds);
+  return ForeignLayer(NewClient(), location, size, layer);
+}
+
+TestPaintArtifact& TestPaintArtifact::ForeignLayer(
+    DisplayItemClient& client,
+    const FloatPoint& location,
+    const IntSize& size,
+    scoped_refptr<cc::Layer> layer) {
+  static_cast<DummyRectClient&>(client).SetVisualRect(
+      FloatRect(location, FloatSize(size)));
   display_item_list_.AllocateAndConstruct<ForeignLayerDisplayItem>(
-      *client, DisplayItem::kForeignLayerFirst, std::move(layer), location,
+      client, DisplayItem::kForeignLayerFirst, std::move(layer), location,
       size);
-  dummy_clients_.push_back(std::move(client));
   return *this;
 }
 
 TestPaintArtifact& TestPaintArtifact::ScrollHitTest(
     RefPtr<const TransformPaintPropertyNode> scroll_offset) {
-  auto client = WTF::MakeUnique<DummyRectClient>();
+  return ScrollHitTest(NewClient(), scroll_offset);
+}
+
+TestPaintArtifact& TestPaintArtifact::ScrollHitTest(
+    DisplayItemClient& client,
+    RefPtr<const TransformPaintPropertyNode> scroll_offset) {
   display_item_list_.AllocateAndConstruct<ScrollHitTestDisplayItem>(
-      *client, DisplayItem::kScrollHitTest, std::move(scroll_offset));
-  dummy_clients_.push_back(std::move(client));
+      client, DisplayItem::kScrollHitTest, std::move(scroll_offset));
   return *this;
 }
 
@@ -117,4 +144,13 @@
   return paint_artifact_;
 }
 
+DisplayItemClient& TestPaintArtifact::NewClient() {
+  dummy_clients_.push_back(WTF::MakeUnique<DummyRectClient>());
+  return *dummy_clients_.back();
+}
+
+DisplayItemClient& TestPaintArtifact::Client(size_t i) const {
+  return *dummy_clients_[i];
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/testing/TestPaintArtifact.h b/third_party/WebKit/Source/platform/testing/TestPaintArtifact.h
index 0c0c8f94..2d9e964 100644
--- a/third_party/WebKit/Source/platform/testing/TestPaintArtifact.h
+++ b/third_party/WebKit/Source/platform/testing/TestPaintArtifact.h
@@ -59,9 +59,32 @@
       RefPtr<const TransformPaintPropertyNode> scroll_offset);
   TestPaintArtifact& KnownToBeOpaque();
 
+  // Add to the artifact, with specified display item client. These are used
+  // to test incremental paint artifact updates.
+  TestPaintArtifact& Chunk(DisplayItemClient&,
+                           RefPtr<const TransformPaintPropertyNode>,
+                           RefPtr<const ClipPaintPropertyNode>,
+                           RefPtr<const EffectPaintPropertyNode>);
+  TestPaintArtifact& Chunk(DisplayItemClient&, const PaintChunkProperties&);
+  TestPaintArtifact& RectDrawing(DisplayItemClient&,
+                                 const FloatRect& bounds,
+                                 Color);
+  TestPaintArtifact& ForeignLayer(DisplayItemClient&,
+                                  const FloatPoint&,
+                                  const IntSize&,
+                                  scoped_refptr<cc::Layer>);
+  TestPaintArtifact& ScrollHitTest(
+      DisplayItemClient&,
+      RefPtr<const TransformPaintPropertyNode> scroll_offset);
+
   // Can't add more things once this is called.
   const PaintArtifact& Build();
 
+  // Create a new display item client which is owned by this TestPaintArtifact.
+  DisplayItemClient& NewClient();
+
+  DisplayItemClient& Client(size_t) const;
+
  private:
   class DummyRectClient;
   Vector<std::unique_ptr<DummyRectClient>> dummy_clients_;
diff --git a/third_party/WebKit/Source/platform/text/BidiContext.cpp b/third_party/WebKit/Source/platform/text/BidiContext.cpp
index 0c39a1dd..a6f654b 100644
--- a/third_party/WebKit/Source/platform/text/BidiContext.cpp
+++ b/third_party/WebKit/Source/platform/text/BidiContext.cpp
@@ -113,9 +113,10 @@
 
   RefPtr<BidiContext> top_context =
       CopyContextAndRebaselineLevel(contexts.back(), 0);
-  for (int i = contexts.size() - 1; i > 0; --i)
+  for (int i = contexts.size() - 1; i > 0; --i) {
     top_context =
-        CopyContextAndRebaselineLevel(contexts[i - 1], top_context.Get());
+        CopyContextAndRebaselineLevel(contexts[i - 1], top_context.get());
+  }
 
   return top_context;
 }
diff --git a/third_party/WebKit/Source/platform/text/BidiContext.h b/third_party/WebKit/Source/platform/text/BidiContext.h
index f8c530a6..583e23be 100644
--- a/third_party/WebKit/Source/platform/text/BidiContext.h
+++ b/third_party/WebKit/Source/platform/text/BidiContext.h
@@ -42,7 +42,7 @@
                                     BidiEmbeddingSource = kFromStyleOrDOM,
                                     BidiContext* parent = 0);
 
-  BidiContext* Parent() const { return parent_.Get(); }
+  BidiContext* Parent() const { return parent_.get(); }
   unsigned char Level() const { return level_; }
   WTF::Unicode::CharDirection Dir() const {
     return static_cast<WTF::Unicode::CharDirection>(direction_);
diff --git a/third_party/WebKit/Source/platform/text/BidiResolver.h b/third_party/WebKit/Source/platform/text/BidiResolver.h
index 1a4142aa..5a38812 100644
--- a/third_party/WebKit/Source/platform/text/BidiResolver.h
+++ b/third_party/WebKit/Source/platform/text/BidiResolver.h
@@ -239,7 +239,7 @@
     nested_isolate_count_ = nested_isolated_count;
   }
 
-  BidiContext* Context() const { return status_.context.Get(); }
+  BidiContext* Context() const { return status_.context.get(); }
   void SetContext(RefPtr<BidiContext> c) { status_.context = std::move(c); }
 
   void SetLastDir(WTF::Unicode::CharDirection last_dir) {
@@ -621,9 +621,10 @@
         level = NextGreaterOddLevel(level);
       else
         level = NextGreaterEvenLevel(level);
-      if (level < BidiContext::kMaxLevel)
+      if (level < BidiContext::kMaxLevel) {
         to_context = BidiContext::Create(level, direction, override,
-                                         embedding.Source(), to_context.Get());
+                                         embedding.Source(), to_context.get());
+      }
     }
   }
 
diff --git a/third_party/WebKit/Source/platform/text/HyphenationTest.cpp b/third_party/WebKit/Source/platform/text/HyphenationTest.cpp
index 5383ba98..10397caa 100644
--- a/third_party/WebKit/Source/platform/text/HyphenationTest.cpp
+++ b/third_party/WebKit/Source/platform/text/HyphenationTest.cpp
@@ -33,7 +33,7 @@
 TEST(HyphenationTest, Get) {
   RefPtr<Hyphenation> hyphenation = WTF::AdoptRef(new NoHyphenation);
   LayoutLocale::SetHyphenationForTesting("en-US", hyphenation);
-  EXPECT_EQ(hyphenation.Get(), LayoutLocale::Get("en-US")->GetHyphenation());
+  EXPECT_EQ(hyphenation.get(), LayoutLocale::Get("en-US")->GetHyphenation());
 
   LayoutLocale::SetHyphenationForTesting("en-UK", nullptr);
   EXPECT_EQ(nullptr, LayoutLocale::Get("en-UK")->GetHyphenation());
diff --git a/third_party/WebKit/Source/platform/transforms/TransformOperations.cpp b/third_party/WebKit/Source/platform/transforms/TransformOperations.cpp
index 925205f..b664734 100644
--- a/third_party/WebKit/Source/platform/transforms/TransformOperations.cpp
+++ b/third_party/WebKit/Source/platform/transforms/TransformOperations.cpp
@@ -74,12 +74,12 @@
   unsigned size = std::max(from_size, to_size);
   for (unsigned i = 0; i < size; i++) {
     RefPtr<TransformOperation> from_operation =
-        (i < from_size) ? from.Operations()[i].Get() : 0;
+        (i < from_size) ? from.Operations()[i].get() : 0;
     RefPtr<TransformOperation> to_operation =
-        (i < to_size) ? Operations()[i].Get() : 0;
+        (i < to_size) ? Operations()[i].get() : 0;
     RefPtr<TransformOperation> blended_operation =
         to_operation
-            ? to_operation->Blend(from_operation.Get(), progress)
+            ? to_operation->Blend(from_operation.get(), progress)
             : (from_operation ? from_operation->Blend(0, progress, true)
                               : nullptr);
     if (blended_operation)
@@ -288,7 +288,7 @@
     TransformOperation::OperationType interpolation_type =
         to_operation ? to_operation->GetType() : from_operation->GetType();
     if (from_operation && to_operation &&
-        !from_operation->CanBlendWith(*to_operation.Get()))
+        !from_operation->CanBlendWith(*to_operation.get()))
       return false;
 
     switch (interpolation_type) {
@@ -312,15 +312,15 @@
         RefPtr<TransformOperation> from_transform;
         RefPtr<TransformOperation> to_transform;
         if (!to_operation) {
-          from_transform = from_operation->Blend(to_operation.Get(),
+          from_transform = from_operation->Blend(to_operation.get(),
                                                  1 - min_progress, false);
-          to_transform = from_operation->Blend(to_operation.Get(),
+          to_transform = from_operation->Blend(to_operation.get(),
                                                1 - max_progress, false);
         } else {
           from_transform =
-              to_operation->Blend(from_operation.Get(), min_progress, false);
+              to_operation->Blend(from_operation.get(), min_progress, false);
           to_transform =
-              to_operation->Blend(from_operation.Get(), max_progress, false);
+              to_operation->Blend(from_operation.get(), max_progress, false);
         }
         if (!from_transform || !to_transform)
           continue;
@@ -345,14 +345,14 @@
         const RotateTransformOperation* to_rotation = nullptr;
         if (from_operation) {
           from_rotation = static_cast<const RotateTransformOperation*>(
-              from_operation.Get());
+              from_operation.get());
           if (from_rotation->Axis().IsZero())
             from_rotation = nullptr;
         }
 
         if (to_operation) {
           to_rotation =
-              static_cast<const RotateTransformOperation*>(to_operation.Get());
+              static_cast<const RotateTransformOperation*>(to_operation.get());
           if (to_rotation->Axis().IsZero())
             to_rotation = nullptr;
         }
@@ -370,7 +370,7 @@
               axis.X(), axis.Y(), axis.Z(), 0,
               from_operation ? from_operation->GetType()
                              : to_operation->GetType());
-          from_rotation = identity_rotation.Get();
+          from_rotation = identity_rotation.get();
         }
 
         if (!to_rotation) {
@@ -379,7 +379,7 @@
                 axis.X(), axis.Y(), axis.Z(), 0,
                 from_operation ? from_operation->GetType()
                                : to_operation->GetType());
-          to_rotation = identity_rotation.Get();
+          to_rotation = identity_rotation.get();
         }
 
         FloatBox from_box = *bounds;
diff --git a/third_party/WebKit/Source/platform/transforms/TransformOperations.h b/third_party/WebKit/Source/platform/transforms/TransformOperations.h
index fcef2b0..a4844e38 100644
--- a/third_party/WebKit/Source/platform/transforms/TransformOperations.h
+++ b/third_party/WebKit/Source/platform/transforms/TransformOperations.h
@@ -81,7 +81,7 @@
 
   size_t size() const { return operations_.size(); }
   const TransformOperation* at(size_t index) const {
-    return index < operations_.size() ? operations_.at(index).Get() : 0;
+    return index < operations_.size() ? operations_.at(index).get() : 0;
   }
 
   bool BlendedBoundsForBox(const FloatBox&,
diff --git a/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.cpp b/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.cpp
index 8b5fd5a..7115e14 100644
--- a/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.cpp
+++ b/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.cpp
@@ -298,10 +298,10 @@
 
   // We call isSameSchemeHostPort here instead of canAccess because we want
   // to ignore document.domain effects.
-  if (IsSameSchemeHostPort(target_origin.Get()))
+  if (IsSameSchemeHostPort(target_origin.get()))
     return true;
 
-  if (SecurityPolicy::IsAccessWhiteListed(this, target_origin.Get()))
+  if (SecurityPolicy::IsAccessWhiteListed(this, target_origin.get()))
     return true;
 
   return false;
@@ -587,13 +587,13 @@
     return false;
 
   RefPtr<SecurityOrigin> other = SecurityOrigin::Create(url);
-  return IsSameSchemeHostPort(other.Get());
+  return IsSameSchemeHostPort(other.get());
 }
 
 bool SecurityOrigin::AreSameSchemeHostPort(const KURL& a, const KURL& b) {
   RefPtr<SecurityOrigin> origin_a = SecurityOrigin::Create(a);
   RefPtr<SecurityOrigin> origin_b = SecurityOrigin::Create(b);
-  return origin_b->IsSameSchemeHostPort(origin_a.Get());
+  return origin_b->IsSameSchemeHostPort(origin_a.get());
 }
 
 const KURL& SecurityOrigin::UrlWithUniqueSecurityOrigin() {
diff --git a/third_party/WebKit/Source/platform/weborigin/SecurityOriginHash.h b/third_party/WebKit/Source/platform/weborigin/SecurityOriginHash.h
index b49d214..446b33b5 100644
--- a/third_party/WebKit/Source/platform/weborigin/SecurityOriginHash.h
+++ b/third_party/WebKit/Source/platform/weborigin/SecurityOriginHash.h
@@ -49,7 +49,7 @@
     return StringHasher::HashMemory<sizeof(hash_codes)>(hash_codes);
   }
   static unsigned GetHash(const RefPtr<SecurityOrigin>& origin) {
-    return GetHash(origin.Get());
+    return GetHash(origin.get());
   }
 
   static bool Equal(SecurityOrigin* a, SecurityOrigin* b) {
@@ -71,14 +71,14 @@
     return true;
   }
   static bool Equal(SecurityOrigin* a, const RefPtr<SecurityOrigin>& b) {
-    return Equal(a, b.Get());
+    return Equal(a, b.get());
   }
   static bool Equal(const RefPtr<SecurityOrigin>& a, SecurityOrigin* b) {
-    return Equal(a.Get(), b);
+    return Equal(a.get(), b);
   }
   static bool Equal(const RefPtr<SecurityOrigin>& a,
                     const RefPtr<SecurityOrigin>& b) {
-    return Equal(a.Get(), b.Get());
+    return Equal(a.get(), b.get());
   }
 
   static const bool safe_to_compare_to_empty_or_deleted = false;
diff --git a/third_party/WebKit/Source/platform/weborigin/SecurityOriginTest.cpp b/third_party/WebKit/Source/platform/weborigin/SecurityOriginTest.cpp
index 2ca1a56d5..b3b0345 100644
--- a/third_party/WebKit/Source/platform/weborigin/SecurityOriginTest.cpp
+++ b/third_party/WebKit/Source/platform/weborigin/SecurityOriginTest.cpp
@@ -80,24 +80,24 @@
   RefPtr<SecurityOrigin> file2 =
       SecurityOrigin::CreateFromString("file:///etc/shadow");
 
-  EXPECT_TRUE(file1->IsSameSchemeHostPort(file1.Get()));
-  EXPECT_TRUE(file1->IsSameSchemeHostPort(file2.Get()));
-  EXPECT_TRUE(file2->IsSameSchemeHostPort(file1.Get()));
+  EXPECT_TRUE(file1->IsSameSchemeHostPort(file1.get()));
+  EXPECT_TRUE(file1->IsSameSchemeHostPort(file2.get()));
+  EXPECT_TRUE(file2->IsSameSchemeHostPort(file1.get()));
 
-  EXPECT_TRUE(file1->CanAccess(file1.Get()));
-  EXPECT_TRUE(file1->CanAccess(file2.Get()));
-  EXPECT_TRUE(file2->CanAccess(file1.Get()));
+  EXPECT_TRUE(file1->CanAccess(file1.get()));
+  EXPECT_TRUE(file1->CanAccess(file2.get()));
+  EXPECT_TRUE(file2->CanAccess(file1.get()));
 
   // Block |file1|'s access to local origins. It should now be same-origin
   // with itself, but shouldn't have access to |file2|.
   file1->BlockLocalAccessFromLocalOrigin();
-  EXPECT_TRUE(file1->IsSameSchemeHostPort(file1.Get()));
-  EXPECT_FALSE(file1->IsSameSchemeHostPort(file2.Get()));
-  EXPECT_FALSE(file2->IsSameSchemeHostPort(file1.Get()));
+  EXPECT_TRUE(file1->IsSameSchemeHostPort(file1.get()));
+  EXPECT_FALSE(file1->IsSameSchemeHostPort(file2.get()));
+  EXPECT_FALSE(file2->IsSameSchemeHostPort(file1.get()));
 
-  EXPECT_TRUE(file1->CanAccess(file1.Get()));
-  EXPECT_FALSE(file1->CanAccess(file2.Get()));
-  EXPECT_FALSE(file2->CanAccess(file1.Get()));
+  EXPECT_TRUE(file1->CanAccess(file1.get()));
+  EXPECT_FALSE(file1->CanAccess(file2.get()));
+  EXPECT_FALSE(file2->CanAccess(file1.get()));
 }
 
 TEST_F(SecurityOriginTest, IsPotentiallyTrustworthy) {
@@ -322,11 +322,11 @@
   RefPtr<SecurityOrigin> other4 =
       SecurityOrigin::CreateFromString("https://test.com");
 
-  EXPECT_TRUE(origin->IsSameSchemeHostPortAndSuborigin(origin.Get()));
-  EXPECT_FALSE(origin->IsSameSchemeHostPortAndSuborigin(other1.Get()));
-  EXPECT_FALSE(origin->IsSameSchemeHostPortAndSuborigin(other2.Get()));
-  EXPECT_FALSE(origin->IsSameSchemeHostPortAndSuborigin(other3.Get()));
-  EXPECT_FALSE(origin->IsSameSchemeHostPortAndSuborigin(other4.Get()));
+  EXPECT_TRUE(origin->IsSameSchemeHostPortAndSuborigin(origin.get()));
+  EXPECT_FALSE(origin->IsSameSchemeHostPortAndSuborigin(other1.get()));
+  EXPECT_FALSE(origin->IsSameSchemeHostPortAndSuborigin(other2.get()));
+  EXPECT_FALSE(origin->IsSameSchemeHostPortAndSuborigin(other3.get()));
+  EXPECT_FALSE(origin->IsSameSchemeHostPortAndSuborigin(other4.get()));
 }
 
 TEST_F(SecurityOriginTest, CanAccess) {
@@ -351,7 +351,7 @@
         SecurityOrigin::CreateFromString(tests[i].origin1);
     RefPtr<SecurityOrigin> origin2 =
         SecurityOrigin::CreateFromString(tests[i].origin2);
-    EXPECT_EQ(tests[i].can_access, origin1->CanAccess(origin2.Get()));
+    EXPECT_EQ(tests[i].can_access, origin1->CanAccess(origin2.get()));
   }
 }
 
@@ -479,7 +479,7 @@
     EXPECT_EQ(test.expected_uniqueness, origin->IsUnique());
     EXPECT_EQ(test.expected_origin_string, origin->ToString());
 
-    KURL blob_url = BlobURL::CreatePublicURL(origin.Get());
+    KURL blob_url = BlobURL::CreatePublicURL(origin.get());
     RefPtr<SecurityOrigin> blob_url_origin = SecurityOrigin::Create(blob_url);
     EXPECT_EQ(blob_url_origin->IsUnique(), origin->IsUnique());
     EXPECT_EQ(blob_url_origin->ToString(), origin->ToString());
@@ -492,11 +492,11 @@
   RefPtr<SecurityOrigin> tuple_origin =
       SecurityOrigin::CreateFromString("http://example.com");
 
-  EXPECT_TRUE(unique_origin->IsSameSchemeHostPort(unique_origin.Get()));
+  EXPECT_TRUE(unique_origin->IsSameSchemeHostPort(unique_origin.get()));
   EXPECT_FALSE(SecurityOrigin::CreateUnique()->IsSameSchemeHostPort(
-      unique_origin.Get()));
-  EXPECT_FALSE(tuple_origin->IsSameSchemeHostPort(unique_origin.Get()));
-  EXPECT_FALSE(unique_origin->IsSameSchemeHostPort(tuple_origin.Get()));
+      unique_origin.get()));
+  EXPECT_FALSE(tuple_origin->IsSameSchemeHostPort(unique_origin.get()));
+  EXPECT_FALSE(unique_origin->IsSameSchemeHostPort(tuple_origin.get()));
 }
 
 TEST_F(SecurityOriginTest, CanonicalizeHost) {
diff --git a/third_party/WebKit/Source/platform/weborigin/SecurityPolicy.cpp b/third_party/WebKit/Source/platform/weborigin/SecurityPolicy.cpp
index 85fd494..18dbbb38 100644
--- a/third_party/WebKit/Source/platform/weborigin/SecurityPolicy.cpp
+++ b/third_party/WebKit/Source/platform/weborigin/SecurityPolicy.cpp
@@ -119,7 +119,7 @@
       RefPtr<SecurityOrigin> referrer_origin =
           SecurityOrigin::Create(referrer_url);
       RefPtr<SecurityOrigin> url_origin = SecurityOrigin::Create(url);
-      if (!url_origin->IsSameSchemeHostPort(referrer_origin.Get())) {
+      if (!url_origin->IsSameSchemeHostPort(referrer_origin.get())) {
         String origin = referrer_origin->ToString();
         return Referrer(origin + "/", referrer_policy_no_default);
       }
@@ -129,7 +129,7 @@
       RefPtr<SecurityOrigin> referrer_origin =
           SecurityOrigin::Create(referrer_url);
       RefPtr<SecurityOrigin> url_origin = SecurityOrigin::Create(url);
-      if (!url_origin->IsSameSchemeHostPort(referrer_origin.Get())) {
+      if (!url_origin->IsSameSchemeHostPort(referrer_origin.get())) {
         return Referrer(Referrer::NoReferrer(), referrer_policy_no_default);
       }
       return Referrer(referrer, referrer_policy_no_default);
@@ -145,7 +145,7 @@
       RefPtr<SecurityOrigin> referrer_origin =
           SecurityOrigin::Create(referrer_url);
       RefPtr<SecurityOrigin> url_origin = SecurityOrigin::Create(url);
-      if (!url_origin->IsSameSchemeHostPort(referrer_origin.Get())) {
+      if (!url_origin->IsSameSchemeHostPort(referrer_origin.get())) {
         String origin = referrer_origin->ToString();
         return Referrer(ShouldHideReferrer(url, referrer_url)
                             ? Referrer::NoReferrer()
@@ -190,7 +190,7 @@
   // Early return to avoid initializing the SecurityOrigin.
   if (TrustworthyOriginSet().IsEmpty())
     return false;
-  return IsOriginWhiteListedTrustworthy(*SecurityOrigin::Create(url).Get());
+  return IsOriginWhiteListedTrustworthy(*SecurityOrigin::Create(url).get());
 }
 
 bool SecurityPolicy::IsAccessWhiteListed(const SecurityOrigin* active_origin,
@@ -212,7 +212,7 @@
     const SecurityOrigin* active_origin,
     const KURL& url) {
   RefPtr<SecurityOrigin> target_origin = SecurityOrigin::Create(url);
-  return IsAccessWhiteListed(active_origin, target_origin.Get());
+  return IsAccessWhiteListed(active_origin, target_origin.get());
 }
 
 void SecurityPolicy::AddOriginAccessWhitelistEntry(
diff --git a/third_party/WebKit/Source/platform/wtf/Assertions.h b/third_party/WebKit/Source/platform/wtf/Assertions.h
index de12c5c..506fb0d8 100644
--- a/third_party/WebKit/Source/platform/wtf/Assertions.h
+++ b/third_party/WebKit/Source/platform/wtf/Assertions.h
@@ -61,7 +61,7 @@
 //    https://bugs.chromium.org/p/chromium/issues/entry?template=Security%20Bug
 #if ENABLE_SECURITY_ASSERT
 #define SECURITY_DCHECK(condition) \
-  LOG_IF(FATAL, !(condition)) << "Security DCHECK failed: " #condition ". "
+  LOG_IF(DCHECK, !(condition)) << "Security DCHECK failed: " #condition ". "
 // A SECURITY_CHECK failure is actually not vulnerable.
 #define SECURITY_CHECK(condition) \
   LOG_IF(FATAL, !(condition)) << "Security CHECK failed: " #condition ". "
diff --git a/third_party/WebKit/Source/platform/wtf/FilePrintStream.cpp b/third_party/WebKit/Source/platform/wtf/FilePrintStream.cpp
index 0aa104d..e2c96b76 100644
--- a/third_party/WebKit/Source/platform/wtf/FilePrintStream.cpp
+++ b/third_party/WebKit/Source/platform/wtf/FilePrintStream.cpp
@@ -25,7 +25,6 @@
 
 #include "platform/wtf/FilePrintStream.h"
 
-#include "platform/wtf/PtrUtil.h"
 #include <memory>
 
 namespace WTF {
@@ -45,7 +44,7 @@
   if (!file)
     return std::unique_ptr<FilePrintStream>();
 
-  return WTF::MakeUnique<FilePrintStream>(file);
+  return std::make_unique<FilePrintStream>(file);
 }
 
 void FilePrintStream::Vprintf(const char* format, va_list arg_list) {
diff --git a/third_party/WebKit/Source/platform/wtf/Functional.h b/third_party/WebKit/Source/platform/wtf/Functional.h
index bc5d22b..5edf36c3 100644
--- a/third_party/WebKit/Source/platform/wtf/Functional.h
+++ b/third_party/WebKit/Source/platform/wtf/Functional.h
@@ -278,7 +278,7 @@
 
 template <typename T>
 struct BindUnwrapTraits<WTF::RefPtr<T>> {
-  static T* Unwrap(const WTF::RefPtr<T>& wrapped) { return wrapped.Get(); }
+  static T* Unwrap(const WTF::RefPtr<T>& wrapped) { return wrapped.get(); }
 };
 
 template <typename T>
diff --git a/third_party/WebKit/Source/platform/wtf/FunctionalTest.cpp b/third_party/WebKit/Source/platform/wtf/FunctionalTest.cpp
index 3b6e262..d8fe8aa 100644
--- a/third_party/WebKit/Source/platform/wtf/FunctionalTest.cpp
+++ b/third_party/WebKit/Source/platform/wtf/FunctionalTest.cpp
@@ -25,10 +25,11 @@
 
 #include "platform/wtf/Functional.h"
 
+#include <memory>
+#include <utility>
 #include "platform/wtf/RefCounted.h"
 #include "platform/wtf/WeakPtr.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include <utility>
 
 namespace WTF {
 
@@ -306,13 +307,13 @@
 }
 
 TEST(FunctionalTest, MemberFunctionBindByUniquePtr) {
-  Function<int()> function1 = WTF::Bind(&A::F, WTF::MakeUnique<A>(10));
+  Function<int()> function1 = WTF::Bind(&A::F, std::make_unique<A>(10));
   EXPECT_EQ(10, function1());
 }
 
 TEST(FunctionalTest, MemberFunctionBindByPassedUniquePtr) {
   Function<int()> function1 =
-      WTF::Bind(&A::F, WTF::Passed(WTF::MakeUnique<A>(10)));
+      WTF::Bind(&A::F, WTF::Passed(std::make_unique<A>(10)));
   EXPECT_EQ(10, function1());
 }
 
@@ -369,7 +370,7 @@
   RefPtr<Number> five = Number::Create(5);
   EXPECT_EQ(1, five->RefCount());
   Function<int()> multiply_five_by_two_function =
-      WTF::Bind(MultiplyNumberByTwo, WTF::Unretained(five.Get()));
+      WTF::Bind(MultiplyNumberByTwo, WTF::Unretained(five.get()));
   EXPECT_EQ(1, five->RefCount());
   EXPECT_EQ(10, multiply_five_by_two_function());
   EXPECT_EQ(1, five->RefCount());
diff --git a/third_party/WebKit/Source/platform/wtf/HashFunctions.h b/third_party/WebKit/Source/platform/wtf/HashFunctions.h
index f123973..1f7b96a 100644
--- a/third_party/WebKit/Source/platform/wtf/HashFunctions.h
+++ b/third_party/WebKit/Source/platform/wtf/HashFunctions.h
@@ -149,7 +149,7 @@
 template <typename T>
 struct RefPtrHash : PtrHash<T> {
   using PtrHash<T>::GetHash;
-  static unsigned GetHash(const RefPtr<T>& key) { return GetHash(key.Get()); }
+  static unsigned GetHash(const RefPtr<T>& key) { return GetHash(key.get()); }
   using PtrHash<T>::Equal;
   static bool Equal(const RefPtr<T>& a, const RefPtr<T>& b) { return a == b; }
   static bool Equal(T* a, const RefPtr<T>& b) { return a == b; }
diff --git a/third_party/WebKit/Source/platform/wtf/HashMapTest.cpp b/third_party/WebKit/Source/platform/wtf/HashMapTest.cpp
index 534d4e9..2c1b809 100644
--- a/third_party/WebKit/Source/platform/wtf/HashMapTest.cpp
+++ b/third_party/WebKit/Source/platform/wtf/HashMapTest.cpp
@@ -175,7 +175,7 @@
   EXPECT_EQ(1, DummyRefCounted::ref_invokes_count_);
   EXPECT_EQ(1, map.at(ptr));
 
-  DummyRefCounted* raw_ptr = ptr.Get();
+  DummyRefCounted* raw_ptr = ptr.get();
 
   EXPECT_TRUE(map.Contains(raw_ptr));
   EXPECT_NE(map.end(), map.find(raw_ptr));
@@ -251,7 +251,7 @@
   EXPECT_EQ(simple1, map.at(1));
 
   IntSimpleMap::AddResult result2 =
-      map.insert(1, WTF::MakeUnique<SimpleClass>(2));
+      map.insert(1, std::make_unique<SimpleClass>(2));
   EXPECT_FALSE(result2.is_new_entry);
   EXPECT_EQ(1, result.stored_value->key);
   EXPECT_EQ(1, result.stored_value->value->V());
diff --git a/third_party/WebKit/Source/platform/wtf/HashSetTest.cpp b/third_party/WebKit/Source/platform/wtf/HashSetTest.cpp
index 5b25fe59..2dd6027 100644
--- a/third_party/WebKit/Source/platform/wtf/HashSetTest.cpp
+++ b/third_party/WebKit/Source/platform/wtf/HashSetTest.cpp
@@ -130,8 +130,8 @@
   deleted2 = false;
   {
     OwnPtrSet set;
-    set.insert(WTF::MakeUnique<Dummy>(deleted1));
-    set.insert(WTF::MakeUnique<Dummy>(deleted2));
+    set.insert(std::make_unique<Dummy>(deleted1));
+    set.insert(std::make_unique<Dummy>(deleted2));
   }
   EXPECT_TRUE(deleted1);
   EXPECT_TRUE(deleted2);
@@ -187,7 +187,7 @@
   // Referenced only once (to store a copy in the container).
   EXPECT_EQ(1, DummyRefCounted::ref_invokes_count_);
 
-  DummyRefCounted* raw_ptr = ptr.Get();
+  DummyRefCounted* raw_ptr = ptr.get();
 
   EXPECT_TRUE(set.Contains(raw_ptr));
   EXPECT_NE(set.end(), set.find(raw_ptr));
diff --git a/third_party/WebKit/Source/platform/wtf/HashTable.h b/third_party/WebKit/Source/platform/wtf/HashTable.h
index 256ed5b8..a6c7f26 100644
--- a/third_party/WebKit/Source/platform/wtf/HashTable.h
+++ b/third_party/WebKit/Source/platform/wtf/HashTable.h
@@ -147,14 +147,14 @@
 
  public:
   static std::unique_ptr<HashTableStats> Create() {
-    return base::MakeUnique<HashTableStats>();
+    return std::make_unique<HashTableStats>();
   }
 
   static std::unique_ptr<HashTableStats> copy(
       const std::unique_ptr<HashTableStats>& other) {
     if (!other)
       return nullptr;
-    return base::MakeUnique<HashTableStats>(*other);
+    return std::make_unique<HashTableStats>(*other);
   }
 
   static void swap(std::unique_ptr<HashTableStats>& stats,
diff --git a/third_party/WebKit/Source/platform/wtf/HashTraits.h b/third_party/WebKit/Source/platform/wtf/HashTraits.h
index c4d75a75..0012c7e 100644
--- a/third_party/WebKit/Source/platform/wtf/HashTraits.h
+++ b/third_party/WebKit/Source/platform/wtf/HashTraits.h
@@ -252,7 +252,7 @@
   }
 
   typedef P* PeekOutType;
-  static PeekOutType Peek(const RefPtr<P>& value) { return value.Get(); }
+  static PeekOutType Peek(const RefPtr<P>& value) { return value.get(); }
 };
 
 template <typename T>
diff --git a/third_party/WebKit/Source/platform/wtf/ListHashSetTest.cpp b/third_party/WebKit/Source/platform/wtf/ListHashSetTest.cpp
index 08993e1..024b785 100644
--- a/third_party/WebKit/Source/platform/wtf/ListHashSetTest.cpp
+++ b/third_party/WebKit/Source/platform/wtf/ListHashSetTest.cpp
@@ -412,7 +412,7 @@
   EXPECT_EQ(ptr, set.front());
   EXPECT_EQ(1, DummyRefCounted::ref_invokes_count_);
 
-  DummyRefCounted* raw_ptr = ptr.Get();
+  DummyRefCounted* raw_ptr = ptr.get();
 
   EXPECT_TRUE(set.Contains(ptr));
   EXPECT_TRUE(set.Contains(raw_ptr));
@@ -586,8 +586,8 @@
   deleted2 = false;
   {
     OwnPtrSet set;
-    set.insert(WTF::MakeUnique<Dummy>(deleted1));
-    set.insert(WTF::MakeUnique<Dummy>(deleted2));
+    set.insert(std::make_unique<Dummy>(deleted1));
+    set.insert(std::make_unique<Dummy>(deleted2));
   }
   EXPECT_TRUE(deleted1);
   EXPECT_TRUE(deleted2);
diff --git a/third_party/WebKit/Source/platform/wtf/RefPtr.h b/third_party/WebKit/Source/platform/wtf/RefPtr.h
index 8b18772e..a635d69 100644
--- a/third_party/WebKit/Source/platform/wtf/RefPtr.h
+++ b/third_party/WebKit/Source/platform/wtf/RefPtr.h
@@ -73,7 +73,7 @@
   ALWAYS_INLINE RefPtr(const RefPtr& o) : ptr_(o.ptr_) { RefIfNotNull(ptr_); }
   template <typename U>
   RefPtr(const RefPtr<U>& o, EnsurePtrConvertibleArgDecl(U, T))
-      : ptr_(o.Get()) {
+      : ptr_(o.get()) {
     RefIfNotNull(ptr_);
   }
   RefPtr(RefPtr&& o) : ptr_(o.ptr_) { o.ptr_ = nullptr; }
@@ -83,7 +83,7 @@
 
   ALWAYS_INLINE ~RefPtr() { DerefIfNotNull(ptr_); }
 
-  ALWAYS_INLINE T* Get() const { return ptr_; }
+  ALWAYS_INLINE T* get() const { return ptr_; }
   T* LeakRef() WARN_UNUSED_RESULT;
 
   T& operator*() const { return *ptr_; }
@@ -144,57 +144,57 @@
 
 template <typename T, typename U>
 inline bool operator==(const RefPtr<T>& a, const RefPtr<U>& b) {
-  return a.Get() == b.Get();
+  return a.get() == b.get();
 }
 
 template <typename T, typename U>
 inline bool operator==(const RefPtr<T>& a, U* b) {
-  return a.Get() == b;
+  return a.get() == b;
 }
 
 template <typename T, typename U>
 inline bool operator==(T* a, const RefPtr<U>& b) {
-  return a == b.Get();
+  return a == b.get();
 }
 
 template <typename T>
 inline bool operator==(const RefPtr<T>& a, std::nullptr_t) {
-  return !a.Get();
+  return !a.get();
 }
 
 template <typename T>
 inline bool operator==(std::nullptr_t, const RefPtr<T>& b) {
-  return !b.Get();
+  return !b.get();
 }
 
 template <typename T, typename U>
 inline bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b) {
-  return a.Get() != b.Get();
+  return a.get() != b.get();
 }
 
 template <typename T, typename U>
 inline bool operator!=(const RefPtr<T>& a, U* b) {
-  return a.Get() != b;
+  return a.get() != b;
 }
 
 template <typename T, typename U>
 inline bool operator!=(T* a, const RefPtr<U>& b) {
-  return a != b.Get();
+  return a != b.get();
 }
 
 template <typename T>
 inline bool operator!=(const RefPtr<T>& a, std::nullptr_t) {
-  return a.Get();
+  return a.get();
 }
 
 template <typename T>
 inline bool operator!=(std::nullptr_t, const RefPtr<T>& b) {
-  return b.Get();
+  return b.get();
 }
 
 template <typename T>
 inline T* GetPtr(const RefPtr<T>& p) {
-  return p.Get();
+  return p.get();
 }
 
 template <typename T>
@@ -205,7 +205,7 @@
   ALWAYS_INLINE RefPtrValuePeeker(T* p) : ptr_(p) {}
   ALWAYS_INLINE RefPtrValuePeeker(std::nullptr_t) : ptr_(nullptr) {}
   template <typename U>
-  RefPtrValuePeeker(const RefPtr<U>& p) : ptr_(p.Get()) {}
+  RefPtrValuePeeker(const RefPtr<U>& p) : ptr_(p.get()) {}
 
   ALWAYS_INLINE operator T*() const { return ptr_; }
 
diff --git a/third_party/WebKit/Source/platform/wtf/RefPtrTest.cpp b/third_party/WebKit/Source/platform/wtf/RefPtrTest.cpp
index c82c15e..7324a6b 100644
--- a/third_party/WebKit/Source/platform/wtf/RefPtrTest.cpp
+++ b/third_party/WebKit/Source/platform/wtf/RefPtrTest.cpp
@@ -25,7 +25,7 @@
   RefPtr<StringImpl> string = StringImpl::Create("test");
   EXPECT_TRUE(string);
   EXPECT_TRUE(string->HasOneRef());
-  StringImpl* raw = string.Get();
+  StringImpl* raw = string.get();
   StringImpl* leaked = string.LeakRef();
   EXPECT_TRUE(!string);
   EXPECT_TRUE(leaked);
diff --git a/third_party/WebKit/Source/platform/wtf/TreeNodeTest.cpp b/third_party/WebKit/Source/platform/wtf/TreeNodeTest.cpp
index 986fc4d..1d37296 100644
--- a/third_party/WebKit/Source/platform/wtf/TreeNodeTest.cpp
+++ b/third_party/WebKit/Source/platform/wtf/TreeNodeTest.cpp
@@ -41,17 +41,17 @@
   RefPtr<TestTree> first_child = TestTree::Create();
   RefPtr<TestTree> last_child = TestTree::Create();
 
-  root->AppendChild(first_child.Get());
-  EXPECT_EQ(root->FirstChild(), first_child.Get());
-  EXPECT_EQ(root->LastChild(), first_child.Get());
-  EXPECT_EQ(first_child->Parent(), root.Get());
+  root->AppendChild(first_child.get());
+  EXPECT_EQ(root->FirstChild(), first_child.get());
+  EXPECT_EQ(root->LastChild(), first_child.get());
+  EXPECT_EQ(first_child->Parent(), root.get());
 
-  root->AppendChild(last_child.Get());
-  EXPECT_EQ(root->FirstChild(), first_child.Get());
-  EXPECT_EQ(root->LastChild(), last_child.Get());
-  EXPECT_EQ(last_child->Previous(), first_child.Get());
-  EXPECT_EQ(first_child->Next(), last_child.Get());
-  EXPECT_EQ(last_child->Parent(), root.Get());
+  root->AppendChild(last_child.get());
+  EXPECT_EQ(root->FirstChild(), first_child.get());
+  EXPECT_EQ(root->LastChild(), last_child.get());
+  EXPECT_EQ(last_child->Previous(), first_child.get());
+  EXPECT_EQ(first_child->Next(), last_child.get());
+  EXPECT_EQ(last_child->Parent(), root.get());
 }
 
 TEST(TreeNodeTest, InsertBefore) {
@@ -61,28 +61,28 @@
   RefPtr<TestTree> last_child = TestTree::Create();
 
   // Inserting single node
-  root->InsertBefore(last_child.Get(), 0);
-  EXPECT_EQ(last_child->Parent(), root.Get());
-  EXPECT_EQ(root->FirstChild(), last_child.Get());
-  EXPECT_EQ(root->LastChild(), last_child.Get());
+  root->InsertBefore(last_child.get(), 0);
+  EXPECT_EQ(last_child->Parent(), root.get());
+  EXPECT_EQ(root->FirstChild(), last_child.get());
+  EXPECT_EQ(root->LastChild(), last_child.get());
 
   // Then prepend
-  root->InsertBefore(first_child.Get(), last_child.Get());
-  EXPECT_EQ(first_child->Parent(), root.Get());
-  EXPECT_EQ(root->FirstChild(), first_child.Get());
-  EXPECT_EQ(root->LastChild(), last_child.Get());
-  EXPECT_EQ(first_child->Next(), last_child.Get());
-  EXPECT_EQ(first_child.Get(), last_child->Previous());
+  root->InsertBefore(first_child.get(), last_child.get());
+  EXPECT_EQ(first_child->Parent(), root.get());
+  EXPECT_EQ(root->FirstChild(), first_child.get());
+  EXPECT_EQ(root->LastChild(), last_child.get());
+  EXPECT_EQ(first_child->Next(), last_child.get());
+  EXPECT_EQ(first_child.get(), last_child->Previous());
 
   // Inserting in the middle
-  root->InsertBefore(middle_child.Get(), last_child.Get());
-  EXPECT_EQ(middle_child->Parent(), root.Get());
-  EXPECT_EQ(root->FirstChild(), first_child.Get());
-  EXPECT_EQ(root->LastChild(), last_child.Get());
-  EXPECT_EQ(middle_child->Previous(), first_child.Get());
-  EXPECT_EQ(middle_child->Next(), last_child.Get());
-  EXPECT_EQ(first_child->Next(), middle_child.Get());
-  EXPECT_EQ(last_child->Previous(), middle_child.Get());
+  root->InsertBefore(middle_child.get(), last_child.get());
+  EXPECT_EQ(middle_child->Parent(), root.get());
+  EXPECT_EQ(root->FirstChild(), first_child.get());
+  EXPECT_EQ(root->LastChild(), last_child.get());
+  EXPECT_EQ(middle_child->Previous(), first_child.get());
+  EXPECT_EQ(middle_child->Next(), last_child.get());
+  EXPECT_EQ(first_child->Next(), middle_child.get());
+  EXPECT_EQ(last_child->Previous(), middle_child.get());
 }
 
 TEST(TreeNodeTest, RemoveSingle) {
@@ -90,13 +90,13 @@
   RefPtr<TestTree> child = TestTree::Create();
   RefPtr<TestTree> null_node;
 
-  root->AppendChild(child.Get());
-  root->RemoveChild(child.Get());
-  EXPECT_EQ(child->Next(), null_node.Get());
-  EXPECT_EQ(child->Previous(), null_node.Get());
-  EXPECT_EQ(child->Parent(), null_node.Get());
-  EXPECT_EQ(root->FirstChild(), null_node.Get());
-  EXPECT_EQ(root->LastChild(), null_node.Get());
+  root->AppendChild(child.get());
+  root->RemoveChild(child.get());
+  EXPECT_EQ(child->Next(), null_node.get());
+  EXPECT_EQ(child->Previous(), null_node.get());
+  EXPECT_EQ(child->Parent(), null_node.get());
+  EXPECT_EQ(root->FirstChild(), null_node.get());
+  EXPECT_EQ(root->LastChild(), null_node.get());
 }
 
 class Trio {
@@ -108,9 +108,9 @@
         last_child(TestTree::Create()) {}
 
   void AppendChildren() {
-    root->AppendChild(first_child.Get());
-    root->AppendChild(middle_child.Get());
-    root->AppendChild(last_child.Get());
+    root->AppendChild(first_child.get());
+    root->AppendChild(middle_child.get());
+    root->AppendChild(last_child.get());
   }
 
   RefPtr<TestTree> root;
@@ -123,12 +123,12 @@
   Trio trio;
   trio.AppendChildren();
 
-  trio.root->RemoveChild(trio.middle_child.Get());
+  trio.root->RemoveChild(trio.middle_child.get());
   EXPECT_TRUE(trio.middle_child->Orphan());
-  EXPECT_EQ(trio.first_child->Next(), trio.last_child.Get());
-  EXPECT_EQ(trio.last_child->Previous(), trio.first_child.Get());
-  EXPECT_EQ(trio.root->FirstChild(), trio.first_child.Get());
-  EXPECT_EQ(trio.root->LastChild(), trio.last_child.Get());
+  EXPECT_EQ(trio.first_child->Next(), trio.last_child.get());
+  EXPECT_EQ(trio.last_child->Previous(), trio.first_child.get());
+  EXPECT_EQ(trio.root->FirstChild(), trio.first_child.get());
+  EXPECT_EQ(trio.root->LastChild(), trio.last_child.get());
 }
 
 TEST(TreeNodeTest, RemoveLast) {
@@ -136,11 +136,11 @@
   Trio trio;
   trio.AppendChildren();
 
-  trio.root->RemoveChild(trio.last_child.Get());
+  trio.root->RemoveChild(trio.last_child.get());
   EXPECT_TRUE(trio.last_child->Orphan());
-  EXPECT_EQ(trio.middle_child->Next(), null_node.Get());
-  EXPECT_EQ(trio.root->FirstChild(), trio.first_child.Get());
-  EXPECT_EQ(trio.root->LastChild(), trio.middle_child.Get());
+  EXPECT_EQ(trio.middle_child->Next(), null_node.get());
+  EXPECT_EQ(trio.root->FirstChild(), trio.first_child.get());
+  EXPECT_EQ(trio.root->LastChild(), trio.middle_child.get());
 }
 
 TEST(TreeNodeTest, RemoveFirst) {
@@ -148,11 +148,11 @@
   Trio trio;
   trio.AppendChildren();
 
-  trio.root->RemoveChild(trio.first_child.Get());
+  trio.root->RemoveChild(trio.first_child.get());
   EXPECT_TRUE(trio.first_child->Orphan());
-  EXPECT_EQ(trio.middle_child->Previous(), null_node.Get());
-  EXPECT_EQ(trio.root->FirstChild(), trio.middle_child.Get());
-  EXPECT_EQ(trio.root->LastChild(), trio.last_child.Get());
+  EXPECT_EQ(trio.middle_child->Previous(), null_node.get());
+  EXPECT_EQ(trio.root->FirstChild(), trio.middle_child.get());
+  EXPECT_EQ(trio.root->LastChild(), trio.last_child.get());
 }
 
 TEST(TreeNodeTest, TakeChildrenFrom) {
@@ -160,13 +160,13 @@
   Trio trio;
   trio.AppendChildren();
 
-  new_parent->TakeChildrenFrom(trio.root.Get());
+  new_parent->TakeChildrenFrom(trio.root.get());
 
   EXPECT_FALSE(trio.root->HasChildren());
   EXPECT_TRUE(new_parent->HasChildren());
-  EXPECT_EQ(trio.first_child.Get(), new_parent->FirstChild());
-  EXPECT_EQ(trio.middle_child.Get(), new_parent->FirstChild()->Next());
-  EXPECT_EQ(trio.last_child.Get(), new_parent->LastChild());
+  EXPECT_EQ(trio.first_child.get(), new_parent->FirstChild());
+  EXPECT_EQ(trio.middle_child.get(), new_parent->FirstChild()->Next());
+  EXPECT_EQ(trio.last_child.get(), new_parent->LastChild());
 }
 
 class TrioWithGrandChild : public Trio {
@@ -175,7 +175,7 @@
 
   void AppendChildren() {
     Trio::AppendChildren();
-    middle_child->AppendChild(grand_child.Get());
+    middle_child->AppendChild(grand_child.get());
   }
 
   RefPtr<TestTree> grand_child;
@@ -185,12 +185,12 @@
   TrioWithGrandChild trio;
   trio.AppendChildren();
 
-  TestTree* order[] = {trio.root.Get(), trio.first_child.Get(),
-                       trio.middle_child.Get(), trio.grand_child.Get(),
-                       trio.last_child.Get()};
+  TestTree* order[] = {trio.root.get(), trio.first_child.get(),
+                       trio.middle_child.get(), trio.grand_child.get(),
+                       trio.last_child.get()};
 
   unsigned order_index = 0;
-  for (TestTree *node = trio.root.Get(); node;
+  for (TestTree *node = trio.root.get(); node;
        node = TraverseNext(node), order_index++)
     EXPECT_EQ(node, order[order_index]);
   EXPECT_EQ(order_index, sizeof(order) / sizeof(TestTree*));
@@ -200,12 +200,12 @@
   TrioWithGrandChild trio;
   trio.AppendChildren();
 
-  TestTree* order[] = {trio.first_child.Get(), trio.grand_child.Get(),
-                       trio.middle_child.Get(), trio.last_child.Get(),
-                       trio.root.Get()};
+  TestTree* order[] = {trio.first_child.get(), trio.grand_child.get(),
+                       trio.middle_child.get(), trio.last_child.get(),
+                       trio.root.get()};
 
   unsigned order_index = 0;
-  for (TestTree *node = TraverseFirstPostOrder(trio.root.Get()); node;
+  for (TestTree *node = TraverseFirstPostOrder(trio.root.get()); node;
        node = TraverseNextPostOrder(node), order_index++)
     EXPECT_EQ(node, order[order_index]);
   EXPECT_EQ(order_index, sizeof(order) / sizeof(TestTree*));
diff --git a/third_party/WebKit/Source/platform/wtf/text/CString.h b/third_party/WebKit/Source/platform/wtf/text/CString.h
index a773c137..b9e7177 100644
--- a/third_party/WebKit/Source/platform/wtf/text/CString.h
+++ b/third_party/WebKit/Source/platform/wtf/text/CString.h
@@ -91,7 +91,7 @@
 
   bool IsSafeToSendToAnotherThread() const;
 
-  CStringImpl* Impl() const { return buffer_.Get(); }
+  CStringImpl* Impl() const { return buffer_.get(); }
 
  private:
   RefPtr<CStringImpl> buffer_;
diff --git a/third_party/WebKit/Source/platform/wtf/text/StringHash.h b/third_party/WebKit/Source/platform/wtf/text/StringHash.h
index a9dfaff..022e9e9b 100644
--- a/third_party/WebKit/Source/platform/wtf/text/StringHash.h
+++ b/third_party/WebKit/Source/platform/wtf/text/StringHash.h
@@ -62,7 +62,7 @@
     return key->GetHash();
   }
   static bool Equal(const RefPtr<StringImpl>& a, const RefPtr<StringImpl>& b) {
-    return Equal(a.Get(), b.Get());
+    return Equal(a.get(), b.get());
   }
 
   static unsigned GetHash(const String& key) { return key.Impl()->GetHash(); }
@@ -113,11 +113,11 @@
   }
 
   static unsigned GetHash(const RefPtr<StringImpl>& key) {
-    return GetHash(key.Get());
+    return GetHash(key.get());
   }
 
   static bool Equal(const RefPtr<StringImpl>& a, const RefPtr<StringImpl>& b) {
-    return Equal(a.Get(), b.Get());
+    return Equal(a.get(), b.get());
   }
 
   static unsigned GetHash(const String& key) { return GetHash(key.Impl()); }
diff --git a/third_party/WebKit/Source/platform/wtf/text/StringImplTest.cpp b/third_party/WebKit/Source/platform/wtf/text/StringImplTest.cpp
index bff44b29..d328a7d 100644
--- a/third_party/WebKit/Source/platform/wtf/text/StringImplTest.cpp
+++ b/third_party/WebKit/Source/platform/wtf/text/StringImplTest.cpp
@@ -48,27 +48,27 @@
   EXPECT_TRUE(test_string_impl->Is8Bit());
   EXPECT_TRUE(StringImpl::Create("a\xE1")->Is8Bit());
 
-  EXPECT_TRUE(Equal(test_string_impl.Get(),
-                    StringImpl::Create("link")->LowerASCII().Get()));
-  EXPECT_TRUE(Equal(test_string_impl.Get(),
-                    StringImpl::Create("LINK")->LowerASCII().Get()));
-  EXPECT_TRUE(Equal(test_string_impl.Get(),
-                    StringImpl::Create("lInk")->LowerASCII().Get()));
+  EXPECT_TRUE(Equal(test_string_impl.get(),
+                    StringImpl::Create("link")->LowerASCII().get()));
+  EXPECT_TRUE(Equal(test_string_impl.get(),
+                    StringImpl::Create("LINK")->LowerASCII().get()));
+  EXPECT_TRUE(Equal(test_string_impl.get(),
+                    StringImpl::Create("lInk")->LowerASCII().get()));
 
-  EXPECT_TRUE(Equal(StringImpl::Create("LINK")->LowerUnicode().Get(),
-                    StringImpl::Create("LINK")->LowerASCII().Get()));
-  EXPECT_TRUE(Equal(StringImpl::Create("lInk")->LowerUnicode().Get(),
-                    StringImpl::Create("lInk")->LowerASCII().Get()));
+  EXPECT_TRUE(Equal(StringImpl::Create("LINK")->LowerUnicode().get(),
+                    StringImpl::Create("LINK")->LowerASCII().get()));
+  EXPECT_TRUE(Equal(StringImpl::Create("lInk")->LowerUnicode().get(),
+                    StringImpl::Create("lInk")->LowerASCII().get()));
 
-  EXPECT_TRUE(Equal(StringImpl::Create("a\xE1").Get(),
-                    StringImpl::Create("A\xE1")->LowerASCII().Get()));
-  EXPECT_TRUE(Equal(StringImpl::Create("a\xC1").Get(),
-                    StringImpl::Create("A\xC1")->LowerASCII().Get()));
+  EXPECT_TRUE(Equal(StringImpl::Create("a\xE1").get(),
+                    StringImpl::Create("A\xE1")->LowerASCII().get()));
+  EXPECT_TRUE(Equal(StringImpl::Create("a\xC1").get(),
+                    StringImpl::Create("A\xC1")->LowerASCII().get()));
 
-  EXPECT_FALSE(Equal(StringImpl::Create("a\xE1").Get(),
-                     StringImpl::Create("a\xC1")->LowerASCII().Get()));
-  EXPECT_FALSE(Equal(StringImpl::Create("A\xE1").Get(),
-                     StringImpl::Create("A\xC1")->LowerASCII().Get()));
+  EXPECT_FALSE(Equal(StringImpl::Create("a\xE1").get(),
+                     StringImpl::Create("a\xC1")->LowerASCII().get()));
+  EXPECT_FALSE(Equal(StringImpl::Create("A\xE1").get(),
+                     StringImpl::Create("A\xC1")->LowerASCII().get()));
 
   static const UChar kTest[5] = {0x006c, 0x0069, 0x006e, 0x006b, 0};  // link
   static const UChar kTestCapitalized[5] = {0x004c, 0x0049, 0x004e, 0x004b,
@@ -77,11 +77,11 @@
   RefPtr<StringImpl> test_string_impl16 = StringImpl::Create(kTest, 4);
   EXPECT_FALSE(test_string_impl16->Is8Bit());
 
-  EXPECT_TRUE(Equal(test_string_impl16.Get(),
-                    StringImpl::Create(kTest, 4)->LowerASCII().Get()));
+  EXPECT_TRUE(Equal(test_string_impl16.get(),
+                    StringImpl::Create(kTest, 4)->LowerASCII().get()));
   EXPECT_TRUE(
-      Equal(test_string_impl16.Get(),
-            StringImpl::Create(kTestCapitalized, 4)->LowerASCII().Get()));
+      Equal(test_string_impl16.get(),
+            StringImpl::Create(kTestCapitalized, 4)->LowerASCII().get()));
 
   static const UChar kTestWithNonASCII[3] = {0x0061, 0x00e1, 0};  // a\xE1
   static const UChar kTestWithNonASCIIComparison[3] = {0x0061, 0x00c1,
@@ -93,11 +93,11 @@
   RefPtr<const StringImpl> const_ref = test_string_impl->IsolatedCopy();
   DCHECK(const_ref->HasOneRef());
   EXPECT_TRUE(Equal(
-      StringImpl::Create(kTestWithNonASCII, 2).Get(),
-      StringImpl::Create(kTestWithNonASCIICapitalized, 2)->LowerASCII().Get()));
+      StringImpl::Create(kTestWithNonASCII, 2).get(),
+      StringImpl::Create(kTestWithNonASCIICapitalized, 2)->LowerASCII().get()));
   EXPECT_FALSE(Equal(
-      StringImpl::Create(kTestWithNonASCII, 2).Get(),
-      StringImpl::Create(kTestWithNonASCIIComparison, 2)->LowerASCII().Get()));
+      StringImpl::Create(kTestWithNonASCII, 2).get(),
+      StringImpl::Create(kTestWithNonASCIIComparison, 2)->LowerASCII().get()));
 }
 
 TEST(StringImplTest, UpperASCII) {
@@ -105,27 +105,27 @@
   EXPECT_TRUE(test_string_impl->Is8Bit());
   EXPECT_TRUE(StringImpl::Create("a\xE1")->Is8Bit());
 
-  EXPECT_TRUE(Equal(test_string_impl.Get(),
-                    StringImpl::Create("link")->UpperASCII().Get()));
-  EXPECT_TRUE(Equal(test_string_impl.Get(),
-                    StringImpl::Create("LINK")->UpperASCII().Get()));
-  EXPECT_TRUE(Equal(test_string_impl.Get(),
-                    StringImpl::Create("lInk")->UpperASCII().Get()));
+  EXPECT_TRUE(Equal(test_string_impl.get(),
+                    StringImpl::Create("link")->UpperASCII().get()));
+  EXPECT_TRUE(Equal(test_string_impl.get(),
+                    StringImpl::Create("LINK")->UpperASCII().get()));
+  EXPECT_TRUE(Equal(test_string_impl.get(),
+                    StringImpl::Create("lInk")->UpperASCII().get()));
 
-  EXPECT_TRUE(Equal(StringImpl::Create("LINK")->UpperUnicode().Get(),
-                    StringImpl::Create("LINK")->UpperASCII().Get()));
-  EXPECT_TRUE(Equal(StringImpl::Create("lInk")->UpperUnicode().Get(),
-                    StringImpl::Create("lInk")->UpperASCII().Get()));
+  EXPECT_TRUE(Equal(StringImpl::Create("LINK")->UpperUnicode().get(),
+                    StringImpl::Create("LINK")->UpperASCII().get()));
+  EXPECT_TRUE(Equal(StringImpl::Create("lInk")->UpperUnicode().get(),
+                    StringImpl::Create("lInk")->UpperASCII().get()));
 
-  EXPECT_TRUE(Equal(StringImpl::Create("A\xE1").Get(),
-                    StringImpl::Create("a\xE1")->UpperASCII().Get()));
-  EXPECT_TRUE(Equal(StringImpl::Create("A\xC1").Get(),
-                    StringImpl::Create("a\xC1")->UpperASCII().Get()));
+  EXPECT_TRUE(Equal(StringImpl::Create("A\xE1").get(),
+                    StringImpl::Create("a\xE1")->UpperASCII().get()));
+  EXPECT_TRUE(Equal(StringImpl::Create("A\xC1").get(),
+                    StringImpl::Create("a\xC1")->UpperASCII().get()));
 
-  EXPECT_FALSE(Equal(StringImpl::Create("A\xE1").Get(),
-                     StringImpl::Create("a\xC1")->UpperASCII().Get()));
-  EXPECT_FALSE(Equal(StringImpl::Create("A\xE1").Get(),
-                     StringImpl::Create("A\xC1")->UpperASCII().Get()));
+  EXPECT_FALSE(Equal(StringImpl::Create("A\xE1").get(),
+                     StringImpl::Create("a\xC1")->UpperASCII().get()));
+  EXPECT_FALSE(Equal(StringImpl::Create("A\xE1").get(),
+                     StringImpl::Create("A\xC1")->UpperASCII().get()));
 
   static const UChar kTest[5] = {0x006c, 0x0069, 0x006e, 0x006b, 0};  // link
   static const UChar kTestCapitalized[5] = {0x004c, 0x0049, 0x004e, 0x004b,
@@ -135,11 +135,11 @@
       StringImpl::Create(kTestCapitalized, 4);
   EXPECT_FALSE(test_string_impl16->Is8Bit());
 
-  EXPECT_TRUE(Equal(test_string_impl16.Get(),
-                    StringImpl::Create(kTest, 4)->UpperASCII().Get()));
+  EXPECT_TRUE(Equal(test_string_impl16.get(),
+                    StringImpl::Create(kTest, 4)->UpperASCII().get()));
   EXPECT_TRUE(
-      Equal(test_string_impl16.Get(),
-            StringImpl::Create(kTestCapitalized, 4)->UpperASCII().Get()));
+      Equal(test_string_impl16.get(),
+            StringImpl::Create(kTestCapitalized, 4)->UpperASCII().get()));
 
   static const UChar kTestWithNonASCII[3] = {0x0061, 0x00e1, 0};  // a\xE1
   static const UChar kTestWithNonASCIIComparison[3] = {0x0061, 0x00c1,
@@ -151,11 +151,11 @@
   RefPtr<const StringImpl> const_ref = test_string_impl->IsolatedCopy();
   DCHECK(const_ref->HasOneRef());
   EXPECT_TRUE(
-      Equal(StringImpl::Create(kTestWithNonASCIICapitalized, 2).Get(),
-            StringImpl::Create(kTestWithNonASCII, 2)->UpperASCII().Get()));
+      Equal(StringImpl::Create(kTestWithNonASCIICapitalized, 2).get(),
+            StringImpl::Create(kTestWithNonASCII, 2)->UpperASCII().get()));
   EXPECT_FALSE(Equal(
-      StringImpl::Create(kTestWithNonASCIICapitalized, 2).Get(),
-      StringImpl::Create(kTestWithNonASCIIComparison, 2)->UpperASCII().Get()));
+      StringImpl::Create(kTestWithNonASCIICapitalized, 2).get(),
+      StringImpl::Create(kTestWithNonASCIIComparison, 2)->UpperASCII().get()));
 }
 
 }  // namespace WTF
diff --git a/third_party/WebKit/Source/platform/wtf/text/StringViewTest.cpp b/third_party/WebKit/Source/platform/wtf/text/StringViewTest.cpp
index d7e4c64..6173187 100644
--- a/third_party/WebKit/Source/platform/wtf/text/StringViewTest.cpp
+++ b/third_party/WebKit/Source/platform/wtf/text/StringViewTest.cpp
@@ -19,61 +19,61 @@
   RefPtr<StringImpl> impl8_bit = StringImpl::Create(kChars8, 5);
 
   // StringView(StringImpl*);
-  ASSERT_TRUE(StringView(impl8_bit.Get()).Is8Bit());
-  EXPECT_FALSE(StringView(impl8_bit.Get()).IsNull());
+  ASSERT_TRUE(StringView(impl8_bit.get()).Is8Bit());
+  EXPECT_FALSE(StringView(impl8_bit.get()).IsNull());
   EXPECT_EQ(impl8_bit->Characters8(),
-            StringView(impl8_bit.Get()).Characters8());
-  EXPECT_EQ(impl8_bit->length(), StringView(impl8_bit.Get()).length());
-  EXPECT_STREQ(kChars, StringView(impl8_bit.Get()).ToString().Utf8().data());
+            StringView(impl8_bit.get()).Characters8());
+  EXPECT_EQ(impl8_bit->length(), StringView(impl8_bit.get()).length());
+  EXPECT_STREQ(kChars, StringView(impl8_bit.get()).ToString().Utf8().data());
 
   // StringView(StringImpl*, unsigned offset);
-  ASSERT_TRUE(StringView(impl8_bit.Get(), 2).Is8Bit());
-  EXPECT_FALSE(StringView(impl8_bit.Get(), 2).IsNull());
+  ASSERT_TRUE(StringView(impl8_bit.get(), 2).Is8Bit());
+  EXPECT_FALSE(StringView(impl8_bit.get(), 2).IsNull());
   EXPECT_EQ(impl8_bit->Characters8() + 2,
-            StringView(impl8_bit.Get(), 2).Characters8());
-  EXPECT_EQ(3u, StringView(impl8_bit.Get(), 2).length());
-  EXPECT_EQ(StringView("345"), StringView(impl8_bit.Get(), 2));
-  EXPECT_STREQ("345", StringView(impl8_bit.Get(), 2).ToString().Utf8().data());
+            StringView(impl8_bit.get(), 2).Characters8());
+  EXPECT_EQ(3u, StringView(impl8_bit.get(), 2).length());
+  EXPECT_EQ(StringView("345"), StringView(impl8_bit.get(), 2));
+  EXPECT_STREQ("345", StringView(impl8_bit.get(), 2).ToString().Utf8().data());
 
   // StringView(StringImpl*, unsigned offset, unsigned length);
-  ASSERT_TRUE(StringView(impl8_bit.Get(), 2, 1).Is8Bit());
-  EXPECT_FALSE(StringView(impl8_bit.Get(), 2, 1).IsNull());
+  ASSERT_TRUE(StringView(impl8_bit.get(), 2, 1).Is8Bit());
+  EXPECT_FALSE(StringView(impl8_bit.get(), 2, 1).IsNull());
   EXPECT_EQ(impl8_bit->Characters8() + 2,
-            StringView(impl8_bit.Get(), 2, 1).Characters8());
-  EXPECT_EQ(1u, StringView(impl8_bit.Get(), 2, 1).length());
-  EXPECT_EQ(StringView("3"), StringView(impl8_bit.Get(), 2, 1));
-  EXPECT_STREQ("3", StringView(impl8_bit.Get(), 2, 1).ToString().Utf8().data());
+            StringView(impl8_bit.get(), 2, 1).Characters8());
+  EXPECT_EQ(1u, StringView(impl8_bit.get(), 2, 1).length());
+  EXPECT_EQ(StringView("3"), StringView(impl8_bit.get(), 2, 1));
+  EXPECT_STREQ("3", StringView(impl8_bit.get(), 2, 1).ToString().Utf8().data());
 }
 
 TEST(StringViewTest, ConstructionStringImpl16) {
   RefPtr<StringImpl> impl16_bit = StringImpl::Create(kChars16, 5);
 
   // StringView(StringImpl*);
-  ASSERT_FALSE(StringView(impl16_bit.Get()).Is8Bit());
-  EXPECT_FALSE(StringView(impl16_bit.Get()).IsNull());
+  ASSERT_FALSE(StringView(impl16_bit.get()).Is8Bit());
+  EXPECT_FALSE(StringView(impl16_bit.get()).IsNull());
   EXPECT_EQ(impl16_bit->Characters16(),
-            StringView(impl16_bit.Get()).Characters16());
-  EXPECT_EQ(impl16_bit->length(), StringView(impl16_bit.Get()).length());
-  EXPECT_STREQ(kChars, StringView(impl16_bit.Get()).ToString().Utf8().data());
+            StringView(impl16_bit.get()).Characters16());
+  EXPECT_EQ(impl16_bit->length(), StringView(impl16_bit.get()).length());
+  EXPECT_STREQ(kChars, StringView(impl16_bit.get()).ToString().Utf8().data());
 
   // StringView(StringImpl*, unsigned offset);
-  ASSERT_FALSE(StringView(impl16_bit.Get(), 2).Is8Bit());
-  EXPECT_FALSE(StringView(impl16_bit.Get(), 2).IsNull());
+  ASSERT_FALSE(StringView(impl16_bit.get(), 2).Is8Bit());
+  EXPECT_FALSE(StringView(impl16_bit.get(), 2).IsNull());
   EXPECT_EQ(impl16_bit->Characters16() + 2,
-            StringView(impl16_bit.Get(), 2).Characters16());
-  EXPECT_EQ(3u, StringView(impl16_bit.Get(), 2).length());
-  EXPECT_EQ(StringView("345"), StringView(impl16_bit.Get(), 2));
-  EXPECT_STREQ("345", StringView(impl16_bit.Get(), 2).ToString().Utf8().data());
+            StringView(impl16_bit.get(), 2).Characters16());
+  EXPECT_EQ(3u, StringView(impl16_bit.get(), 2).length());
+  EXPECT_EQ(StringView("345"), StringView(impl16_bit.get(), 2));
+  EXPECT_STREQ("345", StringView(impl16_bit.get(), 2).ToString().Utf8().data());
 
   // StringView(StringImpl*, unsigned offset, unsigned length);
-  ASSERT_FALSE(StringView(impl16_bit.Get(), 2, 1).Is8Bit());
-  EXPECT_FALSE(StringView(impl16_bit.Get(), 2, 1).IsNull());
+  ASSERT_FALSE(StringView(impl16_bit.get(), 2, 1).Is8Bit());
+  EXPECT_FALSE(StringView(impl16_bit.get(), 2, 1).IsNull());
   EXPECT_EQ(impl16_bit->Characters16() + 2,
-            StringView(impl16_bit.Get(), 2, 1).Characters16());
-  EXPECT_EQ(1u, StringView(impl16_bit.Get(), 2, 1).length());
-  EXPECT_EQ(StringView("3"), StringView(impl16_bit.Get(), 2, 1));
+            StringView(impl16_bit.get(), 2, 1).Characters16());
+  EXPECT_EQ(1u, StringView(impl16_bit.get(), 2, 1).length());
+  EXPECT_EQ(StringView("3"), StringView(impl16_bit.get(), 2, 1));
   EXPECT_STREQ("3",
-               StringView(impl16_bit.Get(), 2, 1).ToString().Utf8().data());
+               StringView(impl16_bit.get(), 2, 1).ToString().Utf8().data());
 }
 
 TEST(StringViewTest, ConstructionStringImplRef8) {
diff --git a/third_party/WebKit/Source/platform/wtf/text/TextCodecUTF16.cpp b/third_party/WebKit/Source/platform/wtf/text/TextCodecUTF16.cpp
index d2db587d..d882aba6 100644
--- a/third_party/WebKit/Source/platform/wtf/text/TextCodecUTF16.cpp
+++ b/third_party/WebKit/Source/platform/wtf/text/TextCodecUTF16.cpp
@@ -25,7 +25,6 @@
 
 #include "platform/wtf/text/TextCodecUTF16.h"
 
-#include "platform/wtf/PtrUtil.h"
 #include "platform/wtf/text/CString.h"
 #include "platform/wtf/text/CharacterNames.h"
 #include "platform/wtf/text/StringBuffer.h"
@@ -51,13 +50,13 @@
 static std::unique_ptr<TextCodec> NewStreamingTextDecoderUTF16LE(
     const TextEncoding&,
     const void*) {
-  return WTF::MakeUnique<TextCodecUTF16>(true);
+  return std::make_unique<TextCodecUTF16>(true);
 }
 
 static std::unique_ptr<TextCodec> NewStreamingTextDecoderUTF16BE(
     const TextEncoding&,
     const void*) {
-  return WTF::MakeUnique<TextCodecUTF16>(false);
+  return std::make_unique<TextCodecUTF16>(false);
 }
 
 void TextCodecUTF16::RegisterCodecs(TextCodecRegistrar registrar) {
diff --git a/third_party/WebKit/Source/platform/wtf/text/TextPosition.cpp b/third_party/WebKit/Source/platform/wtf/text/TextPosition.cpp
index 71c0e6e4..d17a348 100644
--- a/third_party/WebKit/Source/platform/wtf/text/TextPosition.cpp
+++ b/third_party/WebKit/Source/platform/wtf/text/TextPosition.cpp
@@ -25,7 +25,6 @@
 
 #include "platform/wtf/text/TextPosition.h"
 
-#include "platform/wtf/PtrUtil.h"
 #include "platform/wtf/StdLibExtras.h"
 #include <algorithm>
 #include <memory>
@@ -33,7 +32,8 @@
 namespace WTF {
 
 std::unique_ptr<Vector<unsigned>> GetLineEndings(const String& text) {
-  std::unique_ptr<Vector<unsigned>> result(WTF::MakeUnique<Vector<unsigned>>());
+  std::unique_ptr<Vector<unsigned>> result(
+      std::make_unique<Vector<unsigned>>());
 
   unsigned start = 0;
   while (start < text.length()) {
diff --git a/third_party/WebKit/Source/platform/wtf/text/WTFString.h b/third_party/WebKit/Source/platform/wtf/text/WTFString.h
index 2eaac98..cb9957f1 100644
--- a/third_party/WebKit/Source/platform/wtf/text/WTFString.h
+++ b/third_party/WebKit/Source/platform/wtf/text/WTFString.h
@@ -112,7 +112,7 @@
   bool IsNull() const { return !impl_; }
   bool IsEmpty() const { return !impl_ || !impl_->length(); }
 
-  StringImpl* Impl() const { return impl_.Get(); }
+  StringImpl* Impl() const { return impl_.get(); }
   RefPtr<StringImpl> ReleaseImpl() { return std::move(impl_); }
 
   unsigned length() const {
diff --git a/third_party/WebKit/Source/platform/wtf/typed_arrays/ArrayBuffer.cpp b/third_party/WebKit/Source/platform/wtf/typed_arrays/ArrayBuffer.cpp
index a3d564e..20718110 100644
--- a/third_party/WebKit/Source/platform/wtf/typed_arrays/ArrayBuffer.cpp
+++ b/third_party/WebKit/Source/platform/wtf/typed_arrays/ArrayBuffer.cpp
@@ -92,7 +92,7 @@
 }
 
 void ArrayBuffer::RemoveView(ArrayBufferView* view) {
-  DCHECK_EQ(this, view->buffer_.Get());
+  DCHECK_EQ(this, view->buffer_.get());
   if (view->next_view_)
     view->next_view_->prev_view_ = view->prev_view_;
   if (view->prev_view_)
diff --git a/third_party/WebKit/Source/platform/wtf/typed_arrays/ArrayBufferBuilder.h b/third_party/WebKit/Source/platform/wtf/typed_arrays/ArrayBufferBuilder.h
index 252ca47..12314f8 100644
--- a/third_party/WebKit/Source/platform/wtf/typed_arrays/ArrayBufferBuilder.h
+++ b/third_party/WebKit/Source/platform/wtf/typed_arrays/ArrayBufferBuilder.h
@@ -56,7 +56,7 @@
     buffer_ = ArrayBuffer::Create(capacity, 1);
   }
 
-  bool IsValid() const { return buffer_.Get(); }
+  bool IsValid() const { return buffer_.get(); }
 
   // Appending empty data is not allowed.
   unsigned Append(const char* data, unsigned length);
diff --git a/third_party/WebKit/Source/platform/wtf/typed_arrays/ArrayBufferBuilderTest.cpp b/third_party/WebKit/Source/platform/wtf/typed_arrays/ArrayBufferBuilderTest.cpp
index 39b4820..65e04c33 100644
--- a/third_party/WebKit/Source/platform/wtf/typed_arrays/ArrayBufferBuilderTest.cpp
+++ b/third_party/WebKit/Source/platform/wtf/typed_arrays/ArrayBufferBuilderTest.cpp
@@ -145,7 +145,7 @@
 
   RefPtr<ArrayBuffer> result1 = builder.ToArrayBuffer();
   RefPtr<ArrayBuffer> result2 = builder.ToArrayBuffer();
-  EXPECT_EQ(result1.Get(), result2.Get());
+  EXPECT_EQ(result1.get(), result2.get());
 }
 
 TEST(ArrayBufferBuilderTest, ToString) {
diff --git a/third_party/WebKit/Source/platform/wtf/typed_arrays/ArrayBufferView.h b/third_party/WebKit/Source/platform/wtf/typed_arrays/ArrayBufferView.h
index 377221d..a659b26 100644
--- a/third_party/WebKit/Source/platform/wtf/typed_arrays/ArrayBufferView.h
+++ b/third_party/WebKit/Source/platform/wtf/typed_arrays/ArrayBufferView.h
@@ -51,7 +51,7 @@
   virtual ViewType GetType() const = 0;
   const char* TypeName();
 
-  ArrayBuffer* Buffer() const { return buffer_.Get(); }
+  ArrayBuffer* Buffer() const { return buffer_.get(); }
 
   void* BaseAddress() const {
     DCHECK(!IsShared());
diff --git a/third_party/WebKit/Source/platform/wtf/typed_arrays/TypedArrayBase.h b/third_party/WebKit/Source/platform/wtf/typed_arrays/TypedArrayBase.h
index dac779dc..339726e 100644
--- a/third_party/WebKit/Source/platform/wtf/typed_arrays/TypedArrayBase.h
+++ b/third_party/WebKit/Source/platform/wtf/typed_arrays/TypedArrayBase.h
@@ -87,7 +87,7 @@
   static RefPtr<Subclass> Create(RefPtr<ArrayBuffer> buffer,
                                  unsigned byte_offset,
                                  unsigned length) {
-    CHECK(VerifySubRange<T>(buffer.Get(), byte_offset, length));
+    CHECK(VerifySubRange<T>(buffer.get(), byte_offset, length));
     return WTF::AdoptRef(new Subclass(std::move(buffer), byte_offset, length));
   }
 
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn
index d41a8bdb..a541c96 100644
--- a/third_party/WebKit/public/BUILD.gn
+++ b/third_party/WebKit/public/BUILD.gn
@@ -808,6 +808,7 @@
     "platform/reporting.mojom",
     "platform/site_engagement.mojom",
     "web/console_message.mojom",
+    "web/selection_menu_behavior.mojom",
     "web/shared_worker_creation_context_type.mojom",
     "web/window_features.mojom",
     "web/worker_content_settings_proxy.mojom",
diff --git a/third_party/WebKit/public/platform/WebAudioBus.h b/third_party/WebKit/public/platform/WebAudioBus.h
index 0e0a027..39b5205 100644
--- a/third_party/WebKit/public/platform/WebAudioBus.h
+++ b/third_party/WebKit/public/platform/WebAudioBus.h
@@ -44,7 +44,7 @@
 //
 class BLINK_PLATFORM_EXPORT WebAudioBus {
  public:
-  WebAudioBus() : private_(0) {}
+  WebAudioBus() {}
   ~WebAudioBus() { Reset(); }
 
   // Initialize() allocates memory of the given length for the given number of
@@ -76,7 +76,7 @@
   WebAudioBus(const WebAudioBus&);
   void operator=(const WebAudioBus&);
 
-  AudioBus* private_;
+  AudioBus* private_ = nullptr;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/public/platform/WebLayer.h b/third_party/WebKit/public/platform/WebLayer.h
index bce439d7..34c5ae6 100644
--- a/third_party/WebKit/public/platform/WebLayer.h
+++ b/third_party/WebKit/public/platform/WebLayer.h
@@ -245,9 +245,6 @@
   virtual void SetElementId(const cc::ElementId&) = 0;
   virtual cc::ElementId GetElementId() const = 0;
 
-  virtual void SetCompositorMutableProperties(uint32_t) = 0;
-  virtual uint32_t CompositorMutableProperties() const = 0;
-
   virtual void SetHasWillChangeTransformHint(bool) = 0;
 
   // Called on the scroll layer to trigger showing the overlay scrollbars.
diff --git a/third_party/WebKit/public/platform/WebMediaStreamCenter.h b/third_party/WebKit/public/platform/WebMediaStreamCenter.h
index 513dca3d..8c10b68 100644
--- a/third_party/WebKit/public/platform/WebMediaStreamCenter.h
+++ b/third_party/WebKit/public/platform/WebMediaStreamCenter.h
@@ -38,6 +38,7 @@
 class WebAudioSourceProvider;
 class WebMediaStream;
 class WebMediaStreamTrack;
+class WebMediaStreamSource;
 
 class WebMediaStreamCenter {
  public:
@@ -57,6 +58,9 @@
     return false;
   }
 
+  // Source functionality.
+  virtual void DidStopMediaStreamSource(const WebMediaStreamSource&) {}
+
   // Caller must take the ownership of the returned |WebAudioSourceProvider|
   // object.
   virtual WebAudioSourceProvider* CreateWebAudioSourceFromMediaStreamTrack(
diff --git a/third_party/WebKit/public/platform/WebMenuSourceType.h b/third_party/WebKit/public/platform/WebMenuSourceType.h
index 5d97c3f..10d730e9 100644
--- a/third_party/WebKit/public/platform/WebMenuSourceType.h
+++ b/third_party/WebKit/public/platform/WebMenuSourceType.h
@@ -17,7 +17,8 @@
   kMenuSourceLongTap,
   kMenuSourceTouchHandle,
   kMenuSourceStylus,
-  kMenuSourceTypeLast = kMenuSourceStylus
+  kMenuSourceAdjustSelection,
+  kMenuSourceTypeLast = kMenuSourceAdjustSelection
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/public/platform/WebRuntimeFeatures.h b/third_party/WebKit/public/platform/WebRuntimeFeatures.h
index 5acf35d..5ec57af 100644
--- a/third_party/WebKit/public/platform/WebRuntimeFeatures.h
+++ b/third_party/WebKit/public/platform/WebRuntimeFeatures.h
@@ -98,6 +98,7 @@
   BLINK_PLATFORM_EXPORT static void EnableMediaCapture(bool);
   BLINK_PLATFORM_EXPORT static void EnableMediaSession(bool);
   BLINK_PLATFORM_EXPORT static void EnableMiddleClickAutoscroll(bool);
+  BLINK_PLATFORM_EXPORT static void EnableModernMediaControls(bool);
   BLINK_PLATFORM_EXPORT static void EnableModuleScripts(bool);
   BLINK_PLATFORM_EXPORT static void EnableModuleScriptsDynamicImport(bool);
   BLINK_PLATFORM_EXPORT static void EnableMojoBlobs(bool);
diff --git a/third_party/WebKit/public/platform/modules/serviceworker/service_worker_registration.mojom b/third_party/WebKit/public/platform/modules/serviceworker/service_worker_registration.mojom
index 539f0266..0a240c3 100644
--- a/third_party/WebKit/public/platform/modules/serviceworker/service_worker_registration.mojom
+++ b/third_party/WebKit/public/platform/modules/serviceworker/service_worker_registration.mojom
@@ -37,4 +37,18 @@
   // The registration options attached with this registration object, including
   // some information such as scope of this registration.
   ServiceWorkerRegistrationOptions options;
+
+  // Holds one mojo connection to browser process, acts as a reference count to
+  // control lifetime of ServiceWorkerRegistration on the browser process.
+  associated ServiceWorkerRegistrationObjectHost? host_ptr_info;
+};
+
+// This interface lives on the browser process, it corresponds to one
+// ServiceWorkerRegistration JavaScript object. The renderer uses it to ask the
+// browser to do operations needed to implement ServiceWorkerRegistration
+// methods.
+interface ServiceWorkerRegistrationObjectHost {
+  // TODO(leonhsl): Implement all methods.
+  // Update() => (ServiceWorkerErrorType error, string? error_msg);
+  // Unregister() => (ServiceWorkerErrorType error, string? error_msg);
 };
diff --git a/third_party/WebKit/public/platform/web_feature.mojom b/third_party/WebKit/public/platform/web_feature.mojom
index a442b84..c279e9e 100644
--- a/third_party/WebKit/public/platform/web_feature.mojom
+++ b/third_party/WebKit/public/platform/web_feature.mojom
@@ -1531,8 +1531,6 @@
   kInertAttribute = 1995,
   kPluginInstanceAccessFromIsolatedWorld = 1996,
   kPluginInstanceAccessFromMainWorld = 1997,
-  kRequestFullscreenForDialogElement = 1998,
-  kRequestFullscreenForDialogElementInTopLayer = 1999,
   kShowModalForElementInFullscreenStack = 2000,
   kThreeValuedPositionBackground = 2001,
   kThreeValuedPositionBasicShape = 2002,
diff --git a/third_party/WebKit/public/web/WebConsoleMessage.h b/third_party/WebKit/public/web/WebConsoleMessage.h
index d1fb8b89..6d1ebf6 100644
--- a/third_party/WebKit/public/web/WebConsoleMessage.h
+++ b/third_party/WebKit/public/web/WebConsoleMessage.h
@@ -32,6 +32,7 @@
 #define WebConsoleMessage_h
 
 #include "public/platform/WebString.h"
+#include "public/web/WebNode.h"
 
 namespace blink {
 
@@ -46,13 +47,22 @@
 
   Level level;
   WebString text;
+  WebVector<blink::WebNode> nodes;
   WebString url;
   unsigned line_number;
   unsigned column_number;
 
   WebConsoleMessage() : level(kLevelInfo), line_number(0), column_number(0) {}
+  WebConsoleMessage(Level level,
+                    const WebString& text,
+                    const WebVector<blink::WebNode>& nodes)
+      : level(level),
+        text(text),
+        nodes(nodes),
+        line_number(0),
+        column_number(0) {}
   WebConsoleMessage(Level level, const WebString& text)
-      : level(level), text(text), line_number(0), column_number(0) {}
+      : WebConsoleMessage(level, text, WebVector<blink::WebNode>()) {}
   WebConsoleMessage(Level level,
                     const WebString& text,
                     const WebString url,
diff --git a/third_party/WebKit/public/web/WebLocalFrame.h b/third_party/WebKit/public/web/WebLocalFrame.h
index 4d413506..1300a8e3 100644
--- a/third_party/WebKit/public/web/WebLocalFrame.h
+++ b/third_party/WebKit/public/web/WebLocalFrame.h
@@ -21,6 +21,7 @@
 #include "public/platform/scheduler/single_thread_task_runner.h"
 #include "public/platform/site_engagement.mojom-shared.h"
 #include "public/web/WebSandboxFlags.h"
+#include "public/web/selection_menu_behavior.mojom-shared.h"
 #include "v8/include/v8.h"
 
 namespace blink {
@@ -499,8 +500,10 @@
     // Keep the current handle visibility.
     kPreserveHandleVisibility,
   };
+
   virtual void SelectRange(const WebRange&,
-                           HandleVisibilityBehavior = kHideSelectionHandle) = 0;
+                           HandleVisibilityBehavior,
+                           mojom::SelectionMenuBehavior) = 0;
 
   virtual WebString RangeAsText(const WebRange&) = 0;
 
diff --git a/third_party/WebKit/public/web/selection_menu_behavior.mojom b/third_party/WebKit/public/web/selection_menu_behavior.mojom
new file mode 100644
index 0000000..4d794df
--- /dev/null
+++ b/third_party/WebKit/public/web/selection_menu_behavior.mojom
@@ -0,0 +1,11 @@
+// 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 blink.mojom;
+
+// Mojom enum for selection menu behavior.
+enum SelectionMenuBehavior {
+  kHide,
+  kShow,
+};
diff --git a/third_party/android_platform/OWNERS b/third_party/android_platform/OWNERS
index e86384c..9064cd5 100644
--- a/third_party/android_platform/OWNERS
+++ b/third_party/android_platform/OWNERS
@@ -1,5 +1,4 @@
 agrieve@chromium.org
 rmcilroy@chromium.org
-sgurun@chromium.org
 
 # COMPONENT: Infra>Client>Android
diff --git a/third_party/android_system_sdk/OWNERS b/third_party/android_system_sdk/OWNERS
index 7db1875..554fe70 100644
--- a/third_party/android_system_sdk/OWNERS
+++ b/third_party/android_system_sdk/OWNERS
@@ -1,4 +1,3 @@
-sgurun@chromium.org
 torne@chromium.org
 tobiasjs@chromium.org
 
diff --git a/third_party/blink/tools/move_blink_source.py b/third_party/blink/tools/move_blink_source.py
index f8af13d..2b59693 100755
--- a/third_party/blink/tools/move_blink_source.py
+++ b/third_party/blink/tools/move_blink_source.py
@@ -13,7 +13,6 @@
 import logging
 import os
 import re
-import subprocess
 import sys
 from functools import partial
 
@@ -23,8 +22,11 @@
                  'third_party', 'WebKit', 'Tools', 'Scripts')))
 from blinkpy.common.name_style_converter import NameStyleConverter
 from plan_blink_move import plan_blink_move
+from plan_blink_move import relative_dest
 from webkitpy.common.checkout.git import Git
 from webkitpy.common.path_finder import get_chromium_src_dir
+from webkitpy.common.path_finder import get_scripts_dir
+from webkitpy.common.system.executive import Executive
 from webkitpy.common.system.filesystem import FileSystem
 
 _log = logging.getLogger('move_blink_source')
@@ -84,6 +86,8 @@
         # and generated header files.
         self._checked_in_header_re = None
 
+        self._updated_files = []
+
     def update(self):
         _log.info('Planning renaming ...')
         file_pairs = plan_blink_move(self._fs, [])
@@ -110,6 +114,15 @@
             ('DEPS',
              [('src/third_party/WebKit/Source/devtools',
                'src/third_party/blink/renderer/devtools')]),
+            ('WATCHLISTS',
+             [('third_party/WebKit/Source', 'third_party/blink/renderer'),
+              ('third_party/WebKit/public', 'third_party/blink/renderer/public')]),
+            ('build/check_gn_headers_whitelist.txt',
+             [('third_party/WebKit/Source', 'third_party/blink/renderer'),
+              ('third_party/WebKit/public', 'third_party/blink/renderer/public'),
+              self._update_basename]),
+            ('testing/buildbot/gn_isolate_map.pyl',
+             [('third_party/WebKit/Source', 'third_party/blink/renderer')]),
             ('third_party/WebKit/Source/BUILD.gn',
              [('$root_gen_dir/third_party/WebKit',
                '$root_gen_dir/third_party/blink/renderer')]),
@@ -139,13 +152,52 @@
                '$root_gen_dir/third_party/blink/renderer')]),
             ('third_party/WebKit/public/blink_resources.grd',
              [('../Source/', '../')]),
+            ('tools/android/eclipse/.classpath',
+             [('third_party/WebKit/public', 'third_party/blink/renderer/public')]),
+            ('tools/android/loading/cloud/backend/deploy.sh',
+             [('third_party/WebKit/Source', 'third_party/blink/renderer')]),
+            ('tools/android/loading/emulation_unittest.py',
+             [('third_party/WebKit/Source', 'third_party/blink/renderer')]),
+            ('tools/android/loading/options.py',
+             [('third_party/WebKit/Source', 'third_party/blink/renderer')]),
+            ('tools/android/loading/request_track.py',
+             [('third_party/WebKit/Source', 'third_party/blink/renderer')]),
             ('tools/gritsettings/resource_ids',
              [('third_party/WebKit/public', 'third_party/blink/renderer/public'),
               ('third_party/WebKit/Source', 'third_party/blink/renderer')]),
+            ('tools/metrics/actions/extract_actions.py',
+             [('third_party/WebKit/Source', 'third_party/blink/renderer')]),
+            ('tools/metrics/histograms/update_editor_commands.py',
+             [('third_party/WebKit/Source/core/editing/EditorCommand.cpp',
+               'third_party/blink/renderer/core/editing/editor_command.cc')]),
+            ('tools/metrics/histograms/update_use_counter_css.py',
+             [('third_party/WebKit/Source/core/frame/UseCounter.cpp',
+               'third_party/blink/renderer/core/frame/use_counter.cc')]),
+            ('tools/metrics/histograms/update_use_counter_feature_enum.py',
+             [('third_party/WebKit/public', 'third_party/blink/renderer/public')]),
         ]
         for file_path, replacement_list in file_replacement_list:
             self._update_single_file_content(file_path, replacement_list, should_write=self._options.run)
 
+        if self._options.run:
+            _log.info('Formatting updated %d files ...', len(self._updated_files))
+            git = Git(cwd=self._repo_root)
+            # |git cl format| can't handle too many files at once.
+            while len(self._updated_files) > 0:
+                end_index = 100
+                if end_index > len(self._updated_files):
+                    end_index = len(self._updated_files)
+                git.run(['cl', 'format'] + self._updated_files[:end_index])
+                self._updated_files = self._updated_files[end_index:]
+
+            _log.info('Make a local commit ...')
+            git.commit_locally_with_message("""The Great Blink mv for source files, part 1.
+
+Update file contents without moving files.
+
+Bug: 768828
+""")
+
     def move(self):
         _log.info('Planning renaming ...')
         file_pairs = plan_blink_move(self._fs, [])
@@ -170,6 +222,20 @@
             'build/get_landmines.py',
             [('\ndef main', '  print \'The Great Blink mv for source files (crbug.com/768828)\'\n\ndef main')])
 
+        _log.info('Run run-bindings-tests ...')
+        Executive().run_command(['python',
+                                 self._fs.join(get_scripts_dir(), 'run-bindings-tests'),
+                                 '--reset-results'],
+                                cwd=self._repo_root)
+
+        if self._options.run_git:
+            _log.info('Make a local commit ...')
+            git.commit_locally_with_message("""The Great Blink mv for source files, part 2.
+
+Move and rename files.
+
+Bug: 768828
+""")
 
     def _create_basename_maps(self, file_pairs):
         basename_map = {}
@@ -315,6 +381,7 @@
                 continue
             if self._options.run:
                 self._fs.write_text_file(file_path, content)
+                self._updated_files.append(file_path)
             if file_type == FileType.DEPS:
                 self._append_unless_upper_dir_exists(updated_deps_dirs, self._fs.dirname(file_path))
             _log.info('Updated %s', self._shorten_path(file_path))
@@ -333,11 +400,14 @@
                 content = self._update_cpp_includes(original_content)
                 if file_path.endswith('.h') and '/third_party/WebKit/public/' in file_path.replace('\\', '/'):
                     content = self._update_basename_only_includes(content, file_path)
+                if file_path.endswith('.h') and '/third_party/WebKit/' in file_path.replace('\\', '/'):
+                    content = self._update_include_guard(content, file_path)
 
                 if original_content == content:
                     continue
                 if self._options.run:
                     self._fs.write_text_file(file_path, content)
+                    self._updated_files.append(file_path)
                 _log.info('Updated %s', self._shorten_path(file_path))
 
     def _replace_include_path(self, match):
@@ -399,6 +469,16 @@
         return re.sub(r'#include\s+"(\w+\.h)"',
                       partial(self._replace_basename_only_include, subdir, source_path), content)
 
+    def _update_include_guard(self, content, source_path):
+        current_guard = re.sub(r'[.]', '_', self._fs.basename(source_path))
+        new_path = relative_dest(self._fs, self._fs.relpath(
+            source_path, start=self._fs.join(self._repo_root, 'third_party', 'WebKit')))
+        new_guard = 'THIRD_PARTY_BLINK_' + re.sub(r'[\\/.]', '_', new_path.upper()) + '_'
+        content = re.sub(r'#ifndef\s+(WTF_)?' + current_guard, '#ifndef ' + new_guard, content);
+        content = re.sub(r'#define\s+(WTF_)?' + current_guard, '#define ' + new_guard, content);
+        content = re.sub(r'#endif\s+//\s+(WTF_)?' + current_guard, '#endif  // ' + new_guard, content);
+        return content
+
     def _update_single_file_content(self, file_path, replace_list, should_write=True):
         full_path = self._fs.join(self._repo_root, file_path)
         original_content = self._fs.read_text_file(full_path)
@@ -414,6 +494,7 @@
         if content != original_content:
             if should_write:
                 self._fs.write_text_file(full_path, content)
+                self._updated_files.append(full_path)
             _log.info('Updated %s', file_path)
         else:
             _log.warning('%s does not contain specified source strings.', file_path)
diff --git a/third_party/dom_distiller_js/update_domdistiller_js.sh b/third_party/dom_distiller_js/update_domdistiller_js.sh
index 0fdec04..c3540ca 100755
--- a/third_party/dom_distiller_js/update_domdistiller_js.sh
+++ b/third_party/dom_distiller_js/update_domdistiller_js.sh
@@ -21,12 +21,13 @@
   changes=$tmpdir/domdistiller.changes
   bugs=$tmpdir/domdistiller.bugs
   curr_gitsha=$(grep 'Version:' $readme_chromium | awk '{print $2}')
+  repo_host=https://chromium.googlesource.com/chromium
 
   rm -rf $tmpdir
   mkdir $tmpdir
   pushd $tmpdir
 
-  git clone https://github.com/chromium/dom-distiller.git
+  git clone $repo_host/dom-distiller
   pushd dom-distiller
 
   # The new git SHA1 is HEAD or the first command line parameter.
@@ -55,7 +56,7 @@
   ant package
   popd # dom-distiller
 
-  git clone https://github.com/chromium/dom-distiller-dist.git $tmpdir/dom-distiller-dist
+  git clone $repo_host/dom-distiller/dist $tmpdir/dom-distiller-dist
   rm -rf $tmpdir/dom-distiller-dist/*
   pushd dom-distiller-dist
   cp -r $tmpdir/dom-distiller/out/package/* .
@@ -71,7 +72,7 @@
   popd # dom-distiller-dist
 
   popd # tmpdir
-  curr_dist_gitsha=$(grep -e "/external\/github.com\/chromium\/dom-distiller-dist.git" $src_path/DEPS | sed -e "s/.*'\([A-Za-z0-9]\{40\}\)'.*/\1/g")
+  curr_dist_gitsha=$(grep -e "/chromium\/dom-distiller\/dist.git" $src_path/DEPS | sed -e "s/.*'\([A-Za-z0-9]\{40\}\)'.*/\1/g")
   if [[ "${new_dist_gitsha}" == "${curr_dist_gitsha}" ]]; then
     echo "The roll does not include any changes to the dist package. Exiting."
     rm -rf $tmpdir
@@ -80,7 +81,7 @@
 
   cp $tmpdir/dom-distiller/LICENSE $dom_distiller_js_path/
   sed -i "s/Version: [0-9a-f]*/Version: ${new_gitsha}/" $readme_chromium
-  sed -i -e "s/\('\/external\/github.com\/chromium\/dom-distiller-dist.git' + '@' + '\)\([0-9a-f]\+\)'/\1${new_dist_gitsha}'/" $src_path/DEPS
+  sed -i -e "s/\('\/chromium\/dom-distiller\/dist.git' + '@' + '\)\([0-9a-f]\+\)'/\1${new_dist_gitsha}'/" $src_path/DEPS
 
   gen_message () {
     echo "Roll DOM Distiller JavaScript distribution package"
diff --git a/third_party/polymer/v1_0/bower.json b/third_party/polymer/v1_0/bower.json
index d02b0b9..f8d2f6b 100644
--- a/third_party/polymer/v1_0/bower.json
+++ b/third_party/polymer/v1_0/bower.json
@@ -52,7 +52,6 @@
     "paper-styles": "PolymerElements/paper-styles#1.1.4",
     "paper-tabs": "PolymerElements/paper-tabs#1.6.2",
     "paper-toggle-button": "PolymerElements/paper-toggle-button#1.3.0",
-    "paper-toolbar": "PolymerElements/paper-toolbar#1.1.6",
     "paper-tooltip": "PolymerElements/paper-tooltip#1.1.3",
     "polymer": "Polymer/polymer#1.9.1",
     "web-animations-js": "web-animations/web-animations-js#2.2.2"
diff --git a/third_party/polymer/v1_0/components-chromium/paper-toolbar/bower.json b/third_party/polymer/v1_0/components-chromium/paper-toolbar/bower.json
deleted file mode 100644
index 1fc3b4e..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-toolbar/bower.json
+++ /dev/null
@@ -1,37 +0,0 @@
-{
-  "name": "paper-toolbar",
-  "version": "1.1.6",
-  "license": "http://polymer.github.io/LICENSE.txt",
-  "description": "A material design toolbar that is easily customizable",
-  "private": true,
-  "main": "paper-toolbar.html",
-  "authors": [
-    "The Polymer Authors"
-  ],
-  "keywords": [
-    "web-components",
-    "polymer",
-    "toolbar",
-    "layout"
-  ],
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/PolymerElements/paper-toolbar.git"
-  },
-  "dependencies": {
-    "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0",
-    "paper-styles": "PolymerElements/paper-styles#^1.1.0",
-    "polymer": "Polymer/polymer#^1.2.0"
-  },
-  "devDependencies": {
-    "iron-component-page": "PolymerElements/iron-component-page#^1.0.0",
-    "iron-demo-helpers": "PolymerElements/iron-demo-helpers#^1.0.0",
-    "iron-icons": "PolymerElements/iron-icons#^1.0.0",
-    "paper-icon-button": "PolymerElements/paper-icon-button#^1.0.0",
-    "paper-progress": "PolymerElements/paper-progress#^1.0.0",
-    "test-fixture": "PolymerElements/test-fixture#^1.0.0",
-    "web-component-tester": "^4.0.0",
-    "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0"
-  },
-  "ignore": []
-}
diff --git a/third_party/polymer/v1_0/components-chromium/paper-toolbar/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/paper-toolbar/compiled_resources2.gyp
deleted file mode 100644
index 8f4d512..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-toolbar/compiled_resources2.gyp
+++ /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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'paper-toolbar-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/paper-toolbar/paper-toolbar-extracted.js b/third_party/polymer/v1_0/components-chromium/paper-toolbar/paper-toolbar-extracted.js
deleted file mode 100644
index 81755a9b..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-toolbar/paper-toolbar-extracted.js
+++ /dev/null
@@ -1,89 +0,0 @@
-Polymer({
-      is: 'paper-toolbar',
-
-      hostAttributes: {
-        'role': 'toolbar'
-      },
-
-      properties: {
-        /**
-         * Controls how the items are aligned horizontally when they are placed
-         * at the bottom.
-         * Options are `start`, `center`, `end`, `justified` and `around`.
-         */
-        bottomJustify: {
-          type: String,
-          value: ''
-        },
-
-        /**
-         * Controls how the items are aligned horizontally.
-         * Options are `start`, `center`, `end`, `justified` and `around`.
-         */
-        justify: {
-          type: String,
-          value: ''
-        },
-
-        /**
-         * Controls how the items are aligned horizontally when they are placed
-         * in the middle.
-         * Options are `start`, `center`, `end`, `justified` and `around`.
-         */
-        middleJustify: {
-          type: String,
-          value: ''
-        }
-
-      },
-
-      attached: function() {
-        this._observer = this._observe(this);
-        this._updateAriaLabelledBy();
-      },
-
-      detached: function() {
-        if (this._observer) {
-          this._observer.disconnect();
-        }
-      },
-
-      _observe: function(node) {
-        var observer = new MutationObserver(function() {
-          this._updateAriaLabelledBy();
-        }.bind(this));
-        observer.observe(node, {
-          childList: true,
-          subtree: true
-        });
-        return observer;
-      },
-
-      _updateAriaLabelledBy: function() {
-        var labelledBy = [];
-        var contents = Polymer.dom(this.root).querySelectorAll('content');
-        for (var content, index = 0; content = contents[index]; index++) {
-          var nodes = Polymer.dom(content).getDistributedNodes();
-          for (var node, jndex = 0; node = nodes[jndex]; jndex++) {
-            if (node.classList && node.classList.contains('title')) {
-              if (node.id) {
-                labelledBy.push(node.id);
-              } else {
-                var id = 'paper-toolbar-label-' + Math.floor(Math.random() * 10000);
-                node.id = id;
-                labelledBy.push(id);
-              }
-            }
-          }
-        }
-        if (labelledBy.length > 0) {
-          this.setAttribute('aria-labelledby', labelledBy.join(' '));
-        }
-      },
-
-      _computeBarExtraClasses: function(barJustify) {
-        if (!barJustify) return '';
-
-        return barJustify + (barJustify === 'justified' ? '' : '-justified');
-      }
-    });
\ No newline at end of file
diff --git a/third_party/polymer/v1_0/components-chromium/paper-toolbar/paper-toolbar.html b/third_party/polymer/v1_0/components-chromium/paper-toolbar/paper-toolbar.html
deleted file mode 100644
index 25292ca..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-toolbar/paper-toolbar.html
+++ /dev/null
@@ -1,291 +0,0 @@
-<!--
-@license
-Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
-This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
-The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
-The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
-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="../paper-styles/default-theme.html">
-<link rel="import" href="../paper-styles/typography.html">
-<link rel="import" href="../iron-flex-layout/iron-flex-layout.html">
-
-<!--
-Material design: [Toolbars](https://www.google.com/design/spec/components/toolbars.html)
-
-`paper-toolbar` is a horizontal bar containing items that can be used for
-label, navigation, search and actions.  The items placed inside the
-`paper-toolbar` are projected into a `class="horizontal center layout"` container inside of
-`paper-toolbar`'s Shadow DOM.  You can use flex attributes to control the items'
-sizing.
-
-Example:
-
-```html
-<paper-toolbar>
-  <paper-icon-button icon="menu" on-tap="menuAction"></paper-icon-button>
-  <div class="title">Title</div>
-  <paper-icon-button icon="more-vert" on-tap="moreAction"></paper-icon-button>
-</paper-toolbar>
-```
-
-`paper-toolbar` has a standard height, but can made be taller by setting `tall`
-class on the `paper-toolbar`. This will make the toolbar 3x the normal height.
-
-```html
-<paper-toolbar class="tall">
-  <paper-icon-button icon="menu"></paper-icon-button>
-</paper-toolbar>
-```
-
-Apply `medium-tall` class to make the toolbar medium tall.  This will make the
-toolbar 2x the normal height.
-
-```html
-<paper-toolbar class="medium-tall">
-  <paper-icon-button icon="menu"></paper-icon-button>
-</paper-toolbar>
-```
-
-When `tall`, items can pin to either the top (default), middle or bottom.  Use
-`middle` class for middle content and `bottom` class for bottom content.
-
-```html
-<paper-toolbar class="tall">
-  <paper-icon-button icon="menu"></paper-icon-button>
-  <div class="middle title">Middle Title</div>
-  <div class="bottom title">Bottom Title</div>
-</paper-toolbar>
-```
-
-For `medium-tall` toolbar, the middle and bottom contents overlap and are
-pinned to the bottom.  But `middleJustify` and `bottomJustify` attributes are
-still honored separately.
-
-To make an element completely fit at the bottom of the toolbar, use `fit` along
-with `bottom`.
-
-```html
-<paper-toolbar class="tall">
-  <div id="progressBar" class="bottom fit"></div>
-</paper-toolbar>
-```
-
-When inside a `paper-header-panel` element, the class `.animate` is toggled to animate
-the height change in the toolbar.
-
-### Styling
-
-The following custom properties and mixins are available for styling:
-
-Custom property | Description | Default
-----------------|-------------|----------
-`--paper-toolbar-title`      | Mixin applied to the title of the toolbar | `{}`
-`--paper-toolbar-background` | Toolbar background color     | `--primary-color`
-`--paper-toolbar-color`      | Toolbar foreground color     | `--dark-theme-text-color`
-`--paper-toolbar-height`     | Custom height for toolbar    | `64px`
-`--paper-toolbar-sm-height`  | Custom height for small screen toolbar | `56px`
-`--paper-toolbar`            | Mixin applied to the toolbar | `{}`
-`--paper-toolbar-content`    | Mixin applied to the content section of the toolbar | `{}`
-`--paper-toolbar-medium`     | Mixin applied to medium height toolbar | `{}`
-`--paper-toolbar-tall`       | Mixin applied to tall height toolbar | `{}`
-`--paper-toolbar-transition` | Transition applied to the `.animate` class | `height 0.18s ease-in`
-
-### Accessibility
-
-`<paper-toolbar>` has `role="toolbar"` by default. Any elements with the class `title` will
-be used as the label of the toolbar via `aria-labelledby`.
-
-@demo demo/index.html
--->
-
-</head><body><dom-module id="paper-toolbar">
-  <template>
-    <style>
-      :host {
-        --calculated-paper-toolbar-height: var(--paper-toolbar-height, 64px);
-        --calculated-paper-toolbar-sm-height: var(--paper-toolbar-sm-height, 56px);
-
-        /* technical */
-        display: block;
-        position: relative;
-        box-sizing: border-box;
-        -moz-box-sizing: border-box;
-
-        /* size */
-        height: var(--calculated-paper-toolbar-height);
-
-        background: var(--paper-toolbar-background, --primary-color);
-        color: var(--paper-toolbar-color, --dark-theme-text-color);
-
-        @apply(--paper-toolbar);
-      }
-
-      :host(.animate) {
-        /* transition */
-        transition: var(--paper-toolbar-transition, height 0.18s ease-in);
-      }
-
-      :host(.medium-tall) {
-        height: calc(var(--calculated-paper-toolbar-height) * 2);
-        @apply(--paper-toolbar-medium);
-      }
-
-      :host(.tall) {
-        height: calc(var(--calculated-paper-toolbar-height) * 3);
-        @apply(--paper-toolbar-tall);
-      }
-
-      .toolbar-tools {
-        position: relative;
-        height: var(--calculated-paper-toolbar-height);
-        padding: 0 16px;
-        pointer-events: none;
-        @apply(--layout-horizontal);
-        @apply(--layout-center);
-        @apply(--paper-toolbar-content);
-      }
-
-      /*
-       * TODO: Where should media query breakpoints live so they can be shared between elements?
-       */
-
-      @media (max-width: 600px) {
-        :host {
-          height: var(--calculated-paper-toolbar-sm-height);
-        }
-
-        :host(.medium-tall) {
-          height: calc(var(--calculated-paper-toolbar-sm-height) * 2);
-        }
-
-        :host(.tall) {
-          height: calc(var(--calculated-paper-toolbar-sm-height) * 3);
-        }
-
-        .toolbar-tools {
-          height: var(--calculated-paper-toolbar-sm-height);
-        }
-      }
-
-      #topBar {
-        position: relative;
-      }
-
-      /* middle bar */
-      #middleBar {
-        position: absolute;
-        top: 0;
-        right: 0;
-        left: 0;
-      }
-
-      :host(.tall) #middleBar,
-      :host(.medium-tall) #middleBar {
-        -webkit-transform: translateY(100%);
-        transform: translateY(100%);
-      }
-
-      /* bottom bar */
-      #bottomBar {
-        position: absolute;
-        right: 0;
-        bottom: 0;
-        left: 0;
-      }
-
-      /*
-       * make elements (e.g. buttons) respond to mouse/touch events
-       *
-       * `.toolbar-tools` disables touch events so multiple toolbars can stack and not
-       * absorb events. All children must have pointer events re-enabled to work as
-       * expected.
-       */
-      .toolbar-tools > ::content > *:not([disabled]) {
-        pointer-events: auto;
-      }
-
-      .toolbar-tools > ::content .title {
-        @apply(--paper-font-common-base);
-
-        white-space: nowrap;
-        overflow: hidden;
-        text-overflow: ellipsis;
-        font-size: 20px;
-        font-weight: 400;
-        line-height: 1;
-        pointer-events: none;
-
-        @apply(--layout-flex);
-      }
-
-      .toolbar-tools > ::content > .title {
-        margin-left: 56px;
-      }
-
-      .toolbar-tools > ::content > paper-icon-button + .title {
-        margin-left: 0;
-      }
-
-      /**
-       * The --paper-toolbar-title mixin is applied here instead of above to
-       * fix the issue with margin-left being ignored due to css ordering.
-       */
-      .toolbar-tools > ::content .title {
-        @apply(--paper-toolbar-title);
-      }
-
-      .toolbar-tools > ::content paper-icon-button[icon=menu] {
-        margin-right: 24px;
-      }
-
-      .toolbar-tools > ::content > .fit {
-        position: absolute;
-        top: auto;
-        right: 0;
-        bottom: 0;
-        left: 0;
-        width: auto;
-        margin: 0;
-      }
-
-      /* TODO(noms): Until we have a better solution for classes that don't use
-       * /deep/ create our own.
-       */
-      .start-justified {
-        @apply(--layout-start-justified);
-      }
-
-      .center-justified {
-        @apply(--layout-center-justified);
-      }
-
-      .end-justified {
-        @apply(--layout-end-justified);
-      }
-
-      .around-justified {
-        @apply(--layout-around-justified);
-      }
-
-      .justified {
-        @apply(--layout-justified);
-      }
-    </style>
-
-    <div id="topBar" class$="toolbar-tools [[_computeBarExtraClasses(justify)]]">
-      <content select=":not(.middle):not(.bottom)"></content>
-    </div>
-
-    <div id="middleBar" class$="toolbar-tools [[_computeBarExtraClasses(middleJustify)]]">
-      <content select=".middle"></content>
-    </div>
-
-    <div id="bottomBar" class$="toolbar-tools [[_computeBarExtraClasses(bottomJustify)]]">
-      <content select=".bottom"></content>
-    </div>
-  </template>
-
-  </dom-module>
-<script src="paper-toolbar-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 628185f..72cb2da3 100644
--- a/third_party/polymer/v1_0/components_summary.txt
+++ b/third_party/polymer/v1_0/components_summary.txt
@@ -298,12 +298,6 @@
 Revision: 2f279868a9c8965aba76017c7ee6008ac4879f6a
 Tree link: https://github.com/PolymerElements/paper-toggle-button/tree/v1.3.0
 
-Name: paper-toolbar
-Repository: https://github.com/PolymerElements/paper-toolbar.git
-Tree: v1.1.6
-Revision: 39b8ad381bd4ba7834ed8f30a938b49810b9204f
-Tree link: https://github.com/PolymerElements/paper-toolbar/tree/v1.1.6
-
 Name: paper-tooltip
 Repository: https://github.com/PolymerElements/paper-tooltip.git
 Tree: v1.1.3
diff --git a/third_party/zlib/BUILD.gn b/third_party/zlib/BUILD.gn
index 4b4db15b..11f57ef 100644
--- a/third_party/zlib/BUILD.gn
+++ b/third_party/zlib/BUILD.gn
@@ -2,10 +2,61 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+if (current_cpu == "arm" || current_cpu == "arm64") {
+  import("//build/config/arm.gni")
+}
+
 config("zlib_config") {
   include_dirs = [ "." ]
 }
 
+config("zlib_adler32_simd_config") {
+  if (!is_ios && (current_cpu == "x86" || current_cpu == "x64")) {
+    defines = [ "ADLER32_SIMD_SSSE3" ]
+  }
+
+  if (current_cpu == "arm" || current_cpu == "arm64") {
+    if (arm_use_neon) {
+      defines = [ "ADLER32_SIMD_NEON" ]
+    }
+  }
+}
+
+source_set("zlib_adler32_simd") {
+  visibility = [ ":*" ]
+
+  if (!is_ios && (current_cpu == "x86" || current_cpu == "x64")) {
+    sources = [
+      "adler32_simd.c",
+      "adler32_simd.h",
+    ]
+
+    if (!is_win || is_clang) {
+      cflags = [ "-mssse3" ]
+    }
+  }
+
+  if (current_cpu == "arm" || current_cpu == "arm64") {
+    if (arm_use_neon) {
+      sources = [
+        "adler32_simd.c",
+        "adler32_simd.h",
+      ]
+
+      if (!is_debug) {
+        # Use optimize_speed (-O3) to output the _smallest_ code.
+        configs -= [ "//build/config/compiler:default_optimization" ]
+        configs += [ "//build/config/compiler:optimize_speed" ]
+      }
+    }
+  }
+
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [ "//build/config/compiler:no_chromium_code" ]
+
+  public_configs = [ ":zlib_adler32_simd_config" ]
+}
+
 static_library("zlib_x86_simd") {
   if (!is_ios && (current_cpu == "x86" || current_cpu == "x64")) {
     sources = [
@@ -71,8 +122,34 @@
     "zutil.h",
   ]
 
+  if (current_cpu == "arm" || current_cpu == "arm64") {
+    if (arm_use_neon) {
+      # TODO: handle InflateBack case, see crbug.com/769880.
+      sources -= [
+        "inffast.c",
+        "inflate.c",
+      ]
+      sources += [
+        "contrib/arm/chunkcopy.h",
+        "contrib/arm/inffast.c",
+        "contrib/arm/inflate.c",
+      ]
+    }
+  }
+
+  defines = []
+  deps = []
+
   if (!is_ios && (current_cpu == "x86" || current_cpu == "x64")) {
     sources += [ "x86.c" ]
+
+    deps += [ ":zlib_adler32_simd" ]
+  }
+
+  if (current_cpu == "arm" || current_cpu == "arm64") {
+    if (arm_use_neon) {
+      deps += [ ":zlib_adler32_simd" ]
+    }
   }
 
   configs -= [ "//build/config/compiler:chromium_code" ]
@@ -84,8 +161,9 @@
   ]
 
   public_configs = [ ":zlib_config" ]
-  deps = [
-    ":zlib_x86_simd",
+
+  deps += [
+    ":zlib_x86_simd"
   ]
 }
 
@@ -132,5 +210,6 @@
     # Must be after no_chromium_code for warning flags to be ordered correctly.
     ":minizip_warnings",
   ]
+
   public_configs = [ ":zlib_config" ]
 }
diff --git a/third_party/zlib/adler32.c b/third_party/zlib/adler32.c
index d0be438..03491b9 100644
--- a/third_party/zlib/adler32.c
+++ b/third_party/zlib/adler32.c
@@ -59,6 +59,13 @@
 #  define MOD63(a) a %= BASE
 #endif
 
+#if defined(ADLER32_SIMD_SSSE3)
+#include "adler32_simd.h"
+#include "x86.h"
+#elif defined(ADLER32_SIMD_NEON)
+#include "adler32_simd.h"
+#endif
+
 /* ========================================================================= */
 uLong ZEXPORT adler32_z(adler, buf, len)
     uLong adler;
@@ -68,6 +75,14 @@
     unsigned long sum2;
     unsigned n;
 
+#if defined(ADLER32_SIMD_SSSE3)
+    if (x86_cpu_enable_ssse3 && buf && len >= 64)
+        return adler32_simd_(adler, buf, len);
+#elif defined(ADLER32_SIMD_NEON)
+    if (buf && len >= 64)
+        return adler32_simd_(adler, buf, len);
+#endif
+
     /* split Adler-32 into component sums */
     sum2 = (adler >> 16) & 0xffff;
     adler &= 0xffff;
diff --git a/third_party/zlib/adler32_simd.c b/third_party/zlib/adler32_simd.c
new file mode 100644
index 0000000..d73f97e
--- /dev/null
+++ b/third_party/zlib/adler32_simd.c
@@ -0,0 +1,366 @@
+/* adler32_simd.c
+ *
+ * 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 Chromium source repository LICENSE file.
+ *
+ * Per http://en.wikipedia.org/wiki/Adler-32 the adler32 A value (aka s1) is
+ * the sum of N input data bytes D1 ... DN,
+ *
+ *   A = A0 + D1 + D2 + ... + DN
+ *
+ * where A0 is the initial value.
+ *
+ * SSE2 _mm_sad_epu8() can be used for byte sums (see http://bit.ly/2wpUOeD,
+ * for example) and accumulating the byte sums can use SSE shuffle-adds (see
+ * the "Integer" section of http://bit.ly/2erPT8t for details). Arm NEON has
+ * similar instructions.
+ *
+ * The adler32 B value (aka s2) sums the A values from each step:
+ *
+ *   B0 + (A0 + D1) + (A0 + D1 + D2) + ... + (A0 + D1 + D2 + ... + DN) or
+ *
+ *       B0 + N.A0 + N.D1 + (N-1).D2 + (N-2).D3 + ... + (N-(N-1)).DN
+ *
+ * B0 being the initial value. For 32 bytes (ideal for garden-variety SIMD):
+ *
+ *   B = B0 + 32.A0 + [D1 D2 D3 ... D32] x [32 31 30 ... 1].
+ *
+ * Adjacent blocks of 32 input bytes can be iterated with the expressions to
+ * compute the adler32 s1 s2 of M >> 32 input bytes [1].
+ *
+ * As M grows, the s1 s2 sums grow. If left unchecked, they would eventually
+ * overflow the precision of their integer representation (bad). However, s1
+ * and s2 also need to be computed modulo the adler BASE value (reduced). If
+ * at most NMAX bytes are processed before a reduce, s1 s2 _cannot_ overflow
+ * a uint32_t type (the NMAX constraint) [2].
+ *
+ * [1] the iterative equations for s2 contain constant factors; these can be
+ * hoisted from the n-blocks do loop of the SIMD code.
+ *
+ * [2] zlib adler32_z() uses this fact to implement NMAX-block-based updates
+ * of the adler s1 s2 of uint32_t type (see adler32.c).
+ */
+
+#include "adler32_simd.h"
+
+/* Definitions from adler32.c: largest prime smaller than 65536 */
+#define BASE 65521U
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+#define NMAX 5552
+
+#if defined(ADLER32_SIMD_SSSE3)
+
+#include <tmmintrin.h>
+
+uint32_t ZLIB_INTERNAL adler32_simd_(  /* SSSE3 */
+    uint32_t adler,
+    const unsigned char *buf,
+    z_size_t len)
+{
+    /*
+     * Split Adler-32 into component sums.
+     */
+    uint32_t s1 = adler & 0xffff;
+    uint32_t s2 = adler >> 16;
+
+    /*
+     * Process the data in blocks.
+     */
+    const unsigned BLOCK_SIZE = 1 << 5;
+
+    z_size_t blocks = len / BLOCK_SIZE;
+    len -= blocks * BLOCK_SIZE;
+
+    while (blocks)
+    {
+        unsigned n = NMAX / BLOCK_SIZE;  /* The NMAX constraint. */
+        if (n > blocks)
+            n = blocks;
+        blocks -= n;
+
+        const __m128i tap1 =
+            _mm_setr_epi8(32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17);
+        const __m128i tap2 =
+            _mm_setr_epi8(16,15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1);
+        const __m128i zero =
+            _mm_setr_epi8( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+        const __m128i ones =
+            _mm_set_epi16( 1, 1, 1, 1, 1, 1, 1, 1);
+
+        /*
+         * Process n blocks of data. At most NMAX data bytes can be
+         * processed before s2 must be reduced modulo BASE.
+         */
+        __m128i v_ps = _mm_set_epi32(0, 0, 0, s1 * n);
+        __m128i v_s2 = _mm_set_epi32(0, 0, 0, s2);
+        __m128i v_s1 = _mm_set_epi32(0, 0, 0, 0);
+
+        do {
+            /*
+             * Load 32 input bytes.
+             */
+            const __m128i bytes1 = _mm_loadu_si128((__m128i*)(buf));
+            const __m128i bytes2 = _mm_loadu_si128((__m128i*)(buf + 16));
+
+            /*
+             * Add previous block byte sum to v_ps.
+             */
+            v_ps = _mm_add_epi32(v_ps, v_s1);
+
+            /*
+             * Horizontally add the bytes for s1, multiply-adds the
+             * bytes by [ 32, 31, 30, ... ] for s2.
+             */
+            v_s1 = _mm_add_epi32(v_s1, _mm_sad_epu8(bytes1, zero));
+            const __m128i mad1 = _mm_maddubs_epi16(bytes1, tap1);
+            v_s2 = _mm_add_epi32(v_s2, _mm_madd_epi16(mad1, ones));
+
+            v_s1 = _mm_add_epi32(v_s1, _mm_sad_epu8(bytes2, zero));
+            const __m128i mad2 = _mm_maddubs_epi16(bytes2, tap2);
+            v_s2 = _mm_add_epi32(v_s2, _mm_madd_epi16(mad2, ones));
+
+            buf += BLOCK_SIZE;
+
+        } while (--n);
+
+        v_s2 = _mm_add_epi32(v_s2, _mm_slli_epi32(v_ps, 5));
+
+        /*
+         * Sum epi32 ints v_s1(s2) and accumulate in s1(s2).
+         */
+
+#define S23O1 _MM_SHUFFLE(2,3,0,1)  /* A B C D -> B A D C */
+#define S1O32 _MM_SHUFFLE(1,0,3,2)  /* A B C D -> C D A B */
+
+        v_s1 = _mm_add_epi32(v_s1, _mm_shuffle_epi32(v_s1, S23O1));
+        v_s1 = _mm_add_epi32(v_s1, _mm_shuffle_epi32(v_s1, S1O32));
+
+        s1 += _mm_cvtsi128_si32(v_s1);
+
+        v_s2 = _mm_add_epi32(v_s2, _mm_shuffle_epi32(v_s2, S23O1));
+        v_s2 = _mm_add_epi32(v_s2, _mm_shuffle_epi32(v_s2, S1O32));
+
+        s2 = _mm_cvtsi128_si32(v_s2);
+
+#undef S23O1
+#undef S1O32
+
+        /*
+         * Reduce.
+         */
+        s1 %= BASE;
+        s2 %= BASE;
+    }
+
+    /*
+     * Handle leftover data.
+     */
+    if (len) {
+        if (len >= 16) {
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+
+            len -= 16;
+        }
+
+        while (len--) {
+            s2 += (s1 += *buf++);
+        }
+
+        if (s1 >= BASE)
+            s1 -= BASE;
+        s2 %= BASE;
+    }
+
+    /*
+     * Return the recombined sums.
+     */
+    return s1 | (s2 << 16);
+}
+
+#elif defined(ADLER32_SIMD_NEON)
+
+#include <arm_neon.h>
+
+uint32_t ZLIB_INTERNAL adler32_simd_(  /* NEON */
+    uint32_t adler,
+    const unsigned char *buf,
+    z_size_t len)
+{
+    /*
+     * Split Adler-32 into component sums.
+     */
+    uint32_t s1 = adler & 0xffff;
+    uint32_t s2 = adler >> 16;
+
+    /*
+     * Serially compute s1 & s2, until the data is 16-byte aligned.
+     */
+    if ((uintptr_t)buf & 15) {
+        while ((uintptr_t)buf & 15) {
+            s2 += (s1 += *buf++);
+            --len;
+        }
+
+        if (s1 >= BASE)
+            s1 -= BASE;
+        s2 %= BASE;
+    }
+
+    /*
+     * Process the data in blocks.
+     */
+    const unsigned BLOCK_SIZE = 1 << 5;
+
+    z_size_t blocks = len / BLOCK_SIZE;
+    len -= blocks * BLOCK_SIZE;
+
+    while (blocks)
+    {
+        unsigned n = NMAX / BLOCK_SIZE;  /* The NMAX constraint. */
+        if (n > blocks)
+            n = blocks;
+        blocks -= n;
+
+        /*
+         * Process n blocks of data. At most NMAX data bytes can be
+         * processed before s2 must be reduced modulo BASE.
+         */
+        uint32x4_t v_s2 = (uint32x4_t) { 0, 0, 0, s1 * n };
+        uint32x4_t v_s1 = (uint32x4_t) { 0, 0, 0, 0 };
+
+        uint16x8_t v_column_sum_1 = vdupq_n_u16(0);
+        uint16x8_t v_column_sum_2 = vdupq_n_u16(0);
+        uint16x8_t v_column_sum_3 = vdupq_n_u16(0);
+        uint16x8_t v_column_sum_4 = vdupq_n_u16(0);
+
+        do {
+            /*
+             * Load 32 input bytes.
+             */
+            const uint8x16_t bytes1 = vld1q_u8((uint8_t*)(buf));
+            const uint8x16_t bytes2 = vld1q_u8((uint8_t*)(buf + 16));
+
+            /*
+             * Add previous block byte sum to v_s2.
+             */
+            v_s2 = vaddq_u32(v_s2, v_s1);
+
+            /*
+             * Horizontally add the bytes for s1.
+             */
+            v_s1 = vpadalq_u16(v_s1, vpadalq_u8(vpaddlq_u8(bytes1), bytes2));
+
+            /*
+             * Vertically add the bytes for s2.
+             */
+            v_column_sum_1 = vaddw_u8(v_column_sum_1, vget_low_u8 (bytes1));
+            v_column_sum_2 = vaddw_u8(v_column_sum_2, vget_high_u8(bytes1));
+            v_column_sum_3 = vaddw_u8(v_column_sum_3, vget_low_u8 (bytes2));
+            v_column_sum_4 = vaddw_u8(v_column_sum_4, vget_high_u8(bytes2));
+
+            buf += BLOCK_SIZE;
+
+        } while (--n);
+
+        v_s2 = vshlq_n_u32(v_s2, 5);
+
+        /*
+         * Multiply-add bytes by [ 32, 31, 30, ... ] for s2.
+         */
+        v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_1),
+            (uint16x4_t) { 32, 31, 30, 29 });
+        v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_1),
+            (uint16x4_t) { 28, 27, 26, 25 });
+        v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_2),
+            (uint16x4_t) { 24, 23, 22, 21 });
+        v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_2),
+            (uint16x4_t) { 20, 19, 18, 17 });
+        v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_3),
+            (uint16x4_t) { 16, 15, 14, 13 });
+        v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_3),
+            (uint16x4_t) { 12, 11, 10,  9 });
+        v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_4),
+            (uint16x4_t) {  8,  7,  6,  5 });
+        v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_4),
+            (uint16x4_t) {  4,  3,  2,  1 });
+
+        /*
+         * Sum epi32 ints v_s1(s2) and accumulate in s1(s2).
+         */
+        uint32x2_t sum1 = vpadd_u32(vget_low_u32(v_s1), vget_high_u32(v_s1));
+        uint32x2_t sum2 = vpadd_u32(vget_low_u32(v_s2), vget_high_u32(v_s2));
+        uint32x2_t s1s2 = vpadd_u32(sum1, sum2);
+
+        s1 += vget_lane_u32(s1s2, 0);
+        s2 += vget_lane_u32(s1s2, 1);
+
+        /*
+         * Reduce.
+         */
+        s1 %= BASE;
+        s2 %= BASE;
+    }
+
+    /*
+     * Handle leftover data.
+     */
+    if (len) {
+        if (len >= 16) {
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+            s2 += (s1 += *buf++);
+
+            len -= 16;
+        }
+
+        while (len--) {
+            s2 += (s1 += *buf++);
+        }
+
+        if (s1 >= BASE)
+            s1 -= BASE;
+        s2 %= BASE;
+    }
+
+    /*
+     * Return the recombined sums.
+     */
+    return s1 | (s2 << 16);
+}
+
+#endif  /* ADLER32_SIMD_SSSE3 */
diff --git a/third_party/zlib/adler32_simd.h b/third_party/zlib/adler32_simd.h
new file mode 100644
index 0000000..52bb14d
--- /dev/null
+++ b/third_party/zlib/adler32_simd.h
@@ -0,0 +1,16 @@
+/* adler32_simd.h
+ *
+ * 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 Chromium source repository LICENSE file.
+ */
+
+#include <stdint.h>
+
+#include "zconf.h"
+#include "zutil.h"
+
+uint32_t ZLIB_INTERNAL adler32_simd_(
+    uint32_t adler,
+    const unsigned char *buf,
+    z_size_t len);
diff --git a/third_party/zlib/contrib/arm/chunkcopy.h b/third_party/zlib/contrib/arm/chunkcopy.h
new file mode 100644
index 0000000..bc8a77d
--- /dev/null
+++ b/third_party/zlib/contrib/arm/chunkcopy.h
@@ -0,0 +1,297 @@
+/* chunkcopy.h -- fast copies and sets
+ * Copyright (C) 2017 ARM, Inc.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#ifndef CHUNKCOPY_H
+#define CHUNKCOPY_H
+
+#include <arm_neon.h>
+#include "zutil.h"
+
+#if __STDC_VERSION__ >= 199901L
+#define Z_RESTRICT restrict
+#else
+#define Z_RESTRICT
+#endif
+
+typedef uint8x16_t chunkcopy_chunk_t;
+#define CHUNKCOPY_CHUNK_SIZE sizeof(chunkcopy_chunk_t)
+
+/*
+   Ask the compiler to perform a wide, unaligned load with an machine
+   instruction appropriate for the chunkcopy_chunk_t type.
+ */
+static inline chunkcopy_chunk_t loadchunk(const unsigned char FAR* s) {
+  chunkcopy_chunk_t c;
+  __builtin_memcpy(&c, s, sizeof(c));
+  return c;
+}
+
+/*
+   Ask the compiler to perform a wide, unaligned store with an machine
+   instruction appropriate for the chunkcopy_chunk_t type.
+ */
+static inline void storechunk(unsigned char FAR* d, chunkcopy_chunk_t c) {
+  __builtin_memcpy(d, &c, sizeof(c));
+}
+
+/*
+   Perform a memcpy-like operation, but assume that length is non-zero and that
+   it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE bytes of output even if
+   the length is shorter than this.
+
+   It also guarantees that it will properly unroll the data if the distance
+   between `out` and `from` is at least CHUNKCOPY_CHUNK_SIZE, which we rely on
+   in chunkcopy_relaxed().
+
+   Aside from better memory bus utilisation, this means that short copies
+   (CHUNKCOPY_CHUNK_SIZE bytes or fewer) will fall straight through the loop
+   without iteration, which will hopefully make the branch prediction more
+   reliable.
+ */
+static inline unsigned char FAR* chunkcopy_core(unsigned char FAR* out,
+                                                const unsigned char FAR* from,
+                                                unsigned len) {
+  int bump = (--len % CHUNKCOPY_CHUNK_SIZE) + 1;
+  storechunk(out, loadchunk(from));
+  out += bump;
+  from += bump;
+  len /= CHUNKCOPY_CHUNK_SIZE;
+  while (len-- > 0) {
+    storechunk(out, loadchunk(from));
+    out += CHUNKCOPY_CHUNK_SIZE;
+    from += CHUNKCOPY_CHUNK_SIZE;
+  }
+  return out;
+}
+
+/*
+   Like chunkcopy_core, but avoid writing beyond of legal output.
+
+   Accepts an additional pointer to the end of safe output.  A generic safe
+   copy would use (out + len), but it's normally the case that the end of the
+   output buffer is beyond the end of the current copy, and this can still be
+   exploited.
+ */
+static inline unsigned char FAR* chunkcopy_core_safe(
+    unsigned char FAR* out,
+    const unsigned char FAR* from,
+    unsigned len,
+    unsigned char FAR* limit) {
+  Assert(out + len <= limit, "chunk copy exceeds safety limit");
+  if (limit - out < CHUNKCOPY_CHUNK_SIZE) {
+    const unsigned char FAR* Z_RESTRICT rfrom = from;
+    if (len & 8) {
+      __builtin_memcpy(out, rfrom, 8);
+      out += 8;
+      rfrom += 8;
+    }
+    if (len & 4) {
+      __builtin_memcpy(out, rfrom, 4);
+      out += 4;
+      rfrom += 4;
+    }
+    if (len & 2) {
+      __builtin_memcpy(out, rfrom, 2);
+      out += 2;
+      rfrom += 2;
+    }
+    if (len & 1) {
+      *out++ = *rfrom++;
+    }
+    return out;
+  }
+  return chunkcopy_core(out, from, len);
+}
+
+/*
+   Perform short copies until distance can be rewritten as being at least
+   CHUNKCOPY_CHUNK_SIZE.
+
+   This assumes that it's OK to overwrite at least the first
+   2*CHUNKCOPY_CHUNK_SIZE bytes of output even if the copy is shorter than
+   this.  This assumption holds within inflate_fast() which starts every
+   iteration with at least 258 bytes of output space available (258 being the
+   maximum length output from a single token; see inffast.c).
+ */
+static inline unsigned char FAR* chunkunroll_relaxed(unsigned char FAR* out,
+                                                     unsigned FAR* dist,
+                                                     unsigned FAR* len) {
+  const unsigned char FAR* from = out - *dist;
+  while (*dist < *len && *dist < CHUNKCOPY_CHUNK_SIZE) {
+    storechunk(out, loadchunk(from));
+    out += *dist;
+    *len -= *dist;
+    *dist += *dist;
+  }
+  return out;
+}
+
+static inline uint8x16_t chunkset_vld1q_dup_u8x8(
+    const unsigned char FAR* Z_RESTRICT from) {
+#if defined(__clang__) || defined(__aarch64__)
+  return vreinterpretq_u8_u64(vld1q_dup_u64((void*)from));
+#else
+  /* 32-bit GCC uses an alignment hint for vld1q_dup_u64, even when given a
+   * void pointer, so here's an alternate implementation.
+   */
+  uint8x8_t h = vld1_u8(from);
+  return vcombine_u8(h, h);
+#endif
+}
+
+/*
+   Perform an overlapping copy which behaves as a memset() operation, but
+   supporting periods other than one, and assume that length is non-zero and
+   that it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE*3 bytes of output
+   even if the length is shorter than this.
+ */
+static inline unsigned char FAR* chunkset_core(unsigned char FAR* out,
+                                               unsigned period,
+                                               unsigned len) {
+  uint8x16_t f;
+  int bump = ((len - 1) % sizeof(f)) + 1;
+
+  switch (period) {
+    case 1:
+      f = vld1q_dup_u8(out - 1);
+      vst1q_u8(out, f);
+      out += bump;
+      len -= bump;
+      while (len > 0) {
+        vst1q_u8(out, f);
+        out += sizeof(f);
+        len -= sizeof(f);
+      }
+      return out;
+    case 2:
+      f = vreinterpretq_u8_u16(vld1q_dup_u16((void*)(out - 2)));
+      vst1q_u8(out, f);
+      out += bump;
+      len -= bump;
+      if (len > 0) {
+        f = vreinterpretq_u8_u16(vld1q_dup_u16((void*)(out - 2)));
+        do {
+          vst1q_u8(out, f);
+          out += sizeof(f);
+          len -= sizeof(f);
+        } while (len > 0);
+      }
+      return out;
+    case 4:
+      f = vreinterpretq_u8_u32(vld1q_dup_u32((void*)(out - 4)));
+      vst1q_u8(out, f);
+      out += bump;
+      len -= bump;
+      if (len > 0) {
+        f = vreinterpretq_u8_u32(vld1q_dup_u32((void*)(out - 4)));
+        do {
+          vst1q_u8(out, f);
+          out += sizeof(f);
+          len -= sizeof(f);
+        } while (len > 0);
+      }
+      return out;
+    case 8:
+      f = chunkset_vld1q_dup_u8x8(out - 8);
+      vst1q_u8(out, f);
+      out += bump;
+      len -= bump;
+      if (len > 0) {
+        f = chunkset_vld1q_dup_u8x8(out - 8);
+        do {
+          vst1q_u8(out, f);
+          out += sizeof(f);
+          len -= sizeof(f);
+        } while (len > 0);
+      }
+      return out;
+  }
+  out = chunkunroll_relaxed(out, &period, &len);
+  return chunkcopy_core(out, out - period, len);
+}
+
+/*
+   Perform a memcpy-like operation, but assume that length is non-zero and that
+   it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE bytes of output even if
+   the length is shorter than this.
+
+   Unlike chunkcopy_core() above, no guarantee is made regarding the behaviour
+   of overlapping buffers, regardless of the distance between the pointers.
+   This is reflected in the `restrict`-qualified pointers, allowing the
+   compiler to reorder loads and stores.
+ */
+static inline unsigned char FAR* chunkcopy_relaxed(
+    unsigned char FAR* Z_RESTRICT out,
+    const unsigned char FAR* Z_RESTRICT from,
+    unsigned len) {
+  return chunkcopy_core(out, from, len);
+}
+
+/*
+   Like chunkcopy_relaxed, but avoid writing beyond of legal output.
+
+   Unlike chunkcopy_core_safe() above, no guarantee is made regarding the
+   behaviour of overlapping buffers, regardless of the distance between the
+   pointers.  This is reflected in the `restrict`-qualified pointers, allowing
+   the compiler to reorder loads and stores.
+
+   Accepts an additional pointer to the end of safe output.  A generic safe
+   copy would use (out + len), but it's normally the case that the end of the
+   output buffer is beyond the end of the current copy, and this can still be
+   exploited.
+ */
+static inline unsigned char FAR* chunkcopy_safe(
+    unsigned char FAR* out,
+    const unsigned char FAR* Z_RESTRICT from,
+    unsigned len,
+    unsigned char FAR* limit) {
+  Assert(out + len <= limit, "chunk copy exceeds safety limit");
+  return chunkcopy_core_safe(out, from, len, limit);
+}
+
+/*
+   Perform chunky copy within the same buffer, where the source and destination
+   may potentially overlap.
+
+   Assumes that len > 0 on entry, and that it's safe to write at least
+   CHUNKCOPY_CHUNK_SIZE*3 bytes to the output.
+ */
+static inline unsigned char FAR*
+chunkcopy_lapped_relaxed(unsigned char FAR* out, unsigned dist, unsigned len) {
+  if (dist < len && dist < CHUNKCOPY_CHUNK_SIZE) {
+    return chunkset_core(out, dist, len);
+  }
+  return chunkcopy_core(out, out - dist, len);
+}
+
+/*
+   Behave like chunkcopy_lapped_relaxed, but avoid writing beyond of legal
+   output.
+
+   Accepts an additional pointer to the end of safe output.  A generic safe
+   copy would use (out + len), but it's normally the case that the end of the
+   output buffer is beyond the end of the current copy, and this can still be
+   exploited.
+ */
+static inline unsigned char FAR* chunkcopy_lapped_safe(
+    unsigned char FAR* out,
+    unsigned dist,
+    unsigned len,
+    unsigned char FAR* limit) {
+  Assert(out + len <= limit, "chunk copy exceeds safety limit");
+  if (limit - out < CHUNKCOPY_CHUNK_SIZE * 3) {
+    /* TODO: try harder to optimise this */
+    while (len-- > 0) {
+      *out = *(out - dist);
+      out++;
+    }
+    return out;
+  }
+  return chunkcopy_lapped_relaxed(out, dist, len);
+}
+
+#undef Z_RESTRICT
+
+#endif /* CHUNKCOPY_H */
diff --git a/third_party/zlib/contrib/arm/inffast.c b/third_party/zlib/contrib/arm/inffast.c
new file mode 100644
index 0000000..f7f5007
--- /dev/null
+++ b/third_party/zlib/contrib/arm/inffast.c
@@ -0,0 +1,307 @@
+/* inffast.c -- fast decoding
+ * Copyright (C) 1995-2017 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+#include "chunkcopy.h"
+
+#ifdef ASMINF
+#  pragma message("Assembler code may have bugs -- use at your own risk")
+#else
+
+/*
+   Decode literal, length, and distance codes and write out the resulting
+   literal and match bytes until either not enough input or output is
+   available, an end-of-block is encountered, or a data error is encountered.
+   When large enough input and output buffers are supplied to inflate(), for
+   example, a 16K input buffer and a 64K output buffer, more than 95% of the
+   inflate execution time is spent in this routine.
+
+   Entry assumptions:
+
+        state->mode == LEN
+        strm->avail_in >= 6
+        strm->avail_out >= 258
+        start >= strm->avail_out
+        state->bits < 8
+
+   On return, state->mode is one of:
+
+        LEN -- ran out of enough output space or enough available input
+        TYPE -- reached end of block code, inflate() to interpret next block
+        BAD -- error in block data
+
+   Notes:
+
+    - The maximum input bits used by a length/distance pair is 15 bits for the
+      length code, 5 bits for the length extra, 15 bits for the distance code,
+      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
+      Therefore if strm->avail_in >= 6, then there is enough input to avoid
+      checking for available input while decoding.
+
+    - The maximum bytes that a single length/distance pair can output is 258
+      bytes, which is the maximum length that can be coded.  inflate_fast()
+      requires strm->avail_out >= 258 for each loop to avoid checking for
+      output space.
+ */
+void ZLIB_INTERNAL inflate_fast(strm, start)
+z_streamp strm;
+unsigned start;         /* inflate()'s starting value for strm->avail_out */
+{
+    struct inflate_state FAR *state;
+    z_const unsigned char FAR *in;      /* local strm->next_in */
+    z_const unsigned char FAR *last;    /* have enough input while in < last */
+    unsigned char FAR *out;     /* local strm->next_out */
+    unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
+    unsigned char FAR *end;     /* while out < end, enough space available */
+    unsigned char FAR *limit;   /* safety limit for chunky copies */
+#ifdef INFLATE_STRICT
+    unsigned dmax;              /* maximum distance from zlib header */
+#endif
+    unsigned wsize;             /* window size or zero if not using window */
+    unsigned whave;             /* valid bytes in the window */
+    unsigned wnext;             /* window write index */
+    unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */
+    unsigned long hold;         /* local strm->hold */
+    unsigned bits;              /* local strm->bits */
+    code const FAR *lcode;      /* local strm->lencode */
+    code const FAR *dcode;      /* local strm->distcode */
+    unsigned lmask;             /* mask for first level of length codes */
+    unsigned dmask;             /* mask for first level of distance codes */
+    code here;                  /* retrieved table entry */
+    unsigned op;                /* code bits, operation, extra bits, or */
+                                /*  window position, window bytes to copy */
+    unsigned len;               /* match length, unused bytes */
+    unsigned dist;              /* match distance */
+    unsigned char FAR *from;    /* where to copy match from */
+
+    /* copy state to local variables */
+    state = (struct inflate_state FAR *)strm->state;
+    in = strm->next_in;
+    last = in + (strm->avail_in - 5);
+    out = strm->next_out;
+    beg = out - (start - strm->avail_out);
+    end = out + (strm->avail_out - 257);
+    limit = out + strm->avail_out;
+#ifdef INFLATE_STRICT
+    dmax = state->dmax;
+#endif
+    wsize = state->wsize;
+    whave = state->whave;
+    wnext = (state->wnext == 0 && whave >= wsize) ? wsize : state->wnext;
+    window = state->window;
+    hold = state->hold;
+    bits = state->bits;
+    lcode = state->lencode;
+    dcode = state->distcode;
+    lmask = (1U << state->lenbits) - 1;
+    dmask = (1U << state->distbits) - 1;
+
+    /* decode literals and length/distances until end-of-block or not enough
+       input data or output space */
+    do {
+        if (bits < 15) {
+            hold += (unsigned long)(*in++) << bits;
+            bits += 8;
+            hold += (unsigned long)(*in++) << bits;
+            bits += 8;
+        }
+        here = lcode[hold & lmask];
+      dolen:
+        op = (unsigned)(here.bits);
+        hold >>= op;
+        bits -= op;
+        op = (unsigned)(here.op);
+        if (op == 0) {                          /* literal */
+            Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+                    "inflate:         literal '%c'\n" :
+                    "inflate:         literal 0x%02x\n", here.val));
+            *out++ = (unsigned char)(here.val);
+        }
+        else if (op & 16) {                     /* length base */
+            len = (unsigned)(here.val);
+            op &= 15;                           /* number of extra bits */
+            if (op) {
+                if (bits < op) {
+                    hold += (unsigned long)(*in++) << bits;
+                    bits += 8;
+                }
+                len += (unsigned)hold & ((1U << op) - 1);
+                hold >>= op;
+                bits -= op;
+            }
+            Tracevv((stderr, "inflate:         length %u\n", len));
+            if (bits < 15) {
+                hold += (unsigned long)(*in++) << bits;
+                bits += 8;
+                hold += (unsigned long)(*in++) << bits;
+                bits += 8;
+            }
+            here = dcode[hold & dmask];
+          dodist:
+            op = (unsigned)(here.bits);
+            hold >>= op;
+            bits -= op;
+            op = (unsigned)(here.op);
+            if (op & 16) {                      /* distance base */
+                dist = (unsigned)(here.val);
+                op &= 15;                       /* number of extra bits */
+                if (bits < op) {
+                    hold += (unsigned long)(*in++) << bits;
+                    bits += 8;
+                    if (bits < op) {
+                        hold += (unsigned long)(*in++) << bits;
+                        bits += 8;
+                    }
+                }
+                dist += (unsigned)hold & ((1U << op) - 1);
+#ifdef INFLATE_STRICT
+                if (dist > dmax) {
+                    strm->msg = (char *)"invalid distance too far back";
+                    state->mode = BAD;
+                    break;
+                }
+#endif
+                hold >>= op;
+                bits -= op;
+                Tracevv((stderr, "inflate:         distance %u\n", dist));
+                op = (unsigned)(out - beg);     /* max distance in output */
+                if (dist > op) {                /* see if copy from window */
+                    op = dist - op;             /* distance back in window */
+                    if (op > whave) {
+                        if (state->sane) {
+                            strm->msg =
+                                (char *)"invalid distance too far back";
+                            state->mode = BAD;
+                            break;
+                        }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+                        if (len <= op - whave) {
+                            do {
+                                *out++ = 0;
+                            } while (--len);
+                            continue;
+                        }
+                        len -= op - whave;
+                        do {
+                            *out++ = 0;
+                        } while (--op > whave);
+                        if (op == 0) {
+                            from = out - dist;
+                            do {
+                                *out++ = *from++;
+                            } while (--len);
+                            continue;
+                        }
+#endif
+                    }
+                    from = window;
+                    if (wnext >= op) {          /* contiguous in window */
+                        from += wnext - op;
+                    }
+                    else {                      /* wrap around window */
+                        op -= wnext;
+                        from += wsize - op;
+                        if (op < len) {         /* some from end of window */
+                            len -= op;
+                            out = chunkcopy_safe(out, from, op, limit);
+                            from = window;      /* more from start of window */
+                            op = wnext;
+                            /* This (rare) case can create a situation where
+                               the first chunkcopy below must be checked.
+                             */
+                        }
+                    }
+                    if (op < len) {             /* still need some from output */
+                        out = chunkcopy_safe(out, from, op, limit);
+                        len -= op;
+                        /* When dist is small the amount of data that can be
+                           copied from the window is also small, and progress
+                           towards the dangerous end of the output buffer is
+                           also small.  This means that for trivial memsets and
+                           for chunkunroll_relaxed() a safety check is
+                           unnecessary.  However, these conditions may not be
+                           entered at all, and in that case it's possible that
+                           the main copy is near the end.
+                          */
+                        out = chunkunroll_relaxed(out, &dist, &len);
+                        out = chunkcopy_safe(out, out - dist, len, limit);
+                    } else {
+                        /* from points to window, so there is no risk of
+                           overlapping pointers requiring memset-like behaviour
+                         */
+                        out = chunkcopy_safe(out, from, len, limit);
+                    }
+                }
+                else {
+                    /* Whole reference is in range of current output.  No
+                       range checks are necessary because we start with room
+                       for at least 258 bytes of output, so unroll and roundoff
+                       operations can write beyond `out+len` so long as they
+                       stay within 258 bytes of `out`.
+                     */
+                    out = chunkcopy_lapped_relaxed(out, dist, len);
+                }
+            }
+            else if ((op & 64) == 0) {          /* 2nd level distance code */
+                here = dcode[here.val + (hold & ((1U << op) - 1))];
+                goto dodist;
+            }
+            else {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+        }
+        else if ((op & 64) == 0) {              /* 2nd level length code */
+            here = lcode[here.val + (hold & ((1U << op) - 1))];
+            goto dolen;
+        }
+        else if (op & 32) {                     /* end-of-block */
+            Tracevv((stderr, "inflate:         end of block\n"));
+            state->mode = TYPE;
+            break;
+        }
+        else {
+            strm->msg = (char *)"invalid literal/length code";
+            state->mode = BAD;
+            break;
+        }
+    } while (in < last && out < end);
+
+    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+    len = bits >> 3;
+    in -= len;
+    bits -= len << 3;
+    hold &= (1U << bits) - 1;
+
+    /* update state and return */
+    strm->next_in = in;
+    strm->next_out = out;
+    strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
+    strm->avail_out = (unsigned)(out < end ?
+                                 257 + (end - out) : 257 - (out - end));
+    state->hold = hold;
+    state->bits = bits;
+    return;
+}
+
+/*
+   inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
+   - Using bit fields for code structure
+   - Different op definition to avoid & for extra bits (do & for table bits)
+   - Three separate decoding do-loops for direct, window, and wnext == 0
+   - Special case for distance > 1 copies to do overlapped load and store copy
+   - Explicit branch predictions (based on measured branch probabilities)
+   - Deferring match copy and interspersed it with decoding subsequent codes
+   - Swapping literal/length else
+   - Swapping window/direct else
+   - Larger unrolled copy loops (three is about right)
+   - Moving len -= 3 statement into middle of loop
+ */
+
+#endif /* !ASMINF */
diff --git a/third_party/zlib/contrib/arm/inflate.c b/third_party/zlib/contrib/arm/inflate.c
new file mode 100644
index 0000000..23e95f1f
--- /dev/null
+++ b/third_party/zlib/contrib/arm/inflate.c
@@ -0,0 +1,1572 @@
+/* inflate.c -- zlib decompression
+ * Copyright (C) 1995-2016 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * Change history:
+ *
+ * 1.2.beta0    24 Nov 2002
+ * - First version -- complete rewrite of inflate to simplify code, avoid
+ *   creation of window when not needed, minimize use of window when it is
+ *   needed, make inffast.c even faster, implement gzip decoding, and to
+ *   improve code readability and style over the previous zlib inflate code
+ *
+ * 1.2.beta1    25 Nov 2002
+ * - Use pointers for available input and output checking in inffast.c
+ * - Remove input and output counters in inffast.c
+ * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
+ * - Remove unnecessary second byte pull from length extra in inffast.c
+ * - Unroll direct copy to three copies per loop in inffast.c
+ *
+ * 1.2.beta2    4 Dec 2002
+ * - Change external routine names to reduce potential conflicts
+ * - Correct filename to inffixed.h for fixed tables in inflate.c
+ * - Make hbuf[] unsigned char to match parameter type in inflate.c
+ * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
+ *   to avoid negation problem on Alphas (64 bit) in inflate.c
+ *
+ * 1.2.beta3    22 Dec 2002
+ * - Add comments on state->bits assertion in inffast.c
+ * - Add comments on op field in inftrees.h
+ * - Fix bug in reuse of allocated window after inflateReset()
+ * - Remove bit fields--back to byte structure for speed
+ * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
+ * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
+ * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
+ * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
+ * - Use local copies of stream next and avail values, as well as local bit
+ *   buffer and bit count in inflate()--for speed when inflate_fast() not used
+ *
+ * 1.2.beta4    1 Jan 2003
+ * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
+ * - Move a comment on output buffer sizes from inffast.c to inflate.c
+ * - Add comments in inffast.c to introduce the inflate_fast() routine
+ * - Rearrange window copies in inflate_fast() for speed and simplification
+ * - Unroll last copy for window match in inflate_fast()
+ * - Use local copies of window variables in inflate_fast() for speed
+ * - Pull out common wnext == 0 case for speed in inflate_fast()
+ * - Make op and len in inflate_fast() unsigned for consistency
+ * - Add FAR to lcode and dcode declarations in inflate_fast()
+ * - Simplified bad distance check in inflate_fast()
+ * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
+ *   source file infback.c to provide a call-back interface to inflate for
+ *   programs like gzip and unzip -- uses window as output buffer to avoid
+ *   window copying
+ *
+ * 1.2.beta5    1 Jan 2003
+ * - Improved inflateBack() interface to allow the caller to provide initial
+ *   input in strm.
+ * - Fixed stored blocks bug in inflateBack()
+ *
+ * 1.2.beta6    4 Jan 2003
+ * - Added comments in inffast.c on effectiveness of POSTINC
+ * - Typecasting all around to reduce compiler warnings
+ * - Changed loops from while (1) or do {} while (1) to for (;;), again to
+ *   make compilers happy
+ * - Changed type of window in inflateBackInit() to unsigned char *
+ *
+ * 1.2.beta7    27 Jan 2003
+ * - Changed many types to unsigned or unsigned short to avoid warnings
+ * - Added inflateCopy() function
+ *
+ * 1.2.0        9 Mar 2003
+ * - Changed inflateBack() interface to provide separate opaque descriptors
+ *   for the in() and out() functions
+ * - Changed inflateBack() argument and in_func typedef to swap the length
+ *   and buffer address return values for the input function
+ * - Check next_in and next_out for Z_NULL on entry to inflate()
+ *
+ * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+#include "contrib/arm/chunkcopy.h"
+
+#ifdef MAKEFIXED
+#  ifndef BUILDFIXED
+#    define BUILDFIXED
+#  endif
+#endif
+
+/* function prototypes */
+local int inflateStateCheck OF((z_streamp strm));
+local void fixedtables OF((struct inflate_state FAR *state));
+local int updatewindow OF((z_streamp strm, const unsigned char FAR *end,
+                           unsigned copy));
+#ifdef BUILDFIXED
+   void makefixed OF((void));
+#endif
+local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,
+                              unsigned len));
+
+local int inflateStateCheck(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+    if (strm == Z_NULL ||
+        strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
+        return 1;
+    state = (struct inflate_state FAR *)strm->state;
+    if (state == Z_NULL || state->strm != strm ||
+        state->mode < HEAD || state->mode > SYNC)
+        return 1;
+    return 0;
+}
+
+int ZEXPORT inflateResetKeep(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    strm->total_in = strm->total_out = state->total = 0;
+    strm->msg = Z_NULL;
+    if (state->wrap)        /* to support ill-conceived Java test suite */
+        strm->adler = state->wrap & 1;
+    state->mode = HEAD;
+    state->last = 0;
+    state->havedict = 0;
+    state->dmax = 32768U;
+    state->head = Z_NULL;
+    state->hold = 0;
+    state->bits = 0;
+    state->lencode = state->distcode = state->next = state->codes;
+    state->sane = 1;
+    state->back = -1;
+    Tracev((stderr, "inflate: reset\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflateReset(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    state->wsize = 0;
+    state->whave = 0;
+    state->wnext = 0;
+    return inflateResetKeep(strm);
+}
+
+int ZEXPORT inflateReset2(strm, windowBits)
+z_streamp strm;
+int windowBits;
+{
+    int wrap;
+    struct inflate_state FAR *state;
+
+    /* get the state */
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* extract wrap request from windowBits parameter */
+    if (windowBits < 0) {
+        wrap = 0;
+        windowBits = -windowBits;
+    }
+    else {
+        wrap = (windowBits >> 4) + 5;
+#ifdef GUNZIP
+        if (windowBits < 48)
+            windowBits &= 15;
+#endif
+    }
+
+    /* set number of window bits, free window if different */
+    if (windowBits && (windowBits < 8 || windowBits > 15))
+        return Z_STREAM_ERROR;
+    if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
+        ZFREE(strm, state->window);
+        state->window = Z_NULL;
+    }
+
+    /* update state and reset the rest of it */
+    state->wrap = wrap;
+    state->wbits = (unsigned)windowBits;
+    return inflateReset(strm);
+}
+
+int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
+z_streamp strm;
+int windowBits;
+const char *version;
+int stream_size;
+{
+    int ret;
+    struct inflate_state FAR *state;
+
+    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+        stream_size != (int)(sizeof(z_stream)))
+        return Z_VERSION_ERROR;
+    if (strm == Z_NULL) return Z_STREAM_ERROR;
+    strm->msg = Z_NULL;                 /* in case we return an error */
+    if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
+        strm->zalloc = zcalloc;
+        strm->opaque = (voidpf)0;
+#endif
+    }
+    if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
+        strm->zfree = zcfree;
+#endif
+    state = (struct inflate_state FAR *)
+            ZALLOC(strm, 1, sizeof(struct inflate_state));
+    if (state == Z_NULL) return Z_MEM_ERROR;
+    Tracev((stderr, "inflate: allocated\n"));
+    strm->state = (struct internal_state FAR *)state;
+    state->strm = strm;
+    state->window = Z_NULL;
+    state->mode = HEAD;     /* to pass state test in inflateReset2() */
+    state->check = 1L;      /* 1L is the result of adler32() zero length data */
+    ret = inflateReset2(strm, windowBits);
+    if (ret != Z_OK) {
+        ZFREE(strm, state);
+        strm->state = Z_NULL;
+    }
+    return ret;
+}
+
+int ZEXPORT inflateInit_(strm, version, stream_size)
+z_streamp strm;
+const char *version;
+int stream_size;
+{
+    return inflateInit2_(strm, DEF_WBITS, version, stream_size);
+}
+
+int ZEXPORT inflatePrime(strm, bits, value)
+z_streamp strm;
+int bits;
+int value;
+{
+    struct inflate_state FAR *state;
+
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (bits < 0) {
+        state->hold = 0;
+        state->bits = 0;
+        return Z_OK;
+    }
+    if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR;
+    value &= (1L << bits) - 1;
+    state->hold += (unsigned)value << state->bits;
+    state->bits += (uInt)bits;
+    return Z_OK;
+}
+
+/*
+   Return state with length and distance decoding tables and index sizes set to
+   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
+   If BUILDFIXED is defined, then instead this routine builds the tables the
+   first time it's called, and returns those tables the first time and
+   thereafter.  This reduces the size of the code by about 2K bytes, in
+   exchange for a little execution time.  However, BUILDFIXED should not be
+   used for threaded applications, since the rewriting of the tables and virgin
+   may not be thread-safe.
+ */
+local void fixedtables(state)
+struct inflate_state FAR *state;
+{
+#ifdef BUILDFIXED
+    static int virgin = 1;
+    static code *lenfix, *distfix;
+    static code fixed[544];
+
+    /* build fixed huffman tables if first call (may not be thread safe) */
+    if (virgin) {
+        unsigned sym, bits;
+        static code *next;
+
+        /* literal/length table */
+        sym = 0;
+        while (sym < 144) state->lens[sym++] = 8;
+        while (sym < 256) state->lens[sym++] = 9;
+        while (sym < 280) state->lens[sym++] = 7;
+        while (sym < 288) state->lens[sym++] = 8;
+        next = fixed;
+        lenfix = next;
+        bits = 9;
+        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+        /* distance table */
+        sym = 0;
+        while (sym < 32) state->lens[sym++] = 5;
+        distfix = next;
+        bits = 5;
+        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+        /* do this just once */
+        virgin = 0;
+    }
+#else /* !BUILDFIXED */
+#   include "inffixed.h"
+#endif /* BUILDFIXED */
+    state->lencode = lenfix;
+    state->lenbits = 9;
+    state->distcode = distfix;
+    state->distbits = 5;
+}
+
+#ifdef MAKEFIXED
+#include <stdio.h>
+
+/*
+   Write out the inffixed.h that is #include'd above.  Defining MAKEFIXED also
+   defines BUILDFIXED, so the tables are built on the fly.  makefixed() writes
+   those tables to stdout, which would be piped to inffixed.h.  A small program
+   can simply call makefixed to do this:
+
+    void makefixed(void);
+
+    int main(void)
+    {
+        makefixed();
+        return 0;
+    }
+
+   Then that can be linked with zlib built with MAKEFIXED defined and run:
+
+    a.out > inffixed.h
+ */
+void makefixed()
+{
+    unsigned low, size;
+    struct inflate_state state;
+
+    fixedtables(&state);
+    puts("    /* inffixed.h -- table for decoding fixed codes");
+    puts("     * Generated automatically by makefixed().");
+    puts("     */");
+    puts("");
+    puts("    /* WARNING: this file should *not* be used by applications.");
+    puts("       It is part of the implementation of this library and is");
+    puts("       subject to change. Applications should only use zlib.h.");
+    puts("     */");
+    puts("");
+    size = 1U << 9;
+    printf("    static const code lenfix[%u] = {", size);
+    low = 0;
+    for (;;) {
+        if ((low % 7) == 0) printf("\n        ");
+        printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
+               state.lencode[low].bits, state.lencode[low].val);
+        if (++low == size) break;
+        putchar(',');
+    }
+    puts("\n    };");
+    size = 1U << 5;
+    printf("\n    static const code distfix[%u] = {", size);
+    low = 0;
+    for (;;) {
+        if ((low % 6) == 0) printf("\n        ");
+        printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
+               state.distcode[low].val);
+        if (++low == size) break;
+        putchar(',');
+    }
+    puts("\n    };");
+}
+#endif /* MAKEFIXED */
+
+/*
+   Update the window with the last wsize (normally 32K) bytes written before
+   returning.  If window does not exist yet, create it.  This is only called
+   when a window is already in use, or when output has been written during this
+   inflate call, but the end of the deflate stream has not been reached yet.
+   It is also called to create a window for dictionary data when a dictionary
+   is loaded.
+
+   Providing output buffers larger than 32K to inflate() should provide a speed
+   advantage, since only the last 32K of output is copied to the sliding window
+   upon return from inflate(), and since all distances after the first 32K of
+   output will fall in the output data, making match copies simpler and faster.
+   The advantage may be dependent on the size of the processor's data caches.
+ */
+local int updatewindow(strm, end, copy)
+z_streamp strm;
+const Bytef *end;
+unsigned copy;
+{
+    struct inflate_state FAR *state;
+    unsigned dist;
+
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* if it hasn't been done already, allocate space for the window */
+    if (state->window == Z_NULL) {
+        unsigned wsize = 1U << state->wbits;
+        state->window = (unsigned char FAR *)
+                        ZALLOC(strm, wsize + CHUNKCOPY_CHUNK_SIZE,
+                               sizeof(unsigned char));
+        if (state->window == Z_NULL) return 1;
+#ifdef INFLATE_CLEAR_UNUSED_UNDEFINED
+        /* Copies from the overflow portion of this buffer are undefined and
+           may cause analysis tools to raise a warning if we don't initialize
+           it.  However, this undefined data overwrites other undefined data
+           and is subsequently either overwritten or left deliberately
+           undefined at the end of decode; so there's really no point.
+         */
+        memset(state->window + wsize, 0, CHUNKCOPY_CHUNK_SIZE);
+#endif
+    }
+
+    /* if window not in use yet, initialize */
+    if (state->wsize == 0) {
+        state->wsize = 1U << state->wbits;
+        state->wnext = 0;
+        state->whave = 0;
+    }
+
+    /* copy state->wsize or less output bytes into the circular window */
+    if (copy >= state->wsize) {
+        zmemcpy(state->window, end - state->wsize, state->wsize);
+        state->wnext = 0;
+        state->whave = state->wsize;
+    }
+    else {
+        dist = state->wsize - state->wnext;
+        if (dist > copy) dist = copy;
+        zmemcpy(state->window + state->wnext, end - copy, dist);
+        copy -= dist;
+        if (copy) {
+            zmemcpy(state->window, end - copy, copy);
+            state->wnext = copy;
+            state->whave = state->wsize;
+        }
+        else {
+            state->wnext += dist;
+            if (state->wnext == state->wsize) state->wnext = 0;
+            if (state->whave < state->wsize) state->whave += dist;
+        }
+    }
+    return 0;
+}
+
+/* Macros for inflate(): */
+
+/* check function to use adler32() for zlib or crc32() for gzip */
+#ifdef GUNZIP
+#  define UPDATE(check, buf, len) \
+    (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
+#else
+#  define UPDATE(check, buf, len) adler32(check, buf, len)
+#endif
+
+/* check macros for header crc */
+#ifdef GUNZIP
+#  define CRC2(check, word) \
+    do { \
+        hbuf[0] = (unsigned char)(word); \
+        hbuf[1] = (unsigned char)((word) >> 8); \
+        check = crc32(check, hbuf, 2); \
+    } while (0)
+
+#  define CRC4(check, word) \
+    do { \
+        hbuf[0] = (unsigned char)(word); \
+        hbuf[1] = (unsigned char)((word) >> 8); \
+        hbuf[2] = (unsigned char)((word) >> 16); \
+        hbuf[3] = (unsigned char)((word) >> 24); \
+        check = crc32(check, hbuf, 4); \
+    } while (0)
+#endif
+
+/* Load registers with state in inflate() for speed */
+#define LOAD() \
+    do { \
+        put = strm->next_out; \
+        left = strm->avail_out; \
+        next = strm->next_in; \
+        have = strm->avail_in; \
+        hold = state->hold; \
+        bits = state->bits; \
+    } while (0)
+
+/* Restore state from registers in inflate() */
+#define RESTORE() \
+    do { \
+        strm->next_out = put; \
+        strm->avail_out = left; \
+        strm->next_in = next; \
+        strm->avail_in = have; \
+        state->hold = hold; \
+        state->bits = bits; \
+    } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+    do { \
+        hold = 0; \
+        bits = 0; \
+    } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflate()
+   if there is no input available. */
+#define PULLBYTE() \
+    do { \
+        if (have == 0) goto inf_leave; \
+        have--; \
+        hold += (unsigned long)(*next++) << bits; \
+        bits += 8; \
+    } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator.  If there is
+   not enough available input to do that, then return from inflate(). */
+#define NEEDBITS(n) \
+    do { \
+        while (bits < (unsigned)(n)) \
+            PULLBYTE(); \
+    } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+    ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+    do { \
+        hold >>= (n); \
+        bits -= (unsigned)(n); \
+    } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+    do { \
+        hold >>= bits & 7; \
+        bits -= bits & 7; \
+    } while (0)
+
+/*
+   inflate() uses a state machine to process as much input data and generate as
+   much output data as possible before returning.  The state machine is
+   structured roughly as follows:
+
+    for (;;) switch (state) {
+    ...
+    case STATEn:
+        if (not enough input data or output space to make progress)
+            return;
+        ... make progress ...
+        state = STATEm;
+        break;
+    ...
+    }
+
+   so when inflate() is called again, the same case is attempted again, and
+   if the appropriate resources are provided, the machine proceeds to the
+   next state.  The NEEDBITS() macro is usually the way the state evaluates
+   whether it can proceed or should return.  NEEDBITS() does the return if
+   the requested bits are not available.  The typical use of the BITS macros
+   is:
+
+        NEEDBITS(n);
+        ... do something with BITS(n) ...
+        DROPBITS(n);
+
+   where NEEDBITS(n) either returns from inflate() if there isn't enough
+   input left to load n bits into the accumulator, or it continues.  BITS(n)
+   gives the low n bits in the accumulator.  When done, DROPBITS(n) drops
+   the low n bits off the accumulator.  INITBITS() clears the accumulator
+   and sets the number of available bits to zero.  BYTEBITS() discards just
+   enough bits to put the accumulator on a byte boundary.  After BYTEBITS()
+   and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+
+   NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+   if there is no input available.  The decoding of variable length codes uses
+   PULLBYTE() directly in order to pull just enough bytes to decode the next
+   code, and no more.
+
+   Some states loop until they get enough input, making sure that enough
+   state information is maintained to continue the loop where it left off
+   if NEEDBITS() returns in the loop.  For example, want, need, and keep
+   would all have to actually be part of the saved state in case NEEDBITS()
+   returns:
+
+    case STATEw:
+        while (want < need) {
+            NEEDBITS(n);
+            keep[want++] = BITS(n);
+            DROPBITS(n);
+        }
+        state = STATEx;
+    case STATEx:
+
+   As shown above, if the next state is also the next case, then the break
+   is omitted.
+
+   A state may also return if there is not enough output space available to
+   complete that state.  Those states are copying stored data, writing a
+   literal byte, and copying a matching string.
+
+   When returning, a "goto inf_leave" is used to update the total counters,
+   update the check value, and determine whether any progress has been made
+   during that inflate() call in order to return the proper return code.
+   Progress is defined as a change in either strm->avail_in or strm->avail_out.
+   When there is a window, goto inf_leave will update the window with the last
+   output written.  If a goto inf_leave occurs in the middle of decompression
+   and there is no window currently, goto inf_leave will create one and copy
+   output to the window for the next call of inflate().
+
+   In this implementation, the flush parameter of inflate() only affects the
+   return code (per zlib.h).  inflate() always writes as much as possible to
+   strm->next_out, given the space available and the provided input--the effect
+   documented in zlib.h of Z_SYNC_FLUSH.  Furthermore, inflate() always defers
+   the allocation of and copying into a sliding window until necessary, which
+   provides the effect documented in zlib.h for Z_FINISH when the entire input
+   stream available.  So the only thing the flush parameter actually does is:
+   when flush is set to Z_FINISH, inflate() cannot return Z_OK.  Instead it
+   will return Z_BUF_ERROR if it has not reached the end of the stream.
+ */
+
+int ZEXPORT inflate(strm, flush)
+z_streamp strm;
+int flush;
+{
+    struct inflate_state FAR *state;
+    z_const unsigned char FAR *next;    /* next input */
+    unsigned char FAR *put;     /* next output */
+    unsigned have, left;        /* available input and output */
+    unsigned long hold;         /* bit buffer */
+    unsigned bits;              /* bits in bit buffer */
+    unsigned in, out;           /* save starting available input and output */
+    unsigned copy;              /* number of stored or match bytes to copy */
+    unsigned char FAR *from;    /* where to copy match bytes from */
+    code here;                  /* current decoding table entry */
+    code last;                  /* parent table entry */
+    unsigned len;               /* length to copy for repeats, bits to drop */
+    int ret;                    /* return code */
+#ifdef GUNZIP
+    unsigned char hbuf[4];      /* buffer for gzip header crc calculation */
+#endif
+    static const unsigned short order[19] = /* permutation of code lengths */
+        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+    if (inflateStateCheck(strm) || strm->next_out == Z_NULL ||
+        (strm->next_in == Z_NULL && strm->avail_in != 0))
+        return Z_STREAM_ERROR;
+
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->mode == TYPE) state->mode = TYPEDO;      /* skip check */
+    LOAD();
+    in = have;
+    out = left;
+    ret = Z_OK;
+    for (;;)
+        switch (state->mode) {
+        case HEAD:
+            if (state->wrap == 0) {
+                state->mode = TYPEDO;
+                break;
+            }
+            NEEDBITS(16);
+#ifdef GUNZIP
+            if ((state->wrap & 2) && hold == 0x8b1f) {  /* gzip header */
+                if (state->wbits == 0)
+                    state->wbits = 15;
+                state->check = crc32(0L, Z_NULL, 0);
+                CRC2(state->check, hold);
+                INITBITS();
+                state->mode = FLAGS;
+                break;
+            }
+            state->flags = 0;           /* expect zlib header */
+            if (state->head != Z_NULL)
+                state->head->done = -1;
+            if (!(state->wrap & 1) ||   /* check if zlib header allowed */
+#else
+            if (
+#endif
+                ((BITS(8) << 8) + (hold >> 8)) % 31) {
+                strm->msg = (char *)"incorrect header check";
+                state->mode = BAD;
+                break;
+            }
+            if (BITS(4) != Z_DEFLATED) {
+                strm->msg = (char *)"unknown compression method";
+                state->mode = BAD;
+                break;
+            }
+            DROPBITS(4);
+            len = BITS(4) + 8;
+            if (state->wbits == 0)
+                state->wbits = len;
+            if (len > 15 || len > state->wbits) {
+                strm->msg = (char *)"invalid window size";
+                state->mode = BAD;
+                break;
+            }
+            state->dmax = 1U << len;
+            Tracev((stderr, "inflate:   zlib header ok\n"));
+            strm->adler = state->check = adler32(0L, Z_NULL, 0);
+            state->mode = hold & 0x200 ? DICTID : TYPE;
+            INITBITS();
+            break;
+#ifdef GUNZIP
+        case FLAGS:
+            NEEDBITS(16);
+            state->flags = (int)(hold);
+            if ((state->flags & 0xff) != Z_DEFLATED) {
+                strm->msg = (char *)"unknown compression method";
+                state->mode = BAD;
+                break;
+            }
+            if (state->flags & 0xe000) {
+                strm->msg = (char *)"unknown header flags set";
+                state->mode = BAD;
+                break;
+            }
+            if (state->head != Z_NULL)
+                state->head->text = (int)((hold >> 8) & 1);
+            if ((state->flags & 0x0200) && (state->wrap & 4))
+                CRC2(state->check, hold);
+            INITBITS();
+            state->mode = TIME;
+        case TIME:
+            NEEDBITS(32);
+            if (state->head != Z_NULL)
+                state->head->time = hold;
+            if ((state->flags & 0x0200) && (state->wrap & 4))
+                CRC4(state->check, hold);
+            INITBITS();
+            state->mode = OS;
+        case OS:
+            NEEDBITS(16);
+            if (state->head != Z_NULL) {
+                state->head->xflags = (int)(hold & 0xff);
+                state->head->os = (int)(hold >> 8);
+            }
+            if ((state->flags & 0x0200) && (state->wrap & 4))
+                CRC2(state->check, hold);
+            INITBITS();
+            state->mode = EXLEN;
+        case EXLEN:
+            if (state->flags & 0x0400) {
+                NEEDBITS(16);
+                state->length = (unsigned)(hold);
+                if (state->head != Z_NULL)
+                    state->head->extra_len = (unsigned)hold;
+                if ((state->flags & 0x0200) && (state->wrap & 4))
+                    CRC2(state->check, hold);
+                INITBITS();
+            }
+            else if (state->head != Z_NULL)
+                state->head->extra = Z_NULL;
+            state->mode = EXTRA;
+        case EXTRA:
+            if (state->flags & 0x0400) {
+                copy = state->length;
+                if (copy > have) copy = have;
+                if (copy) {
+                    if (state->head != Z_NULL &&
+                        state->head->extra != Z_NULL) {
+                        len = state->head->extra_len - state->length;
+                        zmemcpy(state->head->extra + len, next,
+                                len + copy > state->head->extra_max ?
+                                state->head->extra_max - len : copy);
+                    }
+                    if ((state->flags & 0x0200) && (state->wrap & 4))
+                        state->check = crc32(state->check, next, copy);
+                    have -= copy;
+                    next += copy;
+                    state->length -= copy;
+                }
+                if (state->length) goto inf_leave;
+            }
+            state->length = 0;
+            state->mode = NAME;
+        case NAME:
+            if (state->flags & 0x0800) {
+                if (have == 0) goto inf_leave;
+                copy = 0;
+                do {
+                    len = (unsigned)(next[copy++]);
+                    if (state->head != Z_NULL &&
+                            state->head->name != Z_NULL &&
+                            state->length < state->head->name_max)
+                        state->head->name[state->length++] = (Bytef)len;
+                } while (len && copy < have);
+                if ((state->flags & 0x0200) && (state->wrap & 4))
+                    state->check = crc32(state->check, next, copy);
+                have -= copy;
+                next += copy;
+                if (len) goto inf_leave;
+            }
+            else if (state->head != Z_NULL)
+                state->head->name = Z_NULL;
+            state->length = 0;
+            state->mode = COMMENT;
+        case COMMENT:
+            if (state->flags & 0x1000) {
+                if (have == 0) goto inf_leave;
+                copy = 0;
+                do {
+                    len = (unsigned)(next[copy++]);
+                    if (state->head != Z_NULL &&
+                            state->head->comment != Z_NULL &&
+                            state->length < state->head->comm_max)
+                        state->head->comment[state->length++] = (Bytef)len;
+                } while (len && copy < have);
+                if ((state->flags & 0x0200) && (state->wrap & 4))
+                    state->check = crc32(state->check, next, copy);
+                have -= copy;
+                next += copy;
+                if (len) goto inf_leave;
+            }
+            else if (state->head != Z_NULL)
+                state->head->comment = Z_NULL;
+            state->mode = HCRC;
+        case HCRC:
+            if (state->flags & 0x0200) {
+                NEEDBITS(16);
+                if ((state->wrap & 4) && hold != (state->check & 0xffff)) {
+                    strm->msg = (char *)"header crc mismatch";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+            }
+            if (state->head != Z_NULL) {
+                state->head->hcrc = (int)((state->flags >> 9) & 1);
+                state->head->done = 1;
+            }
+            strm->adler = state->check = crc32(0L, Z_NULL, 0);
+            state->mode = TYPE;
+            break;
+#endif
+        case DICTID:
+            NEEDBITS(32);
+            strm->adler = state->check = ZSWAP32(hold);
+            INITBITS();
+            state->mode = DICT;
+        case DICT:
+            if (state->havedict == 0) {
+                RESTORE();
+                return Z_NEED_DICT;
+            }
+            strm->adler = state->check = adler32(0L, Z_NULL, 0);
+            state->mode = TYPE;
+        case TYPE:
+            if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
+        case TYPEDO:
+            if (state->last) {
+                BYTEBITS();
+                state->mode = CHECK;
+                break;
+            }
+            NEEDBITS(3);
+            state->last = BITS(1);
+            DROPBITS(1);
+            switch (BITS(2)) {
+            case 0:                             /* stored block */
+                Tracev((stderr, "inflate:     stored block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = STORED;
+                break;
+            case 1:                             /* fixed block */
+                fixedtables(state);
+                Tracev((stderr, "inflate:     fixed codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = LEN_;             /* decode codes */
+                if (flush == Z_TREES) {
+                    DROPBITS(2);
+                    goto inf_leave;
+                }
+                break;
+            case 2:                             /* dynamic block */
+                Tracev((stderr, "inflate:     dynamic codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = TABLE;
+                break;
+            case 3:
+                strm->msg = (char *)"invalid block type";
+                state->mode = BAD;
+            }
+            DROPBITS(2);
+            break;
+        case STORED:
+            BYTEBITS();                         /* go to byte boundary */
+            NEEDBITS(32);
+            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+                strm->msg = (char *)"invalid stored block lengths";
+                state->mode = BAD;
+                break;
+            }
+            state->length = (unsigned)hold & 0xffff;
+            Tracev((stderr, "inflate:       stored length %u\n",
+                    state->length));
+            INITBITS();
+            state->mode = COPY_;
+            if (flush == Z_TREES) goto inf_leave;
+        case COPY_:
+            state->mode = COPY;
+        case COPY:
+            copy = state->length;
+            if (copy) {
+                if (copy > have) copy = have;
+                if (copy > left) copy = left;
+                if (copy == 0) goto inf_leave;
+                zmemcpy(put, next, copy);
+                have -= copy;
+                next += copy;
+                left -= copy;
+                put += copy;
+                state->length -= copy;
+                break;
+            }
+            Tracev((stderr, "inflate:       stored end\n"));
+            state->mode = TYPE;
+            break;
+        case TABLE:
+            NEEDBITS(14);
+            state->nlen = BITS(5) + 257;
+            DROPBITS(5);
+            state->ndist = BITS(5) + 1;
+            DROPBITS(5);
+            state->ncode = BITS(4) + 4;
+            DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+            if (state->nlen > 286 || state->ndist > 30) {
+                strm->msg = (char *)"too many length or distance symbols";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            Tracev((stderr, "inflate:       table sizes ok\n"));
+            state->have = 0;
+            state->mode = LENLENS;
+        case LENLENS:
+            while (state->have < state->ncode) {
+                NEEDBITS(3);
+                state->lens[order[state->have++]] = (unsigned short)BITS(3);
+                DROPBITS(3);
+            }
+            while (state->have < 19)
+                state->lens[order[state->have++]] = 0;
+            state->next = state->codes;
+            state->lencode = (const code FAR *)(state->next);
+            state->lenbits = 7;
+            ret = inflate_table(CODES, state->lens, 19, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid code lengths set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       code lengths ok\n"));
+            state->have = 0;
+            state->mode = CODELENS;
+        case CODELENS:
+            while (state->have < state->nlen + state->ndist) {
+                for (;;) {
+                    here = state->lencode[BITS(state->lenbits)];
+                    if ((unsigned)(here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                if (here.val < 16) {
+                    DROPBITS(here.bits);
+                    state->lens[state->have++] = here.val;
+                }
+                else {
+                    if (here.val == 16) {
+                        NEEDBITS(here.bits + 2);
+                        DROPBITS(here.bits);
+                        if (state->have == 0) {
+                            strm->msg = (char *)"invalid bit length repeat";
+                            state->mode = BAD;
+                            break;
+                        }
+                        len = state->lens[state->have - 1];
+                        copy = 3 + BITS(2);
+                        DROPBITS(2);
+                    }
+                    else if (here.val == 17) {
+                        NEEDBITS(here.bits + 3);
+                        DROPBITS(here.bits);
+                        len = 0;
+                        copy = 3 + BITS(3);
+                        DROPBITS(3);
+                    }
+                    else {
+                        NEEDBITS(here.bits + 7);
+                        DROPBITS(here.bits);
+                        len = 0;
+                        copy = 11 + BITS(7);
+                        DROPBITS(7);
+                    }
+                    if (state->have + copy > state->nlen + state->ndist) {
+                        strm->msg = (char *)"invalid bit length repeat";
+                        state->mode = BAD;
+                        break;
+                    }
+                    while (copy--)
+                        state->lens[state->have++] = (unsigned short)len;
+                }
+            }
+
+            /* handle error breaks in while */
+            if (state->mode == BAD) break;
+
+            /* check for end-of-block code (better have one) */
+            if (state->lens[256] == 0) {
+                strm->msg = (char *)"invalid code -- missing end-of-block";
+                state->mode = BAD;
+                break;
+            }
+
+            /* build code tables -- note: do not change the lenbits or distbits
+               values here (9 and 6) without reading the comments in inftrees.h
+               concerning the ENOUGH constants, which depend on those values */
+            state->next = state->codes;
+            state->lencode = (const code FAR *)(state->next);
+            state->lenbits = 9;
+            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid literal/lengths set";
+                state->mode = BAD;
+                break;
+            }
+            state->distcode = (const code FAR *)(state->next);
+            state->distbits = 6;
+            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+                            &(state->next), &(state->distbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid distances set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       codes ok\n"));
+            state->mode = LEN_;
+            if (flush == Z_TREES) goto inf_leave;
+        case LEN_:
+            state->mode = LEN;
+        case LEN:
+            if (have >= 6 && left >= 258) {
+                RESTORE();
+                inflate_fast(strm, out);
+                LOAD();
+                if (state->mode == TYPE)
+                    state->back = -1;
+                break;
+            }
+            state->back = 0;
+            for (;;) {
+                here = state->lencode[BITS(state->lenbits)];
+                if ((unsigned)(here.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if (here.op && (here.op & 0xf0) == 0) {
+                last = here;
+                for (;;) {
+                    here = state->lencode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+                state->back += last.bits;
+            }
+            DROPBITS(here.bits);
+            state->back += here.bits;
+            state->length = (unsigned)here.val;
+            if ((int)(here.op) == 0) {
+                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+                        "inflate:         literal '%c'\n" :
+                        "inflate:         literal 0x%02x\n", here.val));
+                state->mode = LIT;
+                break;
+            }
+            if (here.op & 32) {
+                Tracevv((stderr, "inflate:         end of block\n"));
+                state->back = -1;
+                state->mode = TYPE;
+                break;
+            }
+            if (here.op & 64) {
+                strm->msg = (char *)"invalid literal/length code";
+                state->mode = BAD;
+                break;
+            }
+            state->extra = (unsigned)(here.op) & 15;
+            state->mode = LENEXT;
+        case LENEXT:
+            if (state->extra) {
+                NEEDBITS(state->extra);
+                state->length += BITS(state->extra);
+                DROPBITS(state->extra);
+                state->back += state->extra;
+            }
+            Tracevv((stderr, "inflate:         length %u\n", state->length));
+            state->was = state->length;
+            state->mode = DIST;
+        case DIST:
+            for (;;) {
+                here = state->distcode[BITS(state->distbits)];
+                if ((unsigned)(here.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if ((here.op & 0xf0) == 0) {
+                last = here;
+                for (;;) {
+                    here = state->distcode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+                state->back += last.bits;
+            }
+            DROPBITS(here.bits);
+            state->back += here.bits;
+            if (here.op & 64) {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+            state->offset = (unsigned)here.val;
+            state->extra = (unsigned)(here.op) & 15;
+            state->mode = DISTEXT;
+        case DISTEXT:
+            if (state->extra) {
+                NEEDBITS(state->extra);
+                state->offset += BITS(state->extra);
+                DROPBITS(state->extra);
+                state->back += state->extra;
+            }
+#ifdef INFLATE_STRICT
+            if (state->offset > state->dmax) {
+                strm->msg = (char *)"invalid distance too far back";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
+            state->mode = MATCH;
+        case MATCH:
+            if (left == 0) goto inf_leave;
+            copy = out - left;
+            if (state->offset > copy) {         /* copy from window */
+                copy = state->offset - copy;
+                if (copy > state->whave) {
+                    if (state->sane) {
+                        strm->msg = (char *)"invalid distance too far back";
+                        state->mode = BAD;
+                        break;
+                    }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+                    Trace((stderr, "inflate.c too far\n"));
+                    copy -= state->whave;
+                    if (copy > state->length) copy = state->length;
+                    if (copy > left) copy = left;
+                    left -= copy;
+                    state->length -= copy;
+                    do {
+                        *put++ = 0;
+                    } while (--copy);
+                    if (state->length == 0) state->mode = LEN;
+                    break;
+#endif
+                }
+                if (copy > state->wnext) {
+                    copy -= state->wnext;
+                    from = state->window + (state->wsize - copy);
+                }
+                else
+                    from = state->window + (state->wnext - copy);
+                if (copy > state->length) copy = state->length;
+                if (copy > left) copy = left;
+                put = chunkcopy_safe(put, from, copy, put + left);
+            }
+            else {                              /* copy from output */
+                copy = state->length;
+                if (copy > left) copy = left;
+                put = chunkcopy_lapped_safe(put, state->offset, copy, put + left);
+            }
+            left -= copy;
+            state->length -= copy;
+            if (state->length == 0) state->mode = LEN;
+            break;
+        case LIT:
+            if (left == 0) goto inf_leave;
+            *put++ = (unsigned char)(state->length);
+            left--;
+            state->mode = LEN;
+            break;
+        case CHECK:
+            if (state->wrap) {
+                NEEDBITS(32);
+                out -= left;
+                strm->total_out += out;
+                state->total += out;
+                if ((state->wrap & 4) && out)
+                    strm->adler = state->check =
+                        UPDATE(state->check, put - out, out);
+                out = left;
+                if ((state->wrap & 4) && (
+#ifdef GUNZIP
+                     state->flags ? hold :
+#endif
+                     ZSWAP32(hold)) != state->check) {
+                    strm->msg = (char *)"incorrect data check";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+                Tracev((stderr, "inflate:   check matches trailer\n"));
+            }
+#ifdef GUNZIP
+            state->mode = LENGTH;
+        case LENGTH:
+            if (state->wrap && state->flags) {
+                NEEDBITS(32);
+                if (hold != (state->total & 0xffffffffUL)) {
+                    strm->msg = (char *)"incorrect length check";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+                Tracev((stderr, "inflate:   length matches trailer\n"));
+            }
+#endif
+            state->mode = DONE;
+        case DONE:
+            ret = Z_STREAM_END;
+            goto inf_leave;
+        case BAD:
+            ret = Z_DATA_ERROR;
+            goto inf_leave;
+        case MEM:
+            return Z_MEM_ERROR;
+        case SYNC:
+        default:
+            return Z_STREAM_ERROR;
+        }
+
+    /*
+       Return from inflate(), updating the total counts and the check value.
+       If there was no progress during the inflate() call, return a buffer
+       error.  Call updatewindow() to create and/or update the window state.
+       Note: a memory error from inflate() is non-recoverable.
+     */
+  inf_leave:
+    RESTORE();
+    if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
+            (state->mode < CHECK || flush != Z_FINISH)))
+        if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {
+            state->mode = MEM;
+            return Z_MEM_ERROR;
+        }
+    in -= strm->avail_in;
+    out -= strm->avail_out;
+    strm->total_in += in;
+    strm->total_out += out;
+    state->total += out;
+    if ((state->wrap & 4) && out)
+        strm->adler = state->check =
+            UPDATE(state->check, strm->next_out - out, out);
+    strm->data_type = (int)state->bits + (state->last ? 64 : 0) +
+                      (state->mode == TYPE ? 128 : 0) +
+                      (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
+    if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+        ret = Z_BUF_ERROR;
+    return ret;
+}
+
+int ZEXPORT inflateEnd(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+    if (inflateStateCheck(strm))
+        return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->window != Z_NULL) ZFREE(strm, state->window);
+    ZFREE(strm, strm->state);
+    strm->state = Z_NULL;
+    Tracev((stderr, "inflate: end\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength)
+z_streamp strm;
+Bytef *dictionary;
+uInt *dictLength;
+{
+    struct inflate_state FAR *state;
+
+    /* check state */
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* copy dictionary */
+    if (state->whave && dictionary != Z_NULL) {
+        zmemcpy(dictionary, state->window + state->wnext,
+                state->whave - state->wnext);
+        zmemcpy(dictionary + state->whave - state->wnext,
+                state->window, state->wnext);
+    }
+    if (dictLength != Z_NULL)
+        *dictLength = state->whave;
+    return Z_OK;
+}
+
+int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
+z_streamp strm;
+const Bytef *dictionary;
+uInt dictLength;
+{
+    struct inflate_state FAR *state;
+    unsigned long dictid;
+    int ret;
+
+    /* check state */
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->wrap != 0 && state->mode != DICT)
+        return Z_STREAM_ERROR;
+
+    /* check for correct dictionary identifier */
+    if (state->mode == DICT) {
+        dictid = adler32(0L, Z_NULL, 0);
+        dictid = adler32(dictid, dictionary, dictLength);
+        if (dictid != state->check)
+            return Z_DATA_ERROR;
+    }
+
+    /* copy dictionary to window using updatewindow(), which will amend the
+       existing dictionary if appropriate */
+    ret = updatewindow(strm, dictionary + dictLength, dictLength);
+    if (ret) {
+        state->mode = MEM;
+        return Z_MEM_ERROR;
+    }
+    state->havedict = 1;
+    Tracev((stderr, "inflate:   dictionary set\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflateGetHeader(strm, head)
+z_streamp strm;
+gz_headerp head;
+{
+    struct inflate_state FAR *state;
+
+    /* check state */
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
+
+    /* save header structure */
+    state->head = head;
+    head->done = 0;
+    return Z_OK;
+}
+
+/*
+   Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff.  Return when found
+   or when out of input.  When called, *have is the number of pattern bytes
+   found in order so far, in 0..3.  On return *have is updated to the new
+   state.  If on return *have equals four, then the pattern was found and the
+   return value is how many bytes were read including the last byte of the
+   pattern.  If *have is less than four, then the pattern has not been found
+   yet and the return value is len.  In the latter case, syncsearch() can be
+   called again with more data and the *have state.  *have is initialized to
+   zero for the first call.
+ */
+local unsigned syncsearch(have, buf, len)
+unsigned FAR *have;
+const unsigned char FAR *buf;
+unsigned len;
+{
+    unsigned got;
+    unsigned next;
+
+    got = *have;
+    next = 0;
+    while (next < len && got < 4) {
+        if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
+            got++;
+        else if (buf[next])
+            got = 0;
+        else
+            got = 4 - got;
+        next++;
+    }
+    *have = got;
+    return next;
+}
+
+int ZEXPORT inflateSync(strm)
+z_streamp strm;
+{
+    unsigned len;               /* number of bytes to look at or looked at */
+    unsigned long in, out;      /* temporary to save total_in and total_out */
+    unsigned char buf[4];       /* to restore bit buffer to byte string */
+    struct inflate_state FAR *state;
+
+    /* check parameters */
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
+
+    /* if first time, start search in bit buffer */
+    if (state->mode != SYNC) {
+        state->mode = SYNC;
+        state->hold <<= state->bits & 7;
+        state->bits -= state->bits & 7;
+        len = 0;
+        while (state->bits >= 8) {
+            buf[len++] = (unsigned char)(state->hold);
+            state->hold >>= 8;
+            state->bits -= 8;
+        }
+        state->have = 0;
+        syncsearch(&(state->have), buf, len);
+    }
+
+    /* search available input */
+    len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
+    strm->avail_in -= len;
+    strm->next_in += len;
+    strm->total_in += len;
+
+    /* return no joy or set up to restart inflate() on a new block */
+    if (state->have != 4) return Z_DATA_ERROR;
+    in = strm->total_in;  out = strm->total_out;
+    inflateReset(strm);
+    strm->total_in = in;  strm->total_out = out;
+    state->mode = TYPE;
+    return Z_OK;
+}
+
+/*
+   Returns true if inflate is currently at the end of a block generated by
+   Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+   implementation to provide an additional safety check. PPP uses
+   Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
+   block. When decompressing, PPP checks that at the end of input packet,
+   inflate is waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    return state->mode == STORED && state->bits == 0;
+}
+
+int ZEXPORT inflateCopy(dest, source)
+z_streamp dest;
+z_streamp source;
+{
+    struct inflate_state FAR *state;
+    struct inflate_state FAR *copy;
+    unsigned char FAR *window;
+    unsigned wsize;
+
+    /* check input */
+    if (inflateStateCheck(source) || dest == Z_NULL)
+        return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)source->state;
+
+    /* allocate space */
+    copy = (struct inflate_state FAR *)
+           ZALLOC(source, 1, sizeof(struct inflate_state));
+    if (copy == Z_NULL) return Z_MEM_ERROR;
+    window = Z_NULL;
+    if (state->window != Z_NULL) {
+        window = (unsigned char FAR *)
+                 ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
+        if (window == Z_NULL) {
+            ZFREE(source, copy);
+            return Z_MEM_ERROR;
+        }
+    }
+
+    /* copy state */
+    zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
+    zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
+    copy->strm = dest;
+    if (state->lencode >= state->codes &&
+        state->lencode <= state->codes + ENOUGH - 1) {
+        copy->lencode = copy->codes + (state->lencode - state->codes);
+        copy->distcode = copy->codes + (state->distcode - state->codes);
+    }
+    copy->next = copy->codes + (state->next - state->codes);
+    if (window != Z_NULL) {
+        wsize = 1U << state->wbits;
+        zmemcpy(window, state->window, wsize);
+    }
+    copy->window = window;
+    dest->state = (struct internal_state FAR *)copy;
+    return Z_OK;
+}
+
+int ZEXPORT inflateUndermine(strm, subvert)
+z_streamp strm;
+int subvert;
+{
+    struct inflate_state FAR *state;
+
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+    state->sane = !subvert;
+    return Z_OK;
+#else
+    (void)subvert;
+    state->sane = 1;
+    return Z_DATA_ERROR;
+#endif
+}
+
+int ZEXPORT inflateValidate(strm, check)
+z_streamp strm;
+int check;
+{
+    struct inflate_state FAR *state;
+
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (check)
+        state->wrap |= 4;
+    else
+        state->wrap &= ~4;
+    return Z_OK;
+}
+
+long ZEXPORT inflateMark(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (inflateStateCheck(strm))
+        return -(1L << 16);
+    state = (struct inflate_state FAR *)strm->state;
+    return (long)(((unsigned long)((long)state->back)) << 16) +
+        (state->mode == COPY ? state->length :
+            (state->mode == MATCH ? state->was - state->length : 0));
+}
+
+unsigned long ZEXPORT inflateCodesUsed(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+    if (inflateStateCheck(strm)) return (unsigned long)-1;
+    state = (struct inflate_state FAR *)strm->state;
+    return (unsigned long)(state->next - state->codes);
+}
diff --git a/third_party/zlib/inflate.c b/third_party/zlib/inflate.c
index bec9497..e84be46 100644
--- a/third_party/zlib/inflate.c
+++ b/third_party/zlib/inflate.c
@@ -84,6 +84,7 @@
 #include "inftrees.h"
 #include "inflate.h"
 #include "inffast.h"
+#include "x86.h"
 
 #ifdef MAKEFIXED
 #  ifndef BUILDFIXED
@@ -201,6 +202,8 @@
     int ret;
     struct inflate_state FAR *state;
 
+    x86_check_features();
+
     if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
         stream_size != (int)(sizeof(z_stream)))
         return Z_VERSION_ERROR;
@@ -228,7 +231,7 @@
     state->strm = strm;
     state->window = Z_NULL;
     state->mode = HEAD;     /* to pass state test in inflateReset2() */
-    state->check = adler32(0L, Z_NULL, 0);
+    state->check = 1L;      /* 1L is the result of adler32() zero length data */
     ret = inflateReset2(strm, windowBits);
     if (ret != Z_OK) {
         ZFREE(strm, state);
diff --git a/third_party/zlib/names.h b/third_party/zlib/names.h
index 3436baa..cd98ec9 100644
--- a/third_party/zlib/names.h
+++ b/third_party/zlib/names.h
@@ -162,6 +162,13 @@
 #define fill_window_sse Cr_z_fill_window_sse
 #define read_buf Cr_z_read_buf
 #define x86_check_features Cr_z_x86_check_features
+/* FIXME: x86_cpu_enable_ssse3 wasn't part of the simd.patch */
+#define x86_cpu_enable_ssse3 Cr_z_x86_cpu_enable_ssse3
 #define x86_cpu_enable_simd Cr_z_x86_cpu_enable_simd
 
+#if defined(ADLER32_SIMD_SSSE3) || defined(ADLER32_SIMD_NEON)
+/* Symbols added by adler_simd.c, see also the FIXME above */
+#define adler32_simd_ Cr_z_adler32_simd_
+#endif
+
 #endif  /* THIRD_PARTY_ZLIB_NAMES_H_ */
diff --git a/third_party/zlib/patches/0002-uninitializedcheck.patch b/third_party/zlib/patches/0002-uninitializedcheck.patch
index 0713c00..7c49783 100644
--- a/third_party/zlib/patches/0002-uninitializedcheck.patch
+++ b/third_party/zlib/patches/0002-uninitializedcheck.patch
@@ -1,12 +1,27 @@
-diff --git a/inflate.c b/inflate.c
-index ac333e8c2eda..69b769a871b8 100644
+From 1a03e7aec95d89c659fd91f195b99893b6458cd7 Mon Sep 17 00:00:00 2001
+From: Adenilson Cavalcanti <adenilson.cavalcanti@arm.com>
+Date: Wed, 27 Sep 2017 13:59:04 -0700
+Subject: [PATCH] Zlib patch: prevent uninitialized use of state->check
+
+No need to call the Adler32 checksum function, just set
+the struct field to the expected value.
+
+Upstream bug: madler/zlib#245
+---
+ third_party/zlib/inflate.c                             |  2 +-
+ 1 files changed, 1 insertion(+), 1 deletions(-)
+ delete mode 100644 third_party/zlib/patches/0002-uninitializedcheck.patch
+
+diff --git a/third_party/zlib/inflate.c b/third_party/zlib/inflate.c
+index bec9497..5c40cf1 100644
 --- a/third_party/zlib/inflate.c
 +++ b/third_party/zlib/inflate.c
-@@ -228,6 +228,7 @@ int stream_size;
+@@ -228,7 +228,7 @@ int stream_size;
      state->strm = strm;
      state->window = Z_NULL;
      state->mode = HEAD;     /* to pass state test in inflateReset2() */
-+    state->check = adler32(0L, Z_NULL, 0);
+-    state->check = adler32(0L, Z_NULL, 0);
++    state->check = 1L;      /* 1L is the result of adler32() zero length data */
      ret = inflateReset2(strm, windowBits);
      if (ret != Z_OK) {
          ZFREE(strm, state);
diff --git a/third_party/zlib/patches/0004-neon-inffast.patch b/third_party/zlib/patches/0004-neon-inffast.patch
new file mode 100644
index 0000000..93144c8e
--- /dev/null
+++ b/third_party/zlib/patches/0004-neon-inffast.patch
@@ -0,0 +1,2259 @@
+From a3719bd5f937566faab554c9596e7984a37ec5c8 Mon Sep 17 00:00:00 2001
+From: Adenilson Cavalcanti <adenilson.cavalcanti@arm.com>
+Date: Thu, 28 Sep 2017 12:31:26 -0700
+Subject: [PATCH] zlib: inflate using wider loads and stores
+
+In inflate_fast() the output pointer always has plenty of room to write.
+This means that so long as the target is capable, wide un-aligned
+loads and stores can be used to transfer several bytes at once.
+
+When the reference distance is too short simply unroll the data a
+little to increase the distance. Patch by Simon Hosie.
+
+PNG decoding performance gains should be around 30-33%.
+
+This also includes the fix reported in madler/zlib#245.
+---
+ third_party/zlib/BUILD.gn                |   19 +
+ third_party/zlib/contrib/arm/chunkcopy.h |  297 ++++++
+ third_party/zlib/contrib/arm/inffast.c   |  307 ++++++
+ third_party/zlib/contrib/arm/inflate.c   | 1572 ++++++++++++++++++++++++++++++
+ 4 files changed, 2195 insertions(+)
+ create mode 100644 third_party/zlib/contrib/arm/chunkcopy.h
+ create mode 100644 third_party/zlib/contrib/arm/inffast.c
+ create mode 100644 third_party/zlib/contrib/arm/inflate.c
+
+diff --git a/third_party/zlib/BUILD.gn b/third_party/zlib/BUILD.gn
+index 4b4db15..027a38c 100644
+--- a/third_party/zlib/BUILD.gn
++++ b/third_party/zlib/BUILD.gn
+@@ -2,6 +2,10 @@
+ # Use of this source code is governed by a BSD-style license that can be
+ # found in the LICENSE file.
+ 
++if (current_cpu == "arm" || current_cpu == "arm64") {
++  import("//build/config/arm.gni")
++}
++
+ config("zlib_config") {
+   include_dirs = [ "." ]
+ }
+@@ -71,6 +75,21 @@ static_library("zlib") {
+     "zutil.h",
+   ]
+ 
++  if (current_cpu == "arm" || current_cpu == "arm64") {
++    if (arm_use_neon) {
++      # TODO: handle InflateBack case, see crbug.com/769880.
++      sources -= [
++        "inffast.c",
++        "inflate.c",
++      ]
++      sources += [
++        "contrib/arm/chunkcopy.h",
++        "contrib/arm/inffast.c",
++        "contrib/arm/inflate.c",
++      ]
++    }
++  }
++
+   if (!is_ios && (current_cpu == "x86" || current_cpu == "x64")) {
+     sources += [ "x86.c" ]
+   }
+diff --git a/third_party/zlib/contrib/arm/chunkcopy.h b/third_party/zlib/contrib/arm/chunkcopy.h
+new file mode 100644
+index 0000000..bc8a77d
+--- /dev/null
++++ b/third_party/zlib/contrib/arm/chunkcopy.h
+@@ -0,0 +1,297 @@
++/* chunkcopy.h -- fast copies and sets
++ * Copyright (C) 2017 ARM, Inc.
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++#ifndef CHUNKCOPY_H
++#define CHUNKCOPY_H
++
++#include <arm_neon.h>
++#include "zutil.h"
++
++#if __STDC_VERSION__ >= 199901L
++#define Z_RESTRICT restrict
++#else
++#define Z_RESTRICT
++#endif
++
++typedef uint8x16_t chunkcopy_chunk_t;
++#define CHUNKCOPY_CHUNK_SIZE sizeof(chunkcopy_chunk_t)
++
++/*
++   Ask the compiler to perform a wide, unaligned load with an machine
++   instruction appropriate for the chunkcopy_chunk_t type.
++ */
++static inline chunkcopy_chunk_t loadchunk(const unsigned char FAR* s) {
++  chunkcopy_chunk_t c;
++  __builtin_memcpy(&c, s, sizeof(c));
++  return c;
++}
++
++/*
++   Ask the compiler to perform a wide, unaligned store with an machine
++   instruction appropriate for the chunkcopy_chunk_t type.
++ */
++static inline void storechunk(unsigned char FAR* d, chunkcopy_chunk_t c) {
++  __builtin_memcpy(d, &c, sizeof(c));
++}
++
++/*
++   Perform a memcpy-like operation, but assume that length is non-zero and that
++   it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE bytes of output even if
++   the length is shorter than this.
++
++   It also guarantees that it will properly unroll the data if the distance
++   between `out` and `from` is at least CHUNKCOPY_CHUNK_SIZE, which we rely on
++   in chunkcopy_relaxed().
++
++   Aside from better memory bus utilisation, this means that short copies
++   (CHUNKCOPY_CHUNK_SIZE bytes or fewer) will fall straight through the loop
++   without iteration, which will hopefully make the branch prediction more
++   reliable.
++ */
++static inline unsigned char FAR* chunkcopy_core(unsigned char FAR* out,
++                                                const unsigned char FAR* from,
++                                                unsigned len) {
++  int bump = (--len % CHUNKCOPY_CHUNK_SIZE) + 1;
++  storechunk(out, loadchunk(from));
++  out += bump;
++  from += bump;
++  len /= CHUNKCOPY_CHUNK_SIZE;
++  while (len-- > 0) {
++    storechunk(out, loadchunk(from));
++    out += CHUNKCOPY_CHUNK_SIZE;
++    from += CHUNKCOPY_CHUNK_SIZE;
++  }
++  return out;
++}
++
++/*
++   Like chunkcopy_core, but avoid writing beyond of legal output.
++
++   Accepts an additional pointer to the end of safe output.  A generic safe
++   copy would use (out + len), but it's normally the case that the end of the
++   output buffer is beyond the end of the current copy, and this can still be
++   exploited.
++ */
++static inline unsigned char FAR* chunkcopy_core_safe(
++    unsigned char FAR* out,
++    const unsigned char FAR* from,
++    unsigned len,
++    unsigned char FAR* limit) {
++  Assert(out + len <= limit, "chunk copy exceeds safety limit");
++  if (limit - out < CHUNKCOPY_CHUNK_SIZE) {
++    const unsigned char FAR* Z_RESTRICT rfrom = from;
++    if (len & 8) {
++      __builtin_memcpy(out, rfrom, 8);
++      out += 8;
++      rfrom += 8;
++    }
++    if (len & 4) {
++      __builtin_memcpy(out, rfrom, 4);
++      out += 4;
++      rfrom += 4;
++    }
++    if (len & 2) {
++      __builtin_memcpy(out, rfrom, 2);
++      out += 2;
++      rfrom += 2;
++    }
++    if (len & 1) {
++      *out++ = *rfrom++;
++    }
++    return out;
++  }
++  return chunkcopy_core(out, from, len);
++}
++
++/*
++   Perform short copies until distance can be rewritten as being at least
++   CHUNKCOPY_CHUNK_SIZE.
++
++   This assumes that it's OK to overwrite at least the first
++   2*CHUNKCOPY_CHUNK_SIZE bytes of output even if the copy is shorter than
++   this.  This assumption holds within inflate_fast() which starts every
++   iteration with at least 258 bytes of output space available (258 being the
++   maximum length output from a single token; see inffast.c).
++ */
++static inline unsigned char FAR* chunkunroll_relaxed(unsigned char FAR* out,
++                                                     unsigned FAR* dist,
++                                                     unsigned FAR* len) {
++  const unsigned char FAR* from = out - *dist;
++  while (*dist < *len && *dist < CHUNKCOPY_CHUNK_SIZE) {
++    storechunk(out, loadchunk(from));
++    out += *dist;
++    *len -= *dist;
++    *dist += *dist;
++  }
++  return out;
++}
++
++static inline uint8x16_t chunkset_vld1q_dup_u8x8(
++    const unsigned char FAR* Z_RESTRICT from) {
++#if defined(__clang__) || defined(__aarch64__)
++  return vreinterpretq_u8_u64(vld1q_dup_u64((void*)from));
++#else
++  /* 32-bit GCC uses an alignment hint for vld1q_dup_u64, even when given a
++   * void pointer, so here's an alternate implementation.
++   */
++  uint8x8_t h = vld1_u8(from);
++  return vcombine_u8(h, h);
++#endif
++}
++
++/*
++   Perform an overlapping copy which behaves as a memset() operation, but
++   supporting periods other than one, and assume that length is non-zero and
++   that it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE*3 bytes of output
++   even if the length is shorter than this.
++ */
++static inline unsigned char FAR* chunkset_core(unsigned char FAR* out,
++                                               unsigned period,
++                                               unsigned len) {
++  uint8x16_t f;
++  int bump = ((len - 1) % sizeof(f)) + 1;
++
++  switch (period) {
++    case 1:
++      f = vld1q_dup_u8(out - 1);
++      vst1q_u8(out, f);
++      out += bump;
++      len -= bump;
++      while (len > 0) {
++        vst1q_u8(out, f);
++        out += sizeof(f);
++        len -= sizeof(f);
++      }
++      return out;
++    case 2:
++      f = vreinterpretq_u8_u16(vld1q_dup_u16((void*)(out - 2)));
++      vst1q_u8(out, f);
++      out += bump;
++      len -= bump;
++      if (len > 0) {
++        f = vreinterpretq_u8_u16(vld1q_dup_u16((void*)(out - 2)));
++        do {
++          vst1q_u8(out, f);
++          out += sizeof(f);
++          len -= sizeof(f);
++        } while (len > 0);
++      }
++      return out;
++    case 4:
++      f = vreinterpretq_u8_u32(vld1q_dup_u32((void*)(out - 4)));
++      vst1q_u8(out, f);
++      out += bump;
++      len -= bump;
++      if (len > 0) {
++        f = vreinterpretq_u8_u32(vld1q_dup_u32((void*)(out - 4)));
++        do {
++          vst1q_u8(out, f);
++          out += sizeof(f);
++          len -= sizeof(f);
++        } while (len > 0);
++      }
++      return out;
++    case 8:
++      f = chunkset_vld1q_dup_u8x8(out - 8);
++      vst1q_u8(out, f);
++      out += bump;
++      len -= bump;
++      if (len > 0) {
++        f = chunkset_vld1q_dup_u8x8(out - 8);
++        do {
++          vst1q_u8(out, f);
++          out += sizeof(f);
++          len -= sizeof(f);
++        } while (len > 0);
++      }
++      return out;
++  }
++  out = chunkunroll_relaxed(out, &period, &len);
++  return chunkcopy_core(out, out - period, len);
++}
++
++/*
++   Perform a memcpy-like operation, but assume that length is non-zero and that
++   it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE bytes of output even if
++   the length is shorter than this.
++
++   Unlike chunkcopy_core() above, no guarantee is made regarding the behaviour
++   of overlapping buffers, regardless of the distance between the pointers.
++   This is reflected in the `restrict`-qualified pointers, allowing the
++   compiler to reorder loads and stores.
++ */
++static inline unsigned char FAR* chunkcopy_relaxed(
++    unsigned char FAR* Z_RESTRICT out,
++    const unsigned char FAR* Z_RESTRICT from,
++    unsigned len) {
++  return chunkcopy_core(out, from, len);
++}
++
++/*
++   Like chunkcopy_relaxed, but avoid writing beyond of legal output.
++
++   Unlike chunkcopy_core_safe() above, no guarantee is made regarding the
++   behaviour of overlapping buffers, regardless of the distance between the
++   pointers.  This is reflected in the `restrict`-qualified pointers, allowing
++   the compiler to reorder loads and stores.
++
++   Accepts an additional pointer to the end of safe output.  A generic safe
++   copy would use (out + len), but it's normally the case that the end of the
++   output buffer is beyond the end of the current copy, and this can still be
++   exploited.
++ */
++static inline unsigned char FAR* chunkcopy_safe(
++    unsigned char FAR* out,
++    const unsigned char FAR* Z_RESTRICT from,
++    unsigned len,
++    unsigned char FAR* limit) {
++  Assert(out + len <= limit, "chunk copy exceeds safety limit");
++  return chunkcopy_core_safe(out, from, len, limit);
++}
++
++/*
++   Perform chunky copy within the same buffer, where the source and destination
++   may potentially overlap.
++
++   Assumes that len > 0 on entry, and that it's safe to write at least
++   CHUNKCOPY_CHUNK_SIZE*3 bytes to the output.
++ */
++static inline unsigned char FAR*
++chunkcopy_lapped_relaxed(unsigned char FAR* out, unsigned dist, unsigned len) {
++  if (dist < len && dist < CHUNKCOPY_CHUNK_SIZE) {
++    return chunkset_core(out, dist, len);
++  }
++  return chunkcopy_core(out, out - dist, len);
++}
++
++/*
++   Behave like chunkcopy_lapped_relaxed, but avoid writing beyond of legal
++   output.
++
++   Accepts an additional pointer to the end of safe output.  A generic safe
++   copy would use (out + len), but it's normally the case that the end of the
++   output buffer is beyond the end of the current copy, and this can still be
++   exploited.
++ */
++static inline unsigned char FAR* chunkcopy_lapped_safe(
++    unsigned char FAR* out,
++    unsigned dist,
++    unsigned len,
++    unsigned char FAR* limit) {
++  Assert(out + len <= limit, "chunk copy exceeds safety limit");
++  if (limit - out < CHUNKCOPY_CHUNK_SIZE * 3) {
++    /* TODO: try harder to optimise this */
++    while (len-- > 0) {
++      *out = *(out - dist);
++      out++;
++    }
++    return out;
++  }
++  return chunkcopy_lapped_relaxed(out, dist, len);
++}
++
++#undef Z_RESTRICT
++
++#endif /* CHUNKCOPY_H */
+diff --git a/third_party/zlib/contrib/arm/inffast.c b/third_party/zlib/contrib/arm/inffast.c
+new file mode 100644
+index 0000000..f7f5007
+--- /dev/null
++++ b/third_party/zlib/contrib/arm/inffast.c
+@@ -0,0 +1,307 @@
++/* inffast.c -- fast decoding
++ * Copyright (C) 1995-2017 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++#include "zutil.h"
++#include "inftrees.h"
++#include "inflate.h"
++#include "inffast.h"
++#include "chunkcopy.h"
++
++#ifdef ASMINF
++#  pragma message("Assembler code may have bugs -- use at your own risk")
++#else
++
++/*
++   Decode literal, length, and distance codes and write out the resulting
++   literal and match bytes until either not enough input or output is
++   available, an end-of-block is encountered, or a data error is encountered.
++   When large enough input and output buffers are supplied to inflate(), for
++   example, a 16K input buffer and a 64K output buffer, more than 95% of the
++   inflate execution time is spent in this routine.
++
++   Entry assumptions:
++
++        state->mode == LEN
++        strm->avail_in >= 6
++        strm->avail_out >= 258
++        start >= strm->avail_out
++        state->bits < 8
++
++   On return, state->mode is one of:
++
++        LEN -- ran out of enough output space or enough available input
++        TYPE -- reached end of block code, inflate() to interpret next block
++        BAD -- error in block data
++
++   Notes:
++
++    - The maximum input bits used by a length/distance pair is 15 bits for the
++      length code, 5 bits for the length extra, 15 bits for the distance code,
++      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
++      Therefore if strm->avail_in >= 6, then there is enough input to avoid
++      checking for available input while decoding.
++
++    - The maximum bytes that a single length/distance pair can output is 258
++      bytes, which is the maximum length that can be coded.  inflate_fast()
++      requires strm->avail_out >= 258 for each loop to avoid checking for
++      output space.
++ */
++void ZLIB_INTERNAL inflate_fast(strm, start)
++z_streamp strm;
++unsigned start;         /* inflate()'s starting value for strm->avail_out */
++{
++    struct inflate_state FAR *state;
++    z_const unsigned char FAR *in;      /* local strm->next_in */
++    z_const unsigned char FAR *last;    /* have enough input while in < last */
++    unsigned char FAR *out;     /* local strm->next_out */
++    unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
++    unsigned char FAR *end;     /* while out < end, enough space available */
++    unsigned char FAR *limit;   /* safety limit for chunky copies */
++#ifdef INFLATE_STRICT
++    unsigned dmax;              /* maximum distance from zlib header */
++#endif
++    unsigned wsize;             /* window size or zero if not using window */
++    unsigned whave;             /* valid bytes in the window */
++    unsigned wnext;             /* window write index */
++    unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */
++    unsigned long hold;         /* local strm->hold */
++    unsigned bits;              /* local strm->bits */
++    code const FAR *lcode;      /* local strm->lencode */
++    code const FAR *dcode;      /* local strm->distcode */
++    unsigned lmask;             /* mask for first level of length codes */
++    unsigned dmask;             /* mask for first level of distance codes */
++    code here;                  /* retrieved table entry */
++    unsigned op;                /* code bits, operation, extra bits, or */
++                                /*  window position, window bytes to copy */
++    unsigned len;               /* match length, unused bytes */
++    unsigned dist;              /* match distance */
++    unsigned char FAR *from;    /* where to copy match from */
++
++    /* copy state to local variables */
++    state = (struct inflate_state FAR *)strm->state;
++    in = strm->next_in;
++    last = in + (strm->avail_in - 5);
++    out = strm->next_out;
++    beg = out - (start - strm->avail_out);
++    end = out + (strm->avail_out - 257);
++    limit = out + strm->avail_out;
++#ifdef INFLATE_STRICT
++    dmax = state->dmax;
++#endif
++    wsize = state->wsize;
++    whave = state->whave;
++    wnext = (state->wnext == 0 && whave >= wsize) ? wsize : state->wnext;
++    window = state->window;
++    hold = state->hold;
++    bits = state->bits;
++    lcode = state->lencode;
++    dcode = state->distcode;
++    lmask = (1U << state->lenbits) - 1;
++    dmask = (1U << state->distbits) - 1;
++
++    /* decode literals and length/distances until end-of-block or not enough
++       input data or output space */
++    do {
++        if (bits < 15) {
++            hold += (unsigned long)(*in++) << bits;
++            bits += 8;
++            hold += (unsigned long)(*in++) << bits;
++            bits += 8;
++        }
++        here = lcode[hold & lmask];
++      dolen:
++        op = (unsigned)(here.bits);
++        hold >>= op;
++        bits -= op;
++        op = (unsigned)(here.op);
++        if (op == 0) {                          /* literal */
++            Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
++                    "inflate:         literal '%c'\n" :
++                    "inflate:         literal 0x%02x\n", here.val));
++            *out++ = (unsigned char)(here.val);
++        }
++        else if (op & 16) {                     /* length base */
++            len = (unsigned)(here.val);
++            op &= 15;                           /* number of extra bits */
++            if (op) {
++                if (bits < op) {
++                    hold += (unsigned long)(*in++) << bits;
++                    bits += 8;
++                }
++                len += (unsigned)hold & ((1U << op) - 1);
++                hold >>= op;
++                bits -= op;
++            }
++            Tracevv((stderr, "inflate:         length %u\n", len));
++            if (bits < 15) {
++                hold += (unsigned long)(*in++) << bits;
++                bits += 8;
++                hold += (unsigned long)(*in++) << bits;
++                bits += 8;
++            }
++            here = dcode[hold & dmask];
++          dodist:
++            op = (unsigned)(here.bits);
++            hold >>= op;
++            bits -= op;
++            op = (unsigned)(here.op);
++            if (op & 16) {                      /* distance base */
++                dist = (unsigned)(here.val);
++                op &= 15;                       /* number of extra bits */
++                if (bits < op) {
++                    hold += (unsigned long)(*in++) << bits;
++                    bits += 8;
++                    if (bits < op) {
++                        hold += (unsigned long)(*in++) << bits;
++                        bits += 8;
++                    }
++                }
++                dist += (unsigned)hold & ((1U << op) - 1);
++#ifdef INFLATE_STRICT
++                if (dist > dmax) {
++                    strm->msg = (char *)"invalid distance too far back";
++                    state->mode = BAD;
++                    break;
++                }
++#endif
++                hold >>= op;
++                bits -= op;
++                Tracevv((stderr, "inflate:         distance %u\n", dist));
++                op = (unsigned)(out - beg);     /* max distance in output */
++                if (dist > op) {                /* see if copy from window */
++                    op = dist - op;             /* distance back in window */
++                    if (op > whave) {
++                        if (state->sane) {
++                            strm->msg =
++                                (char *)"invalid distance too far back";
++                            state->mode = BAD;
++                            break;
++                        }
++#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
++                        if (len <= op - whave) {
++                            do {
++                                *out++ = 0;
++                            } while (--len);
++                            continue;
++                        }
++                        len -= op - whave;
++                        do {
++                            *out++ = 0;
++                        } while (--op > whave);
++                        if (op == 0) {
++                            from = out - dist;
++                            do {
++                                *out++ = *from++;
++                            } while (--len);
++                            continue;
++                        }
++#endif
++                    }
++                    from = window;
++                    if (wnext >= op) {          /* contiguous in window */
++                        from += wnext - op;
++                    }
++                    else {                      /* wrap around window */
++                        op -= wnext;
++                        from += wsize - op;
++                        if (op < len) {         /* some from end of window */
++                            len -= op;
++                            out = chunkcopy_safe(out, from, op, limit);
++                            from = window;      /* more from start of window */
++                            op = wnext;
++                            /* This (rare) case can create a situation where
++                               the first chunkcopy below must be checked.
++                             */
++                        }
++                    }
++                    if (op < len) {             /* still need some from output */
++                        out = chunkcopy_safe(out, from, op, limit);
++                        len -= op;
++                        /* When dist is small the amount of data that can be
++                           copied from the window is also small, and progress
++                           towards the dangerous end of the output buffer is
++                           also small.  This means that for trivial memsets and
++                           for chunkunroll_relaxed() a safety check is
++                           unnecessary.  However, these conditions may not be
++                           entered at all, and in that case it's possible that
++                           the main copy is near the end.
++                          */
++                        out = chunkunroll_relaxed(out, &dist, &len);
++                        out = chunkcopy_safe(out, out - dist, len, limit);
++                    } else {
++                        /* from points to window, so there is no risk of
++                           overlapping pointers requiring memset-like behaviour
++                         */
++                        out = chunkcopy_safe(out, from, len, limit);
++                    }
++                }
++                else {
++                    /* Whole reference is in range of current output.  No
++                       range checks are necessary because we start with room
++                       for at least 258 bytes of output, so unroll and roundoff
++                       operations can write beyond `out+len` so long as they
++                       stay within 258 bytes of `out`.
++                     */
++                    out = chunkcopy_lapped_relaxed(out, dist, len);
++                }
++            }
++            else if ((op & 64) == 0) {          /* 2nd level distance code */
++                here = dcode[here.val + (hold & ((1U << op) - 1))];
++                goto dodist;
++            }
++            else {
++                strm->msg = (char *)"invalid distance code";
++                state->mode = BAD;
++                break;
++            }
++        }
++        else if ((op & 64) == 0) {              /* 2nd level length code */
++            here = lcode[here.val + (hold & ((1U << op) - 1))];
++            goto dolen;
++        }
++        else if (op & 32) {                     /* end-of-block */
++            Tracevv((stderr, "inflate:         end of block\n"));
++            state->mode = TYPE;
++            break;
++        }
++        else {
++            strm->msg = (char *)"invalid literal/length code";
++            state->mode = BAD;
++            break;
++        }
++    } while (in < last && out < end);
++
++    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
++    len = bits >> 3;
++    in -= len;
++    bits -= len << 3;
++    hold &= (1U << bits) - 1;
++
++    /* update state and return */
++    strm->next_in = in;
++    strm->next_out = out;
++    strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
++    strm->avail_out = (unsigned)(out < end ?
++                                 257 + (end - out) : 257 - (out - end));
++    state->hold = hold;
++    state->bits = bits;
++    return;
++}
++
++/*
++   inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
++   - Using bit fields for code structure
++   - Different op definition to avoid & for extra bits (do & for table bits)
++   - Three separate decoding do-loops for direct, window, and wnext == 0
++   - Special case for distance > 1 copies to do overlapped load and store copy
++   - Explicit branch predictions (based on measured branch probabilities)
++   - Deferring match copy and interspersed it with decoding subsequent codes
++   - Swapping literal/length else
++   - Swapping window/direct else
++   - Larger unrolled copy loops (three is about right)
++   - Moving len -= 3 statement into middle of loop
++ */
++
++#endif /* !ASMINF */
+diff --git a/third_party/zlib/contrib/arm/inflate.c b/third_party/zlib/contrib/arm/inflate.c
+new file mode 100644
+index 0000000..23e95f1
+--- /dev/null
++++ b/third_party/zlib/contrib/arm/inflate.c
+@@ -0,0 +1,1572 @@
++/* inflate.c -- zlib decompression
++ * Copyright (C) 1995-2016 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++/*
++ * Change history:
++ *
++ * 1.2.beta0    24 Nov 2002
++ * - First version -- complete rewrite of inflate to simplify code, avoid
++ *   creation of window when not needed, minimize use of window when it is
++ *   needed, make inffast.c even faster, implement gzip decoding, and to
++ *   improve code readability and style over the previous zlib inflate code
++ *
++ * 1.2.beta1    25 Nov 2002
++ * - Use pointers for available input and output checking in inffast.c
++ * - Remove input and output counters in inffast.c
++ * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
++ * - Remove unnecessary second byte pull from length extra in inffast.c
++ * - Unroll direct copy to three copies per loop in inffast.c
++ *
++ * 1.2.beta2    4 Dec 2002
++ * - Change external routine names to reduce potential conflicts
++ * - Correct filename to inffixed.h for fixed tables in inflate.c
++ * - Make hbuf[] unsigned char to match parameter type in inflate.c
++ * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
++ *   to avoid negation problem on Alphas (64 bit) in inflate.c
++ *
++ * 1.2.beta3    22 Dec 2002
++ * - Add comments on state->bits assertion in inffast.c
++ * - Add comments on op field in inftrees.h
++ * - Fix bug in reuse of allocated window after inflateReset()
++ * - Remove bit fields--back to byte structure for speed
++ * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
++ * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
++ * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
++ * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
++ * - Use local copies of stream next and avail values, as well as local bit
++ *   buffer and bit count in inflate()--for speed when inflate_fast() not used
++ *
++ * 1.2.beta4    1 Jan 2003
++ * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
++ * - Move a comment on output buffer sizes from inffast.c to inflate.c
++ * - Add comments in inffast.c to introduce the inflate_fast() routine
++ * - Rearrange window copies in inflate_fast() for speed and simplification
++ * - Unroll last copy for window match in inflate_fast()
++ * - Use local copies of window variables in inflate_fast() for speed
++ * - Pull out common wnext == 0 case for speed in inflate_fast()
++ * - Make op and len in inflate_fast() unsigned for consistency
++ * - Add FAR to lcode and dcode declarations in inflate_fast()
++ * - Simplified bad distance check in inflate_fast()
++ * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
++ *   source file infback.c to provide a call-back interface to inflate for
++ *   programs like gzip and unzip -- uses window as output buffer to avoid
++ *   window copying
++ *
++ * 1.2.beta5    1 Jan 2003
++ * - Improved inflateBack() interface to allow the caller to provide initial
++ *   input in strm.
++ * - Fixed stored blocks bug in inflateBack()
++ *
++ * 1.2.beta6    4 Jan 2003
++ * - Added comments in inffast.c on effectiveness of POSTINC
++ * - Typecasting all around to reduce compiler warnings
++ * - Changed loops from while (1) or do {} while (1) to for (;;), again to
++ *   make compilers happy
++ * - Changed type of window in inflateBackInit() to unsigned char *
++ *
++ * 1.2.beta7    27 Jan 2003
++ * - Changed many types to unsigned or unsigned short to avoid warnings
++ * - Added inflateCopy() function
++ *
++ * 1.2.0        9 Mar 2003
++ * - Changed inflateBack() interface to provide separate opaque descriptors
++ *   for the in() and out() functions
++ * - Changed inflateBack() argument and in_func typedef to swap the length
++ *   and buffer address return values for the input function
++ * - Check next_in and next_out for Z_NULL on entry to inflate()
++ *
++ * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
++ */
++
++#include "zutil.h"
++#include "inftrees.h"
++#include "inflate.h"
++#include "inffast.h"
++#include "contrib/arm/chunkcopy.h"
++
++#ifdef MAKEFIXED
++#  ifndef BUILDFIXED
++#    define BUILDFIXED
++#  endif
++#endif
++
++/* function prototypes */
++local int inflateStateCheck OF((z_streamp strm));
++local void fixedtables OF((struct inflate_state FAR *state));
++local int updatewindow OF((z_streamp strm, const unsigned char FAR *end,
++                           unsigned copy));
++#ifdef BUILDFIXED
++   void makefixed OF((void));
++#endif
++local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,
++                              unsigned len));
++
++local int inflateStateCheck(strm)
++z_streamp strm;
++{
++    struct inflate_state FAR *state;
++    if (strm == Z_NULL ||
++        strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
++        return 1;
++    state = (struct inflate_state FAR *)strm->state;
++    if (state == Z_NULL || state->strm != strm ||
++        state->mode < HEAD || state->mode > SYNC)
++        return 1;
++    return 0;
++}
++
++int ZEXPORT inflateResetKeep(strm)
++z_streamp strm;
++{
++    struct inflate_state FAR *state;
++
++    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
++    state = (struct inflate_state FAR *)strm->state;
++    strm->total_in = strm->total_out = state->total = 0;
++    strm->msg = Z_NULL;
++    if (state->wrap)        /* to support ill-conceived Java test suite */
++        strm->adler = state->wrap & 1;
++    state->mode = HEAD;
++    state->last = 0;
++    state->havedict = 0;
++    state->dmax = 32768U;
++    state->head = Z_NULL;
++    state->hold = 0;
++    state->bits = 0;
++    state->lencode = state->distcode = state->next = state->codes;
++    state->sane = 1;
++    state->back = -1;
++    Tracev((stderr, "inflate: reset\n"));
++    return Z_OK;
++}
++
++int ZEXPORT inflateReset(strm)
++z_streamp strm;
++{
++    struct inflate_state FAR *state;
++
++    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
++    state = (struct inflate_state FAR *)strm->state;
++    state->wsize = 0;
++    state->whave = 0;
++    state->wnext = 0;
++    return inflateResetKeep(strm);
++}
++
++int ZEXPORT inflateReset2(strm, windowBits)
++z_streamp strm;
++int windowBits;
++{
++    int wrap;
++    struct inflate_state FAR *state;
++
++    /* get the state */
++    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
++    state = (struct inflate_state FAR *)strm->state;
++
++    /* extract wrap request from windowBits parameter */
++    if (windowBits < 0) {
++        wrap = 0;
++        windowBits = -windowBits;
++    }
++    else {
++        wrap = (windowBits >> 4) + 5;
++#ifdef GUNZIP
++        if (windowBits < 48)
++            windowBits &= 15;
++#endif
++    }
++
++    /* set number of window bits, free window if different */
++    if (windowBits && (windowBits < 8 || windowBits > 15))
++        return Z_STREAM_ERROR;
++    if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
++        ZFREE(strm, state->window);
++        state->window = Z_NULL;
++    }
++
++    /* update state and reset the rest of it */
++    state->wrap = wrap;
++    state->wbits = (unsigned)windowBits;
++    return inflateReset(strm);
++}
++
++int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
++z_streamp strm;
++int windowBits;
++const char *version;
++int stream_size;
++{
++    int ret;
++    struct inflate_state FAR *state;
++
++    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
++        stream_size != (int)(sizeof(z_stream)))
++        return Z_VERSION_ERROR;
++    if (strm == Z_NULL) return Z_STREAM_ERROR;
++    strm->msg = Z_NULL;                 /* in case we return an error */
++    if (strm->zalloc == (alloc_func)0) {
++#ifdef Z_SOLO
++        return Z_STREAM_ERROR;
++#else
++        strm->zalloc = zcalloc;
++        strm->opaque = (voidpf)0;
++#endif
++    }
++    if (strm->zfree == (free_func)0)
++#ifdef Z_SOLO
++        return Z_STREAM_ERROR;
++#else
++        strm->zfree = zcfree;
++#endif
++    state = (struct inflate_state FAR *)
++            ZALLOC(strm, 1, sizeof(struct inflate_state));
++    if (state == Z_NULL) return Z_MEM_ERROR;
++    Tracev((stderr, "inflate: allocated\n"));
++    strm->state = (struct internal_state FAR *)state;
++    state->strm = strm;
++    state->window = Z_NULL;
++    state->mode = HEAD;     /* to pass state test in inflateReset2() */
++    state->check = 1L;      /* 1L is the result of adler32() zero length data */
++    ret = inflateReset2(strm, windowBits);
++    if (ret != Z_OK) {
++        ZFREE(strm, state);
++        strm->state = Z_NULL;
++    }
++    return ret;
++}
++
++int ZEXPORT inflateInit_(strm, version, stream_size)
++z_streamp strm;
++const char *version;
++int stream_size;
++{
++    return inflateInit2_(strm, DEF_WBITS, version, stream_size);
++}
++
++int ZEXPORT inflatePrime(strm, bits, value)
++z_streamp strm;
++int bits;
++int value;
++{
++    struct inflate_state FAR *state;
++
++    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
++    state = (struct inflate_state FAR *)strm->state;
++    if (bits < 0) {
++        state->hold = 0;
++        state->bits = 0;
++        return Z_OK;
++    }
++    if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR;
++    value &= (1L << bits) - 1;
++    state->hold += (unsigned)value << state->bits;
++    state->bits += (uInt)bits;
++    return Z_OK;
++}
++
++/*
++   Return state with length and distance decoding tables and index sizes set to
++   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
++   If BUILDFIXED is defined, then instead this routine builds the tables the
++   first time it's called, and returns those tables the first time and
++   thereafter.  This reduces the size of the code by about 2K bytes, in
++   exchange for a little execution time.  However, BUILDFIXED should not be
++   used for threaded applications, since the rewriting of the tables and virgin
++   may not be thread-safe.
++ */
++local void fixedtables(state)
++struct inflate_state FAR *state;
++{
++#ifdef BUILDFIXED
++    static int virgin = 1;
++    static code *lenfix, *distfix;
++    static code fixed[544];
++
++    /* build fixed huffman tables if first call (may not be thread safe) */
++    if (virgin) {
++        unsigned sym, bits;
++        static code *next;
++
++        /* literal/length table */
++        sym = 0;
++        while (sym < 144) state->lens[sym++] = 8;
++        while (sym < 256) state->lens[sym++] = 9;
++        while (sym < 280) state->lens[sym++] = 7;
++        while (sym < 288) state->lens[sym++] = 8;
++        next = fixed;
++        lenfix = next;
++        bits = 9;
++        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
++
++        /* distance table */
++        sym = 0;
++        while (sym < 32) state->lens[sym++] = 5;
++        distfix = next;
++        bits = 5;
++        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
++
++        /* do this just once */
++        virgin = 0;
++    }
++#else /* !BUILDFIXED */
++#   include "inffixed.h"
++#endif /* BUILDFIXED */
++    state->lencode = lenfix;
++    state->lenbits = 9;
++    state->distcode = distfix;
++    state->distbits = 5;
++}
++
++#ifdef MAKEFIXED
++#include <stdio.h>
++
++/*
++   Write out the inffixed.h that is #include'd above.  Defining MAKEFIXED also
++   defines BUILDFIXED, so the tables are built on the fly.  makefixed() writes
++   those tables to stdout, which would be piped to inffixed.h.  A small program
++   can simply call makefixed to do this:
++
++    void makefixed(void);
++
++    int main(void)
++    {
++        makefixed();
++        return 0;
++    }
++
++   Then that can be linked with zlib built with MAKEFIXED defined and run:
++
++    a.out > inffixed.h
++ */
++void makefixed()
++{
++    unsigned low, size;
++    struct inflate_state state;
++
++    fixedtables(&state);
++    puts("    /* inffixed.h -- table for decoding fixed codes");
++    puts("     * Generated automatically by makefixed().");
++    puts("     */");
++    puts("");
++    puts("    /* WARNING: this file should *not* be used by applications.");
++    puts("       It is part of the implementation of this library and is");
++    puts("       subject to change. Applications should only use zlib.h.");
++    puts("     */");
++    puts("");
++    size = 1U << 9;
++    printf("    static const code lenfix[%u] = {", size);
++    low = 0;
++    for (;;) {
++        if ((low % 7) == 0) printf("\n        ");
++        printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
++               state.lencode[low].bits, state.lencode[low].val);
++        if (++low == size) break;
++        putchar(',');
++    }
++    puts("\n    };");
++    size = 1U << 5;
++    printf("\n    static const code distfix[%u] = {", size);
++    low = 0;
++    for (;;) {
++        if ((low % 6) == 0) printf("\n        ");
++        printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
++               state.distcode[low].val);
++        if (++low == size) break;
++        putchar(',');
++    }
++    puts("\n    };");
++}
++#endif /* MAKEFIXED */
++
++/*
++   Update the window with the last wsize (normally 32K) bytes written before
++   returning.  If window does not exist yet, create it.  This is only called
++   when a window is already in use, or when output has been written during this
++   inflate call, but the end of the deflate stream has not been reached yet.
++   It is also called to create a window for dictionary data when a dictionary
++   is loaded.
++
++   Providing output buffers larger than 32K to inflate() should provide a speed
++   advantage, since only the last 32K of output is copied to the sliding window
++   upon return from inflate(), and since all distances after the first 32K of
++   output will fall in the output data, making match copies simpler and faster.
++   The advantage may be dependent on the size of the processor's data caches.
++ */
++local int updatewindow(strm, end, copy)
++z_streamp strm;
++const Bytef *end;
++unsigned copy;
++{
++    struct inflate_state FAR *state;
++    unsigned dist;
++
++    state = (struct inflate_state FAR *)strm->state;
++
++    /* if it hasn't been done already, allocate space for the window */
++    if (state->window == Z_NULL) {
++        unsigned wsize = 1U << state->wbits;
++        state->window = (unsigned char FAR *)
++                        ZALLOC(strm, wsize + CHUNKCOPY_CHUNK_SIZE,
++                               sizeof(unsigned char));
++        if (state->window == Z_NULL) return 1;
++#ifdef INFLATE_CLEAR_UNUSED_UNDEFINED
++        /* Copies from the overflow portion of this buffer are undefined and
++           may cause analysis tools to raise a warning if we don't initialize
++           it.  However, this undefined data overwrites other undefined data
++           and is subsequently either overwritten or left deliberately
++           undefined at the end of decode; so there's really no point.
++         */
++        memset(state->window + wsize, 0, CHUNKCOPY_CHUNK_SIZE);
++#endif
++    }
++
++    /* if window not in use yet, initialize */
++    if (state->wsize == 0) {
++        state->wsize = 1U << state->wbits;
++        state->wnext = 0;
++        state->whave = 0;
++    }
++
++    /* copy state->wsize or less output bytes into the circular window */
++    if (copy >= state->wsize) {
++        zmemcpy(state->window, end - state->wsize, state->wsize);
++        state->wnext = 0;
++        state->whave = state->wsize;
++    }
++    else {
++        dist = state->wsize - state->wnext;
++        if (dist > copy) dist = copy;
++        zmemcpy(state->window + state->wnext, end - copy, dist);
++        copy -= dist;
++        if (copy) {
++            zmemcpy(state->window, end - copy, copy);
++            state->wnext = copy;
++            state->whave = state->wsize;
++        }
++        else {
++            state->wnext += dist;
++            if (state->wnext == state->wsize) state->wnext = 0;
++            if (state->whave < state->wsize) state->whave += dist;
++        }
++    }
++    return 0;
++}
++
++/* Macros for inflate(): */
++
++/* check function to use adler32() for zlib or crc32() for gzip */
++#ifdef GUNZIP
++#  define UPDATE(check, buf, len) \
++    (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
++#else
++#  define UPDATE(check, buf, len) adler32(check, buf, len)
++#endif
++
++/* check macros for header crc */
++#ifdef GUNZIP
++#  define CRC2(check, word) \
++    do { \
++        hbuf[0] = (unsigned char)(word); \
++        hbuf[1] = (unsigned char)((word) >> 8); \
++        check = crc32(check, hbuf, 2); \
++    } while (0)
++
++#  define CRC4(check, word) \
++    do { \
++        hbuf[0] = (unsigned char)(word); \
++        hbuf[1] = (unsigned char)((word) >> 8); \
++        hbuf[2] = (unsigned char)((word) >> 16); \
++        hbuf[3] = (unsigned char)((word) >> 24); \
++        check = crc32(check, hbuf, 4); \
++    } while (0)
++#endif
++
++/* Load registers with state in inflate() for speed */
++#define LOAD() \
++    do { \
++        put = strm->next_out; \
++        left = strm->avail_out; \
++        next = strm->next_in; \
++        have = strm->avail_in; \
++        hold = state->hold; \
++        bits = state->bits; \
++    } while (0)
++
++/* Restore state from registers in inflate() */
++#define RESTORE() \
++    do { \
++        strm->next_out = put; \
++        strm->avail_out = left; \
++        strm->next_in = next; \
++        strm->avail_in = have; \
++        state->hold = hold; \
++        state->bits = bits; \
++    } while (0)
++
++/* Clear the input bit accumulator */
++#define INITBITS() \
++    do { \
++        hold = 0; \
++        bits = 0; \
++    } while (0)
++
++/* Get a byte of input into the bit accumulator, or return from inflate()
++   if there is no input available. */
++#define PULLBYTE() \
++    do { \
++        if (have == 0) goto inf_leave; \
++        have--; \
++        hold += (unsigned long)(*next++) << bits; \
++        bits += 8; \
++    } while (0)
++
++/* Assure that there are at least n bits in the bit accumulator.  If there is
++   not enough available input to do that, then return from inflate(). */
++#define NEEDBITS(n) \
++    do { \
++        while (bits < (unsigned)(n)) \
++            PULLBYTE(); \
++    } while (0)
++
++/* Return the low n bits of the bit accumulator (n < 16) */
++#define BITS(n) \
++    ((unsigned)hold & ((1U << (n)) - 1))
++
++/* Remove n bits from the bit accumulator */
++#define DROPBITS(n) \
++    do { \
++        hold >>= (n); \
++        bits -= (unsigned)(n); \
++    } while (0)
++
++/* Remove zero to seven bits as needed to go to a byte boundary */
++#define BYTEBITS() \
++    do { \
++        hold >>= bits & 7; \
++        bits -= bits & 7; \
++    } while (0)
++
++/*
++   inflate() uses a state machine to process as much input data and generate as
++   much output data as possible before returning.  The state machine is
++   structured roughly as follows:
++
++    for (;;) switch (state) {
++    ...
++    case STATEn:
++        if (not enough input data or output space to make progress)
++            return;
++        ... make progress ...
++        state = STATEm;
++        break;
++    ...
++    }
++
++   so when inflate() is called again, the same case is attempted again, and
++   if the appropriate resources are provided, the machine proceeds to the
++   next state.  The NEEDBITS() macro is usually the way the state evaluates
++   whether it can proceed or should return.  NEEDBITS() does the return if
++   the requested bits are not available.  The typical use of the BITS macros
++   is:
++
++        NEEDBITS(n);
++        ... do something with BITS(n) ...
++        DROPBITS(n);
++
++   where NEEDBITS(n) either returns from inflate() if there isn't enough
++   input left to load n bits into the accumulator, or it continues.  BITS(n)
++   gives the low n bits in the accumulator.  When done, DROPBITS(n) drops
++   the low n bits off the accumulator.  INITBITS() clears the accumulator
++   and sets the number of available bits to zero.  BYTEBITS() discards just
++   enough bits to put the accumulator on a byte boundary.  After BYTEBITS()
++   and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
++
++   NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
++   if there is no input available.  The decoding of variable length codes uses
++   PULLBYTE() directly in order to pull just enough bytes to decode the next
++   code, and no more.
++
++   Some states loop until they get enough input, making sure that enough
++   state information is maintained to continue the loop where it left off
++   if NEEDBITS() returns in the loop.  For example, want, need, and keep
++   would all have to actually be part of the saved state in case NEEDBITS()
++   returns:
++
++    case STATEw:
++        while (want < need) {
++            NEEDBITS(n);
++            keep[want++] = BITS(n);
++            DROPBITS(n);
++        }
++        state = STATEx;
++    case STATEx:
++
++   As shown above, if the next state is also the next case, then the break
++   is omitted.
++
++   A state may also return if there is not enough output space available to
++   complete that state.  Those states are copying stored data, writing a
++   literal byte, and copying a matching string.
++
++   When returning, a "goto inf_leave" is used to update the total counters,
++   update the check value, and determine whether any progress has been made
++   during that inflate() call in order to return the proper return code.
++   Progress is defined as a change in either strm->avail_in or strm->avail_out.
++   When there is a window, goto inf_leave will update the window with the last
++   output written.  If a goto inf_leave occurs in the middle of decompression
++   and there is no window currently, goto inf_leave will create one and copy
++   output to the window for the next call of inflate().
++
++   In this implementation, the flush parameter of inflate() only affects the
++   return code (per zlib.h).  inflate() always writes as much as possible to
++   strm->next_out, given the space available and the provided input--the effect
++   documented in zlib.h of Z_SYNC_FLUSH.  Furthermore, inflate() always defers
++   the allocation of and copying into a sliding window until necessary, which
++   provides the effect documented in zlib.h for Z_FINISH when the entire input
++   stream available.  So the only thing the flush parameter actually does is:
++   when flush is set to Z_FINISH, inflate() cannot return Z_OK.  Instead it
++   will return Z_BUF_ERROR if it has not reached the end of the stream.
++ */
++
++int ZEXPORT inflate(strm, flush)
++z_streamp strm;
++int flush;
++{
++    struct inflate_state FAR *state;
++    z_const unsigned char FAR *next;    /* next input */
++    unsigned char FAR *put;     /* next output */
++    unsigned have, left;        /* available input and output */
++    unsigned long hold;         /* bit buffer */
++    unsigned bits;              /* bits in bit buffer */
++    unsigned in, out;           /* save starting available input and output */
++    unsigned copy;              /* number of stored or match bytes to copy */
++    unsigned char FAR *from;    /* where to copy match bytes from */
++    code here;                  /* current decoding table entry */
++    code last;                  /* parent table entry */
++    unsigned len;               /* length to copy for repeats, bits to drop */
++    int ret;                    /* return code */
++#ifdef GUNZIP
++    unsigned char hbuf[4];      /* buffer for gzip header crc calculation */
++#endif
++    static const unsigned short order[19] = /* permutation of code lengths */
++        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
++
++    if (inflateStateCheck(strm) || strm->next_out == Z_NULL ||
++        (strm->next_in == Z_NULL && strm->avail_in != 0))
++        return Z_STREAM_ERROR;
++
++    state = (struct inflate_state FAR *)strm->state;
++    if (state->mode == TYPE) state->mode = TYPEDO;      /* skip check */
++    LOAD();
++    in = have;
++    out = left;
++    ret = Z_OK;
++    for (;;)
++        switch (state->mode) {
++        case HEAD:
++            if (state->wrap == 0) {
++                state->mode = TYPEDO;
++                break;
++            }
++            NEEDBITS(16);
++#ifdef GUNZIP
++            if ((state->wrap & 2) && hold == 0x8b1f) {  /* gzip header */
++                if (state->wbits == 0)
++                    state->wbits = 15;
++                state->check = crc32(0L, Z_NULL, 0);
++                CRC2(state->check, hold);
++                INITBITS();
++                state->mode = FLAGS;
++                break;
++            }
++            state->flags = 0;           /* expect zlib header */
++            if (state->head != Z_NULL)
++                state->head->done = -1;
++            if (!(state->wrap & 1) ||   /* check if zlib header allowed */
++#else
++            if (
++#endif
++                ((BITS(8) << 8) + (hold >> 8)) % 31) {
++                strm->msg = (char *)"incorrect header check";
++                state->mode = BAD;
++                break;
++            }
++            if (BITS(4) != Z_DEFLATED) {
++                strm->msg = (char *)"unknown compression method";
++                state->mode = BAD;
++                break;
++            }
++            DROPBITS(4);
++            len = BITS(4) + 8;
++            if (state->wbits == 0)
++                state->wbits = len;
++            if (len > 15 || len > state->wbits) {
++                strm->msg = (char *)"invalid window size";
++                state->mode = BAD;
++                break;
++            }
++            state->dmax = 1U << len;
++            Tracev((stderr, "inflate:   zlib header ok\n"));
++            strm->adler = state->check = adler32(0L, Z_NULL, 0);
++            state->mode = hold & 0x200 ? DICTID : TYPE;
++            INITBITS();
++            break;
++#ifdef GUNZIP
++        case FLAGS:
++            NEEDBITS(16);
++            state->flags = (int)(hold);
++            if ((state->flags & 0xff) != Z_DEFLATED) {
++                strm->msg = (char *)"unknown compression method";
++                state->mode = BAD;
++                break;
++            }
++            if (state->flags & 0xe000) {
++                strm->msg = (char *)"unknown header flags set";
++                state->mode = BAD;
++                break;
++            }
++            if (state->head != Z_NULL)
++                state->head->text = (int)((hold >> 8) & 1);
++            if ((state->flags & 0x0200) && (state->wrap & 4))
++                CRC2(state->check, hold);
++            INITBITS();
++            state->mode = TIME;
++        case TIME:
++            NEEDBITS(32);
++            if (state->head != Z_NULL)
++                state->head->time = hold;
++            if ((state->flags & 0x0200) && (state->wrap & 4))
++                CRC4(state->check, hold);
++            INITBITS();
++            state->mode = OS;
++        case OS:
++            NEEDBITS(16);
++            if (state->head != Z_NULL) {
++                state->head->xflags = (int)(hold & 0xff);
++                state->head->os = (int)(hold >> 8);
++            }
++            if ((state->flags & 0x0200) && (state->wrap & 4))
++                CRC2(state->check, hold);
++            INITBITS();
++            state->mode = EXLEN;
++        case EXLEN:
++            if (state->flags & 0x0400) {
++                NEEDBITS(16);
++                state->length = (unsigned)(hold);
++                if (state->head != Z_NULL)
++                    state->head->extra_len = (unsigned)hold;
++                if ((state->flags & 0x0200) && (state->wrap & 4))
++                    CRC2(state->check, hold);
++                INITBITS();
++            }
++            else if (state->head != Z_NULL)
++                state->head->extra = Z_NULL;
++            state->mode = EXTRA;
++        case EXTRA:
++            if (state->flags & 0x0400) {
++                copy = state->length;
++                if (copy > have) copy = have;
++                if (copy) {
++                    if (state->head != Z_NULL &&
++                        state->head->extra != Z_NULL) {
++                        len = state->head->extra_len - state->length;
++                        zmemcpy(state->head->extra + len, next,
++                                len + copy > state->head->extra_max ?
++                                state->head->extra_max - len : copy);
++                    }
++                    if ((state->flags & 0x0200) && (state->wrap & 4))
++                        state->check = crc32(state->check, next, copy);
++                    have -= copy;
++                    next += copy;
++                    state->length -= copy;
++                }
++                if (state->length) goto inf_leave;
++            }
++            state->length = 0;
++            state->mode = NAME;
++        case NAME:
++            if (state->flags & 0x0800) {
++                if (have == 0) goto inf_leave;
++                copy = 0;
++                do {
++                    len = (unsigned)(next[copy++]);
++                    if (state->head != Z_NULL &&
++                            state->head->name != Z_NULL &&
++                            state->length < state->head->name_max)
++                        state->head->name[state->length++] = (Bytef)len;
++                } while (len && copy < have);
++                if ((state->flags & 0x0200) && (state->wrap & 4))
++                    state->check = crc32(state->check, next, copy);
++                have -= copy;
++                next += copy;
++                if (len) goto inf_leave;
++            }
++            else if (state->head != Z_NULL)
++                state->head->name = Z_NULL;
++            state->length = 0;
++            state->mode = COMMENT;
++        case COMMENT:
++            if (state->flags & 0x1000) {
++                if (have == 0) goto inf_leave;
++                copy = 0;
++                do {
++                    len = (unsigned)(next[copy++]);
++                    if (state->head != Z_NULL &&
++                            state->head->comment != Z_NULL &&
++                            state->length < state->head->comm_max)
++                        state->head->comment[state->length++] = (Bytef)len;
++                } while (len && copy < have);
++                if ((state->flags & 0x0200) && (state->wrap & 4))
++                    state->check = crc32(state->check, next, copy);
++                have -= copy;
++                next += copy;
++                if (len) goto inf_leave;
++            }
++            else if (state->head != Z_NULL)
++                state->head->comment = Z_NULL;
++            state->mode = HCRC;
++        case HCRC:
++            if (state->flags & 0x0200) {
++                NEEDBITS(16);
++                if ((state->wrap & 4) && hold != (state->check & 0xffff)) {
++                    strm->msg = (char *)"header crc mismatch";
++                    state->mode = BAD;
++                    break;
++                }
++                INITBITS();
++            }
++            if (state->head != Z_NULL) {
++                state->head->hcrc = (int)((state->flags >> 9) & 1);
++                state->head->done = 1;
++            }
++            strm->adler = state->check = crc32(0L, Z_NULL, 0);
++            state->mode = TYPE;
++            break;
++#endif
++        case DICTID:
++            NEEDBITS(32);
++            strm->adler = state->check = ZSWAP32(hold);
++            INITBITS();
++            state->mode = DICT;
++        case DICT:
++            if (state->havedict == 0) {
++                RESTORE();
++                return Z_NEED_DICT;
++            }
++            strm->adler = state->check = adler32(0L, Z_NULL, 0);
++            state->mode = TYPE;
++        case TYPE:
++            if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
++        case TYPEDO:
++            if (state->last) {
++                BYTEBITS();
++                state->mode = CHECK;
++                break;
++            }
++            NEEDBITS(3);
++            state->last = BITS(1);
++            DROPBITS(1);
++            switch (BITS(2)) {
++            case 0:                             /* stored block */
++                Tracev((stderr, "inflate:     stored block%s\n",
++                        state->last ? " (last)" : ""));
++                state->mode = STORED;
++                break;
++            case 1:                             /* fixed block */
++                fixedtables(state);
++                Tracev((stderr, "inflate:     fixed codes block%s\n",
++                        state->last ? " (last)" : ""));
++                state->mode = LEN_;             /* decode codes */
++                if (flush == Z_TREES) {
++                    DROPBITS(2);
++                    goto inf_leave;
++                }
++                break;
++            case 2:                             /* dynamic block */
++                Tracev((stderr, "inflate:     dynamic codes block%s\n",
++                        state->last ? " (last)" : ""));
++                state->mode = TABLE;
++                break;
++            case 3:
++                strm->msg = (char *)"invalid block type";
++                state->mode = BAD;
++            }
++            DROPBITS(2);
++            break;
++        case STORED:
++            BYTEBITS();                         /* go to byte boundary */
++            NEEDBITS(32);
++            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
++                strm->msg = (char *)"invalid stored block lengths";
++                state->mode = BAD;
++                break;
++            }
++            state->length = (unsigned)hold & 0xffff;
++            Tracev((stderr, "inflate:       stored length %u\n",
++                    state->length));
++            INITBITS();
++            state->mode = COPY_;
++            if (flush == Z_TREES) goto inf_leave;
++        case COPY_:
++            state->mode = COPY;
++        case COPY:
++            copy = state->length;
++            if (copy) {
++                if (copy > have) copy = have;
++                if (copy > left) copy = left;
++                if (copy == 0) goto inf_leave;
++                zmemcpy(put, next, copy);
++                have -= copy;
++                next += copy;
++                left -= copy;
++                put += copy;
++                state->length -= copy;
++                break;
++            }
++            Tracev((stderr, "inflate:       stored end\n"));
++            state->mode = TYPE;
++            break;
++        case TABLE:
++            NEEDBITS(14);
++            state->nlen = BITS(5) + 257;
++            DROPBITS(5);
++            state->ndist = BITS(5) + 1;
++            DROPBITS(5);
++            state->ncode = BITS(4) + 4;
++            DROPBITS(4);
++#ifndef PKZIP_BUG_WORKAROUND
++            if (state->nlen > 286 || state->ndist > 30) {
++                strm->msg = (char *)"too many length or distance symbols";
++                state->mode = BAD;
++                break;
++            }
++#endif
++            Tracev((stderr, "inflate:       table sizes ok\n"));
++            state->have = 0;
++            state->mode = LENLENS;
++        case LENLENS:
++            while (state->have < state->ncode) {
++                NEEDBITS(3);
++                state->lens[order[state->have++]] = (unsigned short)BITS(3);
++                DROPBITS(3);
++            }
++            while (state->have < 19)
++                state->lens[order[state->have++]] = 0;
++            state->next = state->codes;
++            state->lencode = (const code FAR *)(state->next);
++            state->lenbits = 7;
++            ret = inflate_table(CODES, state->lens, 19, &(state->next),
++                                &(state->lenbits), state->work);
++            if (ret) {
++                strm->msg = (char *)"invalid code lengths set";
++                state->mode = BAD;
++                break;
++            }
++            Tracev((stderr, "inflate:       code lengths ok\n"));
++            state->have = 0;
++            state->mode = CODELENS;
++        case CODELENS:
++            while (state->have < state->nlen + state->ndist) {
++                for (;;) {
++                    here = state->lencode[BITS(state->lenbits)];
++                    if ((unsigned)(here.bits) <= bits) break;
++                    PULLBYTE();
++                }
++                if (here.val < 16) {
++                    DROPBITS(here.bits);
++                    state->lens[state->have++] = here.val;
++                }
++                else {
++                    if (here.val == 16) {
++                        NEEDBITS(here.bits + 2);
++                        DROPBITS(here.bits);
++                        if (state->have == 0) {
++                            strm->msg = (char *)"invalid bit length repeat";
++                            state->mode = BAD;
++                            break;
++                        }
++                        len = state->lens[state->have - 1];
++                        copy = 3 + BITS(2);
++                        DROPBITS(2);
++                    }
++                    else if (here.val == 17) {
++                        NEEDBITS(here.bits + 3);
++                        DROPBITS(here.bits);
++                        len = 0;
++                        copy = 3 + BITS(3);
++                        DROPBITS(3);
++                    }
++                    else {
++                        NEEDBITS(here.bits + 7);
++                        DROPBITS(here.bits);
++                        len = 0;
++                        copy = 11 + BITS(7);
++                        DROPBITS(7);
++                    }
++                    if (state->have + copy > state->nlen + state->ndist) {
++                        strm->msg = (char *)"invalid bit length repeat";
++                        state->mode = BAD;
++                        break;
++                    }
++                    while (copy--)
++                        state->lens[state->have++] = (unsigned short)len;
++                }
++            }
++
++            /* handle error breaks in while */
++            if (state->mode == BAD) break;
++
++            /* check for end-of-block code (better have one) */
++            if (state->lens[256] == 0) {
++                strm->msg = (char *)"invalid code -- missing end-of-block";
++                state->mode = BAD;
++                break;
++            }
++
++            /* build code tables -- note: do not change the lenbits or distbits
++               values here (9 and 6) without reading the comments in inftrees.h
++               concerning the ENOUGH constants, which depend on those values */
++            state->next = state->codes;
++            state->lencode = (const code FAR *)(state->next);
++            state->lenbits = 9;
++            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
++                                &(state->lenbits), state->work);
++            if (ret) {
++                strm->msg = (char *)"invalid literal/lengths set";
++                state->mode = BAD;
++                break;
++            }
++            state->distcode = (const code FAR *)(state->next);
++            state->distbits = 6;
++            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
++                            &(state->next), &(state->distbits), state->work);
++            if (ret) {
++                strm->msg = (char *)"invalid distances set";
++                state->mode = BAD;
++                break;
++            }
++            Tracev((stderr, "inflate:       codes ok\n"));
++            state->mode = LEN_;
++            if (flush == Z_TREES) goto inf_leave;
++        case LEN_:
++            state->mode = LEN;
++        case LEN:
++            if (have >= 6 && left >= 258) {
++                RESTORE();
++                inflate_fast(strm, out);
++                LOAD();
++                if (state->mode == TYPE)
++                    state->back = -1;
++                break;
++            }
++            state->back = 0;
++            for (;;) {
++                here = state->lencode[BITS(state->lenbits)];
++                if ((unsigned)(here.bits) <= bits) break;
++                PULLBYTE();
++            }
++            if (here.op && (here.op & 0xf0) == 0) {
++                last = here;
++                for (;;) {
++                    here = state->lencode[last.val +
++                            (BITS(last.bits + last.op) >> last.bits)];
++                    if ((unsigned)(last.bits + here.bits) <= bits) break;
++                    PULLBYTE();
++                }
++                DROPBITS(last.bits);
++                state->back += last.bits;
++            }
++            DROPBITS(here.bits);
++            state->back += here.bits;
++            state->length = (unsigned)here.val;
++            if ((int)(here.op) == 0) {
++                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
++                        "inflate:         literal '%c'\n" :
++                        "inflate:         literal 0x%02x\n", here.val));
++                state->mode = LIT;
++                break;
++            }
++            if (here.op & 32) {
++                Tracevv((stderr, "inflate:         end of block\n"));
++                state->back = -1;
++                state->mode = TYPE;
++                break;
++            }
++            if (here.op & 64) {
++                strm->msg = (char *)"invalid literal/length code";
++                state->mode = BAD;
++                break;
++            }
++            state->extra = (unsigned)(here.op) & 15;
++            state->mode = LENEXT;
++        case LENEXT:
++            if (state->extra) {
++                NEEDBITS(state->extra);
++                state->length += BITS(state->extra);
++                DROPBITS(state->extra);
++                state->back += state->extra;
++            }
++            Tracevv((stderr, "inflate:         length %u\n", state->length));
++            state->was = state->length;
++            state->mode = DIST;
++        case DIST:
++            for (;;) {
++                here = state->distcode[BITS(state->distbits)];
++                if ((unsigned)(here.bits) <= bits) break;
++                PULLBYTE();
++            }
++            if ((here.op & 0xf0) == 0) {
++                last = here;
++                for (;;) {
++                    here = state->distcode[last.val +
++                            (BITS(last.bits + last.op) >> last.bits)];
++                    if ((unsigned)(last.bits + here.bits) <= bits) break;
++                    PULLBYTE();
++                }
++                DROPBITS(last.bits);
++                state->back += last.bits;
++            }
++            DROPBITS(here.bits);
++            state->back += here.bits;
++            if (here.op & 64) {
++                strm->msg = (char *)"invalid distance code";
++                state->mode = BAD;
++                break;
++            }
++            state->offset = (unsigned)here.val;
++            state->extra = (unsigned)(here.op) & 15;
++            state->mode = DISTEXT;
++        case DISTEXT:
++            if (state->extra) {
++                NEEDBITS(state->extra);
++                state->offset += BITS(state->extra);
++                DROPBITS(state->extra);
++                state->back += state->extra;
++            }
++#ifdef INFLATE_STRICT
++            if (state->offset > state->dmax) {
++                strm->msg = (char *)"invalid distance too far back";
++                state->mode = BAD;
++                break;
++            }
++#endif
++            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
++            state->mode = MATCH;
++        case MATCH:
++            if (left == 0) goto inf_leave;
++            copy = out - left;
++            if (state->offset > copy) {         /* copy from window */
++                copy = state->offset - copy;
++                if (copy > state->whave) {
++                    if (state->sane) {
++                        strm->msg = (char *)"invalid distance too far back";
++                        state->mode = BAD;
++                        break;
++                    }
++#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
++                    Trace((stderr, "inflate.c too far\n"));
++                    copy -= state->whave;
++                    if (copy > state->length) copy = state->length;
++                    if (copy > left) copy = left;
++                    left -= copy;
++                    state->length -= copy;
++                    do {
++                        *put++ = 0;
++                    } while (--copy);
++                    if (state->length == 0) state->mode = LEN;
++                    break;
++#endif
++                }
++                if (copy > state->wnext) {
++                    copy -= state->wnext;
++                    from = state->window + (state->wsize - copy);
++                }
++                else
++                    from = state->window + (state->wnext - copy);
++                if (copy > state->length) copy = state->length;
++                if (copy > left) copy = left;
++                put = chunkcopy_safe(put, from, copy, put + left);
++            }
++            else {                              /* copy from output */
++                copy = state->length;
++                if (copy > left) copy = left;
++                put = chunkcopy_lapped_safe(put, state->offset, copy, put + left);
++            }
++            left -= copy;
++            state->length -= copy;
++            if (state->length == 0) state->mode = LEN;
++            break;
++        case LIT:
++            if (left == 0) goto inf_leave;
++            *put++ = (unsigned char)(state->length);
++            left--;
++            state->mode = LEN;
++            break;
++        case CHECK:
++            if (state->wrap) {
++                NEEDBITS(32);
++                out -= left;
++                strm->total_out += out;
++                state->total += out;
++                if ((state->wrap & 4) && out)
++                    strm->adler = state->check =
++                        UPDATE(state->check, put - out, out);
++                out = left;
++                if ((state->wrap & 4) && (
++#ifdef GUNZIP
++                     state->flags ? hold :
++#endif
++                     ZSWAP32(hold)) != state->check) {
++                    strm->msg = (char *)"incorrect data check";
++                    state->mode = BAD;
++                    break;
++                }
++                INITBITS();
++                Tracev((stderr, "inflate:   check matches trailer\n"));
++            }
++#ifdef GUNZIP
++            state->mode = LENGTH;
++        case LENGTH:
++            if (state->wrap && state->flags) {
++                NEEDBITS(32);
++                if (hold != (state->total & 0xffffffffUL)) {
++                    strm->msg = (char *)"incorrect length check";
++                    state->mode = BAD;
++                    break;
++                }
++                INITBITS();
++                Tracev((stderr, "inflate:   length matches trailer\n"));
++            }
++#endif
++            state->mode = DONE;
++        case DONE:
++            ret = Z_STREAM_END;
++            goto inf_leave;
++        case BAD:
++            ret = Z_DATA_ERROR;
++            goto inf_leave;
++        case MEM:
++            return Z_MEM_ERROR;
++        case SYNC:
++        default:
++            return Z_STREAM_ERROR;
++        }
++
++    /*
++       Return from inflate(), updating the total counts and the check value.
++       If there was no progress during the inflate() call, return a buffer
++       error.  Call updatewindow() to create and/or update the window state.
++       Note: a memory error from inflate() is non-recoverable.
++     */
++  inf_leave:
++    RESTORE();
++    if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
++            (state->mode < CHECK || flush != Z_FINISH)))
++        if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {
++            state->mode = MEM;
++            return Z_MEM_ERROR;
++        }
++    in -= strm->avail_in;
++    out -= strm->avail_out;
++    strm->total_in += in;
++    strm->total_out += out;
++    state->total += out;
++    if ((state->wrap & 4) && out)
++        strm->adler = state->check =
++            UPDATE(state->check, strm->next_out - out, out);
++    strm->data_type = (int)state->bits + (state->last ? 64 : 0) +
++                      (state->mode == TYPE ? 128 : 0) +
++                      (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
++    if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
++        ret = Z_BUF_ERROR;
++    return ret;
++}
++
++int ZEXPORT inflateEnd(strm)
++z_streamp strm;
++{
++    struct inflate_state FAR *state;
++    if (inflateStateCheck(strm))
++        return Z_STREAM_ERROR;
++    state = (struct inflate_state FAR *)strm->state;
++    if (state->window != Z_NULL) ZFREE(strm, state->window);
++    ZFREE(strm, strm->state);
++    strm->state = Z_NULL;
++    Tracev((stderr, "inflate: end\n"));
++    return Z_OK;
++}
++
++int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength)
++z_streamp strm;
++Bytef *dictionary;
++uInt *dictLength;
++{
++    struct inflate_state FAR *state;
++
++    /* check state */
++    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
++    state = (struct inflate_state FAR *)strm->state;
++
++    /* copy dictionary */
++    if (state->whave && dictionary != Z_NULL) {
++        zmemcpy(dictionary, state->window + state->wnext,
++                state->whave - state->wnext);
++        zmemcpy(dictionary + state->whave - state->wnext,
++                state->window, state->wnext);
++    }
++    if (dictLength != Z_NULL)
++        *dictLength = state->whave;
++    return Z_OK;
++}
++
++int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
++z_streamp strm;
++const Bytef *dictionary;
++uInt dictLength;
++{
++    struct inflate_state FAR *state;
++    unsigned long dictid;
++    int ret;
++
++    /* check state */
++    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
++    state = (struct inflate_state FAR *)strm->state;
++    if (state->wrap != 0 && state->mode != DICT)
++        return Z_STREAM_ERROR;
++
++    /* check for correct dictionary identifier */
++    if (state->mode == DICT) {
++        dictid = adler32(0L, Z_NULL, 0);
++        dictid = adler32(dictid, dictionary, dictLength);
++        if (dictid != state->check)
++            return Z_DATA_ERROR;
++    }
++
++    /* copy dictionary to window using updatewindow(), which will amend the
++       existing dictionary if appropriate */
++    ret = updatewindow(strm, dictionary + dictLength, dictLength);
++    if (ret) {
++        state->mode = MEM;
++        return Z_MEM_ERROR;
++    }
++    state->havedict = 1;
++    Tracev((stderr, "inflate:   dictionary set\n"));
++    return Z_OK;
++}
++
++int ZEXPORT inflateGetHeader(strm, head)
++z_streamp strm;
++gz_headerp head;
++{
++    struct inflate_state FAR *state;
++
++    /* check state */
++    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
++    state = (struct inflate_state FAR *)strm->state;
++    if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
++
++    /* save header structure */
++    state->head = head;
++    head->done = 0;
++    return Z_OK;
++}
++
++/*
++   Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff.  Return when found
++   or when out of input.  When called, *have is the number of pattern bytes
++   found in order so far, in 0..3.  On return *have is updated to the new
++   state.  If on return *have equals four, then the pattern was found and the
++   return value is how many bytes were read including the last byte of the
++   pattern.  If *have is less than four, then the pattern has not been found
++   yet and the return value is len.  In the latter case, syncsearch() can be
++   called again with more data and the *have state.  *have is initialized to
++   zero for the first call.
++ */
++local unsigned syncsearch(have, buf, len)
++unsigned FAR *have;
++const unsigned char FAR *buf;
++unsigned len;
++{
++    unsigned got;
++    unsigned next;
++
++    got = *have;
++    next = 0;
++    while (next < len && got < 4) {
++        if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
++            got++;
++        else if (buf[next])
++            got = 0;
++        else
++            got = 4 - got;
++        next++;
++    }
++    *have = got;
++    return next;
++}
++
++int ZEXPORT inflateSync(strm)
++z_streamp strm;
++{
++    unsigned len;               /* number of bytes to look at or looked at */
++    unsigned long in, out;      /* temporary to save total_in and total_out */
++    unsigned char buf[4];       /* to restore bit buffer to byte string */
++    struct inflate_state FAR *state;
++
++    /* check parameters */
++    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
++    state = (struct inflate_state FAR *)strm->state;
++    if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
++
++    /* if first time, start search in bit buffer */
++    if (state->mode != SYNC) {
++        state->mode = SYNC;
++        state->hold <<= state->bits & 7;
++        state->bits -= state->bits & 7;
++        len = 0;
++        while (state->bits >= 8) {
++            buf[len++] = (unsigned char)(state->hold);
++            state->hold >>= 8;
++            state->bits -= 8;
++        }
++        state->have = 0;
++        syncsearch(&(state->have), buf, len);
++    }
++
++    /* search available input */
++    len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
++    strm->avail_in -= len;
++    strm->next_in += len;
++    strm->total_in += len;
++
++    /* return no joy or set up to restart inflate() on a new block */
++    if (state->have != 4) return Z_DATA_ERROR;
++    in = strm->total_in;  out = strm->total_out;
++    inflateReset(strm);
++    strm->total_in = in;  strm->total_out = out;
++    state->mode = TYPE;
++    return Z_OK;
++}
++
++/*
++   Returns true if inflate is currently at the end of a block generated by
++   Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
++   implementation to provide an additional safety check. PPP uses
++   Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
++   block. When decompressing, PPP checks that at the end of input packet,
++   inflate is waiting for these length bytes.
++ */
++int ZEXPORT inflateSyncPoint(strm)
++z_streamp strm;
++{
++    struct inflate_state FAR *state;
++
++    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
++    state = (struct inflate_state FAR *)strm->state;
++    return state->mode == STORED && state->bits == 0;
++}
++
++int ZEXPORT inflateCopy(dest, source)
++z_streamp dest;
++z_streamp source;
++{
++    struct inflate_state FAR *state;
++    struct inflate_state FAR *copy;
++    unsigned char FAR *window;
++    unsigned wsize;
++
++    /* check input */
++    if (inflateStateCheck(source) || dest == Z_NULL)
++        return Z_STREAM_ERROR;
++    state = (struct inflate_state FAR *)source->state;
++
++    /* allocate space */
++    copy = (struct inflate_state FAR *)
++           ZALLOC(source, 1, sizeof(struct inflate_state));
++    if (copy == Z_NULL) return Z_MEM_ERROR;
++    window = Z_NULL;
++    if (state->window != Z_NULL) {
++        window = (unsigned char FAR *)
++                 ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
++        if (window == Z_NULL) {
++            ZFREE(source, copy);
++            return Z_MEM_ERROR;
++        }
++    }
++
++    /* copy state */
++    zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
++    zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
++    copy->strm = dest;
++    if (state->lencode >= state->codes &&
++        state->lencode <= state->codes + ENOUGH - 1) {
++        copy->lencode = copy->codes + (state->lencode - state->codes);
++        copy->distcode = copy->codes + (state->distcode - state->codes);
++    }
++    copy->next = copy->codes + (state->next - state->codes);
++    if (window != Z_NULL) {
++        wsize = 1U << state->wbits;
++        zmemcpy(window, state->window, wsize);
++    }
++    copy->window = window;
++    dest->state = (struct internal_state FAR *)copy;
++    return Z_OK;
++}
++
++int ZEXPORT inflateUndermine(strm, subvert)
++z_streamp strm;
++int subvert;
++{
++    struct inflate_state FAR *state;
++
++    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
++    state = (struct inflate_state FAR *)strm->state;
++#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
++    state->sane = !subvert;
++    return Z_OK;
++#else
++    (void)subvert;
++    state->sane = 1;
++    return Z_DATA_ERROR;
++#endif
++}
++
++int ZEXPORT inflateValidate(strm, check)
++z_streamp strm;
++int check;
++{
++    struct inflate_state FAR *state;
++
++    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
++    state = (struct inflate_state FAR *)strm->state;
++    if (check)
++        state->wrap |= 4;
++    else
++        state->wrap &= ~4;
++    return Z_OK;
++}
++
++long ZEXPORT inflateMark(strm)
++z_streamp strm;
++{
++    struct inflate_state FAR *state;
++
++    if (inflateStateCheck(strm))
++        return -(1L << 16);
++    state = (struct inflate_state FAR *)strm->state;
++    return (long)(((unsigned long)((long)state->back)) << 16) +
++        (state->mode == COPY ? state->length :
++            (state->mode == MATCH ? state->was - state->length : 0));
++}
++
++unsigned long ZEXPORT inflateCodesUsed(strm)
++z_streamp strm;
++{
++    struct inflate_state FAR *state;
++    if (inflateStateCheck(strm)) return (unsigned long)-1;
++    state = (struct inflate_state FAR *)strm->state;
++    return (unsigned long)(state->next - state->codes);
++}
+-- 
+2.7.4
+
diff --git a/third_party/zlib/patches/0005-adler32-simd.patch b/third_party/zlib/patches/0005-adler32-simd.patch
new file mode 100644
index 0000000..7034389e
--- /dev/null
+++ b/third_party/zlib/patches/0005-adler32-simd.patch
@@ -0,0 +1,695 @@
+From 7b27bbdc07ed76de114bf9a82db854d2f2c8e85c Mon Sep 17 00:00:00 2001
+From: Noel Gordon <noel@chromium.org>
+Date: Fri, 29 Sep 2017 22:32:47 +1000
+Subject: [PATCH] zlib adler_simd.c
+
+Add SSSE3 implementation of the adler32 checksum, suitable for
+both large workloads, and small workloads commonly seen during
+PNG image decoding. Add a NEON implementation.
+
+Speed is comparable to the serial adler32 computation but near
+64 bytes of input data, the SIMD code paths begin to be faster
+than the serial path: 3x faster at 256 bytes of input data, to
+~8x faster for 1M of input data (~4x on ARMv8 NEON).
+
+For the PNG 140 image corpus, PNG decoding speed is ~8% faster
+on average on the desktop machines tested, and ~2% on an ARMv8
+Pixel C Android (N) tablet, https://crbug.com/762564#c41
+
+Update x86.{c,h} to runtime detect SSSE3 support and use it to
+enable the adler32_simd code path and update inflate.c to call
+x86_check_features(). Update the name mangler file names.h for
+the new symbols added, add FIXME about simd.patch.
+
+Ignore data alignment in the SSSE3 case since unaligned access
+is no longer penalized on current generation Intel CPU. Use it
+in the NEON case however to avoid the extra costs of unaligned
+memory access on ARMv8/v7.
+
+NEON credits: the v_s1/s2 vector component accumulate code was
+provided by Adenilson Cavalcanti. The uint16 column vector sum
+code is from libdeflate with corrections to process NMAX input
+bytes which improves performance by 3% for large buffers.
+
+Update BUILD.gn to put the code in its own source set, and add
+it conditionally to the zlib library build rule. On ARM, build
+the SIMD with max-speed config to produce the smallest code.
+
+No change in behavior, covered by many existing tests.
+
+Bug:762564
+Change-Id: I14a39940ae113b5a67ba70a99c3741e289b1796b
+---
+ third_party/zlib/BUILD.gn       |  64 ++++++-
+ third_party/zlib/adler32.c      |  15 ++
+ third_party/zlib/adler32_simd.c | 366 ++++++++++++++++++++++++++++++++++++++++
+ third_party/zlib/adler32_simd.h |  16 ++
+ third_party/zlib/inflate.c      |   3 +
+ third_party/zlib/names.h        |   7 +
+ third_party/zlib/x86.c          |  13 +-
+ third_party/zlib/x86.h          |   1 +
+ 8 files changed, 481 insertions(+), 4 deletions(-)
+ create mode 100644 third_party/zlib/adler32_simd.c
+ create mode 100644 third_party/zlib/adler32_simd.h
+
+diff --git a/third_party/zlib/BUILD.gn b/third_party/zlib/BUILD.gn
+index 027a38cbcac3..11f57effb5ad 100644
+--- a/third_party/zlib/BUILD.gn
++++ b/third_party/zlib/BUILD.gn
+@@ -10,6 +10,53 @@ config("zlib_config") {
+   include_dirs = [ "." ]
+ }
+ 
++config("zlib_adler32_simd_config") {
++  if (!is_ios && (current_cpu == "x86" || current_cpu == "x64")) {
++    defines = [ "ADLER32_SIMD_SSSE3" ]
++  }
++
++  if (current_cpu == "arm" || current_cpu == "arm64") {
++    if (arm_use_neon) {
++      defines = [ "ADLER32_SIMD_NEON" ]
++    }
++  }
++}
++
++source_set("zlib_adler32_simd") {
++  visibility = [ ":*" ]
++
++  if (!is_ios && (current_cpu == "x86" || current_cpu == "x64")) {
++    sources = [
++      "adler32_simd.c",
++      "adler32_simd.h",
++    ]
++
++    if (!is_win || is_clang) {
++      cflags = [ "-mssse3" ]
++    }
++  }
++
++  if (current_cpu == "arm" || current_cpu == "arm64") {
++    if (arm_use_neon) {
++      sources = [
++        "adler32_simd.c",
++        "adler32_simd.h",
++      ]
++
++      if (!is_debug) {
++        # Use optimize_speed (-O3) to output the _smallest_ code.
++        configs -= [ "//build/config/compiler:default_optimization" ]
++        configs += [ "//build/config/compiler:optimize_speed" ]
++      }
++    }
++  }
++
++  configs -= [ "//build/config/compiler:chromium_code" ]
++  configs += [ "//build/config/compiler:no_chromium_code" ]
++
++  public_configs = [ ":zlib_adler32_simd_config" ]
++}
++
+ static_library("zlib_x86_simd") {
+   if (!is_ios && (current_cpu == "x86" || current_cpu == "x64")) {
+     sources = [
+@@ -90,8 +137,19 @@ static_library("zlib") {
+     }
+   }
+ 
++  defines = []
++  deps = []
++
+   if (!is_ios && (current_cpu == "x86" || current_cpu == "x64")) {
+     sources += [ "x86.c" ]
++
++    deps += [ ":zlib_adler32_simd" ]
++  }
++
++  if (current_cpu == "arm" || current_cpu == "arm64") {
++    if (arm_use_neon) {
++      deps += [ ":zlib_adler32_simd" ]
++    }
+   }
+ 
+   configs -= [ "//build/config/compiler:chromium_code" ]
+@@ -103,8 +161,9 @@ static_library("zlib") {
+   ]
+ 
+   public_configs = [ ":zlib_config" ]
+-  deps = [
+-    ":zlib_x86_simd",
++
++  deps += [
++    ":zlib_x86_simd"
+   ]
+ }
+ 
+@@ -151,5 +210,6 @@ static_library("minizip") {
+     # Must be after no_chromium_code for warning flags to be ordered correctly.
+     ":minizip_warnings",
+   ]
++
+   public_configs = [ ":zlib_config" ]
+ }
+diff --git a/third_party/zlib/adler32.c b/third_party/zlib/adler32.c
+index d0be4380a39c..03491b920d3e 100644
+--- a/third_party/zlib/adler32.c
++++ b/third_party/zlib/adler32.c
+@@ -59,6 +59,13 @@ local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
+ #  define MOD63(a) a %= BASE
+ #endif
+ 
++#if defined(ADLER32_SIMD_SSSE3)
++#include "adler32_simd.h"
++#include "x86.h"
++#elif defined(ADLER32_SIMD_NEON)
++#include "adler32_simd.h"
++#endif
++
+ /* ========================================================================= */
+ uLong ZEXPORT adler32_z(adler, buf, len)
+     uLong adler;
+@@ -68,6 +75,14 @@ uLong ZEXPORT adler32_z(adler, buf, len)
+     unsigned long sum2;
+     unsigned n;
+ 
++#if defined(ADLER32_SIMD_SSSE3)
++    if (x86_cpu_enable_ssse3 && buf && len >= 64)
++        return adler32_simd_(adler, buf, len);
++#elif defined(ADLER32_SIMD_NEON)
++    if (buf && len >= 64)
++        return adler32_simd_(adler, buf, len);
++#endif
++
+     /* split Adler-32 into component sums */
+     sum2 = (adler >> 16) & 0xffff;
+     adler &= 0xffff;
+diff --git a/third_party/zlib/adler32_simd.c b/third_party/zlib/adler32_simd.c
+new file mode 100644
+index 000000000000..d73f97e52cff
+--- /dev/null
++++ b/third_party/zlib/adler32_simd.c
+@@ -0,0 +1,366 @@
++/* adler32_simd.c
++ *
++ * 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 Chromium source repository LICENSE file.
++ *
++ * Per http://en.wikipedia.org/wiki/Adler-32 the adler32 A value (aka s1) is
++ * the sum of N input data bytes D1 ... DN,
++ *
++ *   A = A0 + D1 + D2 + ... + DN
++ *
++ * where A0 is the initial value.
++ *
++ * SSE2 _mm_sad_epu8() can be used for byte sums (see http://bit.ly/2wpUOeD,
++ * for example) and accumulating the byte sums can use SSE shuffle-adds (see
++ * the "Integer" section of http://bit.ly/2erPT8t for details). Arm NEON has
++ * similar instructions.
++ *
++ * The adler32 B value (aka s2) sums the A values from each step:
++ *
++ *   B0 + (A0 + D1) + (A0 + D1 + D2) + ... + (A0 + D1 + D2 + ... + DN) or
++ *
++ *       B0 + N.A0 + N.D1 + (N-1).D2 + (N-2).D3 + ... + (N-(N-1)).DN
++ *
++ * B0 being the initial value. For 32 bytes (ideal for garden-variety SIMD):
++ *
++ *   B = B0 + 32.A0 + [D1 D2 D3 ... D32] x [32 31 30 ... 1].
++ *
++ * Adjacent blocks of 32 input bytes can be iterated with the expressions to
++ * compute the adler32 s1 s2 of M >> 32 input bytes [1].
++ *
++ * As M grows, the s1 s2 sums grow. If left unchecked, they would eventually
++ * overflow the precision of their integer representation (bad). However, s1
++ * and s2 also need to be computed modulo the adler BASE value (reduced). If
++ * at most NMAX bytes are processed before a reduce, s1 s2 _cannot_ overflow
++ * a uint32_t type (the NMAX constraint) [2].
++ *
++ * [1] the iterative equations for s2 contain constant factors; these can be
++ * hoisted from the n-blocks do loop of the SIMD code.
++ *
++ * [2] zlib adler32_z() uses this fact to implement NMAX-block-based updates
++ * of the adler s1 s2 of uint32_t type (see adler32.c).
++ */
++
++#include "adler32_simd.h"
++
++/* Definitions from adler32.c: largest prime smaller than 65536 */
++#define BASE 65521U
++/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
++#define NMAX 5552
++
++#if defined(ADLER32_SIMD_SSSE3)
++
++#include <tmmintrin.h>
++
++uint32_t ZLIB_INTERNAL adler32_simd_(  /* SSSE3 */
++    uint32_t adler,
++    const unsigned char *buf,
++    z_size_t len)
++{
++    /*
++     * Split Adler-32 into component sums.
++     */
++    uint32_t s1 = adler & 0xffff;
++    uint32_t s2 = adler >> 16;
++
++    /*
++     * Process the data in blocks.
++     */
++    const unsigned BLOCK_SIZE = 1 << 5;
++
++    z_size_t blocks = len / BLOCK_SIZE;
++    len -= blocks * BLOCK_SIZE;
++
++    while (blocks)
++    {
++        unsigned n = NMAX / BLOCK_SIZE;  /* The NMAX constraint. */
++        if (n > blocks)
++            n = blocks;
++        blocks -= n;
++
++        const __m128i tap1 =
++            _mm_setr_epi8(32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17);
++        const __m128i tap2 =
++            _mm_setr_epi8(16,15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1);
++        const __m128i zero =
++            _mm_setr_epi8( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
++        const __m128i ones =
++            _mm_set_epi16( 1, 1, 1, 1, 1, 1, 1, 1);
++
++        /*
++         * Process n blocks of data. At most NMAX data bytes can be
++         * processed before s2 must be reduced modulo BASE.
++         */
++        __m128i v_ps = _mm_set_epi32(0, 0, 0, s1 * n);
++        __m128i v_s2 = _mm_set_epi32(0, 0, 0, s2);
++        __m128i v_s1 = _mm_set_epi32(0, 0, 0, 0);
++
++        do {
++            /*
++             * Load 32 input bytes.
++             */
++            const __m128i bytes1 = _mm_loadu_si128((__m128i*)(buf));
++            const __m128i bytes2 = _mm_loadu_si128((__m128i*)(buf + 16));
++
++            /*
++             * Add previous block byte sum to v_ps.
++             */
++            v_ps = _mm_add_epi32(v_ps, v_s1);
++
++            /*
++             * Horizontally add the bytes for s1, multiply-adds the
++             * bytes by [ 32, 31, 30, ... ] for s2.
++             */
++            v_s1 = _mm_add_epi32(v_s1, _mm_sad_epu8(bytes1, zero));
++            const __m128i mad1 = _mm_maddubs_epi16(bytes1, tap1);
++            v_s2 = _mm_add_epi32(v_s2, _mm_madd_epi16(mad1, ones));
++
++            v_s1 = _mm_add_epi32(v_s1, _mm_sad_epu8(bytes2, zero));
++            const __m128i mad2 = _mm_maddubs_epi16(bytes2, tap2);
++            v_s2 = _mm_add_epi32(v_s2, _mm_madd_epi16(mad2, ones));
++
++            buf += BLOCK_SIZE;
++
++        } while (--n);
++
++        v_s2 = _mm_add_epi32(v_s2, _mm_slli_epi32(v_ps, 5));
++
++        /*
++         * Sum epi32 ints v_s1(s2) and accumulate in s1(s2).
++         */
++
++#define S23O1 _MM_SHUFFLE(2,3,0,1)  /* A B C D -> B A D C */
++#define S1O32 _MM_SHUFFLE(1,0,3,2)  /* A B C D -> C D A B */
++
++        v_s1 = _mm_add_epi32(v_s1, _mm_shuffle_epi32(v_s1, S23O1));
++        v_s1 = _mm_add_epi32(v_s1, _mm_shuffle_epi32(v_s1, S1O32));
++
++        s1 += _mm_cvtsi128_si32(v_s1);
++
++        v_s2 = _mm_add_epi32(v_s2, _mm_shuffle_epi32(v_s2, S23O1));
++        v_s2 = _mm_add_epi32(v_s2, _mm_shuffle_epi32(v_s2, S1O32));
++
++        s2 = _mm_cvtsi128_si32(v_s2);
++
++#undef S23O1
++#undef S1O32
++
++        /*
++         * Reduce.
++         */
++        s1 %= BASE;
++        s2 %= BASE;
++    }
++
++    /*
++     * Handle leftover data.
++     */
++    if (len) {
++        if (len >= 16) {
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++
++            len -= 16;
++        }
++
++        while (len--) {
++            s2 += (s1 += *buf++);
++        }
++
++        if (s1 >= BASE)
++            s1 -= BASE;
++        s2 %= BASE;
++    }
++
++    /*
++     * Return the recombined sums.
++     */
++    return s1 | (s2 << 16);
++}
++
++#elif defined(ADLER32_SIMD_NEON)
++
++#include <arm_neon.h>
++
++uint32_t ZLIB_INTERNAL adler32_simd_(  /* NEON */
++    uint32_t adler,
++    const unsigned char *buf,
++    z_size_t len)
++{
++    /*
++     * Split Adler-32 into component sums.
++     */
++    uint32_t s1 = adler & 0xffff;
++    uint32_t s2 = adler >> 16;
++
++    /*
++     * Serially compute s1 & s2, until the data is 16-byte aligned.
++     */
++    if ((uintptr_t)buf & 15) {
++        while ((uintptr_t)buf & 15) {
++            s2 += (s1 += *buf++);
++            --len;
++        }
++
++        if (s1 >= BASE)
++            s1 -= BASE;
++        s2 %= BASE;
++    }
++
++    /*
++     * Process the data in blocks.
++     */
++    const unsigned BLOCK_SIZE = 1 << 5;
++
++    z_size_t blocks = len / BLOCK_SIZE;
++    len -= blocks * BLOCK_SIZE;
++
++    while (blocks)
++    {
++        unsigned n = NMAX / BLOCK_SIZE;  /* The NMAX constraint. */
++        if (n > blocks)
++            n = blocks;
++        blocks -= n;
++
++        /*
++         * Process n blocks of data. At most NMAX data bytes can be
++         * processed before s2 must be reduced modulo BASE.
++         */
++        uint32x4_t v_s2 = (uint32x4_t) { 0, 0, 0, s1 * n };
++        uint32x4_t v_s1 = (uint32x4_t) { 0, 0, 0, 0 };
++
++        uint16x8_t v_column_sum_1 = vdupq_n_u16(0);
++        uint16x8_t v_column_sum_2 = vdupq_n_u16(0);
++        uint16x8_t v_column_sum_3 = vdupq_n_u16(0);
++        uint16x8_t v_column_sum_4 = vdupq_n_u16(0);
++
++        do {
++            /*
++             * Load 32 input bytes.
++             */
++            const uint8x16_t bytes1 = vld1q_u8((uint8_t*)(buf));
++            const uint8x16_t bytes2 = vld1q_u8((uint8_t*)(buf + 16));
++
++            /*
++             * Add previous block byte sum to v_s2.
++             */
++            v_s2 = vaddq_u32(v_s2, v_s1);
++
++            /*
++             * Horizontally add the bytes for s1.
++             */
++            v_s1 = vpadalq_u16(v_s1, vpadalq_u8(vpaddlq_u8(bytes1), bytes2));
++
++            /*
++             * Vertically add the bytes for s2.
++             */
++            v_column_sum_1 = vaddw_u8(v_column_sum_1, vget_low_u8 (bytes1));
++            v_column_sum_2 = vaddw_u8(v_column_sum_2, vget_high_u8(bytes1));
++            v_column_sum_3 = vaddw_u8(v_column_sum_3, vget_low_u8 (bytes2));
++            v_column_sum_4 = vaddw_u8(v_column_sum_4, vget_high_u8(bytes2));
++
++            buf += BLOCK_SIZE;
++
++        } while (--n);
++
++        v_s2 = vshlq_n_u32(v_s2, 5);
++
++        /*
++         * Multiply-add bytes by [ 32, 31, 30, ... ] for s2.
++         */
++        v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_1),
++            (uint16x4_t) { 32, 31, 30, 29 });
++        v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_1),
++            (uint16x4_t) { 28, 27, 26, 25 });
++        v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_2),
++            (uint16x4_t) { 24, 23, 22, 21 });
++        v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_2),
++            (uint16x4_t) { 20, 19, 18, 17 });
++        v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_3),
++            (uint16x4_t) { 16, 15, 14, 13 });
++        v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_3),
++            (uint16x4_t) { 12, 11, 10,  9 });
++        v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_4),
++            (uint16x4_t) {  8,  7,  6,  5 });
++        v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_4),
++            (uint16x4_t) {  4,  3,  2,  1 });
++
++        /*
++         * Sum epi32 ints v_s1(s2) and accumulate in s1(s2).
++         */
++        uint32x2_t sum1 = vpadd_u32(vget_low_u32(v_s1), vget_high_u32(v_s1));
++        uint32x2_t sum2 = vpadd_u32(vget_low_u32(v_s2), vget_high_u32(v_s2));
++        uint32x2_t s1s2 = vpadd_u32(sum1, sum2);
++
++        s1 += vget_lane_u32(s1s2, 0);
++        s2 += vget_lane_u32(s1s2, 1);
++
++        /*
++         * Reduce.
++         */
++        s1 %= BASE;
++        s2 %= BASE;
++    }
++
++    /*
++     * Handle leftover data.
++     */
++    if (len) {
++        if (len >= 16) {
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++            s2 += (s1 += *buf++);
++
++            len -= 16;
++        }
++
++        while (len--) {
++            s2 += (s1 += *buf++);
++        }
++
++        if (s1 >= BASE)
++            s1 -= BASE;
++        s2 %= BASE;
++    }
++
++    /*
++     * Return the recombined sums.
++     */
++    return s1 | (s2 << 16);
++}
++
++#endif  /* ADLER32_SIMD_SSSE3 */
+diff --git a/third_party/zlib/adler32_simd.h b/third_party/zlib/adler32_simd.h
+new file mode 100644
+index 000000000000..52bb14d16751
+--- /dev/null
++++ b/third_party/zlib/adler32_simd.h
+@@ -0,0 +1,16 @@
++/* adler32_simd.h
++ *
++ * 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 Chromium source repository LICENSE file.
++ */
++
++#include <stdint.h>
++
++#include "zconf.h"
++#include "zutil.h"
++
++uint32_t ZLIB_INTERNAL adler32_simd_(
++    uint32_t adler,
++    const unsigned char *buf,
++    z_size_t len);
+diff --git a/third_party/zlib/inflate.c b/third_party/zlib/inflate.c
+index 5c40cf1ee0ff..e84be468b8de 100644
+--- a/third_party/zlib/inflate.c
++++ b/third_party/zlib/inflate.c
+@@ -84,6 +84,7 @@
+ #include "inftrees.h"
+ #include "inflate.h"
+ #include "inffast.h"
++#include "x86.h"
+ 
+ #ifdef MAKEFIXED
+ #  ifndef BUILDFIXED
+@@ -201,6 +202,8 @@ int stream_size;
+     int ret;
+     struct inflate_state FAR *state;
+ 
++    x86_check_features();
++
+     if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+         stream_size != (int)(sizeof(z_stream)))
+         return Z_VERSION_ERROR;
+diff --git a/third_party/zlib/names.h b/third_party/zlib/names.h
+index 3436baa4eb57..cd98ec9940b6 100644
+--- a/third_party/zlib/names.h
++++ b/third_party/zlib/names.h
+@@ -162,6 +162,13 @@
+ #define fill_window_sse Cr_z_fill_window_sse
+ #define read_buf Cr_z_read_buf
+ #define x86_check_features Cr_z_x86_check_features
++/* FIXME: x86_cpu_enable_ssse3 wasn't part of the simd.patch */
++#define x86_cpu_enable_ssse3 Cr_z_x86_cpu_enable_ssse3
+ #define x86_cpu_enable_simd Cr_z_x86_cpu_enable_simd
+ 
++#if defined(ADLER32_SIMD_SSSE3) || defined(ADLER32_SIMD_NEON)
++/* Symbols added by adler_simd.c, see also the FIXME above */
++#define adler32_simd_ Cr_z_adler32_simd_
++#endif
++
+ #endif  /* THIRD_PARTY_ZLIB_NAMES_H_ */
+diff --git a/third_party/zlib/x86.c b/third_party/zlib/x86.c
+index e56fe8b85a39..7488ad08b976 100644
+--- a/third_party/zlib/x86.c
++++ b/third_party/zlib/x86.c
+@@ -4,13 +4,14 @@
+  * Copyright (C) 2013 Intel Corporation. All rights reserved.
+  * Author:
+  *  Jim Kukunas
+- * 
++ *
+  * For conditions of distribution and use, see copyright notice in zlib.h
+  */
+ 
+ #include "x86.h"
+ #include "zutil.h"
+ 
++int ZLIB_INTERNAL x86_cpu_enable_ssse3 = 0;
+ int ZLIB_INTERNAL x86_cpu_enable_simd = 0;
+ 
+ #ifndef _MSC_VER
+@@ -27,6 +28,7 @@ void x86_check_features(void)
+ static void _x86_check_features(void)
+ {
+     int x86_cpu_has_sse2;
++    int x86_cpu_has_ssse3;
+     int x86_cpu_has_sse42;
+     int x86_cpu_has_pclmulqdq;
+     unsigned eax, ebx, ecx, edx;
+@@ -47,9 +49,12 @@ static void _x86_check_features(void)
+ #endif  /* (__i386__) */
+ 
+     x86_cpu_has_sse2 = edx & 0x4000000;
++    x86_cpu_has_ssse3 = ecx & 0x000200;
+     x86_cpu_has_sse42 = ecx & 0x100000;
+     x86_cpu_has_pclmulqdq = ecx & 0x2;
+ 
++    x86_cpu_enable_ssse3 = x86_cpu_has_ssse3;
++
+     x86_cpu_enable_simd = x86_cpu_has_sse2 &&
+                           x86_cpu_has_sse42 &&
+                           x86_cpu_has_pclmulqdq;
+@@ -74,6 +79,7 @@ static BOOL CALLBACK _x86_check_features(PINIT_ONCE once,
+                                          PVOID *context)
+ {
+     int x86_cpu_has_sse2;
++    int x86_cpu_has_ssse3;
+     int x86_cpu_has_sse42;
+     int x86_cpu_has_pclmulqdq;
+     int regs[4];
+@@ -81,9 +87,12 @@ static BOOL CALLBACK _x86_check_features(PINIT_ONCE once,
+     __cpuid(regs, 1);
+ 
+     x86_cpu_has_sse2 = regs[3] & 0x4000000;
+-    x86_cpu_has_sse42= regs[2] & 0x100000;
++    x86_cpu_has_ssse3 = regs[2] & 0x000200;
++    x86_cpu_has_sse42 = regs[2] & 0x100000;
+     x86_cpu_has_pclmulqdq = regs[2] & 0x2;
+ 
++    x86_cpu_enable_ssse3 = x86_cpu_has_ssse3;
++
+     x86_cpu_enable_simd = x86_cpu_has_sse2 &&
+                           x86_cpu_has_sse42 &&
+                           x86_cpu_has_pclmulqdq;
+diff --git a/third_party/zlib/x86.h b/third_party/zlib/x86.h
+index ebcf10ab09d2..7205d50265c3 100644
+--- a/third_party/zlib/x86.h
++++ b/third_party/zlib/x86.h
+@@ -8,6 +8,7 @@
+ 
+ #include "zlib.h"
+ 
++extern int x86_cpu_enable_ssse3;
+ extern int x86_cpu_enable_simd;
+ 
+ void x86_check_features(void);
+-- 
+2.14.0.rc1.383.gd1ce394fe2-goog
+
diff --git a/third_party/zlib/patches/README b/third_party/zlib/patches/README
index 350ca655..687842c 100644
--- a/third_party/zlib/patches/README
+++ b/third_party/zlib/patches/README
@@ -4,9 +4,6 @@
    build.
  - 0001-simd.patch: integrate Intel SIMD optimizations from
    https://github.com/jtkukunas/zlib/
- - 0002-uninitializedcheck.patch: default-initialize state->check, see
-   crbug.com/697481
- - 0003-use-defines-for-inffast.patch: replace magic numbers with defines.
 
 == Procedure to create a patch file ==
 
diff --git a/third_party/zlib/x86.c b/third_party/zlib/x86.c
index e56fe8b..7488ad0 100644
--- a/third_party/zlib/x86.c
+++ b/third_party/zlib/x86.c
@@ -4,13 +4,14 @@
  * Copyright (C) 2013 Intel Corporation. All rights reserved.
  * Author:
  *  Jim Kukunas
- * 
+ *
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
 #include "x86.h"
 #include "zutil.h"
 
+int ZLIB_INTERNAL x86_cpu_enable_ssse3 = 0;
 int ZLIB_INTERNAL x86_cpu_enable_simd = 0;
 
 #ifndef _MSC_VER
@@ -27,6 +28,7 @@
 static void _x86_check_features(void)
 {
     int x86_cpu_has_sse2;
+    int x86_cpu_has_ssse3;
     int x86_cpu_has_sse42;
     int x86_cpu_has_pclmulqdq;
     unsigned eax, ebx, ecx, edx;
@@ -47,9 +49,12 @@
 #endif  /* (__i386__) */
 
     x86_cpu_has_sse2 = edx & 0x4000000;
+    x86_cpu_has_ssse3 = ecx & 0x000200;
     x86_cpu_has_sse42 = ecx & 0x100000;
     x86_cpu_has_pclmulqdq = ecx & 0x2;
 
+    x86_cpu_enable_ssse3 = x86_cpu_has_ssse3;
+
     x86_cpu_enable_simd = x86_cpu_has_sse2 &&
                           x86_cpu_has_sse42 &&
                           x86_cpu_has_pclmulqdq;
@@ -74,6 +79,7 @@
                                          PVOID *context)
 {
     int x86_cpu_has_sse2;
+    int x86_cpu_has_ssse3;
     int x86_cpu_has_sse42;
     int x86_cpu_has_pclmulqdq;
     int regs[4];
@@ -81,9 +87,12 @@
     __cpuid(regs, 1);
 
     x86_cpu_has_sse2 = regs[3] & 0x4000000;
-    x86_cpu_has_sse42= regs[2] & 0x100000;
+    x86_cpu_has_ssse3 = regs[2] & 0x000200;
+    x86_cpu_has_sse42 = regs[2] & 0x100000;
     x86_cpu_has_pclmulqdq = regs[2] & 0x2;
 
+    x86_cpu_enable_ssse3 = x86_cpu_has_ssse3;
+
     x86_cpu_enable_simd = x86_cpu_has_sse2 &&
                           x86_cpu_has_sse42 &&
                           x86_cpu_has_pclmulqdq;
diff --git a/third_party/zlib/x86.h b/third_party/zlib/x86.h
index ebcf10a..7205d50 100644
--- a/third_party/zlib/x86.h
+++ b/third_party/zlib/x86.h
@@ -8,6 +8,7 @@
 
 #include "zlib.h"
 
+extern int x86_cpu_enable_ssse3;
 extern int x86_cpu_enable_simd;
 
 void x86_check_features(void);
diff --git a/tools/OWNERS b/tools/OWNERS
index 945ca919..c18ff577 100644
--- a/tools/OWNERS
+++ b/tools/OWNERS
@@ -40,7 +40,6 @@
 per-file ipc_messages_log.py=yfriedman@chromium.org
 
 per-file licenses.py=phajdan.jr@chromium.org
-per-file licenses.py=sgurun@chromium.org
 per-file licenses.py=torne@chromium.org
 
 per-file remove_stale_pyc_files.py=dtu@chromium.org
diff --git a/tools/binary_size/diagnose_bloat.py b/tools/binary_size/diagnose_bloat.py
index 8b354ce..1c76309 100755
--- a/tools/binary_size/diagnose_bloat.py
+++ b/tools/binary_size/diagnose_bloat.py
@@ -315,13 +315,15 @@
 
 class _BuildArchive(object):
   """Class for managing a directory with build results and build metadata."""
-  def __init__(self, rev, base_archive_dir, build, subrepo, slow_options):
+  def __init__(self, rev, base_archive_dir, build, subrepo, slow_options,
+               save_unstripped):
     self.build = build
     self.dir = os.path.join(base_archive_dir, rev)
     metadata_path = os.path.join(self.dir, 'metadata.txt')
     self.rev = rev
     self.metadata = _Metadata([self], build, metadata_path, subrepo)
     self._slow_options = slow_options
+    self._save_unstripped = save_unstripped
 
   def ArchiveBuildResults(self, supersize_path):
     """Save build artifacts necessary for diffing."""
@@ -332,10 +334,24 @@
       self._ArchiveFile(self.build.abs_apk_path + '.mapping')
       self._ArchiveResourceSizes()
     self._ArchiveSizeFile(supersize_path)
+    if self._save_unstripped:
+      self._ArchiveFile(self.build.abs_main_lib_path)
     self.metadata.Write()
+    assert self.Exists()
 
   def Exists(self):
-    return self.metadata.Exists()
+    ret = self.metadata.Exists() and os.path.exists(self.archived_size_path)
+    if self._save_unstripped:
+      ret = ret and os.path.exists(self.archived_unstripped_path)
+    return ret
+
+  @property
+  def archived_unstripped_path(self):
+    return os.path.join(self.dir, os.path.basename(self.build.main_lib_path))
+
+  @property
+  def archived_size_path(self):
+    return os.path.join(self.dir, self.build.size_name)
 
   def _ArchiveResourceSizes(self):
     cmd = [_RESOURCE_SIZES_PATH, self.build.abs_apk_path,'--output-dir',
@@ -355,12 +371,10 @@
     existing_size_file = self.build.abs_apk_path + '.size'
     if os.path.exists(existing_size_file):
       logging.info('Found existing .size file')
-      os.rename(
-          existing_size_file, os.path.join(self.dir, self.build.size_name))
+      shutil.copy(existing_size_file, self.archived_size_path)
     else:
-      size_path = os.path.join(self.dir, self.build.size_name)
-      supersize_cmd = [supersize_path, 'archive', size_path, '--elf-file',
-                       self.build.abs_main_lib_path]
+      supersize_cmd = [supersize_path, 'archive', self.archived_size_path,
+                       '--elf-file', self.build.abs_main_lib_path]
       if self.build.IsCloud():
         supersize_cmd += ['--no-source-paths']
       else:
@@ -373,11 +387,13 @@
 
 class _DiffArchiveManager(object):
   """Class for maintaining BuildArchives and their related diff artifacts."""
-  def __init__(self, revs, archive_dir, diffs, build, subrepo, slow_options):
+  def __init__(self, revs, archive_dir, diffs, build, subrepo, slow_options,
+               save_unstripped):
     self.archive_dir = archive_dir
     self.build = build
     self.build_archives = [
-        _BuildArchive(rev, archive_dir, build, subrepo, slow_options)
+        _BuildArchive(rev, archive_dir, build, subrepo, slow_options,
+                      save_unstripped)
         for rev in revs
     ]
     self.diffs = diffs
@@ -410,18 +426,10 @@
       with open(diff_path, 'a') as diff_file:
         for d in self.diffs:
           d.RunDiff(diff_file, before.dir, after.dir)
-        logging.info('See detailed diff results here: %s',
-                     os.path.relpath(diff_path))
-        if len(self.build_archives) == 2:
-          supersize_path = os.path.join(_BINARY_SIZE_DIR, 'supersize')
-          size_paths = [os.path.join(a.dir, a.build.size_name)
-                        for a in self.build_archives]
-          logging.info('Enter supersize console via: %s console %s %s',
-                       os.path.relpath(supersize_path),
-                       os.path.relpath(size_paths[0]),
-                       os.path.relpath(size_paths[1]))
       metadata.Write()
       self._AddDiffSummaryStat(before, after)
+    logging.info('See detailed diff results here: %s',
+                 os.path.relpath(diff_path))
 
   def Summarize(self):
     if self._summary_stats:
@@ -433,11 +441,14 @@
         for s, before, after in stats:
           _PrintAndWriteToFile(f, '{:>+10} {} {} for range: {}..{}',
                                s.value, s.units, s.name, before, after)
-    elif self.build_archives:
+    if self.build_archives:
       supersize_path = os.path.join(_BINARY_SIZE_DIR, 'supersize')
-      size_path = os.path.join(self.build_archives[0].dir, self.build.size_name)
-      logging.info('Enter supersize console via: %s console %s',
-                   os.path.relpath(supersize_path), os.path.relpath(size_path))
+      size2 = ''
+      if len(self.build_archives) > 1:
+        size2 = os.path.relpath(self.build_archives[-1].archived_size_path)
+      logging.info('Enter supersize console via: %s console %s %s',
+          os.path.relpath(supersize_path),
+          os.path.relpath(self.build_archives[0].archived_size_path), size2)
 
 
   def _AddDiffSummaryStat(self, before, after):
@@ -756,6 +767,9 @@
   parser.add_argument('--single',
                       action='store_true',
                       help='Sets --reference-rev=rev')
+  parser.add_argument('--unstripped',
+                      action='store_true',
+                      help='Save the unstripped native library when archiving.')
   parser.add_argument('--depot-tools-path',
                       help='Custom path to depot tools. Needed for --cloud if '
                            'depot tools isn\'t in your PATH.')
@@ -836,7 +850,8 @@
           ResourceSizesDiff(build.apk_name)
       ]
     diff_mngr = _DiffArchiveManager(revs, args.archive_directory, diffs, build,
-                                    subrepo, args.include_slow_options)
+                                    subrepo, args.include_slow_options,
+                                    args.unstripped)
     consecutive_failures = 0
     for i, archive in enumerate(diff_mngr.IterArchives()):
       if archive.Exists():
diff --git a/tools/binary_size/libsupersize/describe.py b/tools/binary_size/libsupersize/describe.py
index b3857b75..3879327d 100644
--- a/tools/binary_size/libsupersize/describe.py
+++ b/tools/binary_size/libsupersize/describe.py
@@ -9,6 +9,7 @@
 import csv
 import datetime
 import itertools
+import math
 import time
 
 import models
@@ -75,6 +76,55 @@
   return (total_bytes, section_names)
 
 
+class Histogram(object):
+  BUCKET_NAMES_FOR_SMALL_VALUES = {-1: '(-1,0)', 0: '{0}', 1: '(0,1)'}
+
+  def __init__(self):
+    self.data = collections.defaultdict(int)
+
+  # Input:  (-8,-4], (-4,-2], (-2,-1], (-1,0), {0}, (0,1), [1,2), [2,4), [4,8).
+  # Output:   -4,      -3,      -2,      -1,    0,    1,     2,     3,     4.
+  @staticmethod
+  def _Bucket(v):
+    absv = abs(v)
+    if absv < 1:
+      return 0 if v == 0 else (-1 if v < 0 else 1)
+    mag = int(math.log(absv, 2.0)) + 2
+    return mag if v > 0 else -mag
+
+  @staticmethod
+  def _BucketName(k):
+    if abs(k) <= 1:
+      return Histogram.BUCKET_NAMES_FOR_SMALL_VALUES[k]
+    if k < 0:
+      return '(-{},-{}]'.format(1 << (-k - 1), 1 << (-k - 2))
+    return '[{},{})'.format(1 << (k - 2), 1 << (k - 1))
+
+  def Add(self, v):
+    self.data[self._Bucket(v)] += 1
+
+  def Generate(self):
+    keys = sorted(self.data.keys())
+    bucket_names = [self._BucketName(k) for k in keys]
+    bucket_values = [str(self.data[k]) for k in keys]
+    num_items = len(keys)
+    num_cols = 6
+    num_rows = (num_items + num_cols - 1) / num_cols  # Divide and round up.
+    # Spaces needed by items in each column, to align on ':'.
+    name_col_widths = []
+    value_col_widths = []
+    for i in xrange(0, num_items, num_rows):
+      name_col_widths.append(max(len(s) for s in bucket_names[i:][:num_rows]))
+      value_col_widths.append(max(len(s) for s in bucket_values[i:][:num_rows]))
+
+    yield 'Histogram of symbols based on PSS:'
+    for r in xrange(num_rows):
+      row = zip(bucket_names[r::num_rows], name_col_widths,
+                bucket_values[r::num_rows], value_col_widths)
+      line = '    ' + '   '.join('{:>{}}: {:<{}}'.format(*t) for t in row)
+      yield line.rstrip()
+
+
 class Describer(object):
   def __init__(self):
     pass
@@ -242,6 +292,9 @@
       section_sizes = collections.defaultdict(float)
       for s in group.IterLeafSymbols():
         section_sizes[s.section_name] += s.pss
+      histogram = Histogram()
+      for s in group:
+        histogram.Add(s.pss)
 
     # Apply this filter after calcualating size since an alias being removed
     # causes some symbols to be UNCHANGED, yet have pss != 0.
@@ -275,14 +328,15 @@
           '{}={}'.format(models.SECTION_NAME_TO_SECTION[k], k)
           for k in relevant_sections if k in models.SECTION_NAME_TO_SECTION)
 
-      summary_desc = [
-          'Showing {:,} symbols ({}) with total pss: {} bytes'.format(
-              len(group), unique_part, int(total_size)),
-          size_summary,
-          'Number of unique paths: {}'.format(len(unique_paths)),
-          '',
-          'Section Legend: {}'.format(section_legend),
-      ]
+      summary_desc = itertools.chain(
+          ['Showing {:,} symbols ({}) with total pss: {} bytes'.format(
+              len(group), unique_part, int(total_size))],
+          histogram.Generate(),
+          [size_summary.rstrip()],
+          ['Number of unique paths: {}'.format(len(unique_paths))],
+          [''],
+          ['Section Legend: {}'.format(section_legend)],
+      )
     else:
       summary_desc = ()
 
@@ -339,6 +393,12 @@
       header_template = ('{} symbols added (+), {} changed (~), '
                          '{} removed (-), {} unchanged ({})')
       unchanged_msg = '=' if self.verbose else 'not shown'
+      # Apply this filter since an alias being removed causes some symbols to be
+      # UNCHANGED, yet have pss != 0.
+      changed_delta_group = delta_group.WhereDiffStatusIs(
+          models.DIFF_STATUS_UNCHANGED).Inverted()
+      num_inc = sum(1 for s in changed_delta_group if s.pss > 0)
+      num_dec = sum(1 for s in changed_delta_group if s.pss < 0)
       counts = delta_group.CountsByDiffStatus()
       num_unique_before_symbols, num_unique_after_symbols = (
           delta_group.CountUniqueSymbols())
@@ -349,6 +409,7 @@
               counts[models.DIFF_STATUS_REMOVED],
               counts[models.DIFF_STATUS_UNCHANGED],
               unchanged_msg),
+          'Of changed symbols, {} grew, {} shrank'.format(num_inc, num_dec),
           'Number of unique symbols {} -> {} ({:+})'.format(
               num_unique_before_symbols, num_unique_after_symbols,
               num_unique_after_symbols - num_unique_before_symbols),
diff --git a/tools/binary_size/libsupersize/testdata/Console.golden b/tools/binary_size/libsupersize/testdata/Console.golden
index 1e5fa7e..6b92971 100644
--- a/tools/binary_size/libsupersize/testdata/Console.golden
+++ b/tools/binary_size/libsupersize/testdata/Console.golden
@@ -75,6 +75,10 @@
     .text: 34.2mb (35900712 bytes) (35.8%)
 
 Showing 45 symbols (42 unique) with total pss: 43785380 bytes
+Histogram of symbols based on PSS:
+      [4,8): 9     [32,64): 9        [256,512): 1    [131072,262144): 2     [1048576,2097152): 1
+     [8,16): 3    [64,128): 1      [2048,4096): 1    [262144,524288): 1     [2097152,4194304): 2
+    [16,32): 9   [128,256): 2   [65536,131072): 2   [524288,1048576): 1   [33554432,67108864): 1
 .text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      total=41.8mb
 Number of unique paths: 9
 
diff --git a/tools/binary_size/libsupersize/testdata/Diff_Basic.golden b/tools/binary_size/libsupersize/testdata/Diff_Basic.golden
index 8ab6fc1a..8b18420 100644
--- a/tools/binary_size/libsupersize/testdata/Diff_Basic.golden
+++ b/tools/binary_size/libsupersize/testdata/Diff_Basic.golden
@@ -39,13 +39,16 @@
     .symtab: 0 bytes (0 bytes)
 
 0 symbols added (+), 1 changed (~), 0 removed (-), 40 unchanged (=)
+Of changed symbols, 1 grew, 0 shrank
 Number of unique symbols 46 -> 46 (+0)
 0 paths added, 0 removed, 1 changed
 Changed files:
   base/page_allocator.cc
 
 Showing 41 symbols (aliases not grouped for diffs) with total pss: 10 bytes
-.text=10 bytes   .rodata=0 bytes    .data.rel.ro=0 bytes    .data=0 bytes    .bss=0 bytes    total=10 bytes  
+Histogram of symbols based on PSS:
+    {0}: 40   [8,16): 1
+.text=10 bytes   .rodata=0 bytes    .data.rel.ro=0 bytes    .data=0 bytes    .bss=0 bytes    total=10 bytes
 Number of unique paths: 9
 
 Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss
diff --git a/tools/binary_size/libsupersize/testdata/Diff_NullDiff.golden b/tools/binary_size/libsupersize/testdata/Diff_NullDiff.golden
index e95b0c7..0336725 100644
--- a/tools/binary_size/libsupersize/testdata/Diff_NullDiff.golden
+++ b/tools/binary_size/libsupersize/testdata/Diff_NullDiff.golden
@@ -19,11 +19,14 @@
     .text: 0 bytes (0 bytes) (0.0%)
 
 0 symbols added (+), 0 changed (~), 0 removed (-), 45 unchanged (not shown)
+Of changed symbols, 0 grew, 0 shrank
 Number of unique symbols 46 -> 46 (+0)
 0 paths added, 0 removed, 0 changed
 
 Showing 0 symbols (aliases not grouped for diffs) with total pss: 0 bytes
-.text=0 bytes    .rodata=0 bytes    .data.rel.ro=0 bytes    .data=0 bytes    .bss=0 bytes    total=0 bytes   
+Histogram of symbols based on PSS:
+    {0}: 45
+.text=0 bytes    .rodata=0 bytes    .data.rel.ro=0 bytes    .data=0 bytes    .bss=0 bytes    total=0 bytes
 Number of unique paths: 0
 
 Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss
diff --git a/tools/binary_size/libsupersize/testdata/FullDescription.golden b/tools/binary_size/libsupersize/testdata/FullDescription.golden
index dbfcade..d9ebac9 100644
--- a/tools/binary_size/libsupersize/testdata/FullDescription.golden
+++ b/tools/binary_size/libsupersize/testdata/FullDescription.golden
@@ -62,7 +62,11 @@
 * 0 symbols have shared ownership
 
 Showing 49 symbols (46 unique) with total pss: 43785380 bytes
-.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      total=41.8mb    
+Histogram of symbols based on PSS:
+     [2,4): 1    [16,32): 9     [128,256): 2       [4096,8192): 1     [262144,524288): 1     [2097152,4194304): 1
+     [4,8): 9    [32,64): 9     [256,512): 1    [65536,131072): 2    [524288,1048576): 2   [33554432,67108864): 1
+    [8,16): 3   [64,128): 1   [2048,4096): 2   [131072,262144): 2   [1048576,2097152): 2
+.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      total=41.8mb
 Number of unique paths: 9
 
 Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss
@@ -227,7 +231,11 @@
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={anon,gen}  name=g_AnimationFrameTimeHistogram_clazz
 Showing 45 symbols (42 unique) with total pss: 43785380 bytes
-.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      total=41.8mb    
+Histogram of symbols based on PSS:
+      [4,8): 9     [32,64): 9        [256,512): 1    [131072,262144): 2     [1048576,2097152): 1
+     [8,16): 3    [64,128): 1      [2048,4096): 1    [262144,524288): 1     [2097152,4194304): 2
+    [16,32): 9   [128,256): 2   [65536,131072): 2   [524288,1048576): 1   [33554432,67108864): 1
+.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      total=41.8mb
 Number of unique paths: 9
 
 Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss
diff --git a/tools/binary_size/libsupersize/testdata/SymbolGroupMethods.golden b/tools/binary_size/libsupersize/testdata/SymbolGroupMethods.golden
index f1c472b..4c2489e 100644
--- a/tools/binary_size/libsupersize/testdata/SymbolGroupMethods.golden
+++ b/tools/binary_size/libsupersize/testdata/SymbolGroupMethods.golden
@@ -1,6 +1,10 @@
 GroupedByName()
 Showing 41 symbols (41 unique) with total pss: 43785380 bytes
-.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      total=41.8mb    
+Histogram of symbols based on PSS:
+       {0}: 6    [16,32): 8     [128,256): 1      [65536,131072): 1     [2097152,4194304): 1
+     [4,8): 7    [32,64): 7     [256,512): 1    [524288,1048576): 1   [33554432,67108864): 1
+    [8,16): 3   [64,128): 2   [2048,4096): 1   [1048576,2097152): 1
+.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      total=41.8mb
 Number of unique paths: 9
 
 Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss
@@ -49,7 +53,11 @@
 40)  43785380 (100.0%) *@Group      0               g_AnimationFrameTimeHistogram_clazz (count=1)
 GroupedByName(depth=1)
 Showing 33 symbols (33 unique) with total pss: 43785380 bytes
-.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      total=41.8mb    
+Histogram of symbols based on PSS:
+       {0}: 6    [16,32): 5     [128,256): 2      [65536,131072): 1     [2097152,4194304): 1
+     [4,8): 2    [32,64): 6     [256,512): 1    [524288,1048576): 1   [33554432,67108864): 1
+    [8,16): 4   [64,128): 1   [2048,4096): 1   [1048576,2097152): 1
+.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      total=41.8mb
 Number of unique paths: 9
 
 Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss
@@ -90,7 +98,11 @@
 32)  43785380 (100.0%) *@Group      0               g_AnimationFrameTimeHistogram_clazz (count=1)
 GroupedByName(depth=-1)
 Showing 36 symbols (36 unique) with total pss: 43785380 bytes
-.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      total=41.8mb    
+Histogram of symbols based on PSS:
+       {0}: 6    [16,32): 5     [128,256): 1      [65536,131072): 1     [2097152,4194304): 1
+     [4,8): 3    [32,64): 8     [256,512): 1    [524288,1048576): 1   [33554432,67108864): 1
+    [8,16): 4   [64,128): 2   [2048,4096): 1   [1048576,2097152): 1
+.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      total=41.8mb
 Number of unique paths: 9
 
 Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss
@@ -134,7 +146,11 @@
 35)  43785380 (100.0%) *@Group      0               g_AnimationFrameTimeHistogram_clazz (count=1)
 GroupedByName(depth=1, min_count=2)
 Showing 33 symbols (32 unique) with total pss: 43785380 bytes
-.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      total=41.8mb    
+Histogram of symbols based on PSS:
+      [4,8): 3     [32,64): 6        [256,512): 1    [131072,262144): 2     [1048576,2097152): 1
+     [8,16): 4    [64,128): 1      [2048,4096): 1    [262144,524288): 1     [2097152,4194304): 1
+    [16,32): 6   [128,256): 3   [65536,131072): 1   [524288,1048576): 1   [33554432,67108864): 1
+.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      total=41.8mb
 Number of unique paths: 9
 
 Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss
diff --git a/tools/grit/grit/tool/build.py b/tools/grit/grit/tool/build.py
index 13a02ed..f409c95 100755
--- a/tools/grit/grit/tool/build.py
+++ b/tools/grit/grit/tool/build.py
@@ -334,7 +334,11 @@
     outfile.writelines(formatted)
     if output_node.GetType() == 'data_package':
       with open(output_node.GetOutputFilename() + '.info', 'w') as infofile:
-        infofile.writelines('\n'.join(node.info))
+        if node.info:
+          # We terminate with a newline so that when these files are
+          # concatenated later we consistently terminate with a newline so
+          # consumers can account for terminating newlines.
+          infofile.writelines(['\n'.join(node.info), '\n'])
 
 
   def Process(self):
diff --git a/tools/idl_parser/idl_parser_test.py b/tools/idl_parser/idl_parser_test.py
index f9d0edf..6aeabd4 100755
--- a/tools/idl_parser/idl_parser_test.py
+++ b/tools/idl_parser/idl_parser_test.py
@@ -4,6 +4,7 @@
 # found in the LICENSE file.
 
 import glob
+import os
 import unittest
 
 from idl_lexer import IDLLexer
@@ -20,7 +21,9 @@
 
   def setUp(self):
     self.parser = IDLParser(IDLLexer(), mute_error=True)
-    self.filenames = glob.glob('test_parser/*_web.idl')
+    test_dir = os.path.abspath(
+        os.path.join(os.path.dirname(__file__), 'test_parser'))
+    self.filenames = glob.glob('%s/*_web.idl' % test_dir)
 
   def _TestNode(self, node):
     comments = node.GetListOf('SpecialComment')
diff --git a/tools/idl_parser/test_parser/interface_web.idl b/tools/idl_parser/test_parser/interface_web.idl
index b85977d..589a47c 100644
--- a/tools/idl_parser/test_parser/interface_web.idl
+++ b/tools/idl_parser/test_parser/interface_web.idl
@@ -555,3 +555,70 @@
   void voidMethodTestArgumentWithExtAttribute1([Clamp, XAttr] long long myLong);
   void voidMethodTestArgumentWithExtAttribute2([EnforceRange] long longArg);
 };
+
+/** TREE
+ *Interface(InterfaceConstructors)
+ *  ExtAttributes()
+ *    ExtAttribute(Constructor)
+ *    ExtAttribute(Constructor)
+ *      Arguments()
+ *        Argument(doubleArg)
+ *          Type()
+ *            PrimitiveType(double)
+ *    ExtAttribute(CustomConstructor)
+ *    ExtAttribute(CustomConstructor)
+ *      Arguments()
+ *        Argument(doubleArg)
+ *          Type()
+ *            PrimitiveType(double)
+ *    ExtAttribute(NamedConstructor) = "Audio"
+ *    ExtAttribute(NamedConstructor)
+ *      Call(Audio)
+ *        Arguments()
+ *          Argument(src)
+ *            Type()
+ *              StringType(DOMString)
+ */
+[
+    Constructor,
+    Constructor(double doubleArg),
+    CustomConstructor,
+    CustomConstructor(double doubleArg),
+    NamedConstructor=Audio,
+    NamedConstructor=Audio(DOMString src)
+] interface InterfaceConstructors { };
+
+/** TREE
+ *Interface(InterfaceExposed)
+ *  ExtAttributes()
+ *    ExtAttribute(Exposed) = "Window"
+ *    ExtAttribute(Exposed) = "['Window', 'Worker']"
+ *    ExtAttribute(Exposed)
+ *      Arguments()
+ *        Argument(Feature1)
+ *          Type()
+ *            Typeref(Window)
+ *    ExtAttribute(Exposed)
+ *      Arguments()
+ *        Argument(Feature1)
+ *          Type()
+ *            Typeref(Window)
+ *        Argument(Feature2)
+ *          Type()
+ *            Typeref(Worker)
+ */
+[
+    Exposed=Window,
+    Exposed=(Window, Worker),
+    Exposed(Window Feature1),
+    Exposed(Window Feature1, Worker Feature2)
+] interface InterfaceExposed { };
+
+/** TREE
+ *Interface(InterfaceExposedError)
+ *  ExtAttributes()
+ *    ExtAttribute(Exposed)
+ *      Arguments()
+ *        Error(Unexpected ,.)
+ */
+[ Exposed(Window, Worker) ] interface InterfaceExposedError { };
diff --git a/tools/ipc_fuzzer/message_lib/BUILD.gn b/tools/ipc_fuzzer/message_lib/BUILD.gn
index a947294e..ce870ac 100644
--- a/tools/ipc_fuzzer/message_lib/BUILD.gn
+++ b/tools/ipc_fuzzer/message_lib/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/features.gni")
+import("//components/nacl/features.gni")
 import("//remoting/remoting_enable.gni")
 
 static_library("ipc_message_lib") {
diff --git a/tools/json_schema_compiler/cpp_bundle_generator.py b/tools/json_schema_compiler/cpp_bundle_generator.py
index a6531b0..620b3f191 100644
--- a/tools/json_schema_compiler/cpp_bundle_generator.py
+++ b/tools/json_schema_compiler/cpp_bundle_generator.py
@@ -290,9 +290,6 @@
 
   def Generate(self, _):  # namespace not relevant, this is a bundle
     c = code.Code()
-    c.Append('#include <map>')
-    c.Append('#include <string>')
-    c.Append()
     c.Append('#include "base/strings/string_piece.h"')
     c.Append()
     c.Concat(cpp_util.OpenNamespace(self._bundle._cpp_namespace))
@@ -301,10 +298,10 @@
              self._bundle._GenerateBundleClass('GeneratedSchemas'))
     c.Sblock(' public:')
     c.Append('// Determines if schema named |name| is generated.')
-    c.Append('static bool IsGenerated(std::string name);')
+    c.Append('static bool IsGenerated(base::StringPiece name);')
     c.Append()
     c.Append('// Gets the API schema named |name|.')
-    c.Append('static base::StringPiece Get(const std::string& name);')
+    c.Append('static base::StringPiece Get(base::StringPiece name);')
     c.Eblock('};')
     c.Append()
     c.Concat(cpp_util.CloseNamespace(self._bundle._cpp_namespace))
@@ -332,8 +329,6 @@
     c.Append('#include "%s"' % (os.path.join(self._bundle._source_file_dir,
                                              'generated_schemas.h')))
     c.Append()
-    c.Append('#include "base/lazy_instance.h"')
-    c.Append()
     c.Append('namespace {')
     for api in self._bundle._api_defs:
       namespace = self._bundle._model.namespaces[api.get('namespace')]
@@ -350,35 +345,37 @@
                   for i in xrange(0, len(json_content), max_length)]
       c.Append('const char %s[] = "%s";' %
           (_FormatNameAsConstant(namespace.name), '" "'.join(segments)))
-    c.Append()
-    c.Sblock('struct Static {')
-    c.Sblock('Static() {')
-    for api in self._bundle._api_defs:
-      namespace = self._bundle._model.namespaces[api.get('namespace')]
-      c.Append('schemas["%s"] = %s;' % (namespace.name,
-                                        _FormatNameAsConstant(namespace.name)))
-    c.Eblock('}')
-    c.Append()
-    c.Append('std::map<std::string, const char*> schemas;')
-    c.Eblock('};')
-    c.Append()
-    c.Append('base::LazyInstance<Static>::DestructorAtExit g_lazy_instance;')
-    c.Append()
     c.Append('}  // namespace')
     c.Append()
     c.Concat(cpp_util.OpenNamespace(self._bundle._cpp_namespace))
     c.Append()
     c.Append('// static')
-    c.Sblock('base::StringPiece %s::Get(const std::string& name) {' %
+    c.Sblock('bool %s::IsGenerated(base::StringPiece name) {' %
              self._bundle._GenerateBundleClass('GeneratedSchemas'))
-    c.Append('return IsGenerated(name) ? '
-             'g_lazy_instance.Get().schemas[name] : "";')
+    c.Append('return !Get(name).empty();')
     c.Eblock('}')
     c.Append()
     c.Append('// static')
-    c.Sblock('bool %s::IsGenerated(std::string name) {' %
+    c.Sblock('base::StringPiece %s::Get(base::StringPiece name) {' %
              self._bundle._GenerateBundleClass('GeneratedSchemas'))
-    c.Append('return g_lazy_instance.Get().schemas.count(name) > 0;')
+    c.Append('static const struct {')
+    c.Append('  base::StringPiece name;')
+    c.Append('  base::StringPiece schema;')
+    c.Sblock('} kSchemas[] = {')
+    namespaces = [self._bundle._model.namespaces[api.get('namespace')].name
+                  for api in self._bundle._api_defs]
+    for namespace in sorted(namespaces):
+      schema_constant_name = _FormatNameAsConstant(namespace)
+      c.Append('{{"%s", %d}, {%s, sizeof(%s) - 1}},' %
+               (namespace, len(namespace),
+                schema_constant_name, schema_constant_name))
+    c.Eblock('};')
+    c.Sblock('for (const auto& schema : kSchemas) {')
+    c.Sblock('if (schema.name == name)')
+    c.Append('return schema.schema;')
+    c.Eblock()
+    c.Eblock('}')
+    c.Append('return base::StringPiece();')
     c.Eblock('}')
     c.Append()
     c.Concat(cpp_util.CloseNamespace(self._bundle._cpp_namespace))
diff --git a/tools/json_schema_compiler/test/features_generation_unittest.cc b/tools/json_schema_compiler/test/features_generation_unittest.cc
index 81ab003..37387a3 100644
--- a/tools/json_schema_compiler/test/features_generation_unittest.cc
+++ b/tools/json_schema_compiler/test/features_generation_unittest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/optional.h"
 #include "extensions/common/features/complex_feature.h"
 #include "extensions/common/features/feature.h"
 #include "extensions/common/features/simple_feature.h"
@@ -21,9 +22,6 @@
   EXPECT_EQ(expected, actual) << name;
 }
 
-SimpleFeature::Location kDefaultLocation = SimpleFeature::UNSPECIFIED_LOCATION;
-const int kDefaultMinVersion = 0;
-const int kDefaultMaxVersion = 0;
 const bool kDefaultAutoGrant = true;
 const bool kDefaultInternal = false;
 
@@ -44,23 +42,24 @@
   std::vector<Manifest::Type> extension_types;
   std::vector<Feature::Context> contexts;
   std::vector<Feature::Platform> platforms;
+
   URLPatternSet matches;
-  SimpleFeature::Location location;
-  int min_manifest_version;
-  int max_manifest_version;
-  bool component_extensions_auto_granted;
-  std::string command_line_switch;
-  std::unique_ptr<version_info::Channel> channel;
-  bool internal;
+
+  base::Optional<SimpleFeature::Location> location;
+  base::Optional<int> min_manifest_version;
+  base::Optional<int> max_manifest_version;
+  base::Optional<std::string> command_line_switch;
+  base::Optional<version_info::Channel> channel;
+
   std::string alias;
   std::string source;
+
+  bool component_extensions_auto_granted;
+  bool internal;
 };
 
 FeatureComparator::FeatureComparator(const std::string& name)
     : name(name),
-      location(kDefaultLocation),
-      min_manifest_version(kDefaultMinVersion),
-      max_manifest_version(kDefaultMaxVersion),
       component_extensions_auto_granted(kDefaultAutoGrant),
       internal(kDefaultInternal) {}
 
@@ -83,9 +82,7 @@
             feature->component_extensions_auto_granted())
       << name;
   EXPECT_EQ(command_line_switch, feature->command_line_switch()) << name;
-  ASSERT_EQ(channel.get() != nullptr, feature->has_channel()) << name;
-  if (channel)
-    EXPECT_EQ(*channel, feature->channel()) << name;
+  EXPECT_EQ(channel, feature->channel()) << name;
   EXPECT_EQ(internal, feature->IsInternal()) << name;
   EXPECT_EQ(alias, feature->alias()) << name;
   EXPECT_EQ(source, feature->source()) << name;
@@ -114,8 +111,7 @@
     FeatureComparator comparator("alpha");
     comparator.dependencies = {"permission:alpha"};
     comparator.contexts = {Feature::BLESSED_EXTENSION_CONTEXT};
-    comparator.channel.reset(
-        new version_info::Channel(version_info::Channel::STABLE));
+    comparator.channel = version_info::Channel::STABLE;
     comparator.max_manifest_version = 1;
     comparator.CompareFeature(feature);
   }
@@ -123,8 +119,7 @@
     const SimpleFeature* feature = GetAsSimpleFeature("beta");
     FeatureComparator comparator("beta");
     comparator.contexts = {Feature::BLESSED_EXTENSION_CONTEXT};
-    comparator.channel.reset(
-        new version_info::Channel(version_info::Channel::DEV));
+    comparator.channel = version_info::Channel::DEV;
     comparator.extension_types = {Manifest::TYPE_EXTENSION,
                                   Manifest::TYPE_PLATFORM_APP};
     comparator.location = SimpleFeature::COMPONENT_LOCATION;
@@ -136,8 +131,7 @@
   {
     const SimpleFeature* feature = GetAsSimpleFeature("gamma");
     FeatureComparator comparator("gamma");
-    comparator.channel.reset(
-        new version_info::Channel(version_info::Channel::BETA));
+    comparator.channel = version_info::Channel::BETA;
     comparator.platforms = {Feature::WIN_PLATFORM, Feature::MACOSX_PLATFORM};
     comparator.contexts = {Feature::BLESSED_EXTENSION_CONTEXT};
     comparator.dependencies = {"permission:gamma"};
@@ -161,8 +155,7 @@
     FeatureComparator comparator("gamma.unparented");
     comparator.blacklist = {"ddd"};
     comparator.contexts = {Feature::UNBLESSED_EXTENSION_CONTEXT};
-    comparator.channel.reset(
-        new version_info::Channel(version_info::Channel::DEV));
+    comparator.channel = version_info::Channel::DEV;
     comparator.CompareFeature(feature);
   }
   {
@@ -170,8 +163,7 @@
         GetAsComplexFeature("gamma.complex_unparented");
     FeatureComparator comparator("gamma.complex_unparented");
     comparator.contexts = {Feature::UNBLESSED_EXTENSION_CONTEXT};
-    comparator.channel.reset(
-        new version_info::Channel(version_info::Channel::STABLE));
+    comparator.channel = version_info::Channel::STABLE;
     // We cheat and have both children exactly the same for ease of comparing;
     // complex features are tested more thoroughly below.
     for (const auto& feature : complex_feature->features_)
@@ -182,8 +174,7 @@
     FeatureComparator comparator("delta");
     comparator.contexts = {Feature::BLESSED_EXTENSION_CONTEXT,
                            Feature::WEBUI_CONTEXT};
-    comparator.channel.reset(
-        new version_info::Channel(version_info::Channel::DEV));
+    comparator.channel = version_info::Channel::DEV;
     comparator.matches.AddPattern(
         URLPattern(URLPattern::SCHEME_ALL, "*://example.com/*"));
     comparator.min_manifest_version = 2;
@@ -204,8 +195,7 @@
         Manifest::TYPE_EXTENSION,           Manifest::TYPE_HOSTED_APP,
         Manifest::TYPE_LEGACY_PACKAGED_APP, Manifest::TYPE_PLATFORM_APP,
         Manifest::TYPE_SHARED_MODULE,       Manifest::TYPE_THEME};
-    comparator.channel.reset(
-        new version_info::Channel(version_info::Channel::BETA));
+    comparator.channel = version_info::Channel::BETA;
     comparator.CompareFeature(feature);
   }
   {
@@ -213,8 +203,7 @@
     const SimpleFeature* feature = GetAsSimpleFeature("omega");
     FeatureComparator comparator("omega");
     comparator.contexts = {Feature::WEB_PAGE_CONTEXT};
-    comparator.channel.reset(
-        new version_info::Channel(version_info::Channel::DEV));
+    comparator.channel = version_info::Channel::DEV;
     comparator.min_manifest_version = 2;
     comparator.CompareFeature(feature);
   }
@@ -250,8 +239,7 @@
     {
       // Check the default parent.
       FeatureComparator comparator("complex");
-      comparator.channel.reset(
-          new version_info::Channel(version_info::Channel::STABLE));
+      comparator.channel = version_info::Channel::STABLE;
       comparator.contexts = {Feature::BLESSED_EXTENSION_CONTEXT};
       comparator.extension_types = {Manifest::TYPE_EXTENSION};
       comparator.CompareFeature(default_parent);
@@ -266,8 +254,7 @@
     {
       // Finally, check the branch of the complex feature.
       FeatureComparator comparator("complex");
-      comparator.channel.reset(
-          new version_info::Channel(version_info::Channel::BETA));
+      comparator.channel = version_info::Channel::BETA;
       comparator.contexts = {Feature::BLESSED_EXTENSION_CONTEXT};
       comparator.extension_types = {Manifest::TYPE_EXTENSION};
       comparator.whitelist = {"aaa"};
@@ -280,8 +267,7 @@
     const SimpleFeature* feature = GetAsSimpleFeature("alias");
     FeatureComparator comparator("alias");
     comparator.contexts = {Feature::BLESSED_EXTENSION_CONTEXT};
-    comparator.channel.reset(
-        new version_info::Channel(version_info::Channel::STABLE));
+    comparator.channel = version_info::Channel::STABLE;
     comparator.source = "alias_source";
     comparator.CompareFeature(feature);
   }
@@ -289,8 +275,7 @@
     const SimpleFeature* feature = GetAsSimpleFeature("alias_source");
     FeatureComparator comparator("alias_source");
     comparator.contexts = {Feature::BLESSED_EXTENSION_CONTEXT};
-    comparator.channel.reset(
-        new version_info::Channel(version_info::Channel::STABLE));
+    comparator.channel = version_info::Channel::STABLE;
     comparator.alias = "alias";
     comparator.CompareFeature(feature);
   }
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 86ba7fc1..264a467a 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -3547,6 +3547,11 @@
   <int value="1" label="FMP not OK, network was already quiet"/>
 </enum>
 
+<enum name="BooleanNull">
+  <int value="0" label="Is not a nullptr"/>
+  <int value="1" label="Is a nullptr"/>
+</enum>
+
 <enum name="BooleanNullStream">
   <int value="0" label="Stream is not a nullptr"/>
   <int value="1" label="Stream is a nullptr"/>
@@ -3847,6 +3852,11 @@
   <int value="1" label="Wasted"/>
 </enum>
 
+<enum name="BooleanWebApkNotificationPermission">
+  <int value="0" label="WebAPK notification permission disabled"/>
+  <int value="1" label="WebAPK notification permission enabled"/>
+</enum>
+
 <enum name="BooleanWiped">
   <int value="0" label="Re-enabled"/>
   <int value="1" label="Wiped out"/>
@@ -11448,6 +11458,7 @@
   <int value="388" label="DeviceNativePrintersBlacklist"/>
   <int value="389" label="DeviceNativePrintersWhitelist"/>
   <int value="390" label="DeviceTPMFirmwareUpdateSettings"/>
+  <int value="391" label="RunAllFlashInAllowMode"/>
 </enum>
 
 <enum name="EnterprisePolicyInvalidations">
@@ -11867,7 +11878,7 @@
 </enum>
 
 <enum name="ExtensionEvents">
-<!-- Generated from extensions/browser/extension_event_histogram_value.h -->
+<!-- Generated from extensions/browser/extension_event_histogram_value.h.-->
 
   <int value="0" label="UNKNOWN"/>
   <int value="1" label="FOR_TEST"/>
@@ -12291,7 +12302,7 @@
   <int value="411" label="WEB_VIEW_INTERNAL_ON_AUDIO_STATE_CHANGED"/>
   <int value="412" label="AUTOMATION_INTERNAL_ON_ACTION_RESULT"/>
   <int value="413" label="OMNIBOX_ON_DELETE_SUGGESTION"/>
-  <int value="414" label="PASSWORDS_PRIVATE_ON_SHOW_IMPORT_EXPORT_BUTTONS"/>
+  <int value="414" label="VIRTUAL_KEYBOARD_PRIVATE_ON_KEYBOARD_CONFIG_CHANGED"/>
 </enum>
 
 <enum name="ExtensionFileWriteResult">
@@ -12310,7 +12321,7 @@
 </enum>
 
 <enum name="ExtensionFunctions">
-<!-- Generated from extensions/browser/extension_function_histogram_value.h -->
+<!-- Generated from extensions/browser/extension_function_histogram_value.h.-->
 
   <int value="0" label="UNKNOWN"/>
   <int value="1" label="WEBNAVIGATION_GETALLFRAMES"/>
@@ -12817,9 +12828,9 @@
   <int value="500" label="DELETED_WEBVIEW_STOP"/>
   <int value="501" label="DELETED_WEBVIEW_RELOAD"/>
   <int value="502" label="DELETED_WEBVIEW_TERMINATE"/>
-  <int value="503" label="TYPES_PRIVATE_CHROMEDIRECTSETTING_GET"/>
-  <int value="504" label="TYPES_PRIVATE_CHROMEDIRECTSETTING_SET"/>
-  <int value="505" label="TYPES_PRIVATE_CHROMEDIRECTSETTING_CLEAR"/>
+  <int value="503" label="DELETED_TYPES_PRIVATE_CHROMEDIRECTSETTING_GET"/>
+  <int value="504" label="DELETED_TYPES_PRIVATE_CHROMEDIRECTSETTING_SET"/>
+  <int value="505" label="DELETED_TYPES_PRIVATE_CHROMEDIRECTSETTING_CLEAR"/>
   <int value="506" label="DELETED_EXPERIMENTAL_SYSTEMINFO_STORAGE_EJECTDEVICE"/>
   <int value="507" label="SYSTEM_CPU_GETINFO"/>
   <int value="508" label="BOOKMARKMANAGERPRIVATE_REMOVETREES"/>
@@ -17267,6 +17278,8 @@
   <int value="5" label="File has invalid contents."/>
   <int value="6" label="File could not be exclusively opened."/>
   <int value="7" label="File contents internally deleted."/>
+  <int value="8" label="File processing was postponed due to filtering."/>
+  <int value="9" label="File was skipped/deleted due to filtering."/>
 </enum>
 
 <enum name="FileMetricsProviderEmbeddedProfileResult">
@@ -23396,6 +23409,7 @@
   <int value="-1426034869" label="NoCreditCardAbort:enabled"/>
   <int value="-1419788257" label="enable-experimental-hotwording"/>
   <int value="-1416754663" label="enable-mac-views-native-app-windows"/>
+  <int value="-1416184931" label="TranslateRankerEnforcement:enabled"/>
   <int value="-1411003295" label="disable-encrypted-media"/>
   <int value="-1409643943" label="enable-child-account-detection"/>
   <int value="-1408288176" label="enable-account-consistency"/>
@@ -23492,6 +23506,7 @@
   <int value="-1107762575" label="enable-data-reduction-proxy-config-client"/>
   <int value="-1102212525" label="enable-tcp-fastopen"/>
   <int value="-1099142083" label="V8Ignition:disabled"/>
+  <int value="-1099135056" label="AsyncDns:enabled"/>
   <int value="-1096595907" label="disable-new-virtual-keyboard-behavior"/>
   <int value="-1085492638" label="FetchKeepaliveTimeoutSetting:enabled"/>
   <int value="-1084055006" label="disable-web-notification-custom-layouts"/>
@@ -23562,6 +23577,7 @@
   <int value="-894214299" label="fill-on-account-select:enabled"/>
   <int value="-894185031" label="HighDynamicRange:disabled"/>
   <int value="-891856063" label="MidiManagerAndroid:enabled"/>
+  <int value="-886912558" label="ChromeHomePromo:enabled"/>
   <int value="-885601782" label="enable-contextual-search"/>
   <int value="-884864731" label="WebPaymentsSingleAppUiSkip:enabled"/>
   <int value="-881854123" label="enable-heap-profiling"/>
@@ -23633,6 +23649,7 @@
   <int value="-684900739" label="disable-merge-key-char-events"/>
   <int value="-684223908" label="enable-android-wallpapers-app"/>
   <int value="-680589442" label="MacRTL:disabled"/>
+  <int value="-671992446" label="TranslateRankerEnforcement:disabled"/>
   <int value="-667517406" label="overscroll-history-navigation"/>
   <int value="-666508951" label="CrOSContainer:enabled"/>
   <int value="-663476391" label="enable-pixel-canvas-recording:enabled"/>
@@ -23880,6 +23897,7 @@
   <int value="59784035" label="ImeThread:disabled"/>
   <int value="59964519" label="OmniboxEnableClipboardProvider:disabled"/>
   <int value="61205887" label="enable-text-input-focus-manager"/>
+  <int value="61466986" label="AsyncDns:disabled"/>
   <int value="64942701" label="OfflinePagesSvelteConcurrentLoading:disabled"/>
   <int value="70878462" label="WebAssembly:disabled"/>
   <int value="75747474" label="disable-webview-signin-flow"/>
@@ -24455,6 +24473,7 @@
   <int value="1820317896" label="NTPShowGoogleGInOmnibox:disabled"/>
   <int value="1820451991" label="enable-offline-auto-reload"/>
   <int value="1821723343" label="disable-saml-signin"/>
+  <int value="1825940786" label="ChromeHomePromo:disabled"/>
   <int value="1827369558" label="AndroidPayIntegrationV1:disabled"/>
   <int value="1828660283" label="enable-webfonts-intervention-trigger"/>
   <int value="1831835753" label="MaterialDesignIncognitoNTP:enabled"/>
@@ -25869,11 +25888,24 @@
   <int value="2" label="ErrorTooManyRetries"/>
 </enum>
 
+<enum name="MediaRouterCastChannelError">
+  <int value="0" label="Unknown"/>
+  <int value="1" label="Authentication"/>
+  <int value="2" label="Connect"/>
+  <int value="3" label="General Certificate"/>
+  <int value="4" label="Certificate timing"/>
+  <int value="5" label="Network"/>
+  <int value="6" label="Connect Timeout"/>
+  <int value="7" label="Ping Timeout"/>
+</enum>
+
 <enum name="MediaRouterCastSinkSource">
   <int value="0" label="NetworkCache"/>
   <int value="1" label="mDNS"/>
   <int value="2" label="DIAL"/>
   <int value="3" label="Connection retry"/>
+  <int value="4" label="First by mDNS, then by DIAL"/>
+  <int value="5" label="First by DIAL, then by mDNS"/>
 </enum>
 
 <enum name="MediaRouterCreateRouteOutcome">
@@ -28023,6 +28055,28 @@
   <int value="3" label="Too few URLs, didn't flip tiles 1 and 4"/>
 </enum>
 
+<enum name="NTPTileTitleSource">
+  <summary>
+    The source where the displayed title of an NTP tile originates from.
+  </summary>
+  <int value="0" label="Unknown">
+    The title might be invalid, aggregated, user-set, extracted from history,
+    not loaded or simply not known.
+  </int>
+  <int value="1" label="Manifest">
+    The site's manifest contained a usable &quot;(short_)name&quot; attribute.
+  </int>
+  <int value="2" label="MetaTag">
+    The site provided a meta tag (e.g. OpenGraph's site_name).
+  </int>
+  <int value="3" label="TitleTag">
+    The site's title is used as tile title, extracted from the title tag.
+  </int>
+  <int value="4" label="InferredTitle">
+    The title was inferred from multiple signals (e.g. meta tags, url, title).
+  </int>
+</enum>
+
 <enum name="NTPTileVisualType">
   <summary>The visual type of a most visited tile on the new tab page.</summary>
   <int value="0" label="None">The icon or thumbnail hasn't loaded yet.</int>
@@ -33088,6 +33142,10 @@
   <int value="9" label="Idle"/>
   <int value="10" label="Test"/>
   <int value="11" label="FrameLoadingControl"/>
+  <int value="12" label="FrameThrottleable"/>
+  <int value="13" label="FrameDeferrable"/>
+  <int value="14" label="FramePausable"/>
+  <int value="15" label="FrameUnpausable"/>
 </enum>
 
 <enum name="RendererType">
@@ -36734,6 +36792,7 @@
   <int value="9" label="CAPTIVE_PORTAL_CERT_FOUND"/>
   <int value="10" label="WWW_MISMATCH_FOUND_IN_SAN"/>
   <int value="11" label="SHOW_MITM_SOFTWARE_INTERSTITIAL"/>
+  <int value="12" label="OS_REPORTS_CAPTIVE_PORTAL"/>
 </enum>
 
 <enum name="SSLErrorTypes">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 5822585..5e7f3b5 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -3438,6 +3438,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.ConfigParseResult" enum="BooleanSuccess">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>Whether DnsConfig was parsed successfully.</summary>
 </histogram>
@@ -3450,6 +3453,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.DNSChangerDetected" enum="BooleanSuccess">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Whether the first valid DnsConfig included a rogue nameserver.
@@ -3536,6 +3542,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.JobQueueTime" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTime.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the time the HostResolverImpl::Job was created and the
@@ -3544,6 +3553,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.JobQueueTime_HIGHEST" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTime.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the time the HostResolverImpl::Job was created and the
@@ -3553,6 +3565,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.JobQueueTime_IDLE" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTime.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the time the HostResolverImpl::Job was created and the
@@ -3562,6 +3577,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.JobQueueTime_LOW" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTime.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the time the HostResolverImpl::Job was created and the
@@ -3571,6 +3589,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.JobQueueTime_LOWEST" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTime.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the time the HostResolverImpl::Job was created and the
@@ -3580,6 +3601,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.JobQueueTime_MEDIUM" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTime.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the time the HostResolverImpl::Job was created and the
@@ -3589,6 +3613,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.JobQueueTimeAfterChange" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTimeAfterChange.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the last time the priority of a HostResolverImpl::Job
@@ -3598,6 +3625,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.JobQueueTimeAfterChange_HIGHEST" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTimeAfterChange.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the last time the priority of a HostResolverImpl::Job
@@ -3608,6 +3638,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.JobQueueTimeAfterChange_IDLE" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTimeAfterChange.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the last time the priority of a HostResolverImpl::Job
@@ -3618,6 +3651,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.JobQueueTimeAfterChange_LOW" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTimeAfterChange.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the last time the priority of a HostResolverImpl::Job
@@ -3628,6 +3664,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.JobQueueTimeAfterChange_LOWEST" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTimeAfterChange.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the last time the priority of a HostResolverImpl::Job
@@ -3638,6 +3677,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.JobQueueTimeAfterChange_MEDIUM" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTimeAfterChange.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the last time the priority of a HostResolverImpl::Job
@@ -3667,6 +3709,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.PrefDefaultSource" enum="AsyncDNSPrefDefaultSource">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     The source of the async DNS preference's default. Logged at startup, when
@@ -3675,6 +3720,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.PrefSource" enum="AsyncDNSPrefSource">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     The source of the async DNS preference's value. Logged at startup, when the
@@ -3683,6 +3731,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.ResolveError" enum="NetErrorCodes">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.DnsTaskError.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Counts of specific error codes returned by DnsTask if a subsequent ProcTask
@@ -3691,6 +3742,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.ResolveFail" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.DnsTaskFail.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Duration of time taken by DnsTask in resolutions that failed. Excludes time
@@ -3699,6 +3753,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.ResolveStatus" enum="AsyncDNSResolveStatus">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Counts of the overall results of using asynchronous DNS in HostResolverImpl.
@@ -3708,6 +3765,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.ResolveSuccess" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.DnsTaskSuccess.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Duration of time taken by DnsTask in resolutions that succeeded.
@@ -3715,6 +3775,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.ResolveSuccess_FAMILY_IPV4" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.DnsTaskSuccess.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Same as AsyncDNS.ResolveSuccess, but limited to pure IPv4 lookups.
@@ -3722,6 +3785,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.ResolveSuccess_FAMILY_IPV6" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.DnsTaskSuccess.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Same as AsyncDNS.ResolveSuccess, but limited to pure IPv6 lookups.
@@ -3729,6 +3795,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.ResolveSuccess_FAMILY_UNSPEC" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.DnsTaskSuccess.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Same as AsyncDNS.ResolveSuccess, but limited to IPv4/IPv6 lookups.
@@ -3785,6 +3854,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.ServerIsGood" enum="BooleanSuccess">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     The current server is &quot;good&quot; and does not have to be skipped.
@@ -3891,6 +3963,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.TotalTime" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.TotalTime.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Duration of time since a HostResolverImpl::Resolve request to the time a
@@ -3900,6 +3975,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.TotalTime_speculative" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.TotalTime_speculative.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Duration of time since a HostResolverImpl::Resolve request to the time a
@@ -10069,6 +10147,12 @@
   </summary>
 </histogram>
 
+<histogram name="ContentSettings.DefaultSoundSetting" enum="ContentSetting">
+  <owner>mlamouri@chromium.org</owner>
+  <owner>steimel@chromium.org</owner>
+  <summary>The default sound setting at profile open.</summary>
+</histogram>
+
 <histogram name="ContentSettings.DefaultSubresourceFilterSetting"
     enum="ContentSetting">
   <owner>csharrison@chromium.org</owner>
@@ -10340,6 +10424,18 @@
   </summary>
 </histogram>
 
+<histogram name="ContentSuggestions.FetchPendingPlaceholder.VisibleDuration"
+    units="ms">
+  <owner>dgn@chromium.org</owner>
+  <owner>ntp-dev+metrics@chromium.org</owner>
+  <summary>
+    Android: How long the content suggestion placeholder is shown. This is
+    tracked based on when the placeholder is enabled in the UI, not how long it
+    is actually visible on screen. Depending on the screen size, the used value
+    could be bigger.
+  </summary>
+</histogram>
+
 <histogram name="ContextMenu.SaveLinkType" enum="ContextMenuSaveLinkType">
   <owner>qinmin@chromium.org</owner>
   <summary>
@@ -14104,6 +14200,9 @@
 </histogram>
 
 <histogram name="DNS.CacheEvicted" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     The time left to expiration of an entry when it is removed while compacting
@@ -14112,6 +14211,9 @@
 </histogram>
 
 <histogram name="DNS.CacheExpired" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     The time since expiration of an entry when it is removed while compacting
@@ -14120,6 +14222,9 @@
 </histogram>
 
 <histogram name="DNS.CacheExpiredOnGet" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     The time since expiration of an entry when it is removed on lookup.
@@ -14128,6 +14233,9 @@
 
 <histogram name="DNS.EmptyAddressListAndNoError"
     enum="DNSEmptyAddressListAndNoError">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Error status when an empty address list was found in OnLookupComplete().
@@ -14247,6 +14355,9 @@
 </histogram>
 
 <histogram name="DNS.IndependentFailedNavigation" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     When either a pre-resolution was not done recently enough to provide
@@ -14260,6 +14371,9 @@
 </histogram>
 
 <histogram name="DNS.IndependentNavigation" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     When either a pre-resolution was not done recently enough to provide
@@ -14273,6 +14387,9 @@
 </histogram>
 
 <histogram name="DNS.JobQueueTime" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTime.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the time the HostResolverImpl::Job was created and the
@@ -14282,6 +14399,9 @@
 </histogram>
 
 <histogram name="DNS.JobQueueTime_HIGHEST" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTime.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the time the HostResolverImpl::Job was created and the
@@ -14291,6 +14411,9 @@
 </histogram>
 
 <histogram name="DNS.JobQueueTime_IDLE" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTime.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the time the HostResolverImpl::Job was created and the
@@ -14300,6 +14423,9 @@
 </histogram>
 
 <histogram name="DNS.JobQueueTime_LOW" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTime.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the time the HostResolverImpl::Job was created and the
@@ -14309,6 +14435,9 @@
 </histogram>
 
 <histogram name="DNS.JobQueueTime_LOWEST" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTime.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the time the HostResolverImpl::Job was created and the
@@ -14318,6 +14447,9 @@
 </histogram>
 
 <histogram name="DNS.JobQueueTime_MEDIUM" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTime.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the time the HostResolverImpl::Job was created and the
@@ -14327,6 +14459,9 @@
 </histogram>
 
 <histogram name="DNS.JobQueueTimeAfterChange" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTimeAfterChange.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the last time the priority of a HostResolverImpl::Job
@@ -14336,6 +14471,9 @@
 </histogram>
 
 <histogram name="DNS.JobQueueTimeAfterChange_HIGHEST" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTimeAfterChange.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the last time the priority of a HostResolverImpl::Job
@@ -14346,6 +14484,9 @@
 </histogram>
 
 <histogram name="DNS.JobQueueTimeAfterChange_IDLE" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTimeAfterChange.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the last time the priority of a HostResolverImpl::Job
@@ -14356,6 +14497,9 @@
 </histogram>
 
 <histogram name="DNS.JobQueueTimeAfterChange_LOW" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTimeAfterChange.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the last time the priority of a HostResolverImpl::Job
@@ -14366,6 +14510,9 @@
 </histogram>
 
 <histogram name="DNS.JobQueueTimeAfterChange_LOWEST" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTimeAfterChange.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the last time the priority of a HostResolverImpl::Job
@@ -14376,6 +14523,9 @@
 </histogram>
 
 <histogram name="DNS.JobQueueTimeAfterChange_MEDIUM" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.JobQueueTimeAfterChange.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Time elapsed between the last time the priority of a HostResolverImpl::Job
@@ -14386,6 +14536,9 @@
 </histogram>
 
 <histogram name="DNS.PrefetchCacheEviction" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     The duration of time used (most recently) to pre-resolve a hostname, when
@@ -14396,6 +14549,9 @@
 </histogram>
 
 <histogram name="DNS.PrefetchCacheEvictionL" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     The duration of time used (most recently) to pre-resolve a hostname, when
@@ -14406,6 +14562,9 @@
 </histogram>
 
 <histogram name="DNS.PrefetchFoundName">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>Replaced by DNS.PrefetchFoundNameL.</summary>
 </histogram>
@@ -14428,11 +14587,17 @@
 </histogram>
 
 <histogram name="DNS.PrefetchNegativeHit">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>Replaced by DNS.PrefetchNegativeHitL.</summary>
 </histogram>
 
 <histogram name="DNS.PrefetchNegativeHitL" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     The duration of time saved due to DNS pre-resolving in the &quot;name not
@@ -14451,11 +14616,17 @@
 </histogram>
 
 <histogram name="DNS.PrefetchPositiveHit">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>Replaced by DNS.PrefetchPositiveHitL.</summary>
 </histogram>
 
 <histogram name="DNS.PrefetchPositiveHitL" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     The duration of time saved due to DNS pre-resolving in the &quot;name was
@@ -14472,6 +14643,9 @@
 </histogram>
 
 <histogram name="DNS.PrefetchQueue" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     The duration of time spent by a proposed resolution waiting in the queue to
@@ -14481,6 +14655,9 @@
 </histogram>
 
 <histogram name="DNS.PrefetchReferredPositiveHit" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     The duration of time saved due to DNS pre-resolving in the &quot;name was
@@ -14511,6 +14688,9 @@
 </histogram>
 
 <histogram name="DNS.QueueRecycledDeltaOver2">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     When, due to congestion avoidance, a queued pre-resolution is abandoned
@@ -14521,6 +14701,9 @@
 </histogram>
 
 <histogram name="DNS.QueueRecycledUnder2">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     When, due to congestion avoidance, a queued pre-resolution is abandoned
@@ -14531,6 +14714,9 @@
 </histogram>
 
 <histogram name="DNS.ResolveCategory" enum="ResolutionCategory">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.ResolveCategory.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Counts of successes and failures of OS resolutions in various categories.
@@ -14538,6 +14724,9 @@
 </histogram>
 
 <histogram name="DNS.ResolveFail" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.ProcTaskFail.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Duration of time taken in OS resolutions for actual navigations.  Note that
@@ -14546,21 +14735,33 @@
 </histogram>
 
 <histogram name="DNS.ResolveFail_FAMILY_IPV4" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.ProcTaskFail.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>Same as DNS.ResolveFail, but limited to pure IPv4 lookups.</summary>
 </histogram>
 
 <histogram name="DNS.ResolveFail_FAMILY_IPV6" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.ProcTaskFail.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>Same as DNS.ResolveFail, but limited to pure IPv6 lookups.</summary>
 </histogram>
 
 <histogram name="DNS.ResolveFail_FAMILY_UNSPEC" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.ProcTaskFail.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>Same as DNS.ResolveFail, but limited to IPv4/IPv6 lookups.</summary>
 </histogram>
 
 <histogram name="DNS.ResolveSpeculativeFail" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.ProcTaskFail.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Duration of time taken in speculative OS resolutions.  Note that cached OS
@@ -14569,6 +14770,9 @@
 </histogram>
 
 <histogram name="DNS.ResolveSpeculativeSuccess" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.ProcTaskSuccess.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Duration of time taken in speculative OS resolution that succeeded.  Note
@@ -14577,6 +14781,9 @@
 </histogram>
 
 <histogram name="DNS.ResolveSuccess" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.ProcTaskSuccess.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Duration of time taken in OS resolutions that succeeded and were requested
@@ -14586,6 +14793,9 @@
 </histogram>
 
 <histogram name="DNS.ResolveSuccess_FAMILY_IPV4" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.ProcTaskSuccess.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Same as DNS.ResolveSuccess, but limited to pure IPv4 lookups.
@@ -14593,6 +14803,9 @@
 </histogram>
 
 <histogram name="DNS.ResolveSuccess_FAMILY_IPV6" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.ProcTaskSuccess.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Same as DNS.ResolveSuccess, but limited to pure IPv6 lookups.
@@ -14600,6 +14813,9 @@
 </histogram>
 
 <histogram name="DNS.ResolveSuccess_FAMILY_UNSPEC" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.ProcTaskSuccess.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Same as DNS.ResolveSuccess, but limited to IPv4/IPv6 lookups.
@@ -14672,6 +14888,9 @@
 </histogram>
 
 <histogram name="DNS.TotalTime" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.TotalTime.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Duration of time since a HostResolverImpl::Resolve request to the time a
@@ -14681,6 +14900,9 @@
 </histogram>
 
 <histogram name="DNS.TotalTime_speculative" units="ms">
+  <obsolete>
+    Deprecated as of 9/2017. Replaced by Net.DNS.TotalTime_speculative.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Duration of time since a HostResolverImpl::Resolve request to the time a
@@ -14690,6 +14912,9 @@
 </histogram>
 
 <histogram name="DNS.UnexpectedResolution">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     In some cases, such as when content arrives with embedded references to
@@ -14708,6 +14933,9 @@
 </histogram>
 
 <histogram name="DNS.UnexpectedResolutionL">
+  <obsolete>
+    Deprecated as of 9/2017.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     In some cases, such as when content arrives with embedded references to
@@ -22445,6 +22673,15 @@
   </summary>
 </histogram>
 
+<histogram name="Extensions.Messaging.MessageSize" units="bytes">
+  <owner>redevlin.cronin@chromium.org</owner>
+  <summary>
+    The size, in bytes, of a message sent from an extension using one of the
+    messaging APIs (e.g. chrome.runtime.sendMessage). All message sizes are
+    logged, but messages over 64 MB in size aren't sent.
+  </summary>
+</histogram>
+
 <histogram name="Extensions.Messaging.SetPortIdTime" units="ms">
   <owner>rdevlin.cronin@chromium.org</owner>
   <summary>
@@ -32455,10 +32692,19 @@
 </histogram>
 
 <histogram name="Media.Remoting.SessionStopTrigger" enum="RemotingStopTrigger">
+<!-- Name completed by histogram_suffixes name="RemotingSessionDuration" -->
+
   <owner>miu@chromium.org</owner>
   <summary>Tracks the trigger for stopping a remoting session.</summary>
 </histogram>
 
+<histogram name="Media.Remoting.ShortSessionDuration" units="ms">
+  <owner>miu@chromium.org</owner>
+  <summary>
+    Measures the duration of each remoting session shorter than 15 seconds.
+  </summary>
+</histogram>
+
 <histogram name="Media.Remoting.StartMediaBitrate" units="kbps">
   <owner>miu@chromium.org</owner>
   <summary>
@@ -33651,6 +33897,24 @@
   <summary>Various usage counts for media galleries.</summary>
 </histogram>
 
+<histogram name="MediaRouter.Cast.Channel.ConnectResult" enum="BooleanSuccess">
+  <owner>zhaobin@chromium.org</owner>
+  <summary>
+    Whether opening Cast channel succeeds or not. Recorded when all opening
+    channel attempts (including retry attempts) finish.
+  </summary>
+</histogram>
+
+<histogram name="MediaRouter.Cast.Channel.Error"
+    enum="MediaRouterCastChannelError">
+  <owner>zhaobin@chromium.org</owner>
+  <summary>
+    Errors encountered on a Cast channel. Recorded when a Cast channel fails to
+    open, or when an opened channel fails to respond to keepalive ping request
+    and times out.
+  </summary>
+</histogram>
+
 <histogram name="MediaRouter.Cast.Discovery.CachedSinksAvailableCount"
     units="devices">
   <owner>btolsch@chromium.org</owner>
@@ -33683,6 +33947,22 @@
   <summary>The source of discovery for a newly-created Cast sink.</summary>
 </histogram>
 
+<histogram name="MediaRouter.Cast.Mdns.Channel.Open_Failure" units="ms">
+  <owner>zhaobin@chromium.org</owner>
+  <summary>
+    Duration in milliseconds taken to fail to open a cast channel. Recorded when
+    one opening channel attempt fails.
+  </summary>
+</histogram>
+
+<histogram name="MediaRouter.Cast.Mdns.Channel.Open_Success" units="ms">
+  <owner>zhaobin@chromium.org</owner>
+  <summary>
+    Duration in milliseconds taken to successfully open a cast channel. Recorded
+    when one opening channel attempt succeeds.
+  </summary>
+</histogram>
+
 <histogram name="MediaRouter.Dial.AvailableDevicesCount" units="devices">
   <owner>zhaobin@chromium.org</owner>
   <summary>
@@ -39376,6 +39656,108 @@
   </summary>
 </histogram>
 
+<histogram name="Net.DNS.DnsTask.Errors" enum="NetErrorCodes">
+  <owner>mgersh@chromium.org</owner>
+  <summary>
+    Counts of specific error codes returned by DnsTask if a subsequent ProcTask
+    succeeded.
+  </summary>
+</histogram>
+
+<histogram name="Net.DNS.DnsTask.FailureTime" units="ms">
+  <owner>mgersh@chromium.org</owner>
+  <summary>
+    Duration of time taken by DnsTask in resolutions that failed. Excludes time
+    spent in the subsequent fallback.
+  </summary>
+</histogram>
+
+<histogram name="Net.DNS.DnsTask.SuccessTime" units="ms">
+  <owner>mgersh@chromium.org</owner>
+  <summary>
+    Duration of time taken by DnsTask in resolutions that succeeded.
+  </summary>
+</histogram>
+
+<histogram name="Net.DNS.JobQueueTime" units="ms">
+  <owner>mgersh@chromium.org</owner>
+  <summary>
+    Time elapsed between the time the HostResolverImpl::Job was created and the
+    time the Job was started.
+  </summary>
+</histogram>
+
+<histogram name="Net.DNS.JobQueueTimeAfterChange" units="ms">
+  <owner>mgersh@chromium.org</owner>
+  <summary>
+    Time elapsed between the last time the priority of a HostResolverImpl::Job
+    changed (when a Request was attached or detached) and the time the Job was
+    started.
+  </summary>
+</histogram>
+
+<histogram name="Net.DNS.ProcTask.FailureTime" units="ms">
+  <owner>mgersh@chromium.org</owner>
+  <summary>
+    Duration of time taken by ProcTask in resolutions that failed.
+  </summary>
+</histogram>
+
+<histogram name="Net.DNS.ProcTask.SuccessTime" units="ms">
+  <owner>mgersh@chromium.org</owner>
+  <summary>
+    Duration of time taken by ProcTask in resolutions that succeeded.
+  </summary>
+</histogram>
+
+<histogram name="Net.DNS.ResolveCategory" enum="ResolutionCategory">
+  <owner>mgersh@chromium.org</owner>
+  <summary>
+    Whether a DNS resolution (single HostResolverImpl::Job) succeeded or failed,
+    and whether it was speculative.
+  </summary>
+</histogram>
+
+<histogram name="Net.DNS.ResolveFailureTime" units="ms">
+  <owner>mgersh@chromium.org</owner>
+  <summary>
+    Duration of time taken by HostResolverImpl::Job in resolutions that failed.
+    This is the time to resolve a hostname from start to finish. The main
+    histogram and by-priority versions exclude speculative requests, which are
+    recorded in the _speculative version.
+  </summary>
+</histogram>
+
+<histogram name="Net.DNS.ResolveSuccessTime" units="ms">
+  <owner>mgersh@chromium.org</owner>
+  <summary>
+    Duration of time taken by HostResolverImpl::Job in resolutions that
+    succeeded. This is the time to resolve a hostname from start to finish. The
+    main histogram and by-priority versions exclude speculative requests, which
+    are recorded in the _speculative version.
+  </summary>
+</histogram>
+
+<histogram name="Net.DNS.TotalTime" units="ms">
+  <owner>mgersh@chromium.org</owner>
+  <summary>
+    Duration of time since a HostResolverImpl::Resolve request to the time a
+    result is posted. Excludes canceled, evicted, and aborted requests. Includes
+    cache hits (recorded as 0). Main histogram excludes speculative requests,
+    which go in the _speculative version.
+  </summary>
+</histogram>
+
+<histogram name="Net.DNS.TotalTimeNotCached" units="ms">
+  <owner>mgersh@chromium.org</owner>
+  <summary>
+    Duration of time since a HostResolverImpl::Resolve request to the time a
+    result is posted. Excludes canceled, evicted, and aborted requests and
+    requests that returned synchronously (such as cache hits). Main histogram
+    excludes speculative requests, which go in the _speculative version.
+  </summary>
+</histogram>
+
 <histogram name="Net.DNS_Resolution_And_TCP_Connection_Latency">
   <obsolete>
     Deprecated- see Net.DNS_Resolution_And_TCP_Connection_Latency2
@@ -49198,6 +49580,22 @@
   </summary>
 </histogram>
 
+<histogram name="NewTabPage.TileTitle" enum="NTPTileTitleSource">
+  <owner>fhorschig@chromium.org</owner>
+  <summary>
+    Records the source of the title for each most visited tiled displayed when
+    an NTP is opened, e.g. a short_name from a manifest, or the page title.
+  </summary>
+</histogram>
+
+<histogram name="NewTabPage.TileTitleClicked" enum="NTPTileTitleSource">
+  <owner>fhorschig@chromium.org</owner>
+  <summary>
+    Records the source for the name a most visited tile showed when the user
+    clicked it, e.g. a URL, or the page title.
+  </summary>
+</histogram>
+
 <histogram name="NewTabPage.TileType" enum="NTPTileVisualType">
   <owner>mastiz@chromium.org</owner>
   <summary>
@@ -52232,6 +52630,20 @@
   </summary>
 </histogram>
 
+<histogram name="Omnibox.URLNavigationScheme" enum="NavigationScheme">
+  <owner>mpearson@chromium.org</owner>
+  <summary>
+    The scheme of the destination URL for the selected omnibox suggestion. This
+    could be a what-you-typed suggestion (if the user fully typed a URL), an
+    inline autocompletion, or something in the dropdown, anything as long as
+    it's a URL navigation, not a search query.  Excludes omnibox URL navigations
+    that are effectively reloads as well as cut-and-pastes of URLs.  Also does
+    not take into account any redirects that destination URL may do before
+    finally serving a page. In other words, it's the scheme of the first request
+    in a possible chain.
+  </summary>
+</histogram>
+
 <histogram name="Omnibox.UserTextCleared" enum="OmniboxUserTextCleared">
   <owner>kenjibaheux@chromium.org</owner>
   <owner>mpearson@chromium.org</owner>
@@ -54898,6 +55310,32 @@
   </summary>
 </histogram>
 
+<histogram name="PartnerBookmark.Count" units="bookmarks">
+  <owner>wychen@chromium.org</owner>
+  <summary>
+    The number of partner bookmark entries. Note that zero would be
+    under-represented because reading is throttled if the last result is zero.
+    Logged on every cold start except when it is skipped (
+    PartnerBookmark.Skipped == True).
+  </summary>
+</histogram>
+
+<histogram name="PartnerBookmark.Null" enum="BooleanNull">
+  <owner>wychen@chromium.org</owner>
+  <summary>
+    Whether there's no partner bookmark provider. By default, the system image
+    contains a dummy partner bookmarks provider that provides zero entries.
+    Logged on every cold start.
+  </summary>
+</histogram>
+
+<histogram name="PartnerBookmark.Skipped" enum="BooleanSkipped">
+  <owner>wychen@chromium.org</owner>
+  <summary>
+    Whether reading of partner bookmark is skipped. Logged on every cold start.
+  </summary>
+</histogram>
+
 <histogram name="PasswordBubble.DisplayDisposition"
     enum="PasswordBubbleDisplayDisposition">
   <owner>vasilii@chromium.org</owner>
@@ -65869,6 +66307,14 @@
   <summary>Time between subsequent gestures (scrolls and pinches).</summary>
 </histogram>
 
+<histogram name="RendererScheduler.WebFramesPerScheduler" units="web frames">
+  <owner>altimin@chromium.org</owner>
+  <summary>
+    Number of web frame schedulers per renderer scheduler. Recorded once per
+    navigation.
+  </summary>
+</histogram>
+
 <histogram name="RendererScheduler.WebViewsPerScheduler" units="web views">
   <owner>altimin@chromium.org</owner>
   <summary>
@@ -82683,6 +83129,14 @@
   </summary>
 </histogram>
 
+<histogram name="Tab.VisibleTimeAfterCrossOriginRedirect" units="ms">
+  <owner>csharrison@chromium.org</owner>
+  <summary>
+    Measures the total time a tab is visible after it navigates itself
+    cross-origin in the background. Measured at WebContents destruction.
+  </summary>
+</histogram>
+
 <histogram
     name="TabManager.BackgroundTabOpening.ForegroundTab.ExpectedTaskQueueingDuration"
     units="ms">
@@ -88567,13 +89021,23 @@
   </summary>
 </histogram>
 
+<histogram name="WebApk.Install.ChromeCacheSize.Fail" units="MB">
+  <owner>hanxi@chromium.org</owner>
+  <owner>ranj@chromium.org</owner>
+  <owner>yfriedman@chromium.org</owner>
+  <summary>
+    Records the Chrome cache size when installing a WebAPK from Google Play
+    fails, with a range between 0 and 2000, rounded to the nearest 10MB.
+  </summary>
+</histogram>
+
 <histogram name="WebApk.Install.ChromeUnimportantStorage.Fail" units="MB">
   <owner>hanxi@chromium.org</owner>
   <owner>ranj@chromium.org</owner>
   <owner>yfriedman@chromium.org</owner>
   <summary>
     Records the Chrome unimportant storage size when installing a WebAPK from
-    Google Play fails, with a range between 0 and 1000, round to the nearest
+    Google Play fails, with a range between 0 and 1000, rounded to the nearest
     10MB.
   </summary>
 </histogram>
@@ -88717,6 +89181,17 @@
   </summary>
 </histogram>
 
+<histogram name="WebApk.Notification.Permission.Status"
+    enum="BooleanWebApkNotificationPermission">
+  <owner>hanxi@chromium.org</owner>
+  <owner>ranj@chromium.org</owner>
+  <owner>yfriedman@chromium.org</owner>
+  <summary>
+    When a WebAPK receives a notification, log whether it has permission to
+    display that notification.
+  </summary>
+</histogram>
+
 <histogram name="WebApk.OpenFromMenu" enum="WebApkOpenResult">
   <owner>hanxi@chromium.org</owner>
   <owner>pkotwicz@chromium.org</owner>
@@ -94728,6 +95203,7 @@
   <suffix name="protocol-handler" label="Protocol handler exceptions"/>
   <suffix name="push-messaging" label="Push messaging exceptions"/>
   <suffix name="site-engagement" label="Site engagement exceptions"/>
+  <suffix name="sound" label="Sound exceptions"/>
   <suffix name="ssl-cert-decisions" label="SSL cert decisions exceptions"/>
   <suffix name="subresource-filter" label="Subresource filter exceptions"/>
   <suffix name="usb-chooser-data" label="USB chooser data exceptions"/>
@@ -97720,6 +98196,33 @@
   <affected-histogram name="Net.BidirectionalStream.TimeToSendStart"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="Net.DNS.AddressFamily" separator=".">
+  <suffix name="IPV4" label="Requests for ADDRESS_FAMILY_IPV4."/>
+  <suffix name="IPV6" label="Requests for ADDRESS_FAMILY_IPV6."/>
+  <suffix name="UNSPEC" label="Requests for ADDRESS_FAMILY_UNSPEC."/>
+  <affected-histogram name="Net.DNS.ResolveFailureTime"/>
+  <affected-histogram name="Net.DNS.ResolveSuccessTime"/>
+</histogram_suffixes>
+
+<histogram_suffixes name="Net.DNS.Priorities" separator=".">
+  <suffix name="THROTTLED" label="Jobs with priority THROTTLED."/>
+  <suffix name="IDLE" label="Jobs with priority IDLE."/>
+  <suffix name="LOWEST" label="Jobs with priority LOWEST."/>
+  <suffix name="LOW" label="Jobs with priority LOW."/>
+  <suffix name="MEDIUM" label="Jobs with priority MEDIUM."/>
+  <suffix name="HIGHEST" label="Jobs with priority HIGHEST."/>
+  <affected-histogram name="Net.DNS.JobQueueTime"/>
+  <affected-histogram name="Net.DNS.JobQueueTimeAfterChange"/>
+</histogram_suffixes>
+
+<histogram_suffixes name="Net.DNS.Speculative" separator=".">
+  <suffix name="Speculative" label="Speculative resolutions only."/>
+  <affected-histogram name="Net.DNS.ResolveFailureTime"/>
+  <affected-histogram name="Net.DNS.ResolveSuccessTime"/>
+  <affected-histogram name="Net.DNS.TotalTime"/>
+  <affected-histogram name="Net.DNS.TotalTimeNotCached"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="Net.HttpJob.TotalTimeSuccess.Priorities"
     separator=".">
   <suffix name="Priority0" label="THROTTLED or MINIMUM_PRIORITY"/>
@@ -99205,6 +99708,8 @@
   </suffix>
   <affected-histogram name="NewTabPage.MostVisited"/>
   <affected-histogram name="NewTabPage.SuggestionsImpression"/>
+  <affected-histogram name="NewTabPage.TileTitle"/>
+  <affected-histogram name="NewTabPage.TileTitleClicked"/>
   <affected-histogram name="NewTabPage.TileType"/>
   <affected-histogram name="NewTabPage.TileTypeClicked"/>
 </histogram_suffixes>
@@ -101648,6 +102153,22 @@
   <affected-histogram name="Startup.WarmStartTimeFromRemoteProcessStart"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="RemotingSessionDuration" separator=".">
+  <suffix name="Duration0To100MilliSec"
+      label="remoting sessions have duration in (0, 0.1] seconds"/>
+  <suffix name="Duration100MilliSecTo1Sec"
+      label="remoting sessions have duration in (0.1, 1] seconds"/>
+  <suffix name="Duration1To3Sec"
+      label="remoting sessions have duration in (1, 3] seconds"/>
+  <suffix name="Duration3To5Sec"
+      label="remoting sessions have duration in (3, 5] seconds"/>
+  <suffix name="Duration5To10Sec"
+      label="remoting sessions have duration in (5, 10] seconds"/>
+  <suffix name="Duration10To15Sec"
+      label="remoting sessions have duration in (10, 15] seconds"/>
+  <affected-histogram name="Media.Remoting.SessionStopTrigger"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="RendererEventLatency" separator=".">
   <suffix name="Char" label="The Char event occurs on textual keyboard input."/>
   <suffix name="ContextMenu" label="For ContextMenu event."/>
diff --git a/tools/perf/benchmarks/loading.py b/tools/perf/benchmarks/loading.py
index ca0bbcf7..89d19908 100644
--- a/tools/perf/benchmarks/loading.py
+++ b/tools/perf/benchmarks/loading.py
@@ -55,6 +55,9 @@
   def CreateStorySet(self, options):
     return page_sets.LoadingMobileStorySet(
         cache_temperatures=[cache_temperature.ANY],
+        cache_temperatures_for_pwa=[cache_temperature.COLD,
+                                    cache_temperature.WARM,
+                                    cache_temperature.HOT],
         traffic_settings=[traffic_setting.NONE, traffic_setting.REGULAR_3G])
 
   def GetExpectations(self):
diff --git a/tools/perf/benchmarks/system_health_smoke_test.py b/tools/perf/benchmarks/system_health_smoke_test.py
index 9823e655..3dbe8694 100644
--- a/tools/perf/benchmarks/system_health_smoke_test.py
+++ b/tools/perf/benchmarks/system_health_smoke_test.py
@@ -48,6 +48,9 @@
   # crbug.com/769263
   'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.play:media:soundcloud',  # pylint: disable=line-too-long
 
+  # crbug.com/769809
+  'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.browse_accessibility:tools:gmail_compose', # pylint: disable=line-too-long
+
   # crbug.com/
   'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.browse:news:nytimes',  # pylint: disable=line-too-long
 
@@ -61,8 +64,6 @@
   'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.load:tools:drive',  # pylint: disable=line-too-long
   'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.load:tools:gmail',  # pylint: disable=line-too-long
 
-  # crbug.com/699966
-  'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.multitab:misc:typical24', # pylint: disable=line-too-long
   # crbug.com/725386
   'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.browse:social:twitter', # pylint: disable=line-too-long
 
diff --git a/tools/perf/chromium.perf.fyi.extras.json b/tools/perf/chromium.perf.fyi.extras.json
index 47805986..24ec714 100644
--- a/tools/perf/chromium.perf.fyi.extras.json
+++ b/tools/perf/chromium.perf.fyi.extras.json
@@ -71,10 +71,16 @@
         "isolate_name": "telemetry_perf_tests_new",
         "name": "benchmarks for bot 1",
         "override_compile_targets": [
-          "telemetry_perf_tests"
+          "telemetry_perf_tests_new"
         ],
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "id": "swarm823-c4",
+              "pool": "Chrome-perf-fyi"
+            }
+          ],
           "expiration": 36000,
           "hard_timeout": 10800,
           "ignore_task_failure": false,
diff --git a/tools/perf/contrib/cros_benchmarks/data/tab_switching.json b/tools/perf/contrib/cros_benchmarks/data/tab_switching.json
index 473be49..e90bb94 100644
--- a/tools/perf/contrib/cros_benchmarks/data/tab_switching.json
+++ b/tools/perf/contrib/cros_benchmarks/data/tab_switching.json
@@ -1,7 +1,7 @@
 {
     "archives": {
         "cros_tab_switching_typical24": {
-            "DEFAULT": "tab_switching.wpr"
+            "DEFAULT": "tab_switching.wprgo"
         }
     },
     "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.",
diff --git a/tools/perf/contrib/cros_benchmarks/data/tab_switching.wpr.sha1 b/tools/perf/contrib/cros_benchmarks/data/tab_switching.wpr.sha1
deleted file mode 100644
index ef87891..0000000
--- a/tools/perf/contrib/cros_benchmarks/data/tab_switching.wpr.sha1
+++ /dev/null
@@ -1 +0,0 @@
-fdf3c3844b38e9ff07fd3031b7c7f893867460a7
\ No newline at end of file
diff --git a/tools/perf/contrib/cros_benchmarks/data/tab_switching.wprgo.sha1 b/tools/perf/contrib/cros_benchmarks/data/tab_switching.wprgo.sha1
new file mode 100644
index 0000000..9fd6cb1
--- /dev/null
+++ b/tools/perf/contrib/cros_benchmarks/data/tab_switching.wprgo.sha1
@@ -0,0 +1 @@
+42341cef9c0292dd30179051f674cdc0800dd19b
\ No newline at end of file
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index c5a9042e..5ca615ea 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -122,17 +122,21 @@
   return waterfall
 
 
+# Additional compile targets to add to builders.
+BUILDER_ADDITIONAL_COMPILE_TARGETS = {
+    'Android Compile': ['microdump_stackwalk'],
+    'Android arm64 Compile': ['microdump_stackwalk'],
+    # crbug.com/758630. Test builder, will be removed.
+    'Linux Builder': ['telemetry_perf_tests_new'],
+}
+
+
 def get_waterfall_config():
   waterfall = {'builders':{}, 'testers': {}}
 
-  waterfall = add_builder(
-      waterfall, 'Android Compile', additional_compile_targets=[
-          'microdump_stackwalk'
-      ])
-  waterfall = add_builder(
-      waterfall, 'Android arm64 Compile', additional_compile_targets=[
-          'microdump_stackwalk'
-      ])
+  for builder, targets in BUILDER_ADDITIONAL_COMPILE_TARGETS.items():
+    waterfall = add_builder(
+        waterfall, builder, additional_compile_targets=targets)
 
   # These configurations are taken from chromium_perf.py in
   # build/scripts/slave/recipe_modules/chromium_tests and must be kept in sync
@@ -1049,9 +1053,8 @@
     elif 'scripts' in tests[t]:
       scripts = tests[t]['scripts']
     else:
-      assert('Android Compile' == t
-        or 'Android arm64 Compile' == t
-        or t.startswith('AAAAA')), 'Unknown test data %s' % t
+      assert(t in BUILDER_ADDITIONAL_COMPILE_TARGETS
+             or t.startswith('AAAAA')), 'Unknown test data %s' % t
     for s in scripts:
       name = s['name']
       name = re.sub('\\.reference$', '', name)
diff --git a/tools/perf/page_sets/data/loading_mobile.json b/tools/perf/page_sets/data/loading_mobile.json
index b364e63..f1e82ba2 100644
--- a/tools/perf/page_sets/data/loading_mobile.json
+++ b/tools/perf/page_sets/data/loading_mobile.json
@@ -1,8 +1,23 @@
 {
     "archives": {
+        "DevOpera": {
+            "DEFAULT": "loading_mobile_003.wprgo"
+        },
         "Facebook": {
             "DEFAULT": "loading_mobile_002.wprgo"
         },
+        "FlipBoard": {
+            "DEFAULT": "loading_mobile_003.wprgo"
+        },
+        "FlipKart": {
+            "DEFAULT": "loading_mobile_003.wprgo"
+        },
+        "Suumo": {
+            "DEFAULT": "loading_mobile_003.wprgo"
+        },
+        "VoiceMemos": {
+            "DEFAULT": "loading_mobile_003.wprgo"
+        },
         "http://enquiry.indianrail.gov.in/mntes/MntesServlet?action=MainMenu&subAction=excep&excpType=EC": {
             "DEFAULT": "loading_mobile_000.wprgo"
         },
@@ -96,27 +111,9 @@
         "http://xw.qq.com/news/20160803025029/NEW2016080302502901": {
             "DEFAULT": "loading_mobile_000.wprgo"
         },
-        "https://2048-opera-pwa.surge.sh/": {
-            "DEFAULT": "loading_mobile_000.wprgo"
-        },
-        "https://andreasbovens.github.io/inbox-attack/": {
-            "DEFAULT": "loading_mobile_000.wprgo"
-        },
-        "https://dev.opera.com/": {
-            "DEFAULT": "loading_mobile_000.wprgo"
-        },
         "https://en.m.wikipedia.org/wiki/Solo_Foods": {
             "DEFAULT": "loading_mobile_000.wprgo"
         },
-        "https://flipboard.com/topic/yoga": {
-            "DEFAULT": "loading_mobile_000.wprgo"
-        },
-        "https://guitar-tuner.appspot.com": {
-            "DEFAULT": "loading_mobile_000.wprgo"
-        },
-        "https://jakearchibald.github.io/trained-to-thrill/": {
-            "DEFAULT": "loading_mobile_000.wprgo"
-        },
         "https://m.baidu.com/s?word=%E9%B2%9C%E8%8A%B1%E9%80%9F%E9%80%92&oq=%E9%B2%9C%E8%8A%B1": {
             "DEFAULT": "loading_mobile_000.wprgo"
         },
@@ -126,18 +123,6 @@
         "https://mobile.twitter.com/scottjehl/status/760618697727803394": {
             "DEFAULT": "loading_mobile_000.wprgo"
         },
-        "https://smp.suumo.jp/mansion/tokyo/sc_104/cond/?moreCond=1": {
-            "DEFAULT": "loading_mobile_000.wprgo"
-        },
-        "https://townwork.net": {
-            "DEFAULT": "loading_mobile_000.wprgo"
-        },
-        "https://voice-memos.appspot.com": {
-            "DEFAULT": "loading_mobile_000.wprgo"
-        },
-        "https://www.flipkart.com/big-wing-casuals/p/itmemeageyfn6m9z?lid=LSTSHOEMEAGURG2PHPW18FTBN&pid=SHOEMEAGURG2PHPW": {
-            "DEFAULT": "loading_mobile_000.wprgo"
-        },
         "https://www.google.co.id/#q=pengiriman+bunga": {
             "DEFAULT": "loading_mobile_000.wprgo"
         },
@@ -150,13 +135,10 @@
         "https://www.google.com/search?q=flower#q=flower+delivery": {
             "DEFAULT": "loading_mobile_000.wprgo"
         },
-        "https://www.pokedex.org/": {
-            "DEFAULT": "loading_mobile_000.wprgo"
-        },
         "https://www.youtube.com/watch?v=MU3YuvNRhVY": {
             "DEFAULT": "loading_mobile_000.wprgo"
         }
     },
     "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.",
     "platform_specific": true
-}
\ No newline at end of file
+}
diff --git a/tools/perf/page_sets/data/loading_mobile_003.wprgo.sha1 b/tools/perf/page_sets/data/loading_mobile_003.wprgo.sha1
new file mode 100644
index 0000000..978ec5f
--- /dev/null
+++ b/tools/perf/page_sets/data/loading_mobile_003.wprgo.sha1
@@ -0,0 +1 @@
+e075a38890b06bc2bf5566a139b6872f453be3b2
\ No newline at end of file
diff --git a/tools/perf/page_sets/loading_mobile.py b/tools/perf/page_sets/loading_mobile.py
index 1849edeb..a6455706 100644
--- a/tools/perf/page_sets/loading_mobile.py
+++ b/tools/perf/page_sets/loading_mobile.py
@@ -16,7 +16,8 @@
   Design doc: https://docs.google.com/document/d/1QKlZIoURAxZk-brrXsKYZl9O8ieqXht3ogeF9yLNFCI/edit
   """
 
-  def __init__(self, cache_temperatures=None, traffic_settings=None):
+  def __init__(self, cache_temperatures=None, cache_temperatures_for_pwa=None,
+               traffic_settings=None):
     super(LoadingMobileStorySet, self).__init__(
         archive_data_file='data/loading_mobile.json',
         cloud_storage_bucket=story.PARTNER_BUCKET)
@@ -24,6 +25,9 @@
     if cache_temperatures is None:
       cache_temperatures = [cache_temperature_module.ANY]
 
+    if cache_temperatures_for_pwa is None:
+      cache_temperatures_for_pwa = [cache_temperature_module.ANY]
+
     if traffic_settings is None:
       traffic_settings = [traffic_setting_module.NONE]
 
@@ -87,23 +91,15 @@
        'FlipKart'),
       ('https://smp.suumo.jp/mansion/tokyo/sc_104/cond/?moreCond=1',
        'Suumo'),
-      ('https://guitar-tuner.appspot.com', 'GuitarTuner'),
-      ('https://andreasbovens.github.io/inbox-attack/',
-       'InboxAttack'),
       ('https://voice-memos.appspot.com', 'VoiceMemos'),
       ('https://dev.opera.com/', 'DevOpera'),
-      ('https://www.pokedex.org/', 'Pokedex'),
-      ('https://2048-opera-pwa.surge.sh/', '2048'),
-      ('https://jakearchibald.github.io/trained-to-thrill/',
-       'TrainedToThrill'),
-      ('https://townwork.net', 'TownWork'),
       ('https://flipboard.com/topic/yoga', 'FlipBoard'),
       # TODO(rnephew): Record these. crbug.com/728882
       # ('https://wiki-offline.jakearchibald.com/',
       #  'WikiOffline'),
       # ('https://busrouter.sg', 'BusRouter'),
       # ('https://airhorner.com', 'AirHorner'),
-    ], cache_temperatures, traffic_settings)
+    ], cache_temperatures_for_pwa, traffic_settings)
 
     self.AddStories(['tough_ttfmp'], [
       ('http://www.localmoxie.com', 'LocalMoxie'),
diff --git a/tools/perf/page_sets/system_health/expectations.py b/tools/perf/page_sets/system_health/expectations.py
index 279e42d..627aab63 100644
--- a/tools/perf/page_sets/system_health/expectations.py
+++ b/tools/perf/page_sets/system_health/expectations.py
@@ -26,6 +26,8 @@
                       [expectations.MAC_10_11], 'crbug.com/760966')
     self.DisableStory('browse:news:cnn',
                       [expectations.ALL_MAC], 'crbug.com/728576')
+    self.DisableStory('browse_accessibility:tools:gmail_compose',
+                      [expectations.ALL], 'crbug.com/769809')
 
 
 class SystemHealthDesktopMemoryExpectations(expectations.StoryExpectations):
diff --git a/tools/tests/OWNERS b/tools/tests/OWNERS
index 704ad91..b094cbb 100644
--- a/tools/tests/OWNERS
+++ b/tools/tests/OWNERS
@@ -1,3 +1,2 @@
 per-file licenses_test.py=phajdan.jr@chromium.org
-per-file licenses_test.py=sgurun@chromium.org
 per-file licenses_test.py=torne@chromium.org
diff --git a/tools/traffic_annotation/auditor/BUILD.gn b/tools/traffic_annotation/auditor/BUILD.gn
index e9e563a2..9c10ed16 100644
--- a/tools/traffic_annotation/auditor/BUILD.gn
+++ b/tools/traffic_annotation/auditor/BUILD.gn
@@ -58,7 +58,7 @@
     "traffic_annotation_file_filter.h",
   ]
   data = [
-    "white_list.txt",
+    "safe_list.txt",
   ]
 
   public_deps = [
@@ -84,6 +84,8 @@
     "traffic_annotation_auditor_unittest.cc",
   ]
   data = [
+    "tests/extractor_outputs/bad_assignment1.txt",
+    "tests/extractor_outputs/bad_assignment2.txt",
     "tests/extractor_outputs/bad_call.txt",
     "tests/extractor_outputs/bad_syntax_annotation1.txt",
     "tests/extractor_outputs/bad_syntax_annotation2.txt",
@@ -92,6 +94,7 @@
     "tests/extractor_outputs/fatal_annotation1.txt",
     "tests/extractor_outputs/fatal_annotation2.txt",
     "tests/extractor_outputs/fatal_annotation3.txt",
+    "tests/extractor_outputs/good_assignment.txt",
     "tests/extractor_outputs/good_branched_completing_annotation.txt",
     "tests/extractor_outputs/good_call.txt",
     "tests/extractor_outputs/good_complete_annotation.txt",
diff --git a/tools/traffic_annotation/auditor/traffic_annotation_auditor.cc b/tools/traffic_annotation/auditor/traffic_annotation_auditor.cc
index 66cd3c8d..11b6d9de 100644
--- a/tools/traffic_annotation/auditor/traffic_annotation_auditor.cc
+++ b/tools/traffic_annotation/auditor/traffic_annotation_auditor.cc
@@ -53,18 +53,6 @@
   AnnotationInstance* instance;
 };
 
-// Removes all occurances of a charcter from a string and returns the modified
-// string.
-std::string RemoveChar(const std::string& source, char removee) {
-  std::string output;
-  output.reserve(source.length());
-  for (const char* current = source.data(); *current; current++) {
-    if (*current != removee)
-      output += *current;
-  }
-  return output;
-}
-
 const std::string kBlockTypes[] = {"ASSIGNMENT", "ANNOTATION", "CALL"};
 
 const base::FilePath kSafeListPath =
@@ -218,11 +206,10 @@
   if (!safe_list_loaded_ && !LoadSafeList())
     return false;
   // Remove possible carriage return characters before splitting lines.
-  // Not using base::RemoveChars as the input is ~47M and the implementation is
-  // too slow for it.
-  std::vector<std::string> lines =
-      base::SplitString(RemoveChar(clang_tool_raw_output_, '\r'), "\n",
-                        base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
+  std::string temp_string;
+  base::RemoveChars(clang_tool_raw_output_, "\r", &temp_string);
+  std::vector<std::string> lines = base::SplitString(
+      temp_string, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
   for (unsigned int current = 0; current < lines.size(); current++) {
     // All blocks reported by clang tool start with '====', so we can ignore
     // all lines that do not start with a '='.
diff --git a/tools/traffic_annotation/auditor/traffic_annotation_auditor_unittest.cc b/tools/traffic_annotation/auditor/traffic_annotation_auditor_unittest.cc
index 4bf024f..b9ef384 100644
--- a/tools/traffic_annotation/auditor/traffic_annotation_auditor_unittest.cc
+++ b/tools/traffic_annotation/auditor/traffic_annotation_auditor_unittest.cc
@@ -121,7 +121,8 @@
   EXPECT_TRUE(base::ReadFileToString(
       tests_folder_.Append(FILE_PATH_LITERAL("extractor_outputs"))
           .AppendASCII(file_name),
-      &file_content));
+      &file_content))
+      << file_name;
   base::RemoveChars(file_content, "\r", &file_content);
   std::vector<std::string> lines = base::SplitString(
       file_content, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
@@ -881,4 +882,4 @@
 TEST_F(TrafficAnnotationAuditorTest, GetClangLibraryPath) {
   base::FilePath clang_library = auditor().GetClangLibraryPath();
   EXPECT_FALSE(clang_library.empty());
-}
\ No newline at end of file
+}
diff --git a/tools/win/ShowThreadNames/ReadMe.txt b/tools/win/ShowThreadNames/ReadMe.txt
index e322aa3c..c4bf66ab 100644
--- a/tools/win/ShowThreadNames/ReadMe.txt
+++ b/tools/win/ShowThreadNames/ReadMe.txt
@@ -2,11 +2,11 @@
 This tool is designed to test the usage of the SetThreadDescription WinAPI in
 Chrome. In Chrome, the SetThreadDescription API has been enabled to set thread
 names. However, since there is no tool support to retrieve thread names set by
-GetThreadDescription, we'll still rely on SetNameInternal function in
+GetThreadDescription, we'll still rely on SetNameInternal function in 
 platform_thread_win.cc to set thread names. Despite this, we need a tool to demo
 the SetThreadDescription API works, even without the debugger to be present.
 
-The problem setting can be referred to
+The problem setting can be referred to 
 https://bugs.chromium.org/p/chromium/issues/detail?id=684203
 
 This tool incorporates the GetThreadDescription API trying to get names of all
@@ -20,11 +20,11 @@
 later ones.
 
 [How to use it]
-Please download the three files (.cc, .sln, .vcxproj) and compile the code in
-Visual Studio. Run "ShowThreadNames.exe" either from the build directory or from
-Visual Studio. No parameters are needed. This tool allows interaction with the
-user. Once launched, it will show "Please enter the process Id, or "quit" to
-end the program :" on the terminal. Simply type in the ID of any Chrome process
+Please download the three files (.cc, .sln, .vcxproj) and compile the code in 
+Visual Studio. Run "ShowThreadNames.exe" either from the build directory or from 
+Visual Studio. No parameters are needed. This tool allows interaction with the 
+user. Once launched, it will show "Please enter the process Id, or "quit" to 
+end the program :" on the terminal. Simply type in the ID of any Chrome process 
 you are interested in, and you will get output like below:
 
 thread_ID   thread_name
@@ -37,7 +37,10 @@
 2256    AudioThread
 9308    BrokerEvent
 5668    BrowserWatchdog
+4352    Chrome_CacheThread
+12268   Chrome_DBThread
 8616    Chrome_FileThread
+1072    Chrome_FileUserBlockingThread
 8280    Chrome_HistoryThread
 7472    Chrome_IOThread
 6336    Chrome_ProcessLauncherThread
@@ -52,6 +55,6 @@
 8216    TaskSchedulerServiceThread
 11088   VideoCaptureThread
 
-The threads are sorted by their names. Note that some threads have no names in
-this example. If checking them using Visual Studio debugger, it is found that
+The threads are sorted by their names. Note that some threads have no names in 
+this example. If checking them using Visual Studio debugger, it is found that 
 they are ntdll.dll!WorkerThreads.
diff --git a/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm b/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
index d9be65f..daeff4c 100644
--- a/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
+++ b/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
@@ -22,33 +22,6 @@
 #include "ui/gl/ca_renderer_layer_params.h"
 #include "ui/gl/gl_image_io_surface.h"
 
-#if !defined(MAC_OS_X_VERSION_10_8) || \
-    MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8
-extern NSString* const AVLayerVideoGravityResize;
-extern "C" void NSAccessibilityPostNotificationWithUserInfo(
-    id object,
-    NSString* notification,
-    NSDictionary* user_info);
-extern "C" OSStatus CMSampleBufferCreateForImageBuffer(
-    CFAllocatorRef,
-    CVImageBufferRef,
-    Boolean dataReady,
-    CMSampleBufferMakeDataReadyCallback,
-    void*,
-    CMVideoFormatDescriptionRef,
-    const CMSampleTimingInfo*,
-    CMSampleBufferRef*);
-extern "C" CFArrayRef CMSampleBufferGetSampleAttachmentsArray(CMSampleBufferRef,
-                                                              Boolean);
-extern "C" OSStatus CMVideoFormatDescriptionCreateForImageBuffer(
-    CFAllocatorRef,
-    CVImageBufferRef,
-    CMVideoFormatDescriptionRef*);
-extern "C" CMTime CMTimeMake(int64_t, int32_t);
-extern CFStringRef const kCMSampleAttachmentKey_DisplayImmediately;
-extern const CMTime kCMTimeInvalid;
-#endif  // MAC_OS_X_VERSION_10_8
-
 namespace ui {
 
 namespace {
diff --git a/ui/accessibility/PRESUBMIT.py b/ui/accessibility/PRESUBMIT.py
index 31b9a6e..f953d4f 100644
--- a/ui/accessibility/PRESUBMIT.py
+++ b/ui/accessibility/PRESUBMIT.py
@@ -91,6 +91,8 @@
 
   # Focused state only exists in automation.
   automation_enums['StateType'].remove('focused')
+  # Offscreen state only exists in automation.
+  automation_enums['StateType'].remove('offscreen')
 
   errs = []
   CheckMatchingEnum(ax_enums, 'AXRole', automation_enums, 'RoleType', errs,
diff --git a/ui/accessibility/ax_enums.idl b/ui/accessibility/ax_enums.idl
index 8d5cf9e3..c635a14 100644
--- a/ui/accessibility/ax_enums.idl
+++ b/ui/accessibility/ax_enums.idl
@@ -217,7 +217,6 @@
     linked,
     multiline,
     multiselectable,
-    offscreen,
     protected,
     required,
     richly_editable,
diff --git a/ui/accessibility/platform/ax_platform_node_base.cc b/ui/accessibility/platform/ax_platform_node_base.cc
index e7755b5..cf0ff4c 100644
--- a/ui/accessibility/platform/ax_platform_node_base.cc
+++ b/ui/accessibility/platform/ax_platform_node_base.cc
@@ -319,6 +319,7 @@
 
 bool AXPlatformNodeBase::IsRangeValueSupported() const {
   switch (GetData().role) {
+    case AX_ROLE_METER:
     case AX_ROLE_PROGRESS_INDICATOR:
     case AX_ROLE_SLIDER:
     case AX_ROLE_SPIN_BUTTON:
diff --git a/ui/accessibility/platform/ax_platform_node_delegate.h b/ui/accessibility/platform/ax_platform_node_delegate.h
index ff9325e..c4cb1da 100644
--- a/ui/accessibility/platform/ax_platform_node_delegate.h
+++ b/ui/accessibility/platform/ax_platform_node_delegate.h
@@ -76,6 +76,9 @@
   // has focus.
   virtual gfx::NativeViewAccessible GetFocus() = 0;
 
+  // Get whether this node is offscreen.
+  virtual bool IsOffscreen() const = 0;
+
   virtual AXPlatformNode* GetFromNodeID(int32_t id) = 0;
 
   //
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc
index d452a00c..530c656 100644
--- a/ui/accessibility/platform/ax_platform_node_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -3572,7 +3572,7 @@
     msaa_state |= STATE_SYSTEM_MULTISELECTABLE;
   }
 
-  if (data.HasState(AX_STATE_OFFSCREEN))
+  if (delegate_->IsOffscreen())
     msaa_state |= STATE_SYSTEM_OFFSCREEN;
 
   if (data.HasState(AX_STATE_PROTECTED))
diff --git a/ui/accessibility/platform/ax_system_caret_win.cc b/ui/accessibility/platform/ax_system_caret_win.cc
index ec11277..aaf82cf9 100644
--- a/ui/accessibility/platform/ax_system_caret_win.cc
+++ b/ui/accessibility/platform/ax_system_caret_win.cc
@@ -119,4 +119,8 @@
   return false;
 }
 
+bool AXSystemCaretWin::IsOffscreen() const {
+  return false;
+}
+
 }  // namespace ui
diff --git a/ui/accessibility/platform/ax_system_caret_win.h b/ui/accessibility/platform/ax_system_caret_win.h
index 05dd4ae..21652b6a 100644
--- a/ui/accessibility/platform/ax_system_caret_win.h
+++ b/ui/accessibility/platform/ax_system_caret_win.h
@@ -48,6 +48,7 @@
   gfx::AcceleratedWidget GetTargetForNativeAccessibilityEvent() override;
   bool AccessibilityPerformAction(const AXActionData& data) override;
   bool ShouldIgnoreHoveredStateForTesting() override;
+  bool IsOffscreen() const override;
 
   AXPlatformNodeWin* caret_;
   gfx::AcceleratedWidget event_target_;
diff --git a/ui/accessibility/platform/test_ax_node_wrapper.cc b/ui/accessibility/platform/test_ax_node_wrapper.cc
index c15cf8f..a78075f 100644
--- a/ui/accessibility/platform/test_ax_node_wrapper.cc
+++ b/ui/accessibility/platform/test_ax_node_wrapper.cc
@@ -225,6 +225,10 @@
   return true;
 }
 
+bool TestAXNodeWrapper::IsOffscreen() const {
+  return false;
+}
+
 TestAXNodeWrapper::TestAXNodeWrapper(AXTree* tree, AXNode* node)
     : tree_(tree),
       node_(node),
diff --git a/ui/accessibility/platform/test_ax_node_wrapper.h b/ui/accessibility/platform/test_ax_node_wrapper.h
index d0f1603..0f50c843 100644
--- a/ui/accessibility/platform/test_ax_node_wrapper.h
+++ b/ui/accessibility/platform/test_ax_node_wrapper.h
@@ -45,6 +45,7 @@
   gfx::AcceleratedWidget GetTargetForNativeAccessibilityEvent() override;
   bool AccessibilityPerformAction(const AXActionData& data) override;
   bool ShouldIgnoreHoveredStateForTesting() override;
+  bool IsOffscreen() const override;
 
  private:
   TestAXNodeWrapper(AXTree* tree, AXNode* node);
diff --git a/ui/app_list/pagination_controller.cc b/ui/app_list/pagination_controller.cc
index a896419..46d9e4b 100644
--- a/ui/app_list/pagination_controller.cc
+++ b/ui/app_list/pagination_controller.cc
@@ -28,7 +28,7 @@
     : pagination_model_(model), scroll_axis_(scroll_axis) {}
 
 bool PaginationController::OnScroll(const gfx::Vector2d& offset,
-                                    ScrollEventType type) {
+                                    ui::EventType type) {
   int offset_magnitude;
   if (scroll_axis_ == SCROLL_AXIS_HORIZONTAL) {
     // If the view scrolls horizontally, both horizontal and vertical scroll
@@ -47,10 +47,11 @@
       !pagination_model_->has_transition()) {
     const int delta = offset_magnitude > 0 ? -1 : 1;
     if (pagination_model_->IsValidPageRelative(delta)) {
-      UMA_HISTOGRAM_ENUMERATION(
-          kAppListPageSwitcherSourceHistogram,
-          type == SCROLL_MOUSE_WHEEL ? kMouseWheelScroll : kMousePadScroll,
-          kMaxAppListPageSwitcherSource);
+      UMA_HISTOGRAM_ENUMERATION(kAppListPageSwitcherSourceHistogram,
+                                type == ui::EventType::ET_MOUSEWHEEL
+                                    ? kMouseWheelScroll
+                                    : kMousePadScroll,
+                                kMaxAppListPageSwitcherSource);
     }
     pagination_model_->SelectPageRelative(delta, true);
     return true;
diff --git a/ui/app_list/pagination_controller.h b/ui/app_list/pagination_controller.h
index 5012deb2..86aacd8 100644
--- a/ui/app_list/pagination_controller.h
+++ b/ui/app_list/pagination_controller.h
@@ -6,6 +6,7 @@
 #define UI_APP_LIST_PAGINATION_CONTROLLER_H_
 
 #include "ui/app_list/app_list_export.h"
+#include "ui/events/event_constants.h"
 
 namespace gfx {
 class Vector2d;
@@ -24,8 +25,6 @@
 // touch gestures) and manipulates a PaginationModel as necessary.
 class APP_LIST_EXPORT PaginationController {
  public:
-  enum ScrollEventType { SCROLL_MOUSE_WHEEL, SCROLL_TOUCHPAD };
-
   enum ScrollAxis { SCROLL_AXIS_HORIZONTAL, SCROLL_AXIS_VERTICAL };
 
   // Creates a PaginationController. Does not take ownership of |model|. The
@@ -38,7 +37,7 @@
   // Handles a mouse wheel or touchpad scroll event in the area represented by
   // the PaginationModel. |offset| is the number of units scrolled in each axis.
   // Returns true if the event was captured and there was some room to scroll.
-  bool OnScroll(const gfx::Vector2d& offset, ScrollEventType type);
+  bool OnScroll(const gfx::Vector2d& offset, ui::EventType type);
 
   // Handles a touch gesture event in the area represented by the
   // PaginationModel. Returns true if the event was captured.
diff --git a/ui/app_list/pagination_model_unittest.cc b/ui/app_list/pagination_model_unittest.cc
index 05c3edb00..a2ee6f2 100644
--- a/ui/app_list/pagination_model_unittest.cc
+++ b/ui/app_list/pagination_model_unittest.cc
@@ -439,5 +439,24 @@
   EXPECT_EQ(0, pagination_.selected_page());
 }
 
+TEST_F(PaginationModelTest, SelectPageRelativeBeginning) {
+  // Test starts with 5 pages. Select Page 1.
+  pagination_.SelectPage(1, false);
+
+  pagination_.SelectPageRelative(-1, false);
+  EXPECT_EQ(0, pagination_.selected_page());
+}
+
+TEST_F(PaginationModelTest, SelectPageRelativeMiddle) {
+  // Test starts with 5 pages. Select page 2.
+  pagination_.SelectPage(2, false);
+
+  pagination_.SelectPageRelative(-1, false);
+  EXPECT_EQ(1, pagination_.selected_page());
+
+  pagination_.SelectPageRelative(1, false);
+  EXPECT_EQ(2, pagination_.selected_page());
+}
+
 }  // namespace test
 }  // namespace app_list
diff --git a/ui/app_list/views/app_list_view.cc b/ui/app_list/views/app_list_view.cc
index f0ba1cc..15099f9 100644
--- a/ui/app_list/views/app_list_view.cc
+++ b/ui/app_list/views/app_list_view.cc
@@ -10,6 +10,7 @@
 #include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_util.h"
+#include "base/timer/elapsed_timer.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"
@@ -234,9 +235,7 @@
       is_background_blur_enabled_(features::IsBackgroundBlurEnabled()),
       is_app_list_focus_enabled_(features::IsAppListFocusEnabled()),
       display_observer_(this),
-      animation_observer_(new HideViewAnimationObserver()),
-      previous_arrow_key_traversal_enabled_(
-          views::FocusManager::arrow_key_traversal_enabled()) {
+      animation_observer_(new HideViewAnimationObserver()) {
   CHECK(delegate);
   delegate_->GetSpeechUI()->AddObserver(this);
 
@@ -244,11 +243,6 @@
     display_observer_.Add(display::Screen::GetScreen());
     delegate_->AddObserver(this);
   }
-  if (is_app_list_focus_enabled_) {
-    // Enable arrow key in FocusManager. Arrow left/right and up/down triggers
-    // the same focus movement as tab/shift+tab.
-    views::FocusManager::set_arrow_key_traversal_enabled(true);
-  }
 }
 
 AppListView::~AppListView() {
@@ -259,10 +253,6 @@
   animation_observer_.reset();
   // Remove child views first to ensure no remaining dependencies on delegate_.
   RemoveAllChildViews(true);
-  if (is_app_list_focus_enabled_) {
-    views::FocusManager::set_arrow_key_traversal_enabled(
-        previous_arrow_key_traversal_enabled_);
-  }
 }
 
 // static
@@ -901,9 +891,6 @@
   if (!is_fullscreen_app_list_enabled_)
     return;
 
-  if (event->type() == ui::ET_SCROLL_FLING_CANCEL)
-    return;
-
   if (!HandleScroll(event->y_offset(), event->type()))
     return;
 
@@ -1066,7 +1053,7 @@
                                            ->folder_header_view()
                                            ->HasTextFocus();
   if (is_app_list_focus_enabled_ && !is_search_box_focused &&
-      !is_folder_header_view_focused && !SearchBoxView::IsArrowKey(*event)) {
+      !is_folder_header_view_focused) {
     views::Textfield* search_box = search_box_view_->search_box();
     // Redirect key event to |search_box_|.
     search_box->OnKeyEvent(event);
@@ -1095,35 +1082,48 @@
 }
 
 bool AppListView::HandleScroll(int offset, ui::EventType type) {
-  if (app_list_state_ != PEEKING)
+  if (app_list_state_ != PEEKING && app_list_state_ != FULLSCREEN_ALL_APPS)
     return false;
 
-  switch (type) {
-    case ui::ET_MOUSEWHEEL:
-      SetState(offset < 0 ? FULLSCREEN_ALL_APPS : CLOSED);
-      if (app_list_state_ == FULLSCREEN_ALL_APPS) {
-        UMA_HISTOGRAM_ENUMERATION(kAppListPeekingToFullscreenHistogram,
-                                  kMousewheelScroll, kMaxPeekingToFullscreen);
-      }
-      // Return true unconditionally because all mousewheel events are large
-      // enough to transition the app list.
-      return true;
-    case ui::ET_SCROLL:
-    case ui::ET_SCROLL_FLING_START: {
-      if (abs(offset) > kAppListMinScrollToSwitchStates) {
-        SetState(offset < 0 ? FULLSCREEN_ALL_APPS : CLOSED);
-        if (app_list_state_ == FULLSCREEN_ALL_APPS) {
-          UMA_HISTOGRAM_ENUMERATION(kAppListPeekingToFullscreenHistogram,
-                                    kMousepadScroll, kMaxPeekingToFullscreen);
-        }
-        return true;
-      }
-      break;
-    }
-    default:
-      break;
+  // Let the Apps grid view handle the event first in FULLSCREEN_ALL_APPS.
+  if (app_list_state_ == FULLSCREEN_ALL_APPS &&
+      GetAppsGridView()->HandleScrollFromAppListView(offset, type)) {
+    // Set the scroll ignore timer to avoid processing the tail end of the
+    // stream of scroll events, which would close the view.
+    SetOrRestartScrollIgnoreTimer();
+    return true;
   }
-  return false;
+
+  if (ShouldIgnoreScrollEvents())
+    return true;
+
+  // If the event is a mousewheel event, the offset is always large enough,
+  // otherwise the offset must be larger than the scroll threshold.
+  if (type == ui::ET_MOUSEWHEEL ||
+      abs(offset) > kAppListMinScrollToSwitchStates) {
+    if (offset >= 0) {
+      Dismiss();
+    } else {
+      if (app_list_state_ == FULLSCREEN_ALL_APPS)
+        return true;
+      SetState(FULLSCREEN_ALL_APPS);
+      const AppListPeekingToFullscreenSource source =
+          type == ui::ET_MOUSEWHEEL ? kMousewheelScroll : kMousepadScroll;
+      UMA_HISTOGRAM_ENUMERATION(kAppListPeekingToFullscreenHistogram, source,
+                                kMaxPeekingToFullscreen);
+    }
+  }
+  return true;
+}
+
+void AppListView::SetOrRestartScrollIgnoreTimer() {
+  scroll_ignore_timer_.reset(new base::ElapsedTimer());
+}
+
+bool AppListView::ShouldIgnoreScrollEvents() {
+  return scroll_ignore_timer_ &&
+         scroll_ignore_timer_->Elapsed() <=
+             base::TimeDelta::FromMilliseconds(kScrollIgnoreTimeMs);
 }
 
 void AppListView::SetState(AppListState new_state) {
@@ -1138,7 +1138,8 @@
     if (new_state == HALF) {
       new_state_override = FULLSCREEN_SEARCH;
     } else if (new_state == PEEKING) {
-      // If the old state was already FULLSCREEN_ALL_APPS, then we should close.
+      // If the old state was already FULLSCREEN_ALL_APPS, then we should
+      // close.
       new_state_override =
           app_list_state_ == FULLSCREEN_ALL_APPS ? CLOSED : FULLSCREEN_ALL_APPS;
     }
@@ -1209,8 +1210,8 @@
 
   // Reset the focus to initially focused view. This should be done before
   // updating visibility of views, because setting focused view invisible
-  // automatically moves focus to next focusable view, which potentially causes
-  // bugs.
+  // automatically moves focus to next focusable view, which potentially
+  // causes bugs.
   GetInitiallyFocusedView()->RequestFocus();
 
   // Updates the visibility of app list items according to the change of
@@ -1480,8 +1481,9 @@
 }
 
 void AppListView::SetBackgroundShieldColor() {
-  // There is a chance when AppListView::OnWallpaperColorsChanged is called from
-  // AppListViewDelegate, the |app_list_background_shield_| is not initialized.
+  // There is a chance when AppListView::OnWallpaperColorsChanged is called
+  // from AppListViewDelegate, the |app_list_background_shield_| is not
+  // initialized.
   if (!is_fullscreen_app_list_enabled_ || !app_list_background_shield_)
     return;
 
diff --git a/ui/app_list/views/app_list_view.h b/ui/app_list/views/app_list_view.h
index 879fda5..fc6e002 100644
--- a/ui/app_list/views/app_list_view.h
+++ b/ui/app_list/views/app_list_view.h
@@ -23,6 +23,10 @@
 class Window;
 }
 
+namespace base {
+class ElapsedTimer;
+}
+
 namespace display {
 class Screen;
 }
@@ -65,6 +69,10 @@
   // The defualt color of the app list background.
   static constexpr SkColor kDefaultBackgroundColor = SK_ColorBLACK;
 
+  // The duration the AppListView ignores scroll events which could transition
+  // its state.
+  static constexpr int kScrollIgnoreTimeMs = 500;
+
   enum AppListState {
     // Closes |app_list_main_view_| and dismisses the delegate.
     CLOSED = 0,
@@ -246,6 +254,12 @@
   // AppListView.
   void HandleClickOrTap(ui::LocatedEvent* event);
 
+  // Sets or restarts the scroll ignore timer.
+  void SetOrRestartScrollIgnoreTimer();
+
+  // Whether scroll events should be ignored.
+  bool ShouldIgnoreScrollEvents();
+
   // Initializes |initial_drag_point_|.
   void StartDrag(const gfx::Point& location);
 
@@ -375,12 +389,12 @@
   // True if the dragging started from PEEKING state.
   bool drag_started_from_peeking_ = false;
 
+  // Timer to ignore scroll events which would close the view by accident.
+  std::unique_ptr<base::ElapsedTimer> scroll_ignore_timer_;
+
   // Accessibility announcement dialogue.
   base::string16 state_announcement_;
 
-  // Whether FocusManager can handle arrow key before this class is constructed.
-  const bool previous_arrow_key_traversal_enabled_;
-
   DISALLOW_COPY_AND_ASSIGN(AppListView);
 };
 
diff --git a/ui/app_list/views/app_list_view_unittest.cc b/ui/app_list/views/app_list_view_unittest.cc
index 791dc5d..2bef6b3 100644
--- a/ui/app_list/views/app_list_view_unittest.cc
+++ b/ui/app_list/views/app_list_view_unittest.cc
@@ -6,7 +6,6 @@
 
 #include <stddef.h>
 
-#include <algorithm>
 #include <string>
 #include <vector>
 
@@ -31,7 +30,6 @@
 #include "ui/app_list/views/apps_grid_view.h"
 #include "ui/app_list/views/contents_view.h"
 #include "ui/app_list/views/expand_arrow_view.h"
-#include "ui/app_list/views/folder_header_view.h"
 #include "ui/app_list/views/search_box_view.h"
 #include "ui/app_list/views/search_result_list_view.h"
 #include "ui/app_list/views/search_result_page_view.h"
@@ -211,7 +209,6 @@
     params.is_tablet_mode = is_tablet_mode;
     params.is_side_shelf = is_side_shelf;
     view_->Initialize(params);
-    // Initialize around a point that ensures the window is wholly shown.
     EXPECT_FALSE(view_->GetWidget()->IsVisible());
   }
 
@@ -332,21 +329,14 @@
     view_->Initialize(params);
     test_api_.reset(new AppsGridViewTestApi(apps_grid_view()));
 
-    // Add suggestion apps, a folder with apps and other app list items.
-    const int kSuggestionAppNum = 3;
-    const int kItemNumInFolder = 8;
+    // Add suggestion apps and app list items.
+    const int kSuggestionAppNum = 5;
     const int kAppListItemNum = test_api_->TilesPerPage(0) + 1;
     AppListTestModel* model = delegate_->GetTestModel();
     for (size_t i = 0; i < kSuggestionAppNum; i++)
       model->results()->Add(base::MakeUnique<TestStartPageSearchResult>());
-    AppListFolderItem* folder_item =
-        model->CreateAndPopulateFolderWithApps(kItemNumInFolder);
     model->PopulateApps(kAppListItemNum);
     apps_grid_view()->ResetForShowApps();
-    EXPECT_EQ(static_cast<size_t>(kAppListItemNum + 1),
-              model->top_level_item_list()->item_count());
-    EXPECT_EQ(folder_item->id(),
-              model->top_level_item_list()->item_at(0)->id());
 
     // Disable animation timer.
     view_->GetWidget()->GetLayer()->GetAnimator()->set_disable_timer_for_test(
@@ -413,20 +403,6 @@
     return delegate_->open_search_result_count();
   }
 
-  // Test focus traversal across all the views in |view_list|. The initial focus
-  // is expected to be on the first view in |view_list|. The final focus is
-  // expected to be on the last view in |view_list| after |view_list.size()-1|
-  // key events are pressed.
-  void TestFocusTraversal(const std::vector<views::View*>& view_list,
-                          ui::KeyboardCode key_code,
-                          bool shift_down) {
-    EXPECT_EQ(view_list[0], focused_view());
-    for (size_t i = 1; i < view_list.size(); ++i) {
-      SimulateKeyPress(key_code, shift_down);
-      EXPECT_EQ(view_list[i], focused_view());
-    }
-  }
-
   AppListView* app_list_view() { return view_; }
 
   AppListMainView* main_view() { return view_->app_list_main_view(); }
@@ -442,23 +418,12 @@
         ->apps_grid_view();
   }
 
-  AppListFolderView* app_list_folder_view() {
-    return main_view()
-        ->contents_view()
-        ->apps_container_view()
-        ->app_list_folder_view();
-  }
-
   SuggestionsContainerView* suggestions_container_view() {
     return apps_grid_view()->suggestions_container_for_test();
   }
 
   SearchBoxView* search_box_view() { return main_view()->search_box_view(); }
 
-  AppListItemView* folder_item_view() {
-    return apps_grid_view()->view_model_for_test()->view_at(0);
-  }
-
   views::View* focused_view() {
     return view_->GetWidget()->GetFocusManager()->GetFocusedView();
   }
@@ -480,77 +445,53 @@
   EXPECT_EQ(search_box_view()->search_box(), focused_view());
 }
 
-// Tests the linear focus traversal in PEEKING state.
-TEST_F(AppListViewFocusTest, LinearFocusTraversalInPeekingState) {
+// Tests the focus traversal triggered by tab in peeking state.
+TEST_F(AppListViewFocusTest, FocusTraversalInPeekingState) {
   Show();
   SetAppListState(AppListView::PEEKING);
 
-  std::vector<views::View*> forward_view_list;
-  forward_view_list.push_back(search_box_view()->search_box());
-  for (int i = 0; i < suggestions_container_view()->num_results(); ++i)
-    forward_view_list.push_back(suggestions_container_view()->tile_views()[i]);
-  forward_view_list.push_back(apps_grid_view()->expand_arrow_view_for_test());
-  forward_view_list.push_back(search_box_view()->search_box());
-  std::vector<views::View*> backward_view_list = forward_view_list;
-  std::reverse(backward_view_list.begin(), backward_view_list.end());
+  // Move focus along suggestion apps.
+  for (views::View* v : suggestions_container_view()->tile_views()) {
+    SimulateKeyPress(ui::VKEY_TAB, false);
+    EXPECT_EQ(v, focused_view());
+  }
 
-  // Test traversal triggered by tab.
-  TestFocusTraversal(forward_view_list, ui::VKEY_TAB, false);
+  // Move focus on expand arrow.
+  SimulateKeyPress(ui::VKEY_TAB, false);
+  EXPECT_EQ(apps_grid_view()->expand_arrow_view_for_test(), focused_view());
 
-  // Test traversal triggered by shift+tab.
-  TestFocusTraversal(backward_view_list, ui::VKEY_TAB, true);
-
-  // Test traversal triggered by right, Left and right key are handled by
-  // search box when focus is on it, so focus will not move. Move focus to
-  // next element before testing.
-  forward_view_list.erase(forward_view_list.begin());
-  forward_view_list.front()->RequestFocus();
-  TestFocusTraversal(forward_view_list, ui::VKEY_RIGHT, false);
-
-  // Test traversal triggered by left.
-  backward_view_list.erase(backward_view_list.begin());
-  backward_view_list.front()->RequestFocus();
-  TestFocusTraversal(backward_view_list, ui::VKEY_LEFT, false);
+  // Move focus back to search box.
+  SimulateKeyPress(ui::VKEY_TAB, false);
+  EXPECT_EQ(search_box_view()->search_box(), focused_view());
 }
 
-// Tests the linear focus traversal in FULLSCREEN_ALL_APPS state.
-TEST_F(AppListViewFocusTest, LinearFocusTraversalInFullscreenAllAppsState) {
+// Tests the focus traversal triggered by tab in fullscreen all apps state.
+TEST_F(AppListViewFocusTest, FocusTraversalInFullscreenAllAppsState) {
   Show();
   SetAppListState(AppListView::FULLSCREEN_ALL_APPS);
 
-  std::vector<views::View*> forward_view_list;
-  forward_view_list.push_back(search_box_view()->search_box());
-  for (int i = 0; i < suggestions_container_view()->num_results(); ++i)
-    forward_view_list.push_back(suggestions_container_view()->tile_views()[i]);
+  // Move focus along suggestion apps.
+  for (views::View* v : suggestions_container_view()->tile_views()) {
+    SimulateKeyPress(ui::VKEY_TAB, false);
+    EXPECT_EQ(v, focused_view());
+  }
+
+  // Move focus along app list items.
   const views::ViewModelT<AppListItemView>* view_model =
       apps_grid_view()->view_model_for_test();
-  for (int i = 0; i < view_model->view_size(); ++i)
-    forward_view_list.push_back(view_model->view_at(i));
-  forward_view_list.push_back(search_box_view()->search_box());
-  std::vector<views::View*> backward_view_list = forward_view_list;
-  std::reverse(backward_view_list.begin(), backward_view_list.end());
+  for (int i = 0; i < view_model->view_size(); ++i) {
+    SimulateKeyPress(ui::VKEY_TAB, false);
+    EXPECT_EQ(view_model->view_at(i), focused_view());
+  }
 
-  // Test traversal triggered by tab.
-  TestFocusTraversal(forward_view_list, ui::VKEY_TAB, false);
-
-  // Test traversal triggered by shift+tab.
-  TestFocusTraversal(backward_view_list, ui::VKEY_TAB, true);
-
-  // Test traversal triggered by right, Left and right key are handled by
-  // search box when focus is on it, so focus will not move. Move focus to
-  // next element before testing.
-  forward_view_list.erase(forward_view_list.begin());
-  forward_view_list.front()->RequestFocus();
-  TestFocusTraversal(forward_view_list, ui::VKEY_RIGHT, false);
-
-  // Test traversal triggered by left.
-  backward_view_list.erase(backward_view_list.begin());
-  backward_view_list.front()->RequestFocus();
-  TestFocusTraversal(backward_view_list, ui::VKEY_LEFT, false);
+  // Move focus back to search box.
+  SimulateKeyPress(ui::VKEY_TAB, false);
+  EXPECT_EQ(search_box_view()->search_box(), focused_view());
 }
 
-// Tests the linear focus traversal in HALF state with opened search box.
-TEST_F(AppListViewFocusTest, LinearFocusTraversalInHalfState) {
+// Tests the focus traversal triggered by tab in half state with opened search
+// box.
+TEST_F(AppListViewFocusTest, FocusTraversalInHalfState) {
   Show();
 
   // Type something in search box to transition to HALF state and populate
@@ -561,186 +502,31 @@
   const int kListResults = 2;
   SetUpSearchResults(kTileResults, kListResults);
 
-  std::vector<views::View*> forward_view_list;
-  forward_view_list.push_back(search_box_view()->search_box());
-  forward_view_list.push_back(search_box_view()->close_button());
+  // Move focus to close button.
+  SimulateKeyPress(ui::VKEY_TAB, false);
+  EXPECT_EQ(search_box_view()->close_button(), focused_view());
+
+  // Move focus along the search results.
   const std::vector<SearchResultTileItemView*>& tile_views =
       contents_view()
           ->search_result_tile_item_list_view_for_test()
           ->tile_views_for_test();
-  for (int i = 0; i < kTileResults; ++i)
-    forward_view_list.push_back(tile_views[i]);
-  views::View* results_container = contents_view()
-                                       ->search_result_list_view_for_test()
-                                       ->results_container_for_test();
-  for (int i = 0; i < kListResults; ++i)
-    forward_view_list.push_back(results_container->child_at(i));
-  forward_view_list.push_back(search_box_view()->search_box());
-  std::vector<views::View*> backward_view_list = forward_view_list;
-  std::reverse(backward_view_list.begin(), backward_view_list.end());
+  for (int i = 0; i < kTileResults; ++i) {
+    SimulateKeyPress(ui::VKEY_TAB, false);
+    EXPECT_EQ(tile_views[i], focused_view());
+  }
+  const views::View* results_container =
+      contents_view()
+          ->search_result_list_view_for_test()
+          ->results_container_for_test();
+  for (int i = 0; i < kListResults; ++i) {
+    SimulateKeyPress(ui::VKEY_TAB, false);
+    EXPECT_EQ(results_container->child_at(i), focused_view());
+  }
 
-  // Test traversal triggered by tab.
-  TestFocusTraversal(forward_view_list, ui::VKEY_TAB, false);
-
-  // Test traversal triggered by shift+tab.
-  TestFocusTraversal(backward_view_list, ui::VKEY_TAB, true);
-
-  // Test traversal triggered by right, Left and right key are handled by
-  // search box when focus is on it, so focus will not move. Move focus to
-  // next element before testing.
-  forward_view_list.erase(forward_view_list.begin());
-  forward_view_list.front()->RequestFocus();
-  TestFocusTraversal(forward_view_list, ui::VKEY_RIGHT, false);
-
-  // Test traversal triggered by left.
-  backward_view_list.erase(backward_view_list.begin());
-  backward_view_list.front()->RequestFocus();
-  TestFocusTraversal(backward_view_list, ui::VKEY_LEFT, false);
-}
-
-// Tests the linear focus traversal in FULLSCREEN_ALL_APPS state within folder.
-TEST_F(AppListViewFocusTest, LinearFocusTraversalInFolder) {
-  Show();
-
-  // Transition to FULLSCREEN_ALL_APPS state and open the folder.
-  SetAppListState(AppListView::FULLSCREEN_ALL_APPS);
-  folder_item_view()->RequestFocus();
-  SimulateKeyPress(ui::VKEY_RETURN, false);
-  EXPECT_TRUE(contents_view()->apps_container_view()->IsInFolderView());
-
-  std::vector<views::View*> forward_view_list;
-  forward_view_list.push_back(search_box_view()->search_box());
-  forward_view_list.push_back(
-      app_list_folder_view()->folder_header_view()->GetFolderNameViewForTest());
-  const views::ViewModelT<AppListItemView>* view_model =
-      app_list_folder_view()->items_grid_view()->view_model_for_test();
-  for (int i = 0; i < view_model->view_size(); ++i)
-    forward_view_list.push_back(view_model->view_at(i));
-  forward_view_list.push_back(search_box_view()->back_button());
-  forward_view_list.push_back(search_box_view()->search_box());
-  std::vector<views::View*> backward_view_list = forward_view_list;
-  std::reverse(backward_view_list.begin(), backward_view_list.end());
-
-  // Test traversal triggered by tab.
-  TestFocusTraversal(forward_view_list, ui::VKEY_TAB, false);
-
-  // Test traversal triggered by shift+tab.
-  TestFocusTraversal(backward_view_list, ui::VKEY_TAB, true);
-
-  // Test traversal triggered by right, Left and right key are handled by
-  // search box when focus is on it, so focus will not move. Move focus to
-  // non-textfield element before testing.
-  forward_view_list.erase(forward_view_list.begin(),
-                          forward_view_list.begin() + 2);
-  forward_view_list.front()->RequestFocus();
-  TestFocusTraversal(forward_view_list, ui::VKEY_RIGHT, false);
-
-  // Test traversal triggered by left.
-  backward_view_list.erase(backward_view_list.begin());
-  backward_view_list.erase(backward_view_list.end() - 1);
-  backward_view_list.front()->RequestFocus();
-  TestFocusTraversal(backward_view_list, ui::VKEY_LEFT, false);
-}
-
-// Tests the vertical focus traversal by in PEEKING state.
-TEST_F(AppListViewFocusTest, VerticalFocusTraversalInPeekingState) {
-  Show();
-  SetAppListState(AppListView::PEEKING);
-
-  std::vector<views::View*> forward_view_list;
-  forward_view_list.push_back(search_box_view()->search_box());
-  const std::vector<SearchResultTileItemView*>& tile_views =
-      suggestions_container_view()->tile_views();
-  const int suggestions_num_results =
-      suggestions_container_view()->num_results();
-  forward_view_list.push_back(tile_views.front());
-  forward_view_list.push_back(apps_grid_view()->expand_arrow_view_for_test());
-  forward_view_list.push_back(search_box_view()->search_box());
-
-  // Test traversal triggered by down.
-  TestFocusTraversal(forward_view_list, ui::VKEY_DOWN, false);
-
-  std::vector<views::View*> backward_view_list;
-  backward_view_list.push_back(search_box_view()->search_box());
-  backward_view_list.push_back(apps_grid_view()->expand_arrow_view_for_test());
-  backward_view_list.push_back(tile_views[suggestions_num_results - 1]);
-  backward_view_list.push_back(search_box_view()->search_box());
-
-  // Test traversal triggered by up.
-  TestFocusTraversal(backward_view_list, ui::VKEY_UP, false);
-}
-
-// Tests the vertical focus traversal in FULLSCREEN_ALL_APPS state.
-TEST_F(AppListViewFocusTest, VerticalFocusTraversalInFullscreenAllAppsState) {
-  Show();
-  SetAppListState(AppListView::FULLSCREEN_ALL_APPS);
-
-  std::vector<views::View*> forward_view_list;
-  forward_view_list.push_back(search_box_view()->search_box());
-  const std::vector<SearchResultTileItemView*>& tile_views =
-      suggestions_container_view()->tile_views();
-  const int suggestions_num_results =
-      suggestions_container_view()->num_results();
-  forward_view_list.push_back(tile_views.front());
-  const views::ViewModelT<AppListItemView>* view_model =
-      apps_grid_view()->view_model_for_test();
-  for (int i = 0; i < view_model->view_size(); i += apps_grid_view()->cols())
-    forward_view_list.push_back(view_model->view_at(i));
-  forward_view_list.push_back(search_box_view()->search_box());
-
-  // Test traversal triggered by down.
-  TestFocusTraversal(forward_view_list, ui::VKEY_DOWN, false);
-
-  std::vector<views::View*> backward_view_list;
-  backward_view_list.push_back(search_box_view()->search_box());
-  for (int i = view_model->view_size() - 1; i >= 0;
-       i -= apps_grid_view()->cols())
-    backward_view_list.push_back(view_model->view_at(i));
-  const int index = std::min(view_model->view_size() % apps_grid_view()->cols(),
-                             suggestions_num_results) -
-                    1;
-  backward_view_list.push_back(tile_views[index]);
-  backward_view_list.push_back(search_box_view()->search_box());
-
-  // Test traversal triggered by up.
-  TestFocusTraversal(backward_view_list, ui::VKEY_UP, false);
-}
-
-// Tests the vertical focus traversal in FULLSCREEN_ALL_APPS state within
-// folder.
-TEST_F(AppListViewFocusTest, VerticalFocusTraversalInFolder) {
-  Show();
-
-  // Transition to FULLSCREEN_ALL_APPS state and open the folder.
-  SetAppListState(AppListView::FULLSCREEN_ALL_APPS);
-  folder_item_view()->RequestFocus();
-  SimulateKeyPress(ui::VKEY_RETURN, false);
-  EXPECT_TRUE(contents_view()->apps_container_view()->IsInFolderView());
-
-  std::vector<views::View*> forward_view_list;
-  forward_view_list.push_back(search_box_view()->search_box());
-  forward_view_list.push_back(
-      app_list_folder_view()->folder_header_view()->GetFolderNameViewForTest());
-  const views::ViewModelT<AppListItemView>* view_model =
-      app_list_folder_view()->items_grid_view()->view_model_for_test();
-  for (int i = 0; i < view_model->view_size(); i += apps_grid_view()->cols())
-    forward_view_list.push_back(view_model->view_at(i));
-  forward_view_list.push_back(search_box_view()->search_box());
-
-  // Test traversal triggered by down.
-  TestFocusTraversal(forward_view_list, ui::VKEY_DOWN, false);
-
-  std::vector<views::View*> backward_view_list;
-  backward_view_list.push_back(search_box_view()->search_box());
-  for (int i = view_model->view_size() - 1; i >= 0;
-       i -= apps_grid_view()->cols())
-    backward_view_list.push_back(view_model->view_at(i));
-  backward_view_list.push_back(
-      app_list_folder_view()->folder_header_view()->GetFolderNameViewForTest());
-  backward_view_list.push_back(search_box_view()->search_box());
-
-  // Test traversal triggered by up.
-  TestFocusTraversal(backward_view_list, ui::VKEY_UP, false);
+  // Move focus back to search box.
+  SimulateKeyPress(ui::VKEY_TAB, false);
+  EXPECT_EQ(search_box_view()->search_box(), focused_view());
 }
 
 // Tests that the focus is set back onto search box after state transition.
@@ -771,13 +557,7 @@
             AppListView::FULLSCREEN_ALL_APPS);
   EXPECT_EQ(search_box_view()->search_box(), focused_view());
 
-  // Move focus to first suggestion app, then open the folder.
-  folder_item_view()->RequestFocus();
-  SimulateKeyPress(ui::VKEY_RETURN, false);
-  EXPECT_TRUE(contents_view()->apps_container_view()->IsInFolderView());
-  EXPECT_EQ(search_box_view()->search_box(), focused_view());
-
-  // Move focus to the first app, then transition to PEEKING state.
+  // Move focus to the first suggestion app, then transition to PEEKING state.
   SimulateKeyPress(ui::VKEY_TAB, false);
   SetAppListState(AppListView::PEEKING);
   EXPECT_EQ(app_list_view()->app_list_state(), AppListView::PEEKING);
@@ -917,6 +697,24 @@
   ASSERT_EQ(AppListView::PEEKING, view_->app_list_state());
 }
 
+TEST_F(AppListViewFullscreenTest, MouseWheelScrollTransitionsToFullscreen) {
+  Initialize(0, false, false);
+  delegate_->GetTestModel()->PopulateApps(kInitialItems);
+  Show();
+
+  view_->HandleScroll(-30, ui::ET_MOUSEWHEEL);
+  EXPECT_EQ(AppListView::FULLSCREEN_ALL_APPS, view_->app_list_state());
+}
+
+TEST_F(AppListViewFullscreenTest, GestureScrollTransitionsToFullscreen) {
+  Initialize(0, false, false);
+  delegate_->GetTestModel()->PopulateApps(kInitialItems);
+  Show();
+
+  view_->HandleScroll(-30, ui::ET_SCROLL);
+  EXPECT_EQ(AppListView::FULLSCREEN_ALL_APPS, view_->app_list_state());
+}
+
 // Tests that typing text after opening transitions from peeking to half.
 TEST_F(AppListViewFullscreenTest, TypingPeekingToHalf) {
   Initialize(0, false, false);
diff --git a/ui/app_list/views/apps_container_view.cc b/ui/app_list/views/apps_container_view.cc
index f5652bd..d22ea7e 100644
--- a/ui/app_list/views/apps_container_view.cc
+++ b/ui/app_list/views/apps_container_view.cc
@@ -24,7 +24,6 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/events/event.h"
 #include "ui/strings/grit/ui_strings.h"
-#include "ui/views/controls/textfield/textfield.h"
 
 namespace app_list {
 
@@ -39,8 +38,7 @@
 
 AppsContainerView::AppsContainerView(AppListMainView* app_list_main_view,
                                      AppListModel* model)
-    : is_fullscreen_app_list_enabled_(features::IsFullscreenAppListEnabled()),
-      is_app_list_focus_enabled_(features::IsAppListFocusEnabled()) {
+    : is_fullscreen_app_list_enabled_(features::IsFullscreenAppListEnabled()) {
   apps_grid_view_ =
       new AppsGridView(app_list_main_view->contents_view(), nullptr);
   if (is_fullscreen_app_list_enabled_) {
@@ -78,10 +76,7 @@
 
   CreateViewsForFolderTopItemsAnimation(folder_item, true);
 
-  if (is_app_list_focus_enabled_)
-    contents_view()->GetSearchBoxView()->search_box()->RequestFocus();
-  else
-    apps_grid_view_->ClearAnySelectedView();
+  apps_grid_view_->ClearAnySelectedView();
 }
 
 void AppsContainerView::ShowApps(AppListFolderItem* folder_item) {
diff --git a/ui/app_list/views/apps_container_view.h b/ui/app_list/views/apps_container_view.h
index cdc2ba0f..d109275 100644
--- a/ui/app_list/views/apps_container_view.h
+++ b/ui/app_list/views/apps_container_view.h
@@ -132,9 +132,6 @@
 
   const bool is_fullscreen_app_list_enabled_;
 
-  // Whether the app list focus is enabled.
-  const bool is_app_list_focus_enabled_;
-
   DISALLOW_COPY_AND_ASSIGN(AppsContainerView);
 };
 
diff --git a/ui/app_list/views/apps_grid_view.cc b/ui/app_list/views/apps_grid_view.cc
index c53f811..e86043e7 100644
--- a/ui/app_list/views/apps_grid_view.cc
+++ b/ui/app_list/views/apps_grid_view.cc
@@ -24,14 +24,12 @@
 #include "ui/app_list/views/app_list_folder_view.h"
 #include "ui/app_list/views/app_list_item_view.h"
 #include "ui/app_list/views/app_list_main_view.h"
-#include "ui/app_list/views/apps_container_view.h"
 #include "ui/app_list/views/contents_view.h"
 #include "ui/app_list/views/expand_arrow_view.h"
 #include "ui/app_list/views/indicator_chip_view.h"
 #include "ui/app_list/views/page_switcher_horizontal.h"
 #include "ui/app_list/views/page_switcher_vertical.h"
 #include "ui/app_list/views/pulsing_block_view.h"
-#include "ui/app_list/views/search_box_view.h"
 #include "ui/app_list/views/search_result_tile_item_view.h"
 #include "ui/app_list/views/suggestions_container_view.h"
 #include "ui/app_list/views/tile_item_view.h"
@@ -51,7 +49,6 @@
 #include "ui/strings/grit/ui_strings.h"
 #include "ui/views/border.h"
 #include "ui/views/controls/label.h"
-#include "ui/views/controls/textfield/textfield.h"
 #include "ui/views/view_model_utils.h"
 #include "ui/views/widget/widget.h"
 
@@ -948,17 +945,8 @@
 
 bool AppsGridView::OnKeyPressed(const ui::KeyEvent& event) {
   if (is_app_list_focus_enabled_) {
-    if (event.key_code() != ui::VKEY_UP && event.key_code() != ui::VKEY_DOWN)
-      return false;
-
-    AppListView::AppListState state =
-        contents_view_->app_list_view()->app_list_state();
-    bool arrow_up = event.key_code() == ui::VKEY_UP;
-    if (state == AppListView::PEEKING)
-      return HandleFocusMovementInPeekingState(arrow_up);
-
-    DCHECK(state == AppListView::FULLSCREEN_ALL_APPS);
-    return HandleFocusMovementInFullscreenAllAppsState(arrow_up);
+    // TODO(weidongg/766810) Add handling of arrow up and down here.
+    return false;
   }
   // TODO(weidongg/766807) Remove everything below when the flag is enabled by
   // default.
@@ -1047,21 +1035,6 @@
   return handled;
 }
 
-bool AppsGridView::OnMouseWheel(const ui::MouseWheelEvent& event) {
-  if (is_ignoring_scroll_events_)
-    return true;
-
-  // Bail on STATE_START or no apps page to make PaginationModel happy.
-  if (contents_view_->GetActiveState() == AppListModel::STATE_START ||
-      pagination_model_.total_pages() <= 0) {
-    return false;
-  }
-
-  return pagination_controller_->OnScroll(
-      gfx::Vector2d(event.x_offset(), event.y_offset()),
-      PaginationController::SCROLL_MOUSE_WHEEL);
-}
-
 void AppsGridView::ViewHierarchyChanged(
     const ViewHierarchyChangedDetails& details) {
   if (!details.is_add && details.parent == this) {
@@ -1098,26 +1071,6 @@
   }
 }
 
-void AppsGridView::OnScrollEvent(ui::ScrollEvent* event) {
-  if (is_ignoring_scroll_events_)
-    return;
-  // Bail on STATE_START or no apps page to make PaginationModel happy.
-  if (contents_view_->GetActiveState() == AppListModel::STATE_START ||
-      pagination_model_.total_pages() <= 0) {
-    return;
-  }
-
-  if (event->type() == ui::ET_SCROLL_FLING_CANCEL)
-    return;
-
-  gfx::Vector2dF offset(event->x_offset(), event->y_offset());
-  if (pagination_controller_->OnScroll(gfx::ToFlooredVector2d(offset),
-                                       PaginationController::SCROLL_TOUCHPAD)) {
-    event->SetHandled();
-    event->StopPropagation();
-  }
-}
-
 void AppsGridView::Update() {
   DCHECK(!selected_view_ && !drag_view_);
   view_model_.Clear();
@@ -1204,6 +1157,21 @@
   return view;
 }
 
+bool AppsGridView::HandleScroll(int offset, ui::EventType type) {
+  if (is_ignoring_scroll_events_)
+    return false;
+
+  // Bail on STATE_START or no apps page to make PaginationModel happy.
+  if (contents_view_->GetActiveState() == AppListModel::STATE_START ||
+      pagination_model_.total_pages() <= 0) {
+    return false;
+  }
+
+  const gfx::Vector2dF scroll_offset_vector(0, offset);
+  return pagination_controller_->OnScroll(
+      gfx::ToFlooredVector2d(scroll_offset_vector), type);
+}
+
 AppsGridView::Index AppsGridView::GetIndexFromModelIndex(
     int model_index) const {
   if (model_index < TilesPerPage(0))
@@ -1850,83 +1818,6 @@
   return folder_delegate_->IsOEMFolder();
 }
 
-bool AppsGridView::HandleFocusMovementInPeekingState(bool arrow_up) {
-  DCHECK(expand_arrow_view_);
-  if (expand_arrow_view_->HasFocus())
-    return false;
-  // In peeking mode, the focus is now in suggestions container.
-  if (arrow_up)
-    contents_view_->GetSearchBoxView()->search_box()->RequestFocus();
-  else
-    expand_arrow_view_->RequestFocus();
-  return true;
-}
-
-bool AppsGridView::HandleFocusMovementInFullscreenAllAppsState(bool arrow_up) {
-  // The global index is the index of focused app in all pages, assuming
-  // all pages except last one have |cols_*rows_per_page_| apps, including
-  // apps in both |view_model_| and |suggestions_container_|. For example, if
-  // the focused app is the n-th app in p-th page, the global index is
-  // |(p-1)*(cols_*rows_per_page_)+(n-1)|.
-  int global_index;
-
-  // |suggestions_container_| does not exist in folder view.
-  bool has_suggestions_app =
-      suggestions_container_ && suggestions_container_->num_results() > 0;
-  const int suggestions_app_max_num = has_suggestions_app ? cols_ : 0;
-
-  // Calculate current global focus index.
-  views::View* focused_view = GetFocusManager()->GetFocusedView();
-  if (has_suggestions_app && suggestions_container_->Contains(focused_view)) {
-    const std::vector<SearchResultTileItemView*>& tile_views =
-        suggestions_container_->tile_views();
-    global_index =
-        std::find(tile_views.begin(), tile_views.end(), focused_view) -
-        tile_views.begin();
-    DCHECK(global_index < cols_);
-  } else {
-    global_index = view_model_.GetIndexOfView(
-                       static_cast<const AppListItemView*>(focused_view)) +
-                   suggestions_app_max_num;
-  }
-
-  // Calculate target global focus index.
-  const int tile_total = view_model_.view_size() + suggestions_app_max_num;
-  const int row_total = tile_total / cols_ + ((tile_total % cols_) ? 1 : 0);
-  int target_global_index = global_index + (arrow_up ? -cols_ : cols_);
-  if (target_global_index >= tile_total &&
-      target_global_index < cols_ * row_total) {
-    // Target index is on last row, so set it to last app's global index.
-    target_global_index = tile_total - 1;
-  } else if (has_suggestions_app && target_global_index >= 0 &&
-             target_global_index < cols_) {
-    // Target index is in |suggestions_container|, set it to last suggestion
-    // app's index if it is outside range.
-    target_global_index = std::min(suggestions_container_->num_results() - 1,
-                                   target_global_index);
-  }
-
-  // Move focus based on target global focus index.
-  if (target_global_index < 0 || target_global_index >= cols_ * row_total) {
-    // Target index is outside apps grid view.
-    if (folder_delegate_ && arrow_up) {
-      contents_view_->apps_container_view()
-          ->app_list_folder_view()
-          ->folder_header_view()
-          ->SetTextFocus();
-    } else {
-      contents_view_->GetSearchBoxView()->search_box()->RequestFocus();
-    }
-  } else if (has_suggestions_app &&
-             target_global_index < suggestions_container_->num_results()) {
-    suggestions_container_->tile_views()[target_global_index]->RequestFocus();
-  } else {
-    view_model_.view_at(target_global_index - suggestions_app_max_num)
-        ->RequestFocus();
-  }
-  return true;
-}
-
 void AppsGridView::DispatchDragEventForReparent(Pointer pointer,
                                                 const gfx::Point& drag_point) {
   folder_delegate_->DispatchDragEventForReparent(pointer, drag_point);
@@ -2133,6 +2024,14 @@
                              &AppsGridView::StopIgnoringScrollEvents);
 }
 
+bool AppsGridView::HandleScrollFromAppListView(int offset, ui::EventType type) {
+  if (!pagination_model()->IsValidPageRelative(offset <= 0 ? 1 : -1))
+    return false;
+
+  HandleScroll(offset, type);
+  return true;
+}
+
 void AppsGridView::StartDragAndDropHostDrag(const gfx::Point& grid_location) {
   // When a drag and drop host is given, the item can be dragged out of the app
   // list window. In that case a proxy widget needs to be used.
diff --git a/ui/app_list/views/apps_grid_view.h b/ui/app_list/views/apps_grid_view.h
index e9056c5..d908a86 100644
--- a/ui/app_list/views/apps_grid_view.h
+++ b/ui/app_list/views/apps_grid_view.h
@@ -139,7 +139,6 @@
   void Layout() override;
   bool OnKeyPressed(const ui::KeyEvent& event) override;
   bool OnKeyReleased(const ui::KeyEvent& event) override;
-  bool OnMouseWheel(const ui::MouseWheelEvent& event) override;
   void ViewHierarchyChanged(
       const ViewHierarchyChangedDetails& details) override;
   bool GetDropFormats(
@@ -155,7 +154,6 @@
 
   // Overridden from ui::EventHandler:
   void OnGestureEvent(ui::GestureEvent* event) override;
-  void OnScrollEvent(ui::ScrollEvent* event) override;
 
   // Stops the timer that triggers a page flip during a drag.
   void StopPageFlipTimer();
@@ -211,6 +209,10 @@
   // Starts a timer during which we ignore scroll events.
   void StartTimerToIgnoreScrollEvents();
 
+  // Passes scroll information from AppListView to the PaginationController,
+  // returns true if this scroll would change pages.
+  bool HandleScrollFromAppListView(int offset, ui::EventType type);
+
   // Return the view model for test purposes.
   const views::ViewModelT<AppListItemView>* view_model_for_test() const {
     return &view_model_;
@@ -298,6 +300,9 @@
 
   AppListItemView* CreateViewForItemAtIndex(size_t index);
 
+  // Returns true if the event was handled by the pagination controller.
+  bool HandleScroll(int offset, ui::EventType type);
+
   // Convert between the model index and the visual index. The model index
   // is the index of the item in AppListModel. The visual index is the Index
   // struct above with page/slot info of where to display the item.
@@ -514,13 +519,6 @@
   // Returns true if the grid view is under an OEM folder.
   bool IsUnderOEMFolder();
 
-  // Handle focus movement triggered by arrow up and down in PEEKING state.
-  bool HandleFocusMovementInPeekingState(bool arrow_up);
-
-  // Handle focus movement triggered by arrow up and down in FULLSCREEN_ALL_APPS
-  // state.
-  bool HandleFocusMovementInFullscreenAllAppsState(bool arrow_up);
-
   AppListModel* model_ = nullptr;         // Owned by AppListView.
   AppListItemList* item_list_ = nullptr;  // Not owned.
 
diff --git a/ui/app_list/views/folder_header_view.cc b/ui/app_list/views/folder_header_view.cc
index d298c26..84a55d6 100644
--- a/ui/app_list/views/folder_header_view.cc
+++ b/ui/app_list/views/folder_header_view.cc
@@ -159,10 +159,6 @@
   return gfx::Size(kPreferredWidth, preferred_height);
 }
 
-views::View* FolderHeaderView::GetFolderNameViewForTest() const {
-  return folder_name_view_;
-}
-
 int FolderHeaderView::GetMaxFolderNameWidth() const {
   return is_fullscreen_app_list_enabled_ ? kMaxFolderNameWidthFullScreen
                                          : kMaxFolderNameWidth;
diff --git a/ui/app_list/views/folder_header_view.h b/ui/app_list/views/folder_header_view.h
index cdbdcd0..d8605f4b 100644
--- a/ui/app_list/views/folder_header_view.h
+++ b/ui/app_list/views/folder_header_view.h
@@ -41,8 +41,6 @@
   // Overridden from views::View:
   gfx::Size CalculatePreferredSize() const override;
 
-  views::View* GetFolderNameViewForTest() const;
-
  private:
   class FolderNameView;
   friend class test::FolderHeaderViewTest;
diff --git a/ui/app_list/views/search_box_view.cc b/ui/app_list/views/search_box_view.cc
index 2d1a1d4..50b7cc9e 100644
--- a/ui/app_list/views/search_box_view.cc
+++ b/ui/app_list/views/search_box_view.cc
@@ -661,21 +661,6 @@
 
 void SearchBoxView::OnKeyEvent(ui::KeyEvent* event) {
   app_list_view_->OnKeyEvent(event);
-
-  if (event->handled() || event->type() != ui::ET_KEY_PRESSED)
-    return;
-
-  if (event->key_code() != ui::VKEY_UP && event->key_code() != ui::VKEY_DOWN)
-    return;
-
-  // If focus is in search box view, up key moves focus to the last element of
-  // contents view, while down key moves focus to the first element of contents
-  // view.
-  views::View* v = GetFocusManager()->GetNextFocusableView(
-      contents_view_, GetWidget(), event->key_code() == ui::VKEY_UP, false);
-  if (v)
-    v->RequestFocus();
-  event->SetHandled();
 }
 
 void SearchBoxView::ButtonPressed(views::Button* sender,
diff --git a/ui/app_list/views/search_result_tile_item_list_view_unittest.cc b/ui/app_list/views/search_result_tile_item_list_view_unittest.cc
index 98de018..5e7fd85 100644
--- a/ui/app_list/views/search_result_tile_item_list_view_unittest.cc
+++ b/ui/app_list/views/search_result_tile_item_list_view_unittest.cc
@@ -170,7 +170,7 @@
         ->child_at(first_child + i * child_step)
         ->GetAccessibleNodeData(&node_data);
     EXPECT_EQ(ui::AX_ROLE_BUTTON, node_data.role);
-    EXPECT_EQ(base::StringPrintf("PlayStoreApp %d, %d.0, Price %d",
+    EXPECT_EQ(base::StringPrintf("PlayStoreApp %d, Star rating %d.0, Price %d",
                                  i - kInstalledApps, i + 1 - kInstalledApps,
                                  i - kInstalledApps),
               node_data.GetStringAttribute(ui::AX_ATTR_NAME));
diff --git a/ui/app_list/views/search_result_tile_item_view.cc b/ui/app_list/views/search_result_tile_item_view.cc
index fb1f4a98..9ab6e4c 100644
--- a/ui/app_list/views/search_result_tile_item_view.cc
+++ b/ui/app_list/views/search_result_tile_item_view.cc
@@ -13,7 +13,9 @@
 #include "ui/app_list/search_result.h"
 #include "ui/app_list/vector_icons/vector_icons.h"
 #include "ui/app_list/views/search_result_container_view.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/paint_vector_icon.h"
+#include "ui/strings/grit/ui_strings.h"
 #include "ui/views/background.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
@@ -161,8 +163,12 @@
   }
 
   base::string16 accessible_name = title()->text();
-  if (rating_ && rating_->visible())
-    accessible_name += base::UTF8ToUTF16(", ") + rating_->text();
+  if (rating_ && rating_->visible()) {
+    accessible_name +=
+        base::UTF8ToUTF16(", ") +
+        l10n_util::GetStringFUTF16(IDS_APP_ACCESSIBILITY_STAR_RATING_ARC,
+                                   rating_->text());
+  }
   if (price_ && price_->visible())
     accessible_name += base::UTF8ToUTF16(", ") + price_->text();
   SetAccessibleName(accessible_name);
diff --git a/ui/aura/window_event_dispatcher.cc b/ui/aura/window_event_dispatcher.cc
index f1e7b29..c6fd23c 100644
--- a/ui/aura/window_event_dispatcher.cc
+++ b/ui/aura/window_event_dispatcher.cc
@@ -83,6 +83,7 @@
     : host_(host),
       mouse_pressed_handler_(NULL),
       mouse_moved_handler_(NULL),
+      touchpad_pinch_handler_(nullptr),
       event_dispatch_target_(NULL),
       old_dispatch_target_(NULL),
       synthesize_mouse_move_(false),
@@ -332,6 +333,8 @@
     mouse_pressed_handler_ = NULL;
   if (invisible->Contains(mouse_moved_handler_))
     mouse_moved_handler_ = NULL;
+  if (invisible->Contains(touchpad_pinch_handler_))
+    touchpad_pinch_handler_ = nullptr;
 
   // If events are being dispatched from a nested message-loop, and the target
   // of the outer loop is hidden or moved to another dispatcher during
@@ -565,6 +568,8 @@
     details = PreDispatchTouchEvent(target_window, event->AsTouchEvent());
   } else if (event->IsKeyEvent()) {
     details = PreDispatchKeyEvent(event->AsKeyEvent());
+  } else if (event->IsPinchEvent()) {
+    details = PreDispatchPinchEvent(target_window, event->AsGestureEvent());
   }
   if (details.dispatcher_destroyed || details.target_destroyed)
     return details;
@@ -959,6 +964,25 @@
   return PreDispatchLocatedEvent(target, event);
 }
 
+DispatchDetails WindowEventDispatcher::PreDispatchPinchEvent(
+    Window* target,
+    ui::GestureEvent* event) {
+  if (event->details().device_type() != ui::GestureDeviceType::DEVICE_TOUCHPAD)
+    return PreDispatchLocatedEvent(target, event);
+  switch (event->type()) {
+    case ui::ET_GESTURE_PINCH_BEGIN:
+      touchpad_pinch_handler_ = target;
+      break;
+    case ui::ET_GESTURE_PINCH_END:
+      touchpad_pinch_handler_ = nullptr;
+      break;
+    default:
+      break;
+  }
+
+  return PreDispatchLocatedEvent(target, event);
+}
+
 DispatchDetails WindowEventDispatcher::PreDispatchTouchEvent(
     Window* target,
     ui::TouchEvent* event) {
diff --git a/ui/aura/window_event_dispatcher.h b/ui/aura/window_event_dispatcher.h
index e3ee61c..946d0b8 100644
--- a/ui/aura/window_event_dispatcher.h
+++ b/ui/aura/window_event_dispatcher.h
@@ -60,6 +60,7 @@
 
   Window* mouse_pressed_handler() { return mouse_pressed_handler_; }
   Window* mouse_moved_handler() { return mouse_moved_handler_; }
+  Window* touchpad_pinch_handler() { return touchpad_pinch_handler_; }
 
   // Overridden from ui::EventProcessor:
   ui::EventTargeter* GetDefaultEventTargeter() override;
@@ -244,6 +245,8 @@
                                                    ui::LocatedEvent* event);
   ui::EventDispatchDetails PreDispatchMouseEvent(Window* target,
                                                  ui::MouseEvent* event);
+  ui::EventDispatchDetails PreDispatchPinchEvent(Window* target,
+                                                 ui::GestureEvent* event);
   ui::EventDispatchDetails PreDispatchTouchEvent(Window* target,
                                                  ui::TouchEvent* event);
   ui::EventDispatchDetails PreDispatchKeyEvent(ui::KeyEvent* event);
@@ -252,6 +255,7 @@
 
   Window* mouse_pressed_handler_;
   Window* mouse_moved_handler_;
+  Window* touchpad_pinch_handler_;
   Window* event_dispatch_target_;
   Window* old_dispatch_target_;
 
diff --git a/ui/aura/window_event_dispatcher_unittest.cc b/ui/aura/window_event_dispatcher_unittest.cc
index 69240f88..86bbb75 100644
--- a/ui/aura/window_event_dispatcher_unittest.cc
+++ b/ui/aura/window_event_dispatcher_unittest.cc
@@ -1988,6 +1988,51 @@
   root_window()->RemovePreTargetHandler(&recorder);
 }
 
+// Places two windows side by side.  Starts a pinch in one window, then sets
+// capture to the other window.  Ensures that subsequent pinch events are
+// sent to the window which gained capture.
+TEST_P(WindowEventDispatcherTest, TouchpadPinchEventsRetargetOnCapture) {
+  EventFilterRecorder recorder1;
+  EventFilterRecorder recorder2;
+  std::unique_ptr<Window> window1(
+      CreateNormalWindow(1, root_window(), nullptr));
+  window1->SetBounds(gfx::Rect(0, 0, 40, 40));
+
+  std::unique_ptr<Window> window2(
+      CreateNormalWindow(2, root_window(), nullptr));
+  window2->SetBounds(gfx::Rect(40, 0, 40, 40));
+
+  window1->AddPreTargetHandler(&recorder1);
+  window2->AddPreTargetHandler(&recorder2);
+
+  gfx::Point position1 = window1->bounds().CenterPoint();
+
+  ui::GestureEventDetails begin_details(ui::ET_GESTURE_PINCH_BEGIN);
+  begin_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHPAD);
+  ui::GestureEvent begin(position1.x(), position1.y(), 0, ui::EventTimeForNow(),
+                         begin_details);
+  DispatchEventUsingWindowDispatcher(&begin);
+
+  window2->SetCapture();
+
+  ui::GestureEventDetails update_details(ui::ET_GESTURE_PINCH_UPDATE);
+  update_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHPAD);
+  ui::GestureEvent update(position1.x(), position1.y(), 0,
+                          ui::EventTimeForNow(), update_details);
+  DispatchEventUsingWindowDispatcher(&update);
+
+  ui::GestureEventDetails end_details(ui::ET_GESTURE_PINCH_END);
+  end_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHPAD);
+  ui::GestureEvent end(position1.x(), position1.y(), 0, ui::EventTimeForNow(),
+                       end_details);
+  DispatchEventUsingWindowDispatcher(&end);
+
+  EXPECT_EQ("GESTURE_PINCH_BEGIN", EventTypesToString(recorder1.events()));
+
+  EXPECT_EQ("GESTURE_PINCH_UPDATE GESTURE_PINCH_END",
+            EventTypesToString(recorder2.events()));
+}
+
 // Places two windows side by side. Presses down on one window, and starts a
 // scroll. Sets capture on the other window and ensures that the "ending" events
 // aren't sent to the window which gained capture.
diff --git a/ui/aura/window_targeter.cc b/ui/aura/window_targeter.cc
index e04383a..4c63e7f 100644
--- a/ui/aura/window_targeter.cc
+++ b/ui/aura/window_targeter.cc
@@ -65,6 +65,14 @@
   if (capture_window)
     return capture_window;
 
+  if (event.IsPinchEvent()) {
+    DCHECK_EQ(event.AsGestureEvent()->details().device_type(),
+              ui::GestureDeviceType::DEVICE_TOUCHPAD);
+    WindowEventDispatcher* dispatcher = root_window->GetHost()->dispatcher();
+    if (dispatcher->touchpad_pinch_handler())
+      return dispatcher->touchpad_pinch_handler();
+  }
+
   if (event.IsTouchEvent()) {
     // Query the gesture-recognizer to find targets for touch events.
     const ui::TouchEvent& touch = *event.AsTouchEvent();
diff --git a/ui/base/test/scoped_fake_nswindow_fullscreen.mm b/ui/base/test/scoped_fake_nswindow_fullscreen.mm
index c98641f..1b5fd3c1 100644
--- a/ui/base/test/scoped_fake_nswindow_fullscreen.mm
+++ b/ui/base/test/scoped_fake_nswindow_fullscreen.mm
@@ -17,17 +17,6 @@
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 
-// This method exists on NSWindowDelegate on 10.7+.
-// To build on 10.6, we just need to declare it somewhere. We'll test
-// -[NSObject respondsToSelector] before calling it.
-#if !defined(MAC_OS_X_VERSION_10_7) || \
-    MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7
-@protocol NSWindowDelegateLion
-- (NSSize)window:(NSWindow*)window
-    willUseFullScreenContentSize:(NSSize)proposedSize;
-@end
-#endif
-
 // Donates a testing implementation of [NSWindow toggleFullScreen:].
 @interface ToggleFullscreenDonorForWindow : NSObject
 @end
diff --git a/ui/base/ui_base_types.h b/ui/base/ui_base_types.h
index 975a82d..2605e457 100644
--- a/ui/base/ui_base_types.h
+++ b/ui/base/ui_base_types.h
@@ -41,16 +41,17 @@
 
 // TODO(varunjain): Remove MENU_SOURCE_NONE (crbug.com/250964)
 enum MenuSourceType {
-  MENU_SOURCE_NONE            = 0,
-  MENU_SOURCE_MOUSE           = 1,
-  MENU_SOURCE_KEYBOARD        = 2,
-  MENU_SOURCE_TOUCH           = 3,
+  MENU_SOURCE_NONE = 0,
+  MENU_SOURCE_MOUSE = 1,
+  MENU_SOURCE_KEYBOARD = 2,
+  MENU_SOURCE_TOUCH = 3,
   MENU_SOURCE_TOUCH_EDIT_MENU = 4,
-  MENU_SOURCE_LONG_PRESS      = 5,
-  MENU_SOURCE_LONG_TAP        = 6,
-  MENU_SOURCE_TOUCH_HANDLE    = 7,
-  MENU_SOURCE_STYLUS          = 8,
-  MENU_SOURCE_TYPE_LAST = MENU_SOURCE_STYLUS
+  MENU_SOURCE_LONG_PRESS = 5,
+  MENU_SOURCE_LONG_TAP = 6,
+  MENU_SOURCE_TOUCH_HANDLE = 7,
+  MENU_SOURCE_STYLUS = 8,
+  MENU_SOURCE_ADJUST_SELECTION = 9,
+  MENU_SOURCE_TYPE_LAST = MENU_SOURCE_ADJUST_SELECTION
 };
 
 UI_BASE_EXPORT MenuSourceType GetMenuSourceTypeForEvent(const ui::Event& event);
diff --git a/ui/base/win/osk_display_manager.cc b/ui/base/win/osk_display_manager.cc
index 5d9e7c3e..0f055f6 100644
--- a/ui/base/win/osk_display_manager.cc
+++ b/ui/base/win/osk_display_manager.cc
@@ -117,7 +117,9 @@
 OnScreenKeyboardDetector::OnScreenKeyboardDetector()
     : keyboard_detector_factory_(this) {}
 
-OnScreenKeyboardDetector::~OnScreenKeyboardDetector() {}
+OnScreenKeyboardDetector::~OnScreenKeyboardDetector() {
+  ClearObservers();
+}
 
 void OnScreenKeyboardDetector::DetectKeyboard(HWND main_window) {
   main_window_ = main_window;
diff --git a/ui/compositor/layer_animation_element.cc b/ui/compositor/layer_animation_element.cc
index 82cdb89..c447ee7 100644
--- a/ui/compositor/layer_animation_element.cc
+++ b/ui/compositor/layer_animation_element.cc
@@ -309,7 +309,9 @@
   }
   ~ThreadedLayerAnimationElement() override {}
 
-  bool IsThreaded() const override { return !duration().is_zero(); }
+  bool IsThreaded(LayerAnimationDelegate* delegate) const override {
+    return !duration().is_zero();
+  }
 
  protected:
   explicit ThreadedLayerAnimationElement(const LayerAnimationElement& element)
@@ -323,7 +325,7 @@
     if (t < 1.0)
       return false;
 
-    if (Started() && IsThreaded()) {
+    if (Started() && IsThreaded(delegate)) {
       LayerThreadedAnimationDelegate* threaded =
           delegate->GetThreadedAnimationDelegate();
       DCHECK(threaded);
@@ -335,7 +337,7 @@
   }
 
   void OnAbort(LayerAnimationDelegate* delegate) override {
-    if (delegate && Started() && IsThreaded()) {
+    if (delegate && Started() && IsThreaded(delegate)) {
       LayerThreadedAnimationDelegate* threaded =
           delegate->GetThreadedAnimationDelegate();
       DCHECK(threaded);
@@ -345,7 +347,7 @@
 
   void RequestEffectiveStart(LayerAnimationDelegate* delegate) override {
     DCHECK(animation_group_id());
-    if (!IsThreaded()) {
+    if (!IsThreaded(delegate)) {
       set_effective_start_time(requested_start_time());
       return;
     }
@@ -412,6 +414,17 @@
     target->opacity = target_;
   }
 
+  bool IsThreaded(LayerAnimationDelegate* delegate) const override {
+    // If the start and target values are the same, we do not create cc
+    // animation so that we will not create render pass in this case.
+    // http://crbug.com/764575.
+    if (duration().is_zero())
+      return false;
+    if (Started())
+      return start_ != target_;
+    return delegate->GetOpacityForAnimation() != target_;
+  }
+
  private:
   float start_;
   const float target_;
@@ -624,7 +637,7 @@
   OnGetTarget(target);
 }
 
-bool LayerAnimationElement::IsThreaded() const {
+bool LayerAnimationElement::IsThreaded(LayerAnimationDelegate* delegate) const {
   return false;
 }
 
diff --git a/ui/compositor/layer_animation_element.h b/ui/compositor/layer_animation_element.h
index 9a11b97c..8b33e30 100644
--- a/ui/compositor/layer_animation_element.h
+++ b/ui/compositor/layer_animation_element.h
@@ -169,7 +169,7 @@
   void Start(LayerAnimationDelegate* delegate, int animation_group_id);
 
   // Returns true if the animation has started but hasn't finished.
-  bool Started() { return !first_frame_; }
+  bool Started() const { return !first_frame_; }
 
   // Updates the delegate to the appropriate value for |now|. Returns true
   // if a redraw is required.
@@ -195,7 +195,7 @@
   AnimatableProperties properties() const { return properties_; }
 
   // Whether this element animates on the compositor thread.
-  virtual bool IsThreaded() const;
+  virtual bool IsThreaded(LayerAnimationDelegate* delegate) const;
 
   gfx::Tween::Type tween_type() const { return tween_type_; }
   void set_tween_type(gfx::Tween::Type tween_type) { tween_type_ = tween_type; }
diff --git a/ui/compositor/layer_animation_element_unittest.cc b/ui/compositor/layer_animation_element_unittest.cc
index 6baad14..e306022a 100644
--- a/ui/compositor/layer_animation_element_unittest.cc
+++ b/ui/compositor/layer_animation_element_unittest.cc
@@ -400,6 +400,28 @@
                           delegate.GetTransformForAnimation());
 }
 
+// Check that an opacity element is not threaded if the start and target values
+// are the same.
+TEST(LayerAnimationElementTest, OpacityElementIsThreaded) {
+  TestLayerAnimationDelegate delegate;
+  float start = 0.0;
+  float target = 1.0;
+  delegate.SetOpacityFromAnimation(start);
+  base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
+  std::unique_ptr<LayerAnimationElement> element =
+      LayerAnimationElement::CreateOpacityElement(target, delta);
+  EXPECT_TRUE(element->IsThreaded(&delegate));
+  element->ProgressToEnd(&delegate);
+  EXPECT_FLOAT_EQ(target, delegate.GetOpacityForAnimation());
+
+  start = 1.0;
+  delegate.SetOpacityFromAnimation(start);
+  element = LayerAnimationElement::CreateOpacityElement(target, delta);
+  EXPECT_FALSE(element->IsThreaded(&delegate));
+  element->ProgressToEnd(&delegate);
+  EXPECT_FLOAT_EQ(target, delegate.GetOpacityForAnimation());
+}
+
 TEST(LayerAnimationElementTest, ToString) {
   float target = 1.0;
   base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
diff --git a/ui/compositor/layer_animation_sequence.cc b/ui/compositor/layer_animation_sequence.cc
index a7a7b1c5..a252a0a 100644
--- a/ui/compositor/layer_animation_sequence.cc
+++ b/ui/compositor/layer_animation_sequence.cc
@@ -195,9 +195,10 @@
   return (properties_ & other) != LayerAnimationElement::UNKNOWN;
 }
 
-bool LayerAnimationSequence::IsFirstElementThreaded() const {
+bool LayerAnimationSequence::IsFirstElementThreaded(
+    LayerAnimationDelegate* delegate) const {
   if (!elements_.empty())
-    return elements_[0]->IsThreaded();
+    return elements_[0]->IsThreaded(delegate);
 
   return false;
 }
diff --git a/ui/compositor/layer_animation_sequence.h b/ui/compositor/layer_animation_sequence.h
index cee0500..0629c571 100644
--- a/ui/compositor/layer_animation_sequence.h
+++ b/ui/compositor/layer_animation_sequence.h
@@ -103,7 +103,7 @@
       LayerAnimationElement::AnimatableProperties other) const;
 
   // Returns true if the first element animates on the compositor thread.
-  bool IsFirstElementThreaded() const;
+  bool IsFirstElementThreaded(LayerAnimationDelegate* delegate) const;
 
   // Used to identify groups of sequences that are supposed to start together.
   // Once started, used to identify the sequence that owns a particular
diff --git a/ui/compositor/layer_animator.cc b/ui/compositor/layer_animator.cc
index 5902c14..601fc4c 100644
--- a/ui/compositor/layer_animator.cc
+++ b/ui/compositor/layer_animator.cc
@@ -271,8 +271,7 @@
 
   bool wait_for_group_start = false;
   for (iter = animations.begin(); iter != animations.end(); ++iter)
-    wait_for_group_start |= (*iter)->IsFirstElementThreaded();
-
+    wait_for_group_start |= (*iter)->IsFirstElementThreaded(delegate_);
   int group_id = cc::AnimationIdProvider::NextGroupId();
 
   // These animations (provided they don't animate any common properties) will
@@ -309,7 +308,7 @@
 
   bool wait_for_group_start = false;
   for (iter = animations.begin(); iter != animations.end(); ++iter)
-    wait_for_group_start |= (*iter)->IsFirstElementThreaded();
+    wait_for_group_start |= (*iter)->IsFirstElementThreaded(delegate_);
 
   int group_id = cc::AnimationIdProvider::NextGroupId();
 
@@ -403,7 +402,7 @@
     // Ensure that each sequence is only Started once, regardless of the
     // number of sequences in the group that have threaded first elements.
     if (((*iter).sequence()->animation_group_id() == group_id) &&
-        !(*iter).sequence()->IsFirstElementThreaded() &&
+        !(*iter).sequence()->IsFirstElementThreaded(delegate_) &&
         (*iter).sequence()->waiting_for_group_start()) {
       (*iter).sequence()->set_start_time(start_time);
       (*iter).sequence()->set_waiting_for_group_start(false);
@@ -544,9 +543,8 @@
     }
   }
 
-  if (!to_return.get() ||
-      !to_return->waiting_for_group_start() ||
-      !to_return->IsFirstElementThreaded())
+  if (!to_return.get() || !to_return->waiting_for_group_start() ||
+      !to_return->IsFirstElementThreaded(delegate_))
     return to_return.release();
 
   // The removed sequence may have been responsible for making other sequences
@@ -557,7 +555,7 @@
   for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
        queue_iter != animation_queue_.end(); ++queue_iter) {
     if (((*queue_iter)->animation_group_id() == group_id) &&
-        (*queue_iter)->IsFirstElementThreaded()) {
+        (*queue_iter)->IsFirstElementThreaded(delegate_)) {
       is_wait_still_needed = true;
       break;
     }
@@ -853,7 +851,7 @@
   AddToQueueIfNotPresent(sequence);
 
   if (!sequence->waiting_for_group_start() ||
-      sequence->IsFirstElementThreaded()) {
+      sequence->IsFirstElementThreaded(delegate_)) {
     sequence->set_start_time(start_time);
     sequence->Start(delegate());
   }
diff --git a/ui/compositor/layer_animator_unittest.cc b/ui/compositor/layer_animator_unittest.cc
index 3e09d10..0d3a13e 100644
--- a/ui/compositor/layer_animator_unittest.cc
+++ b/ui/compositor/layer_animator_unittest.cc
@@ -2839,6 +2839,7 @@
   EXPECT_FALSE(compositor_2->layer_animator_collection()->HasActiveAnimators());
 
   Layer layer;
+  layer.SetOpacity(0.5f);
   root_1.Add(&layer);
   LayerAnimator* animator = layer.GetAnimator();
   EXPECT_FALSE(layer.cc_layer_for_testing()->HasTickingAnimationForTesting());
@@ -2879,6 +2880,7 @@
   compositor->SetRootLayer(&root);
 
   Layer layer;
+  layer.SetOpacity(0.5f);
   root.Add(&layer);
 
   LayerAnimator* animator = layer.GetAnimator();
diff --git a/ui/display/manager/chromeos/touch_transform_controller.cc b/ui/display/manager/chromeos/touch_transform_controller.cc
index 3ed5de8..0c33b1c 100644
--- a/ui/display/manager/chromeos/touch_transform_controller.cc
+++ b/ui/display/manager/chromeos/touch_transform_controller.cc
@@ -219,15 +219,18 @@
   // transform as we want to use the raw native touch input data for calibration
   if (is_calibrating_)
     return ctm;
-
+  uint32_t touch_device_identifier =
+      TouchCalibrationData::GenerateTouchDeviceIdentifier(
+          touchscreen.name, touchscreen.vendor_id, touchscreen.product_id);
   // If touch calibration data is unavailable, use naive approach.
-  if (!touch_display.has_touch_calibration_data()) {
+  if (!touch_display.HasTouchCalibrationData(touch_device_identifier)) {
     return GetUncalibratedTransform(ctm, display, touch_display, touch_area,
                                     touch_native_size);
   }
-
+  const TouchCalibrationData& calibration_data =
+      touch_display.GetTouchCalibrationData(touch_device_identifier);
   // The resolution at which the touch calibration was performed.
-  gfx::SizeF touch_calib_size(touch_display.GetTouchCalibrationData().bounds);
+  gfx::SizeF touch_calib_size(calibration_data.bounds);
 
   // Any additional transfomration that needs to be applied to the display
   // points, before we solve for the final transform.
@@ -260,15 +263,15 @@
   }
   // Solve for coefficients and compute transform matrix.
   gfx::Transform stored_ctm;
-  if (!GetCalibratedTransform(
-          touch_display.GetTouchCalibrationData().point_pairs, pre_transform,
-          &stored_ctm)) {
+  if (!GetCalibratedTransform(calibration_data.point_pairs, pre_transform,
+                              &stored_ctm)) {
     // TODO(malaykeshav): This can be checked at the calibration step before
     // storing the calibration associated data. This will allow us to explicitly
     // inform the user with proper UX.
 
-    // Clear stored calibration data.
-    display_manager_->ClearTouchCalibrationData(touch_display.id());
+    // Clear stored calibration data as it does not produce a valid calibration.
+    display_manager_->ClearTouchCalibrationData(touch_display.id(),
+                                                touch_device_identifier);
 
     // Return uncalibrated transform.
     return GetUncalibratedTransform(ctm, display, touch_display, touch_area,
diff --git a/ui/display/manager/chromeos/touch_transform_controller_unittest.cc b/ui/display/manager/chromeos/touch_transform_controller_unittest.cc
index cb707cc..8860de9 100644
--- a/ui/display/manager/chromeos/touch_transform_controller_unittest.cc
+++ b/ui/display/manager/chromeos/touch_transform_controller_unittest.cc
@@ -546,13 +546,17 @@
       std::make_pair(gfx::Point(1820, 1100), gfx::Point(1820, 1100)),
   }};
   TouchCalibrationData touch_data(user_input, kDisplaySize);
-  display.SetTouchCalibrationData(touch_data);
-  EXPECT_TRUE(display.has_touch_calibration_data());
 
   const std::string msg = GetTouchPointString(user_input);
 
   ui::TouchscreenDevice touchscreen =
       CreateTouchscreenDevice(kTouchId1, kTouchSize);
+  uint32_t touch_device_identifier =
+      TouchCalibrationData::GenerateTouchDeviceIdentifier(
+          touchscreen.name, touchscreen.vendor_id, touchscreen.vendor_id);
+
+  display.SetTouchCalibrationData(touch_device_identifier, touch_data);
+  EXPECT_TRUE(display.HasTouchCalibrationData(touch_device_identifier));
 
   ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance();
   std::vector<ui::TouchDeviceTransform> transforms;
@@ -590,13 +594,17 @@
        std::make_pair(gfx::Point(100, 1100), gfx::Point(158, 1060)),
        std::make_pair(gfx::Point(1820, 1100), gfx::Point(1790, 1140))}};
   TouchCalibrationData touch_data(user_input, kDisplaySize);
-  display.SetTouchCalibrationData(touch_data);
-  EXPECT_TRUE(display.has_touch_calibration_data());
 
   const std::string msg = GetTouchPointString(user_input);
 
   ui::TouchscreenDevice touchscreen =
       CreateTouchscreenDevice(kTouchId1, kTouchSize);
+  uint32_t touch_device_identifier =
+      TouchCalibrationData::GenerateTouchDeviceIdentifier(
+          touchscreen.name, touchscreen.vendor_id, touchscreen.vendor_id);
+
+  display.SetTouchCalibrationData(touch_device_identifier, touch_data);
+  EXPECT_TRUE(display.HasTouchCalibrationData(touch_device_identifier));
 
   ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance();
   std::vector<ui::TouchDeviceTransform> transforms;
@@ -636,13 +644,17 @@
        std::make_pair(gfx::Point(1820, 1100), gfx::Point(1770, 1140))}};
 
   TouchCalibrationData touch_data(user_input, CALIBRATION_SIZE);
-  display.SetTouchCalibrationData(touch_data);
-  EXPECT_TRUE(display.has_touch_calibration_data());
 
   const std::string msg = GetTouchPointString(user_input);
 
   ui::TouchscreenDevice touchscreen =
       CreateTouchscreenDevice(kTouchId1, kTouchSize);
+  uint32_t touch_device_identifier =
+      TouchCalibrationData::GenerateTouchDeviceIdentifier(
+          touchscreen.name, touchscreen.vendor_id, touchscreen.vendor_id);
+
+  display.SetTouchCalibrationData(touch_device_identifier, touch_data);
+  EXPECT_TRUE(display.HasTouchCalibrationData(touch_device_identifier));
 
   ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance();
   std::vector<ui::TouchDeviceTransform> transforms;
@@ -677,13 +689,17 @@
        std::make_pair(gfx::Point(136, 411), gfx::Point(611, 2800)),
        std::make_pair(gfx::Point(873, 411), gfx::Point(3535, 2949))}};
   TouchCalibrationData touch_data(user_input, kDisplaySize);
-  display.SetTouchCalibrationData(touch_data);
-  EXPECT_TRUE(display.has_touch_calibration_data());
 
   const std::string msg = GetTouchPointString(user_input);
 
   ui::TouchscreenDevice touchscreen =
       CreateTouchscreenDevice(kTouchId1, kTouchSize);
+  uint32_t touch_device_identifier =
+      TouchCalibrationData::GenerateTouchDeviceIdentifier(
+          touchscreen.name, touchscreen.vendor_id, touchscreen.vendor_id);
+
+  display.SetTouchCalibrationData(touch_device_identifier, touch_data);
+  EXPECT_TRUE(display.HasTouchCalibrationData(touch_device_identifier));
 
   ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance();
 
@@ -725,6 +741,10 @@
 
   ui::TouchscreenDevice internal_touchscreen =
       CreateTouchscreenDevice(kTouchId1, kTouchSize);
+  uint32_t touch_device_identifier =
+      TouchCalibrationData::GenerateTouchDeviceIdentifier(
+          internal_touchscreen.name, internal_touchscreen.vendor_id,
+          internal_touchscreen.vendor_id);
 
   ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance();
 
@@ -740,8 +760,10 @@
   }};
   // The calibration was performed at the native display resolution.
   TouchCalibrationData touch_data(user_input, kNativeDisplaySize);
-  internal_display_info.SetTouchCalibrationData(touch_data);
-  EXPECT_TRUE(internal_display_info.has_touch_calibration_data());
+  internal_display_info.SetTouchCalibrationData(touch_device_identifier,
+                                                touch_data);
+  EXPECT_TRUE(
+      internal_display_info.HasTouchCalibrationData(touch_device_identifier));
 
   std::vector<ui::TouchDeviceTransform> transforms;
   transforms.push_back(CreateTouchDeviceTransform(
@@ -798,6 +820,10 @@
 
   ui::TouchscreenDevice internal_touchscreen =
       CreateTouchscreenDevice(kTouchId1, kDisplaySize);
+  uint32_t touch_device_identifier =
+      TouchCalibrationData::GenerateTouchDeviceIdentifier(
+          internal_touchscreen.name, internal_touchscreen.vendor_id,
+          internal_touchscreen.vendor_id);
 
   ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance();
 
@@ -813,8 +839,10 @@
   }};
   // The calibration was performed at the native display resolution.
   TouchCalibrationData touch_data(user_input, kNativeDisplaySize);
-  internal_display_info.SetTouchCalibrationData(touch_data);
-  EXPECT_TRUE(internal_display_info.has_touch_calibration_data());
+  internal_display_info.SetTouchCalibrationData(touch_device_identifier,
+                                                touch_data);
+  EXPECT_TRUE(
+      internal_display_info.HasTouchCalibrationData(touch_device_identifier));
 
   std::vector<ui::TouchDeviceTransform> transforms;
   transforms.push_back(CreateTouchDeviceTransform(
diff --git a/ui/display/manager/display_manager.cc b/ui/display/manager/display_manager.cc
index 29ecd32..b54b6c5a 100644
--- a/ui/display/manager/display_manager.cc
+++ b/ui/display/manager/display_manager.cc
@@ -452,7 +452,7 @@
     const gfx::Insets* overscan_insets,
     const gfx::Size& resolution_in_pixels,
     float device_scale_factor,
-    const TouchCalibrationData* touch_calibration_data) {
+    std::map<uint32_t, TouchCalibrationData>* touch_calibration_data_map) {
   if (display_info_.find(display_id) == display_info_.end())
     display_info_[display_id] =
         ManagedDisplayInfo(display_id, std::string(), false);
@@ -472,8 +472,12 @@
     display_info_[display_id].set_configured_ui_scale(ui_scale);
   if (overscan_insets)
     display_info_[display_id].SetOverscanInsets(*overscan_insets);
-  if (touch_calibration_data)
-    display_info_[display_id].SetTouchCalibrationData(*touch_calibration_data);
+  if (touch_calibration_data_map) {
+    display_info_[display_id].SetTouchCalibrationDataMap(
+        *touch_calibration_data_map);
+  } else {
+    display_info_[display_id].ClearAllTouchCalibrationData();
+  }
   if (!resolution_in_pixels.IsEmpty()) {
     DCHECK(!Display::IsInternalDisplayId(display_id));
     // Default refresh rate, until OnNativeDisplaysChanged() updates us with the
@@ -1040,39 +1044,54 @@
 void DisplayManager::SetTouchCalibrationData(
     int64_t display_id,
     const TouchCalibrationData::CalibrationPointPairQuad& point_pair_quad,
-    const gfx::Size& display_bounds) {
+    const gfx::Size& display_bounds,
+    uint32_t touch_device_identifier) {
   bool update = false;
   TouchCalibrationData calibration_data(point_pair_quad, display_bounds);
+
   DisplayInfoList display_info_list;
   for (const auto& display : active_display_list_) {
     ManagedDisplayInfo info = GetDisplayInfo(display.id());
     if (info.id() == display_id) {
-      info.SetTouchCalibrationData(calibration_data);
+      info.SetTouchCalibrationData(touch_device_identifier, calibration_data);
       update = true;
     }
     display_info_list.push_back(info);
   }
   if (update)
     UpdateDisplaysWith(display_info_list);
-  else
-    display_info_[display_id].SetTouchCalibrationData(calibration_data);
+  else {
+    display_info_[display_id].SetTouchCalibrationData(touch_device_identifier,
+                                                      calibration_data);
+  }
 }
 
-void DisplayManager::ClearTouchCalibrationData(int64_t display_id) {
+void DisplayManager::ClearTouchCalibrationData(
+    int64_t display_id,
+    base::Optional<uint32_t> touch_device_identifier) {
   bool update = false;
   DisplayInfoList display_info_list;
   for (const auto& display : active_display_list_) {
     ManagedDisplayInfo info = GetDisplayInfo(display.id());
     if (info.id() == display_id) {
-      info.clear_touch_calibration_data();
+      if (touch_device_identifier)
+        info.ClearTouchCalibrationData(*touch_device_identifier);
+      else
+        info.ClearAllTouchCalibrationData();
       update = true;
     }
     display_info_list.push_back(info);
   }
   if (update)
     UpdateDisplaysWith(display_info_list);
-  else
-    display_info_[display_id].clear_touch_calibration_data();
+  else {
+    if (touch_device_identifier) {
+      display_info_[display_id].ClearTouchCalibrationData(
+          *touch_device_identifier);
+    } else {
+      display_info_[display_id].ClearAllTouchCalibrationData();
+    }
+  }
 }
 #endif
 
diff --git a/ui/display/manager/display_manager.h b/ui/display/manager/display_manager.h
index 676558d..01223c5 100644
--- a/ui/display/manager/display_manager.h
+++ b/ui/display/manager/display_manager.h
@@ -28,6 +28,7 @@
 #include "ui/display/types/display_constants.h"
 
 #if defined(OS_CHROMEOS)
+#include "base/optional.h"
 #include "ui/display/manager/chromeos/display_configurator.h"
 #endif
 
@@ -193,7 +194,7 @@
       const gfx::Insets* overscan_insets,
       const gfx::Size& resolution_in_pixels,
       float device_scale_factor,
-      const TouchCalibrationData* touch_calibration_data);
+      std::map<uint32_t, TouchCalibrationData>* touch_calibration_data_map);
 
   // Register stored rotation properties for the internal display.
   void RegisterDisplayRotationProperties(bool rotation_lock,
@@ -322,8 +323,11 @@
   void SetTouchCalibrationData(
       int64_t display_id,
       const TouchCalibrationData::CalibrationPointPairQuad& point_pair_quad,
-      const gfx::Size& display_bounds);
-  void ClearTouchCalibrationData(int64_t display_id);
+      const gfx::Size& display_bounds,
+      uint32_t touch_device_identifier);
+  void ClearTouchCalibrationData(
+      int64_t display_id,
+      base::Optional<uint32_t> touch_device_identifier);
 #endif
 
   // Sets/gets default multi display mode.
diff --git a/ui/display/manager/managed_display_info.cc b/ui/display/manager/managed_display_info.cc
index 82b1ea3..5d2669e 100644
--- a/ui/display/manager/managed_display_info.cc
+++ b/ui/display/manager/managed_display_info.cc
@@ -9,6 +9,7 @@
 #include <string>
 #include <vector>
 
+#include "base/hash.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
@@ -34,6 +35,8 @@
 
 const float kDpi96 = 96.0;
 
+constexpr char kFallbackTouchDeviceName[] = "fallback_touch_device_name";
+
 // Check the content of |spec| and fill |bounds| and |device_scale_factor|.
 // Returns true when |bounds| is found.
 bool GetDisplayBounds(const std::string& spec,
@@ -86,6 +89,23 @@
     : point_pairs(calibration_data.point_pairs),
       bounds(calibration_data.bounds) {}
 
+// static
+uint32_t TouchCalibrationData::GenerateTouchDeviceIdentifier(
+    const std::string& device_name,
+    uint16_t vendor_id,
+    uint16_t product_id) {
+  std::string hash_str = device_name + "-" + base::UintToString(vendor_id) +
+                         "-" + base::UintToString(product_id);
+  return base::PersistentHash(hash_str);
+}
+
+// static
+uint32_t TouchCalibrationData::GetFallbackTouchDeviceIdentifier() {
+  static const uint32_t kFallbackTouchDeviceIdentifier =
+      GenerateTouchDeviceIdentifier(kFallbackTouchDeviceName, 0, 0);
+  return kFallbackTouchDeviceIdentifier;
+}
+
 bool TouchCalibrationData::operator==(TouchCalibrationData other) const {
   if (bounds != other.bounds)
     return false;
@@ -297,7 +317,6 @@
       has_overscan_(false),
       active_rotation_source_(Display::ROTATION_SOURCE_UNKNOWN),
       touch_support_(Display::TOUCH_SUPPORT_UNKNOWN),
-      has_touch_calibration_data_(false),
       device_scale_factor_(1.0f),
       device_dpi_(kDpi96),
       overscan_insets_in_dip_(0, 0, 0, 0),
@@ -314,7 +333,6 @@
       has_overscan_(has_overscan),
       active_rotation_source_(Display::ROTATION_SOURCE_UNKNOWN),
       touch_support_(Display::TOUCH_SUPPORT_UNKNOWN),
-      has_touch_calibration_data_(false),
       device_scale_factor_(1.0f),
       device_dpi_(kDpi96),
       overscan_insets_in_dip_(0, 0, 0, 0),
@@ -374,9 +392,7 @@
     else if (!native_info.overscan_insets_in_dip_.IsEmpty())
       overscan_insets_in_dip_ = native_info.overscan_insets_in_dip_;
 
-    has_touch_calibration_data_ = native_info.has_touch_calibration_data_;
-    if (has_touch_calibration_data_)
-      touch_calibration_data_ = native_info.touch_calibration_data_;
+    touch_calibration_data_map_ = native_info.touch_calibration_data_map_;
 
     rotations_ = native_info.rotations_;
     configured_ui_scale_ = native_info.configured_ui_scale_;
@@ -512,9 +528,49 @@
 }
 
 void ManagedDisplayInfo::SetTouchCalibrationData(
+    uint32_t touch_device_identifier,
     const TouchCalibrationData& touch_calibration_data) {
-  has_touch_calibration_data_ = true;
-  touch_calibration_data_ = touch_calibration_data;
+  touch_calibration_data_map_[touch_device_identifier] = touch_calibration_data;
+}
+
+const TouchCalibrationData& ManagedDisplayInfo::GetTouchCalibrationData(
+    uint32_t touch_device_identifier) const {
+  DCHECK(HasTouchCalibrationData(touch_device_identifier));
+
+  // If the system does not have the calibration information for the touch
+  // device identified with |touch_device_identifier|, use the fallback
+  // calibration data if availble. This also helps keep support for legacy
+  // touch calibration data which is stored in association with the fallback
+  // device identifier.
+  if (touch_calibration_data_map_.count(
+          TouchCalibrationData::GetFallbackTouchDeviceIdentifier()) &&
+      touch_calibration_data_map_.size() == 1) {
+    return touch_calibration_data_map_.at(
+        TouchCalibrationData::GetFallbackTouchDeviceIdentifier());
+  }
+
+  return touch_calibration_data_map_.at(touch_device_identifier);
+}
+
+void ManagedDisplayInfo::SetTouchCalibrationDataMap(
+    const std::map<uint32_t, TouchCalibrationData>& data_map) {
+  touch_calibration_data_map_ = data_map;
+}
+
+bool ManagedDisplayInfo::HasTouchCalibrationData(
+    uint32_t touch_device_identifier) const {
+  return touch_calibration_data_map_.count(touch_device_identifier) ||
+         touch_calibration_data_map_.count(
+             TouchCalibrationData::GetFallbackTouchDeviceIdentifier());
+}
+
+void ManagedDisplayInfo::ClearTouchCalibrationData(
+    uint32_t touch_device_identifier) {
+  touch_calibration_data_map_.erase(touch_device_identifier);
+}
+
+void ManagedDisplayInfo::ClearAllTouchCalibrationData() {
+  touch_calibration_data_map_.clear();
 }
 
 }  // namespace display
diff --git a/ui/display/manager/managed_display_info.h b/ui/display/manager/managed_display_info.h
index 38c2aab..b82aa261 100644
--- a/ui/display/manager/managed_display_info.h
+++ b/ui/display/manager/managed_display_info.h
@@ -41,6 +41,15 @@
                : pair_1.first.x() < pair_2.first.x();
   }
 
+  // Returns a hash that can be used as a key for storing display preferences
+  // for a display associated with a touch device.
+  static uint32_t GenerateTouchDeviceIdentifier(const std::string& device_name,
+                                                uint16_t vendor_id,
+                                                uint16_t product_id);
+
+  // Returns a touch device identifier used as a default or a fallback option.
+  static uint32_t GetFallbackTouchDeviceIdentifier();
+
   bool operator==(TouchCalibrationData other) const;
 
   // Calibration point pairs used during calibration. Each point pair contains a
@@ -272,14 +281,19 @@
   // display.
   void SetManagedDisplayModes(const ManagedDisplayModeList& display_modes);
 
-
-  // Sets/Gets the touch calibration data for the display.
-  void SetTouchCalibrationData(const TouchCalibrationData& calibration_data);
-  TouchCalibrationData
-      GetTouchCalibrationData() const & { return touch_calibration_data_; }
-  bool has_touch_calibration_data() const
-      { return has_touch_calibration_data_; }
-  void clear_touch_calibration_data() { has_touch_calibration_data_ = false; }
+  void SetTouchCalibrationData(uint32_t touch_device_identifier,
+                               const TouchCalibrationData& calibration_data);
+  const TouchCalibrationData& GetTouchCalibrationData(
+      uint32_t touch_device_identifier) const;
+  const std::map<uint32_t, TouchCalibrationData>& touch_calibration_data_map()
+      const {
+    return touch_calibration_data_map_;
+  }
+  void SetTouchCalibrationDataMap(
+      const std::map<uint32_t, TouchCalibrationData>& data_map);
+  bool HasTouchCalibrationData(uint32_t touch_device_identifier) const;
+  void ClearTouchCalibrationData(uint32_t touch_device_identifier);
+  void ClearAllTouchCalibrationData();
 
   // Returns the native mode size. If a native mode is not present, return an
   // empty size.
@@ -321,7 +335,6 @@
   std::map<Display::RotationSource, Display::Rotation> rotations_;
   Display::RotationSource active_rotation_source_;
   Display::TouchSupport touch_support_;
-  bool has_touch_calibration_data_;
 
   // The set of input devices associated with this display.
   std::vector<int> input_devices_;
@@ -368,8 +381,10 @@
   // Maximum cursor size.
   gfx::Size maximum_cursor_size_;
 
-  // Information associated to touch calibration for the display.
-  TouchCalibrationData touch_calibration_data_;
+  // Information associated to touch calibration for the display. Stores a
+  // mapping of each touch device, identified by its unique touch device
+  // identifier, with the touch calibration data associated with the display.
+  std::map<uint32_t, TouchCalibrationData> touch_calibration_data_map_;
 
   // If you add a new member, you need to update Copy().
 };
diff --git a/ui/display/manager/managed_display_info_unittest.cc b/ui/display/manager/managed_display_info_unittest.cc
index 069c761..a5498571 100644
--- a/ui/display/manager/managed_display_info_unittest.cc
+++ b/ui/display/manager/managed_display_info_unittest.cc
@@ -151,29 +151,40 @@
   ManagedDisplayInfo info =
       ManagedDisplayInfo::CreateFromSpecWithID("200x100", 10);
 
-  EXPECT_FALSE(info.has_touch_calibration_data());
+  EXPECT_FALSE(info.touch_calibration_data_map().size());
 
-  TouchCalibrationData::CalibrationPointPairQuad points = {{
-    std::make_pair(gfx::Point(10, 10), gfx::Point(11, 12)),
-    std::make_pair(gfx::Point(190, 10), gfx::Point(195, 8)),
-    std::make_pair(gfx::Point(10, 90), gfx::Point(12, 94)),
-    std::make_pair(gfx::Point(190, 90), gfx::Point(189, 88))
-  }};
+  TouchCalibrationData::CalibrationPointPairQuad points = {
+      {std::make_pair(gfx::Point(10, 10), gfx::Point(11, 12)),
+       std::make_pair(gfx::Point(190, 10), gfx::Point(195, 8)),
+       std::make_pair(gfx::Point(10, 90), gfx::Point(12, 94)),
+       std::make_pair(gfx::Point(190, 90), gfx::Point(189, 88))}};
 
   gfx::Size size(200, 100);
 
   TouchCalibrationData expected_data(points, size);
+  uint32_t touch_device_identifier = 1234;
 
   // Add touch data for the display.
-  info.SetTouchCalibrationData(expected_data);
+  info.SetTouchCalibrationData(touch_device_identifier, expected_data);
 
-  EXPECT_TRUE(info.has_touch_calibration_data());
-  EXPECT_EQ(expected_data, info.GetTouchCalibrationData());
+  EXPECT_TRUE(info.touch_calibration_data_map().size());
+  EXPECT_EQ(expected_data,
+            info.GetTouchCalibrationData(touch_device_identifier));
 
-  // Clear all touch calibration data for the display.
-  info.clear_touch_calibration_data();
+  info.SetTouchCalibrationData(touch_device_identifier + 1, expected_data);
+  EXPECT_EQ(info.touch_calibration_data_map().size(), 2UL);
 
-  EXPECT_FALSE(info.has_touch_calibration_data());
+  // Clear touch calibration data for touch device associated with the given
+  // touch identifier.
+  info.ClearTouchCalibrationData(touch_device_identifier);
+  EXPECT_TRUE(info.touch_calibration_data_map().size());
+
+  // Add another touch device calibration data.
+  info.SetTouchCalibrationData(touch_device_identifier, expected_data);
+  info.ClearAllTouchCalibrationData();
+
+  // There should be no touch device data associated with this display.
+  EXPECT_FALSE(info.touch_calibration_data_map().size());
 }
 
 }  // namespace display
diff --git a/ui/display/win/screen_win.cc b/ui/display/win/screen_win.cc
index 8c543ec5..df4e5cb1 100644
--- a/ui/display/win/screen_win.cc
+++ b/ui/display/win/screen_win.cc
@@ -415,6 +415,8 @@
 }
 
 Display ScreenWin::GetDisplayNearestWindow(gfx::NativeWindow window) const {
+  if (!window)
+    return GetPrimaryDisplay();
   HWND window_hwnd = GetHWNDFromNativeView(window);
   if (!window_hwnd) {
     // When |window| isn't rooted to a display, we should just return the
diff --git a/ui/events/event.h b/ui/events/event.h
index 61861900..f3bdad4 100644
--- a/ui/events/event.h
+++ b/ui/events/event.h
@@ -213,6 +213,11 @@
            !(flags() & EF_FROM_TOUCH));
   }
 
+  bool IsPinchEvent() const {
+    return type_ == ET_GESTURE_PINCH_BEGIN ||
+           type_ == ET_GESTURE_PINCH_UPDATE || type_ == ET_GESTURE_PINCH_END;
+  }
+
   bool IsScrollGestureEvent() const {
     return type_ == ET_GESTURE_SCROLL_BEGIN ||
            type_ == ET_GESTURE_SCROLL_UPDATE ||
diff --git a/ui/gfx/codec/png_codec_unittest.cc b/ui/gfx/codec/png_codec_unittest.cc
index faf665d..4e8f07b 100644
--- a/ui/gfx/codec/png_codec_unittest.cc
+++ b/ui/gfx/codec/png_codec_unittest.cc
@@ -769,7 +769,6 @@
   const int kHeight = 20;
   const int kPaddedWidth = 32;
   const int kBytesPerPixel = 4;
-  const int kPaddedSize = kPaddedWidth * kHeight;
   const int kRowBytes = kPaddedWidth * kBytesPerPixel;
 
   SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight);
@@ -781,7 +780,9 @@
   // We write on the pad area here too.
   // The encoder should ignore the pad area.
   uint32_t* src_data = original_bitmap.getAddr32(0, 0);
-  for (int i = 0; i < kPaddedSize; i++) {
+  const int count =
+      original_bitmap.getSafeSize() / original_bitmap.bytesPerPixel();
+  for (int i = 0; i < count; i++) {
     src_data[i] = SkPreMultiplyARGB(i % 255, i % 250, i % 245, i % 240);
   }
 
diff --git a/ui/gfx/paint_vector_icon.cc b/ui/gfx/paint_vector_icon.cc
index dd6c2c7..f7b034c2 100644
--- a/ui/gfx/paint_vector_icon.cc
+++ b/ui/gfx/paint_vector_icon.cc
@@ -66,6 +66,7 @@
       case V_LINE_TO:
       case R_V_LINE_TO:
       case CANVAS_DIMENSIONS:
+      case PATH_COLOR_ALPHA:
         return 1;
 
       case MOVE_TO:
@@ -123,6 +124,7 @@
     return command;
 
   RETURN_IF_IS(NEW_PATH);
+  RETURN_IF_IS(PATH_COLOR_ALPHA);
   RETURN_IF_IS(PATH_COLOR_ARGB);
   RETURN_IF_IS(PATH_MODE_CLEAR);
   RETURN_IF_IS(STROKE);
@@ -213,6 +215,10 @@
       case NEW_PATH:
         break;
 
+      case PATH_COLOR_ALPHA:
+        flags.setAlpha(SkScalarFloorToInt(arg(0)));
+        break;
+
       case PATH_COLOR_ARGB:
         flags.setColor(SkColorSetARGB(
             SkScalarFloorToInt(arg(0)), SkScalarFloorToInt(arg(1)),
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
index 16a629b0..1e8a19b 100644
--- a/ui/gfx/render_text.cc
+++ b/ui/gfx/render_text.cc
@@ -963,6 +963,14 @@
   return base::string16();
 }
 
+void RenderText::SetPasswordReplacementChar(
+    base::char16 password_replacement_char) {
+  if (password_replacement_char_ == password_replacement_char)
+    return;
+  password_replacement_char_ = password_replacement_char;
+  OnTextAttributeChanged();
+}
+
 RenderText::RenderText()
     : horizontal_alignment_(base::i18n::IsRTL() ? ALIGN_RIGHT : ALIGN_LEFT),
       directionality_mode_(DIRECTIONALITY_FROM_TEXT),
@@ -1346,8 +1354,7 @@
   if (obscured_) {
     size_t obscured_text_length =
         static_cast<size_t>(UTF16IndexToOffset(text_, 0, text_.length()));
-    layout_text_.assign(obscured_text_length,
-                        RenderText::kPasswordReplacementChar);
+    layout_text_.assign(obscured_text_length, password_replacement_char_);
 
     if (obscured_reveal_index_ >= 0 &&
         obscured_reveal_index_ < static_cast<int>(text_.length())) {
diff --git a/ui/gfx/render_text.h b/ui/gfx/render_text.h
index 024c73e..264a6dc0 100644
--- a/ui/gfx/render_text.h
+++ b/ui/gfx/render_text.h
@@ -229,7 +229,8 @@
   bool clip_to_display_rect() const { return clip_to_display_rect_; }
   void set_clip_to_display_rect(bool clip) { clip_to_display_rect_ = clip; }
 
-  // In an obscured (password) field, all text is drawn as asterisks or bullets.
+  // In an obscured (password) field, all text is drawn as asterisks, bullets or
+  // a custom password replacement char.
   bool obscured() const { return obscured_; }
   void SetObscured(bool obscured);
 
@@ -489,6 +490,13 @@
 
   void set_strike_thickness_factor(SkScalar f) { strike_thickness_factor_ = f; }
 
+  // Sets a password replacement char to override the default value.
+  void SetPasswordReplacementChar(base::char16 password_replacement_char);
+
+  base::char16 password_replacement_char() const {
+    return password_replacement_char_;
+  }
+
  protected:
   RenderText();
 
@@ -828,6 +836,9 @@
   // The ratio of strike-through line thickness to text height.
   SkScalar strike_thickness_factor_;
 
+  // The character used for displaying obscured text.
+  base::char16 password_replacement_char_ = kPasswordReplacementChar;
+
   DISALLOW_COPY_AND_ASSIGN(RenderText);
 };
 
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc
index e2d9f2e..f7d043e 100644
--- a/ui/gfx/render_text_unittest.cc
+++ b/ui/gfx/render_text_unittest.cc
@@ -286,7 +286,8 @@
 }
 
 // Helper method to return an obscured string of the given |length|, with the
-// |reveal_index| filled with |reveal_char|.
+// |reveal_index| filled with |reveal_char|, using the default password
+// placement char.
 base::string16 GetObscuredString(size_t length,
                                  size_t reveal_index,
                                  base::char16 reveal_char) {
@@ -295,9 +296,12 @@
   return base::string16(arr.begin(), arr.end());
 }
 
-// Helper method to return an obscured string of the given |length|.
-base::string16 GetObscuredString(size_t length) {
-  return base::string16(length, RenderText::kPasswordReplacementChar);
+// Helper method to return an obscured string of the given |length|, using the
+// specified password placement char, or the default if none is specified.
+base::string16 GetObscuredString(size_t length,
+                                 base::char16 password_replacement_char =
+                                     RenderText::kPasswordReplacementChar) {
+  return base::string16(length, password_replacement_char);
 }
 
 // Converts a vector of UTF8 literals into a vector of (UTF16) string16.
@@ -972,6 +976,30 @@
   EXPECT_EQ(valid_expect_5_and_6, render_text->GetDisplayText());
 }
 
+TEST_P(RenderTextTest, CustomPasswordReplacementChar) {
+  const base::char16 custom_password_replacement_char = 0x2219;
+  const base::string16 seuss = UTF8ToUTF16("hop on pop");
+  const base::string16 no_seuss_default = GetObscuredString(seuss.length());
+  const base::string16 no_seuss_custom =
+      GetObscuredString(seuss.length(), custom_password_replacement_char);
+  RenderText* render_text = GetRenderText();
+
+  render_text->SetText(seuss);
+  render_text->SetObscured(true);
+  EXPECT_EQ(seuss, render_text->text());
+  // If password replacement char is not explicitly set, GetDisplayText()
+  // returns a string filled with the default value.
+  EXPECT_EQ(no_seuss_default, render_text->GetDisplayText());
+
+  // After a custom password replacement char is set, GetDisplayText()
+  // returns a string filled with the custom value.
+  render_text->SetPasswordReplacementChar(custom_password_replacement_char);
+  EXPECT_EQ(no_seuss_custom, render_text->GetDisplayText());
+  render_text->SetObscured(false);
+  EXPECT_EQ(seuss, render_text->text());
+  EXPECT_EQ(seuss, render_text->GetDisplayText());
+}
+
 TEST_P(RenderTextTest, ObscuredEmoji) {
   // Ensures text itemization doesn't crash on obscured multi-char glyphs.
   RenderText* render_text = GetRenderText();
diff --git a/ui/gfx/skia_util.cc b/ui/gfx/skia_util.cc
index c0c4a54..5f0c743a 100644
--- a/ui/gfx/skia_util.cc
+++ b/ui/gfx/skia_util.cc
@@ -98,12 +98,12 @@
   size_t size2 = 0;
 
   addr1 = bitmap1.getAddr32(0, 0);
-  size1 = bitmap1.getSize();
+  size1 = bitmap1.getSafeSize();
 
   addr2 = bitmap2.getAddr32(0, 0);
-  size2 = bitmap2.getSize();
+  size2 = bitmap2.getSafeSize();
 
-  return (size1 == size2) && (0 == memcmp(addr1, addr2, bitmap1.getSize()));
+  return (size1 == size2) && (0 == memcmp(addr1, addr2, size1));
 }
 
 void ConvertSkiaToRGBA(const unsigned char* skia,
diff --git a/ui/gfx/vector_icon_types.h b/ui/gfx/vector_icon_types.h
index 9cbe984..d1cba9b3 100644
--- a/ui/gfx/vector_icon_types.h
+++ b/ui/gfx/vector_icon_types.h
@@ -22,6 +22,8 @@
 enum CommandType {
   // A new <path> element. For the first path, this is assumed.
   NEW_PATH,
+  // Sets the alpha for the current path.
+  PATH_COLOR_ALPHA,
   // Sets the color for the current path.
   PATH_COLOR_ARGB,
   // Sets the path to clear mode (Skia's kClear_Mode).
diff --git a/ui/gl/gl_context_cgl.cc b/ui/gl/gl_context_cgl.cc
index dab9d27..6b85039 100644
--- a/ui/gl/gl_context_cgl.cc
+++ b/ui/gl/gl_context_cgl.cc
@@ -242,6 +242,16 @@
   if (IsCurrent(surface))
     return true;
 
+  // It's likely we're going to switch OpenGL contexts at this point.
+  // Before doing so, if there is a current context, flush it. There
+  // are many implicit assumptions of flush ordering between contexts
+  // at higher levels, and if a flush isn't performed, OpenGL commands
+  // may be issued in unexpected orders, causing flickering and other
+  // artifacts.
+  if (CGLGetCurrentContext() != nullptr) {
+    glFlush();
+  }
+
   ScopedReleaseCurrent release_current;
   TRACE_EVENT0("gpu", "GLContextCGL::MakeCurrent");
 
@@ -270,6 +280,12 @@
   if (!IsCurrent(surface))
     return;
 
+  // Before releasing the current context, flush it. This ensures that
+  // all commands issued by higher levels will be seen by the OpenGL
+  // implementation, which is assumed throughout the code. See comment
+  // in MakeCurrent, above.
+  glFlush();
+
   SetCurrent(nullptr);
   CGLSetCurrentContext(nullptr);
 }
diff --git a/ui/gl/gl_implementation.cc b/ui/gl/gl_implementation.cc
index ba060973..eb9285e 100644
--- a/ui/gl/gl_implementation.cc
+++ b/ui/gl/gl_implementation.cc
@@ -104,7 +104,7 @@
 }
 
 GLImplementation GetSoftwareGLImplementation() {
-#if defined(OS_WIN)
+#if (defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS) && !defined(USE_OZONE)))
   return kGLImplementationSwiftShaderGL;
 #else
   return kGLImplementationOSMesaGL;
diff --git a/ui/gl/init/gl_factory.cc b/ui/gl/init/gl_factory.cc
index 643941be..509d34d4 100644
--- a/ui/gl/init/gl_factory.cc
+++ b/ui/gl/init/gl_factory.cc
@@ -24,7 +24,7 @@
   std::vector<GLImplementation> allowed_impls = GetAllowedGLImplementations();
   DCHECK(!allowed_impls.empty());
 
-  base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
+  const base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
 
   // The default implementation is always the first one in list.
   GLImplementation impl = allowed_impls[0];
diff --git a/ui/gl/init/gl_initializer_x11.cc b/ui/gl/init/gl_initializer_x11.cc
index e363502..2392e65 100644
--- a/ui/gl/init/gl_initializer_x11.cc
+++ b/ui/gl/init/gl_initializer_x11.cc
@@ -85,6 +85,8 @@
   base::FilePath glesv2_path(kGLESv2LibraryName);
   base::FilePath egl_path(kEGLLibraryName);
 
+  const base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
+
   if (implementation == kGLImplementationSwiftShaderGL) {
 #if BUILDFLAG(ENABLE_SWIFTSHADER)
     base::FilePath module_path;
@@ -97,7 +99,8 @@
 #else
     return false;
 #endif
-  } else {
+  } else if (cmd->GetSwitchValueASCII(switches::kUseGL) ==
+             kGLImplementationANGLEName) {
     base::FilePath module_path;
     if (!PathService::Get(base::DIR_MODULE, &module_path))
       return false;
diff --git a/ui/keyboard/keyboard_controller.cc b/ui/keyboard/keyboard_controller.cc
index 004c143a..f73282a 100644
--- a/ui/keyboard/keyboard_controller.cc
+++ b/ui/keyboard/keyboard_controller.cc
@@ -33,12 +33,8 @@
 #include "ui/wm/core/window_animations.h"
 
 #if defined(OS_CHROMEOS)
-#include "base/process/launch.h"
-#include "base/sys_info.h"
-#if defined(USE_OZONE)
 #include "ui/ozone/public/input_controller.h"
 #include "ui/ozone/public/ozone_platform.h"
-#endif
 #endif  // if defined(OS_CHROMEOS)
 
 namespace {
@@ -136,7 +132,6 @@
 
 void ToggleTouchEventLogging(bool enable) {
 #if defined(OS_CHROMEOS)
-#if defined(USE_OZONE)
   // TODO(moshayedi): crbug.com/642863. Revisit when we have mojo interface for
   // InputController for processes that aren't mus-ws.
   if (aura::Env::GetInstance()->mode() == aura::Env::Mode::MUS)
@@ -145,20 +140,6 @@
       ui::OzonePlatform::GetInstance()->GetInputController();
   if (controller)
     controller->SetTouchEventLoggingEnabled(enable);
-#elif defined(USE_X11)
-  if (!base::SysInfo::IsRunningOnChromeOS())
-    return;
-  base::CommandLine command(
-      base::FilePath("/opt/google/touchscreen/toggle_touch_event_logging"));
-  if (enable)
-    command.AppendArg("1");
-  else
-    command.AppendArg("0");
-  VLOG(1) << "Running " << command.GetCommandLineString();
-  base::LaunchOptions options;
-  options.wait = true;
-  base::LaunchProcess(command, options);
-#endif
 #endif  // defined(OS_CHROMEOS)
 }
 
@@ -660,6 +641,11 @@
   ui_->EnsureCaretInWorkArea();
 }
 
+void KeyboardController::NotifyKeyboardConfigChanged() {
+  for (KeyboardControllerObserver& observer : observer_list_)
+    observer.OnKeyboardConfigChanged();
+}
+
 void KeyboardController::AdjustKeyboardBounds() {
   int keyboard_height = GetContainerWindow()->bounds().height();
   const gfx::Rect& root_bounds = container_->GetRootWindow()->bounds();
diff --git a/ui/keyboard/keyboard_controller.h b/ui/keyboard/keyboard_controller.h
index 47331ed..6961e6a 100644
--- a/ui/keyboard/keyboard_controller.h
+++ b/ui/keyboard/keyboard_controller.h
@@ -16,6 +16,7 @@
 #include "ui/keyboard/keyboard_event_filter.h"
 #include "ui/keyboard/keyboard_export.h"
 #include "ui/keyboard/keyboard_layout_delegate.h"
+#include "ui/keyboard/keyboard_util.h"
 
 namespace aura {
 class Window;
@@ -148,6 +149,10 @@
   // For access to SetContainerBounds.
   friend class KeyboardLayoutManager;
 
+  // For access to NotifyKeyboardConfigChanged
+  friend bool keyboard::UpdateKeyboardConfig(
+      const keyboard::KeyboardConfig& config);
+
   // aura::WindowObserver overrides
   void OnWindowHierarchyChanged(const HierarchyChangeParams& params) override;
   void OnWindowAddedToRootWindow(aura::Window* window) override;
@@ -188,6 +193,10 @@
   // display.
   void AdjustKeyboardBounds();
 
+  // Notifies keyboard config change to the observers.
+  // Only called from |UpdateKeyboardConfig| in keyboard_util.
+  void NotifyKeyboardConfigChanged();
+
   // Validates the state transition. Called from ChangeState.
   void CheckStateTransition(KeyboardControllerState prev,
                             KeyboardControllerState next);
diff --git a/ui/keyboard/keyboard_controller_observer.h b/ui/keyboard/keyboard_controller_observer.h
index 025b631..6d14a62e 100644
--- a/ui/keyboard/keyboard_controller_observer.h
+++ b/ui/keyboard/keyboard_controller_observer.h
@@ -30,8 +30,11 @@
   // successfully. This is same as |state| == HIDDEN on OnStateChanged.
   virtual void OnKeyboardHidden() {}
 
-  // When state changed.
+  // Called when the state changed.
   virtual void OnStateChanged(const KeyboardControllerState state) {}
+
+  // Called when the virtual keyboard IME config changed.
+  virtual void OnKeyboardConfigChanged() {}
 };
 
 }  // namespace keyboard
diff --git a/ui/keyboard/keyboard_util.cc b/ui/keyboard/keyboard_util.cc
index e517314e..c698cefa 100644
--- a/ui/keyboard/keyboard_util.cc
+++ b/ui/keyboard/keyboard_util.cc
@@ -49,12 +49,12 @@
 base::LazyInstance<base::Time>::DestructorAtExit g_keyboard_load_time_start =
     LAZY_INSTANCE_INITIALIZER;
 
+struct keyboard::KeyboardConfig g_keyboard_config;
+
 bool g_accessibility_keyboard_enabled = false;
 
 bool g_hotrod_keyboard_enabled = false;
 
-bool g_keyboard_restricted = false;
-
 bool g_touch_keyboard_enabled = false;
 
 KeyboardState g_requested_keyboard_state = KEYBOARD_STATE_AUTO;
@@ -66,6 +66,20 @@
 
 }  // namespace
 
+bool UpdateKeyboardConfig(const KeyboardConfig& keyboard_config) {
+  if (g_keyboard_config == keyboard_config)
+    return false;
+  g_keyboard_config = keyboard_config;
+  keyboard::KeyboardController* controller = KeyboardController::GetInstance();
+  if (controller)
+    controller->NotifyKeyboardConfigChanged();
+  return true;
+}
+
+const KeyboardConfig& GetKeyboardConfig() {
+  return g_keyboard_config;
+}
+
 void SetAccessibilityKeyboardEnabled(bool enabled) {
   g_accessibility_keyboard_enabled = enabled;
 }
@@ -171,14 +185,6 @@
       switches::kDisableInputView);
 }
 
-void SetKeyboardRestricted(bool restricted) {
-  g_keyboard_restricted = restricted;
-}
-
-bool GetKeyboardRestricted() {
-  return g_keyboard_restricted;
-}
-
 bool IsExperimentalInputViewEnabled() {
   return base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableExperimentalInputViewFeatures);
@@ -199,12 +205,6 @@
       switches::kDisableGestureEditing);
 }
 
-bool IsVoiceInputEnabled() {
-  return !g_keyboard_restricted &&
-         !base::CommandLine::ForCurrentProcess()->HasSwitch(
-             switches::kDisableVoiceInput);
-}
-
 bool InsertText(const base::string16& text) {
   KeyboardController* controller = KeyboardController::GetInstance();
   if (!controller)
diff --git a/ui/keyboard/keyboard_util.h b/ui/keyboard/keyboard_util.h
index 62e5daa..80f3f1d5b 100644
--- a/ui/keyboard/keyboard_util.h
+++ b/ui/keyboard/keyboard_util.h
@@ -18,6 +18,23 @@
 
 namespace keyboard {
 
+// For virtual keyboard IME extension.
+struct KeyboardConfig {
+  bool auto_complete = true;
+  bool auto_correct = true;
+  bool handwriting = true;
+  bool spell_check = true;
+  // It denotes the preferred value, and can be true even if there is no actual
+  // audio input device.
+  bool voice_input = true;
+
+  bool operator==(const keyboard::KeyboardConfig& rhs) const {
+    return auto_complete == rhs.auto_complete &&
+           auto_correct == rhs.auto_correct && handwriting == rhs.handwriting &&
+           spell_check == rhs.spell_check && voice_input == rhs.voice_input;
+  }
+};
+
 // An enumeration of different keyboard control events that should be logged.
 enum KeyboardControlEvent {
   KEYBOARD_CONTROL_SHOW = 0,
@@ -50,6 +67,14 @@
   KEYBOARD_STATE_DISABLED,
 };
 
+// Updates the current keyboard config with the given config is they are
+// different, notifying to observers. Returns whether update happened.
+KEYBOARD_EXPORT bool UpdateKeyboardConfig(
+    const keyboard::KeyboardConfig& keyboard_config);
+
+// Gets the current virtual keyboard IME config.
+KEYBOARD_EXPORT const keyboard::KeyboardConfig& GetKeyboardConfig();
+
 // Sets the state of the a11y onscreen keyboard.
 KEYBOARD_EXPORT void SetAccessibilityKeyboardEnabled(bool enabled);
 
diff --git a/ui/keyboard/keyboard_util_unittest.cc b/ui/keyboard/keyboard_util_unittest.cc
index 3385c7e1..88afee2 100644
--- a/ui/keyboard/keyboard_util_unittest.cc
+++ b/ui/keyboard/keyboard_util_unittest.cc
@@ -58,32 +58,32 @@
 // Tests that we respect the accessibility setting.
 TEST_F(KeyboardUtilTest, AlwaysShowIfA11yEnabled) {
   // Disabled by default.
-  ASSERT_FALSE(keyboard::IsKeyboardEnabled());
+  EXPECT_FALSE(keyboard::IsKeyboardEnabled());
   // If enabled by accessibility, should ignore other flag values.
   DisableAllFlags();
   keyboard::SetAccessibilityKeyboardEnabled(true);
-  ASSERT_TRUE(keyboard::IsKeyboardEnabled());
+  EXPECT_TRUE(keyboard::IsKeyboardEnabled());
 }
 
 // Tests that we respect the policy setting.
 TEST_F(KeyboardUtilTest, AlwaysShowIfPolicyEnabled) {
-  ASSERT_FALSE(keyboard::IsKeyboardEnabled());
+  EXPECT_FALSE(keyboard::IsKeyboardEnabled());
   // If policy is enabled, should ignore other flag values.
   DisableAllFlags();
   keyboard::SetKeyboardShowOverride(keyboard::KEYBOARD_SHOW_OVERRIDE_ENABLED);
-  ASSERT_TRUE(keyboard::IsKeyboardEnabled());
+  EXPECT_TRUE(keyboard::IsKeyboardEnabled());
 }
 
 // Tests that we respect the policy setting.
 TEST_F(KeyboardUtilTest, HidesIfPolicyDisabled) {
-  ASSERT_FALSE(keyboard::IsKeyboardEnabled());
+  EXPECT_FALSE(keyboard::IsKeyboardEnabled());
   EnableAllFlags();
   // Set accessibility to neutral since accessibility has higher precedence.
   keyboard::SetAccessibilityKeyboardEnabled(false);
-  ASSERT_TRUE(keyboard::IsKeyboardEnabled());
+  EXPECT_TRUE(keyboard::IsKeyboardEnabled());
   // Disable policy. Keyboard should be disabled.
   keyboard::SetKeyboardShowOverride(keyboard::KEYBOARD_SHOW_OVERRIDE_DISABLED);
-  ASSERT_FALSE(keyboard::IsKeyboardEnabled());
+  EXPECT_FALSE(keyboard::IsKeyboardEnabled());
 }
 
 // Tests that the keyboard shows when requested state provided higher priority
@@ -92,10 +92,10 @@
   DisableAllFlags();
   // Remove device policy, which has higher precedence than us.
   keyboard::SetKeyboardShowOverride(keyboard::KEYBOARD_SHOW_OVERRIDE_NONE);
-  ASSERT_FALSE(keyboard::IsKeyboardEnabled());
+  EXPECT_FALSE(keyboard::IsKeyboardEnabled());
   // Requested should have higher precedence than all the remaining flags.
   keyboard::SetRequestedKeyboardState(keyboard::KEYBOARD_STATE_ENABLED);
-  ASSERT_TRUE(keyboard::IsKeyboardEnabled());
+  EXPECT_TRUE(keyboard::IsKeyboardEnabled());
 }
 
 // Tests that the touch keyboard is hidden when requested state is disabled and
@@ -105,19 +105,32 @@
   // Remove higher precedence flags.
   keyboard::SetKeyboardShowOverride(keyboard::KEYBOARD_SHOW_OVERRIDE_NONE);
   keyboard::SetAccessibilityKeyboardEnabled(false);
-  ASSERT_TRUE(keyboard::IsKeyboardEnabled());
+  EXPECT_TRUE(keyboard::IsKeyboardEnabled());
   // Set requested state to disable. Keyboard should disable.
   keyboard::SetRequestedKeyboardState(keyboard::KEYBOARD_STATE_DISABLED);
-  ASSERT_FALSE(keyboard::IsKeyboardEnabled());
+  EXPECT_FALSE(keyboard::IsKeyboardEnabled());
 }
 
 // SetTouchKeyboardEnabled has the lowest priority, but should still work when
 // none of the other flags are enabled.
 TEST_F(KeyboardUtilTest, HideKeyboardWhenTouchEnabled) {
   ResetAllFlags();
-  ASSERT_FALSE(keyboard::IsKeyboardEnabled());
+  EXPECT_FALSE(keyboard::IsKeyboardEnabled());
   keyboard::SetTouchKeyboardEnabled(true);
-  ASSERT_TRUE(keyboard::IsKeyboardEnabled());
+  EXPECT_TRUE(keyboard::IsKeyboardEnabled());
+}
+
+TEST_F(KeyboardUtilTest, UpdateKeyboardConfig) {
+  ResetAllFlags();
+  keyboard::KeyboardConfig config = keyboard::GetKeyboardConfig();
+  EXPECT_TRUE(config.spell_check);
+  EXPECT_FALSE(keyboard::UpdateKeyboardConfig(config));
+
+  config.spell_check = false;
+  EXPECT_TRUE(keyboard::UpdateKeyboardConfig(config));
+  EXPECT_FALSE(keyboard::GetKeyboardConfig().spell_check);
+
+  EXPECT_FALSE(keyboard::UpdateKeyboardConfig(config));
 }
 
 TEST_F(KeyboardUtilTest, IsOverscrollEnabled) {
diff --git a/ui/login/account_picker/md_user_pod_row.js b/ui/login/account_picker/md_user_pod_row.js
index 404f597..7a02d1c 100644
--- a/ui/login/account_picker/md_user_pod_row.js
+++ b/ui/login/account_picker/md_user_pod_row.js
@@ -4783,7 +4783,8 @@
      */
     maybePreselectPod: function() {
       var pod = this.preselectedPod;
-      this.focusPod(pod);
+      // Force a focus update to ensure the correct wallpaper is loaded.
+      this.focusPod(pod, true /* force */);
 
       // Hide user-type-bubble in case all user pods are disabled and we focus
       // first pod.
diff --git a/ui/login/display_manager.js b/ui/login/display_manager.js
index f50ee7d0..1c4e80e 100644
--- a/ui/login/display_manager.js
+++ b/ui/login/display_manager.js
@@ -41,7 +41,6 @@
 /* Accelerator identifiers. Must be kept in sync with webui_login_view.cc. */
 /** @const */ var ACCELERATOR_CANCEL = 'cancel';
 /** @const */ var ACCELERATOR_ENABLE_DEBBUGING = 'debugging';
-/** @const */ var ACCELERATOR_TOGGLE_EASY_BOOTSTRAP = 'toggle_easy_bootstrap';
 /** @const */ var ACCELERATOR_ENROLLMENT = 'enrollment';
 /** @const */ var ACCELERATOR_KIOSK_ENABLE = 'kiosk_enable';
 /** @const */ var ACCELERATOR_VERSION = 'version';
@@ -414,9 +413,6 @@
       } else if (name == ACCELERATOR_APP_LAUNCH_NETWORK_CONFIG) {
         if (currentStepId == SCREEN_APP_LAUNCH_SPLASH)
           chrome.send('networkConfigRequest');
-      } else if (name == ACCELERATOR_TOGGLE_EASY_BOOTSTRAP) {
-        if (currentStepId == SCREEN_GAIA_SIGNIN)
-          chrome.send('toggleEasyBootstrap');
       } else if (name == ACCELERATOR_BOOTSTRAPPING_SLAVE) {
         chrome.send('setOobeBootstrappingSlave');
       }
diff --git a/ui/strings/ui_strings.grd b/ui/strings/ui_strings.grd
index 71cceaf7..ff1e946 100644
--- a/ui/strings/ui_strings.grd
+++ b/ui/strings/ui_strings.grd
@@ -734,6 +734,9 @@
       <message name="IDS_APP_LIST_PAGE_SWITCHER" desc="Tooltip for page switcher for each page in fullscreen view which shows all apps.">
         Page <ph name="selected_page">$1<ex>1</ex></ph> of <ph name="total_page_num">$2<ex>3</ex></ph>
       </message>
+      <message name="IDS_APP_ACCESSIBILITY_STAR_RATING_ARC" desc="Accessibility text for the start rating of a Play Store app.">
+        Star rating <ph name="RATING_SCORE">$1<ex>5.0</ex></ph>
+      </message>
 
       <!-- Strings describing the touch calibration UX -->
       <message name="IDS_DISPLAY_TOUCH_CALIBRATION_EXIT_LABEL" desc="A message to notify the user about using the escape key to exit the calibration mode.">
diff --git a/ui/views/accessibility/native_view_accessibility_auralinux.cc b/ui/views/accessibility/native_view_accessibility_auralinux.cc
index 84a9ed9c..be5c908 100644
--- a/ui/views/accessibility/native_view_accessibility_auralinux.cc
+++ b/ui/views/accessibility/native_view_accessibility_auralinux.cc
@@ -106,6 +106,11 @@
     return nullptr;
   }
 
+  bool IsOffscreen() const override {
+    // TODO: need to implement.
+    return false;
+  }
+
   int GetIndexInParent() const override { return -1; }
 
   ui::AXPlatformNode* GetFromNodeID(int32_t id) override { return nullptr; }
diff --git a/ui/views/accessibility/native_view_accessibility_base.cc b/ui/views/accessibility/native_view_accessibility_base.cc
index 88446e8..f56b6dd 100644
--- a/ui/views/accessibility/native_view_accessibility_base.cc
+++ b/ui/views/accessibility/native_view_accessibility_base.cc
@@ -221,6 +221,11 @@
   return false;
 }
 
+bool NativeViewAccessibilityBase::IsOffscreen() const {
+  // TODO: need to implement.
+  return false;
+}
+
 void NativeViewAccessibilityBase::OnWidgetDestroying(Widget* widget) {
   if (parent_widget_ == widget) {
     parent_widget_->RemoveObserver(this);
diff --git a/ui/views/accessibility/native_view_accessibility_base.h b/ui/views/accessibility/native_view_accessibility_base.h
index 1846352..1d9f9bb 100644
--- a/ui/views/accessibility/native_view_accessibility_base.h
+++ b/ui/views/accessibility/native_view_accessibility_base.h
@@ -52,6 +52,7 @@
   gfx::AcceleratedWidget GetTargetForNativeAccessibilityEvent() override;
   bool AccessibilityPerformAction(const ui::AXActionData& data) override;
   bool ShouldIgnoreHoveredStateForTesting() override;
+  bool IsOffscreen() const override;
 
   // WidgetObserver
   void OnWidgetDestroying(Widget* widget) override;
diff --git a/ui/views/controls/link.cc b/ui/views/controls/link.cc
index 3d4257b2..1cc2e1fa 100644
--- a/ui/views/controls/link.cc
+++ b/ui/views/controls/link.cc
@@ -27,10 +27,8 @@
 const char Link::kViewClassName[] = "Link";
 constexpr int Link::kFocusBorderPadding;
 
-Link::Link() : Link(base::string16()) {}
-
-Link::Link(const base::string16& title)
-    : Label(title),
+Link::Link(const base::string16& title, int text_context, int text_style)
+    : Label(title, text_context, text_style),
       requested_enabled_color_(gfx::kPlaceholderColor),
       requested_enabled_color_set_(false) {
   Init();
@@ -268,6 +266,7 @@
 }
 
 SkColor Link::GetColor() {
+  // TODO(tapted): Use style::GetColor().
   const ui::NativeTheme* theme = GetNativeTheme();
   DCHECK(theme);
   if (!enabled())
diff --git a/ui/views/controls/link.h b/ui/views/controls/link.h
index 70bab2b..27c73ed 100644
--- a/ui/views/controls/link.h
+++ b/ui/views/controls/link.h
@@ -10,6 +10,7 @@
 #include "base/macros.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/views/controls/label.h"
+#include "ui/views/style/typography.h"
 
 namespace views {
 
@@ -37,8 +38,9 @@
     RING,       // A focus ring is drawn around the View.
   };
 
-  Link();
-  explicit Link(const base::string16& title);
+  explicit Link(const base::string16& title,
+                int text_context = style::CONTEXT_LABEL,
+                int text_style = style::STYLE_LINK);
   ~Link() override;
 
   // Returns the default FocusStyle for a views::Link. Calling SetUnderline()
diff --git a/ui/views/controls/menu/menu_item_view.cc b/ui/views/controls/menu/menu_item_view.cc
index fcf1e9a..d90a8ec 100644
--- a/ui/views/controls/menu/menu_item_view.cc
+++ b/ui/views/controls/menu/menu_item_view.cc
@@ -696,6 +696,7 @@
         type_ == RADIO ||
         (type_ == CHECKBOX && GetDelegate()->IsItemChecked(GetCommand()));
     radio_check_image_view_->SetVisible(show_check_radio_icon);
+    radio_check_image_view_->set_can_process_events_within_subtree(false);
     AddChildView(radio_check_image_view_);
   }
 
diff --git a/ui/views/controls/message_box_view.cc b/ui/views/controls/message_box_view.cc
index 5df957a..a5236e5 100644
--- a/ui/views/controls/message_box_view.cc
+++ b/ui/views/controls/message_box_view.cc
@@ -124,10 +124,11 @@
   } else {
     DCHECK(listener);
     if (!link_) {
-      link_ = new Link();
+      link_ = new Link(text);
       link_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+    } else {
+      link_->SetText(text);
     }
-    link_->SetText(text);
     link_->set_listener(listener);
   }
   ResetLayoutManager();
diff --git a/ui/views/controls/styled_label.cc b/ui/views/controls/styled_label.cc
index 6750ce0..ac3158e 100644
--- a/ui/views/controls/styled_label.cc
+++ b/ui/views/controls/styled_label.cc
@@ -30,52 +30,37 @@
   return label.GetInsets();
 }
 
-// Calculates the height of a line of text. Currently returns the height of
-// a label.
-int CalculateLineHeight(const gfx::FontList& font_list) {
-  Label label;
-  label.SetFontList(font_list);
-  return label.GetPreferredSize().height();
-}
-
 std::unique_ptr<Label> CreateLabelRange(
     const base::string16& text,
-    const gfx::FontList& font_list,
+    int text_context,
+    int default_style,
     const StyledLabel::RangeStyleInfo& style_info,
     views::LinkListener* link_listener) {
   std::unique_ptr<Label> result;
 
-  if (style_info.is_link) {
-    Link* link = new Link(text);
+  if (style_info.IsLink()) {
+    // Nothing should (and nothing does) use a custom font for links.
+    DCHECK(!style_info.custom_font);
+
+    // Note this ignores |default_style|, in favor of style::STYLE_LINK.
+    Link* link = new Link(text, text_context);
     link->set_listener(link_listener);
 
-    // StyledLabel makes assumptions about how to inset the entire View based on
-    // the default focus style: If focus rings are not the default, nothing is
-    // inset. So an individual range can't deviate from that.
-    if (Link::GetDefaultFocusStyle() == Link::FocusStyle::UNDERLINE) {
-      // Nothing should (and nothing does) request underlines for links with MD.
-      DCHECK_EQ(0, style_info.font_style & gfx::Font::UNDERLINE);
-      link->SetUnderline(false);  // Override what Link::Init() does.
-    } else {
-      link->SetUnderline((style_info.font_style & gfx::Font::UNDERLINE) != 0);
-    }
+    // Links in a StyledLabel do not get underlines.
+    link->SetUnderline(false);
 
     result.reset(link);
+  } else if (style_info.custom_font) {
+    result.reset(new Label(text, {style_info.custom_font.value()}));
   } else {
-    result.reset(new Label(text));
+    result.reset(new Label(text, text_context,
+                           style_info.text_style.value_or(default_style)));
   }
-
-  if (style_info.color != SK_ColorTRANSPARENT)
-    result->SetEnabledColor(style_info.color);
-  result->SetFontList(font_list);
+  if (style_info.override_color != SK_ColorTRANSPARENT)
+    result->SetEnabledColor(style_info.override_color);
 
   if (!style_info.tooltip.empty())
     result->SetTooltipText(style_info.tooltip);
-  if (style_info.font_style != gfx::Font::NORMAL ||
-      style_info.weight != gfx::Font::Weight::NORMAL) {
-    result->SetFontList(result->font_list().Derive(0, style_info.font_style,
-                                                   style_info.weight));
-  }
 
   return result;
 }
@@ -84,12 +69,9 @@
 
 // StyledLabel::RangeStyleInfo ------------------------------------------------
 
-StyledLabel::RangeStyleInfo::RangeStyleInfo()
-    : font_style(gfx::Font::NORMAL),
-      weight(gfx::Font::Weight::NORMAL),
-      color(SK_ColorTRANSPARENT),
-      disable_line_wrapping(false),
-      is_link(false) {}
+StyledLabel::RangeStyleInfo::RangeStyleInfo() = default;
+StyledLabel::RangeStyleInfo::RangeStyleInfo(const RangeStyleInfo& copy) =
+    default;
 
 StyledLabel::RangeStyleInfo::~RangeStyleInfo() {}
 
@@ -97,10 +79,13 @@
 StyledLabel::RangeStyleInfo StyledLabel::RangeStyleInfo::CreateForLink() {
   RangeStyleInfo result;
   result.disable_line_wrapping = true;
-  result.is_link = true;
+  result.text_style = style::STYLE_LINK;
   return result;
 }
 
+bool StyledLabel::RangeStyleInfo::IsLink() const {
+  return text_style && text_style.value() == style::STYLE_LINK;
+}
 
 // StyledLabel::StyleRange ----------------------------------------------------
 
@@ -117,8 +102,7 @@
 
 StyledLabel::StyledLabel(const base::string16& text,
                          StyledLabelListener* listener)
-    : font_list_(Label().font_list()),
-      specified_line_height_(0),
+    : specified_line_height_(0),
       listener_(listener),
       width_at_last_size_calculation_(0),
       width_at_last_layout_(0),
@@ -137,9 +121,8 @@
   PreferredSizeChanged();
 }
 
-void StyledLabel::SetBaseFontList(const gfx::FontList& font_list) {
-  font_list_ = font_list;
-  PreferredSizeChanged();
+gfx::FontList StyledLabel::GetDefaultFontList() const {
+  return style::GetFont(text_context_, default_text_style_);
 }
 
 void StyledLabel::AddStyleRange(const gfx::Range& range,
@@ -156,8 +139,19 @@
   PreferredSizeChanged();
 }
 
-void StyledLabel::SetDefaultStyle(const RangeStyleInfo& style_info) {
-  default_style_info_ = style_info;
+void StyledLabel::SetTextContext(int text_context) {
+  if (text_context_ == text_context)
+    return;
+
+  text_context_ = text_context;
+  PreferredSizeChanged();
+}
+
+void StyledLabel::SetDefaultTextStyle(int text_style) {
+  if (default_text_style_ == text_style)
+    return;
+
+  default_text_style_ = text_style;
   PreferredSizeChanged();
 }
 
@@ -201,7 +195,7 @@
   // That in turn will be true only if the link is non-empty.
   for (StyleRanges::const_iterator i(style_ranges_.begin());
         i != style_ranges_.end(); ++i) {
-    if (i->style_info.is_link && !i->range.is_empty()) {
+    if (i->style_info.IsLink() && !i->range.is_empty()) {
       insets += gfx::Insets(Link::kFocusBorderPadding);
       break;
     }
@@ -238,6 +232,26 @@
     listener_->StyledLabelLinkClicked(this, link_targets_[source], event_flags);
 }
 
+int StyledLabel::GetDefaultLineHeight() const {
+  return specified_line_height_ > 0
+             ? specified_line_height_
+             : std::max(
+                   style::GetLineHeight(text_context_, default_text_style_),
+                   GetDefaultFontList().GetHeight());
+}
+
+gfx::FontList StyledLabel::GetFontListForRange(
+    const StyleRanges::const_iterator& range) const {
+  if (range == style_ranges_.end())
+    return GetDefaultFontList();
+
+  return range->style_info.custom_font
+             ? range->style_info.custom_font.value()
+             : style::GetFont(
+                   text_context_,
+                   range->style_info.text_style.value_or(default_text_style_));
+}
+
 gfx::Size StyledLabel::CalculateAndDoLayout(int width, bool dry_run) {
   if (width == width_at_last_size_calculation_ &&
       (dry_run || width == width_at_last_layout_))
@@ -257,8 +271,8 @@
   if (width <= 0 || text_.empty())
     return gfx::Size();
 
-  const int line_height = specified_line_height_ > 0 ? specified_line_height_
-      : CalculateLineHeight(font_list_);
+  const int line_height = GetDefaultLineHeight();
+
   // The index of the line we're on.
   int line = 0;
   // The x position (in pixels) of the line we're on, relative to content
@@ -268,6 +282,9 @@
   // The width that was actually used. Guaranteed to be no larger than |width|.
   int used_width = 0;
 
+  RangeStyleInfo default_style;
+  default_style.text_style = default_text_style_;
+
   base::string16 remaining_string = text_;
   StyleRanges::const_iterator current_range = style_ranges_.begin();
 
@@ -298,15 +315,12 @@
 
     const gfx::Rect chunk_bounds(x, 0, width - x, 2 * line_height);
     std::vector<base::string16> substrings;
-    gfx::FontList text_font_list = font_list_;
     // If the start of the remaining text is inside a styled range, the font
     // style may differ from the base font. The font specified by the range
     // should be used when eliding text.
-    if (position >= range.start()) {
-      text_font_list =
-          text_font_list.Derive(0, current_range->style_info.font_style,
-                                current_range->style_info.weight);
-    }
+    gfx::FontList text_font_list = position >= range.start()
+                                       ? GetFontListForRange(current_range)
+                                       : GetDefaultFontList();
     gfx::ElideRectangleText(remaining_string,
                             text_font_list,
                             chunk_bounds.width(),
@@ -347,9 +361,10 @@
       if (chunk.size() > range.end() - position)
         chunk = chunk.substr(0, range.end() - position);
 
-      label = CreateLabelRange(chunk, font_list_, style_info, this);
+      label = CreateLabelRange(chunk, text_context_, default_text_style_,
+                               style_info, this);
 
-      if (style_info.is_link && !dry_run)
+      if (style_info.IsLink() && !dry_run)
         link_targets_[label.get()] = range;
 
       if (position + chunk.size() >= range.end())
@@ -358,7 +373,8 @@
       // This chunk is normal text.
       if (position + chunk.size() > range.start())
         chunk = chunk.substr(0, range.start() - position);
-      label = CreateLabelRange(chunk, font_list_, default_style_info_, this);
+      label = CreateLabelRange(chunk, text_context_, default_text_style_,
+                               default_style, this);
     }
 
     if (displayed_on_background_color_set_)
diff --git a/ui/views/controls/styled_label.h b/ui/views/controls/styled_label.h
index 2a36e8f1..5b25f40b 100644
--- a/ui/views/controls/styled_label.h
+++ b/ui/views/controls/styled_label.h
@@ -9,12 +9,14 @@
 #include <map>
 
 #include "base/macros.h"
+#include "base/optional.h"
 #include "base/strings/string16.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/font_list.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/range/range.h"
 #include "ui/views/controls/link_listener.h"
+#include "ui/views/style/typography.h"
 #include "ui/views/view.h"
 
 namespace views {
@@ -35,30 +37,31 @@
   // Parameters that define label style for a styled label's text range.
   struct VIEWS_EXPORT RangeStyleInfo {
     RangeStyleInfo();
+    RangeStyleInfo(const RangeStyleInfo& copy);
     ~RangeStyleInfo();
 
     // Creates a range style info with default values for link.
     static RangeStyleInfo CreateForLink();
 
-    // The font style that will be applied to the range. Should be a bitmask of
-    // values defined in gfx::Font::FontStyle (ITALIC, UNDERLINE).
-    int font_style;
+    bool IsLink() const;
 
-    // The font weight to be applied to the range. Default is Weight::NORMAL.
-    gfx::Font::Weight weight;
+    // Allows full customization of the font used in the range. Ignores the
+    // StyledLabel's default text context and |text_style|.
+    base::Optional<gfx::FontList> custom_font;
 
-    // The text color for the range. Default is SK_ColorTRANSPARENT, indicating
-    // the theme's default color should be used.
-    SkColor color;
+    // The style::TextStyle for this range.
+    base::Optional<int> text_style;
+
+    // Overrides the text color given by |text_style| for this range. Default is
+    // SK_ColorTRANSPARENT, indicating not to override.
+    // DEPRECATED: Use TextStyle.
+    SkColor override_color = SK_ColorTRANSPARENT;
 
     // Tooltip for the range.
     base::string16 tooltip;
 
     // If set, the whole range will be put on a single line.
-    bool disable_line_wrapping;
-
-    // If set, the range will be created as a link.
-    bool is_link;
+    bool disable_line_wrapping = false;
   };
 
   // Note that any trailing whitespace in |text| will be trimmed.
@@ -70,17 +73,21 @@
 
   const base::string16& text() const { return text_; }
 
-  // Sets the fonts used by all labels. Can be augemented by styling set by
-  // AddStyleRange and SetDefaultStyle.
-  void SetBaseFontList(const gfx::FontList& font_list);
+  // Returns the font list that results from the default text context and style
+  // for ranges. This can be used as the basis for a range |custom_font|.
+  gfx::FontList GetDefaultFontList() const;
 
   // Marks the given range within |text_| with style defined by |style_info|.
   // |range| must be contained in |text_|.
   void AddStyleRange(const gfx::Range& range, const RangeStyleInfo& style_info);
 
-  // Sets the default style to use for any part of the text that isn't within
-  // a range set by AddStyleRange.
-  void SetDefaultStyle(const RangeStyleInfo& style_info);
+  // Set the context of this text. All ranges have the same context.
+  // |text_context| must be a value from views::style::TextContext.
+  void SetTextContext(int text_context);
+
+  // Set the default text style.
+  // |text_style| must be a value from views::style::TextStyle.
+  void SetDefaultTextStyle(int text_style);
 
   // Get or set the distance in pixels between baselines of multi-line text.
   // Default is 0, indicating the distance between lines should be the standard
@@ -134,6 +141,13 @@
   };
   typedef std::list<StyleRange> StyleRanges;
 
+  // Returns the default line height, based on the default style.
+  int GetDefaultLineHeight() const;
+
+  // Returns the FontList that should be used for |range|.
+  gfx::FontList GetFontListForRange(
+      const StyleRanges::const_iterator& range) const;
+
   // Calculates how to layout child views, creates them and sets their size and
   // position. |width| is the horizontal space, in pixels, that the view has to
   // work with. If |dry_run| is true, the view hierarchy is not touched. Caches
@@ -144,16 +158,12 @@
   // The text to display.
   base::string16 text_;
 
-  // Fonts used to display text. Can be augmented by RangeStyleInfo.
-  gfx::FontList font_list_;
+  int text_context_ = style::CONTEXT_LABEL;
+  int default_text_style_ = style::STYLE_PRIMARY;
 
-  // Line height.
+  // Line height. If zero, style::GetLineHeight() is used.
   int specified_line_height_;
 
-  // The default style to use for any part of the text that isn't within
-  // a range in |style_ranges_|.
-  RangeStyleInfo default_style_info_;
-
   // The listener that will be informed of link clicks.
   StyledLabelListener* listener_;
 
diff --git a/ui/views/controls/styled_label_unittest.cc b/ui/views/controls/styled_label_unittest.cc
index 6902609..101339e 100644
--- a/ui/views/controls/styled_label_unittest.cc
+++ b/ui/views/controls/styled_label_unittest.cc
@@ -18,6 +18,8 @@
 #include "ui/views/border.h"
 #include "ui/views/controls/link.h"
 #include "ui/views/controls/styled_label_listener.h"
+#include "ui/views/style/typography.h"
+#include "ui/views/test/test_layout_provider.h"
 #include "ui/views/test/views_test_base.h"
 #include "ui/views/widget/widget.h"
 
@@ -328,18 +330,14 @@
   EXPECT_EQ(0, styled()->child_at(1)->x());
 }
 
-// TODO(mboc): Linux has never supported UNDERLINE, only virtually. Fix this.
-#if defined(OS_LINUX)
-#define MAYBE_StyledRangeUnderlined DISABLED_StyledRangeUnderlined
-#else
-#define MAYBE_StyledRangeUnderlined StyledRangeUnderlined
-#endif
-TEST_F(StyledLabelTest, MAYBE_StyledRangeUnderlined) {
+TEST_F(StyledLabelTest, StyledRangeCustomFontUnderlined) {
   const std::string text("This is a test block of text, ");
   const std::string underlined_text("and this should be undelined");
   InitStyledLabel(text + underlined_text);
   StyledLabel::RangeStyleInfo style_info;
-  style_info.font_style = gfx::Font::UNDERLINE;
+  style_info.tooltip = ASCIIToUTF16("tooltip");
+  style_info.custom_font =
+      styled()->GetDefaultFontList().DeriveWithStyle(gfx::Font::UNDERLINE);
   styled()->AddStyleRange(
       gfx::Range(static_cast<uint32_t>(text.size()),
                  static_cast<uint32_t>(text.size() + underlined_text.size())),
@@ -356,14 +354,20 @@
       static_cast<Label*>(styled()->child_at(1))->font_list().GetFontStyle());
 }
 
-TEST_F(StyledLabelTest, StyledRangeBold) {
+TEST_F(StyledLabelTest, StyledRangeTextStyleBold) {
+  test::TestLayoutProvider bold_provider;
   const std::string bold_text(
       "This is a block of text whose style will be set to BOLD in the test");
   const std::string text(" normal text");
   InitStyledLabel(bold_text + text);
 
+  // Pretend disabled text becomes bold for testing.
+  bold_provider.SetFont(
+      style::CONTEXT_LABEL, style::STYLE_DISABLED,
+      styled()->GetDefaultFontList().DeriveWithWeight(gfx::Font::Weight::BOLD));
+
   StyledLabel::RangeStyleInfo style_info;
-  style_info.weight = gfx::Font::Weight::BOLD;
+  style_info.text_style = style::STYLE_DISABLED;
   styled()->AddStyleRange(
       gfx::Range(0u, static_cast<uint32_t>(bold_text.size())), style_info);
 
@@ -425,7 +429,7 @@
   InitStyledLabel(text_red + text_link + text);
 
   StyledLabel::RangeStyleInfo style_info_red;
-  style_info_red.color = SK_ColorRED;
+  style_info_red.override_color = SK_ColorRED;
   styled()->AddStyleRange(
       gfx::Range(0u, static_cast<uint32_t>(text_red.size())), style_info_red);
 
@@ -540,22 +544,30 @@
   EXPECT_EQ(ASCIIToUTF16("tooltip"), tooltip);
 }
 
-TEST_F(StyledLabelTest, SetBaseFontList) {
+TEST_F(StyledLabelTest, SetTextContextAndDefaultStyle) {
   const std::string text("This is a test block of text.");
   InitStyledLabel(text);
-  std::string font_name("arial");
-  gfx::Font font(font_name, 30);
-  styled()->SetBaseFontList(gfx::FontList(font));
-  Label label(ASCIIToUTF16(text), Label::CustomFont{gfx::FontList(font)});
+  styled()->SetTextContext(style::CONTEXT_DIALOG_TITLE);
+  styled()->SetDefaultTextStyle(style::STYLE_DISABLED);
+  Label label(ASCIIToUTF16(text), style::CONTEXT_DIALOG_TITLE,
+              style::STYLE_DISABLED);
 
   styled()->SetBounds(0,
                       0,
                       label.GetPreferredSize().width(),
                       label.GetPreferredSize().height());
 
-  // Make sure we have the same sizing as a label.
+  // Make sure we have the same sizing as a label with the same style.
   EXPECT_EQ(label.GetPreferredSize().height(), styled()->height());
   EXPECT_EQ(label.GetPreferredSize().width(), styled()->width());
+
+  styled()->Layout();
+  ASSERT_EQ(1, styled()->child_count());
+  Label* sublabel = static_cast<Label*>(styled()->child_at(0));
+  EXPECT_EQ(style::CONTEXT_DIALOG_TITLE, sublabel->text_context());
+
+  EXPECT_NE(SK_ColorBLACK, label.enabled_color());  // Sanity check,
+  EXPECT_EQ(label.enabled_color(), sublabel->enabled_color());
 }
 
 TEST_F(StyledLabelTest, LineHeight) {
diff --git a/ui/views/controls/tabbed_pane/tabbed_pane.cc b/ui/views/controls/tabbed_pane/tabbed_pane.cc
index a1df00b..893c33a 100644
--- a/ui/views/controls/tabbed_pane/tabbed_pane.cc
+++ b/ui/views/controls/tabbed_pane/tabbed_pane.cc
@@ -415,9 +415,10 @@
   DCHECK(!from_tab->selected());
   DCHECK(to_tab->selected());
 
-  animating_from_ =
-      gfx::Range(from_tab->x(), from_tab->x() + from_tab->width());
-  animating_to_ = gfx::Range(to_tab->x(), to_tab->x() + to_tab->width());
+  animating_from_ = gfx::Range(from_tab->GetMirroredX(),
+                               from_tab->GetMirroredX() + from_tab->width());
+  animating_to_ = gfx::Range(to_tab->GetMirroredX(),
+                             to_tab->GetMirroredX() + to_tab->width());
 
   contract_animation_->Stop();
   expand_animation_->Start();
@@ -478,8 +479,8 @@
       max_x = animating_to_.end();
     }
   } else if (tab) {
-    min_x = tab->x();
-    max_x = tab->x() + tab->width();
+    min_x = tab->GetMirroredX();
+    max_x = tab->GetMirroredX() + tab->width();
   }
 
   DCHECK(min_x != max_x);
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc
index 35a41b6..76180297 100644
--- a/ui/views/controls/textfield/textfield.cc
+++ b/ui/views/controls/textfield/textfield.cc
@@ -567,6 +567,11 @@
   accessible_name_ = name;
 }
 
+void Textfield::SetPasswordReplacementChar(
+    base::char16 password_replacement_char) {
+  GetRenderText()->SetPasswordReplacementChar(password_replacement_char);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Textfield, View overrides:
 
@@ -933,7 +938,7 @@
   if (text_input_type_ == ui::TEXT_INPUT_TYPE_PASSWORD) {
     node_data->AddState(ui::AX_STATE_PROTECTED);
     node_data->SetValue(base::string16(
-        text().size(), gfx::RenderText::kPasswordReplacementChar));
+        text().size(), GetRenderText()->password_replacement_char()));
   } else {
     node_data->SetValue(text());
   }
diff --git a/ui/views/controls/textfield/textfield.h b/ui/views/controls/textfield/textfield.h
index eacbe31..dae9ed58 100644
--- a/ui/views/controls/textfield/textfield.h
+++ b/ui/views/controls/textfield/textfield.h
@@ -210,6 +210,9 @@
   // Set the accessible name of the text field.
   void SetAccessibleName(const base::string16& name);
 
+  // Sets a password replacement char to override the default value.
+  void SetPasswordReplacementChar(base::char16 password_replacement_char);
+
   // View overrides:
   int GetBaseline() const override;
   gfx::Size CalculatePreferredSize() const override;
diff --git a/ui/views/controls/webview/webview.cc b/ui/views/controls/webview/webview.cc
index f4e06dc..4b34ac01 100644
--- a/ui/views/controls/webview/webview.cc
+++ b/ui/views/controls/webview/webview.cc
@@ -4,12 +4,14 @@
 
 #include "ui/views/controls/webview/webview.h"
 
+#include <string>
 #include <utility>
 
 #include "build/build_config.h"
 #include "content/public/browser/browser_accessibility_state.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host_view.h"
@@ -62,8 +64,9 @@
     observing_render_process_host_->RemoveObserver(this);
     observing_render_process_host_ = nullptr;
   }
-  if (web_contents() && web_contents()->GetRenderProcessHost()) {
-    observing_render_process_host_ = web_contents()->GetRenderProcessHost();
+  if (web_contents() && web_contents()->GetMainFrame()->GetProcess()) {
+    observing_render_process_host_ =
+        web_contents()->GetMainFrame()->GetProcess();
     observing_render_process_host_->AddObserver(this);
   }
   // web_contents() now returns |replacement| from here onwards.
diff --git a/ui/views/test/test_layout_provider.cc b/ui/views/test/test_layout_provider.cc
index a2f3fda..14dc6ce 100644
--- a/ui/views/test/test_layout_provider.cc
+++ b/ui/views/test/test_layout_provider.cc
@@ -4,6 +4,8 @@
 
 #include "ui/views/test/test_layout_provider.h"
 
+#include "ui/gfx/font_list.h"
+
 namespace views {
 namespace test {
 
@@ -13,19 +15,37 @@
 void TestLayoutProvider::SetDistanceMetric(int metric, int value) {
   distance_metrics_[metric] = value;
 }
+
 void TestLayoutProvider::SetSnappedDialogWidth(int width) {
   snapped_dialog_width_ = width;
 }
 
+void TestLayoutProvider::SetFont(int context,
+                                 int style,
+                                 const gfx::FontList& font) {
+  fonts_[{context, style}] = font;
+}
+
 int TestLayoutProvider::GetDistanceMetric(int metric) const {
   if (distance_metrics_.count(metric))
     return distance_metrics_.find(metric)->second;
   return LayoutProvider::GetDistanceMetric(metric);
 }
 
+const TypographyProvider& TestLayoutProvider::GetTypographyProvider() const {
+  return *this;
+}
+
 int TestLayoutProvider::GetSnappedDialogWidth(int min_width) const {
   return snapped_dialog_width_ ? snapped_dialog_width_ : min_width;
 }
 
+const gfx::FontList& TestLayoutProvider::GetFont(int context, int style) const {
+  auto it = fonts_.find({context, style});
+  return it != fonts_.end()
+             ? it->second
+             : DefaultTypographyProvider::GetFont(context, style);
+}
+
 }  // namespace test
 }  // namespace views
diff --git a/ui/views/test/test_layout_provider.h b/ui/views/test/test_layout_provider.h
index ede0b65c..b0fa7e5 100644
--- a/ui/views/test/test_layout_provider.h
+++ b/ui/views/test/test_layout_provider.h
@@ -9,12 +9,18 @@
 
 #include "base/macros.h"
 #include "ui/views/layout/layout_provider.h"
+#include "ui/views/style/typography_provider.h"
+
+namespace gfx {
+class FontList;
+}
 
 namespace views {
 namespace test {
 
 // Helper to test LayoutProvider overrides.
-class TestLayoutProvider : public LayoutProvider {
+class TestLayoutProvider : public LayoutProvider,
+                           public DefaultTypographyProvider {
  public:
   TestLayoutProvider();
   ~TestLayoutProvider() override;
@@ -26,12 +32,20 @@
   // Override the return value of GetSnappedDialogWidth().
   void SetSnappedDialogWidth(int width);
 
+  // Override the font provided by style::GetFont().
+  void SetFont(int context, int style, const gfx::FontList& font);
+
   // LayoutProvider:
   int GetDistanceMetric(int metric) const override;
+  const TypographyProvider& GetTypographyProvider() const override;
   int GetSnappedDialogWidth(int min_width) const override;
 
+  // TypographyProvider:
+  const gfx::FontList& GetFont(int context, int style) const override;
+
  private:
   std::map<int, int> distance_metrics_;
+  std::map<std::pair<int, int>, gfx::FontList> fonts_;
   int snapped_dialog_width_ = 0;
 
   DISALLOW_COPY_AND_ASSIGN(TestLayoutProvider);
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/camera_flip_icon.svg b/ui/webui/resources/cr_elements/chromeos/cr_picture/camera_flip_icon.svg
deleted file mode 100644
index b95e714b..0000000
--- a/ui/webui/resources/cr_elements/chromeos/cr_picture/camera_flip_icon.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FFFFFF" preserveAspectRatio="xMidYMid meet"><path d="M15 21h2v-2h-2v2zm4-12h2V7h-2v2zM3 5v14c0 1.1.9 2 2 2h4v-2H5V5h4V3H5c-1.1 0-2 .9-2 2zm16-2v2h2c0-1.1-.9-2-2-2zm-8 20h2V1h-2v22zm8-6h2v-2h-2v2zM15 5h2V3h-2v2zm4 8h2v-2h-2v2zm0 8c1.1 0 2-.9 2-2h-2v2z"></path></svg>
\ No newline at end of file
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/camera_shutter_icon.svg b/ui/webui/resources/cr_elements/chromeos/cr_picture/camera_shutter_icon.svg
new file mode 100644
index 0000000..9199e96a
--- /dev/null
+++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/camera_shutter_icon.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#EDEDED" stroke="#FFFFFF" preserveAspectRatio="xMidYMid meet"><circle cx="12" cy="12" r="10" stroke-width="2"></circle></svg>
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/compiled_resources2.gyp b/ui/webui/resources/cr_elements/chromeos/cr_picture/compiled_resources2.gyp
index ca23e91..e609ba6 100644
--- a/ui/webui/resources/cr_elements/chromeos/cr_picture/compiled_resources2.gyp
+++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/compiled_resources2.gyp
@@ -4,6 +4,7 @@
 {
   'targets': [
     {
+      'dependencies': [ 'cr_png_behavior' ],
       'target_name': 'cr_camera',
       'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
@@ -11,6 +12,7 @@
       'dependencies': [
         '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-selector/compiled_resources2.gyp:iron-selector-extracted',
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+        'cr_png_behavior',
         'cr_picture_types',
       ],
       'target_name': 'cr_picture_list',
@@ -28,5 +30,9 @@
       'target_name': 'cr_picture_types',
       'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
+    {
+      'target_name': 'cr_png_behavior',
+      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+    },
   ],
 }
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.html b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.html
index d62cd3c..404b5d7 100644
--- a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.html
+++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.html
@@ -3,6 +3,7 @@
 <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner.html">
+<link rel="import" href="cr_png_behavior.html">
 
 <dom-module id="cr-camera">
   <template>
@@ -22,23 +23,36 @@
         height: 100%;
         overflow: hidden;
         position: relative;
-        width: 100%;
-      }
-
-      #userImageStreamCrop.flip-x {
         transform: rotateY(180deg);
+        width: 100%;
       }
 
       #userImageStreamCrop::after {
         -webkit-mask-image: radial-gradient(transparent 140px, black 140px);
-        background-color: rgba(214, 214, 214, 0.34);
+        background-color: rgb(214, 214, 214);
         content: '';
         display: block;
         height: 100%;
+        opacity: 0.34;
         transform: translateZ(0);
         width: 100%;
       }
 
+      @-webkit-keyframes pulse {
+        0% { opacity: 0; }
+        50% { opacity: 1; }
+        100% { opacity: 0; }
+      }
+
+      #userImageStreamCrop.capture::after {
+        -webkit-mask-image: none;
+        animation: pulse linear 100ms normal forwards;
+      }
+
+      :host([videomode]) #userImageStreamCrop.capture::after {
+        animation: pulse linear 50ms 20;
+      }
+
       paper-spinner {
         bottom: 0;
         left: 0;
@@ -79,16 +93,24 @@
         display: block;
       }
 
-      #flipPhoto {
-        -webkit-margin-end: 8px;
-        background-image: url(camera_flip_icon.svg);
+      #takePhoto {
+        background-image: url(camera_shutter_icon.svg);
       }
 
-      :host-context([dir=rtl]) #flipPhoto {
+      :host([videomode]) #takePhoto {
+        background-image: url(videocam_shutter_icon.svg);
+      }
+
+      :host-context([dir=rtl]) #switchMode {
         float: left;
       }
 
-      #takePhoto {
+      #switchMode {
+        -webkit-margin-end: 8px;
+        background-image: url(videocam_icon.svg);
+      }
+
+      :host([videomode]) #switchMode {
         background-image: url(camera_alt_icon.svg);
       }
     </style>
@@ -109,8 +131,8 @@
         </button>
       </div>
       <div>
-        <button is="paper-icon-button-light" id="flipPhoto" tabindex="2"
-            title="[[flipPhotoLabel]]" on-tap="onTapFlipPhoto_"
+        <button is="paper-icon-button-light" id="switchMode" tabindex="2"
+            title="[[switchModeLabel]]" on-tap="onTapSwitchMode_"
             disabled="[[!cameraOnline_]]">
         </button>
       </div>
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.js b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.js
index 0f6bfcf..ff3228b 100644
--- a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.js
+++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.js
@@ -13,15 +13,39 @@
  * Dimensions for camera capture.
  * @const
  */
-var CAPTURE_SIZE = {height: 576, width: 576};
+var CAPTURE_SIZE = {width: 576, height: 576};
+
+/**
+ * Interval between frames for camera capture (milliseconds).
+ * @const
+ */
+var CAPTURE_INTERVAL_MS = 1000 / 10;
+
+/**
+ * Duration of camera capture (milliseconds).
+ * @const
+ */
+var CAPTURE_DURATION_MS = 1000;
 
 Polymer({
   is: 'cr-camera',
 
+  behaviors: [CrPngBehavior],
+
   properties: {
     /** Strings provided by host */
-    flipPhotoLabel: String,
     takePhotoLabel: String,
+    switchModeLabel: String,
+
+    /**
+     * True if currently in video mode.
+     * @private {boolean}
+     */
+    videomode: {
+      type: Boolean,
+      value: false,
+      reflectToAttribute: true,
+    },
 
     /**
      * True when the camera is actually streaming video. May be false even when
@@ -32,20 +56,10 @@
       type: Boolean,
       value: false,
     },
-
-    /**
-     * True if the photo is currently marked flipped.
-     * @private {boolean}
-     */
-    isFlipped_: {
-      type: Boolean,
-      value: true,
-    },
   },
 
   /** @override */
   attached: function() {
-    this.$.userImageStreamCrop.classList.toggle('flip-x', this.isFlipped_);
     this.$.cameraVideo.addEventListener('canplay', function() {
       this.cameraOnline_ = true;
     }.bind(this));
@@ -65,17 +79,37 @@
   takePhoto: function() {
     if (!this.cameraOnline_)
       return;
-    var canvas =
-        /** @type {HTMLCanvasElement} */ (document.createElement('canvas'));
-    canvas.width = CAPTURE_SIZE.width;
-    canvas.height = CAPTURE_SIZE.height;
-    this.captureFrame_(
-        this.$.cameraVideo,
-        /** @type {!CanvasRenderingContext2D} */ (canvas.getContext('2d')));
 
-    var photoDataUrl = this.isFlipped_ ? this.flipFrame_(canvas) :
-                                         canvas.toDataURL('image/png');
-    this.fire('photo-taken', {photoDataUrl: photoDataUrl});
+    /** Pre-allocate all frames needed for capture. */
+    var frames = [];
+    if (this.videomode) {
+      /** Reduce capture size when in video mode. */
+      var captureSize = {
+        width: CAPTURE_SIZE.width / 2,
+        height: CAPTURE_SIZE.height / 2
+      };
+      var captureFrameCount = CAPTURE_DURATION_MS / CAPTURE_INTERVAL_MS;
+      while (frames.length < captureFrameCount)
+        frames.push(this.allocateFrame_(captureSize));
+    } else {
+      frames.push(this.allocateFrame_(CAPTURE_SIZE));
+    }
+
+    /** Start capturing frames at an interval. */
+    var capturedFrames = [];
+    this.$.userImageStreamCrop.classList.add('capture');
+    var interval = setInterval(() => {
+      capturedFrames.push(this.captureFrame_(this.$.cameraVideo, frames.pop()));
+
+      /** Stop capturing frames when all allocated frames have been consumed. */
+      if (!frames.length) {
+        this.$.userImageStreamCrop.classList.remove('capture');
+        clearInterval(interval);
+        this.fire(
+            'photo-taken',
+            {photoDataUrl: this.convertFramesToPng_(capturedFrames)});
+      }
+    }, CAPTURE_INTERVAL_MS);
   },
 
   /** Tries to start the camera stream capture. */
@@ -123,61 +157,92 @@
   },
 
   /**
-   * Flip the live camera stream.
+   * Switch between photo and video mode.
    * @private
    */
-  onTapFlipPhoto_: function() {
-    this.isFlipped_ = !this.isFlipped_;
-    this.$.userImageStreamCrop.classList.toggle('flip-x', this.isFlipped_);
-    this.fire('photo-flipped', this.isFlipped_);
+  onTapSwitchMode_: function() {
+    this.videomode = !this.videomode;
+    this.fire('switch-mode', this.videomode);
+  },
+
+  /**
+   * Allocates a canvas for capturing a single still frame at a specific size.
+   * @param {{width: number, height: number}} size Frame size.
+   * @return {!HTMLCanvasElement} The allocated canvas.
+   * @private
+   */
+  allocateFrame_: function(size) {
+    var canvas =
+        /** @type {!HTMLCanvasElement} */ (document.createElement('canvas'));
+    canvas.width = size.width;
+    canvas.height = size.height;
+    var ctx = /** @type {!CanvasRenderingContext2D} */ (
+        canvas.getContext('2d', {alpha: false}));
+    // Flip frame horizontally.
+    ctx.translate(size.width, 0);
+    ctx.scale(-1.0, 1.0);
+    return canvas;
   },
 
   /**
    * Captures a single still frame from a <video> element, placing it at the
    * current drawing origin of a canvas context.
    * @param {!HTMLVideoElement} video Video element to capture from.
-   * @param {!CanvasRenderingContext2D} ctx Canvas context to draw onto.
+   * @param {!HTMLCanvasElement} canvas Canvas to save frame in.
+   * @return {!HTMLCanvasElement} The canvas frame was saved in.
    * @private
    */
-  captureFrame_: function(video, ctx) {
+  captureFrame_: function(video, canvas) {
+    var ctx =
+        /** @type {!CanvasRenderingContext2D} */ (
+            canvas.getContext('2d', {alpha: false}));
     var width = video.videoWidth;
     var height = video.videoHeight;
-    if (width < CAPTURE_SIZE.width || height < CAPTURE_SIZE.height) {
+    if (width < canvas.width || height < canvas.height) {
       console.error(
           'Video capture size too small: ' + width + 'x' + height + '!');
     }
     var src = {};
-    if (width / CAPTURE_SIZE.width > height / CAPTURE_SIZE.height) {
+    if (width / canvas.width > height / canvas.height) {
       // Full height, crop left/right.
       src.height = height;
-      src.width = height * CAPTURE_SIZE.width / CAPTURE_SIZE.height;
+      src.width = height * canvas.width / canvas.height;
     } else {
       // Full width, crop top/bottom.
       src.width = width;
-      src.height = width * CAPTURE_SIZE.height / CAPTURE_SIZE.width;
+      src.height = width * canvas.height / canvas.width;
     }
     src.x = (width - src.width) / 2;
     src.y = (height - src.height) / 2;
     ctx.drawImage(
-        video, src.x, src.y, src.width, src.height, 0, 0, CAPTURE_SIZE.width,
-        CAPTURE_SIZE.height);
+        video, src.x, src.y, src.width, src.height, 0, 0, canvas.width,
+        canvas.height);
+    return canvas;
   },
 
   /**
-   * Flips frame horizontally.
-   * @param {!(HTMLImageElement|HTMLCanvasElement|HTMLVideoElement)} source
-   *     Frame to flip.
-   * @return {string} Flipped frame as data URL.
+   * Encode frames and convert to animated PNG image.
+   * @param {!Array<!HTMLCanvasElement>} frames The frames to convert to image.
+   * @return {!string} The data URL for image.
+   * @private
    */
-  flipFrame_: function(source) {
-    var canvas = document.createElement('canvas');
-    canvas.width = CAPTURE_SIZE.width;
-    canvas.height = CAPTURE_SIZE.height;
-    var ctx = canvas.getContext('2d');
-    ctx.translate(CAPTURE_SIZE.width, 0);
-    ctx.scale(-1.0, 1.0);
-    ctx.drawImage(source, 0, 0);
-    return canvas.toDataURL('image/png');
+  convertFramesToPng_: function(frames) {
+    /** Encode captured frames. */
+    var encodedImages = frames.map(function(frame) {
+      return frame.toDataURL('image/png');
+    });
+
+    /** No need for further processing if single frame. */
+    if (encodedImages.length == 1)
+      return encodedImages[0];
+
+    /** Create forward/backward image sequence. */
+    var forwardBackwardImageSequence =
+        encodedImages.concat(encodedImages.slice(1, -1).reverse());
+
+    /** Convert image sequence to animated PNG. */
+    return CrPngBehavior.convertImageSequenceToPng(
+        forwardBackwardImageSequence);
   },
 });
 
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.html b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.html
index abc2e47a..2c8eb21 100644
--- a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.html
+++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.html
@@ -6,6 +6,7 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-selector/iron-selector.html">
 <link rel="import" href="cr_picture_types.html">
+<link rel="import" href="cr_png_behavior.html">
 
 <dom-module id="cr-picture-list">
   <template>
@@ -86,7 +87,7 @@
             data-type$="[[selectionTypesEnum_.OLD]]"
             data-image-index$="[[oldImageIndex_]]"
             data-url$="[[oldImageUrl_]]"
-            src="[[oldImageUrl_]]" hidden="[[!oldImageUrl_]]"
+            src="[[getImgSrc_(oldImageUrl_)]]" hidden="[[!oldImageUrl_]]"
             title="[[oldImageLabel]]">
         <!-- Shows the list of available images to select from. -->
         <template is="dom-repeat" items="[[defaultImages]]">
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.js b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.js
index 990aaf67..285e937 100644
--- a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.js
+++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.js
@@ -12,6 +12,8 @@
 Polymer({
   is: 'cr-picture-list',
 
+  behaviors: [CrPngBehavior],
+
   properties: {
     cameraPresent: Boolean,
 
@@ -29,6 +31,7 @@
     oldImageLabel: String,
     profileImageLabel: String,
     takePhotoLabel: String,
+    switchModeLabel: String,
 
     /**
      * The currently selected item. This property is bound to the iron-selector
@@ -264,6 +267,13 @@
     if (url.startsWith('chrome://theme'))
       return url + '[0]';
 
+    /**
+     * Extract first frame from image by creating a single frame PNG using
+     * url as input if base64 encoded and potentially animated.
+     */
+    if (url.split(',')[0] == 'data:image/png;base64')
+      return CrPngBehavior.convertImageSequenceToPng([url]);
+
     return url;
   },
 
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.html b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.html
index d7fe749..7bad7c2e 100644
--- a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.html
+++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.html
@@ -75,8 +75,8 @@
     </template>
     <template is="dom-if" if="[[cameraActive_]]">
       <cr-camera id="camera"
-          flip-photo-label="[[flipPhotoLabel]]"
-          take-photo-label="[[takePhotoLabel]]">
+          take-photo-label="[[takePhotoLabel]]"
+          switch-mode-label="[[switchModeLabel]]">
       </cr-camera>
     </template>
   </template>
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.js b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.js
index 3ac41e1..7b71fe92f 100644
--- a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.js
+++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.js
@@ -29,9 +29,9 @@
 
     /** Strings provided by host */
     discardImageLabel: String,
-    flipPhotoLabel: String,
     previewAltText: String,
     takePhotoLabel: String,
+    switchModeLabel: String,
 
     /** Whether the camera should be shown and active (started). */
     cameraActive_: {
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_png_behavior.html b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_png_behavior.html
new file mode 100644
index 0000000..4d7582e
--- /dev/null
+++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_png_behavior.html
@@ -0,0 +1,2 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+<script src="cr_png_behavior.js"></script>
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_png_behavior.js b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_png_behavior.js
new file mode 100644
index 0000000..6298ccf8
--- /dev/null
+++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_png_behavior.js
@@ -0,0 +1,492 @@
+// 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
+ * 'CrPngBehavior' is a behavior to convert image sequences into animated
+ * PNG images.
+ */
+
+/**
+ * PNG frame delay fraction numerator.
+ * @const
+ */
+var PNG_FRAME_DELAY_NUMERATOR = 1;
+
+/**
+ * PNG frame delay fraction denominator.
+ * @const
+ */
+var PNG_FRAME_DELAY_DENOMINATOR = 20;
+
+/**
+ * PNG signature.
+ * @const
+ */
+var PNG_SIGNATURE = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A];
+
+/**
+ * PNG bit depth (8 = 32bpp).
+ * @const
+ */
+var PNG_BIT_DEPTH = 8;
+
+/**
+ * PNG compression method (0 = deflate/inflate compression with a sliding
+ * window PNG compression).
+ * @const
+ */
+var PNG_COMPRESSION_METHOD = 0;
+
+/**
+ * PNG filter method (0 = adaptive filtering with five basic filter types).
+ * @const
+ */
+var PNG_FILTER_METHOD = 0;
+
+/**
+ * PNG interlace method (0 = no interlace).
+ * @const
+ */
+var PNG_INTERLACE_METHOD = 0;
+
+/**
+ * CRC table for PNG encode.
+ *
+ * Generated using:
+ *
+ * for (var i = 0; i < 256; i++) {
+ *   var value = i;
+ *   for (var j = 0; j < 8; j++) {
+ *     if (value & 1)
+ *       value = ((0xEDB88320) ^ (value >>> 1));
+ *     else
+ *       value = (value >>> 1);
+ *   }
+ *   TABLE[i] = value;
+ * }
+ *
+ * @const
+ */
+var PNG_CRC_TABLE = [
+  0x0,        0x77073096, 0xEE0E612C, 0x990951BA, 0x76DC419,  0x706AF48F,
+  0xE963A535, 0x9E6495A3, 0xEDB8832,  0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+  0x9B64C2B,  0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
+  0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+  0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
+  0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+  0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
+  0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+  0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
+  0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+  0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x1DB7106,
+  0x98D220BC, 0xEFD5102A, 0x71B18589, 0x6B6B51F,  0x9FBFE4A5, 0xE8B8D433,
+  0x7807C9A2, 0xF00F934,  0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x86D3D2D,
+  0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
+  0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
+  0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+  0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
+  0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+  0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
+  0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+  0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
+  0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x3B6E20C,  0x74B1D29A,
+  0xEAD54739, 0x9DD277AF, 0x4DB2615,  0x73DC1683, 0xE3630B12, 0x94643B84,
+  0xD6D6A3E,  0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0xA00AE27,  0x7D079EB1,
+  0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
+  0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
+  0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
+  0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+  0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
+  0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+  0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
+  0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+  0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x26D930A,  0x9C0906A9, 0xEB0E363F,
+  0x72076785, 0x5005713,  0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0xCB61B38,
+  0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0xBDBDF21,  0x86D3D2D4, 0xF1D4E242,
+  0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+  0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
+  0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
+  0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
+  0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+  0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
+  0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+  0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+];
+
+/**
+ * PNG object state.
+ * @typedef {{
+ *   frames: number,
+ *   sequences: number,
+ *   width: number,
+ *   height: number,
+ *   colour: number,
+ *   chunks: !Array<Uint8Array>
+ * }}
+ */
+var CrPngState;
+
+/** @polymerBehavior */
+var CrPngBehavior = {
+  /**
+   * Returns a data URL for an animated PNG image that is created
+   * from a sequence of images.
+   * @param {!Array<string>} images The data URLs for each image.
+   * @return {string} A data URL for an animated PNG image.
+   */
+  convertImageSequenceToPng: function(images) {
+    var png =
+        /** @type {!CrPngState} */ ({frames: 0, sequences: 0, chunks: []});
+
+    /** Append signature. */
+    png.chunks.push(new Uint8Array(PNG_SIGNATURE));
+
+    /**
+     * http://www.w3.org/TR/2003/REC-PNG-20031110/#11IHDR
+     *
+     * Width               4 bytes
+     * Height              4 bytes
+     * Bit depth           1 byte
+     * Colour type         1 byte
+     * Compression method  1 byte
+     * Filter method       1 byte
+     * Interlace method    1 byte
+     */
+    var IHDR = new Uint8Array(12 + 13);
+    this.writeUInt32_(IHDR, 13, 0);
+    this.writeFourCC_(IHDR, 'IHDR', 4);
+    /** Write size at the end when known. */
+    this.writeUInt8_(IHDR, PNG_BIT_DEPTH, 16);
+    /** Write colour at the end when known. */
+    this.writeUInt8_(IHDR, PNG_COMPRESSION_METHOD, 18);
+    this.writeUInt8_(IHDR, PNG_FILTER_METHOD, 19);
+    this.writeUInt8_(IHDR, PNG_INTERLACE_METHOD, 20);
+    /** Write CRC at the end when size and colour is known. */
+    png.chunks.push(IHDR);
+
+    /**
+     * acTL
+     *
+     * Number of frames         4 bytes
+     * Number of times to loop  4 bytes
+     */
+    var acTL = new Uint8Array(12 + 8);
+    this.writeUInt32_(acTL, 8, 0);
+    this.writeFourCC_(acTL, 'acTL', 4);
+    this.writeUInt32_(acTL, images.length, 8);
+    this.writeUInt32_(acTL, 0, 12);
+    this.writeUInt32_(acTL, this.getCRC_(acTL, 4, 16), 16);
+    png.chunks.push(acTL);
+
+    /** Append each image as a PNG frame. */
+    for (var i = 0; i < images.length; ++i)
+      this.appendFrameFromDataURL_(images[i], png);
+
+    /** Update IHDR now that size and colour is known. */
+    this.writeUInt32_(IHDR, png.width, 8);
+    this.writeUInt32_(IHDR, png.height, 12);
+    this.writeUInt8_(IHDR, png.colour, 17);
+    this.writeUInt32_(IHDR, this.getCRC_(IHDR, 4, 8 + 13), 8 + 13);
+
+    /**
+     * http://www.w3.org/TR/2003/REC-PNG-20031110/#11IEND
+     */
+    var IEND = new Uint8Array(12);
+    this.writeUInt32_(IEND, 0, 0);
+    this.writeFourCC_(IEND, 'IEND', 4);
+    this.writeUInt32_(IEND, this.getCRC_(IEND, 4, 8), 8);
+    png.chunks.push(IEND);
+
+    return 'data:image/png;base64,' +
+        btoa(png.chunks
+                 .map(function(chunk) {
+                   return String.fromCharCode.apply(null, chunk);
+                 })
+                 .join(''));
+  },
+
+  /**
+   * Reads Uint32 from buffer.
+   * @param {!Uint8Array} buffer Buffer to read UInt32 from.
+   * @param {number} offset Offset in buffer to read UInt32 at.
+   * @return {number} The value read.
+   * @private
+   */
+  readUInt32_: function(buffer, offset) {
+    return (buffer[offset + 0] << 24) + (buffer[offset + 1] << 16) +
+        (buffer[offset + 2] << 8) + (buffer[offset + 3] << 0);
+  },
+
+  /**
+   * Reads string from buffer.
+   * @param {!Uint8Array} buffer Buffer to read string from.
+   * @param {number} offset Offset in buffer to read string at.
+   * @param {number} length Length of string to read.
+   * @return {string} The value read.
+   * @private
+   */
+  readString_: function(buffer, offset, length) {
+    var str = '';
+    for (var i = 0; i < length; i++) {
+      str += String.fromCharCode(buffer[offset + i]);
+    }
+    return str;
+  },
+
+  /**
+   * Write bytes to buffer.
+   * @param {!Uint8Array} buffer Buffer to write bytes to.
+   * @param {!Uint8Array} bytes Array of bytes to be written.
+   * @param {number} offset Offset in buffer to write bytes at.
+   * @private
+   */
+  writeBytes_: function(buffer, bytes, offset) {
+    for (var i = 0; i < bytes.length; i++) {
+      buffer[offset + i] = bytes[i] & 0xFF;
+    }
+  },
+
+  /**
+   * Write UInt8 to buffer.
+   * @param {!Uint8Array} buffer Buffer to write UInt8 to.
+   * @param {number} u8 UInt8 to be written.
+   * @param {number} offset Offset in buffer to write UInt8 at.
+   * @private
+   */
+  writeUInt8_: function(buffer, u8, offset) {
+    buffer[offset] = u8 & 0xFF;
+  },
+
+  /**
+   * Write UInt16 to buffer.
+   * @param {!Uint8Array} buffer Buffer to write UInt16 to.
+   * @param {number} u16 UInt16 to be written.
+   * @param {number} offset Offset in buffer to write UInt16 at.
+   * @private
+   */
+  writeUInt16_: function(buffer, u16, offset) {
+    buffer[offset + 0] = (u16 >> 8) & 0xFF;
+    buffer[offset + 1] = (u16 >> 0) & 0xFF;
+  },
+
+  /**
+   * Write UInt32 to buffer.
+   * @param {!Uint8Array} buffer Buffer to write UInt32 to.
+   * @param {number} u32 UInt32 to be written.
+   * @param {number} offset Offset in buffer to write UInt32 at.
+   * @private
+   */
+  writeUInt32_: function(buffer, u32, offset) {
+    buffer[offset + 0] = (u32 >> 24) & 0xFF;
+    buffer[offset + 1] = (u32 >> 16) & 0xFF;
+    buffer[offset + 2] = (u32 >> 8) & 0xFF;
+    buffer[offset + 3] = (u32 >> 0) & 0xFF;
+  },
+
+  /**
+   * Write string to buffer.
+   * @param {!Uint8Array} buffer Buffer to write string to.
+   * @param {string} string String to be written.
+   * @param {number} offset Offset in buffer to write string at.
+   * @private
+   */
+  writeString_: function(buffer, string, offset) {
+    for (var i = 0; i < string.length; i++) {
+      buffer[offset + i] = string.charCodeAt(i);
+    }
+  },
+
+  /**
+   * Write FourCC code to buffer.
+   * @param {!Uint8Array} buffer Buffer to write FourCC code to.
+   * @param {string} fourcc FourCC code to be written.
+   * @param {number} offset Offset in buffer to write FourCC code at.
+   * @private
+   */
+  writeFourCC_: function(buffer, fourcc, offset) {
+    buffer[offset + 0] = fourcc.charCodeAt(0);
+    buffer[offset + 1] = fourcc.charCodeAt(1);
+    buffer[offset + 2] = fourcc.charCodeAt(2);
+    buffer[offset + 3] = fourcc.charCodeAt(3);
+  },
+
+  /**
+   * Compute CRC from buffer data.
+   * @param {!Uint8Array} buffer Buffer with data to compute CRC from.
+   * @param {number} start Start index in buffer.
+   * @param {number} end End index in buffer.
+   * @return {number} The computed CRC.
+   * @private
+   */
+  getCRC_: function(buffer, start, end) {
+    var crc = 0xFFFFFFFF;
+    for (var i = start; i < end; i++) {
+      var crcTableIndex = (crc ^ (buffer[i])) & 0xFF;
+      crc = PNG_CRC_TABLE[crcTableIndex] ^ (crc >>> 8);
+    }
+    return crc ^ 0xFFFFFFFF;
+  },
+
+  /**
+   * Append frame from data URL to PNG object.
+   * @param {string} dataURL Data URL for frame.
+   * @param {!CrPngState} png PNG object to add frame to.
+   * @private
+   */
+  appendFrameFromDataURL_: function(dataURL, png) {
+    /** Convert data URL to Uint8Array. */
+    var byteString = atob(dataURL.split(',')[1]);
+    var bytes = new Uint8Array(byteString.length);
+    this.writeString_(bytes, byteString, 0);
+
+    /** Check signature. */
+    var signature = bytes.subarray(0, PNG_SIGNATURE.length);
+    if (signature.toString() != PNG_SIGNATURE.toString()) {
+      console.error('Bad PNG signature');
+    }
+
+    /**
+     * fcTL
+     *
+     * Sequence number          4 bytes
+     * Width                    4 bytes
+     * Height                   4 bytes
+     * X position               4 bytes
+     * Y position               4 bytes
+     * Frame delay numerator    2 bytes
+     * Frame delay denominator  2 bytes
+     * Dispose op               1 bytes
+     * Blend op                 1 bytes
+     */
+    var fcTL = new Uint8Array(12 + 26);
+    this.writeUInt32_(fcTL, 26, 0);
+    this.writeFourCC_(fcTL, 'fcTL', 4);
+    this.writeUInt32_(fcTL, png.sequences, 8);
+    /** Write size at the end when known. */
+    this.writeUInt32_(fcTL, 0, 20);
+    this.writeUInt32_(fcTL, 0, 24);
+    this.writeUInt16_(fcTL, PNG_FRAME_DELAY_NUMERATOR, 28);
+    this.writeUInt16_(fcTL, PNG_FRAME_DELAY_DENOMINATOR, 30);
+    this.writeUInt8_(fcTL, 0, 32);
+    this.writeUInt8_(fcTL, 0, 33);
+    /** Write CRC at the end when size is known. */
+    png.sequences += 1;
+    png.chunks.push(fcTL);
+
+    /** Append data chunks for frame. */
+    var i = PNG_SIGNATURE.length;
+    while ((i + 12) <= bytes.length) {
+      /**
+       * http://www.w3.org/TR/2003/REC-PNG-20031110/#5Chunk-layout
+       *
+       * length =  4      bytes
+       * type   =  4      bytes (IHDR, PLTE, IDAT, IEND or others)
+       * chunk  =  length bytes
+       * crc    =  4      bytes
+       */
+      var length = this.readUInt32_(bytes, i);
+      var type = this.readString_(bytes, i + 4, 4);
+      var chunk = bytes.subarray(i + 8, i + 8 + length);
+
+      /** We should have enough bytes left for length. */
+      if (length != chunk.length) {
+        console.error('Unexpectedly reached end of file');
+      }
+
+      switch (type) {
+        case 'IHDR':
+          /**
+           * http://www.w3.org/TR/2003/REC-PNG-20031110/#11IHDR
+           *
+           * Width               4 bytes
+           * Height              4 bytes
+           * Bit depth           1 byte
+           * Colour type         1 byte
+           * Compression method  1 byte
+           * Filter method       1 byte
+           * Interlace method    1 byte
+           */
+          var width = this.readUInt32_(chunk, 0);
+          var height = this.readUInt32_(chunk, 4);
+          var depth = chunk[8];
+          var colour = chunk[9];
+          var compression = chunk[10];
+          var filter = chunk[11];
+          var interlace = chunk[12];
+
+          /** Initialize size and colour if this is the first frame. */
+          if (png.frames == 0) {
+            png.width = width;
+            png.height = height;
+            png.colour = colour;
+          }
+
+          /** Check that header matches our expectations. */
+          if (width != png.width)
+            console.error('Bad PNG width: ' + width);
+          if (height != png.height)
+            console.error('Bad PNG height: ' + height);
+          if (depth != PNG_BIT_DEPTH)
+            console.error('Bad PNG bit depth: ' + depth);
+          if (colour != png.colour)
+            console.error('Bad PNG colour type: ' + colour);
+          if (compression != PNG_COMPRESSION_METHOD)
+            console.error('Bad PNG compression method: ' + compression);
+          if (filter != PNG_FILTER_METHOD)
+            console.error('Bad PNG filter method: ' + filter);
+          if (interlace != PNG_INTERLACE_METHOD)
+            console.error('Bad PNG interlace method: ' + interlace);
+          break;
+        case 'IDAT':
+          /** Append as IDAT chunk if this is the first frame. */
+          if (png.frames == 0) {
+            /**
+             * http://www.w3.org/TR/2003/REC-PNG-20031110/#11IDAT
+             *
+             * Data                     X bytes
+             */
+            var IDAT = new Uint8Array(12 + length);
+            this.writeUInt32_(IDAT, length, 0);
+            this.writeFourCC_(IDAT, 'IDAT', 4);
+            this.writeBytes_(IDAT, chunk, 8);
+            this.writeUInt32_(
+                IDAT, this.getCRC_(IDAT, 4, 8 + length), 8 + length);
+            png.chunks.push(IDAT);
+          } else {
+            /**
+             * fdAT
+             *
+             * Sequence number          4 bytes
+             * Frame data               X bytes
+             */
+            var fdAT = new Uint8Array(12 + 4 + length);
+            this.writeUInt32_(fdAT, 4 + length, 0);
+            this.writeFourCC_(fdAT, 'fdAT', 4);
+            this.writeUInt32_(fdAT, png.sequences, 8);
+            this.writeBytes_(fdAT, chunk, 12);
+            this.writeUInt32_(
+                fdAT, this.getCRC_(fdAT, 4, 12 + length), 12 + length);
+            png.sequences += 1;
+            png.chunks.push(fdAT);
+          }
+          break;
+        case 'PLTE':
+          console.error('Bad PNG chunk type: ' + type);
+          break;
+        case 'IEND':
+          /** Update fcTL now that size is known. */
+          this.writeUInt32_(fcTL, png.width, 12);
+          this.writeUInt32_(fcTL, png.height, 16);
+          this.writeUInt32_(fcTL, this.getCRC_(fcTL, 4, 34), 34);
+          png.frames += 1;
+          return;
+      }
+
+      /** Advance to next chunk. */
+      i += 12 + length;
+    }
+    console.error('Unexpectedly reached end of file');
+  },
+};
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/videocam_icon.svg b/ui/webui/resources/cr_elements/chromeos/cr_picture/videocam_icon.svg
new file mode 100644
index 0000000..a92d1d73
--- /dev/null
+++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/videocam_icon.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FFFFFF" preserveAspectRatio="xMidYMid meet"><path d="M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4z"/></svg>
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/videocam_shutter_icon.svg b/ui/webui/resources/cr_elements/chromeos/cr_picture/videocam_shutter_icon.svg
new file mode 100644
index 0000000..019a2cc
--- /dev/null
+++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/videocam_shutter_icon.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="red" stroke="#FFFFFF" preserveAspectRatio="xMidYMid meet"><circle cx="12" cy="12" r="7" stroke-width="8"></circle></svg>
diff --git a/ui/webui/resources/cr_elements/cr_icons_css.html b/ui/webui/resources/cr_elements/cr_icons_css.html
index 7feaeb9..0b1c6ec 100644
--- a/ui/webui/resources/cr_elements/cr_icons_css.html
+++ b/ui/webui/resources/cr_elements/cr_icons_css.html
@@ -17,6 +17,7 @@
         background-size: var(--cr-icon-size);
         flex-shrink: 0;
         height: var(--cr-icon-ripple-size);
+        user-select: none;
         width: var(--cr-icon-ripple-size);
       }
 
diff --git a/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html b/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html
index 2fa42fb..cd4e8274 100644
--- a/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html
+++ b/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html
@@ -10,23 +10,21 @@
   <template strip-whitespace="">
     <style include="cr-hidden-style cr-icons">
       :host {
+        align-items: center;
         align-self: stretch;
         background: none;
         border: none;
         color: inherit;
         cursor: pointer;
+        display: flex;
+        flex: 1;
         font-size: 100%;  /* Specifically for Mac OSX, harmless elsewhere. */
         line-height: 154%;  /* 20px. */
         margin: 0;
+        min-height: var(--cr-section-min-height);
         outline: none;
-        padding: 0;
+        padding: 0 var(--cr-section-padding);
         position: relative;
-        @apply(--cr-section);
-      }
-
-      :host(.continuation),
-      :host(.first) {
-        border-top: none;
       }
 
       :host([disabled]) {
@@ -77,6 +75,7 @@
         <div id="label" class="label">[[label]]</div>
         <div id="subLabel" class="secondary label">[[subLabel]]</div>
       </div>
+      <slot></slot>
       <div id="icon" class$="cr-icon [[iconClass]]" aria-label$="[[label]]">
       </div>
     </div>
diff --git a/ui/webui/resources/cr_elements/shared_style_css.html b/ui/webui/resources/cr_elements/shared_style_css.html
index 2c6dbb9..c603c10e 100644
--- a/ui/webui/resources/cr_elements/shared_style_css.html
+++ b/ui/webui/resources/cr_elements/shared_style_css.html
@@ -57,6 +57,11 @@
         display: block;
       }
 
+      /* Horizontal rule line. */
+      .hr {
+        border-top: var(--cr-separator-line);
+      }
+
       [scrollable] {
         border-color: transparent;
         border-style: solid;
diff --git a/ui/webui/resources/cr_elements_images.grdp b/ui/webui/resources/cr_elements_images.grdp
index 23265241..8b189bd 100644
--- a/ui/webui/resources/cr_elements_images.grdp
+++ b/ui/webui/resources/cr_elements_images.grdp
@@ -43,8 +43,14 @@
     <include name="IDR_CR_ELEMENTS_CAMERA_ALT_ICON_SVG"
              file="cr_elements/chromeos/cr_picture/camera_alt_icon.svg"
              type="BINDATA" />
-    <include name="IDR_CR_ELEMENTS_CAMERA_FLIP_ICON_SVG"
-             file="cr_elements/chromeos/cr_picture/camera_flip_icon.svg"
+    <include name="IDR_CR_ELEMENTS_CAMERA_SHUTTER_ICON_SVG"
+             file="cr_elements/chromeos/cr_picture/camera_shutter_icon.svg"
+             type="BINDATA" />
+    <include name="IDR_CR_ELEMENTS_VIDEOCAM_ICON_SVG"
+             file="cr_elements/chromeos/cr_picture/videocam_icon.svg"
+             type="BINDATA" />
+    <include name="IDR_CR_ELEMENTS_VIDEOCAM_SHUTTER_ICON_SVG"
+             file="cr_elements/chromeos/cr_picture/videocam_shutter_icon.svg"
              type="BINDATA" />
     <include name="IDR_CR_ELEMENTS_CELLULAR_0_SVG"
              file="cr_elements/chromeos/network/cellular_0.svg"
diff --git a/ui/webui/resources/cr_elements_resources.grdp b/ui/webui/resources/cr_elements_resources.grdp
index 68a22b4..0c6ac6d 100644
--- a/ui/webui/resources/cr_elements_resources.grdp
+++ b/ui/webui/resources/cr_elements_resources.grdp
@@ -78,6 +78,12 @@
     <structure name="IDR_CR_ELEMENTS_CHROMEOS_CR_PICTURE_CR_PICTURE_TYPES_JS"
                file="../../webui/resources/cr_elements/chromeos/cr_picture/cr_picture_types.js"
                type="chrome_html" />
+    <structure name="IDR_CR_ELEMENTS_CHROMEOS_CR_PICTURE_CR_PNG_BEHAVIOR_HTML"
+               file="../../webui/resources/cr_elements/chromeos/cr_picture/cr_png_behavior.html"
+               type="chrome_html" />
+    <structure name="IDR_CR_ELEMENTS_CHROMEOS_CR_PICTURE_CR_PNG_BEHAVIOR_JS"
+               file="../../webui/resources/cr_elements/chromeos/cr_picture/cr_png_behavior.js"
+               type="chrome_html" />
     <structure name="IDR_CR_ELEMENTS_CHROMEOS_CR_NETWORK_ICON_HTML"
                file="../../webui/resources/cr_elements/chromeos/network/cr_network_icon.html"
                type="chrome_html" />
diff --git a/ui/webui/resources/polymer_resources.grdp b/ui/webui/resources/polymer_resources.grdp
index f97db93c..03bdc8d 100644
--- a/ui/webui/resources/polymer_resources.grdp
+++ b/ui/webui/resources/polymer_resources.grdp
@@ -647,12 +647,6 @@
   <structure name="IDR_POLYMER_1_0_PAPER_TOGGLE_BUTTON_PAPER_TOGGLE_BUTTON_HTML"
              file="../../../third_party/polymer/v1_0/components-chromium/paper-toggle-button/paper-toggle-button.html"
              type="chrome_html" />
-  <structure name="IDR_POLYMER_1_0_PAPER_TOOLBAR_PAPER_TOOLBAR_EXTRACTED_JS"
-             file="../../../third_party/polymer/v1_0/components-chromium/paper-toolbar/paper-toolbar-extracted.js"
-             type="chrome_html" />
-  <structure name="IDR_POLYMER_1_0_PAPER_TOOLBAR_PAPER_TOOLBAR_HTML"
-             file="../../../third_party/polymer/v1_0/components-chromium/paper-toolbar/paper-toolbar.html"
-             type="chrome_html" />
   <structure name="IDR_POLYMER_1_0_PAPER_TOOLTIP_PAPER_TOOLTIP_EXTRACTED_JS"
              file="../../../third_party/polymer/v1_0/components-chromium/paper-tooltip/paper-tooltip-extracted.js"
              type="chrome_html" />
diff --git a/ui/wm/core/default_activation_client.cc b/ui/wm/core/default_activation_client.cc
index 0ddc1a1..ee8ac40d 100644
--- a/ui/wm/core/default_activation_client.cc
+++ b/ui/wm/core/default_activation_client.cc
@@ -70,6 +70,9 @@
   if (last_active == window)
     return;
 
+  for (auto& observer : observers_)
+    observer.OnWindowActivating(reason, window, last_active);
+
   last_active_ = last_active;
   RemoveActiveWindow(window);
   active_windows_.push_back(window);
diff --git a/ui/wm/core/focus_controller.cc b/ui/wm/core/focus_controller.cc
index 069e9f46..267d67f 100644
--- a/ui/wm/core/focus_controller.cc
+++ b/ui/wm/core/focus_controller.cc
@@ -305,6 +305,8 @@
       focused_window_ != active_window_) {
     observer_manager_.Remove(active_window_);
   }
+  for (auto& observer : activation_observers_)
+    observer.OnWindowActivating(reason, window, active_window_);
   active_window_ = window;
   if (active_window_ && !observer_manager_.IsObserving(active_window_))
     observer_manager_.Add(active_window_);
diff --git a/ui/wm/public/activation_change_observer.h b/ui/wm/public/activation_change_observer.h
index b242d09..206f830 100644
--- a/ui/wm/public/activation_change_observer.h
+++ b/ui/wm/public/activation_change_observer.h
@@ -26,7 +26,15 @@
     WINDOW_DISPOSITION_CHANGED,
   };
 
-  // Called when |gained_active| gains focus, or there is no active window
+  // Called when |gaining_active| will gain activation, or there is no active
+  // window (|gaining_active| is NULL in this case.) |losing_active| refers to
+  // the previous active window or NULL if there was no previously active
+  // window. |reason| specifies the cause of the activation change.
+  virtual void OnWindowActivating(ActivationReason reason,
+                                  aura::Window* gaining_active,
+                                  aura::Window* losing_active) {}
+
+  // Called when |gained_active| gains activation, or there is no active window
   // (|gained_active| is NULL in this case.) |lost_active| refers to the
   // previous active window or NULL if there was no previously active
   // window. |reason| specifies the cause of the activation change.